Compare commits

..

1 Commits

Author SHA1 Message Date
Mickaël Rémond de080352ca Release 1.1.1
SVN Revision: 559
2006-04-28 10:45:17 +00:00
79 changed files with 4878 additions and 11403 deletions
-362
View File
@@ -1,365 +1,3 @@
2006-09-27 Mickael Remond <mickael.remond@process-one.net>
* doc/release_notes_1.1.2.txt: Minor fixes.
* doc/guide.tex: Fixed Latexish typos.
2006-09-26 Mickael Remond <mickael.remond@process-one.net>
* doc/release_notes_1.1.2.txt: Draft release notes.
* src/msgs/pl.msg: Updated (thanks to Andrzej Smyk).
* src/ejabberd_s2s.erl: Added incoming-s2s-number and
outgoing-s2s-number ejabberdctl commands
* src/mod_muc/mod_muc_room.erl: Minor english update.
* src/msgs/pl.msg: Likewise.
* src/msgs/uk.msg: Likewise.
* src/msgs/pt-br.msg: Likewise.
* src/msgs/cs.msg: Likewise.
* src/msgs/ru.msg: Likewise.
* src/msgs/es.msg: Likewise.
* src/msgs/fr.msg: Likewise.
* src/msgs/de.msg: Likewise.
* src/msgs/nl.msg: Likewise.
* src/msgs/pt-br.msg: Updated Brazilian translation (thanks to
Renato Botelho) and clean-up.
2006-09-25 Mickael Remond <mickael.remond@process-one.net>
* src/msgs/de.msg: Updated German translation (thanks to Nikolaus
Polak).
* src/ejabberd.app: Version update for ejabberd 1.1.2.
* src/msgs/pl.msg: Updated Polish translation (thanks to Zbyszek
Zolkiewski).
* src/msgs/de.msg: Updated German translation (thanks to Marvin
Preuss).
* src/msgs/nl.msg: Updated Dutch translation (thanks to Sander
Devrieze).
* src/msgs/cs.msg: Updated Czech translation and removed unused
strings.
* doc/introduction.tex: Minor doc updates for release 1.1.2.
2006-09-24 Mickael Remond <mickael.remond@process-one.net>
* src/msgs/es.msg: Updated Spanish translation (thanks to Badlop).
* src/mod_muc/mod_muc_room.erl: Strings update (thanks to Serguei
Golovan).
* src/msgs/ru.msg: Updated Russian translation (thanks to Serguei
Golovan).
* src/msgs/uk.msg: Updated Ukrainian translation (thanks to Serguei
Golovan).
* src/msgs/fr.msg: Updated French translation.
* src/doc/guide.html: Minor W3C compliance fix in an Hevea
generated URL.
* src/doc/features.html: Added to be consistent (guide.html is in the
repository to make Latex optional, but still allow access to the doc).
2006-09-23 Mickael Remond <mickael.remond@process-one.net>
* src/ejabberd.hrl: Updated to version 1.1.2
2006-09-23 Alexey Shchepin <alexey@sevcom.net>
* src/eldap/eldap.erl: Enable the keepalive socket option (thanks
to Evgeniy Khramtsov)
* src/ejabberd_auth_ldap.erl: Now uses two LDAP connections
(thanks to Evgeniy Khramtsov)
* src/eldap/eldap_filter.erl: Bugfix (thanks to Evgeniy Khramtsov)
* src/mod_vcard_ldap.erl: Likewise
2006-09-22 Mickael Remond <mickael.remond@process-one.net>
* src/msgs/cs.msg: Added Czech translation (thanks to Milos Svasek).
* src/mod_muc/mod_muc.erl: Component name is now more user friendly
(thanks to Badlop).
* src/mod_irc/mod_irc.erl: Likewise.
* src/mod_pubsub/mod_pubsub.erl: Likewise.
* src/msgs/fr.msg: updated French translation.
* doc/guide.tex: Large improvements for ejabberd 1.1.2 (thanks to
Sander Devrieze)
* doc/version.tex: Likewise.
* doc/features.tex: Likewise.
* doc/Makefile: Likewise.
* doc/dev.tex: Likewise.
2006-09-14 Mickael Remond <mickael.remond@process-one.net>
* doc/guide.tex: Minor fix on index generation.
2006-09-14 Alexey Shchepin <alexey@sevcom.net>
* doc/guide.tex: Updated (thanks to Evgeniy Khramtsov)
* src/ejabberd_auth_ldap.erl: Better LDAP support (thanks to
Evgeniy Khramtsov)
* src/mod_vcard_ldap.erl: Likewise
* src/eldap/eldap_filter.erl: Likewise
2006-09-11 Mickael Remond <mickael.remond@process-one.net>
* src/odbc/mssql.sql: Removed unused fields.
2006-09-10 Alexey Shchepin <alexey@sevcom.net>
* src/ejd2odbc.erl: Updated
* src/mod_muc/mod_muc_log.erl: Fixed html special characters
escaping, added new image buttons, chatroom titles now point to
xmpp: URIs (thanks to Badlop)
2006-09-05 Mickael Remond <mickael.remond@process-one.net>
* src/mod_muc/mod_muc.erl: It is now possible to configure the MUC room
history feature. A new option has been added in ejabberd muc module
configuration (history_size) to define the size of the history. 0 is
used to disable the feature.
* src/mod_muc/mod_muc_room.erl: Likewise.
* doc/guide.tex: Likewise.
2006-09-05 Alexey Shchepin <alexey@sevcom.net>
* src/mod_shared_roster.erl: Bugfix
* src/mod_roster_odbc.erl: Bugfix
2006-09-03 Mickael Remond <mickael.remond@process-one.net>
* src/odbc/odbc_queries.erl: Support for Microsoft SQL Server as a
database backend (via ODBC).
* src/odbc/ejabberd_odbc.erl: Likewise.
* src/odbc/mssql.sql: Likewise.
* src/odbc/Makefile.in: Likewise.
* src/ejabberd_auth_odbc.erl: Likewise.
* src/mod_offline_odbc.erl: Likewise.
* src/mod_roster_odbc.erl: Likewise.
* src/mod_last_odbc.erl: Likewise.
* src/configure.ac: Likewise
* doc/guide.tex: Likewise.
* doc/introduction.tex: Likewise.
* src/odbc/pg.sql: Minor fix.
2006-08-28 Mickael Remond <mickael.remond@process-one.net>
* Makefile.in: Fix for MacOSX compilation.
* ejabberd_zlib/Makefile.in: Likewise.
* mod_irc/Makefile.in: Likewise.
* stringprep/Makefile.in: Likewise.
* tls/Makefile.in: Likewise.
* src/ejabberd.app: Updated to the current version.
2006-08-27 Alexey Shchepin <alexey@sevcom.net>
* src/mod_muc/mod_muc_room.erl: Fixed logging configuring
permission check
2006-08-14 Alexey Shchepin <alexey@sevcom.net>
* src/ejabberd_router.erl: Now filter_packet hook works in
'global' context
2006-08-04 Alexey Shchepin <alexey@sevcom.net>
* src/tls/tls_drv.c: Report OpenSSL error messages (thanks to
Magnus Henoch)
* src/mod_muc/mod_muc_room.erl: Use standardized MUC room
configuration fields (thanks to Magnus Henoch and Andy Turner)
2006-08-02 Alexey Shchepin <alexey@sevcom.net>
* src/mod_roster_odbc.erl: Bugfix
2006-07-28 Mickael Remond <mickael.remond@process-one.net>
* src/ejabberd_c2s.erl: Bugfix: added a missing catch and fixed the
error code used on unknown namespace.
* src/ejabberd_s2s_out.erl: Improved s2s connection negociation
(dialback namespace usage) when using tls.
* src/ejabberd_sm.erl: Fixed the error code used on unknown namespace.
* src/mod_register.erl: ejabberd now sends iq result and stream end on
user remove.
2006-07-16 Mickael Remond <mickael.remond@process-one.net>
* src/acl.erl: The server does not crash anymore on wrong acl rule. Add
rule error message in log file.
2006-07-07 Mickael Remond <mickael.remond@process-one.net>
* src/web/ejabberd_web_admin.erl: User creation form now creates the
user for the current virual host only and does not require to type
the hostname.
* src/jlib.erl: String to JID conversion now returns an error if the
JID string contains two arobases.
2006-07-06 Mickael Remond <mickael.remond@process-one.net>
* src/mod_shared_roster.erl: Shared roster entries can now be moved or
rename from a client without breaking current presence status.
* src/mod_roster.erl: Likewise.
* src/mod_roster_odbc.erl: Likewise.
* src/mod_muc/mod_muc_room.erl: Fixed the order in which room presence
packets are sent (First existing presence to new occupant, then new
occupant presence to existing users.
2006-07-05 Mickael Remond <mickael.remond@process-one.net>
* src/web/ejabberd_web_admin.erl: More flexible parsing the shared
roster members list from the configuration form.
* src/mod_shared_roster.erl: Deletng a shared roster group now
correctly deletes its user entries.
* src/mod_shared_roster.erl: The logged user (self) is now removed from
the shared roster list.
* src/ejabberd_auth.erl: Better handling of errors when the server for
authentication is unknown.
2006-06-19 Alexey Shchepin <alexey@sevcom.net>
* src/ejabberd_s2s_in.erl: Removed needless check for xmlns:db
when starttls is enabled
2006-06-15 Mickael Remond <mickael.remond@process-one.net>
* src/web/ejabberd_http_poll.erl: Bugfix: using tuple instead of a Pid
to send Erlang messages in a rarely used case.
2006-06-13 Mickael Remond <mickael.remond@process-one.net>
* src/ejabberd_auth.erl: Fixed broken multiple connection with
anonymous login problem.
* src/ejabberd_auth_anonymous.erl: Likewise.
2006-06-07 Mickael Remond <mickael.remond@process-one.net>
* src/mod_pubsub/mod_pubsub.erl: Support for pubsub node creation
ACL. It is now possible to limit the node creation rights using an
ACL from ejabberd config file (Thanks to Christophe Romain).
* doc/guide.tex: Likewise.
* src/ejabberd.cfg.example.
* src/mod_pubsub/mod_pubsub.erl: Discovery query on an item does
no more return an "item not found error". Discovery stop correctly
at the item level (Thanks to Christophe Romain).
2006-06-02 Mickael Remond <mickael.remond@process-one.net>
* src/web/ejabberd_http_poll.erl: Messages polled between the
the last client request and the polling timeout were lost. Those
messages are now resent using ejabberd routing mechanisms.
* src/web/ejabberd_http.erl: The web module now accepts HTTP
absolute URL (used behind a proxy). This apply to HTTP polling and
to the web interface (Thanks to Jean-Sebastien Pedron).
2006-05-29 Mickael Remond <mickael.remond@process-one.net>
* src/mod_roster.erl: According to RFC3921 section 9.2, outbound
subscribe presence packets must be sent, even if the user has already
asked for subcription previously (subscription: none and pending: out).
The mod_roster now conforms to this behaviour.
* src/mod_roster_odbc.erl: Likewise.
2006-05-27 Mickael Remond <mickael.remond@process-one.net>
* src/configure.ac: Added an optional check for krb5.h in
configure. ejabberd can now be build directly on RedHat and
OpenBSD.
2006-05-27 Alexey Shchepin <alexey@sevcom.net>
* src/msgs/sk.msg: Slovak translation (thanks to Juraj Michalek
and SkLUG)
2006-05-26 Alexey Shchepin <alexey@sevcom.net>
* src/odbc/pg.sql: Updated
* src/mod_shared_roster.erl: Updated
* src/ejabberd_sm.erl: Bugfix
* src/mod_roster.erl: Bugfix
* src/mod_roster_odbc.erl: Likewise
2006-05-23 Mickael Remond <mickael.remond@process-one.net>
* src/mod_roster.erl: The subscribe request are now resend at login as
long as they have not been answered. mod_roster do no more depends on
mod_offline.
* src/ejabberd_sm.erl: Likewise.
* src/ejabberd_c2s.erl: Likewise.
* src/mod_roster_odbc.erl: Likewise (The ODBC/relational support has
not yet been tested).
* src/mod_roster.hrl: Likewise.
* src/mod_offline.erl: Likewise.
* src/mod_offline_odbc.erl: Likewise.
* odbc/pg.sql: Likewise.
* odbc/mysql.sql: Likewise.
2006-05-22 Mickael Remond <mickael.remond@process-one.net>
* src/ejabberd_sm.erl: The max_user_sessions has been moved to
host configuration.
* src/ejabberd.cfg.example: Likewise.
* doc/guide.tex: Likewise.
2006-05-21 Mickael Remond <mickael.remond@process-one.net>
* src/ejabberd_sm.erl: An option to limit the number of opened sessions
for a given user have been added. As a default, a given user can only
log in 10 times with different resources. After that, new connections
replace the older ones.
* src/ejabberd.cfg.example: Likewise.
* doc/guide.tex: Likewise.
2006-05-15 Mickael Remond <mickael.remond@process-one.net>
* src/web/ejabberd_http_poll.erl: Timeout disconnection were not
properly handled after "active once" migration. This is now fixed.
2006-05-07 Mickael Remond <mickael.remond@process-one.net>
* src/mod_configure.erl: Unknown tables or tables from now unused
modules are ignored during restore. The restore can now be performed in
such case.
* src/web/ejabberd_web_admin.erl: Likewise.
* src/ejabberd_admin.erl: Code refactoring. Common Mnesia database
restore function.
* src/ejabberd_ctl.erl: Now prints a user-friendly when trying to
restore a backup from a non-existent file.
* src/ejabberd_ctl.erl: Added a way to delete the older message
from the offline message table. This function is only available if
offline message queue is stored in Mnesia internal database. The
function delete_old_messages is not available in mod_offline_odbc.
2006-05-01 Mickael Remond <mickael.remond@process-one.net>
* src/ejabberd_ctl.erl: Unknown tables or tables from now unused
modules are ignored during restore. The restore can now be performed in
such case.
2006-04-28 Mickael Remond <mickael.remond@process-one.net>
* src/ejabberd.hrl: release 1.1.1
+7 -4
View File
@@ -27,13 +27,16 @@ clean:
rm -f *.toc
guide.html: guide.tex
hevea -fix -noiso -pedantic guide.tex
hevea guide.tex
hevea guide.tex
dev.html: dev.tex
hevea -fix -noiso -pedantic dev.tex
hevea dev.tex
hevea dev.tex
features.html: features.tex
hevea -fix -noiso -pedantic features.tex
hevea features.tex
hevea features.tex
guide.pdf: guide.tex
pdflatex guide.tex
+62 -50
View File
@@ -4,7 +4,7 @@
<HEAD>
<TITLE>Ejabberd 1.1.2 Developers Guide</TITLE>
<TITLE>Ejabberd 1.0.0 Developers Guide</TITLE>
<META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<META name="GENERATOR" content="hevea 1.08">
@@ -22,7 +22,7 @@ BLOCKQUOTE{margin-left:4ex;margin-right:4ex;text-align:left;}
</HEAD>
<BODY >
<!--HEVEA command line is: hevea -fix -noiso -pedantic dev.tex -->
<!--HEVEA command line is: hevea dev.tex -->
<!--HTMLHEAD-->
<!--ENDHTML-->
<!--PREFIX <ARG ></ARG>-->
@@ -34,7 +34,7 @@ BLOCKQUOTE{margin-left:4ex;margin-right:4ex;text-align:left;}
<TABLE CLASS="title">
<TR><TD>
<H1 CLASS="titlemain">Ejabberd 1.1.2 Developers Guide</H1>
<H1 CLASS="titlemain">Ejabberd 1.0.0 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="xmpp:aleksey@jabber.ru"><TT>xmpp:aleksey@jabber.ru</TT></A></H3></TD>
@@ -42,7 +42,7 @@ BLOCKQUOTE{margin-left:4ex;margin-right:4ex;text-align:left;}
<BR>
<DIV CLASS="center">
<IMG SRC="logo.png" ALT="logo.png">
<IMG SRC="logo.png">
<BR>
@@ -61,57 +61,56 @@ BLOCKQUOTE{margin-left:4ex;margin-right:4ex;text-align:left;}
<A HREF="#htoc2">1.1&nbsp;&nbsp;Key Features</A>
<LI CLASS="li-toc"><A HREF="#htoc3">1.2&nbsp;&nbsp;Additional Features</A>
</UL>
<LI CLASS="li-toc"><A HREF="#htoc4">2&nbsp;&nbsp;How it Works</A>
<LI CLASS="li-toc"><A HREF="#htoc4">2&nbsp;&nbsp;How it works</A>
<UL CLASS="toc"><LI CLASS="li-toc">
<A HREF="#htoc5">2.1&nbsp;&nbsp;Router</A>
<LI CLASS="li-toc"><A HREF="#htoc6">2.2&nbsp;&nbsp;Local Router</A>
<LI CLASS="li-toc"><A HREF="#htoc7">2.3&nbsp;&nbsp;Session Manager</A>
<LI CLASS="li-toc"><A HREF="#htoc8">2.4&nbsp;&nbsp;S2S Manager</A>
</UL>
<LI CLASS="li-toc"><A HREF="#htoc9">3&nbsp;&nbsp;XML Representation</A>
<LI CLASS="li-toc"><A HREF="#htoc9">3&nbsp;&nbsp;XML representation</A>
<LI CLASS="li-toc"><A HREF="#htoc10">4&nbsp;&nbsp;Module <TT>xml</TT></A>
<LI CLASS="li-toc"><A HREF="#htoc11">5&nbsp;&nbsp;Module <TT>xml_stream</TT></A>
<LI CLASS="li-toc"><A HREF="#htoc12">6&nbsp;&nbsp;Modules</A>
<LI CLASS="li-toc"><A HREF="#htoc12">6&nbsp;&nbsp;<TT>ejabberd</TT> modules</A>
<UL CLASS="toc"><LI CLASS="li-toc">
<A HREF="#htoc13">6.1&nbsp;&nbsp;Module gen_iq_handler</A>
<LI CLASS="li-toc"><A HREF="#htoc14">6.2&nbsp;&nbsp;Services</A>
<A HREF="#htoc13">6.1&nbsp;&nbsp;gen_mod behaviour</A>
<LI CLASS="li-toc"><A HREF="#htoc14">6.2&nbsp;&nbsp;Module gen_iq_handler</A>
<LI CLASS="li-toc"><A HREF="#htoc15">6.3&nbsp;&nbsp;Services</A>
</UL>
</UL>
<!--TOC section Introduction-->
<H2 CLASS="section"><A NAME="htoc1">1</A>&nbsp;&nbsp;<A NAME="intro">Introduction</A></H2><!--SEC END -->
<H2 CLASS="section"><A NAME="htoc1">1</A>&nbsp;&nbsp;Introduction</H2><!--SEC END -->
<A NAME="sec:intro"></A>
<A NAME="sec:intr"></A>
<TT>ejabberd</TT> is a free and open source instant messaging server written in <A HREF="http://www.erlang.org/">Erlang</A>.<BR>
<TT>ejabberd</TT> is a free (GPL) distributed fault-tolerant Jabber/XMPP server and is mainly written in <A HREF="http://www.erlang.org/">Erlang</A>.<BR>
<BR>
<TT>ejabberd</TT> is cross-platform, distributed, fault-tolerant, and based on open standards to achieve real-time communication.<BR>
<TT>ejabberd</TT> is designed to be a stable, standards compliant, and feature rich Jabber/XMPP server.<BR>
<BR>
<TT>ejabberd</TT> is designed to be a rock-solid and feature rich XMPP server.<BR>
<BR>
<TT>ejabberd</TT> is suitable for small deployments, whether they need to be scalable or not, as well as extremely big deployments.<BR>
<TT>ejabberd</TT> is suitable for small servers, whether they need to be scalable or not, as well as extremely big servers.<BR>
<BR>
<!--TOC subsection Key Features-->
<H3 CLASS="subsection"><A NAME="htoc2">1.1</A>&nbsp;&nbsp;<A NAME="keyfeatures">Key Features</A></H3><!--SEC END -->
<H3 CLASS="subsection"><A NAME="htoc2">1.1</A>&nbsp;&nbsp;Key Features</H3><!--SEC END -->
<A NAME="sec:keyfeatures"></A>
<TT>ejabberd</TT> is:
<UL CLASS="itemize"><LI CLASS="li-itemize">
Cross-platform: <TT>ejabberd</TT> runs under Microsoft Windows and Unix derived systems such as Linux, FreeBSD and NetBSD.<BR>
Multiplatform: <TT>ejabberd</TT> runs under Microsoft Windows and Unix derived systems such as Linux, FreeBSD and NetBSD.<BR>
<BR>
<LI CLASS="li-itemize">Distributed: You can run <TT>ejabberd</TT> on a cluster of machines and all of them will serve the same Jabber domain(s). When you need more capacity you can simply add a new cheap node to your cluster. Accordingly, you do not need to buy an expensive high-end machine to support tens of thousands concurrent users.<BR>
<LI CLASS="li-itemize">Distributed: You can run <TT>ejabberd</TT> on a cluster of machines and all of them will serve one Jabber domain. When you need more capacity you can simply add a new cheap node to your cluster. Accordingly, you do not need to buy an expensive high-end machine to support tens of thousands concurrent users.<BR>
<BR>
<LI CLASS="li-itemize">Fault-tolerant: You can deploy an <TT>ejabberd</TT> cluster so that all the information required for a properly working service will be replicated permanently on all nodes. This means that if one of the nodes crashes, the others will continue working without disruption. In addition, nodes also can be added or replaced `on the fly'.<BR>
<LI CLASS="li-itemize">Fault-tolerant: You can deploy an <TT>ejabberd</TT> cluster so that all the information required for a properly working service will be replicated permanently on all nodes. This means that if one of the nodes crashes, the others will continue working without disruption. In addition, nodes also can be added or replaced &#8220;on the fly&#8221;.<BR>
<BR>
<LI CLASS="li-itemize">Administrator Friendly: <TT>ejabberd</TT> is built on top of the Open Source Erlang. As a result you do not need to install an external database, an external web server, amongst others because everything is already included, and ready to run out of the box. Other administrator benefits include:
<UL CLASS="itemize"><LI CLASS="li-itemize">
Comprehensive documentation.
<LI CLASS="li-itemize">Straightforward installers for Linux, Mac OS X, and Windows.
<LI CLASS="li-itemize">Straightforward installers for Windows and Linux.
<LI CLASS="li-itemize">Web interface for administration tasks.
<LI CLASS="li-itemize">Shared Roster Groups.
<LI CLASS="li-itemize">Shared Roster groups.
<LI CLASS="li-itemize">Command line administration tool.
<LI CLASS="li-itemize">Can integrate with existing authentication mechanisms.
<LI CLASS="li-itemize">Capability to send announce messages.
@@ -119,25 +118,25 @@ Comprehensive documentation.
<BR>
<LI CLASS="li-itemize">Internationalized: <TT>ejabberd</TT> leads in internationalization. Hence it is very well suited in a globalized world. Related features are:
<UL CLASS="itemize"><LI CLASS="li-itemize">
Translated in 12 languages.
Translated in 11 languages.
<LI CLASS="li-itemize">Support for <A HREF="http://www.ietf.org/rfc/rfc3490.txt">IDNA</A>.
</UL><BR>
<BR>
<LI CLASS="li-itemize">Open Standards: <TT>ejabberd</TT> is the first Open Source Jabber server claiming to fully comply to the XMPP standard.
<UL CLASS="itemize"><LI CLASS="li-itemize">
Fully XMPP compliant.
<LI CLASS="li-itemize">XML-based protocol.
Fully XMPP compliant
<LI CLASS="li-itemize">XML-based protocol
<LI CLASS="li-itemize"><A HREF="http://ejabberd.jabber.ru/protocols">Many JEPs supported</A>.
</UL></UL>
<!--TOC subsection Additional Features-->
<H3 CLASS="subsection"><A NAME="htoc3">1.2</A>&nbsp;&nbsp;<A NAME="addfeatures">Additional Features</A></H3><!--SEC END -->
<H3 CLASS="subsection"><A NAME="htoc3">1.2</A>&nbsp;&nbsp;Additional Features</H3><!--SEC END -->
<A NAME="sec:addfeatures"></A>
Moreover, <TT>ejabberd</TT> comes with a wide range of other state-of-the-art features:
Besides common Jabber server features, <TT>ejabberd</TT> comes with a wide range of other features:
<UL CLASS="itemize"><LI CLASS="li-itemize">
Modular
Modular: <TT>ejabberd</TT>'s modular architecture allows easy customization:
<UL CLASS="itemize"><LI CLASS="li-itemize">
Load only the modules you want.
<LI CLASS="li-itemize">Extend <TT>ejabberd</TT> with your own custom modules.
@@ -146,39 +145,42 @@ Load only the modules you want.
<UL CLASS="itemize"><LI CLASS="li-itemize">
SASL and STARTTLS for c2s and s2s connections.
<LI CLASS="li-itemize">STARTTLS and Dialback s2s connections.
<LI CLASS="li-itemize">Obsolete SSL for c2s connections also supported.
<LI CLASS="li-itemize">Web interface accessible via HTTPS secure access.
</UL>
<LI CLASS="li-itemize">Databases
<UL CLASS="itemize"><LI CLASS="li-itemize">
Native MySQL support.
<LI CLASS="li-itemize">Native PostgreSQL support.
Native PostgreSQL support.
<LI CLASS="li-itemize">Mnesia.
<LI CLASS="li-itemize">ODBC data storage support.
<LI CLASS="li-itemize">Microsoft SQL Server support.
<LI CLASS="li-itemize">ODBC data storage support.
</UL>
<LI CLASS="li-itemize">Authentication
<UL CLASS="itemize"><LI CLASS="li-itemize">
LDAP and ODBC.
LDAP.
<LI CLASS="li-itemize">External Authentication script.
<LI CLASS="li-itemize">Internal Authentication.
</UL>
<LI CLASS="li-itemize">The ability to interface via external components with networks such as:
<UL CLASS="itemize"><LI CLASS="li-itemize">
AIM
<LI CLASS="li-itemize">ICQ
<LI CLASS="li-itemize">MSN
</UL>
<LI CLASS="li-itemize">Others
<UL CLASS="itemize"><LI CLASS="li-itemize">
Compressing XML streams with Stream Compression (<A HREF="http://www.jabber.org/jeps/jep-0138.html">JEP-0138</A>).
<LI CLASS="li-itemize">Interface with networks such as AIM, ICQ and MSN.
<LI CLASS="li-itemize">Statistics via Statistics Gathering (<A HREF="http://www.jabber.org/jeps/jep-0039.html">JEP-0039</A>).
<LI CLASS="li-itemize">IPv6 support both for c2s and s2s connections.
<LI CLASS="li-itemize"><A HREF="http://www.jabber.org/jeps/jep-0045.html">Multi-User Chat</A> module with logging.
<LI CLASS="li-itemize">Users Directory based on users vCards.
<LI CLASS="li-itemize"><A HREF="http://www.jabber.org/jeps/jep-0060.html">Publish-Subscribe</A> component.
<LI CLASS="li-itemize">Support for virtual hosting.
<LI CLASS="li-itemize"><A HREF="http://www.jabber.org/jeps/jep-0025.html">HTTP Polling</A> service.
IPv6 support both for c2s and s2s connections.
<LI CLASS="li-itemize">Support for virtual hosting.
<LI CLASS="li-itemize"><A HREF="http://www.jabber.org/jeps/jep-0025.html">HTTP Polling</A> service
<LI CLASS="li-itemize"><A HREF="http://www.jabber.org/jeps/jep-0045.html">Multi-User Chat</A> module.
<LI CLASS="li-itemize">IRC transport.
<LI CLASS="li-itemize"><A HREF="http://www.jabber.org/jeps/jep-0060.html">Publish-Subscribe</A> component.
<LI CLASS="li-itemize">Users Directory based on users vCards.
<LI CLASS="li-itemize">Statistics via Statistics Gathering (<A HREF="http://www.jabber.org/jeps/jep-0039.html">JEP-0039</A>).
</UL>
</UL>
<!--TOC section How it Works-->
<!--TOC section How it works-->
<H2 CLASS="section"><A NAME="htoc4">2</A>&nbsp;&nbsp;How it Works</H2><!--SEC END -->
<H2 CLASS="section"><A NAME="htoc4">2</A>&nbsp;&nbsp;How it works</H2><!--SEC END -->
<A NAME="sec:howitworks"></A>
A Jabber domain is served by one or more <TT>ejabberd</TT> nodes. These nodes can
@@ -236,9 +238,9 @@ routes the packet to S2S manager on that node, if it is open on this node, then
it is routed to the process that serves this connection, and if a connection
does not exist, then it is opened and registered.<BR>
<BR>
<!--TOC section XML Representation-->
<!--TOC section XML representation-->
<H2 CLASS="section"><A NAME="htoc9">3</A>&nbsp;&nbsp;XML Representation</H2><!--SEC END -->
<H2 CLASS="section"><A NAME="htoc9">3</A>&nbsp;&nbsp;XML representation</H2><!--SEC END -->
<A NAME="sec:xmlrepr"></A>
Each XML stanza is represented as the following tuple:
@@ -326,14 +328,21 @@ Err = term()
</PRE>Parses <TT>Str</TT> using XML parser, returns either parsed element or error
tuple.
</DL>
<!--TOC section Modules-->
<!--TOC section <TT>ejabberd</TT> modules-->
<H2 CLASS="section"><A NAME="htoc12">6</A>&nbsp;&nbsp;Modules</H2><!--SEC END -->
<H2 CLASS="section"><A NAME="htoc12">6</A>&nbsp;&nbsp;<TT>ejabberd</TT> modules</H2><!--SEC END -->
<A NAME="sec:emods"></A>
<!--TOC subsection gen_mod behaviour-->
<H3 CLASS="subsection"><A NAME="htoc13">6.1</A>&nbsp;&nbsp;gen_mod behaviour</H3><!--SEC END -->
<A NAME="sec:genmod"></A>
TBD<BR>
<BR>
<!--TOC subsection Module gen_iq_handler-->
<H3 CLASS="subsection"><A NAME="htoc13">6.1</A>&nbsp;&nbsp;Module gen_iq_handler</H3><!--SEC END -->
<H3 CLASS="subsection"><A NAME="htoc14">6.2</A>&nbsp;&nbsp;Module gen_iq_handler</H3><!--SEC END -->
<A NAME="sec:geniqhandl"></A>
The module <CODE>gen_iq_handler</CODE> allows to easily write handlers for IQ packets
@@ -402,9 +411,12 @@ process_local_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) -&gt;
</PRE>
<!--TOC subsection Services-->
<H3 CLASS="subsection"><A NAME="htoc14">6.2</A>&nbsp;&nbsp;Services</H3><!--SEC END -->
<H3 CLASS="subsection"><A NAME="htoc15">6.3</A>&nbsp;&nbsp;Services</H3><!--SEC END -->
<A NAME="sec:services"></A>
TBD<BR>
<BR>
TODO: use <CODE>proc_lib</CODE>
<PRE CLASS="verbatim">
-module(mod_echo).
+9 -16
View File
@@ -29,31 +29,24 @@
%% Modules
\newcommand{\module}[1]{\texttt{#1}}
\newcommand{\modadhoc}{\module{mod\_adhoc}}
\newcommand{\modannounce}{\module{mod\_announce}}
\newcommand{\modconfigure}{\module{mod\_configure}}
\newcommand{\moddisco}{\module{mod\_disco}}
\newcommand{\modecho}{\module{mod\_echo}}
\newcommand{\modirc}{\module{mod\_irc}}
\newcommand{\modlast}{\module{mod\_last}}
\newcommand{\modlastodbc}{\module{mod\_last\_odbc}}
\newcommand{\modmuc}{\module{mod\_muc}}
\newcommand{\modmuclog}{\module{mod\_muc\_log}}
\newcommand{\modecho}{\module{mod\_echo}}
\newcommand{\modoffline}{\module{mod\_offline}}
\newcommand{\modofflineodbc}{\module{mod\_offline\_odbc}}
\newcommand{\modprivacy}{\module{mod\_privacy}}
\newcommand{\modprivate}{\module{mod\_private}}
\newcommand{\modpubsub}{\module{mod\_pubsub}}
\newcommand{\modregister}{\module{mod\_register}}
\newcommand{\modroster}{\module{mod\_roster}}
\newcommand{\modrosterodbc}{\module{mod\_roster\_odbc}}
\newcommand{\modservicelog}{\module{mod\_service\_log}}
\newcommand{\modsharedroster}{\module{mod\_shared\_roster}}
\newcommand{\modstats}{\module{mod\_stats}}
\newcommand{\modtime}{\module{mod\_time}}
\newcommand{\modvcard}{\module{mod\_vcard}}
\newcommand{\modvcardldap}{\module{mod\_vcard\_ldap}}
\newcommand{\modvcardodbc}{\module{mod\_vcard\_odbc}}
\newcommand{\modversion}{\module{mod\_version}}
%% Title page
@@ -96,7 +89,7 @@
% Input introduction.tex
\input{introduction}
\section{How it Works}
\section{How it works}
\label{sec:howitworks}
@@ -157,7 +150,7 @@ does not exist, then it is opened and registered.
\section{XML Representation}
\section{XML representation}
\label{sec:xmlrepr}
Each XML stanza is represented as the following tuple:
@@ -261,14 +254,14 @@ Err = term()
\end{description}
\section{Modules}
\section{\ejabberd{} modules}
\label{sec:emods}
%\subsection{gen\_mod behaviour}
%\label{sec:genmod}
\subsection{gen\_mod behaviour}
\label{sec:genmod}
%TBD
TBD
\subsection{Module gen\_iq\_handler}
\label{sec:geniqhandl}
@@ -352,10 +345,10 @@ process_local_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
\subsection{Services}
\label{sec:services}
%TBD
TBD
%TODO: use \verb|proc_lib|
TODO: use \verb|proc_lib|
\begin{verbatim}
-module(mod_echo).
-163
View File
@@ -1,163 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
"http://www.w3.org/TR/REC-html40/loose.dtd">
<HTML>
<HEAD>
<TITLE>Ejabberd 1.1.2 Feature Sheet</TITLE>
<META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<META name="GENERATOR" content="hevea 1.08">
<STYLE type="text/css">
.toc{list-style:none;}
.title{margin:auto;text-align:center}
.center{text-align:center;margin-left:auto;margin-right:auto;}
.flushleft{text-align:left;margin-left:0ex;margin-right:auto;}
.flushright{text-align:right;margin-left:auto;margin-right:0ex;}
DIV TABLE{margin-left:inherit;margin-right:inherit;}
PRE{text-align:left;margin-left:0ex;margin-right:auto;}
BLOCKQUOTE{margin-left:4ex;margin-right:4ex;text-align:left;}
.part{margin:auto;text-align:center}
SPAN{width:20%; float:right; text-align:left; margin-left:auto;}
</STYLE>
</HEAD>
<BODY >
<!--HEVEA command line is: hevea -fix -noiso -pedantic features.tex -->
<!--HTMLHEAD-->
<!--ENDHTML-->
<!--PREFIX <ARG ></ARG>-->
<!--CUT DEF section 1 -->
<BR>
<BR>
<A NAME="titlepage"></A>
<TABLE CLASS="title">
<TR><TD>
<H1 CLASS="titlemain">Ejabberd 1.1.2 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="xmpp:sander@devrieze.dyndns.org"><TT>xmpp:sander@devrieze.dyndns.org</TT></A></H3></TD>
</TR></TABLE><BR>
<BR>
<DIV CLASS="center">
<IMG SRC="logo.png" ALT="logo.png">
<BR>
<BR>
</DIV>
<BLOCKQUOTE CLASS="quotation"><FONT COLOR="#921700"><I>I can thoroughly recommend ejabberd for ease of setup &ndash;
Kevin Smith, Current maintainer of the Psi project</I></FONT></BLOCKQUOTE>
<!--TOC section Introduction-->
<H2 CLASS="section"><A NAME="intro">Introduction</A></H2><!--SEC END -->
<A NAME="sec:intro"></A>
<BLOCKQUOTE CLASS="quotation"><FONT COLOR="#921700"><I>I just tried out ejabberd and was impressed both by ejabberd itself and the language it is written in, Erlang. &mdash;
Joeri</I></FONT></BLOCKQUOTE>
<TT>ejabberd</TT> is a <B><FONT SIZE=4><FONT COLOR="#001376">free and open source</FONT></FONT></B> instant messaging server written in <A HREF="http://www.erlang.org/">Erlang</A>.<BR>
<BR>
<TT>ejabberd</TT> is <B><FONT SIZE=4><FONT COLOR="#001376">cross-platform</FONT></FONT></B>, distributed, fault-tolerant, and based on open standards to achieve real-time communication.<BR>
<BR>
<TT>ejabberd</TT> is designed to be a <B><FONT SIZE=4><FONT COLOR="#001376">rock-solid and feature rich</FONT></FONT></B> XMPP server.<BR>
<BR>
<TT>ejabberd</TT> is suitable for small deployments, whether they need to be <B><FONT SIZE=4><FONT COLOR="#001376">scalable</FONT></FONT></B> or not, as well as extremely big deployments.<BR>
<BR>
<!--TOC subsection Key Features-->
<H3 CLASS="subsection"><A NAME="keyfeatures">Key Features</A></H3><!--SEC END -->
<A NAME="sec:keyfeatures"></A>
<BLOCKQUOTE CLASS="quotation"><FONT COLOR="#921700"><I>Erlang seems to be tailor-made for writing stable, robust servers. &mdash;
Peter Saint-Andr&eacute;, Executive Director of the Jabber Software Foundation</I></FONT></BLOCKQUOTE>
<TT>ejabberd</TT> is:
<UL CLASS="itemize"><LI CLASS="li-itemize">
<B><FONT SIZE=4><FONT COLOR="#001376">Cross-platform:</FONT></FONT></B> <TT>ejabberd</TT> runs under Microsoft Windows and Unix derived systems such as Linux, FreeBSD and NetBSD.<BR>
<BR>
<LI CLASS="li-itemize"><B><FONT SIZE=4><FONT COLOR="#001376">Distributed:</FONT></FONT></B> You can run <TT>ejabberd</TT> on a cluster of machines and all of them will serve the same Jabber domain(s). When you need more capacity you can simply add a new cheap node to your cluster. Accordingly, you do not need to buy an expensive high-end machine to support tens of thousands concurrent users.<BR>
<BR>
<LI CLASS="li-itemize"><B><FONT SIZE=4><FONT COLOR="#001376">Fault-tolerant:</FONT></FONT></B> You can deploy an <TT>ejabberd</TT> cluster so that all the information required for a properly working service will be replicated permanently on all nodes. This means that if one of the nodes crashes, the others will continue working without disruption. In addition, nodes also can be added or replaced `on the fly'.<BR>
<BR>
<LI CLASS="li-itemize"><B><FONT SIZE=4><FONT COLOR="#001376">Administrator Friendly:</FONT></FONT></B> <TT>ejabberd</TT> is built on top of the Open Source Erlang. As a result you do not need to install an external database, an external web server, amongst others because everything is already included, and ready to run out of the box. Other administrator benefits include:
<UL CLASS="itemize"><LI CLASS="li-itemize">
Comprehensive documentation.
<LI CLASS="li-itemize">Straightforward installers for Linux, Mac OS X, and Windows.<FONT COLOR="#FFAA00"><SPAN STYLE="font-variant:small-caps">improved</SPAN></FONT>
<LI CLASS="li-itemize">Web interface for administration tasks.
<LI CLASS="li-itemize">Shared Roster Groups.
<LI CLASS="li-itemize">Command line administration tool.<FONT COLOR="#FFAA00"><SPAN STYLE="font-variant:small-caps">improved</SPAN></FONT>
<LI CLASS="li-itemize">Can integrate with existing authentication mechanisms.
<LI CLASS="li-itemize">Capability to send announce messages.
</UL><BR>
<BR>
<LI CLASS="li-itemize"><B><FONT SIZE=4><FONT COLOR="#001376">Internationalized:</FONT></FONT></B> <TT>ejabberd</TT> leads in internationalization. Hence it is very well suited in a globalized world. Related features are:
<UL CLASS="itemize"><LI CLASS="li-itemize">
Translated in 12 languages.<FONT COLOR="#FFAA00"><SPAN STYLE="font-variant:small-caps">improved</SPAN></FONT>
<LI CLASS="li-itemize">Support for <A HREF="http://www.ietf.org/rfc/rfc3490.txt">IDNA</A>.
</UL><BR>
<BR>
<LI CLASS="li-itemize"><B><FONT SIZE=4><FONT COLOR="#001376">Open Standards:</FONT></FONT></B> <TT>ejabberd</TT> is the first Open Source Jabber server claiming to fully comply to the XMPP standard.
<UL CLASS="itemize"><LI CLASS="li-itemize">
Fully XMPP compliant.
<LI CLASS="li-itemize">XML-based protocol.
<LI CLASS="li-itemize"><A HREF="http://ejabberd.jabber.ru/protocols">Many JEPs supported</A>.
</UL></UL>
<!--TOC subsection Additional Features-->
<H3 CLASS="subsection"><A NAME="addfeatures">Additional Features</A></H3><!--SEC END -->
<A NAME="sec:addfeatures"></A>
<BLOCKQUOTE CLASS="quotation"><FONT COLOR="#921700"><I>ejabberd is making inroads to solving the "buggy incomplete server" problem &mdash;
Justin Karneges, Founder of the Psi and the Delta projects</I></FONT></BLOCKQUOTE>
Moreover, <TT>ejabberd</TT> comes with a wide range of other state-of-the-art features:
<UL CLASS="itemize"><LI CLASS="li-itemize">
Modular
<UL CLASS="itemize"><LI CLASS="li-itemize">
Load only the modules you want.
<LI CLASS="li-itemize">Extend <TT>ejabberd</TT> with your own custom modules.
</UL>
<LI CLASS="li-itemize">Security
<UL CLASS="itemize"><LI CLASS="li-itemize">
SASL and STARTTLS for c2s and s2s connections.
<LI CLASS="li-itemize">STARTTLS and Dialback s2s connections.
<LI CLASS="li-itemize">Web interface accessible via HTTPS secure access.
</UL>
<LI CLASS="li-itemize">Databases
<UL CLASS="itemize"><LI CLASS="li-itemize">
Native MySQL support.
<LI CLASS="li-itemize">Native PostgreSQL support.
<LI CLASS="li-itemize">Mnesia.
<LI CLASS="li-itemize">ODBC data storage support.
<LI CLASS="li-itemize">Microsoft SQL Server support.<FONT COLOR="red"><SPAN STYLE="font-variant:small-caps">new</SPAN></FONT>
</UL>
<LI CLASS="li-itemize">Authentication
<UL CLASS="itemize"><LI CLASS="li-itemize">
LDAP and ODBC.<FONT COLOR="#FFAA00"><SPAN STYLE="font-variant:small-caps">improved</SPAN></FONT>
<LI CLASS="li-itemize">External Authentication script.
<LI CLASS="li-itemize">Internal Authentication.
</UL>
<LI CLASS="li-itemize">Others
<UL CLASS="itemize"><LI CLASS="li-itemize">
Compressing XML streams with Stream Compression (<A HREF="http://www.jabber.org/jeps/jep-0138.html">JEP-0138</A>).
<LI CLASS="li-itemize">Interface with networks such as AIM, ICQ and MSN.
<LI CLASS="li-itemize">Statistics via Statistics Gathering (<A HREF="http://www.jabber.org/jeps/jep-0039.html">JEP-0039</A>).
<LI CLASS="li-itemize">IPv6 support both for c2s and s2s connections.
<LI CLASS="li-itemize"><A HREF="http://www.jabber.org/jeps/jep-0045.html">Multi-User Chat</A> module with logging.<FONT COLOR="#FFAA00"><SPAN STYLE="font-variant:small-caps">improved</SPAN></FONT>
<LI CLASS="li-itemize">Users Directory based on users vCards.
<LI CLASS="li-itemize"><A HREF="http://www.jabber.org/jeps/jep-0060.html">Publish-Subscribe</A> component.
<LI CLASS="li-itemize">Support for virtual hosting.
<LI CLASS="li-itemize"><A HREF="http://www.jabber.org/jeps/jep-0025.html">HTTP Polling</A> service.
<LI CLASS="li-itemize">IRC transport.
</UL>
</UL>
<!--HTMLFOOT-->
<!--ENDHTML-->
<!--FOOTER-->
<HR SIZE=2><BLOCKQUOTE CLASS="quote"><EM>This document was translated from L<sup>A</sup>T<sub>E</sub>X by
</EM><A HREF="http://pauillac.inria.fr/~maranget/hevea/index.html"><EM>H<FONT SIZE=2><sup>E</sup></FONT>V<FONT SIZE=2><sup>E</sup></FONT>A</EM></A><EM>.</EM></BLOCKQUOTE></BODY>
</HTML>
+8 -10
View File
@@ -9,7 +9,7 @@
Feature\ Sheet,pdfauthor=Sander\
Devrieze,pdfsubject=ejabberd,pdfkeywords=ejabberd]{hyperref}
\usepackage{verbatim}
\usepackage{color}
\usepackage{xcolor}
%% Index
% Remove the index anchors from the HTML version to save size and bandwith.
@@ -49,14 +49,11 @@
% Options
\newcommand{\marking}[1]{\textbf{\begin{large}\textcolor{ejblue}{#1}\end{large}}} % Marking enabled
\newcommand{\quoting}[2][yozhik]{\begin{quotation}\textcolor{#1}{\textit{#2}}\end{quotation}} % Quotes enabled
\newcommand{\new}{\marginpar{\textcolor{red}{\textsc{new}}}} % Highlight new features
\newcommand{\improved}{\marginpar{\textcolor{orange}{\textsc{improved}}}} % Highlight improved features
\newcommand{\new}{\begin{latexonly}\marginpar{\textcolor{red}{\textsc{new}}}\end{latexonly}} % Highlight new features
\newcommand{\improved}{\begin{latexonly}\marginpar{\textcolor{orange}{\textsc{improved}}}\end{latexonly}} % Highlight improved features
\newcommand{\moreinfo}[1]{} % Hide details
\setcounter{secnumdepth}{-1} % Disable section numbering
%% To by-pass errors in the HTML version.
\newstyle{SPAN}{width:20\%; float:right; text-align:left; margin-left:auto;}
\definecolor{orange} {cmyk}{0.000,0.333,1.000,0.000}
%% Footnotes
\begin{latexonly}
\global\parskip=9pt plus 3pt minus 1pt
@@ -70,7 +67,7 @@
%% Fancy header
\fancyhf{}
\pagestyle{fancy}
\rhead{\textcolor{ejblue}{The Expandable Jabber Daemon.}}
\rhead{\textcolor{ejblue}{The expandable Jabber daemon.}}
\renewcommand{\headrule}{{\color{ejblue}%
\hrule width\headwidth height\headrulewidth \vskip-\headrulewidth}}
\lhead{\setlength{\unitlength}{-6mm}
@@ -88,7 +85,7 @@
\begin{document}
\label{titlepage}
\label{sec:titlepage}
\begin{titlepage}
\maketitle{}
@@ -110,9 +107,10 @@
% the same identifier".
\begin{latexonly}
\setcounter{page}{2}
\pagecolor{ejgreenwhite}
\end{latexonly}
\pagecolor{ejgreenwhite}
% Input introduction.tex
\input{introduction}
+1091 -1980
View File
File diff suppressed because it is too large Load Diff
+909 -1696
View File
File diff suppressed because it is too large Load Diff
+33 -40
View File
@@ -1,31 +1,25 @@
\section{\aname{intro}{Introduction}}
\label{sec:intro}
\section{Introduction}
\label{sec:intr}
\quoting{I just tried out ejabberd and was impressed both by ejabberd itself and the language it is written in, Erlang. ---
\quoting{I just tried out ejabberd and was impressed both by ejabberd itself and the language it is written in, Erlang. --
Joeri}
%ejabberd is a free and open source instant messaging server written in Erlang. ejabberd is cross-platform, distributed, fault-tolerant, and based on open standards to achieve real-time communication (Jabber/XMPP).
\ejabberd{} is a free (GPL) distributed fault-tolerant \Jabber{}/XMPP server and is mainly written in \footahref{http://www.erlang.org/}{Erlang}.
\ejabberd{} is a \marking{free and open source} instant messaging server written in \footahref{http://www.erlang.org/}{Erlang}.
\ejabberd{} is designed to be a \marking{stable}, \marking{standards compliant}, and \marking{\mbox{feature rich}} \Jabber{}/XMPP server.
\ejabberd{} is \marking{cross-platform}, distributed, fault-tolerant, and based on open standards to achieve real-time communication.
\ejabberd{} is suitable for small servers, whether they need to be scalable or not, as well as extremely big servers.
\ejabberd{} is designed to be a \marking{rock-solid and feature rich} XMPP server.
\ejabberd{} is suitable for small deployments, whether they need to be \marking{scalable} or not, as well as extremely big deployments.
%\subsection{\aname{layout}{Layout with example deployment (title needs a better name)}}
%\label{sec:layout}
%\subsection{Layout with example deployment (title needs a better name)}
%In this section there will be a graphical overview like these:\\
%\verb|http://www.tipic.com/var/timp/timp_dep.gif| \\
%\verb|http://www.jabber.com/images/jabber_Com_Platform.jpg| \\
%\verb|http://www.antepo.com/files/OPN45systemdatasheet.pdf| \\
%A page full with names of Jabber client that are known to work with ejabberd. \begin{tiny}tiny font\end{tiny}
%Some small images of Jabber clients that are known to work greatly with ejabberd. Less text!!!
%\subsection{\aname{trytoday}{Try It Today}}
%\label{sec:trytoday}
%\subsection{Try It Today}
%(Not sure if I will include/finish this section for the next version.)
@@ -38,42 +32,42 @@ Joeri}
%\end{itemize}
\newpage
\subsection{\aname{keyfeatures}{Key Features}}
\subsection{Key Features}
\label{sec:keyfeatures}
\ind{features!key features}
\quoting{Erlang seems to be tailor-made for writing stable, robust servers. ---
\quoting{Erlang seems to be tailor-made for writing stable, robust servers. --
Peter Saint-Andr\'e, Executive Director of the Jabber Software Foundation}
\ejabberd{} is:
\begin{itemize}
\item \marking{Cross-platform:} \ejabberd{} runs under Microsoft Windows and Unix derived systems such as Linux, FreeBSD and NetBSD.
\item \marking{Multiplatform:} \ejabberd{} runs under Microsoft Windows and Unix derived systems such as Linux, FreeBSD and NetBSD.
\item \marking{Distributed:} You can run \ejabberd{} on a cluster of machines and all of them will serve the same \Jabber{} domain(s). When you need more capacity you can simply add a new cheap node to your cluster. Accordingly, you do not need to buy an expensive high-end machine to support tens of thousands concurrent users.
\item \marking{Fault-tolerant:} You can deploy an \ejabberd{} cluster so that all the information required for a properly working service will be replicated permanently on all nodes. This means that if one of the nodes crashes, the others will continue working without disruption. In addition, nodes also can be added or replaced `on the fly'.
\item \marking{Fault-tolerant:} You can deploy an \ejabberd{} cluster so that all the information required for a properly working service will be replicated permanently on all nodes. This means that if one of the nodes crashes, the others will continue working without disruption. In addition, nodes also can be added or replaced ``on the fly''.
\item \marking{Administrator Friendly:} \ejabberd{} is built on top of the Open Source Erlang. As a result you do not need to install an external database, an external web server, amongst others because everything is already included, and ready to run out of the box. Other administrator benefits include:
\begin{itemize}
\item Comprehensive documentation.
\item Straightforward installers for Linux, Mac OS X, and Windows.\improved{}
\item Web interface for administration tasks.
\item Shared Roster Groups.
\item Command line administration tool.\improved{}
\item Comprehensive documentation.\moreinfo{ --- You can start in the \footahref{http://ejabberd.jabber.ru/book}{ejabberd Book}.}
\item Straightforward installers for Linux, Mac OS X, and Windows.\improved{}\moreinfo{ --- (\footahref{http://ejabberd.jabber.ru/screenshots-linux-installer}{Screenshots}).}
\item Web interface for administration tasks.\moreinfo{ --- With HTTPS secure access. \footahref{http://ejabberd.jabber.ru/online-demo-webadmin}{Demo}.}
\item Shared Roster Groups.\moreinfo{ --- The administrator can setup a common list of \Jabber{} users for all users on the server. Those users are virtually added to all rosters. They cannot be removed, but can be renamed or moved into different roster groups. Does not require client implementation. Not related to \jepref{0144} (Roster Item Exchange).\footahref{http://ejabberd.jabber.ru/screenshots-shared-roster-groups}{Screenshots})}
\item Command line administration tool.\improved{}\moreinfo{ --- Some basic administration tasks can be acomplished using the command line: register/remove users, backup/restore database, amongst others (\footahref{http://ejabberd.jabber.ru/screenshots-administration#ejabberdctl}{Screenshots}).}
\item Can integrate with existing authentication mechanisms.
\item Capability to send announce messages.
\item Capability to send announce messages.\improved{}
\end{itemize}
\item \marking{Internationalized:} \ejabberd{} leads in internationalization. Hence it is very well suited in a globalized world. Related features are:
\begin{itemize}
\item Translated in 12 languages.\improved{}
\item Translated in 11 languages.\moreinfo{ --- More information is available \footahref{http://ejabberd.jabber.ru/localization}{here}.}
\item Support for \footahref{http://www.ietf.org/rfc/rfc3490.txt}{IDNA}.
\end{itemize}
\item \marking{Open Standards:} \ejabberd{} is the first Open Source Jabber server claiming to fully comply to the XMPP standard.
\begin{itemize}
\item Fully XMPP compliant.
\item XML-based protocol.
\item Fully XMPP compliant \moreinfo{ --- ejabberd is fully compliant with XMPP Core 1.0 and XMPP IM 1.0. Check the \footahref{http://ejabberd.jabber.ru/protocols}{supported protocols}.}
\item XML-based protocol
\item \footahref{http://ejabberd.jabber.ru/protocols}{Many JEPs supported}.
\end{itemize}
@@ -81,51 +75,50 @@ Peter Saint-Andr\'e, Executive Director of the Jabber Software Foundation}
\newpage
\subsection{\aname{addfeatures}{Additional Features}}
\subsection{Additional Features}
\label{sec:addfeatures}
\ind{features!additional features}
\quoting{ejabberd is making inroads to solving the "buggy incomplete server" problem ---
\quoting{ejabberd is making inroads to solving the "buggy incomplete server" problem --
Justin Karneges, Founder of the Psi and the Delta projects}
Moreover, \ejabberd{} comes with a wide range of other state-of-the-art features:
Besides common \Jabber{} server features, \ejabberd{} comes with a wide range of other features:
\begin{itemize}
\item Modular
\begin{itemize}
\item Load only the modules you want.
\item Extend \ejabberd{} with your own custom modules.
\item Extend \ejabberd{} with your own custom modules.\moreinfo{ --- A list of contributed modules and patches is available on the \footahref{http://ejabberd.jabber.ru/contributions}{contributions page}.}
\end{itemize}
\item Security
\begin{itemize}
\item SASL and STARTTLS for c2s and s2s connections.
\item SASL and STARTTLS for c2s and s2s connections.\improved{}
\item STARTTLS and Dialback s2s connections.
\item Web interface accessible via HTTPS secure access.
\end{itemize}
\item Databases
\begin{itemize}
\item Native MySQL support.
\item Native MySQL support.\new{}
\item Native PostgreSQL support.
\item Mnesia.
\item ODBC data storage support.
\item Microsoft SQL Server support.\new{}
\item ODBC data storage support. \moreinfo{ --- ODBC requests can be load balanced between several connections.}
\end{itemize}
\item Authentication
\begin{itemize}
\item LDAP and ODBC.\improved{}
\item LDAP and ODBC. \moreinfo{ --- Accounts can authenticate in a LDAP server.}
\item External Authentication script.
\item Internal Authentication.
\end{itemize}
\item Others
\begin{itemize}
\item Compressing XML streams with Stream Compression (\jepref{0138}).
\item Compressing XML streams with Stream Compression (\jepref{0138}).\new{}
\item Interface with networks such as AIM, ICQ and MSN.
\item Statistics via Statistics Gathering (\jepref{0039}).
\item IPv6 support both for c2s and s2s connections.
\item \tjepref{0045}{Multi-User Chat} module with logging.\improved{}
\item Users Directory based on users vCards.
\item \tjepref{0060}{Publish-Subscribe} component.
\item Support for virtual hosting.
\item Support for virtual hosting. \moreinfo{ --- Several \Jabber{} hosts can be hosted on the same \ejabberd{} instance. As simple as adding a new domain name to the list of hosts in the configuration file.}
\item \tjepref{0025}{HTTP Polling} service.
\item IRC transport.
\item IRC transport.\improved{}
\end{itemize}
\end{itemize}
View File
+1 -1
View File
@@ -9,7 +9,7 @@
This release fix a security issue introduced in ejabberd 1.1.0. In SASL
mode, anonymous login was enabled as a default. Upgrading ejabberd 1.1.0 to
ejabberd 1.1.1 is highly recommended.
ejabberd 1.1.1 is highly recommanded.
ejabberd can be downloaded from the Process-one website:
http://www.process-one.net/en/projects/ejabberd/
-119
View File
@@ -1,119 +0,0 @@
Release Notes
ejabberd 1.1.2
27 September 2006
This document describes the main changes in ejabberd 1.1.2.
This version is a major improvement over ejabberd 1.1.1, improving the
overall behaviour of the server in many areas. Users of ejabberd 1.1.1
should upgrade to this new release for improved robustness and compliance.
ejabberd can be downloaded from the Process-one website:
http://www.process-one.net/en/projects/ejabberd/
Detailed information can be found in the Feature Sheet and in the
Installation and Operation Guide which are both available on the
Process-one website:
http://www.process-one.net/en/projects/ejabberd/docs.html
ejabberd includes 44 improvements. A complete list of changes can be
retrieved from:
http://redir.process-one.net/ejabberd-1.1.2
Recent changes include:
LDAP Improvements
- Major improvements have been made on the LDAP module. It is now more
flexible and more robust.
HTTP Polling Fixes
- The HTTP polling modules have been fixed and improved: the connections are
closed properly and polled messages cannot be lost anymore.
Roster Management Improvement
- Roster management improvements increase reliability, especially in cases
where users are on different servers.
- Shared rosters are more reliable.
Improved Robustness
- It is now possible to limit the number of opened connections for a single
user.
Relational databases
- Database support: Microsoft SQL Server is now officially supported in ODBC
mode.
Publish-Subscribe Improvement
- Restricting node creation with a dedicated ACL rule is now possible.
Localization
- A Czech translation has been added.
- Translations have been updated.
Binary Installer
- New binary installer for Windows including all requirements.
- Improved installers for Linux and MacOSX (PowerPC)
XMPP Compliancy
- Some protocol compliance fix have been added, after the Portland XMPP
Interop Meeting in July.
Miscelanous
- MUC have been improved (logging rendering).
- The command line tool ejabberdctl has been improved.
- The build chain has been improved, including MacOSX support.
- The documentation has been improved and updated to describe the new
features.
Bugfixes
- Anonymous login bugfixes.
- Please refer to the ChangeLog file supplied with this release regarding
all improvements in ejabberd.
Installation Notes
Supported Erlang Version
- You need at least Erlang/OTP R9C-2 to run ejabberd 1.1.2.
- The recommanded version is Erlang/OTP R10B-10.
- Erlang/OTP R11B has not yet been fully certified for ejabberd.
Installation
Installers are provided for Microsoft Windows, Linux/x86 and MacOSX/PPC.
They can be retrieved from:
http://www.process-one.net/en/projects/ejabberd/download.html
Migration Notes
- Before any migration, ejabberd system and database must be properly
backed up.
- The relational database schema has changed between version 1.1.1 and
1.1.2. An "askmessage" column needs to be added in the "rosterusers" table
to perform the migration.
References
Contributed tutorials and documents of interest are:
- Migration from other XMPP servers to ejabberd:
http://ejabberd.jabber.ru/migrate-to-ejabberd
- Transport configuration for connecting to other networks:
http://ejabberd.jabber.ru/tutorials-transports
- Frequently Asked Questions:
http://ejabberd.jabber.ru/faq
END
+1 -1
View File
@@ -1,2 +1,2 @@
% Define ejabberd version here.
\newcommand{\version}{1.1.2}
\newcommand{\version}{1.1.1}
+1 -8
View File
@@ -44,13 +44,6 @@ ETCDIR = $(DESTDIR)@prefix@/etc/ejabberd
ASN_FLAGS = -bber_bin +der +compact_bit_string +optimize +noobj
ifeq ($(shell uname),Darwin)
DYNAMIC_LIB_CFLAGS = -fPIC -bundle -flat_namespace -undefined suppress
else
# Assume Linux-style dynamic library flags
DYNAMIC_LIB_CFLAGS = -fpic -shared
endif
all: $(ERLSHLIBS) compile-beam all-recursive
compile-beam: XmppAddr.hrl $(BEAMS)
@@ -77,7 +70,7 @@ $(ERLSHLIBS): %.so: %.c
$(subst ../,,$(subst .so,.c,$@)) \
$(EXPAT_LIBS) $(EXPAT_CFLAGS) \
$(ERLANG_LIBS) $(ERLANG_CFLAGS) \
-o $@ $(DYNAMIC_LIB_CFLAGS)
-o $@ -fpic -shared
install: all
install -d $(BEAMDIR)
+1 -7
View File
@@ -171,13 +171,7 @@ match_acl(ACL, JID, Host) ->
is_glob_match(Server, SR);
{node_glob, UR, SR} ->
is_glob_match(Server, SR) andalso
is_glob_match(User, UR);
WrongSpec ->
?ERROR_MSG(
"Wrong ACL expression: ~p~n"
"Check your config file and reload it with the override_acls option enabled",
[WrongSpec]),
false
is_glob_match(User, UR)
end
end,
ets:lookup(acl, {ACL, global}) ++
+1641 -2450
View File
File diff suppressed because it is too large Load Diff
+1 -26
View File
@@ -37,7 +37,7 @@ AC_MOD_ENABLE(odbc, no)
AC_MOD_ENABLE(ejabberd_zlib, yes)
AC_ARG_ENABLE(roster_gateway_workaround,
[ --enable-roster-gateway-workaround Turn on workaround for processing gateway subscriptions (default: no)],
[ --enable-roster-gateway-workaround Turn on workaround for processing gateway subscriptions],
[case "${enableval}" in
yes) roster_gateway_workaround=true ;;
no) roster_gateway_workaround=false ;;
@@ -45,15 +45,6 @@ AC_ARG_ENABLE(roster_gateway_workaround,
esac],[roster_gateway_workaround=false])
AC_SUBST(roster_gateway_workaround)
AC_ARG_ENABLE(mssql,
[ --enable-mssql Use Microsoft SQL Server database (default: no, requires --enable-odbc)],
[case "${enableval}" in
yes) db_type=mssql ;;
no) db_type=generic ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-mssql) ;;
esac],[db_type=generic])
AC_SUBST(db_type)
AC_CONFIG_FILES([Makefile
$make_mod_irc
$make_mod_muc
@@ -66,20 +57,4 @@ AC_CONFIG_FILES([Makefile
$make_ejabberd_zlib])
#openssl
AM_WITH_OPENSSL
# If ssl is kerberized it need krb5.h
# On RedHat and OpenBSD, krb5.h is in an unsual place:
KRB5_INCLUDE="`krb5-config --cflags 2>/dev/null`"
if test -n "$KRB5_INCLUDE" ; then
CPPFLAGS="$CPPFLAGS $KRB5_INCLUDE"
else
# For RedHat For BSD
for D in /usr/kerberos/include /usr/include/kerberos /usr/include/kerberosV
do
if test -d $D ; then
CPPFLAGS="$CPPFLAGS -I$D"
fi
done
fi
AC_CHECK_HEADER(krb5.h,,)
AC_OUTPUT
-2
View File
@@ -46,7 +46,6 @@ start() ->
Version = "EJABBERD_VERSION = " ++ ?VERSION ++ "\n",
ExpatDir = "EXPAT_DIR = c:\\progra~1\\expat-1.95.7\n",
OpenSSLDir = "OPENSSL_DIR = c:\\progra~1\\OpenSSL\n",
DBType = "DBTYPE = generic\n", %% 'generic' or 'mssql'
SSLDir = "SSLDIR = " ++ code:lib_dir("ssl") ++ "\n",
StdLibDir = "STDLIBDIR = " ++ code:lib_dir("stdlib") ++ "\n",
@@ -59,7 +58,6 @@ start() ->
SSLDir ++
StdLibDir ++
OpenSSLDir ++
DBType ++
ExpatDir ++
ExpatLib ++
ExpatFlag ++
+1 -1
View File
@@ -2,7 +2,7 @@
{application, ejabberd,
[{description, "ejabberd"},
{vsn, "1.1.2"},
{vsn, "1.0.0"},
{modules, [acl,
configure,
cyrsasl,
+1 -6
View File
@@ -20,8 +20,6 @@
%{acl, test, {user_regexp, "^test"}}.
%{acl, test, {user_glob, "test*"}}.
% Everybody can create pubsub nodes
{access, pubsub_createnode, [{allow, all}]}.
% Only admins can use configuration interface:
{access, configure, [{allow, admin}]}.
@@ -99,9 +97,6 @@
% Host name:
{hosts, ["localhost"]}.
%% Define the maximum number of time a single user is allowed to connect:
{max_user_sessions, 10}.
%% Anonymous login support:
%% auth_method: anonymous
%% anonymous_protocol: sasl_anon|login_anon|both
@@ -173,7 +168,7 @@
{access_admin, muc_admin}]},
% {mod_muc_log, []},
% {mod_shared_roster, []},
{mod_pubsub, [{access_createnode, pubsub_createnode}]},
{mod_pubsub, []},
{mod_time, []},
{mod_last, []},
{mod_version, []}
+1 -1
View File
@@ -6,7 +6,7 @@
%%% Id : $Id$
%%%----------------------------------------------------------------------
-define(VERSION, "1.1.2").
-define(VERSION, "1.1.1").
%-define(ejabberd_debug, true).
%-define(DBGFSM, true).
-59
View File
@@ -1,59 +0,0 @@
%%%-------------------------------------------------------------------
%%% File : ejabberd_admin.erl
%%% Author : Mickael Remond <mremond@process-one.net>
%%% Description : This module gathers admin functions used by different
%%% access method:
%%% - ejabberdctl command-line tool
%%% - web admin interface
%%% - adhoc mode
%%%
%%% Created : 7 May 2006 by Mickael Remond <mremond@process-one.net>
%%% Id : $Id: $
%%%----------------------------------------------------------------------
%%% Copyright (c) 2006 Process One
%%%-------------------------------------------------------------------
-module(ejabberd_admin).
-author('mickael.remond@process-one.net').
-vsn('$Revision: $ ').
-export([restore/1]).
-include("ejabberd.hrl").
%% Mnesia database restore
%% This function is called from ejabberd_ctl, ejabberd_web_admin and
%% mod_configure/adhoc
restore(Path) ->
mnesia:restore(Path, [{keep_tables,keep_tables()},
{default_op, skip_tables}]).
%% This function return a list of tables that should be kept from a previous
%% version backup.
%% Obsolete tables or tables created by module who are no longer used are not
%% restored and are ignored.
keep_tables() ->
lists:flatten([acl, passwd, config, local_config, disco_publish,
keep_modules_tables()]).
%% Returns the list of modules tables in use, according to the list of actually
%% loaded modules
keep_modules_tables() ->
lists:map(fun(Module) -> module_tables(Module) end,
gen_mod:loaded_modules(?MYNAME)).
%% TODO: This mapping should probably be moved to a callback function in each
%% module.
%% Mapping between modules and their tables
module_tables(mod_announce) -> [motd, motd_users];
module_tables(mod_irc) -> [irc_custom];
module_tables(mod_last) -> [last_activity];
module_tables(mod_muc) -> [muc_room, muc_registered];
module_tables(mod_offline) -> [offline_msg];
module_tables(mod_privacy) -> [privacy];
module_tables(mod_private) -> [private_storage];
module_tables(mod_pubsub) -> [pubsub_node];
module_tables(mod_roster) -> [roster];
module_tables(mod_shared_roster) -> [sr_group, sr_user];
module_tables(mod_vcard) -> [vcard, vcard_search];
module_tables(_Other) -> [].
-10
View File
@@ -25,7 +25,6 @@
get_password/2,
get_password_s/2,
is_user_exists/2,
is_user_exists_in_other_modules/3,
remove_user/2,
remove_user/3,
plain_password_required/1,
@@ -131,14 +130,6 @@ is_user_exists(User, Server) ->
M:is_user_exists(User, Server)
end, auth_modules(Server)).
%% Check if the user exists in all authentications module except the module
%% passed as parameter
is_user_exists_in_other_modules(Module, User, Server) ->
lists:any(
fun(M) ->
M:is_user_exists(User, Server)
end, auth_modules(Server)--[Module]).
remove_user(User, Server) ->
lists:foreach(
fun(M) ->
@@ -169,7 +160,6 @@ auth_modules(Server) ->
LServer = jlib:nameprep(Server),
Method = ejabberd_config:get_local_option({auth_method, LServer}),
Methods = if
Method == undefined -> [];
is_list(Method) -> Method;
is_atom(Method) -> [Method]
end,
+1 -2
View File
@@ -149,8 +149,7 @@ check_password(User, Server, Password) ->
check_password(User, Server, _Password, _StreamID, _Digest) ->
%% We refuse login for registered accounts (They cannot logged but
%% they however are "reserved")
case ejabberd_auth:is_user_exists_in_other_modules(?MODULE,
User, Server) of
case ejabberd_auth:is_user_exists(User, Server) of
true -> false;
false -> login(User, Server)
end.
+62 -299
View File
@@ -10,21 +10,8 @@
-author('alexey@sevcom.net').
-vsn('$Revision$ ').
-behaviour(gen_server).
%% gen_server callbacks
-export([init/1,
handle_info/2,
handle_call/3,
handle_cast/2,
terminate/2,
code_change/3
]).
%% External exports
-export([start/1,
stop/1,
start_link/1,
set_password/3,
check_password/3,
check_password/5,
@@ -42,90 +29,39 @@
-include("ejabberd.hrl").
-include("eldap/eldap.hrl").
-record(state, {host,
eldap_id,
bind_eldap_id,
servers,
port,
dn,
password,
base,
uidattr,
uidattr_format,
ufilter,
sfilter,
dn_filter,
dn_filter_attrs
}).
%% Unused callbacks.
handle_cast(_Request, State) ->
{noreply, State}.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
handle_info(_Info, State) ->
{noreply, State}.
%% -----
%%%----------------------------------------------------------------------
%%% API
%%%----------------------------------------------------------------------
start(Host) ->
Proc = gen_mod:get_module_proc(Host, ?MODULE),
ChildSpec = {
Proc, {?MODULE, start_link, [Host]},
permanent, 1000, worker, [?MODULE]
},
supervisor:start_child(ejabberd_sup, ChildSpec).
stop(Host) ->
Proc = gen_mod:get_module_proc(Host, ?MODULE),
gen_server:call(Proc, stop),
supervisor:terminate_child(ejabberd_sup, Proc),
supervisor:delete_child(ejabberd_sup, Proc).
start_link(Host) ->
Proc = gen_mod:get_module_proc(Host, ?MODULE),
gen_server:start_link({local, Proc}, ?MODULE, Host, []).
terminate(_Reason, State) ->
ejabberd_ctl:unregister_commands(
State#state.host,
[{"registered-users", "list all registered users"}],
ejabberd_auth, ctl_process_get_registered).
init(Host) ->
State = parse_options(Host),
eldap:start_link(State#state.eldap_id,
State#state.servers,
State#state.port,
State#state.dn,
State#state.password),
eldap:start_link(State#state.bind_eldap_id,
State#state.servers,
State#state.port,
State#state.dn,
State#state.password),
LDAPServers = ejabberd_config:get_local_option({ldap_servers, Host}),
RootDN = ejabberd_config:get_local_option({ldap_rootdn, Host}),
Password = ejabberd_config:get_local_option({ldap_password, Host}),
eldap:start_link(get_eldap_id(Host, ejabberd),
LDAPServers, 389, RootDN, Password),
eldap:start_link(get_eldap_id(Host, ejabberd_bind),
LDAPServers, 389, RootDN, Password),
ejabberd_ctl:register_commands(
Host,
[{"registered-users", "list all registered users"}],
ejabberd_auth, ctl_process_get_registered),
{ok, State}.
-define(REPLY_TIMEOUT, 10000).
ok.
plain_password_required() ->
true.
check_password(User, Server, Password) ->
Proc = gen_mod:get_module_proc(Server, ?MODULE),
case catch gen_server:call(Proc,
{check_pass, User, Password}, ?REPLY_TIMEOUT) of
{'EXIT', _} ->
case find_user_dn(User, Server) of
false ->
false;
Result ->
Result
DN ->
LServer = jlib:nameprep(Server),
case eldap:bind(get_eldap_id(LServer, ejabberd_bind),
DN, Password) of
ok ->
true;
_ ->
false
end
end.
check_password(User, Server, Password, _StreamID, _Digest) ->
@@ -141,13 +77,31 @@ dirty_get_registered_users() ->
get_vh_registered_users(?MYNAME).
get_vh_registered_users(Server) ->
Proc = gen_mod:get_module_proc(Server, ?MODULE),
case catch gen_server:call(Proc,
get_vh_registered_users, ?REPLY_TIMEOUT) of
{'EXIT', _} ->
[];
Result ->
Result
LServer = jlib:nameprep(Server),
Attr = ejabberd_config:get_local_option({ldap_uidattr, LServer}),
Filter = eldap:present(Attr),
Base = ejabberd_config:get_local_option({ldap_base, LServer}),
case eldap:search(get_eldap_id(LServer, ejabberd),
[{base, Base},
{filter, Filter},
{attributes, [Attr]}]) of
#eldap_search_result{entries = Es} ->
lists:flatmap(
fun(E) ->
case lists:keysearch(Attr, 1, E#eldap_entry.attributes) of
{value, {_, [U]}} ->
case jlib:nodeprep(U) of
error ->
[];
LU ->
[{LU, LServer}]
end;
_ ->
[]
end
end, Es);
_ ->
[]
end.
get_password(_User, _Server) ->
@@ -157,13 +111,11 @@ get_password_s(_User, _Server) ->
"".
is_user_exists(User, Server) ->
Proc = gen_mod:get_module_proc(Server, ?MODULE),
case catch gen_server:call(Proc,
{is_user_exists, User}, ?REPLY_TIMEOUT) of
{'EXIT', _} ->
case find_user_dn(User, Server) of
false ->
false;
Result ->
Result
_DN ->
true
end.
remove_user(_User, _Server) ->
@@ -172,214 +124,25 @@ remove_user(_User, _Server) ->
remove_user(_User, _Server, _Password) ->
not_allowed.
%%%----------------------------------------------------------------------
%%% Internal functions
%%%----------------------------------------------------------------------
handle_call({check_pass, User, Password}, _From, State) ->
Reply = case find_user_dn(User, State) of
false ->
false;
DN ->
case eldap:bind(State#state.bind_eldap_id, DN, Password) of
ok -> true;
_ -> false
end
end,
{reply, Reply, State};
handle_call(get_vh_registered_users, _From, State) ->
UA = State#state.uidattr,
UAF = State#state.uidattr_format,
Eldap_ID = State#state.eldap_id,
Server = State#state.host,
SortedDNAttrs = usort_attrs(State#state.dn_filter_attrs),
Reply = case eldap_filter:parse(State#state.sfilter) of
{ok, EldapFilter} ->
case eldap:search(Eldap_ID, [{base, State#state.base},
{filter, EldapFilter},
{attributes, SortedDNAttrs}]) of
#eldap_search_result{entries = Entries} ->
lists:flatmap(
fun(#eldap_entry{attributes = Attrs,
object_name = DN}) ->
case is_valid_dn(DN, Attrs, State) of
false -> [];
_ ->
case get_ldap_attr(UA, Attrs) of
"" -> [];
User ->
case get_user_part(User, UAF) of
{ok, U} ->
case jlib:nodeprep(U) of
error -> [];
LU -> [{LU, jlib:nameprep(Server)}]
end;
_ -> []
end
end
end
end, Entries);
_ ->
[]
end;
_ ->
[]
end,
{reply, Reply, State};
handle_call({is_user_exists, User}, _From, State) ->
Reply = case find_user_dn(User, State) of
false -> false;
_DN -> true
end,
{reply, Reply, State};
handle_call(stop, _From, State) ->
{stop, normal, ok, State};
handle_call(_Request, _From, State) ->
{reply, bad_request, State}.
find_user_dn(User, State) ->
DNAttrs = usort_attrs(State#state.dn_filter_attrs),
case eldap_filter:parse(State#state.ufilter, [{"%u", User}]) of
{ok, Filter} ->
case eldap:search(State#state.eldap_id, [{base, State#state.base},
{filter, Filter},
{attributes, DNAttrs}]) of
#eldap_search_result{entries = [#eldap_entry{attributes = Attrs,
object_name = DN} | _]} ->
is_valid_dn(DN, Attrs, State);
_ ->
false
end;
find_user_dn(User, Server) ->
LServer = jlib:nameprep(Server),
Attr = ejabberd_config:get_local_option({ldap_uidattr, LServer}),
Filter = eldap:equalityMatch(Attr, User),
Base = ejabberd_config:get_local_option({ldap_base, LServer}),
case eldap:search(get_eldap_id(LServer, ejabberd),
[{base, Base},
{filter, Filter},
{attributes, []}]) of
#eldap_search_result{entries = [E | _]} ->
E#eldap_entry.object_name;
_ ->
false
end.
is_valid_dn(DN, _, #state{dn_filter = undefined}) ->
DN;
is_valid_dn(DN, Attrs, State) ->
DNAttrs = State#state.dn_filter_attrs,
UA = State#state.uidattr,
UAF = State#state.uidattr_format,
Values = [{"%s", get_ldap_attr(Attr, Attrs), 1} || Attr <- DNAttrs],
SubstValues = case get_ldap_attr(UA, Attrs) of
"" -> Values;
S ->
case get_user_part(S, UAF) of
{ok, U} -> [{"%u", U} | Values];
_ -> Values
end
end ++ [{"%d", State#state.host}, {"%D", DN}],
case eldap_filter:parse(State#state.dn_filter, SubstValues) of
{ok, EldapFilter} ->
case eldap:search(State#state.eldap_id, [
{base, State#state.base},
{filter, EldapFilter},
{attributes, ["dn"]}]) of
#eldap_search_result{entries = [_|_]} ->
DN;
_ ->
false
end;
_ ->
false
end.
%%%----------------------------------------------------------------------
%%% Auxiliary functions
%%%----------------------------------------------------------------------
get_user_part(String, Pattern) ->
F = fun(S, P) ->
First = string:str(P, "%u"),
TailLength = length(P) - (First+1),
string:sub_string(S, First, length(S) - TailLength)
end,
case catch F(String, Pattern) of
{'EXIT', _} ->
{error, badmatch};
Result ->
case regexp:sub(Pattern, "%u", Result) of
{ok, String, _} -> {ok, Result};
_ -> {error, badmatch}
end
end.
case_insensitive_match(X, Y) ->
X1 = stringprep:tolower(X),
Y1 = stringprep:tolower(Y),
if
X1 == Y1 -> true;
true -> false
end.
get_ldap_attr(LDAPAttr, Attributes) ->
Res = lists:filter(
fun({Name, _}) ->
case_insensitive_match(Name, LDAPAttr)
end, Attributes),
case Res of
[{_, [Value|_]}] -> Value;
_ -> ""
end.
usort_attrs(Attrs) when is_list(Attrs) ->
lists:usort(Attrs);
usort_attrs(_) ->
[].
parse_options(Host) ->
Eldap_ID = atom_to_list(gen_mod:get_module_proc(Host, ?MODULE)),
Bind_Eldap_ID = atom_to_list(gen_mod:get_module_proc(Host, bind_ejabberd_auth_ldap)),
LDAPServers = ejabberd_config:get_local_option({ldap_servers, Host}),
LDAPPort = case ejabberd_config:get_local_option({ldap_port, Host}) of
undefined -> 389;
P -> P
end,
RootDN = case ejabberd_config:get_local_option({ldap_rootdn, Host}) of
undefined -> "";
RDN -> RDN
end,
Password = case ejabberd_config:get_local_option({ldap_password, Host}) of
undefined -> "";
Pass -> Pass
end,
UIDAttr = case ejabberd_config:get_local_option({ldap_uidattr, Host}) of
undefined -> "uid";
UA -> UA
end,
UIDAttrFormat = case ejabberd_config:get_local_option({ldap_uidattr_format, Host}) of
undefined -> "%u";
UAF -> UAF
end,
SubFilter = "(" ++ UIDAttr ++ "=" ++ UIDAttrFormat ++ ")",
UserFilter = case ejabberd_config:get_local_option({ldap_filter, Host}) of
undefined -> SubFilter;
"" -> SubFilter;
F -> "(&" ++ SubFilter ++ F ++ ")"
end,
SearchFilter = eldap_filter:do_sub(UserFilter, [{"%u", "*"}]),
LDAPBase = ejabberd_config:get_local_option({ldap_base, Host}),
{DNFilter, DNFilterAttrs} =
case ejabberd_config:get_local_option({ldap_dn_filter, Host}) of
undefined -> {undefined, undefined};
{DNF, DNFA} -> {DNF, DNFA}
end,
#state{host = Host,
eldap_id = Eldap_ID,
bind_eldap_id = Bind_Eldap_ID,
servers = LDAPServers,
port = LDAPPort,
dn = RootDN,
password = Password,
base = LDAPBase,
uidattr = UIDAttr,
uidattr_format = UIDAttrFormat,
ufilter = UserFilter,
sfilter = SearchFilter,
dn_filter = DNFilter,
dn_filter_attrs = DNFilterAttrs
}.
get_eldap_id(Host, Name) ->
atom_to_list(gen_mod:get_module_proc(Host, Name)).
+42 -19
View File
@@ -57,8 +57,10 @@ check_password(User, Server, Password) ->
false;
LUser ->
Username = ejabberd_odbc:escape(LUser),
LServer = jlib:nameprep(Server),
case catch odbc_queries:get_password(LServer, Username) of
case catch ejabberd_odbc:sql_query(
jlib:nameprep(Server),
["select password from users "
"where username='", Username, "';"]) of
{selected, ["password"], [{Password}]} ->
true;
_ ->
@@ -72,8 +74,10 @@ check_password(User, Server, Password, StreamID, Digest) ->
false;
LUser ->
Username = ejabberd_odbc:escape(LUser),
LServer = jlib:nameprep(Server),
case catch odbc_queries:get_password(LServer, Username) of
case catch ejabberd_odbc:sql_query(
jlib:nameprep(Server),
["select password from users "
"where username='", Username, "';"]) of
{selected, ["password"], [{Passwd}]} ->
DigRes = if
Digest /= "" ->
@@ -99,7 +103,11 @@ set_password(User, Server, Password) ->
Username = ejabberd_odbc:escape(LUser),
Pass = ejabberd_odbc:escape(Password),
LServer = jlib:nameprep(Server),
catch odbc_queries:set_password_t(LServer, Username, Pass)
catch ejabberd_odbc:sql_transaction(
LServer,
[["delete from users where username='", Username ,"';"],
["insert into users(username, password) "
"values ('", Username, "', '", Pass, "');"]])
end.
@@ -110,8 +118,10 @@ try_register(User, Server, Password) ->
LUser ->
Username = ejabberd_odbc:escape(LUser),
Pass = ejabberd_odbc:escape(Password),
LServer = jlib:nameprep(Server),
case catch odbc_queries:add_user(LServer, Username, Pass) of
case catch ejabberd_odbc:sql_query(
jlib:nameprep(Server),
["insert into users(username, password) "
"values ('", Username, "', '", Pass, "');"]) of
{updated, 1} ->
{atomic, ok};
_ ->
@@ -124,7 +134,9 @@ dirty_get_registered_users() ->
get_vh_registered_users(Server) ->
LServer = jlib:nameprep(Server),
case catch odbc_queries:list_users(LServer) of
case catch ejabberd_odbc:sql_query(
LServer,
"select username from users") of
{selected, ["username"], Res} ->
[{U, LServer} || {U} <- Res];
_ ->
@@ -137,8 +149,10 @@ get_password(User, Server) ->
false;
LUser ->
Username = ejabberd_odbc:escape(LUser),
LServer = jlib:nameprep(Server),
case catch odbc_queries:get_password(LServer, Username) of
case catch ejabberd_odbc:sql_query(
jlib:nameprep(Server),
["select password from users "
"where username='", Username, "';"]) of
{selected, ["password"], [{Password}]} ->
Password;
_ ->
@@ -152,8 +166,10 @@ get_password_s(User, Server) ->
"";
LUser ->
Username = ejabberd_odbc:escape(LUser),
LServer = jlib:nameprep(Server),
case catch odbc_queries:get_password(LServer, Username) of
case catch ejabberd_odbc:sql_query(
jlib:nameprep(Server),
["select password from users "
"where username='", Username, "';"]) of
{selected, ["password"], [{Password}]} ->
Password;
_ ->
@@ -167,8 +183,10 @@ is_user_exists(User, Server) ->
false;
LUser ->
Username = ejabberd_odbc:escape(LUser),
LServer = jlib:nameprep(Server),
case catch odbc_queries:get_password(LServer, Username) of
case catch ejabberd_odbc:sql_query(
jlib:nameprep(Server),
["select password from users "
"where username='", Username, "';"]) of
{selected, ["password"], [{_Password}]} ->
true;
_ ->
@@ -182,8 +200,9 @@ remove_user(User, Server) ->
error;
LUser ->
Username = ejabberd_odbc:escape(LUser),
LServer = jlib:nameprep(Server),
catch odbc_queries:del_user(LServer, Username),
catch ejabberd_odbc:sql_query(
jlib:nameprep(Server),
["delete from users where username='", Username ,"';"]),
ejabberd_hooks:run(remove_user, jlib:nameprep(Server),
[User, Server])
end.
@@ -197,8 +216,12 @@ remove_user(User, Server, Password) ->
Pass = ejabberd_odbc:escape(Password),
LServer = jlib:nameprep(Server),
F = fun() ->
Result = odbc_queries:del_user_return_password(
LServer, Username, Pass),
Result = ejabberd_odbc:sql_query_t(
["select password from users where username='",
Username, "';"]),
ejabberd_odbc:sql_query_t(["delete from users "
"where username='", Username,
"' and password='", Pass, "';"]),
case Result of
{selected, ["password"], [{Password}]} ->
ejabberd_hooks:run(remove_user, jlib:nameprep(Server),
@@ -210,6 +233,6 @@ remove_user(User, Server, Password) ->
not_allowed
end
end,
{atomic, Result} = odbc_queries:transaction(LServer, F),
{atomic, Result } = ejabberd_odbc:transaction(LServer, F),
Result
end.
+1 -16
View File
@@ -1109,7 +1109,6 @@ handle_info({route, From, To, Packet}, StateName, StateData) ->
end,
if
Pass == exit ->
catch send_text(StateData, ?STREAM_TRAILER),
{stop, normal, StateData};
Pass ->
Attrs2 = jlib:replace_from_to_attrs(jlib:jid_to_string(From),
@@ -1365,7 +1364,6 @@ presence_update(From, Packet, StateData) ->
StateData#state.server,
[StateData#state.jid]),
resend_offline_messages(StateData),
resend_subscription_requests(StateData),
presence_broadcast_first(
From, StateData#state{pres_last = Packet,
pres_invis = false
@@ -1729,19 +1727,6 @@ resend_offline_messages(#state{user = User,
end, Rs)
end.
resend_subscription_requests(#state{user = User,
server = Server} = StateData) ->
PendingSubscriptions = ejabberd_hooks:run_fold(
resend_subscription_requests_hook,
Server,
[],
[User, Server]),
lists:foreach(fun(XMLPacket) ->
send_element(StateData,
XMLPacket)
end,
PendingSubscriptions).
get_showtag(undefined) ->
"unavailable";
get_showtag(Presence) ->
@@ -1769,7 +1754,7 @@ process_unauthenticated_stanza(StateData, El) ->
% The only reasonable IQ's here are auth and register IQ's
% They contain secrets, so don't include subelements to response
ResIQ = IQ#iq{type = error,
sub_el = [?ERR_SERVICE_UNAVAILABLE]},
sub_el = [?ERR_FEATURE_NOT_IMPLEMENTED]},
Res1 = jlib:replace_from_to(
jlib:make_jid("", StateData#state.server, ""),
jlib:make_jid("", "", ""),
+2 -27
View File
@@ -8,7 +8,6 @@
-module(ejabberd_ctl).
-author('alexey@sevcom.net').
-vsn('$Revision$ ').
-export([start/0,
init/0,
@@ -19,7 +18,6 @@
unregister_commands/4]).
-include("ejabberd_ctl.hrl").
-include("ejabberd.hrl").
start() ->
case init:get_plain_arguments() of
@@ -124,20 +122,12 @@ process(["load", Path]) ->
end;
process(["restore", Path]) ->
case ejabberd_admin:restore(Path) of
case mnesia:restore(Path, [{default_op, keep_tables}]) of
{atomic, _} ->
?STATUS_SUCCESS;
{error, Reason} ->
io:format("Can't restore backup from ~p at node ~p: ~p~n",
[filename:absname(Path), node(), Reason]),
?STATUS_ERROR;
{aborted,{no_exists,Table}} ->
io:format("Can't restore backup from ~p at node ~p: Table ~p does not exist.~n",
[filename:absname(Path), node(), Table]),
?STATUS_ERROR;
{aborted,enoent} ->
io:format("Can't restore backup from ~p at node ~p: File not found.~n",
[filename:absname(Path), node()]),
?STATUS_ERROR
end;
@@ -175,21 +165,6 @@ process(["delete-expired-messages"]) ->
mod_offline:remove_expired_messages(),
?STATUS_SUCCESS;
process(["delete-old-messages", Days]) ->
case catch list_to_integer(Days) of
{'EXIT',{Reason, _Stack}} ->
io:format("Can't delete old messages (~p). Please pass an integer as parameter.~n",
[Reason]),
?STATUS_ERROR;
Integer when Integer >= 0 ->
{atomic, _} = mod_offline:remove_old_messages(Integer),
io:format("Removed messages older than ~s days~n", [Days]),
?STATUS_SUCCESS;
Integer ->
io:format("Can't delete old messages. Please pass a positive integer as parameter.~n", []),
?STATUS_ERROR
end;
process(["vhost", H | Args]) ->
case jlib:nameprep(H) of
false ->
@@ -232,7 +207,6 @@ print_usage() ->
{"import-file file", "import user data from jabberd 1.4 spool file"},
{"import-dir dir", "import user data from jabberd 1.4 spool directory"},
{"delete-expired-messages", "delete expired offline messages from database"},
{"delete-old-messages n", "delete offline messages older than n days from database"},
{"vhost host ...", "execute host-specific commands"}] ++
ets:tab2list(ejabberd_ctl_cmds),
MaxCmdLen =
@@ -349,3 +323,4 @@ dump_tab(F, T) ->
fun() -> mnesia:match_object(T, W, read) end),
lists:foreach(
fun(Term) -> io:format(F,"~p.~n", [setelement(1, Term, T)]) end, All).
+1 -1
View File
@@ -221,7 +221,7 @@ do_route(OrigFrom, OrigTo, OrigPacket) ->
?DEBUG("route~n\tfrom ~p~n\tto ~p~n\tpacket ~p~n",
[OrigFrom, OrigTo, OrigPacket]),
LOrigDstDomain = OrigTo#jid.lserver,
case ejabberd_hooks:run_fold(filter_packet,
case ejabberd_hooks:run_fold(filter_packet, LOrigDstDomain,
{OrigFrom, OrigTo, OrigPacket}, []) of
{From, To, Packet} ->
LDstDomain = To#jid.lserver,
+1 -19
View File
@@ -19,9 +19,7 @@
get_key/1,
try_register/1,
remove_connection/1,
dirty_get_connections/0,
ctl_process/2
]).
dirty_get_connections/0]).
%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
@@ -29,7 +27,6 @@
-include("ejabberd.hrl").
-include("jlib.hrl").
-include("ejabberd_ctl.hrl").
-record(s2s, {fromto, pid, key}).
-record(state, {}).
@@ -115,10 +112,6 @@ init([]) ->
{attributes, record_info(fields, s2s)}]),
mnesia:add_table_copy(s2s, node(), ram_copies),
mnesia:subscribe(system),
ejabberd_ctl:register_commands(
[{"incoming-s2s-number", "print number of incoming s2s connections on the node"},
{"outgoing-s2s-number", "print number of outgoing s2s connections on the node"}],
?MODULE, ctl_process),
{ok, #state{}}.
%%--------------------------------------------------------------------
@@ -247,17 +240,6 @@ find_connection(From, To) ->
send_element(Pid, El) ->
Pid ! {send_element, El}.
ctl_process(_Val, ["incoming-s2s-number"]) ->
N = length(supervisor:which_children(ejabberd_s2s_in_sup)),
io:format("~p~n", [N]),
{stop, ?STATUS_SUCCESS};
ctl_process(_Val, ["outgoing-s2s-number"]) ->
N = length(supervisor:which_children(ejabberd_s2s_out_sup)),
io:format("~p~n", [N]),
{stop, ?STATUS_SUCCESS};
ctl_process(Val, _Args) ->
Val.
update_tables() ->
case catch mnesia:table_info(s2s, attributes) of
[fromto, node, key] ->
+2 -1
View File
@@ -8,6 +8,7 @@
-module(ejabberd_s2s_in).
-author('alexey@sevcom.net').
-vsn('$Revision$ ').
-behaviour(gen_fsm).
@@ -149,7 +150,7 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) ->
case {xml:get_attr_s("xmlns", Attrs),
xml:get_attr_s("xmlns:db", Attrs),
xml:get_attr_s("version", Attrs) == "1.0"} of
{"jabber:server", _, true} when
{"jabber:server", "jabber:server:dialback", true} when
StateData#state.tls and (not StateData#state.authenticated) ->
send_text(StateData, ?STREAM_HEADER(" version='1.0'")),
SASL =
+8 -10
View File
@@ -8,6 +8,7 @@
-module(ejabberd_s2s_out).
-author('alexey@sevcom.net').
-vsn('$Revision$ ').
-behaviour(gen_fsm).
@@ -45,7 +46,6 @@
tls_enabled = false,
tls_options = [],
authenticated = false,
db_enabled = true,
try_auth = true,
myname, server, queue,
new = false, verify = false,
@@ -224,7 +224,12 @@ wait_for_stream({xmlstreamstart, Name, Attrs}, StateData) ->
StateData#state.use_v10 ->
{next_state, wait_for_features, StateData};
{"jabber:server", "", true} when StateData#state.use_v10 ->
{next_state, wait_for_features, StateData#state{db_enabled = false}};
?INFO_MSG("restarted: ~p", [{StateData#state.myname,
StateData#state.server}]),
% TODO: clear message queue
ejabberd_receiver:close(StateData#state.receiver),
{next_state, reopen_socket, StateData#state{socket = undefined,
use_v10 = false}};
_ ->
send_text(StateData, ?INVALID_NAMESPACE_ERR),
{stop, normal, StateData}
@@ -367,15 +372,8 @@ wait_for_features({xmlstreamelement, El}, StateData) ->
{next_state, reopen_socket,
StateData#state{socket = undefined,
use_v10 = false}};
StateData#state.db_enabled ->
send_db_request(StateData);
true ->
?INFO_MSG("restarted: ~p", [{StateData#state.myname,
StateData#state.server}]),
% TODO: clear message queue
ejabberd_receiver:close(StateData#state.receiver),
{next_state, reopen_socket, StateData#state{socket = undefined,
use_v10 = false}}
send_db_request(StateData)
end;
_ ->
send_text(StateData,
+56 -79
View File
@@ -8,6 +8,7 @@
-module(ejabberd_sm).
-author('alexey@sevcom.net').
-vsn('$Revision$ ').
-behaviour(gen_server).
@@ -41,9 +42,6 @@
-record(session, {sid, usr, us, priority}).
-record(state, {}).
%% default value for the maximum number of user connections
-define(MAX_USER_SESSIONS, infinity).
%%====================================================================
%% API
%%====================================================================
@@ -65,7 +63,6 @@ route(From, To, Packet) ->
open_session(SID, User, Server, Resource) ->
set_session(SID, User, Server, Resource, undefined),
check_for_sessions_to_replace(User, Server, Resource),
JID = jlib:make_jid(User, Server, Resource),
ejabberd_hooks:run(sm_register_connection_hook, JID#jid.lserver,
[SID, JID]).
@@ -180,7 +177,6 @@ init([]) ->
{"connected-users-number", "print a number of established sessions"},
{"user-resources user server", "print user's connected resources"}],
?MODULE, ctl_process),
{ok, #state{}}.
%%--------------------------------------------------------------------
@@ -274,7 +270,23 @@ set_session(SID, User, Server, Resource, Priority) ->
us = US,
priority = Priority})
end,
mnesia:sync_dirty(F).
mnesia:sync_dirty(F),
SIDs = mnesia:dirty_select(
session,
[{#session{sid = '$1', usr = USR, _ = '_'}, [], ['$1']}]),
if
SIDs == [] ->
ok;
true ->
MaxSID = lists:max(SIDs),
lists:foreach(
fun({_, Pid} = S) when S /= MaxSID ->
Pid ! replaced;
(_) ->
ok
end, SIDs)
end.
clean_table_from_bad_node(Node) ->
F = fun() ->
@@ -305,35 +317,32 @@ do_route(From, To, Packet) ->
{Pass, Subsc} =
case xml:get_attr_s("type", Attrs) of
"subscribe" ->
Reason = xml:get_path_s(
Packet,
[{elem, "status"}, cdata]),
{ejabberd_hooks:run_fold(
roster_in_subscription,
LServer,
false,
[User, Server, From, subscribe, Reason]),
[User, Server, From, subscribe]),
true};
"subscribed" ->
{ejabberd_hooks:run_fold(
roster_in_subscription,
LServer,
false,
[User, Server, From, subscribed, ""]),
[User, Server, From, subscribed]),
true};
"unsubscribe" ->
{ejabberd_hooks:run_fold(
roster_in_subscription,
LServer,
false,
[User, Server, From, unsubscribe, ""]),
[User, Server, From, unsubscribe]),
true};
"unsubscribed" ->
{ejabberd_hooks:run_fold(
roster_in_subscription,
LServer,
false,
[User, Server, From, unsubscribed, ""]),
[User, Server, From, unsubscribed]),
true};
_ ->
{true, false}
@@ -342,18 +351,39 @@ do_route(From, To, Packet) ->
LFrom = jlib:jid_tolower(From),
PResources = get_user_present_resources(
LUser, LServer),
lists:foreach(
fun({_, R}) ->
if LFrom /=
{LUser, LServer, R} ->
do_route(
From,
jlib:jid_replace_resource(To, R),
Packet);
true ->
ok
end
end, PResources);
if
PResources /= [] ->
lists:foreach(
fun({_, R}) ->
if LFrom /=
{LUser, LServer, R} ->
do_route(
From,
jlib:jid_replace_resource(To, R),
Packet);
true ->
ok
end
end, PResources);
true ->
if
Subsc ->
case ejabberd_auth:is_user_exists(
LUser, LServer) of
true ->
ejabberd_hooks:run(
offline_subscription_hook,
LServer,
[From, To, Packet]);
_ ->
Err = jlib:make_error_reply(
Packet, ?ERR_SERVICE_UNAVAILABLE),
ejabberd_router:route(To, From, Err)
end;
true ->
ok
end
end;
true ->
ok
end;
@@ -479,59 +509,6 @@ get_user_present_resources(LUser, LServer) ->
S <- clean_session_list(Ss), is_integer(S#session.priority)]
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% On new session, check if some existing connections need to be replace
check_for_sessions_to_replace(User, Server, Resource) ->
LUser = jlib:nodeprep(User),
LServer = jlib:nameprep(Server),
LResource = jlib:resourceprep(Resource),
%% TODO: Depending on how this is executed, there could be an unneeded
%% replacement for max_sessions. We need to check this at some point.
check_existing_resources(LUser, LServer, LResource),
check_max_sessions(LUser, LServer).
check_existing_resources(LUser, LServer, LResource) ->
USR = {LUser, LServer, LResource},
%% A connection exist with the same resource. We replace it:
SIDs = mnesia:dirty_select(
session,
[{#session{sid = '$1', usr = USR, _ = '_'}, [], ['$1']}]),
if
SIDs == [] -> ok;
true ->
MaxSID = lists:max(SIDs),
lists:foreach(
fun({_, Pid} = S) when S /= MaxSID ->
Pid ! replaced;
(_) -> ok
end, SIDs)
end.
check_max_sessions(LUser, LServer) ->
%% If the max number of sessions for a given is reached, we replace the
%% first one
SIDs = mnesia:dirty_select(
session,
[{#session{sid = '$1', usr = {LUser, LServer, '_'}, _ = '_'}, [], ['$1']}]),
MaxSessions = get_max_user_sessions(LServer),
if length(SIDs) =< MaxSessions -> ok;
true -> {_, Pid} = lists:min(SIDs),
Pid ! replaced
end.
%% Get the user_max_session setting
%% This option defines the max number of time a given users are allowed to
%% log in
%% Defaults to infinity
get_max_user_sessions(Host) ->
case ejabberd_config:get_local_option({max_user_sessions, Host}) of
undefined -> ?MAX_USER_SESSIONS;
Max -> Max
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -555,7 +532,7 @@ process_iq(From, To, Packet) ->
From, To, IQ);
[] ->
Err = jlib:make_error_reply(
Packet, ?ERR_SERVICE_UNAVAILABLE),
Packet, ?ERR_FEATURE_NOT_IMPLEMENTED),
ejabberd_router:route(To, From, Err)
end;
reply ->
+1 -8
View File
@@ -6,13 +6,6 @@ CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@ @ZLIB_LIBS@ @ERLANG_LIBS@
ifeq ($(shell uname),Darwin)
DYNAMIC_LIB_CFLAGS = -fPIC -bundle -flat_namespace -undefined suppress
else
# Assume Linux-style dynamic library flags
DYNAMIC_LIB_CFLAGS = -fpic -shared
endif
SUBDIRS =
ERLSHLIBS = ../ejabberd_zlib_drv.so
@@ -33,7 +26,7 @@ $(OUTDIR)/%.beam: %.erl
$(ERLSHLIBS): ../%.so: %.c
$(CC) -Wall $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) \
$(subst ../,,$(subst .so,.c,$@)) $(LIBS) \
-o $@ $(DYNAMIC_LIB_CFLAGS)
-o $@ -fpic -shared
clean:
rm -f $(OBJS) $(ERLSHLIBS)
+2 -4
View File
@@ -74,7 +74,7 @@ export_roster(Server, Output) ->
" and jid='", SJID, "';"
"insert into rosterusers("
" username, jid, nick, "
" subscription, ask, askmessage, "
" subscription, ask, "
" server, subscribe, type) "
" values ", ItemVals, ";"
"delete from rostergroups "
@@ -271,8 +271,7 @@ output(LServer, IO, SQL) ->
record_to_string(#roster{usj = {User, Server, JID},
name = Name,
subscription = Subscription,
ask = Ask,
askmessage = AskMessage}) ->
ask = Ask}) ->
Username = ejabberd_odbc:escape(User),
SJID = ejabberd_odbc:escape(jlib:jid_to_string(JID)),
Nick = ejabberd_odbc:escape(Name),
@@ -296,7 +295,6 @@ record_to_string(#roster{usj = {User, Server, JID},
"'", Nick, "',"
"'", SSubscription, "',"
"'", SAsk, "',"
"'", AskMessage, "',"
"'N', '', 'item')"].
groups_to_string(#roster{usj = {User, Server, JID},
+1 -2
View File
@@ -12,8 +12,7 @@ OUTDIR = ..
EFLAGS = -I .. -pz ..
OBJS = \
$(OUTDIR)/eldap.beam \
$(OUTDIR)/ELDAPv3.beam \
$(OUTDIR)/eldap_filter.beam
$(OUTDIR)/ELDAPv3.beam
all: $(OBJS)
+1 -2
View File
@@ -6,8 +6,7 @@ EFLAGS = -I .. -pz ..
OBJS = \
$(OUTDIR)\eldap.beam \
$(OUTDIR)\ELDAPv3.beam \
$(OUTDIR)\eldap_filter.beam
$(OUTDIR)\ELDAPv3.beam
ALL : $(OBJS)
+1 -1
View File
@@ -808,7 +808,7 @@ polish([], Res, Ref) ->
%%-----------------------------------------------------------------------
connect_bind(S) ->
Host = next_host(S#eldap.host, S#eldap.hosts),
TcpOpts = [{packet, asn1}, {active, true}, {keepalive, true}, binary],
TcpOpts = [{packet, asn1}, {active, true}, binary],
case gen_tcp:connect(Host, S#eldap.port, TcpOpts) of
{ok, Socket} ->
case bind_request(Socket, S) of
-285
View File
@@ -1,285 +0,0 @@
%%%====================================================
%%% File: eldap_filter.erl
%%% Purpose: Converts String Representation of
%%% LDAP Search Filter (RFC 2254)
%%% to eldap's representation of filter
%%% Author: Evgeniy Khramtsov <xramtsov@gmail.com>
%%% License: GPL
%%%====================================================
-module(eldap_filter).
-author('xram@jabber.ru').
%%%======================
%%% Export functions
%%%======================
-export([parse/1,
parse/2,
do_sub/2
]).
%%%-------------------------------------------------------------------------
%%% Arity: parse/1
%%% Function: parse(RFC2254_Filter) -> {ok, EldapFilter} |
%%% {error, bad_filter}
%%%
%%% RFC2254_Filter = string().
%%%
%%% Description: Converts String Representation of LDAP Search Filter (RFC 2254)
%%% to eldap's representation of filter.
%%%
%%% Example:
%%% > eldap_filter:parse("(&(!(uid<=100))(mail=*))").
%%%
%%% {ok,{'and',[{'not',{lessOrEqual,{'AttributeValueAssertion',"uid","100"}}},
%%% {present,"mail"}]}}
%%%-------------------------------------------------------------------------
parse(RFC2254_Filter) ->
parse(RFC2254_Filter, []).
%%%-------------------------------------------------------------------------
%%% Arity: parse/2
%%% Function: parse(RFC2254_Filter, [SubstValue |...]) ->
%%% {ok, EldapFilter} |
%%% {error, bad_filter} |
%%% {error, bad_regexp} |
%%% {error, max_substitute_recursion}
%%%
%%% SubstValue = {RegExp, Value} | {RegExp, Value, N},
%%% RFC2254_Filter = RegExp = Value = string(),
%%% N = integer().
%%%
%%% Description: The same as parse/1, but substitutes N or all occurences
%%% of RegExp with Value *after* parsing.
%%%
%%% Example:
%%% > eldap_filter:parse(
%%% "(|(mail=%u@%d)(jid=%u@%d))",
%%% [{"%u", "xramtsov"},{"%d","gmail.com"}]).
%%%
%%% {ok,{'or',[{equalityMatch,{'AttributeValueAssertion',
%%% "mail",
%%% "xramtsov@gmail.com"}},
%%% {equalityMatch,{'AttributeValueAssertion',
%%% "jid",
%%% "xramtsov@gmail.com"}}]}}
%%%--------------------------------------------------------------------------
parse(RFC2254_Filter, ListOfSubValues) ->
case catch convert_filter(parse_filter(RFC2254_Filter), ListOfSubValues) of
[EldapFilter] when is_tuple(EldapFilter) ->
{ok, EldapFilter};
{regexp, Error} ->
{error, Error};
_ ->
{error, bad_filter}
end.
%%%==========================
%%% Internal functions
%%%==========================
%%%----------------------
%%% split/1,4
%%%----------------------
split(Filter) ->
split(Filter, 0, [], []).
split([], _, _, Result) ->
Result;
split([H|T], Num, Rest, Result) ->
NewNum = case H of
$( -> Num + 1;
$) -> Num - 1;
_ -> Num
end,
if
NewNum == 0 ->
X = Rest++[H],
LenX = length(X),
if
LenX > 2 ->
split(T, 0, [], Result ++ [lists:sublist(X, 2, LenX-2)]);
true ->
split(T, 0, Rest, Result)
end;
true ->
split(T, NewNum, Rest++[H], Result)
end.
%%%-----------------------
%%% parse_filter/1
%%%-----------------------
parse_filter(Filter) ->
case Filter of
[$! | T] ->
{'not', parse_filter(T)};
[$| | T] ->
{'or', parse_filter(T)};
[$& | T] ->
{'and', parse_filter(T)};
[$( | _] ->
parse_filter(split(Filter));
[List | _] when is_list(List) ->
[parse_filter(X) || X <- Filter];
_ ->
Filter
end.
%%%--------------------
%%% convert_filter/2
%%%--------------------
convert_filter({'not', [Val | _]}, Replace) ->
eldap:'not'(convert_filter(Val, Replace));
convert_filter({'or', Vals}, Replace) ->
eldap:'or'([convert_filter(X, Replace) || X <- Vals]);
convert_filter({'and', Vals}, Replace) ->
eldap:'and'([convert_filter(X, Replace) || X <- Vals]);
convert_filter([H|_] = Filter, Replace) when is_integer(H) ->
parse_attr(Filter, Replace);
convert_filter(Filter, Replace) when is_list(Filter) ->
[convert_filter(X, Replace) || X <- Filter].
%%%-----------------
%%% parse_attr/2,3
%%%-----------------
parse_attr(Attr, ListOfSubValues) ->
{Action, [_|_] = Name, [_|_] = Value} = split_attribute(Attr),
parse_attr(Action, {Name, Value}, ListOfSubValues).
parse_attr(approx, {Name, Value}, ListOfSubValues) ->
NewValue = do_sub(Value, ListOfSubValues),
eldap:approxMatch(Name, NewValue);
parse_attr(greater, {Name, Value}, ListOfSubValues) ->
NewValue = do_sub(Value, ListOfSubValues),
eldap:greaterOrEqual(Name, NewValue);
parse_attr(less, {Name, Value}, ListOfSubValues) ->
NewValue = do_sub(Value, ListOfSubValues),
eldap:lessOrEqual(Name, NewValue);
parse_attr(equal, {Name, Value}, ListOfSubValues) ->
{ok, RegSList} = regexp:split(remove_extra_asterisks(Value), "[*]"),
Pattern = case [do_sub(X, ListOfSubValues) || X <- RegSList] of
[Head | Tail] when Tail /= [] ->
{Head, lists:sublist(Tail, length(Tail)-1), lists:last(Tail)};
R ->
R
end,
case Pattern of
[V] ->
eldap:equalityMatch(Name, V);
{[], [], []} ->
eldap:present(Name);
{"", Any, ""} ->
eldap:substrings(Name, [{any, X} || X<-Any]);
{H, Any, ""} ->
eldap:substrings(Name, [{initial, H}]++[{any, X} || X<-Any]);
{"", Any, T} ->
eldap:substrings(Name, [{any, X} || X<-Any]++[{final, T}]);
{H, Any, T} ->
eldap:substrings(Name, [{initial, H}]++[{any, X} || X<-Any]++[{final, T}])
end;
parse_attr(_, _, _) ->
false.
%%%--------------------
%%% do_sub/2,3
%%%--------------------
-define(MAX_RECURSION, 100).
do_sub(S, []) ->
S;
do_sub([], _) ->
[];
do_sub(S, [{RegExp, New} | T]) ->
Result = do_sub(S, {RegExp, replace_amps(New)}, 1),
do_sub(Result, T);
do_sub(S, [{RegExp, New, Times} | T]) ->
Result = do_sub(S, {RegExp, replace_amps(New), Times}, 1),
do_sub(Result, T).
do_sub(S, {RegExp, New}, Iter) ->
case regexp:sub(S, RegExp, New) of
{ok, NewS, 0} ->
NewS;
{ok, NewS, _} when Iter =< ?MAX_RECURSION ->
do_sub(NewS, {RegExp, New}, Iter+1);
{ok, _, _} when Iter > ?MAX_RECURSION ->
throw({regexp, max_substitute_recursion});
_ ->
throw({regexp, bad_regexp})
end;
do_sub(S, {_, _, N}, _) when N<1 ->
S;
do_sub(S, {RegExp, New, Times}, Iter) ->
case regexp:sub(S, RegExp, New) of
{ok, NewS, 0} ->
NewS;
{ok, NewS, _} when Iter < Times ->
do_sub(NewS, {RegExp, New, Times}, Iter+1);
{ok, NewS, _} ->
NewS;
_ ->
throw({regexp, bad_regexp})
end.
remove_extra_asterisks(String) ->
{Res, _} = lists:foldl(
fun(X, {Acc, Last}) ->
case X of
$* when Last==$* ->
{Acc, X};
_ ->
{Acc ++ [X], X}
end
end,
{"", ""}, String),
Res.
replace_amps(String) ->
lists:foldl(
fun(X, Acc) ->
if
X == $& ->
Acc ++ "\\&";
true ->
Acc ++ [X]
end
end,
"", String).
split_attribute(String) ->
split_attribute(String, "", $0).
split_attribute([], _, _) ->
{error, "", ""};
split_attribute([H|Tail], Acc, Last) ->
case H of
$= when Last==$> ->
{greater, lists:sublist(Acc, 1, length(Acc)-1), Tail};
$= when Last==$< ->
{less, lists:sublist(Acc, 1, length(Acc)-1), Tail};
$= when Last==$~ ->
{approx, lists:sublist(Acc, 1, length(Acc)-1), Tail};
$= when Last==$: ->
{equal, lists:sublist(Acc, 1, length(Acc)-1), Tail};
$= ->
{equal, Acc, Tail};
_ ->
split_attribute(Tail, Acc++[H], H)
end.
-3
View File
@@ -181,9 +181,6 @@ string_to_jid1([], "") ->
string_to_jid1([], N) ->
make_jid("", lists:reverse(N), "").
%% Only one "@" is admitted per JID
string_to_jid2([$@ | _J], _N, _S) ->
error;
string_to_jid2([$/ | _J], _N, "") ->
error;
string_to_jid2([$/ | J], N, S) ->
+2 -1
View File
@@ -1126,7 +1126,8 @@ set_form(_Host, ["running nodes", ENode, "backup", "restore"], _Lang, XData) ->
false ->
{error, ?ERR_BAD_REQUEST};
{value, {_, [String]}} ->
case rpc:call(Node, ejabberd_admin, restore, [String]) of
case rpc:call(Node, mnesia, restore,
[String, [{default_op, keep_tables}]]) of
{badrpc, _Reason} ->
{error, ?ERR_INTERNAL_SERVER_ERROR};
{error, _Reason} ->
+1 -8
View File
@@ -6,13 +6,6 @@ CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@ @ERLANG_LIBS@ @LIBICONV@
ifeq ($(shell uname),Darwin)
DYNAMIC_LIB_CFLAGS = -fPIC -bundle -flat_namespace -undefined suppress
else
# Assume Linux-style dynamic library flags
DYNAMIC_LIB_CFLAGS = -fpic -shared
endif
SUBDIRS =
ERLSHLIBS = ../iconv_erl.so
@@ -35,7 +28,7 @@ $(OUTDIR)/%.beam: %.erl
$(ERLSHLIBS): ../%.so: %.c
$(CC) -Wall $(INCLUDES) $(CFLAGS) $(LDFLAGS) \
$(subst ../,,$(subst .so,.c,$@)) $(LIBS) \
-o $@ $(DYNAMIC_LIB_CFLAGS)
-o $@ -fpic -shared
clean:
rm -f $(OBJS) $(ERLSHLIBS)
+1 -1
View File
@@ -291,7 +291,7 @@ iq_disco() ->
[{xmlelement, "identity",
[{"category", "conference"},
{"type", "irc"},
{"name", "IRC Transport"}], []},
{"name", "ejabberd/mod_irc"}], []},
{xmlelement, "feature",
[{"var", ?NS_MUC}], []},
{xmlelement, "feature",
+12 -4
View File
@@ -95,7 +95,10 @@ process_sm_iq(From, To, #iq{type = Type, sub_el = SubEl} = IQ) ->
get_last(IQ, SubEl, LUser, LServer) ->
Username = ejabberd_odbc:escape(LUser),
case catch odbc_queries:get_last(LServer, Username) of
case catch ejabberd_odbc:sql_query(
LServer,
["select seconds, state from last "
"where username='", Username, "';"]) of
{'EXIT', _Reason} ->
IQ#iq{type = error, sub_el = [SubEl, ?ERR_INTERNAL_SERVER_ERROR]};
{selected, ["seconds","state"], []} ->
@@ -128,11 +131,16 @@ store_last_info(User, Server, TimeStamp, Status) ->
Username = ejabberd_odbc:escape(LUser),
Seconds = ejabberd_odbc:escape(integer_to_list(TimeStamp)),
State = ejabberd_odbc:escape(Status),
odbc_queries:set_last_t(LServer, Username, Seconds, State).
%% MREMOND: I think this should be turn into a non transactional behaviour
ejabberd_odbc:sql_transaction(
LServer,
[["delete from last where username='", Username, "';"],
["insert into last(username, seconds, state) "
"values ('", Username, "', '", Seconds, "', '", State, "');"]]).
remove_user(User, Server) ->
LUser = jlib:nodeprep(User),
LServer = jlib:nameprep(Server),
Username = ejabberd_odbc:escape(LUser),
odbc_queries:del_last(LServer, Username).
ejabberd_odbc:sql_query(LServer,
["delete from last where username='", Username, "';"]).
+11 -17
View File
@@ -36,7 +36,7 @@
-record(muc_online_room, {name_host, pid}).
-record(muc_registered, {us_host, nick}).
-record(state, {host, server_host, access, history_size}).
-record(state, {host, server_host, access}).
-define(PROCNAME, ejabberd_mod_muc).
@@ -148,17 +148,14 @@ init([Host, Opts]) ->
Access = gen_mod:get_opt(access, Opts, all),
AccessCreate = gen_mod:get_opt(access_create, Opts, all),
AccessAdmin = gen_mod:get_opt(access_admin, Opts, none),
HistorySize = gen_mod:get_opt(history_size, Opts, 20),
catch ets:new(muc_online_room, [named_table,
public,
{keypos, #muc_online_room.name_host}]),
ejabberd_router:register_route(MyHost),
load_permanent_rooms(MyHost, Host, {Access, AccessCreate, AccessAdmin},
HistorySize),
load_permanent_rooms(MyHost, Host, {Access, AccessCreate, AccessAdmin}),
{ok, #state{host = MyHost,
server_host = Host,
access = {Access, AccessCreate, AccessAdmin},
history_size = HistorySize}}.
access = {Access, AccessCreate, AccessAdmin}}}.
%%--------------------------------------------------------------------
%% Function: %% handle_call(Request, From, State) -> {reply, Reply, State} |
@@ -190,9 +187,8 @@ handle_cast(_Msg, State) ->
handle_info({route, From, To, Packet},
#state{host = Host,
server_host = ServerHost,
access = Access,
history_size = HistorySize} = State) ->
case catch do_route(Host, ServerHost, Access, HistorySize, From, To, Packet) of
access = Access} = State) ->
case catch do_route(Host, ServerHost, Access, From, To, Packet) of
{'EXIT', Reason} ->
?ERROR_MSG("~p", [Reason]);
_ ->
@@ -243,11 +239,11 @@ stop_supervisor(Host) ->
supervisor:terminate_child(ejabberd_sup, Proc),
supervisor:delete_child(ejabberd_sup, Proc).
do_route(Host, ServerHost, Access, HistorySize, From, To, Packet) ->
do_route(Host, ServerHost, Access, From, To, Packet) ->
{AccessRoute, _AccessCreate, _AccessAdmin} = Access,
case acl:match_rule(ServerHost, AccessRoute, From) of
allow ->
do_route1(Host, ServerHost, Access, HistorySize, From, To, Packet);
do_route1(Host, ServerHost, Access, From, To, Packet);
_ ->
{xmlelement, _Name, Attrs, _Els} = Packet,
Lang = xml:get_attr_s("xml:lang", Attrs),
@@ -258,7 +254,7 @@ do_route(Host, ServerHost, Access, HistorySize, From, To, Packet) ->
end.
do_route1(Host, ServerHost, Access, HistorySize, From, To, Packet) ->
do_route1(Host, ServerHost, Access, From, To, Packet) ->
{_AccessRoute, AccessCreate, AccessAdmin} = Access,
{Room, _, Nick} = jlib:jid_tolower(To),
{xmlelement, Name, Attrs, _Els} = Packet,
@@ -383,8 +379,7 @@ do_route1(Host, ServerHost, Access, HistorySize, From, To, Packet) ->
?DEBUG("MUC: open new room '~s'~n", [Room]),
{ok, Pid} = mod_muc_room:start(
Host, ServerHost, Access,
Room, HistorySize, From,
Nick),
Room, From, Nick),
ets:insert(
muc_online_room,
#muc_online_room{name_host = {Room, Host},
@@ -416,7 +411,7 @@ do_route1(Host, ServerHost, Access, HistorySize, From, To, Packet) ->
load_permanent_rooms(Host, ServerHost, Access, HistorySize) ->
load_permanent_rooms(Host, ServerHost, Access) ->
case catch mnesia:dirty_select(
muc_room, [{#muc_room{name_host = {'_', Host}, _ = '_'},
[],
@@ -432,7 +427,6 @@ load_permanent_rooms(Host, ServerHost, Access, HistorySize) ->
ServerHost,
Access,
Room,
HistorySize,
R#muc_room.opts),
ets:insert(
muc_online_room,
@@ -446,7 +440,7 @@ iq_disco_info() ->
[{xmlelement, "identity",
[{"category", "conference"},
{"type", "text"},
{"name", "Chatrooms"}], []},
{"name", "ejabberd/mod_muc"}], []},
{xmlelement, "feature", [{"var", ?NS_MUC}], []},
{xmlelement, "feature", [{"var", ?NS_REGISTER}], []},
{xmlelement, "feature", [{"var", ?NS_VCARD}], []}].
+23 -192
View File
@@ -179,10 +179,10 @@ add_to_log2(text, {Nick, Packet}, Room, Opts, State) ->
{false, false} ->
ok;
{false, SubEl} ->
Message = {body, xml:get_tag_cdata(SubEl)},
Message = {body, htmlize(xml:get_tag_cdata(SubEl))},
add_message_to_log(Nick, Message, Room, Opts, State);
{SubEl, _} ->
Message = {subject, xml:get_tag_cdata(SubEl)},
Message = {subject, htmlize(xml:get_tag_cdata(SubEl))},
add_message_to_log(Nick, Message, Room, Opts, State)
end;
@@ -238,24 +238,16 @@ get_timestamp_daydiff(TimeStamp, Daydiff) ->
{Date2, HMS}.
% Try to close the previous day log, if it exists
close_previous_log(Fn, Images_dir) ->
close_previous_log(Fn) ->
case file:read_file_info(Fn) of
{ok, _} ->
{ok, F} = file:open(Fn, [append]),
%fw(F, "<div class=\"legend\">ejabberd/mod_muc log<span class=\"w3c\">"),
fw(F, "<div class=\"legend\">"),
fw(F, " <a href=\"http://ejabberd.jabber.ru\"><img style=\"border:0\" src=\"~s/powered-by-ejabberd.png\" alt=\"Powered by ejabberd\"/></a>", [Images_dir]),
fw(F, " <a href=\"http://www.erlang.org/\"><img style=\"border:0\" src=\"~s/powered-by-erlang.png\" alt=\"Powered by Erlang\"/></a>", [Images_dir]),
fw(F, "<span class=\"w3c\">"),
fw(F, " <a href=\"http://validator.w3.org/check?uri=referer\"><img style=\"border:0;width:88px;height:31px\" src=\"~s/valid-xhtml10.png\" alt=\"Valid XHTML 1.0 Transitional\" /></a>", [Images_dir]),
fw(F, " <a href=\"http://jigsaw.w3.org/css-validator/\"><img style=\"border:0;width:88px;height:31px\" src=\"~s/vcss.png\" alt=\"Valid CSS!\"/></a>", [Images_dir]),
fw(F, "</span></div></body></html>"),
fw(F, "<div class=\"legend\">ejabberd/mod_muc log<span class=\"w3c\"><a href=\"http://validator.w3.org/check?uri=referer\"><img src=\"http://www.w3.org/Icons/valid-xhtml10\" alt=\"Valid XHTML 1.0 Transitional\" height=\"31\" width=\"88\" /></a> <a href=\"http://jigsaw.w3.org/css-validator/\"><img style=\"border:0;width:88px;height:31px\" src=\"http://jigsaw.w3.org/css-validator/images/vcss\" alt=\"Valid CSS!\" /></a></span></div></body></html>"),
file:close(F);
_ -> ok
end.
add_message_to_log(Nick1, Message, RoomJID, Opts, State) ->
Nick = htmlize(Nick1),
add_message_to_log(Nick, Message, RoomJID, Opts, State) ->
#state{out_dir = OutDir,
dir_type = DirType,
css_file = CSSFile,
@@ -294,14 +286,7 @@ add_message_to_log(Nick1, Message, RoomJID, Opts, State) ->
put_header(F, Room, Datestring, CSSFile, Lang,
HourOffset, DatePrev, DateNext, TopLink),
Images_dir = filename:join([OutDir, "images"]),
file:make_dir(Images_dir),
create_image_files(Images_dir),
Images_url = case DirType of
subdirs -> "../../../images";
plain -> "../images"
end,
close_previous_log(FnYesterday, Images_url)
close_previous_log(FnYesterday)
end,
% Build message
@@ -319,33 +304,33 @@ add_message_to_log(Nick1, Message, RoomJID, Opts, State) ->
[Nick, ?T("leaves the room")]);
{leave, Reason} ->
io_lib:format("<font class=\"ml\">~s ~s: ~s</font><br/>",
[Nick, ?T("leaves the room"), htmlize(Reason)]);
[Nick, ?T("leaves the room"), Reason]);
{kickban, "307", ""} ->
io_lib:format("<font class=\"mk\">~s ~s</font><br/>",
[Nick, ?T("has been kicked")]);
{kickban, "307", Reason} ->
io_lib:format("<font class=\"mk\">~s ~s: ~s</font><br/>",
[Nick, ?T("has been kicked"), htmlize(Reason)]);
[Nick, ?T("has been kicked"), Reason]);
{kickban, "301", ""} ->
io_lib:format("<font class=\"mb\">~s ~s</font><br/>",
[Nick, ?T("has been banned")]);
{kickban, "301", Reason} ->
io_lib:format("<font class=\"mb\">~s ~s: ~s</font><br/>",
[Nick, ?T("has been banned"), htmlize(Reason)]);
[Nick, ?T("has been banned"), Reason]);
{nickchange, OldNick} ->
io_lib:format("<font class=\"mnc\">~s ~s ~s</font><br/>",
[OldNick, ?T("is now known as"), Nick]);
{subject, T} ->
io_lib:format("<font class=\"msc\">~s~s~s</font><br/>",
[Nick, ?T(" has set the subject to: "), htmlize(T)]);
[Nick, ?T(" has set the subject to: "), T]);
{body, T} ->
case regexp:first_match(T, "^/me\s") of
{match, _, _} ->
io_lib:format("<font class=\"mne\">~s ~s</font><br/>",
[Nick, string:substr(htmlize(T), 5)]);
[Nick, string:substr(T, 5)]);
nomatch ->
io_lib:format("<font class=\"mn\">&lt;~s&gt;</font> ~s<br/>",
[Nick, htmlize(T)])
[Nick, T])
end
end,
{Hour, Minute, Second} = Time,
@@ -406,160 +391,6 @@ make_dir_rec(Dir) ->
file:make_dir(Dir)
end.
% {ok, F1}=file:open("valid-xhtml10.png", [read]).
% {ok, F1b}=file:read(F1, 1000000).
% c("../../ejabberd/src/jlib.erl").
% jlib:encode_base64(F1b).
image_base64("powered-by-erlang.png") ->
"iVBORw0KGgoAAAANSUhEUgAAAGUAAAAfCAYAAAD+xQNoAAADN0lEQVRo3u1a"
"P0waURz+rjGRRQ+nUyRCYmJyDPTapDARaSIbTUjt1gVSh8ZW69aBAR0cWLSx"
"CXWp59LR1jbdqKnGxoQuRZZrSYyHEVM6iZMbHewROA7u3fHvkr5vOn737vcu"
"33ffu9/vcQz+gef5Cij6CkmSGABgFEH29r5SVvqIsTEOHo8HkiQxDBXEOjg9"
"PcHc3BxuUSqsI8jR0REAUFGsCCoKFYWCBAN6AxyO0Z7cyMXFb6oGqSgAsIrJ"
"ut9hMQlvdNbUhKWshLd3HtTF4jihShgVpRaBxKKmIGX5HL920/hz/BM2+zAm"
"pn2YioQaxnECj0BiEYcrG0Tzzc8/rfudSm02jaVSm9Vr1MdG8rSKKXlJ7lHr"
"fjouCut2IrC82BDPbe/gc+xlXez7KxEz63H4lmIN473Rh8Si1BKhRY6aEJI8"
"pLmbjSPN0xOnBBILmg5RC6Lg28preKOzsNmHG8R1Bf0o7GdMucUslDy1pJLG"
"2sndVVG0lq3c9vum4zmBR1kuwiYMN5ybmCYXxQg57ThFOTYznzpPO+IQi+IK"
"+jXjg/YhuIJ+cIIHg+wQJoJ+2N3jYN3Olvk4ge/IU98spne+FfGtlslm16nn"
"a8fduntfDscoVjGJqUgIjz686ViFUdjP4N39x9Xq638viZVtlq2tLXKncLf5"
"ticuZSWU5XOUshJKxxKtfdtdvs4OyNb/68urKvlluYizgwwu5SLK8jllu1t9"
"ihYOlzdwdpBBKSvh+vKKzHkCj1JW3y1m+hSj13WjqOiJKK0qpXKhSFxJAYBv"
"KYaZ9TjWRu4SiWi2LyDtb6wghGmn5HfTml16ILGA/G5al2DW7URYTFYrOU7g"
"icQ020sYqYDM9CbdgqFd4vzHL03JfvLjk6ZgADAVCSEsJvHsdL+utNYrm2uf"
"ZDVZSkzPKaQkW8kthpyS297BvRdRzR6DdTurJbPy9Ov1K6xr3HBPQuIMowR3"
"asegUyDuU9SuUG+dmIGyZ0b7FBN9St3WunyC5yMsrVv7uXzRP58s/qKn6C4q"
"lQoVxVIvd4YBwzBUFKs6ZaD27U9hEdcAN98Sx2IxykafIYrizbfESoB+dd9/"
"KF/d/wX3cJvREzl1vAAAAABJRU5ErkJggg==";
image_base64("valid-xhtml10.png") ->
"iVBORw0KGgoAAAANSUhEUgAAAFgAAAAfCAMAAAEjEcpEAAACiFBMVEUAAADe"
"5+fOezmtra3ejEKlhELvvWO9WlrehELOe3vepaWclHvetVLGc3PerVKcCAj3"
"vVqUjHOUe1JjlL0xOUpjjL2UAAC91ueMrc7vrVKlvdbW3u+EpcbO3ufO1ucY"
"WpSMKQi9SiF7e3taWkoQEAiMczkQSoxaUkpzc3O1lEoICACEazEhGAgIAACE"
"YzFra2utjELWcznGnEr/7+9jY2POazHOYzGta2NShLVrlL05OUqctdacCADG"
"a2ucAADGpVqUtc61ORg5OTmlUikYGAiUezl7YzEYEAiUczkxMTG9nEqtIRDe"
"3t4AMXu9lEoQCACMazEAKXspKSmljFrW1ta1jELOzs7n7/fGxsa9pVqEOSkp"
"Y5xznL29tZxahLXOpVr/99ZrY1L/79ZjUiljSikAOYTvxmMAMYScezmchFqU"
"czGtlFp7c2utjFqUlJStxt73///39/9Ce61CSkq9xsZznMbW5+9Cc62MjIxC"
"Qkrv9/fv7/fOzsbnlErWjIz/3mtCORhza1IpIRBzWjH/1mtCMRhzY1L/zmvn"
"vVpSQiHOpVJrUinntVr3zmOEc1L3xmNaWlq1nFo5QkrGWim1lFoISpRSUlK1"
"zt4hWpwASoz///////8xa6WUaykAQoxKe61KSkp7nMbWtWPe5+9jWlL39/f3"
"9/fWrWNCQkLera3nvWPv7+85MRjntWPetVp7c1IxKRCUlHtKORh7a1IxIRCU"
"jHtaSiHWrVIpIQhzWinvvVpaQiH/1mPWpVKMe1L/zmP/xmNrUiGErc4YGBj/"
"73PG1ucQWpT/53O9nFoQUpS1SiEQEBC9zt69vb05c6UISoxSUko5a6UICAhS"
"SkohUpS1tbXetWMAQoSUgD+kAAAA2HRSTlP/////////iP9sSf//dP//////"
"//////////////////////////////////////////8M////////////ef//"
"////////////////////////////////////////////////////////////"
"//////////////////////9d////////////////////////////////////"
"AP//////////////CP//RP//////////////////////////////////////"
"//////////////////////9xPp1gAAAFvUlEQVR42pVWi18URRwfy7vsYUba"
"iqBRBFmICUQGVKcZckQeaRJQUCLeycMSfKGH0uo5NELpIvGQGzokvTTA85VH"
"KTpbRoeJnPno/p1+M7t3txj20e/Nzu7Ofve7v/k9Zg4Vc+wRQMW0eyLx1ZSA"
"NeBDxVmxZZSwEUYkGAewm1eIBOMRvhv1UA+q8KXIVuxGdCelFYwxAnxOrxgb"
"Y8Ti1t4VA0QHYz4x3FnVC8OVLXv9fkKGSWDoW/4lG6VbdtBblesOs+MjmEmz"
"JKNIJWFEfEQTCWNPFKvcKEymjLO1b8bwYQd1hCiiDCl5KsrDCIlhj4fSuvcp"
"fSpgJmyv6dzeZv+nMPx3dhbt94II07/JZliEtm1N2RIYPkTYshwYm245a/zk"
"WjJwcyFh6ZIcYxxmqiaDSYxhOhFUsqngi3Fzcj3ljdYDNE9uzA1YD/5MhnzW"
"1KRqF7mYG8jFYXLcfLpjOe2LA0fuGqQrQHl10sdK0sFcFSOSlzF0BgXQH9h3"
"QZDBI0ccNEhftjXuippBDD2/eMRiETmwwNEYHyqhdDyo22w+3QHuNbdve5a7"
"eOkHmDVJ0ixNmfbz1h0qo/Q6GuSB2wQJQbpOjOQAl7woWSRJ0m2ewhvAOUiY"
"YtZtaZL0CZZmtmVOQttLfr/dbveLZodrfrL7W75wG/JjqkQxoNTtNsTKELQp"
"QL6/D5loaSmyTT8TUhsmi8iFA0hZiyltf7OiNKdarRm5w2So2lTNdPLuIzR+"
"AiLj8VTRJaj0LmX4VhJ27f/VJV/yycilWPOrk8NkXi7Qqmj5bHqVZlJKZIRk"
"1wFzKrt0WUbnXMPJ1fk4TJ5oWBA61p1V76DeIs0MX+s3GxRlA1vtw83KhgNp"
"hc1nyErLO5zcvbOsrq+scbZnpzc6QVFPenLwGxmC+BOfYI+DN55QYddh4Q/N"
"E/yGYYj4TOGNngQavAZnzzTovEA+kcMJ+247uYexNA+4Fsvjmuv662jsWxPZ"
"x2xg890bYMYnTgya7bjmCiEY0qgJ0vMF3c+NoFdPyzxz6V3Uxs3AOWCDchRv"
"OsQtBrbFsrT2fhHEc7ByGzu/dA4IO0A3HdfeP9yMqAwP6NPEb6cbwn0PWVU1"
"7/FDBQh/CPIrbfcg027IZrsAT/Bf3FNWyn9RSR4cvvwn3e4HFmYPDl/thYcR"
"Vi8qPEoXVUWBl6FTBFTtnqmKKg5wnlF4wZ1yeLv7TiwXKektE+iDBNicWEyL"
"pnFhfDkpJc3q2khSPyQBbE0dMJnOoDzTwGsI7cdyMkL5gWqUjCF6Txst/twx"
"Cv1WzzHoy21ZDQ1xnuDzdPDWR4knr14v0tYn3IxaMFFdiMOlEOJHw1jOQ4sW"
"t5rQopRkXZhMEi7pmeDCVWBlfUKwhMZ7rsF6elKsvbwiKxgxIdewa3ErsaYo"
"mCVZFYJb0GUu3JqGUNoplBxYiYby8vLBFWef+Cri4/I1sbQ/1OtYTrNtdXS+"
"rSe7kQ52eSObL99/iErCWUjCy5W4JLygmCouGfG9x9fmx17XhBuDCaOerbt5"
"38erta7TFktLvdHghZcCbcPQO33zIJG9kxF5hoVXnzTzRz0r5js8oTj6uyPk"
"GRf346HOLcasgFexueNUWFPtuFKzjoSFYYedhwVlhsRVYWWJpltv1XPQT1Rl"
"0bjZIBlb1XujVDzY/Kj4k6Ku3+Z0jo1owjVzDpFTXe1juvBSWNFmNWGZy8Lv"
"zUl5PN4JCwyNDzbQ0aAj4Zrjz0FatGJJYhvq4j7mGSpvytGFlZtHf2C4o/28"
"Zu8z7wo7eYPfXysnF0i9NnPh1t1zR7VBb9GqaOXhtTmHQdgMFXE+Z608cnpO"
"DdZdjL+TuDY44Q38kJXHhccWLoOd9uv1AwwvO+48uu+faCSJPJ1bmy6Thyvp"
"ivBmYWgjxPDPAp7JTemY/yGKFEiRt/jG/2P79s8KCwoLCgoLC/khUBA5F0Sf"
"QZ+RYfpNE/4Xosmq7jsZAJsAAAAASUVORK5CYII=";
image_base64("vcss.png") ->
"iVBORw0KGgoAAAANSUhEUgAAAFgAAAAfCAMAAABUFvrSAAABKVBMVEUAAAAj"
"Ix8MR51ZVUqAdlmdnZ3ejEWLDAuNjY1kiMG0n2d9fX19Ghfrp1FtbW3y39+3"
"Ph6lIRNdXV2qJBFcVUhcVUhPT0/dsmpUfLr57+/u7u4/PDWZAACZAADOp1Gd"
"GxG+SyTgvnNdSySzk16+mkuxw+BOS0BOS0DOzs7MzMy4T09RRDwsJBG+vr73"
"wV6fkG6eCQRFcLSurq6/X1+ht9nXfz5sepHuwV59ZTHetFjQ2+wMCQQ2ZK5t"
"WCsmWajsz8+Sq9NMPh4hVaY8MRj///////////////////////9MTEyOp9Lu"
"8vhXU1A8PDyjOSTBz+YLRJ2rLy8sLCwXTaKujEUcHByDn82dfz7/zGafDw+f"
"Dw+zRSlzlMcMDAyNcji1tbXf5vIcFgvATJOjAAAAY3RSTlP/8///////////"
"//////8A//////P/////ov//8//////////////z///T//////////+i////"
"//////////8w/////6IA/xAgMP//////////8/////////8w0/////////+z"
"ehebAAACkUlEQVR42u2VfVPTQBDG19VqC6LY+lKrRIxFQaFSBPuSvhBPF8SI"
"UZK2J5Yav/+HcO8uZdLqTCsU/nKnyWwvk1/unnt2D9ZmH+8/cMAaTRFy+ng6"
"9/yiwC/+gy8R3McGv5zHvGJEGAdR4eBgi1IbZwevIEZE24pFtBtzG1Q4AoD5"
"zvw5pEDcJvIQV/TE3/l+H9GnNJwcdABS5wAbFQLMqI98/UReoAaOTlaJsp0z"
"aHx7LwZvY0BUR2xpWTzqam0gzY8KGzG4MhBCNGucha4QbpETy+Yk/BP85nt7"
"34AjpQLTsE4ZFpf/dnkUCglXVNYB+OfUZJHvAqAoa45OeuPgm4+Xjtv7xm4N"
"7PMV4C61+Mrz3H2WImm3ATiWrAiwZRWcUA5Ej4dgIEMxDv6yxHHcNuAutnjv"
"2HZ1NeuycoVPh0mwC834zZC9Ao5dkZZKwLVGwT+WdLw0YOZ1saEkUDoT+QGW"
"KZ0E2xpcrPakVW2KXwyUtYEtlEAj3GXD/fYwrryAdeiyGqidQSw1eqtJcA8c"
"Zq4zXqhPuCBYE1fKJjh/5X6MwRm9c2xf7WVdLf5oSdt64esVIwVAKC1HJ2ol"
"i8vj3L0YzC4zjkMagt+arDAs6bApbL1RVlWIqrJbreqKZmh4y6VR7rAJeUYD"
"VRj9VqRXkErpJ9lbEwtE83KlIfeG4p52t7zWIMO1XcaGz54uUyet+hBM7BXX"
"DS8Xc5+8Gmmbu1xwSoGIokA3oTptQecQ4Iimm/Ew7jwbPfMi3TM91T9XVIGo"
"+W9xC8oWpugVCXLuwXijjxJ3r/6PjX7nlFua8QmyM+TO/Gja2TTc2Z95C5ua"
"ewGH6cJi6bJO6Z+TY276eH3tbgy+/3ly3Js+rj66osG/AV5htgaQ9SeRAAAA"
"AElFTkSuQmCC";
image_base64("powered-by-ejabberd.png") ->
"iVBORw0KGgoAAAANSUhEUgAAAGUAAAAfCAMAAADJG/NaAAAAw1BMVEUAAAAj"
"BgYtBAM5AwFCAAAYGAJNAABcAABIDQ5qAAAoJRV7AACFAAAoKSdJHByLAAAw"
"Lwk1NQA1MzFJKyo4NxtDQQBEQT5KSCxSTgBSUBlgQ0JYSEpZWQJPUU5hYABb"
"W0ZiYClcW1poaCVwbQRpaDhzYWNsakhuZ2VrbFZ8dwCEgAB3dnd4d2+OjACD"
"hYKcmACJi4iQkpWspgCYmJm5swCmqazEwACwsbS4ub3X0QLExsPLyszW1Nnc"
"3ODm5ugMBwAWAwPHm1IFAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJ"
"cEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfVCRQOBA7VBkCMAAACcElEQVRI"
"x72WjXKiMBSFQalIFbNiy1pdrJZaRVYR5deGwPs/VRNBSBB2OjvQO0oYjPfj"
"5J6bCcdx8i2UldxKcDhk1HbIPwFBF/kHKJfjPSVAyIRHF9rRZ4sUX3EDdWOv"
"1+u2tESaavpnYTbv9zvd0WwDy3/QcGQXlH5uTxB1l07MJlRpsUei0JF6Qi+O"
"HyGK7ijXxPklHe/umIllim3iUBMJDIEULxxPP0TVWhhKJoN9fUpdmQLteV8a"
"DgEAg9gIcTjL4F4L+r4WVKEF+rbJdwYYAoQHY+oQjnGootyKwxapoi73WkyF"
"FySQBv988naEEp4+YMMec5VUCQDJTscEy7Kc0HsLmqNE7rovDjMpIHHGYeid"
"Xn4TQcaxMYqP3RV3C8oCl2WvrlSPaNpGZadRnmPGCk8ylM2okAJ4i9TEe1Ke"
"rsXxSl6jUt5uayiIodirtcKLOaWblj50wiyMv1F9lm9TUDArGAD0FmEpvCUs"
"VoZy6dW81Fg0aDaHogQa36ekAPG5DDGsbdZrGsrzZUnzvBo1I2tLmuL69kSi"
"tAweyHKN9b3leDfQMnu3nIIKWfmXnqGVKedJT6QpICbJvf2f8aOsvn68v+k7"
"/cwUQdPoxaMoRTnKFHNlKsKQphCTOa84u64vpi8bH31CqsbF6lSONRTkTyQG"
"Arq49/fEvjBwz4eDS2/JpaXRNOoXRD/VmOrDVTJJRIZCTLav3VrqbPvP3vdd"
"uGEhQJzilncbpSA4F3vsihErO+dayv/sY5/yRE0GDEXCu2VoNiMlo5i+P2Kl"
"gMEvTNk2eYa5XEyh12Ex17Z8vzQUR3KEPbYd6XG87eC4Ly75RneS5ZYHAAAA"
"AElFTkSuQmCC".
create_image_files(Images_dir) ->
Filenames = [
"powered-by-ejabberd.png",
"powered-by-erlang.png",
"valid-xhtml10.png",
"vcss.png"
],
lists:foreach(
fun(Filename) ->
Filename_full = filename:join([Images_dir, Filename]),
{ok, F} = file:open(Filename_full, [write]),
Image = jlib:decode_base64(image_base64(Filename)),
io:format(F, "~s", [Image]),
file:close(F)
end,
Filenames),
ok.
fw(F, S, O) -> io:format(F, S ++ "~n", O).
fw(F, S) -> fw(F, S, []).
@@ -568,19 +399,19 @@ put_header(F, Room, Date, CSSFile, Lang, Hour_offset, Date_prev, Date_next, Top_
fw(F, "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"~s\" lang=\"~s\">", [Lang, Lang]),
fw(F, "<head>"),
fw(F, "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />"),
fw(F, "<title>~s - ~s</title>", [htmlize(Room#room.title), Date]),
fw(F, "<title>~s - ~s</title>", [Room#room.title, Date]),
put_header_css(F, CSSFile),
put_header_script(F),
fw(F, "</head>"),
fw(F, "<body>"),
{Top_url, Top_text} = Top_link,
fw(F, "<div style=\"text-align: right;\"><a style=\"color: #AAAAAA; font-family: monospace; text-decoration: none; font-weight: bold;\" href=\"~s\">~s</a></div>", [Top_url, Top_text]),
fw(F, "<div class=\"roomtitle\">~s</div>", [htmlize(Room#room.title)]),
fw(F, "<div class=\"roomtitle\"><a class=\"roomtitle\" href=\"xmpp:~s?join\">~s</a></div>", [Room#room.jid, Room#room.title]),
fw(F, "<a class=\"roomjid\" href=\"xmpp:~s?join\">~s</a>", [Room#room.jid, Room#room.jid]),
fw(F, "<div class=\"logdate\">~s<span class=\"w3c\"><a class=\"nav\" href=\"~s\">&lt;</a> <a class=\"nav\" href=\".\/\">^</a> <a class=\"nav\" href=\"~s\">&gt;</a></span></div>", [Date, Date_prev, Date_next]),
case {htmlize(Room#room.subject_author), htmlize(Room#room.subject)} of
case {Room#room.subject_author, Room#room.subject} of
{"", ""} -> ok;
{SuA, Su} -> fw(F, "<div class=\"roomsubject\">~s~s~s</div>", [SuA, ?T(" has set the subject to: "), Su])
{SuA, Su} -> fw(F, "<div class=\"roomsubject\">~s~s~s</div>", [SuA, ?T(" has set the subject to: "), htmlize(Su)])
end,
RoomConfig = roomconfig_to_string(Room#room.config, Lang),
put_room_config(F, RoomConfig, Lang),
@@ -605,7 +436,7 @@ put_header_css(F, false) ->
fw(F, ".mne {color: #AA0099;}"),
fw(F, "a.nav {color: #AAAAAA; font-family: monospace; letter-spacing: 3px; text-decoration: none;}"),
fw(F, "div.roomtitle {border-bottom: #224466 solid 3pt; margin-left: 20pt;}"),
fw(F, "div.roomtitle {color: #336699; font-size: 24px; font-weight: bold; font-family: sans-serif; letter-spacing: 3px; text-decoration: none;}"),
fw(F, "a.roomtitle {color: #336699; font-size: 24px; font-weight: bold; font-family: sans-serif; letter-spacing: 3px; text-decoration: none;}"),
fw(F, "a.roomjid {color: #336699; font-size: 24px; font-weight: bold; font-family: sans-serif; letter-spacing: 3px; margin-left: 20pt; text-decoration: none;}"),
fw(F, "div.logdate {color: #663399; font-size: 20px; font-weight: bold; font-family: sans-serif; letter-spacing: 2px; border-bottom: #224466 solid 1pt; margin-left:80pt; margin-top:20px;}"),
fw(F, "div.roomsubject {color: #336699; font-size: 18px; font-family: sans-serif; margin-left: 80pt; margin-bottom: 10px;}"),
@@ -654,11 +485,11 @@ htmlize(S1) ->
S2_list).
htmlize2(S1) ->
S2 = element(2, regexp:gsub(S1, "\\&", "\\&amp;")),
S3 = element(2, regexp:gsub(S2, "<", "\\&lt;")),
S4 = element(2, regexp:gsub(S3, ">", "\\&gt;")),
S5 = element(2, regexp:gsub(S4, "(http|ftp)://.[^ ]*", "<a href=\"&\">&</a>")),
S5.
S2 = element(2, regexp:gsub(S1, "<", "\\&lt;")),
S3 = element(2, regexp:gsub(S2, ">", "\\&gt;")),
S4 = element(2, regexp:gsub(S3, "(http|ftp)://.[^ ]*", "<a href=\"&\">&</a>")),
%element(2, regexp:gsub(S4, " ", "\\&nbsp;")).
S4.
get_room_info(RoomJID, Opts) ->
Title =
@@ -713,7 +544,7 @@ roomconfig_to_string(Options, Lang) ->
T ->
case Opt of
password -> "<div class=\"rcoe\">" ++ OptText ++ "</div>";
title -> "<div class=\"rcot\">" ++ ?T("Room title") ++ ": \"" ++ htmlize(T) ++ "\"</div>";
title -> "<div class=\"rcot\">" ++ ?T("Room title") ++ ": \"" ++ T ++ "\"</div>";
_ -> "\"" ++ T ++ "\""
end
end,
+38 -72
View File
@@ -14,10 +14,10 @@
%% External exports
-export([start_link/7,
start_link/6,
start/7,
-export([start_link/6,
start_link/5,
start/6,
start/5,
route/4]).
%% gen_fsm callbacks
@@ -85,22 +85,22 @@
%%%----------------------------------------------------------------------
%%% API
%%%----------------------------------------------------------------------
start(Host, ServerHost, Access, Room, HistorySize, Creator, Nick) ->
start(Host, ServerHost, Access, Room, Creator, Nick) ->
Supervisor = gen_mod:get_module_proc(ServerHost, ejabberd_mod_muc_sup),
supervisor:start_child(
Supervisor, [Host, ServerHost, Access, Room, HistorySize, Creator, Nick]).
Supervisor, [Host, ServerHost, Access, Room, Creator, Nick]).
start(Host, ServerHost, Access, Room, HistorySize, Opts) ->
start(Host, ServerHost, Access, Room, Opts) ->
Supervisor = gen_mod:get_module_proc(ServerHost, ejabberd_mod_muc_sup),
supervisor:start_child(
Supervisor, [Host, ServerHost, Access, Room, HistorySize, Opts]).
Supervisor, [Host, ServerHost, Access, Room, Opts]).
start_link(Host, ServerHost, Access, Room, HistorySize, Creator, Nick) ->
gen_fsm:start_link(?MODULE, [Host, ServerHost, Access, Room, HistorySize, Creator, Nick],
start_link(Host, ServerHost, Access, Room, Creator, Nick) ->
gen_fsm:start_link(?MODULE, [Host, ServerHost, Access, Room, Creator, Nick],
?FSMOPTS).
start_link(Host, ServerHost, Access, Room, HistorySize, Opts) ->
gen_fsm:start_link(?MODULE, [Host, ServerHost, Access, Room, HistorySize, Opts],
start_link(Host, ServerHost, Access, Room, Opts) ->
gen_fsm:start_link(?MODULE, [Host, ServerHost, Access, Room, Opts],
?FSMOPTS).
%%%----------------------------------------------------------------------
@@ -114,22 +114,20 @@ start_link(Host, ServerHost, Access, Room, HistorySize, Opts) ->
%% ignore |
%% {stop, StopReason}
%%----------------------------------------------------------------------
init([Host, ServerHost, Access, Room, HistorySize, Creator, _Nick]) ->
init([Host, ServerHost, Access, Room, Creator, _Nick]) ->
State = set_affiliation(Creator, owner,
#state{host = Host,
server_host = ServerHost,
access = Access,
room = Room,
history = lqueue_new(HistorySize),
jid = jlib:make_jid(Room, Host, ""),
just_created = true}),
{ok, normal_state, State};
init([Host, ServerHost, Access, Room, HistorySize, Opts]) ->
init([Host, ServerHost, Access, Room, Opts]) ->
State = set_opts(Opts, #state{host = Host,
server_host = ServerHost,
access = Access,
room = Room,
history = lqueue_new(HistorySize),
jid = jlib:make_jid(Room, Host, "")}),
{ok, normal_state, State}.
@@ -1004,8 +1002,8 @@ add_new_user(From, Nick, {xmlelement, _, Attrs, Els} = Packet, StateData) ->
true ->
ok
end,
send_existing_presences(From, NewState),
send_new_presence(From, NewState),
send_existing_presences(From, NewState),
Shift = count_stanza_shift(Nick, Els, NewState),
case send_history(From, Shift, NewState) of
true ->
@@ -1374,10 +1372,6 @@ lqueue_new(Max) ->
len = 0,
max = Max}.
%% If the message queue limit is set to 0, do not store messages.
lqueue_in(_Item, LQ = #lqueue{max = 0}) ->
LQ;
%% Otherwise, rotate messages in the queue store.
lqueue_in(Item, #lqueue{queue = Q1, len = Len, max = Max}) ->
Q2 = queue:in(Item, Q1),
if
@@ -2074,8 +2068,7 @@ process_iq_owner(From, get, Lang, SubEl, StateData) ->
end.
check_allowed_log_change(XEl, StateData, From) ->
case lists:keymember("muc#roomconfig_enablelogging", 1,
jlib:parse_xdata_submit(XEl)) of
case lists:keymember("logging", 1, jlib:parse_xdata_submit(XEl)) of
false ->
allow;
true ->
@@ -2110,56 +2103,41 @@ get_config(Lang, StateData, From) ->
[{xmlelement, "title", [],
[{xmlcdata, translate:translate(Lang, "Configuration for ") ++
jlib:jid_to_string(StateData#state.jid)}]},
{xmlelement, "field", [{"type", "hidden"},
{"var", "FORM_TYPE"}],
[{xmlelement, "value", [],
[{xmlcdata, "http://jabber.org/protocol/muc#roomconfig"}]}]},
?STRINGXFIELD("Room title",
"muc#roomconfig_roomname",
"title",
Config#config.title),
?BOOLXFIELD("Make room persistent",
"muc#roomconfig_persistentroom",
"persistent",
Config#config.persistent),
?BOOLXFIELD("Make room public searchable",
"muc#roomconfig_publicroom",
"public",
Config#config.public),
?BOOLXFIELD("Make participants list public",
"public_list",
Config#config.public_list),
?BOOLXFIELD("Make room password protected",
"muc#roomconfig_passwordprotectedroom",
"password_protected",
Config#config.password_protected),
?PRIVATEXFIELD("Password",
"muc#roomconfig_roomsecret",
"password",
case Config#config.password_protected of
true -> Config#config.password;
false -> ""
end),
{xmlelement, "field",
[{"type", "list-single"},
{"label", translate:translate(Lang, "Present real JIDs to")},
{"var", "muc#roomconfig_whois"}],
[{xmlelement, "value", [], [{xmlcdata,
if Config#config.anonymous ->
"moderators";
true ->
"anyone"
end}]},
{xmlelement, "option", [{"label", translate:translate(Lang, "moderators only")}],
[{xmlelement, "value", [], [{xmlcdata, "moderators"}]}]},
{xmlelement, "option", [{"label", translate:translate(Lang, "anyone")}],
[{xmlelement, "value", [], [{xmlcdata, "anyone"}]}]}]},
?BOOLXFIELD("Make room semianonymous",
"anonymous",
Config#config.anonymous),
?BOOLXFIELD("Make room members-only",
"muc#roomconfig_membersonly",
"members_only",
Config#config.members_only),
?BOOLXFIELD("Make room moderated",
"muc#roomconfig_moderatedroom",
"moderated",
Config#config.moderated),
?BOOLXFIELD("Default users as participants",
"members_by_default",
Config#config.members_by_default),
?BOOLXFIELD("Allow users to change subject",
"muc#roomconfig_changesubject",
"allow_change_subj",
Config#config.allow_change_subj),
?BOOLXFIELD("Allow users to send private messages",
"allow_private_messages",
@@ -2168,7 +2146,7 @@ get_config(Lang, StateData, From) ->
"allow_query_users",
Config#config.allow_query_users),
?BOOLXFIELD("Allow users to send invites",
"muc#roomconfig_allowinvites",
"allow_user_invites",
Config#config.allow_user_invites)
] ++
case mod_muc_log:check_access_log(
@@ -2176,7 +2154,7 @@ get_config(Lang, StateData, From) ->
allow ->
[?BOOLXFIELD(
"Enable logging",
"muc#roomconfig_enablelogging",
"logging",
Config#config.logging)];
_ -> []
end,
@@ -2223,48 +2201,36 @@ set_config(XEl, StateData) ->
set_xoption([], Config) ->
Config;
set_xoption([{"muc#roomconfig_roomname", [Val]} | Opts], Config) ->
set_xoption([{"title", [Val]} | Opts], Config) ->
?SET_STRING_XOPT(title, Val);
set_xoption([{"muc#roomconfig_changesubject", [Val]} | Opts], Config) ->
set_xoption([{"allow_change_subj", [Val]} | Opts], Config) ->
?SET_BOOL_XOPT(allow_change_subj, Val);
set_xoption([{"allow_query_users", [Val]} | Opts], Config) ->
?SET_BOOL_XOPT(allow_query_users, Val);
set_xoption([{"allow_private_messages", [Val]} | Opts], Config) ->
?SET_BOOL_XOPT(allow_private_messages, Val);
set_xoption([{"muc#roomconfig_publicroom", [Val]} | Opts], Config) ->
set_xoption([{"public", [Val]} | Opts], Config) ->
?SET_BOOL_XOPT(public, Val);
set_xoption([{"public_list", [Val]} | Opts], Config) ->
?SET_BOOL_XOPT(public_list, Val);
set_xoption([{"muc#roomconfig_persistentroom", [Val]} | Opts], Config) ->
set_xoption([{"persistent", [Val]} | Opts], Config) ->
?SET_BOOL_XOPT(persistent, Val);
set_xoption([{"muc#roomconfig_moderatedroom", [Val]} | Opts], Config) ->
set_xoption([{"moderated", [Val]} | Opts], Config) ->
?SET_BOOL_XOPT(moderated, Val);
set_xoption([{"members_by_default", [Val]} | Opts], Config) ->
?SET_BOOL_XOPT(members_by_default, Val);
set_xoption([{"muc#roomconfig_membersonly", [Val]} | Opts], Config) ->
set_xoption([{"members_only", [Val]} | Opts], Config) ->
?SET_BOOL_XOPT(members_only, Val);
set_xoption([{"muc#roomconfig_allowinvites", [Val]} | Opts], Config) ->
set_xoption([{"allow_user_invites", [Val]} | Opts], Config) ->
?SET_BOOL_XOPT(allow_user_invites, Val);
set_xoption([{"muc#roomconfig_passwordprotectedroom", [Val]} | Opts], Config) ->
set_xoption([{"password_protected", [Val]} | Opts], Config) ->
?SET_BOOL_XOPT(password_protected, Val);
set_xoption([{"muc#roomconfig_roomsecret", [Val]} | Opts], Config) ->
set_xoption([{"password", [Val]} | Opts], Config) ->
?SET_STRING_XOPT(password, Val);
set_xoption([{"anonymous", [Val]} | Opts], Config) ->
?SET_BOOL_XOPT(anonymous, Val);
set_xoption([{"muc#roomconfig_whois", [Val]} | Opts], Config) ->
case Val of
"moderators" ->
?SET_BOOL_XOPT(anonymous, "1");
"anyone" ->
?SET_BOOL_XOPT(anonymous, "0");
_ ->
{error, ?ERR_BAD_REQUEST}
end;
set_xoption([{"muc#roomconfig_enablelogging", [Val]} | Opts], Config) ->
set_xoption([{"logging", [Val]} | Opts], Config) ->
?SET_BOOL_XOPT(logging, Val);
set_xoption([{"FORM_TYPE", _} | Opts], Config) ->
%% Ignore our FORM_TYPE
set_xoption(Opts, Config);
set_xoption([_ | _Opts], _Config) ->
{error, ?ERR_BAD_REQUEST}.
+4
View File
@@ -37,6 +37,8 @@ start(Host, _Opts) ->
update_table(),
ejabberd_hooks:add(offline_message_hook, Host,
?MODULE, store_packet, 50),
ejabberd_hooks:add(offline_subscription_hook, Host,
?MODULE, store_packet, 50),
ejabberd_hooks:add(resend_offline_messages_hook, Host,
?MODULE, pop_offline_messages, 50),
ejabberd_hooks:add(remove_user, Host,
@@ -81,6 +83,8 @@ receive_all(Msgs) ->
stop(Host) ->
ejabberd_hooks:delete(offline_message_hook, Host,
?MODULE, store_packet, 50),
ejabberd_hooks:delete(offline_subscription_hook, Host,
?MODULE, store_packet, 50),
ejabberd_hooks:delete(resend_offline_messages_hook, Host,
?MODULE, pop_offline_messages, 50),
ejabberd_hooks:delete(remove_user, Host,
+23 -4
View File
@@ -28,6 +28,8 @@
start(Host, _Opts) ->
ejabberd_hooks:add(offline_message_hook, Host,
?MODULE, store_packet, 50),
ejabberd_hooks:add(offline_subscription_hook, Host,
?MODULE, store_packet, 50),
ejabberd_hooks:add(resend_offline_messages_hook, Host,
?MODULE, pop_offline_messages, 50),
ejabberd_hooks:add(remove_user, Host,
@@ -65,9 +67,14 @@ loop(Host) ->
ejabberd_odbc:escape(
lists:flatten(
xml:element_to_string(Packet))),
odbc_queries:add_spool_sql(Username, XML)
["insert into spool(username, xml) "
"values ('", Username, "', '",
XML,
"');"]
end, Msgs),
case catch odbc_queries:add_spool(Host, Query) of
case catch ejabberd_odbc:sql_transaction(
Host,
Query) of
{'EXIT', Reason} ->
?ERROR_MSG("~p~n", [Reason]);
_ ->
@@ -90,6 +97,8 @@ receive_all(Msgs) ->
stop(Host) ->
ejabberd_hooks:delete(offline_message_hook, Host,
?MODULE, store_packet, 50),
ejabberd_hooks:delete(offline_subscription_hook, Host,
?MODULE, store_packet, 50),
ejabberd_hooks:delete(resend_offline_messages_hook, Host,
?MODULE, pop_offline_messages, 50),
ejabberd_hooks:delete(remove_user, Host,
@@ -202,7 +211,15 @@ pop_offline_messages(Ls, User, Server) ->
LUser = jlib:nodeprep(User),
LServer = jlib:nameprep(Server),
EUser = ejabberd_odbc:escape(LUser),
case odbc_queries:get_and_del_spool_msg_t(LServer, EUser) of
F = fun() ->
Result = ejabberd_odbc:sql_query_t(
["select username, xml from spool where username='", EUser, "'"
" order by seq;"]),
ejabberd_odbc:sql_query_t(
["delete from spool where username='", EUser, "';"]),
Result
end,
case ejabberd_odbc:sql_transaction(LServer,F) of
{atomic, {selected, ["username","xml"], Rs}} ->
Ls ++ lists:flatmap(
fun({_, XML}) ->
@@ -232,5 +249,7 @@ remove_user(User, Server) ->
LUser = jlib:nodeprep(User),
LServer = jlib:nameprep(Server),
Username = ejabberd_odbc:escape(LUser),
odbc_queries:del_spool_msg(LServer, Username).
ejabberd_odbc:sql_query(
LServer,
["delete from spool where username='", Username, "';"]).
+32 -63
View File
@@ -33,7 +33,7 @@
-include("ejabberd.hrl").
-include("jlib.hrl").
-record(state, {host, server_host, access}).
-record(state, {host}).
-define(DICT, dict).
-define(MAXITEMS, 20).
@@ -122,7 +122,6 @@ init([ServerHost, Opts]) ->
update_table(Host),
mnesia:add_table_index(pubsub_node, host_parent),
ServedHosts = gen_mod:get_opt(served_hosts, Opts, []),
Access = gen_mod:get_opt(access_createnode, Opts, all),
ejabberd_router:register_route(Host),
create_new_node(Host, ["pubsub"], ?MYJID),
@@ -134,7 +133,7 @@ init([ServerHost, Opts]) ->
end, ServedHosts),
ets:new(gen_mod:get_module_proc(Host, pubsub_presence),
[set, named_table]),
{ok, #state{host = Host, server_host = ServerHost, access = Access}}.
{ok, #state{host = Host}}.
%%--------------------------------------------------------------------
%% Function: %% handle_call(Request, From, State) -> {reply, Reply, State} |
@@ -163,9 +162,8 @@ handle_cast(_Msg, State) ->
%% {stop, Reason, State}
%% Description: Handling all non call/cast messages
%%--------------------------------------------------------------------
handle_info({route, From, To, Packet},
#state{server_host = ServerHost, access = Access} = State) ->
case catch do_route(To#jid.lserver, ServerHost, Access, From, To, Packet) of
handle_info({route, From, To, Packet}, State) ->
case catch do_route(To#jid.lserver, From, To, Packet) of
{'EXIT', Reason} ->
?ERROR_MSG("~p", [Reason]);
_ ->
@@ -196,7 +194,7 @@ code_change(_OldVsn, State, _Extra) ->
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
do_route(Host, ServerHost, Access, From, To, Packet) ->
do_route(Host, From, To, Packet) ->
{xmlelement, Name, Attrs, Els} = Packet,
case To of
#jid{luser = "", lresource = ""} ->
@@ -234,7 +232,7 @@ do_route(Host, ServerHost, Access, From, To, Packet) ->
#iq{type = Type, xmlns = ?NS_PUBSUB = XMLNS,
sub_el = SubEl} = IQ ->
Res =
case iq_pubsub(Host, ServerHost, From, Type, SubEl, Access) of
case iq_pubsub(Host, From, Type, SubEl) of
{result, IQRes} ->
jlib:iq_to_xml(
IQ#iq{type = result,
@@ -318,7 +316,7 @@ iq_disco_info(SNode) ->
[{xmlelement, "identity",
[{"category", "pubsub"},
{"type", "generic"},
{"name", "Publish-Subscribe"}], []},
{"name", "ejabberd/mod_pubsub"}], []},
{xmlelement, "feature", [{"var", ?NS_PUBSUB}], []},
{xmlelement, "feature", [{"var", ?NS_PUBSUB_EVENT}], []},
{xmlelement, "feature", [{"var", ?NS_PUBSUB_OWNER}], []},
@@ -328,50 +326,32 @@ iq_disco_info(SNode) ->
[]
end.
iq_disco_items(Host, From, SNode) ->
{Node,ItemID} = case SNode of
[] ->
{[],none};
_ ->
Tokens = string:tokens(SNode, "!"),
NodeList = string:tokens(lists:nth(1, Tokens), "/"),
ItemName = case length(Tokens) of
2 -> lists:nth(2, Tokens);
_ -> none
end,
{NodeList, ItemName}
end,
NodeFull = string:tokens(SNode,"/"),
Node = string:tokens(SNode, "/"),
F = fun() ->
case mnesia:read({pubsub_node, {Host, Node}}) of
[#pubsub_node{info = Info}] ->
case ItemID of
none ->
SubNodes = mnesia:index_read(pubsub_node,
SubNodes = mnesia:index_read(pubsub_node,
{Host, Node},
#pubsub_node.host_parent),
SubItems = lists:map(fun(#pubsub_node{host_node = {_, N}}) ->
SubItems =
lists:map(fun(#pubsub_node{host_node = {_, N}}) ->
SN = node_to_string(N),
{xmlelement, "item",
[{"jid", Host},
{"node", SN},
{"name", lists:last(N)}], []}
end, SubNodes),
SN = node_to_string(Node),
Items = lists:map(fun(#item{id = Name}) ->
RealName = case Name of
[] -> "item";
_ -> Name
end,
SN = node_to_string(Node),
Items =
lists:map(fun(#item{id = Name}) ->
{xmlelement, "item",
[{"jid", Host},
{"node", SN ++ "!" ++ Name},
{"name", RealName}], []}
{"name", Name}], []}
end, Info#nodeinfo.items),
SubItems ++ Items;
_ ->
[]
end;
SubItems ++ Items;
[] ->
case Node of
[] ->
@@ -402,6 +382,8 @@ iq_disco_items(Host, From, SNode) ->
{error, ?ERR_INTERNAL_SERVER_ERROR}
end.
iq_get_vcard(Lang) ->
[{xmlelement, "FN", [],
[{xmlcdata, "ejabberd/mod_pubsub"}]},
@@ -415,7 +397,7 @@ iq_get_vcard(Lang) ->
"Copyright (c) 2003-2006 Alexey Shchepin")}]}].
iq_pubsub(Host, ServerHost, From, Type, SubEl, Access) ->
iq_pubsub(Host, From, Type, SubEl) ->
{xmlelement, _, _, SubEls} = SubEl,
case xml:remove_cdata(SubEls) of
[{xmlelement, Name, Attrs, Els}] ->
@@ -423,7 +405,7 @@ iq_pubsub(Host, ServerHost, From, Type, SubEl, Access) ->
Node = string:tokens(SNode, "/"),
case {Type, Name} of
{set, "create"} ->
create_new_node(Host, Node, From, ServerHost, Access);
create_new_node(Host, Node, From);
{set, "publish"} ->
case xml:remove_cdata(Els) of
[{xmlelement, "item", ItemAttrs, Payload}] ->
@@ -502,17 +484,13 @@ iq_pubsub(Host, ServerHost, From, Type, SubEl, Access) ->
%% Create new pubsub nodes
%% This function is used during init to create the first bootstrap nodes
create_new_node(Host, Node, Owner) ->
%% This is the case use during "bootstrapping to create the initial
%% hierarchy. Should always be ... undefined,all
create_new_node(Host, Node, Owner, undefined, all).
create_new_node(Host, Node, Owner, ServerHost, Access) ->
case Node of
[] ->
{LOU, LOS, _} = jlib:jid_tolower(Owner),
HomeNode = ["home", LOS, LOU],
create_new_node(Host, HomeNode, Owner, ServerHost, Access),
create_new_node(Host, HomeNode, Owner),
NewNode = ["home", LOS, LOU, randoms:get_string()],
create_new_node(Host, NewNode, Owner, ServerHost, Access);
create_new_node(Host, NewNode, Owner);
_ ->
LOwner = jlib:jid_tolower(jlib:jid_remove_resource(Owner)),
Parent = lists:sublist(Node, length(Node) - 1),
@@ -547,7 +525,7 @@ create_new_node(Host, Node, Owner, ServerHost, Access) ->
end
end
end,
case check_create_permission(Host, Node, Owner, ServerHost, Access) of
case check_create_permission(Host, Node, Owner) of
true ->
case mnesia:transaction(F) of
{atomic, ok} ->
@@ -1074,23 +1052,14 @@ subscription_to_string(Subscription) ->
end.
check_create_permission(Host, Node, Owner, ServerHost, Access) ->
#jid{luser = User, lserver = Server, lresource = Resource} = Owner,
case acl:match_rule(ServerHost, Access, {User, Server, Resource}) of
allow ->
if Server == Host ->
true;
true ->
case Node of
["home", Server, User | _] ->
true;
_ ->
false
end
end;
_ ->
case Owner of
?MYJID ->
check_create_permission(Host, Node, Owner) ->
if
Owner#jid.lserver == Host ->
true;
true ->
#jid{luser = User, lserver = Server} = Owner,
case Node of
["home", Server, User | _] ->
true;
_ ->
false
+4 -12
View File
@@ -8,6 +8,7 @@
-module(mod_register).
-author('alexey@sevcom.net').
-vsn('$Revision$ ').
-behaviour(gen_mod).
@@ -58,7 +59,7 @@ unauthenticated_iq_register(Acc, _Server, _IQ) ->
Acc.
process_iq(From, To,
#iq{type = Type, lang = Lang, sub_el = SubEl, id = ID} = IQ) ->
#iq{type = Type, lang = Lang, sub_el = SubEl} = IQ) ->
case Type of
set ->
UTag = xml:get_subtag(SubEl, "username"),
@@ -103,18 +104,9 @@ process_iq(From, To,
end;
(UTag == false) and (RTag /= false) ->
case From of
#jid{user = User,
lserver = Server,
resource = Resource} ->
ResIQ = #iq{type = result, xmlns = ?NS_REGISTER,
id = ID,
sub_el = [SubEl]},
ejabberd_router:route(
jlib:make_jid(User, Server, Resource),
jlib:make_jid(User, Server, Resource),
jlib:iq_to_xml(ResIQ)),
#jid{user = User, lserver = Server} ->
ejabberd_auth:remove_user(User, Server),
ignore;
IQ#iq{type = result, sub_el = [SubEl]};
_ ->
IQ#iq{type = error,
sub_el = [SubEl, ?ERR_NOT_ALLOWED]}
+52 -104
View File
@@ -17,8 +17,7 @@
process_local_iq/3,
get_user_roster/2,
get_subscription_lists/3,
get_in_pending_subscriptions/3,
in_subscription/6,
in_subscription/5,
out_subscription/4,
set_items/3,
remove_user/2,
@@ -47,8 +46,6 @@ start(Host, Opts) ->
?MODULE, get_jid_info, 50),
ejabberd_hooks:add(remove_user, Host,
?MODULE, remove_user, 50),
ejabberd_hooks:add(resend_subscription_requests_hook, Host,
?MODULE, get_in_pending_subscriptions, 50),
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_ROSTER,
?MODULE, process_iq, IQDisc).
@@ -65,8 +62,6 @@ stop(Host) ->
?MODULE, get_jid_info, 50),
ejabberd_hooks:delete(remove_user, Host,
?MODULE, remove_user, 50),
ejabberd_hooks:delete(resend_subscription_requests_hook, Host,
?MODULE, get_in_pending_subscriptions, 50),
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_ROSTER).
@@ -135,6 +130,8 @@ get_user_roster(Acc, US) ->
end.
item_to_xml(Item) ->
Attrs1 = [{"jid", jlib:jid_to_string(Item#roster.jid)}],
Attrs2 = case Item#roster.name of
@@ -163,11 +160,12 @@ item_to_xml(Item) ->
_ ->
Attrs3
end,
Attrs = Attrs4 ++ Item#roster.xattrs,
SubEls1 = lists:map(fun(G) ->
{xmlelement, "group", [], [{xmlcdata, G}]}
end, Item#roster.groups),
SubEls = SubEls1 ++ Item#roster.xs,
{xmlelement, "item", Attrs4, SubEls}.
{xmlelement, "item", Attrs, SubEls}.
process_iq_set(From, To, #iq{sub_el = SubEl} = IQ) ->
@@ -195,6 +193,7 @@ process_item_set(From, To, {xmlelement, _Name, Attrs, Els}) ->
I#roster{jid = JID,
name = "",
groups = [],
xattrs = [],
xs = []}
end,
Item1 = process_item_attrs(Item, Attrs),
@@ -205,11 +204,7 @@ process_item_set(From, To, {xmlelement, _Name, Attrs, Els}) ->
_ ->
mnesia:write(Item2)
end,
%% If the item exist in shared roster, take the
%% subscription information from there:
Item3 = ejabberd_hooks:run_fold(roster_process_item,
LServer, Item2, [LServer]),
{Item, Item3}
{Item, Item2}
end,
case mnesia:transaction(F) of
{atomic, {OldItem, Item}} ->
@@ -279,7 +274,9 @@ process_item_attrs(Item, [{Attr, Val} | Attrs]) ->
"ask" ->
process_item_attrs(Item, Attrs);
_ ->
process_item_attrs(Item, Attrs)
XAttrs = Item#roster.xattrs,
process_item_attrs(Item#roster{xattrs = [{Attr, Val} | XAttrs]},
Attrs)
end;
process_item_attrs(Item, []) ->
Item.
@@ -377,13 +374,13 @@ ask_to_pending(Ask) -> Ask.
in_subscription(_, User, Server, JID, Type, Reason) ->
process_subscription(in, User, Server, JID, Type, Reason).
in_subscription(_, User, Server, JID, Type) ->
process_subscription(in, User, Server, JID, Type).
out_subscription(User, Server, JID, Type) ->
process_subscription(out, User, Server, JID, Type, []).
process_subscription(out, User, Server, JID, Type).
process_subscription(Direction, User, Server, JID1, Type, Reason) ->
process_subscription(Direction, User, Server, JID1, Type) ->
LUser = jlib:nodeprep(User),
LServer = jlib:nameprep(Server),
US = {LUser, LServer},
@@ -418,18 +415,12 @@ process_subscription(Direction, User, Server, JID1, Type, Reason) ->
Item#roster.ask,
Type)
end,
AskMessage = case NewState of
{_, both} -> Reason;
{_, in} -> Reason;
_ -> ""
end,
case NewState of
none ->
{none, AutoReply};
{Subscription, Pending} ->
NewItem = Item#roster{subscription = Subscription,
ask = Pending,
askmessage = list_to_binary(AskMessage)},
ask = Pending},
mnesia:write(NewItem),
{{push, NewItem}, AutoReply}
end
@@ -511,7 +502,7 @@ out_state_change(none, none, subscribe) -> {none, out};
out_state_change(none, none, subscribed) -> none;
out_state_change(none, none, unsubscribe) -> none;
out_state_change(none, none, unsubscribed) -> none;
out_state_change(none, out, subscribe) -> {none, out}; %% We need to resend query (RFC3921, section 9.2)
out_state_change(none, out, subscribe) -> none;
out_state_change(none, out, subscribed) -> none;
out_state_change(none, out, unsubscribe) -> {none, none};
out_state_change(none, out, unsubscribed) -> none;
@@ -639,44 +630,13 @@ process_item_attrs_ws(Item, [{Attr, Val} | Attrs]) ->
"ask" ->
process_item_attrs_ws(Item, Attrs);
_ ->
process_item_attrs_ws(Item, Attrs)
XAttrs = Item#roster.xattrs,
process_item_attrs_ws(Item#roster{xattrs = [{Attr, Val} | XAttrs]},
Attrs)
end;
process_item_attrs_ws(Item, []) ->
Item.
get_in_pending_subscriptions(Ls, User, Server) ->
JID = jlib:make_jid(User, Server, ""),
US = {JID#jid.luser, JID#jid.lserver},
case mnesia:dirty_index_read(roster, US, #roster.us) of
Result when list(Result) ->
Ls ++ lists:map(
fun(R) ->
Message = R#roster.askmessage,
Status = if is_binary(Message) ->
binary_to_list(Message);
true ->
""
end,
{xmlelement, "presence",
[{"from", jlib:jid_to_string(R#roster.jid)},
{"to", jlib:jid_to_string(JID)},
{"type", "subscribe"}],
[{xmlelement, "status", [],
[{xmlcdata, Status}]}]}
end,
lists:filter(
fun(R) ->
case R#roster.ask of
in -> true;
both -> true;
_ -> false
end
end,
Result));
_ ->
Ls
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -713,54 +673,42 @@ update_table() ->
Fields ->
ok;
[uj, user, jid, name, subscription, ask, groups, xattrs, xs] ->
convert_table1(Fields);
[usj, us, jid, name, subscription, ask, groups, xattrs, xs] ->
convert_table2(Fields);
?INFO_MSG("Converting roster table from "
"{uj, user, jid, name, subscription, ask, groups, xattrs, xs} format", []),
Host = ?MYNAME,
{atomic, ok} = mnesia:create_table(
mod_roster_tmp_table,
[{disc_only_copies, [node()]},
{type, bag},
{local_content, true},
{record_name, roster},
{attributes, record_info(fields, roster)}]),
mnesia:del_table_index(roster, user),
mnesia:transform_table(roster, ignore, Fields),
F1 = fun() ->
mnesia:write_lock_table(mod_roster_tmp_table),
mnesia:foldl(
fun(#roster{usj = {U, JID}, us = U} = R, _) ->
mnesia:dirty_write(
mod_roster_tmp_table,
R#roster{usj = {U, Host, JID},
us = {U, Host}})
end, ok, roster)
end,
mnesia:transaction(F1),
mnesia:clear_table(roster),
F2 = fun() ->
mnesia:write_lock_table(roster),
mnesia:foldl(
fun(R, _) ->
mnesia:dirty_write(R)
end, ok, mod_roster_tmp_table)
end,
mnesia:transaction(F2),
mnesia:delete_table(mod_roster_tmp_table);
_ ->
?INFO_MSG("Recreating roster table", []),
mnesia:transform_table(roster, ignore, Fields)
end.
%% Convert roster table to support virtual host
convert_table1(Fields) ->
?INFO_MSG("Virtual host support: converting roster table from "
"{uj, user, jid, name, subscription, ask, groups, xattrs, xs} format", []),
Host = ?MYNAME,
{atomic, ok} = mnesia:create_table(
mod_roster_tmp_table,
[{disc_only_copies, [node()]},
{type, bag},
{local_content, true},
{record_name, roster},
{attributes, record_info(fields, roster)}]),
mnesia:del_table_index(roster, user),
mnesia:transform_table(roster, ignore, Fields),
F1 = fun() ->
mnesia:write_lock_table(mod_roster_tmp_table),
mnesia:foldl(
fun(#roster{usj = {U, JID}, us = U} = R, _) ->
mnesia:dirty_write(
mod_roster_tmp_table,
R#roster{usj = {U, Host, JID},
us = {U, Host}})
end, ok, roster)
end,
mnesia:transaction(F1),
mnesia:clear_table(roster),
F2 = fun() ->
mnesia:write_lock_table(roster),
mnesia:foldl(
fun(R, _) ->
mnesia:dirty_write(R)
end, ok, mod_roster_tmp_table)
end,
mnesia:transaction(F2),
mnesia:delete_table(mod_roster_tmp_table).
%% Convert roster table: xattrs fields become
convert_table2(Fields) ->
?INFO_MSG("Converting roster table from "
"{usj, us, jid, name, subscription, ask, groups, xattrs, xs} format", []),
mnesia:transform_table(roster, ignore, Fields).
+1 -1
View File
@@ -13,6 +13,6 @@
subscription = none,
ask = none,
groups = [],
askmessage = [],
xattrs = [],
xs = []}).
+148 -99
View File
@@ -8,6 +8,7 @@
-module(mod_roster_odbc).
-author('alexey@sevcom.net').
-vsn('$Revision$ ').
-behaviour(gen_mod).
@@ -16,8 +17,7 @@
process_local_iq/3,
get_user_roster/2,
get_subscription_lists/3,
get_in_pending_subscriptions/3,
in_subscription/6,
in_subscription/5,
out_subscription/4,
set_items/3,
remove_user/2,
@@ -41,8 +41,6 @@ start(Host, Opts) ->
?MODULE, get_jid_info, 50),
ejabberd_hooks:add(remove_user, Host,
?MODULE, remove_user, 50),
ejabberd_hooks:add(resend_subscription_requests_hook, Host,
?MODULE, get_in_pending_subscriptions, 50),
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_ROSTER,
?MODULE, process_iq, IQDisc).
@@ -59,8 +57,6 @@ stop(Host) ->
?MODULE, get_jid_info, 50),
ejabberd_hooks:delete(remove_user, Host,
?MODULE, remove_user, 50),
ejabberd_hooks:delete(resend_subscription_requests_hook, Host,
?MODULE, get_in_pending_subscriptions, 50),
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_ROSTER).
@@ -122,13 +118,20 @@ process_iq_get(From, To, #iq{sub_el = SubEl} = IQ) ->
get_user_roster(Acc, {LUser, LServer}) ->
Username = ejabberd_odbc:escape(LUser),
case catch odbc_queries:get_roster(LServer, Username) of
case catch ejabberd_odbc:sql_query(
LServer,
["select username, jid, nick, subscription, ask, "
"server, subscribe, type from rosterusers "
"where username='", Username, "'"]) of
{selected, ["username", "jid", "nick", "subscription", "ask",
"askmessage", "server", "subscribe", "type"],
"server", "subscribe", "type"],
Items} when is_list(Items) ->
JIDGroups = case catch odbc_queries:get_roster_jid_groups(LServer, Username) of
{selected, ["jid","grp"], JGrps}
when is_list(JGrps) ->
JIDGroups = case catch ejabberd_odbc:sql_query(
LServer,
["select jid, grp from rostergroups "
"where username='", Username, "'"]) of
{selected, ["jid","grp"],
JGrps} when is_list(JGrps) ->
JGrps;
_ ->
[]
@@ -208,8 +211,13 @@ process_item_set(From, To, {xmlelement, _Name, Attrs, Els}) ->
F = fun() ->
{selected,
["username", "jid", "nick", "subscription",
"ask", "askmessage", "server", "subscribe", "type"],
Res} = odbc_queries:get_roster_by_jid(LServer, Username, SJID),
"ask", "server", "subscribe", "type"],
Res} =
ejabberd_odbc:sql_query_t(
["select username, jid, nick, subscription, "
"ask, server, subscribe, type from rosterusers "
"where username='", Username, "' "
"and jid='", SJID, "'"]),
Item = case Res of
[] ->
#roster{usj = {LUser, LServer, LJID},
@@ -226,19 +234,42 @@ process_item_set(From, To, {xmlelement, _Name, Attrs, Els}) ->
Item2 = process_item_els(Item1, Els),
case Item2#roster.subscription of
remove ->
odbc_queries:del_roster(LServer, Username, SJID);
ejabberd_odbc:sql_query_t(
["delete from rosterusers "
" where username='", Username, "' "
" and jid='", SJID, "';"]),
ejabberd_odbc:sql_query_t(
["delete from rostergroups "
" where username='", Username, "' "
" and jid='", SJID, "';"]);
_ ->
ItemVals = record_to_string(Item2),
ItemGroups = groups_to_string(Item2),
odbc_queries:update_roster(LServer, Username, SJID, ItemVals, ItemGroups)
ejabberd_odbc:sql_query_t(
["delete from rosterusers "
" where username='", Username, "' "
" and jid='", SJID, "';"]),
ejabberd_odbc:sql_query_t(
["insert into rosterusers("
" username, jid, nick, "
" subscription, ask, "
" server, subscribe, type) "
" values ", ItemVals, ";"]),
ejabberd_odbc:sql_query_t(
["delete from rostergroups "
" where username='", Username, "' "
" and jid='", SJID, "';"]),
lists:foreach(fun(ItemGroup) ->
ejabberd_odbc:sql_query_t(
["insert into rostergroups("
" username, jid, grp) "
" values ", ItemGroup, ";"])
end,
ItemGroups)
end,
%% If the item exist in shared roster, take the
%% subscription information from there:
Item3 = ejabberd_hooks:run_fold(roster_process_item,
LServer, Item2, [LServer]),
{Item, Item3}
{Item, Item2}
end,
case odbc_queries:sql_transaction(LServer, F) of
case ejabberd_odbc:sql_transaction(LServer, F) of
{atomic, {OldItem, Item}} ->
push_item(User, LServer, To, Item),
case Item#roster.subscription of
@@ -370,9 +401,13 @@ get_subscription_lists(_, User, Server) ->
LUser = jlib:nodeprep(User),
LServer = jlib:nameprep(Server),
Username = ejabberd_odbc:escape(LUser),
case catch odbc_queries:get_roster(LServer, Username) of
case catch ejabberd_odbc:sql_query(
LServer,
["select username, jid, nick, subscription, ask, "
"server, subscribe, type from rosterusers "
"where username='", Username, "'"]) of
{selected, ["username", "jid", "nick", "subscription", "ask",
"askmessage", "server", "subscribe", "type"],
"server", "subscribe", "type"],
Items} when is_list(Items) ->
fill_subscription_lists(LServer, Items, [], []);
_ ->
@@ -401,13 +436,13 @@ ask_to_pending(Ask) -> Ask.
in_subscription(_, User, Server, JID, Type, Reason) ->
process_subscription(in, User, Server, JID, Type, Reason).
in_subscription(_, User, Server, JID, Type) ->
process_subscription(in, User, Server, JID, Type).
out_subscription(User, Server, JID, Type) ->
process_subscription(out, User, Server, JID, Type, []).
process_subscription(out, User, Server, JID, Type).
process_subscription(Direction, User, Server, JID1, Type, Reason) ->
process_subscription(Direction, User, Server, JID1, Type) ->
LUser = jlib:nodeprep(User),
LServer = jlib:nameprep(Server),
LJID = jlib:jid_tolower(JID1),
@@ -415,14 +450,21 @@ process_subscription(Direction, User, Server, JID1, Type, Reason) ->
SJID = ejabberd_odbc:escape(jlib:jid_to_string(LJID)),
F = fun() ->
Item =
case odbc_queries:get_roster_by_jid(LServer, Username, SJID) of
case ejabberd_odbc:sql_query_t(
["select username, jid, nick, subscription, ask, "
"server, subscribe, type from rosterusers "
"where username='", Username, "' "
"and jid='", SJID, "';"]) of
{selected,
["username", "jid", "nick", "subscription", "ask",
"askmessage", "server", "subscribe", "type"],
"server", "subscribe", "type"],
[I]} ->
R = raw_to_record(LServer, I),
Groups =
case odbc_queries:get_roster_groups(LServer, Username, SJID) of
case ejabberd_odbc:sql_query_t(
["select grp from rostergroups "
"where username='", Username, "' "
"and jid='", SJID, "';"]) of
{selected, ["grp"], JGrps} when is_list(JGrps) ->
[JGrp || {JGrp} <- JGrps];
_ ->
@@ -431,7 +473,7 @@ process_subscription(Direction, User, Server, JID1, Type, Reason) ->
R#roster{groups = Groups};
{selected,
["username", "jid", "nick", "subscription", "ask",
"askmessage", "server", "subscribe", "type"],
"server", "subscribe", "type"],
[]} ->
#roster{usj = {LUser, LServer, LJID},
us = {LUser, LServer},
@@ -455,24 +497,27 @@ process_subscription(Direction, User, Server, JID1, Type, Reason) ->
Item#roster.ask,
Type)
end,
AskMessage = case NewState of
{_, both} -> Reason;
{_, in} -> Reason;
_ -> ""
end,
case NewState of
none ->
{none, AutoReply};
{Subscription, Pending} ->
NewItem = Item#roster{subscription = Subscription,
ask = Pending,
askmessage = AskMessage},
ask = Pending},
ItemVals = record_to_string(NewItem),
odbc_queries:roster_subscribe(LServer, Username, SJID, ItemVals),
ejabberd_odbc:sql_query_t(
["delete from rosterusers "
" where username='", Username, "' "
" and jid='", SJID, "';"]),
ejabberd_odbc:sql_query_t(
["insert into rosterusers("
" username, jid, nick, "
" subscription, ask, "
" server, subscribe, type) "
" values ", ItemVals, ";"]),
{{push, NewItem}, AutoReply}
end
end,
case odbc_queries:sql_transaction(LServer, F) of
case ejabberd_odbc:sql_transaction(LServer, F) of
{atomic, {Push, AutoReply}} ->
case AutoReply of
none ->
@@ -550,7 +595,7 @@ out_state_change(none, none, subscribe) -> {none, out};
out_state_change(none, none, subscribed) -> none;
out_state_change(none, none, unsubscribe) -> none;
out_state_change(none, none, unsubscribed) -> none;
out_state_change(none, out, subscribe) -> {none, out}; %% We need to resend query (RFC3921, section 9.2)
out_state_change(none, out, subscribe) -> none;
out_state_change(none, out, subscribed) -> none;
out_state_change(none, out, unsubscribe) -> {none, none};
out_state_change(none, out, unsubscribed) -> none;
@@ -599,7 +644,16 @@ remove_user(User, Server) ->
LUser = jlib:nodeprep(User),
LServer = jlib:nameprep(Server),
Username = ejabberd_odbc:escape(LUser),
odbc_queries:del_user_roster_t(LServer, Username),
ejabberd_odbc:sql_transaction(
LServer,
fun() ->
ejabberd_odbc:sql_query_t(
["delete from rosterusers "
" where username='", Username, "';"]),
ejabberd_odbc:sql_query_t(
["delete from rostergroups "
" where username='", Username, "';"])
end),
ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -608,7 +662,7 @@ set_items(User, Server, SubEl) ->
{xmlelement, _Name, _Attrs, Els} = SubEl,
LUser = jlib:nodeprep(User),
LServer = jlib:nameprep(Server),
catch odbc_queries:transaction(
catch ejabberd_odbc:transaction(
LServer,
lists:map(fun(El) ->
process_item_set_t(LUser, LServer, El)
@@ -631,11 +685,30 @@ process_item_set_t(LUser, LServer, {xmlelement, _Name, Attrs, Els}) ->
Item2 = process_item_els(Item1, Els),
case Item2#roster.subscription of
remove ->
odbc_queries:del_roster_sql(Username, SJID);
[["delete from rosterusers "
" where username='", Username, "' "
" and jid='", SJID, "';"],
["delete from rostergroups "
" where username='", Username, "' "
" and jid='", SJID, "';"]];
_ ->
ItemVals = record_to_string(Item1),
ItemGroups = groups_to_string(Item2),
odbc_queries:update_roster_sql(Username, SJID, ItemVals, ItemGroups)
[["delete from rosterusers "
" where username='", Username, "' "
" and jid='", SJID, "';"],
["insert into rosterusers("
" username, jid, nick, "
" subscription, ask, "
" server, subscribe, type) "
" values ", ItemVals, ";"],
["delete from rostergroups "
" where username='", Username, "' "
" and jid='", SJID, "';"],
[["insert into rostergroups("
" username, jid, grp) "
" values ", ItemGroup, ";"] ||
ItemGroup <- ItemGroups]]
end
end;
process_item_set_t(_LUser, _LServer, _) ->
@@ -681,39 +754,6 @@ process_item_attrs_ws(Item, [{Attr, Val} | Attrs]) ->
process_item_attrs_ws(Item, []) ->
Item.
get_in_pending_subscriptions(Ls, User, Server) ->
JID = jlib:make_jid(User, Server, ""),
LUser = JID#jid.luser,
LServer = JID#jid.lserver,
Username = ejabberd_odbc:escape(LUser),
case catch odbc_queries:get_roster(LServer, Username) of
{selected, ["username", "jid", "nick", "subscription", "ask",
"askmessage", "server", "subscribe", "type"],
Items} when is_list(Items) ->
Ls ++ lists:map(
fun(R) ->
Message = R#roster.askmessage,
{xmlelement, "presence",
[{"from", jlib:jid_to_string(R#roster.jid)},
{"to", jlib:jid_to_string(JID)},
{"type", "subscribe"}],
[{xmlelement, "status", [],
[{xmlcdata, Message}]}]}
end,
lists:flatmap(
fun(I) ->
R = raw_to_record(LServer, I),
case R#roster.ask of
in -> [R];
both -> [R];
_ -> []
end
end,
Items));
_ ->
Ls
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -723,7 +763,11 @@ get_jid_info(_, User, Server, JID) ->
LJID = jlib:jid_tolower(JID),
Username = ejabberd_odbc:escape(LUser),
SJID = ejabberd_odbc:escape(jlib:jid_to_string(LJID)),
case catch odbc_queries:get_subscription(LServer, Username, SJID) of
case catch ejabberd_odbc:sql_query(
LServer,
["select subscription from rosterusers "
"where username='", Username, "' "
"and jid='", SJID, "'"]) of
{selected, ["subscription"], [{SSubscription}]} ->
Subscription = case SSubscription of
"B" -> both;
@@ -731,7 +775,11 @@ get_jid_info(_, User, Server, JID) ->
"F" -> from;
_ -> none
end,
Groups = case catch odbc_queries:get_roster_group_by_jid(LServer, Username, SJID) of
Groups = case catch ejabberd_odbc:sql_query(
LServer,
["select grp from rostergroups "
"where username='", Username, "' "
"and jid='", SJID, "'"]) of
{selected, ["grp"], JGrps} when is_list(JGrps) ->
[JGrp || {JGrp} <- JGrps];
_ ->
@@ -745,7 +793,11 @@ get_jid_info(_, User, Server, JID) ->
{none, []};
true ->
SRJID = ejabberd_odbc:escape(jlib:jid_to_string(LRJID)),
case catch odbc_queries:get_subscription(LServer, Username, SRJID) of
case catch ejabberd_odbc:sql_query(
LServer,
["select subscription from rosterusers "
"where username='", Username, "' "
"and jid='", SRJID, "'"]) of
{selected, ["subscription"], [{SSubscription}]} ->
Subscription = case SSubscription of
"B" -> both;
@@ -753,7 +805,11 @@ get_jid_info(_, User, Server, JID) ->
"F" -> from;
_ -> none
end,
Groups = case catch odbc_queries:get_rostergroup_by_jid(LServer, Username, SRJID) of
Groups = case catch ejabberd_odbc:sql_query(
LServer,
["select grp from rostergroups "
"where username='", Username, "' "
"and jid='", SRJID, "'"]) of
{selected, ["grp"], JGrps} when is_list(JGrps) ->
[JGrp || {JGrp} <- JGrps];
_ ->
@@ -768,7 +824,7 @@ get_jid_info(_, User, Server, JID) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
raw_to_record(LServer, {User, SJID, Nick, SSubscription, SAsk, SAskMessage,
raw_to_record(LServer, {User, SJID, Nick, SSubscription, SAsk,
_SServer, _SSubscribe, _SType}) ->
case jlib:string_to_jid(SJID) of
error ->
@@ -794,16 +850,14 @@ raw_to_record(LServer, {User, SJID, Nick, SSubscription, SAsk, SAskMessage,
jid = LJID,
name = Nick,
subscription = Subscription,
ask = Ask,
askmessage = SAskMessage}
ask = Ask}
end.
record_to_string(#roster{us = {User, _Server},
jid = JID,
name = Name,
subscription = Subscription,
ask = Ask,
askmessage = AskMessage}) ->
ask = Ask}) ->
Username = ejabberd_odbc:escape(User),
SJID = ejabberd_odbc:escape(jlib:jid_to_string(jlib:jid_tolower(JID))),
Nick = ejabberd_odbc:escape(Name),
@@ -821,26 +875,21 @@ record_to_string(#roster{us = {User, _Server},
in -> "I";
none -> "N"
end,
["'", Username, "',"
["("
"'", Username, "',"
"'", SJID, "',"
"'", Nick, "',"
"'", SSubscription, "',"
"'", SAsk, "',"
"'", AskMessage, "',"
"'N', '', 'item'"].
"'N', '', 'item')"].
groups_to_string(#roster{us = {User, _Server},
jid = JID,
groups = Groups}) ->
Username = ejabberd_odbc:escape(User),
SJID = ejabberd_odbc:escape(jlib:jid_to_string(jlib:jid_tolower(JID))),
%% Empty groups do not need to be converted to string to be inserted in
%% the database
lists:foldl(fun([], Acc) -> Acc;
(Group, Acc) ->
String = ["'", Username, "',"
"'", SJID, "',"
"'", ejabberd_odbc:escape(Group), "'"],
[String|Acc] end, [], Groups).
[["("
"'", Username, "',"
"'", SJID, "',"
"'", ejabberd_odbc:escape(Group), "')"] || Group <- Groups].
+10 -59
View File
@@ -8,6 +8,7 @@
-module(mod_shared_roster).
-author('alexey@sevcom.net').
-vsn('$Revision: 24 $ ').
-behaviour(gen_mod).
@@ -15,8 +16,7 @@
get_user_roster/2,
get_subscription_lists/3,
get_jid_info/4,
process_item/2,
in_subscription/6,
in_subscription/5,
out_subscription/4,
list_groups/1,
create_group/2,
@@ -54,9 +54,7 @@ start(Host, _Opts) ->
ejabberd_hooks:add(roster_get_subscription_lists, Host,
?MODULE, get_subscription_lists, 70),
ejabberd_hooks:add(roster_get_jid_info, Host,
?MODULE, get_jid_info, 70),
ejabberd_hooks:add(roster_process_item, Host,
?MODULE, process_item, 50).
?MODULE, get_jid_info, 70).
%ejabberd_hooks:add(remove_user, Host,
% ?MODULE, remove_user, 50),
@@ -70,9 +68,7 @@ stop(Host) ->
ejabberd_hooks:delete(roster_get_subscription_lists, Host,
?MODULE, get_subscription_lists, 70),
ejabberd_hooks:delete(roster_get_jid_info, Host,
?MODULE, get_jid_info, 70),
ejabberd_hooks:delete(roster_process_item, Host,
?MODULE, process_item, 50).
?MODULE, get_jid_info, 70).
%ejabberd_hooks:delete(remove_user, Host,
% ?MODULE, remove_user, 50),
@@ -80,22 +76,14 @@ stop(Host) ->
get_user_roster(Items, US) ->
{U, S} = US,
DisplayedGroups = get_user_displayed_groups(US),
%% Get shared roster users in all groups and remove self:
SRUsers =
lists:foldl(
fun(Group, Acc1) ->
lists:foldl(
fun(User, Acc2) ->
if User == US -> Acc2;
true -> dict:append(User,
get_group_name(S, Group),
Acc2)
end
dict:append(User, get_group_name(S, Group), Acc2)
end, Acc1, get_group_users(S, Group))
end, dict:new(), DisplayedGroups),
%% If partially subscribed users are also in shared roster, show them as
%% totally subscribed:
{NewItems1, SRUsersRest} =
lists:mapfoldl(
fun(Item, SRUsers1) ->
@@ -109,8 +97,6 @@ get_user_roster(Items, US) ->
{Item, SRUsers1}
end
end, SRUsers, Items),
%% Export items in roster format:
SRItems = [#roster{usj = {U, S, {U1, S1, ""}},
us = US,
jid = {U1, S1, ""},
@@ -121,28 +107,6 @@ get_user_roster(Items, US) ->
{{U1, S1}, GroupNames} <- dict:to_list(SRUsersRest)],
SRItems ++ NewItems1.
%% This function in use to rewrite the roster entries when moving or renaming
%% them in the user contact list.
process_item(RosterItem, Host) ->
USFrom = RosterItem#roster.us,
{User,Server,_Resource} = RosterItem#roster.jid,
USTo = {User,Server},
DisplayedGroups = get_user_displayed_groups(USFrom),
CommonGroups = lists:filter(fun(Group) ->
is_user_in_group(USTo, Group, Host)
end, DisplayedGroups),
case CommonGroups of
[] -> RosterItem;
%% Roster item cannot be removed: We simply reset the original groups:
_ when RosterItem#roster.subscription == remove ->
GroupNames = lists:map(fun(Group) ->
get_group_name(Host, Group)
end, CommonGroups),
RosterItem#roster{subscription = both, ask = none,
groups=[GroupNames]};
_ -> RosterItem#roster{subscription = both, ask = none}
end.
get_subscription_lists({F, T}, User, Server) ->
LUser = jlib:nodeprep(User),
LServer = jlib:nameprep(Server),
@@ -184,7 +148,7 @@ get_jid_info({Subscription, Groups}, User, Server, JID) ->
{Subscription, Groups}
end.
in_subscription(Acc, User, Server, JID, Type, _Reason) ->
in_subscription(Acc, User, Server, JID, Type) ->
process_subscription(in, User, Server, JID, Type, Acc).
out_subscription(User, Server, JID, Type) ->
@@ -234,15 +198,8 @@ create_group(Host, Group, Opts) ->
mnesia:transaction(F).
delete_group(Host, Group) ->
GroupHost = {Group, Host},
F = fun() ->
%% Delete the group ...
mnesia:delete({sr_group, GroupHost}),
%% ... and its users
Users = mnesia:index_read(sr_user, GroupHost, #sr_user.group_host),
lists:foreach(fun(UserEntry) ->
mnesia:delete_object(UserEntry)
end, Users)
mnesia:delete({sr_group, {Group, Host}})
end,
mnesia:transaction(F).
@@ -261,6 +218,8 @@ set_group_opts(Host, Group, Opts) ->
end,
mnesia:transaction(F).
get_user_groups(US) ->
Host = element(2, US),
case catch mnesia:dirty_read(sr_user, US) of
@@ -331,13 +290,6 @@ get_user_displayed_groups(US) ->
end, get_user_groups(US))),
[Group || Group <- DisplayedGroups1, is_group_enabled(Host, Group)].
is_user_in_group(US, Group, Host) ->
case catch mnesia:dirty_match_object(
#sr_user{us=US, group_host={Group, Host}}) of
[] -> false;
_ -> true
end.
add_user_to_group(Host, US, Group) ->
R = #sr_user{us = US, group_host = {Group, Host}},
F = fun() ->
@@ -346,8 +298,7 @@ add_user_to_group(Host, US, Group) ->
mnesia:transaction(F).
remove_user_from_group(Host, US, Group) ->
GroupHost = {Group, Host},
R = #sr_user{us = US, group_host = GroupHost},
R = #sr_user{us = US, group_host = {Group, Host}},
F = fun() ->
mnesia:delete_object(R)
end,
+342 -554
View File
File diff suppressed because it is too large Load Diff
-397
View File
@@ -1,397 +0,0 @@
% $Id$
% Czech translation
% Authors: Milos Svasek [DuxforD] from openheads.net
% jlib.hrl
{"No resource provided", "Nebyl poskytnutý žádny zdroj"}.
% mod_configure.erl
{"Choose storage type of tables", "Vyberte typ úložiště pro tabulky"}.
{"RAM copy", "Kopie RAM"}.
{"RAM and disc copy", "Kopie RAM a disku"}.
{"Disc only copy", "Jen kopie disku"}.
{"Remote copy", "Vzdálená kopie"}.
{"Stop Modules at ", "Zastavit moduly na "}.
{"Choose modules to stop", "Vyberte moduly, které mají být zastavené"}.
{"Start Modules at ", "Spustit moduly na "}.
{"Enter list of {Module, [Options]}", "Vložte seznam modulů {Modul, [Parametre]}"}.
{"List of modules to start", "Seznam modulů, které mají být spuštěné"}.
{"Backup to File at ", "Záloha do souboru na "}.
{"Enter path to backup file", "Zadajte cestu k souboru se zálohou"}.
{"Path to File", "Cesta k souboru"}.
{"Restore Backup from File at ", "Obnovit zálohu ze souboru na "}.
{"Dump Backup to Text File at ", "Uložit zálohu do textového souboru na "}.
{"Enter path to text file", "Zadajte cestu k textovému souboru"}.
{"Import User from File at ", "Importovat uživatele ze souboru na "}.
{"Enter path to jabberd1.4 spool file", "Zadejte cestu k spool souboru jabberd1.4"}.
{"Import Users from Dir at ", "Importovat uživatele z adresáře na "}.
{"Enter path to jabberd1.4 spool dir", "Zadejte cestu k jabberd1.4 spool adresáři"}.
{"Path to Dir", "Cesta k adresáři"}.
{"Hostname Configuration", "Konfigurace jména serveru"}.
{"Choose host name", "Vyberte jméno serveru"}.
{"Host name", "Jméno serveru"}.
{"Access Control List Configuration", "Konfigurace seznamu přístupových práv (ACL)"}.
{"Access control lists", "Seznamy přístupových práv (ACL)"}.
{"Access Configuration", "Konfigurace přístupů"}.
{"Access rules", "Pravidla přístupů"}.
{"Remove Users", "Odstranit uživatele"}.
{"Choose users to remove", "Vybrat uživatele, kteří budou odstraněni"}.
{"Administration of ", "Administrace "}.
{"Action on user", "Akce aplikovaná na uživatele"}.
{"Edit Properties", "Upravit vlastnosti"}.
{"Remove User", "Odstranit uživatele"}.
% mod_disco.erl
{"Configuration", "Konfigurace"}.
{"Online Users", "Online uživatelé"}.
{"All Users", "Všichni uživatelé"}.
{"To ~s", "Pre ~s"}.
{"From ~s", "Od ~s"}.
{"Running Nodes", "Bežící uzly"}.
{"Stopped Nodes", "Zastavené uzly"}.
{"Host Name", "Jméno serveru"}.
{"Access Control Lists", "Seznamy přístupových práv (ACL)"}.
{"Access Rules", "Pravidla přístupů"}.
{"Remove Users", "Odstranit uživatele"}.
{"Modules", "Moduly"}.
{"Start Modules", "Spustit moduly"}.
{"Stop Modules", "Zastavit moduly"}.
{"Backup Management", "Správa zálohování"}.
{"Backup", "Zálohovat"}.
{"Restore", "Obnovit"}.
{"Dump to Text File", "Uložit do textového souboru"}.
{"Import File", "Import souboru"}.
{"Import Directory", "Import adresáře"}.
% mod_register.erl
{"Choose a username and password to register with this server",
"Zadejte jméno uživatele a heslo pro registraci na tomto serveru"}.
% mod_vcard.erl
{"You need an x:data capable client to search",
"K vyhledávání potřebujete klienta podporujícího x:data"}.
{"Search users in ", "Hledat uživatele v "}.
{"Fill in fields to search for any matching Jabber User",
"Vyplňte políčka pro vyhledávání Jabber uživatele"}.
{"User", "Uživatel: "}.
{"Full Name", "Celé jméno: "}.
{"Name", "Jméno: "}.
{"Middle Name", "Prostřední jméno: "}.
{"Family Name", "Příjmení: "}.
{"Nickname", "Přezdívka: "}.
{"Birthday", "Datum narození: "}.
{"Country", "Země: "}.
{"City", "Město: "}.
{"Organization Name", "Název firmy: "}.
{"Organization Unit", "Oddělení: "}.
% mod_muc/mod_muc.erl
{"You need an x:data capable client to register nickname",
"K registraci přezdívky potřebujete klienta podporujícího z x:data"}.
{"Nickname Registration at ", "Registrace prezdívky na "}.
{"Enter nickname you want to register", "Zadajte prezdívku, kterou chete zaregistrovat"}.
{"Only service administrators are allowed to send service messages",
"Pouze správci služby mají povolené odesílání servisních zpráv"}.
{"Conference room does not exist", "Konferenční místnost neexistuje"}.
{"Access denied by service policy", "Přístup byl zamítnutý nastavením služby"}.
{"Specified nickname is already registered", "Zadaná prezdívka je již registrována"}.
% mod_muc/mod_muc_room.erl
{" has set the subject to: ", "změnil(a) téma na: "}.
{"You need an x:data capable client to configure room",
"Ke konfiguraci místnosti potřebujete klienta podporujícího z x:data"}.
{"Configuration for ", "Konfigurace pre "}.
{"Room title", "Název místnosti"}.
{"Password", "Heslo"}.
{"Only moderators and participants are allowed to change subject in this room",
"Jen moderátoři a účastníci mají povoleno měnit téma této místnosti"}.
{"Only moderators are allowed to change subject in this room",
"Jen moderátoři mají povoleno měnit téma místnosti"}.
{"Visitors are not allowed to send messages to all occupants",
"Návštevníci nemají povoleno zsílat zprávy všem přihlášeným do konference"}.
{"Only occupants are allowed to send messages to the conference",
"Jen členové mají povolené zasílat správy do konference"}.
{"It is not allowed to send normal messages to the conference",
"Není povoleno odesílat normální zprávy do konference"}.
{"It is not allowed to send private messages to the conference",
"Není povoleno odesílat soukromé zprávy do konference"}.
{"Improper message type", "Nesprávný typ zprávy"}.
{"Nickname is already in use by another occupant", "Prezdívka je již používána jiným členem"}.
{"Nickname is registered by another person", "Prezdívka je registrována jinou osobou"}.
{"It is not allowed to send private messages of type \"groupchat\"",
"Není dovoleno odeslání soukromé zprávy typu \"Skupinová zpráva\" "}.
{"Recipient is not in the conference room", "Příjemce se nenachází v konferenční místnosti"}.
{"Only occupants are allowed to send queries to the conference",
"Jen členové mohou odesílat požadavky (query) do konference"}.
{"Queries to the conference members are not allowed in this room",
"Požadavky (queries) na členy konference nejsou v této místnosti povolené"}.
{"You have been banned from this room", "Byl jste vyloučen z této místnosti"}.
{"Membership required to enter this room", "Pro vstup do místnosti musíte být členem"}.
{"Password required to enter this room", "Pro vstup do místnosti musíte zadat heslo"}.
{"Incorrect password", "Nesprávne heslo"}.
{"Administrator privileges required", "Jsou potřebná práva administrátora"}.
{"Moderator privileges required", "Jsou potřebná práva moderátora"}.
{"JID ~s is invalid", "JID ~s je neplatné"}.
{"Nickname ~s does not exist in the room", "Prezdívka ~s v místnosti neexistuje"}.
{"Invalid affiliation: ~s", "Neplatné přiřazení: ~s"}.
{"Invalid role: ~s", "Neplatná role: ~s"}.
{"Owner privileges required", "Jsou vyžadována práva vlastníka"}.
{"private, ", "soukromá, "}.
{"Present real JIDs to", "Zjisti skutečné JIDy pro"}.
{"moderators only", "pouze pro moderátory"}.
{"anyone", "každý"}.
% mod_irc/mod_irc.erl
{"You need an x:data capable client to configure mod_irc settings",
"Pro konfiguraci mod_irc potřebujete klienta podporujícího x:data"}.
{"Registration in mod_irc for ", "Registrace do mod_irc na "}.
{"Enter username and encodings you wish to use for connecting to IRC servers",
"Vložte jméno uživatele a kódování, které chcete používat při připojení na IRC server"}.
{"IRC Username", "IRC prezdívka"}.
{"Example: [{\"irc.lucky.net\", \"koi8-r\"}, {\"vendetta.fef.net\", \"iso8859-1\"}].",
"Příklad: [{\"irc.freenode.net\",\"utf-8\"}, {\irc.freenode.net\", \"iso8859-2\"}]."}.
{"Encodings", "Kódování"}.
% web/ejabberd_web_admin.erl
{"Users", "Uživatelé"}.
{"Nodes", "Uzly"}.
{"Statistics", "Statistiky"}.
{"Submitted", "Odeslané"}.
{"CPU Time:", "Čas procesoru"}.
{"Delete Selected", "Smazat vybrané"}.
{"Submit", "Odeslat"}.
{"~s access rule configuration", "~s konfigurace pravidla přístupu"}.
{"Node not found", "Uzel nenalezen"}.
{"Add New", "Přidat nový"}.
{"Change Password", "Změnit heslo"}.
{"Connected Resources:", "Připojené zdroje:"}.
{"Password:", "Heslo:"}.
{"None", "Nic"}.
{"Node ", "Uzel "}.
{"Restart", "Restart"}.
{"Stop", "Stop"}.
{"Name", "Jméno"}.
{"Storage Type", "Typ úložiště"}.
{"Size", "Velikost"}.
{"Memory", "Paměť"}.
{"OK", "OK"}.
{"Listened Ports at ", "Otevřené porty na "}.
{"Port", "Port"}.
{"Module", "Modul"}.
{"Options", "Nastavení"}.
{"Update", "Aktualizovat"}.
{"Delete", "Smazat"}.
{"Add User", "Přidat uživatele"}.
{"Last Activity", "Poslední aktivita"}.
{"Never", "Nikdy"}.
{"Time", "Čas"}.
{"From", "Od"}.
{"To", "Pro"}.
{"Packet", "Paket"}.
{"Roster", "Seznam kontaktů"}.
{"Nickname", "Prezdívka"}.
{"Subscription", "Přihlášení"}.
{"Pending", "Čekající"}.
{"Groups", "Skupiny"}.
{"Remove", "Odstranit"}.
{"User ", "Uživatel "}.
{"Roster of ", "Seznam kontaktů "}.
{"Shared Roster", "Sdílený seznam kontaktů"}.
{"Online", "Online"}.
{"Validate", "Ověřit"}.
{"Name:", "Jméno:"}.
{"Description:", "Popis:"}.
{"Members:", "Členové:"}.
{"Displayed Groups:", "Zobrazené skupiny:"}.
{"Group ", "Skupina "}.
{"Period: ", "Čas:"}.
{"Last month", "Poslední měsíc"}.
{"Last year", "Poslední rok"}.
{"All activity", "Všechny aktivity"}.
{"Show Ordinary Table", "Zobrazit bežnou tabulku"}.
{"Show Integral Table", "Zobrazit kompletní tabulku"}.
{"Start", "Start"}.
{"Modules at ", "Moduly na "}.
{"Virtual Hosts", "Virtuální servery"}.
{"ejabberd virtual hosts", "Ejabberd virtuální servery"}.
{"Host", "Server"}.
{"ejabberd Web Interface", "Ejabberd Web rozhraní"}.
% mod_vcard_odbc.erl
{"Fill in the form to search for any matching Jabber User (Add * to the end of field to match substring)",
"Pro vyhledání Jabber uživatele vyplňte formulář (přidejte znak * na konec, pro vyhledání podřetězce)"}.
% ejabberd_c2s.erl
{"Use of STARTTLS required", "Je vyžadováno STARTTLS."}.
{"Replaced by new connection", "Nahrazeno novým spojením"}.
% mod_pubsub/mod_pubsub.erl
{[], " "}.
{"Node Creator", "Majitel uzlu"}.
{"Deliver payloads with event notifications", "Doručovat náklad s upozorněním na událost"}.
{"Notify subscribers when the node configuration changes", "Upozornit členy na změnu nastavení uzlu"}.
{"Notify subscribers when the node is deleted", "Upozornit členy na smazaní uzlu"}.
{"Notify subscribers when items are removed from the node", "Upozornit členy na odstranění položek z uzlu"}.
{"Persist items to storage", "Uložit položky natrvalo do úložiště"}.
{"Max # of items to persist", "Maximální počet položek, které je možné natrvalo uložit"}.
{"Whether to allow subscriptions", "Povolit přihlašování"}.
{"Specify the subscriber model", "Specifikovat přihlašovací model"}.
{"Specify the publisher model", "Specifikovat model pro publikování"}.
{"Max payload size in bytes", "Maximální náklad v bajtech"}.
{"Send items to new subscribers", "Odeslat položky novým uživatelům"}.
{"Only deliver notifications to available users", "Doručovat upozornení jen aktuálně přihlášeným uživatelům"}.
{"Specify the current subscription approver", "Zadat současného schvalovatele přihlášení "}.
% mod_irc/mod_irc.erl
{"If you want to specify different encodings for IRC servers, fill this list with values in format '{\"irc server\", \"encoding\"}'. By default this service use \"~s\" encoding.",
"Pokud chcete zadat jiné kódování pro IRC servery, vyplňte seznam s hodnotami ve formátě '{\"irc server\",\"encoding\"}'. Předvolené kódování pro tuto službu je \"~s\"."}.
% mod_muc/mod_muc.erl
{"Room creation is denied by service policy", "Vytváranie miestnosti nie je povolené"}.
% /usr/home/src/ejabberd/ejabberd/src/mod_vcard_odbc.erl
{"Erlang Jabber Server\nCopyright (c) 2002-2006 Alexey Shchepin",
"Erlang Jabber Server\nCopyright (c) 2002-2006 Alexey Shchepin"}.
{"Email", "E-mail"}.
{"ejabberd vCard module\nCopyright (c) 2003-2006 Alexey Shchepin",
"Ejabberd vCard modul\nCopyright (c) 2003-2006 Alexey Shchepin"}.
{"Search Results for ", "Hledat výsledky pro "}.
{"Jabber ID", "Jabber ID"}.
% /usr/home/src/ejabberd/ejabberd/src/mod_adhoc.erl
{"Commands", "Příkazy"}.
{"Ping", "Ping"}.
{"Pong", "Pong"}.
% /usr/home/src/ejabberd/ejabberd/src/ejabberd_c2s.erl
{"Replaced by new connection", "Nahrazeno novým spojením"}.
% /usr/home/src/ejabberd/ejabberd/src/mod_announce.erl
{"Really delete message of the day?", "Skutečně smazat správu dne?"}.
{"Subject", "Předmět"}.
{"Message body", "Tělo zprávy"}.
{"No body provided for announce message", "Zpráva neobsahuje text"}.
{"Announcements", "Oznámení"}.
{"Send announcement to all users", "Odeslat seznam všech uživatelů"}.
{"Send announcement to all online users", "Odeslat seznam všech online uživatelů"}.
{"Send announcement to all online users on all hosts", "Odeslat seznam všech online uživatelů na všech serverech"}.
{"Set message of the day and send to online users", "Nastavit zprávu dne a odeslat jí online uživatelům"}.
{"Update message of the day (don't send)", "Aktualizovat zprávu dne (neodesíelat)"}.
{"Delete message of the day", "Smazat zprávu dne"}.
% /usr/home/src/ejabberd/ejabberd/src/mod_configure.erl
{"Database", "Databáze"}.
{"Outgoing s2s Connections", "Odchozí s2s spojení"}.
{"Import Users From jabberd 1.4 Spool Files", "Importovat uživatelů z jabber 1.4 spool souborů"}.
{"Database Tables Configuration at ", "Konfigurace databázových tabulek "}.
% /usr/home/src/ejabberd/ejabberd/src/mod_pubsub/mod_pubsub.erl
{"ejabberd pub/sub module\nCopyright (c) 2003-2006 Alexey Shchepin",
"ejabberd pub/sub modul\nCopyright (c) 2003-2006 Alexey Shchepin"}.
% /usr/home/src/ejabberd/ejabberd/src/web/ejabberd_web_admin.erl
{"ejabberd Web Interface", "Ejabberd Web rozhraní"}.
{"Administration", "Administrace"}.
{"ejabberd (c) 2002-2006 Alexey Shchepin, 2004-2006 Process One",
"Ejabberd (c) 2002-2006 Alexey Shchepin, 2004-2006 Process One"}.
{"(Raw)", "(Zdroj)"}.
{"Bad format", "Nesprávný formát"}.
{"Raw", "Zdroj"}.
{"Users Last Activity", "Poslední aktivita uživatele"}.
{"Registered Users", "Registrovaní uživatelé"}.
{"Offline Messages", "Offline zprávy"}.
{"Registered Users:", "Registrovaní živatelé:"}.
{"Authenticated Users:", "Ověření uživatelé:"}.
{"Online Users:", "Online uživatelé:"}.
{"Outgoing s2s Connections:", "Odchozí s2s spojení:"}.
{"Outgoing s2s Servers:", "Odchozí s2s servery:"}.
{"Offline Messages:", "Offline zprávy"}.
{"~s's Offline Messages Queue", "~s Offline zpráv"}.
{"Add Jabber ID", "Přidat JID"}.
{"No Data", "Žádná data"}.
{"Listened Ports", "Otevřené porty"}.
{"RPC Call Error", "Chyba RPC volání"}.
{"Database Tables at ", "Databázové tabulky na "}.
{"Backup of ", "Záloha na "}.
{"Remark that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately.",
"Podotýkáme, že tato nastavení budou zálohované do zabudované databáze Mnesia. Pokud používáte ODBC modul, musíte zálohovat vaší SQL databázi separátně."}.
{"Store binary backup:", "Uložit binární zálohu:"}.
{"Restore binary backup immediately:", "Okamžitě obnovit binární zálohu:"}.
{"Restore binary backup after next ejabberd restart (requires less memory):",
"Obnovit binární zálohu při následujícím restartu Ejabberd (vyžaduje méně paměti)"}.
{"Store plain text backup:", "Uložit zálohu do textového souboru:"}.
{"Restore plain text backup immediately:", "Okamžitě obnovit zálohu z textového souboru:"}.
{"Statistics of ~p", "Statistiky ~p"}.
{"Uptime:", "Čas běhu"}.
{"Transactions Commited:", "Transakce potvrzena"}.
{"Transactions Aborted:", "Transakce zrušena"}.
{"Transactions Restarted:", "Transakce restartována"}.
{"Transactions Logged:", "Transakce zaznamenána"}.
{"Update ", "Aktualizovat "}.
{"Update plan", "Aktualizovat plán"}.
{"Updated modules", "Aktualizované moduly"}.
{"Update script", "Aktualizované skripty"}.
{"Low level update script", "Nízkoúrovňový aktualizační skript"}.
{"Script check", "Kontrola skriptu"}.
{"Not Found", "Nenalezeno"}.
{"Shared Roster Groups", "Skupiny pro zdílený seznam kontaktů"}.
% /usr/home/src/ejabberd/ejabberd/src/mod_irc/mod_irc.erl
{"ejabberd IRC module\nCopyright (c) 2003-2006 Alexey Shchepin", "Ejabberd IRC modul\nCopyright (c) 2003-2006 Alexey Shchepin"}.
% /usr/home/src/ejabberd/ejabberd/src/mod_muc/mod_muc_log.erl
{"Chatroom configuration modified", "Nastavení diskuzní místnosti bylo změněno"}.
{"joins the room", "vstoupil(a) do místnosti"}.
{"leaves the room", "opustil(a) místnost"}.
{"has been kicked", "byl(a) vyhozen(á) z místnosti"}.
{"has been banned", "byl(a) zablokován(a)"}.
{"is now known as", "se přejmenoval(a) na"}.
{"Monday", "Pondělí"}.
{"Tuesday", "Úterý"}.
{"Wednesday", "Středa"}.
{"Thursday", "Čtvrtek"}.
{"Friday", "Pátek"}.
{"Saturday", "Sobota"}.
{"Sunday", "Neděle"}.
{"January", "Leden"}.
{"February", "Únor"}.
{"March", "Březen"}.
{"April", "Duben"}.
{"May", "Květen"}.
{"June", "Červen"}.
{"July", "Červenec"}.
{"August", "Srpen"}.
{"September", "Září"}.
{"October", "říjen"}.
{"November", "Listopad"}.
{"December", "Prosinec"}.
{"Room Configuration", "Nastavení místnosti"}.
% /usr/home/src/ejabberd/ejabberd/src/mod_muc/mod_muc.erl
{"You must fill in field \"Nickname\" in the form",
"Musíte vyplnit políčko \"Prezdívka\" ve formuláři"}.
{"ejabberd MUC module\nCopyright (c) 2003-2006 Alexey Shchepin",
"Ejabberd MUC modul\nCopyright (c) 2003-2006 Alexey Shchepin"}.
% /usr/home/src/ejabberd/ejabberd/src/mod_muc/mod_muc_room.erl
{"This room is not anonymous", "Tato místnost není anonymní"}.
{"Make room persistent", "Nastavit místnost jako stálou"}.
{"Make room public searchable", "Nastavit místnost jako veřejně prohldávatelnou"}.
{"Make participants list public", "Nastavit seznam účastníků jako veřejný"}.
{"Make room password protected", "Chránit místnost heslem"}.
{"Make room members-only", "Nastavit místnost jen pro členy"}.
{"Make room moderated", "Nastavit místnost jako moderovanou"}.
{"Default users as participants", "Uživatelé jsou implicitně členy"}.
{"Allow users to change subject", "Povolit uživatelům měnit téma této místnosti"}.
{"Allow users to send private messages", "Povolit uživatelům odesíelat soukromé zprávy"}.
{"Allow users to query other users", "Povolit uživatelům odesíela požadavky (query) ostatním uživatelům"}.
{"Allow users to send invites", "povolit uživatelům posíelání pozvánek"}.
{"Enable logging", "Zapnout ukládání historie"}.
{"Description", "Popis"}.
{"Number of occupants", "Počet účastníků"}.
% Local Variables:
% mode: erlang
% End:
+4 -3
View File
@@ -236,6 +236,9 @@
{"Group ", "Gruppe "}.
{"ejabberd Web Interface", "ejabberd Web Interface"}.
% mod_vcard_ldap.erl
{"Given Name", "Vorname"}.
% ejabberd_c2s.erl
{"Use of STARTTLS required", "Verwendung von STARTTLS erforderlich"}.
{"Replaced by new connection", "Durch neue Verbindung ersetzt"}.
@@ -349,6 +352,7 @@
{"Make room public searchable", "Raum öffentlich durchsuchbar machen"}.
{"Make participants list public", "Teilnehmerliste öffentlich machen"}.
{"Make room password protected", "Raum passwortgeschützt machen"}.
{"Make room semianonymous", "Raum semi-anonym machen"}.
{"Make room members-only", "Raum members-only machen"}.
{"Make room moderated", "Raum modieriert machen"}.
{"Default users as participants", "Standartbenutzer als Teilnehmer"}.
@@ -359,9 +363,6 @@
{"Enable logging", "Log-Funktion aktivieren"}.
{"Description", "Beschreibung"}.
{"Number of occupants", "Anzahl der Teilnehmer"}.
{"Present real JIDs to", "Echte Jabber IDs anzeigen für"}.
{"moderators only", "nur Moderatoren"}.
{"anyone", "jeden"}.
% Local Variables:
% mode: erlang
+3 -4
View File
@@ -135,7 +135,7 @@
{"Make participants list public", "La lista de participantes es pública"}.
{"Make room persistent", "Sala permanente"}.
{"Make room moderated", "Sala moderada"}.
{"Default users as participants", "Los usuarios son participantes por defecto"}.
{"Default users as participants", "Los usuarios on participantes por defecto"}.
{"Make room members-only", "Sala sólo para miembros"}.
{"Allow users to send invites", "Permitir a los usuarios enviar invitaciones"}.
{"Make room password protected", "Proteger la sala con contraseña"}.
@@ -167,11 +167,9 @@
{"Invalid role: ~s", "Rol no válido: ~s"}.
{"Owner privileges required", "Se requieren privilegios de propietario de la sala"}.
{"private, ", "privado"}.
{"Make room semianonymous", "Hacer la sala semianónima"}.
{"Description", "Descripción"}.
{"Number of occupants", "Número de ocupantes"}.
{"Present real JIDs to", "Los JID reales pueden verlos"}.
{"moderators only", "solo moderadores"}.
{"anyone", "cualquiera"}.
% mod_muc/mod_muc_log.erl
{"Chatroom configuration modified", "Configuración de la sala modificada"}.
@@ -322,6 +320,7 @@
{"Replaced by new connection", "Reemplazado por una nueva conexión"}.
% mod_vcard_ldap.erl
{"Given Name", "Nombre dado"}.
{"Fill in fields to search for any matching Jabber User", "Rellena campos para buscar usuarios Jabber que concuerden"}.
% mod_adhoc.erl
+2 -3
View File
@@ -74,6 +74,7 @@
% src/mod_vcard_ldap.erl
{"Erlang Jabber Server\nCopyright (c) 2002-2006 Alexey Shchepin", "Serveur Jabber Erlang\nCopyright (c) 2002-2006 Alexey Shchepin"}.
{"Given Name", "Prénom"}.
{"ejabberd vCard module\nCopyright (c) 2003-2006 Alexey Shchepin", "Module vCard ejabberd\nCopyright (c) 2003-2006 Alexey Shchepin"}.
{"Email", "Email"}.
{"Search Results for ", "Résultats de recherche pour "}.
@@ -212,6 +213,7 @@
{"Make room public searchable", "Rendre le salon public"}.
{"Make participants list public", "Rendre la liste des participants publique"}.
{"Make room password protected", "Protéger le salon par mot de passe"}.
{"Make room semianonymous", "Rendre le salon semi-anonyme"}.
{"Make room members-only", "Réserver le salon aux membres uniquement"}.
{"Make room moderated", "Rendre le salon modéré"}.
{"Default users as participants", "Les utilisateurs sont par défaut participant"}.
@@ -222,9 +224,6 @@
{"Enable logging", "Activer l'archivage"}.
{"Description", "Description"}.
{"Number of occupants", "Nombre d'occupants"}.
{"Present real JIDs to", "Rendre le JID réel visible pour"}.
{"moderators only", "modérateurs seulement"}.
{"anyone", "tout le monde"}.
% mod_irc/mod_irc.erl
{"ejabberd IRC module\nCopyright (c) 2003-2006 Alexey Shchepin", "Module IRC ejabberd\nCopyright (c) 2003-2006 Alexey Shchepin"}.
+2 -3
View File
@@ -7,6 +7,7 @@
{"Fill in fields to search for any matching Jabber User", "Vul de velden in om te zoeken naar Jabber-gebruikers op deze server"}.
{"User", "Gebruiker"}.
{"Full Name", "Volledige naam"}.
{"Given Name", "Voornaam"}.
{"Middle Name", "Tussennaam"}.
{"Family Name", "Achternaam"}.
{"Nickname", "Bijnaam"}.
@@ -167,6 +168,7 @@
{"Make room public searchable", "Chatruimte doorzoekbaar maken"}.
{"Make participants list public", "Deelnemerslijst publiek maken"}.
{"Make room password protected", "Chatruimte beveiligen met een wachtwoord"}.
{"Make room semianonymous", "Chatruimte gedeeltelijk anoniem maken"}.
{"Make room members-only", "Chatruimte enkel toegankelijk maken voor leden"}.
{"Make room moderated", "Chatruimte gemodereerd maken"}.
{"Default users as participants", "Gebruikers standaard instellen als deelnemers"}.
@@ -178,9 +180,6 @@
{"You need an x:data capable client to configure room", "U hebt een client nodig die x:data ondersteunt om deze chatruimte in te stellen"}.
{"Description", "Beschrijving"}.
{"Number of occupants", "Aantal aanwezigen"}.
{"Present real JIDs to", "Jabber ID's kunnen achterhaald worden door"}.
{"moderators only", "moderators"}.
{"anyone", "iedereen"}.
% mod_irc/mod_irc.erl
{"ejabberd IRC module\nCopyright (c) 2003-2006 Alexey Shchepin", "ejabberd's IRC-module\nCopyright (c) 2003-2006 Alexey Shchepin"}.
+92 -54
View File
@@ -43,6 +43,7 @@
{"Configuration", "Konfiguracja"}.
{"Online Users", "Użytkownicy zalogowani"}.
{"All Users", "Wszyscy użytkownicy"}.
{"Outgoing S2S connections", "Wychodzące połączenia S2S"}.
{"To ~s", "Do ~s"}.
{"From ~s", "Z ~s"}.
{"Running Nodes", "Uruchomione gałęzie"}.
@@ -51,10 +52,12 @@
{"Access Control Lists", "Lista dostępowa"}.
{"Access Rules", "Zasady dostępu"}.
{"Remove Users", "Usuń użytkowników"}.
{"DB", "DB"}.
{"Modules", "Moduły"}.
{"Start Modules", "Uruchom moduły"}.
{"Stop Modules", "Zatrzymaj moduły"}.
{"Backup Management", "Zarządzanie kopiami zapasowymi"}.
{"Import users from jabberd1.4 spool files", "Importowanie użytkowników z plikow spoool serwera jabberd1.4"}.
{"Backup", "Tworzenie kopii"}.
{"Restore", "Odtwarzanie kopii"}.
{"Dump to Text File", "Zrzucanie do pliku tekstowego"}.
@@ -71,6 +74,7 @@
{"Search users in ", "Wyszukaj użytkowników w "}.
{"Fill in fields to search for any matching Jabber User",
"Wypełnij pola aby znaleźdź pasujących użytkowników Jabbera"}.
{"Results of search in ", "Wyniki wyszukiwania w "}.
{"User", "Użytkownik: "}.
{"Full Name", "Pełna nazwa: "}.
@@ -81,6 +85,7 @@
{"Birthday", "Data urodzenia: "}.
{"Country", "Państwo: "}.
{"City", "Miasto: "}.
{"email", "E-Mail: "}.
{"Organization Name", "Nazwa organizacji: "}.
{"Organization Unit", "Dział: "}.
@@ -93,6 +98,7 @@
"Jedynie administrator może wysyłać wiadomości serwisowe"}.
{"Conference room does not exist", "Pokój konferencyjny nie istnieje"}.
{"Access denied by service policy", "Dostęp zabroniony przez zabezpieczenia serwera"}.
{"You must fill in field \"nick\" in the form", "Musisz wypełnić pole \"nick\" w formularzu"}.
{"Specified nickname is already registered", "Podany nick jest już zarejestrowany"}.
% mod_muc/mod_muc_room.erl
@@ -101,7 +107,25 @@
"Potrzebujesz klienta kompatybilnego z x:data aby skonfigurować pokój"}.
{"Configuration for ", "Konfiguracja dla "}.
{"Room title", "Tytuł pokoju"}.
{"Allow users to change subject?", "Zezwolić użytkownikom na zmianę tematu?"}.
{"Allow users to query other users?",
"Zezwolić użytkownikom na zapraszanie innych użytkowników?"}.
{"Allow users to send private messages?",
"Zezwolić użytkownikom na wysyłanie prywatnych wiadomości?"}.
{"Make room public searchable?", "Uczynić pokój wyszukiwalnym publicznie?"}.
{"Make participants list public?", "Uczynic obecnych wyszukiwalnymi publicznie?"}.
{"Make room persistent?", "Uczynić pokój trwałym?"}.
{"Make room moderated?", "Uczynić pokój moderowanym?"}.
{"Default users as members?",
"Domyślni użytkownicy jako członkowie?"}.
{"Make room members only?",
"Uczynić pokój tylko dla członków?"}.
{"Allow users to send invites?",
"Pozwolić użytkownikom na wysyłanie zaproszeń?"}.
{"Make room password protected?", "Czy zabezpieczyć pokój hasłem?"}.
{"Password", "Hasło"}.
{"Make room anonymous?", "Uczynić pokój anonimowym?"}.
{"Enable logging?", "Włączyć logowanie?"}.
{"Only moderators and participants are allowed to change subject in this room",
"Tylko moderatorzy i wlasciciele mogą zmienić temat tego pokoju"}.
{"Only moderators are allowed to change subject in this room",
@@ -136,10 +160,6 @@
{"Invalid role: ~s", "Nieprawidłowa rola: ~s"}.
{"Owner privileges required", "Wymagane uprawnienia właściciela "}.
{"private, ", "prywatny, "}.
{"Present real JIDs to", "Kto może widzieć prawdziwe JID-y?"}.
{"moderators only", "tylko moderatorzy"}.
{"anyone", "wszyscy"}.
% mod_irc/mod_irc.erl
{"You need an x:data capable client to configure mod_irc settings",
@@ -153,55 +173,91 @@
{"Encodings", "Kodowania"}.
% web/ejabberd_web_admin.erl
{"ejabberd administration", "Administracja serwerem Ejabberd"}.
{"Users", "Użytkownicy"}.
{"Nodes", "Gałęzie"}.
{"Statistics", "Statystyki"}.
{"(raw)", "(raw)"}.
{"submitted", "przesłane"}.
{"bad format", "zły format"}.
{"raw", "raw"}.
{"ejabberd access control lists configuration", "Lista konfiguracyjna dostępu do serwera EJabberd"}.
{"Delete Selected", "Usuń zaznaczone"}.
{"Submit", "Wprowadź"}.
{"ejabberd access rules configuration", "Konfiguracja zasad dostępu do serwera EJabberd"}.
{"~s access rule configuration", "~s konfiguracja zasad dostępu"}.
{"ejabberd users", "Użytkownicy EJabberd"}.
{"ejabberd stats", "Statystyki EJabberd"}.
{"Node not found", "Gałąź nie znaleziona"}.
{"Add New", "Dodaj nowe"}.
{"Registered users", "Zarejestrowani użytkownicy"}.
{"Online users", "Użytkownicy online"}.
{"Outgoing S2S servers", "Sewery zewnętrzne S2S"}.
{"Change Password", "Zmień hasło"}.
{"Connected Resources:", "Zasoby podłączone"}.
{"Password:", "Hasło:"}.
{"None", "Brak"}.
{"Node ", "Gałąź "}.
{"DB Management", "Zarządzanie bazą danych"}.
{"Listened Ports Management", "Zarządzanie portami nasłuchującymi"}.
{"Restart", "Restart"}.
{"Stop", "Stop"}.
{"RPC call error", "Błąd RPC"}.
{"DB Tables at ", "Tabele bazy danych "}.
{"Name", "Nazwa"}.
{"Storage Type", "Typ bazy"}.
{"Size", "Wielkość"}.
{"Memory", "Pamięć"}.
{"Backup Management at ", "Zarządzanie kopiami zapasowymi "}.
{"Store a backup in a file", "Zachowaj kopie zapasowa w pliku "}.
{"OK", "OK"}.
{"Restore a backup from a file", "Odtwórz kopię zapasową z pliku"}.
{"Install a database fallback from a file", "Przywróć zapisaną kopię z pliku"}.
{"Dump a database in a text file", "Zrzuć bazę danych do pliku tekstowego"}.
{"Restore a database from a text file", "Odtwórz bazę danych z pliku tekstowego"}.
{"Listened Ports at ", "Porty nasłuchujące "}.
{"~p statistics", "~p statystyka"}.
{"Uptime", "Uptime"}.
{"CPU Time", "Czas procesora"}.
{"Transactions commited", "Tarnsakcje rozpoczęte"}.
{"Transactions aborted", "Transakcje anulowane"}.
{"Transactions restarted", "Transakcje zrestartowane"}.
{"Transactions logged", "Transakcje logowane"}.
{"Port", "Port"}.
{"Module", "Moduł"}.
{"Options", "Opcje"}.
{"Update", "Aktualizacja"}.
{"Delete", "Usuń"}.
{"Add User", "Dodaj użytkownika"}.
{"Offline messages", "Wiadomości offline"}.
{"Last Activity", "Ostatnia aktywność"}.
{"Never", "Nigdy"}.
{"~s offline messages queue", "~s wiadomości offline w kolejce"}.
{"Time", "Czas"}.
{"From", "Od"}.
{"To", "Do"}.
{"Packet", "Pakiet "}.
{"Offline messages:", "Wiadomości offline: "}.
{"Roster", "Roster "}.
{"Nickname", "Nick "}.
{"Subscription", "Subskrypcja "}.
{"Pending", "Oczekiwanie "}.
{"Groups", "Grupy "}.
{"Remove", "Usuń "}.
{"Add JID", "Dodaj JID "}.
{"User ", "Użytkownik "}.
{"Roster of ", "Roster "}.
{"Shared Roster", "Roster współdzielony"}.
{"Online", "Dostępny"}.
{"Validate", "Zatwierdź"}.
{"Not found", "Nie znaleziony"}.
{"Shared roster groups", "Grupy rosterów współdzielonych"}.
{"Name:", "Nazwa:"}.
{"Description:", "Opis:"}.
{"Members:", "Członkowie:"}.
{"Displayed Groups:", "Wyświetlane grupy:"}.
{"Group ", "Grupa "}.
{"Users last activity", "Ostatnia aktywność użytkowników"}.
{"Period: ", "Przedział czasu "}.
{"Last month", "Ostatni miesiąc"}.
{"Last year", "Ostatni rok"}.
@@ -209,23 +265,35 @@
{"Show Ordinary Table", "Pokaż zwykłą tabelę"}.
{"Show Integral Table", "Pokaż tabelę całkowitą"}.
{"Start", "Start"}.
{"Modules Management", "Zarządzanie modułami"}.
{"Modules at ", "Moduły na "}.
{"No data", "Brak danych"}.
{"Virtual Hosts", "Wirtualne hosty"}.
{"ejabberd virtual hosts", "wirtualne hosty ejabberda"}.
{"Host", "Host"}.
{"ejabberd Web Interface", ""}.
% mod_vcard_odbc.erl
{"Erlang Jabber Server\nCopyright (c) 2002-2005 Alexey Shchepin", "Erlang Jabber Server\nCopyright (c) 2002-2005 Alexey Shchepin"}.
{"Fill in the form to search for any matching Jabber User (Add * to the end of field to match substring)", "Wypełnij formularz aby wyszukać pasujących użytkowników Jabbera (dodaj * na koniec pola aby dopasować)"}.
{"ejabberd vCard module\nCopyright (c) 2003-2005 Alexey Shchepin", "ejabberd vCard module\nCopyright (c) 2003-2005 Alexey Shchepin"}.
{"JID", "JID"}.
% ejabberd_c2s.erl
{"Use of STARTTLS required", "Wymagane użycie STARTTLS"}.
{"Replaced by new connection", ""}.
% mod_configure.erl
{"DB Tables Configuration at ", "Konfiguracja tabel bazy dla "}.
% mod_vcard_ldap.erl
{"Given Name", "Nadana nazwa"}.
% mod_pubsub/mod_pubsub.erl
{"ejabberd pub/sub module\nCopyright (c) 2003-2005 Alexey Shchepin", "ejabberd pub/sub module\nCopyright (c) 2003-2005 Alexey Shchepin"}.
{[], " "}.
{"Node Creator", "Tworzenie gałęzi"}.
{"Deliver payloads with event notifications", "Dołącz zawartość publikowanego przedmiotu podczas wysyłania powiadomienia o publikacji"}.
{"Deliver payloads with event notifications", "Do?cz zawarto? publikowanego przedmiotu podczas wysy?nia powiadomienia o publikacji"}.
{"Notify subscribers when the node configuration changes", "Informuj subskrybentów gdy konfiguracja gałęzi się zmieni"}.
{"Notify subscribers when the node is deleted", "Informuj subskrybentów gdy gałąż zostanie wykasowana"}.
{"Notify subscribers when items are removed from the node", "Informuj subskrybentów kiedy zostaną z gałęzi usunięte jakieś elementy"}.
@@ -234,23 +302,36 @@
{"Whether to allow subscriptions", "Czy pozwolić na subskrypcje"}.
{"Specify the subscriber model", "Oznacz model subskrybenta"}.
{"Specify the publisher model", "Oznacz model publikującego"}.
{"Max payload size in bytes", "Maksymalna wielkość powiadomienia w bajtach"}.
{"Max payload size in bytes", "Maksymalna wielko? powiadomienia w bajtach"}.
{"Send items to new subscribers", "Wysyłaj rzeczy do nowych subskrybentów"}.
{"Only deliver notifications to available users", "Dostarczaj notyfikacje tylko do osiągalnych użytkowników"}.
{"Specify the current subscription approver", "Wyznacz aprobującego obecne subskrypcje "}.
% web/ejabberd_web_admin.erl
{"ejabberd (c) 2002-2005 Alexey Shchepin, 2004-2005 Process One", "ejabberd (c) 2002-2005 Alexey Shchepin, 2004-2005 Process One"}.
{"(raw)", "(raw)"}.
{"raw", "raw"}.
{"Authenticated users", "Użytkownicy zautoryzowani"}.
% mod_irc/mod_irc.erl
{"ejabberd IRC module\nCopyright (c) 2003-2005 Alexey Shchepin", "ejabberd IRC module\nCopyright (c) 2003-2005 Alexey Shchepin"}.
{"If you want to specify different encodings for IRC servers, fill this list with values in format '{\"irc server\", \"encoding\"}'. By default this service use \"~s\" encoding.", "Jeśli chcesz ustawić inne kodowanie dla serwerów IRC, wypełnij tą listę wartościami w formacie '{\"irc server\",\"encoding\"}'. Jako domyślne ten serwis używa kodowania \"~s\"."}.
% mod_muc/mod_muc.erl
{"Room creation is denied by service policy", "Tworzenie pokoju jest zabronione przez polisę"}.
{"ejabberd MUC module\nCopyright (c) 2003-2005 Alexey Shchepin", "ejabberd MUC module\nCopyright (c) 2003-2005 Alexey Shchepin"}.
% Local Variables:
% mode: erlang
% End:
% /usr/home/src/ejabberd/ejabberd/src/mod_vcard_odbc.erl
{"Erlang Jabber Server\nCopyright (c) 2002-2006 Alexey Shchepin", "Erlang Jabber Server\nCopyright (c) 2002-2006 Alexey Shchepin"}.
{"Erlang Jabber Server\nCopyright (c) 2002-2006 Alexey Shchepin", ""}.
{"Email", ""}.
{"ejabberd vCard module\nCopyright (c) 2003-2006 Alexey Shchepin", "Erlang Jabber Server\nCopyright (c) 2002-2006 Alexey Shchepin"}.
{"ejabberd vCard module\nCopyright (c) 2003-2006 Alexey Shchepin", ""}.
{"Search Results for ", "Wyniki wyszukiwania dla "}.
{"Jabber ID", "Jabber ID"}.
{"Jabber ID", ""}.
% /usr/home/src/ejabberd/ejabberd/src/mod_adhoc.erl
{"Commands", "Polecenia"}.
@@ -369,7 +450,8 @@
{"Make room public searchable", "Pozwól wyszukiwać pokój"}.
{"Make participants list public", "Upublicznij listę uczestników"}.
{"Make room password protected", "Zabezpiecz pokój hasłem"}.
{"Make room members-only", "Utwórz pokój tylko dla uczestnikóww"}.
{"Make room semianonymous", "Utwórz pokój pół-nieznanym"}.
{"Make room members-only", "Utwórz pokój tylko dla członków"}.
{"Make room moderated", "Moderuj pokój"}.
{"Default users as participants", "Domyślni użytkownicy jako uczestnicy"}.
{"Allow users to change subject", "Pozwól użytkownikom zmienić tytuł pokoju"}.
@@ -379,47 +461,3 @@
{"Enable logging", "Włącz logowanie"}.
{"Description", "Opis"}.
{"Number of occupants", "Liczba uczestników"}.
% mod_vcard_ldap.erl
{"Erlang Jabber Server\nCopyright (c) 2002-2006 Alexey Shchepin", "Erlang Jabber Server\nCopyright (c) 2002-2006 Alexey Shchepin"}.
{"ejabberd vCard module\nCopyright (c) 2003-2006 Alexey Shchepin", "ejabberd vCard module\nCopyright (c) 2003-2006 Alexey Shchepin"}.
{"Jabber ID", "Jabber ID"}.
% ./mod_presence.erl
{"You need an x:data capable client to register presence", "Potrzebujesz klinta kompatybilnego z x:data aby zarejestrować widoczność "}.
{"Presence registration at ", "Rejestracja widoczności na "}.
{"What presence features do you want to register?", "Jakie usługi widoczności chcesz zarejestrować?"}.
{"Raw XML", ""}.
{"Specified presence is already registered", "Określona widoczność już jest zarejestrowana"}.
{"You must fill in field \"Xml\" in the form", "Musisz wypełnić w formularzu pole \"XML\""}.
{"You must fill in field \"Icon\" in the form", "Musisz wypełnić w formularzu pole \"Icon\""}.
{"ejabberd presence module\nCopyright (c) 2006 Igor Goryachev", ""}.
% ./mod_presence/mod_presence.erl
{"Raw XML export", "Eksport XML do raw"}.
{"Allow icon export", "Pozwól na eksport ikon"}.
% ./mod_stats2file.erl
{"CPUtime", "Czas procesora"}.
% ./mod_vcard_odbc.erl
{"Erlang Jabber Server\nCopyright (c) 2002-2006 Alexey Shchepin", ""}.
{"Email", ""}.
{"ejabberd vCard module\nCopyright (c) 2003-2006 Alexey Shchepin", ""}.
{"Jabber ID", ""}.
% ./mod_pubsub/mod_pubsub.erl
{"ejabberd pub/sub module\nCopyright (c) 2003-2006 Alexey Shchepin", ""}.
% ./web/ejabberd_web_admin.erl
{"ejabberd (c) 2002-2006 Alexey Shchepin, 2004-2006 Process One", ""}.
{"(Raw)", ""}.
{"Raw", ""}.
{"Low level update script", "Skrypt aktualizacyjny niskiego poziomu"}.
% ./mod_irc/mod_irc.erl
{"ejabberd IRC module\nCopyright (c) 2003-2006 Alexey Shchepin", ""}.
% ./mod_muc/mod_muc.erl
{"ejabberd MUC module\nCopyright (c) 2003-2006 Alexey Shchepin", ""}.
+67 -6
View File
@@ -47,12 +47,15 @@
{"Backup", "Salvar cópia de segurança"}.
{"Backup Management", "Gestão de copia de segurança"}.
{"Configuration", "Configuração"}.
{"DB", "BD"}.
{"Dump to Text File", "Exportar para arquivo de texto"}.
{"From ~s", "De ~s"}.
{"Import Directory", "Importar diretório"}.
{"Import File", "Importar arquivo"}.
{"Import users from jabberd1.4 spool files", "Importar usuários a partir de arquivos da spool do jabberd1.4"}.
{"Modules", "Módulos"}.
{"Online Users", "Usuários conectados"}.
{"Outgoing S2S connections", "Conexões S2S de saída"}.
{"Remove Users", "Remover usuários"}.
{"Restore", "Restaurar"}.
{"Running Nodes", "Nos em execução"}.
@@ -71,6 +74,7 @@
{"City", "Cidade"}.
{"Country","País"}.
{"ejabberd vCard module\nCopyright (c) 2003-2006 Alexey Shchepin", "Módulo vCard para ejabberd\nCopyright (c) 2002-2006 Alexey Shchepin"}.
{"email", "e-mail"}.
{"Erlang Jabber Server\nCopyright (c) 2002-2006 Alexey Shchepin", "Servidor Jabber em Erlang\nCopyright (c) 2002-2006 Alexey Shchepin"}.
{"Family Name", "Nome de família"}.
{"Fill in fields to search for any matching Jabber User", "Preencha os campos para procurar usuários Jabber coincidentes"}.
@@ -81,6 +85,7 @@
{"Nickname", "Nick"}.
{"Organization Name", "Nome da organização"}.
{"Organization Unit", "Unidade da organização"}.
{"Results of search in ", "Resultados da busca em "}.
{"Search users in ", "Procurar usuários em "}.
{"User", "Usuário"}.
{"You need an x:data capable client to search", "Necessitas um cliente com suporte de x:data para poder buscar"}.
@@ -105,11 +110,19 @@
{"Whether to allow subscriptions", "Permitir subscrições"}.
% mod_muc/mod_muc.erl
{"Allow users to change subject?", "Permitir aos usuários mudar o tópico?"}.
{"Allow users to query other users?", "Permitir aos usuários consultar outros usuários?"}.
{"Allow users to send invites?", "Permitir que os usuários enviem convites?"}.
{"Allow users to send private messages?", "Permitir que os usuários enviem mensagens privadas?"}.
{"Default users as members?", "Os usuários padrão são membros?"}.
{"Enable logging?", "Salvar históricos?"}.
{"Access denied by service policy", "Aceso denegado por la política do serviço"}.
{"Conference room does not exist", "La sala de conferencias não existe"}.
{"ejabberd MUC module\nCopyright (c) 2003-2006 Alexey Shchepin", "Módulo de MUC para ejabbed\nCopyright (c) 2002-2006 Alexey Shchepin"}.
{"Enter nickname you want to register", "Introduza o apelido que quer registrar"}.
{"Incorrect password", "Senha incorreta"}.
{"Make room anonymous?", "Tornar a sala anônima?"}.
{"Make room password protected?", "Proteger a sala com senha?"}.
{"Nickname is already in use by another occupant", "O apelido já está em uso por outro ocupante"}.
{"Nickname is registered by another person", "O apelido já está registrado por outra pessoa"}.
{"Nickname Registration at ", "Registro do apelido em "}.
@@ -118,11 +131,18 @@
{"Password", "Senha"}.
{"Room creation is denied by service policy", "Se te a denegado criar la sala por política do serviço"}.
{"Specified nickname is already registered", "O apelido especificado já está registrado"}.
{"You must fill in field \"nick\" in the form", "Deve preencher o campo \"apelido\" no formulário"}.
{"You need an x:data capable client to register nickname", "Necessitas um cliente com suporte de x:data para poder registrar o nick"}.
% mod_muc/mod_muc_room.erl
{"Administrator privileges required", "Se necessita privilégios de administrador"}.
{"Allow users to change subject?", "Permitir aos usuários cambiar o assunto"}.
{"Allow users to query other users?", "Permitir aos usuários consultar a outros usuários"}.
{"Allow users to send invites?", "Permitir aos usuários enviar convides"}.
{"Allow users to send private messages?", "Permitir aos usuários enviar mensagens privados"}.
{"Configuration for ", "Configuração para "}.
{"Default users as members?", "Os usuários são membros por defeito"}.
{"Enable logging?", "Guardar históricos"}.
{" has set the subject to: ", " a posto o assunto: "}.
{"Improper message type", "Tipo de mensagem incorreto"}.
{"Incorrect password", "Senha incorreta"}.
@@ -132,6 +152,13 @@
{"It is not allowed to send private messages of type \"groupchat\"", "No está permitido enviar mensagens privados do tipo \"groupchat\""}.
{"It is not allowed to send private messages to the conference", "Impedir o envio de mensagens privados a la sala"}.
{"JID ~s is invalid", "O JID ~s não es válido"}.
{"Make participants list public?", "Fazer pública la lista de participantes"}.
{"Make room anonymous?", "Fazer anônima la sala"}.
{"Make room members only?", "Fazer la sala solo para membros"}.
{"Make room moderated?", "Fazer la sala moderada"}.
{"Make room password protected?", "Proteger la sala com senha"}.
{"Make room persistent?", "Fazer la sala permanente"}.
{"Make room public searchable?", "Fazer a sala publicamente visível"}.
{"Membership required to enter this room", "Necessitas ser membro de esta sala para poder entrar"}.
{"Moderator privileges required", "Se necessita privilégios de moderador"}.
{"Nickname is already in use by another occupant", "O nick já está sendo usado por outro ocupante"}.
@@ -165,57 +192,91 @@
% web/ejabberd_web_admin.erl
{"Add JID", "Adicionar JID"}.
{"Add New", "Adicionar novo"}.
{"Add User", "Adicionar usuário"}.
{"All activity", "Toda la atividade"}.
{"Backup Management at ", "Gestão de copia de segurança em "}.
{"bad format", "mal formato"}.
{"Change Password", "Mudar senha"}.
{"Connected Resources:", "Recursos conectados:"}.
{"CPU Time", "Tempo de processador consumido"}.
{"DB Management", "Gestão do BD"}.
{"DB Tables at ", "Tabelas do BD em "}.
{"Delete", "Eliminar"}.
{"Delete Selected", "Remover os selecionados"}.
{"Dump a database in a text file", "Exportar uma Base de Dados para um arquivo de texto"}.
{"ejabberd access control lists configuration", "Configuração das Listas de Controle de Acesso do ejabberd"}.
{"ejabberd access rules configuration", "Configuração de las Regras de Aceso de ejabberd"}.
{"ejabberd administration", "Administração de ejabberd"}.
{"ejabberd (c) 2002-2006 Alexey Shchepin, 2004-2006 Process One", "ejabberd (c) 2002-2006 Alexey Shchepin, 2004-2006 Process One"}.
{"ejabberd stats", "Estatísticas de ejabberd"}.
{"ejabberd users", "Usuários do ejabberd"}.
{"ejabberd virtual hosts", "Maquinas virtuais de ejabberd"}.
{"From", "De"}.
{"Group ", "Grupo "}.
{"Groups", "Grupos"}.
{"Host", "Máquina"}.
{"Install a database fallback from a file", "Instalar uma recuperação de BD a partir de um arquivo"}.
{"JID", "JID"}.
{"Last Activity", "Última atividade"}.
{"Last month", "Último mês"}.
{"Last year", "Último ano"}.
{"Listened Ports at ", "Portas de escuta em "}.
{"Listened Ports Management", "Gestão dos portas de escuta"}.
{"Members:", "Miembros:"}.
{"Memory", "Memória"}.
{"Module", "Módulo"}.
{"Modules at ", "Módulos em "}.
{"Modules Management", "Gestão de módulos"}.
{"Name:", "Nome:"}.
{"Name", "Nome"}.
{"Never", "Nunca"}.
{"Nickname", "Apelido"}.
{"Online", "Conectado"}.
{"Online users", "Usuários conectados"}.
{"Options", "Opções"}.
{"Outgoing S2S servers", "Servidores conectados"}.
{"Packet", "Pacote"}.
{"Password:", "Senha:"}.
{"Pending", "Pendente"}.
{"Period: ", "Período: "}.
{"Port", "Porta"}.
{"~p statistics", "Estatísticas de ~p"}.
{"(raw)", "(cru)"}.
{"raw", "cru"}.
{"Registered users", "Usuários registrados"}.
{"Remove", "Borrar"}.
{"Restart", "Reiniciar"}.
{"Restore a backup from a file", "Recuperar uma cópia de segurança a partir do arquivo"}.
{"Restore a database from a text file", "Restaurar uma Base de Dados a partir de um arquivo de texto"}.
{"Roster", "Lista de contatos"}.
{"Roster of ", "Lista de contatos de "}.
{"RPC call error", "Erro em la chamada RPC"}.
{"~s access rule configuration", "Configuração da Regra de Acesso ~s"}.
{"Shared roster groups", "Grupos compartilhado"}.
{"Shared Roster", "Lista de contatos compartilhada"}.
{"Show Integral Table", "Mostrar Tabela Integral"}.
{"Show Ordinary Table", "Mostrar Tabela Ordinária"}.
{"Size", "Tamanho"}.
{"~s offline messages queue", "~s cola de mensagens diferidos"}.
{"Start", "Iniciar"}.
{"Statistics", "Estatísticas"}.
{"Stop", "Parar"}.
{"Storage Type", "Tipo de armazenamento"}.
{"Store a backup in a file", "Armazenar uma cópia de segurança no arquivo"}.
{"Submit", "Enviar"}.
{"submitted", "enviado"}.
{"Subscription", "Subscrição"}.
{"Time", "Fecha"}.
{"To", "Para"}.
{"Transactions aborted", "Transações abortadas"}.
{"Transactions commited", "Transações realizadas"}.
{"Transactions logged", "Transações armazenadas"}.
{"Transactions restarted", "Transações reiniciadas"}.
{"Update", "Atualizar"}.
{"Uptime", "Tempo de funcionamento"}.
{"Users last activity", "Última atividades dos usuários"}.
{"Users", "Usuários"}.
{"User ", "Usuário"}.
{"Validate", "Validar"}.
@@ -227,7 +288,8 @@
% mod_vcard_ldap.erl
{"Fill in fields to search for any matching Jabber User", "Preencha campos para buscar usuários Jabber que concordem"}.
{"Given Name", "Nome dado"}.
{"JID", "JID"}.
% mod_adhoc.erl
@@ -322,6 +384,8 @@
{"Description:", "Descrição:"}.
{"Displayed Groups:", "Grupos Indicados"}.
% mod_irc/mod_irc.erl
% mod_muc/mod_muc_log.erl
{"Chatroom configuration modified", "Configuração da sala de bate-papo modificada"}.
{"joins the room", "Entrar na sala"}.
@@ -360,6 +424,7 @@
{"Make room public searchable", "Tornar sala pública possível de ser encontrada"}.
{"Make participants list public", "Tornar pública a lista de participantes"}.
{"Make room password protected", "Tornar protegida a senha da sala"}.
{"Make room semianonymous", "Tornar sala semi-anônima"}.
{"Make room members-only", "Tornar sala apenas para membros"}.
{"Make room moderated", "Tornar a sala moderada"}.
{"Default users as participants", "Usuários padrões como participantes"}.
@@ -370,10 +435,6 @@
{"Enable logging", "Permitir criação de logs"}.
{"Description", "Descrição"}.
{"Number of occupants", "Número de participantes"}.
{"Present real JIDs to", "Tornar o JID real visível por"}.
{"moderators only", "apenas moderadores"}.
{"anyone", "qualquer um"}.
{"is now known as", "é agora conhecido como"}.
% Local Variables:
% mode: erlang
+2 -4
View File
@@ -159,7 +159,7 @@
"Вы должны заполнить поле \"Псевдоним\" в форме"}.
{"Specified nickname is already registered", "Указанный псевдоним уже зарегистрирован"}.
% mod_muc/mod_muc_log.erl
% /home/sergei/src/ejabberd/ejabberd/src/mod_muc/mod_muc_log.erl
{"Chatroom configuration modified", "Конфигурация комнаты изменилась"}.
{"joins the room", "вошёл(а) в комнату"}.
{"leaves the room", "вышел(а) из комнаты"}.
@@ -211,9 +211,7 @@
"Разрешить пользователям посылать приглашения"}.
{"Make room password protected", "Сделать комнату защищённой паролем"}.
{"Password", "Пароль"}.
{"Present real JIDs to", "Сделать реальные JID участников видимыми"}.
{"moderators only", "только модераторам"}.
{"anyone", "всем участникам"}.
{"Make room semianonymous", "Сделать комнату полуанонимной"}.
{"Enable logging", "Включить журналирование"}.
{"Only moderators and participants are allowed to change subject in this room",
"Только модераторы и участники могут изменять тему в этой комнате"}.
-463
View File
@@ -1,463 +0,0 @@
% $Id$
% jlib.hrl
{"No resource provided", "Nebol poskytnutý žiadny zdroj"}.
% mod_configure.erl
{"Choose storage type of tables", "Vyberte typ úložiska pre tabuľky"}.
{"RAM copy", "Kópia RAM"}.
{"RAM and disc copy", "Kópia RAM a disku"}.
{"Disc only copy", "Len kópia disku"}.
{"Remote copy", "Vzdialená kópia"}.
{"Stop Modules at ", "Zastaviť moduly na "}.
{"Choose modules to stop", "Vyberte moduly, ktoré majú byť zastavené"}.
{"Start Modules at ", "Spustiť moduly na "}.
{"Enter list of {Module, [Options]}", "Vložte zoznam modulov {Modul, [Parametre]}"}.
{"List of modules to start", "Zoznam modulov, ktoré majú byť spustené"}.
{"Backup to File at ", "Záloha do súboru na "}.
{"Enter path to backup file", "Zadajte cestu k súboru so zálohou"}.
{"Path to File", "Cesta k súboru"}.
{"Restore Backup from File at ", "Obnoviť zálohu zo súboru na "}.
{"Dump Backup to Text File at ", "Uložiť zálohu do textového súboru na "}.
{"Enter path to text file", "Zadajte cestu k textovému súboru"}.
{"Import User from File at ", "Importovať používateľa zo súboru na "}.
{"Enter path to jabberd1.4 spool file", "Zadajte cestu k spool súboru jabberd1.4"}.
{"Import Users from Dir at ", "Importovať používateľov z adresára na "}.
{"Enter path to jabberd1.4 spool dir", "Zadajte cestu k jabberd1.4 spool adresáru"}.
{"Path to Dir", "Cesta k adresáru"}.
{"Hostname Configuration", "Konfigurácia mena servera"}.
{"Choose host name", "Vyberte meno servera"}.
{"Host name", "Host name"}.
{"Access Control List Configuration", "Konfigurácia zoznamu prístupových oprávnení (ACL)"}.
{"Access control lists", "Zoznamy prístupových oprávnení (ACL)"}.
{"Access Configuration", "Konfigurácia prístupu"}.
{"Access rules", "Prístupové pravidlá"}.
{"Remove Users", "Odstrániť používateľov"}.
{"Choose users to remove", "Zvoliť používateľov, ktorí budú odstránení"}.
{"Administration of ", "Administrácia "}.
{"Action on user", "Operácia aplikovaná na používateľa"}.
{"Edit Properties", "Editovať vlastnosti"}.
{"Remove User", "Odstrániť používateľa"}.
% mod_disco.erl
{"Configuration", "Konfigurácia"}.
{"Online Users", "Online používatelia"}.
{"All Users", "Všetci používatelia"}.
{"Outgoing S2S connections", "Odchádzajúce spojenie S2S"}.
{"To ~s", "Pre ~s"}.
{"From ~s", "Od ~s"}.
{"Running Nodes", "Bežiace uzly"}.
{"Stopped Nodes", "Zastavené uzly"}.
{"Host Name", "Host name"}.
{"Access Control Lists", "Zoznamy prístupových oprávnení (ACL)"}.
{"Access Rules", "Prístupové pravidlá"}.
{"Remove Users", "Odstrániť používateľov"}.
{"DB", "DB"}.
{"Modules", "Moduly"}.
{"Start Modules", "Spustiť moduly"}.
{"Stop Modules", "Zastaviť moduly"}.
{"Backup Management", "Správa zálohovania"}.
{"Import users from jabberd1.4 spool files", "Importovať používateľov z jabberd1.4 spool súborov"}.
{"Backup", "Zálohovať"}.
{"Restore", "Obnoviť"}.
{"Dump to Text File", "Uložiť do textového súboru"}.
{"Import File", "Import súboru"}.
{"Import Directory", "Import adresára"}.
% mod_register.erl
{"Choose a username and password to register with this server",
"Vybrať meno používateľa a heslo pre registráciu na tomto serveri"}.
% mod_vcard.erl
{"You need an x:data capable client to search",
"Na vyhľadávanie potrebujete klienta podporujúceho x:data"}.
{"Search users in ", "Hľadať používateľov v "}.
{"Fill in fields to search for any matching Jabber User",
"Vyplnte políčka pre vyhľadávanie Jabber používateľa"}.
{"Results of search in ", "Výsledky vyhľadávania v "}.
{"User", "Používateľ: "}.
{"Full Name", "Celé meno: "}.
{"Name", "Meno: "}.
{"Middle Name", "Prostredné meno: "}.
{"Family Name", "Priezvisko: "}.
{"Nickname", "Prezývka: "}.
{"Birthday", "Dátum narodenia: "}.
{"Country", "Krajina: "}.
{"City", "Mesto: "}.
{"email", "E-mail: "}.
{"Organization Name", "Meno organizácie: "}.
{"Organization Unit", "Organizačná jednotka: "}.
% mod_muc/mod_muc.erl
{"You need an x:data capable client to register nickname",
"Na registráciu prezývky potrebujete klienta podporujúceho z x:data"}.
{"Nickname Registration at ", "Registrácia prezývky na "}.
{"Enter nickname you want to register", "Zadajte prezývku, ktorú chete registrovať"}.
{"Only service administrators are allowed to send service messages",
"Iba správcovia služby majú povolené odosielanie servisných správ"}.
{"Conference room does not exist", "Konferenčná miestnosť neexistuje"}.
{"Access denied by service policy", "Prístup bol zamiestnutý nastavení služby"}.
{"You must fill in field \"nick\" in the form", "Musíte vyplniť políčko \"prezývka\" vo formulári"}.
{"Specified nickname is already registered", "Zadaná prezývka je už registrovaná"}.
% mod_muc/mod_muc_room.erl
{" has set the subject to: ", "zmiel(a) tému na: "}.
{"You need an x:data capable client to configure room",
"Na konfiguráciu miestnosti potrebujete klienta podporujúceho x:data"}.
{"Configuration for ", "Konfigurácia pre "}.
{"Room title", "Názov miestnosti"}.
{"Allow users to change subject?", "Povoliť používateľom meniť tému?"}.
{"Allow users to query other users?",
"Povoliť používateľom odosielať požiadavky (query) ostatným používateľom?"}.
{"Allow users to send private messages?",
"Povoliť používateľom odosielať súkromné správy?"}.
{"Make room public searchable?", "Nastaviť miestnosť ako verejne prehľadávateľnú?"}.
{"Make participants list public?", "Nastaviť zoznam zúčastnených ako verejný?"}.
{"Make room persistent?", "Nastaviť miestnosť ako trvalú (persistent)?"}.
{"Make room moderated?", "Nastaviť miestnosť ako moderovanú?"}.
{"Default users as members?",
"Používatelia sú implicitne členmi?"}.
{"Make room members only?",
"Nastaviť miestnosť len pre členov?"}.
{"Allow users to send invites?",
"Povoliť používateľom odosielať pozvánky?"}.
{"Make room password protected?", "Chrániť miestnosť heslom?"}.
{"Password", "Heslo"}.
{"Make room anonymous?", "Nastaviť miestnosť ako anonymnú?"}.
{"Enable logging?", "Zapnúť zaznamenávanie histórie?"}.
{"Only moderators and participants are allowed to change subject in this room",
"Len moderátori a zúčastnený majú povolené meniť tému tejto miestnosti"}.
{"Only moderators are allowed to change subject in this room",
"Len moderátori majú povolené meniť tému miestnosti"}.
{"Visitors are not allowed to send messages to all occupants",
"Návštevníci nemajú povolené zasielať správy všetkým prihláseným do konferencie"}.
{"Only occupants are allowed to send messages to the conference",
"Len členovia majú povolené zasielať správy do konferencie"}.
{"It is not allowed to send normal messages to the conference",
"Nie je povolené odosielať normálne správy do konferencie"}.
{"It is not allowed to send private messages to the conference",
"Nie je povolené odosielať súkromné správy do konferencie"}.
{"Improper message type", "Nesprávny typ správy"}.
{"Nickname is already in use by another occupant", "Prezývka je už používaná iným členom"}.
{"Nickname is registered by another person", "Prezývka je registrovaná inou osobou"}.
{"It is not allowed to send private messages of type \"groupchat\"",
"Nie je dovolené odoslanie súkromnej správy typu \"Skupinová správa\" "}.
{"Recipient is not in the conference room", "Príjemca sa nenachádza v konferenčnej miestnosti"}.
{"Only occupants are allowed to send queries to the conference",
"Len členovia majú povolené odosielať požiadavky (query) do konferencie"}.
{"Queries to the conference members are not allowed in this room",
"Požiadavky (queries) na členov konferencie nie sú povolené v tejto miestnosti"}.
{"You have been banned from this room", "Boli ste vylúčený z tejto miestnosti"}.
{"Membership required to enter this room", "Pre vstup do miestnosti je potrebné byť členom"}.
{"Password required to enter this room", "Pre vstup do miestnosti je potrebné heslo"}.
{"Incorrect password", "Nesprávne heslo"}.
{"Administrator privileges required", "Sú potrebné práva administrátora"}.
{"Moderator privileges required", "Sú potrebné práva moderátora"}.
{"JID ~s is invalid", "JID ~s je neplatné"}.
{"Nickname ~s does not exist in the room", "Prezývka ~s v miestnosti neexistuje"}.
{"Invalid affiliation: ~s", "Neplatné priradenie: ~s"}.
{"Invalid role: ~s", "Neplatná rola: ~s"}.
{"Owner privileges required", "Sú vyžadované práva vlastníka"}.
{"private, ", "súkromná, "}.
% mod_irc/mod_irc.erl
{"You need an x:data capable client to configure mod_irc settings",
"Pre konfiguráciu mod_irc potrebujete klienta podporujúceho x:data"}.
{"Registration in mod_irc for ", "Registrácia do mod_irc na "}.
{"Enter username and encodings you wish to use for connecting to IRC servers",
"Vložte meno používateľa a kódovanie, ktoré chcete používať pri pripojení na IRC server"}.
{"IRC Username", "IRC prezývka"}.
{"Example: [{\"irc.lucky.net\", \"koi8-r\"}, {\"vendetta.fef.net\", \"iso8859-1\"}].",
"Príklad: [{\"irc.freenode.net\",\"utf-8\"}, {\irc.freenode.net\", \"iso8859-2\"}]."}.
{"Encodings", "Kódovania"}.
% web/ejabberd_web_admin.erl
{"ejabberd administration", "Administrácia Ejabberd"}.
{"Users", "Používatelia"}.
{"Nodes", "Uzly"}.
{"Statistics", "Štatistiky"}.
{"(raw)", "(raw)"}.
{"submitted", "odoslané"}.
{"bad format", "zlý formát"}.
{"raw", "raw"}.
{"ejabberd access control lists configuration", "Konfigurácia zoznamu prístupových oprávnení (ACL) Ejabberd"}.
{"Delete Selected", "Zmazať vybrané"}.
{"Submit", "Odoslať"}.
{"ejabberd access rules configuration", "Konfigurácia prístupových pravidiel Ejabberd"}.
{"~s access rule configuration", "~s konfigurácia prístupového pravidla"}.
{"ejabberd users", "Používatelia Ejabberd"}.
{"ejabberd stats", "Štatistiky Ejabberd"}.
{"Node not found", "Uzol nenájdený"}.
{"Add New", "Pridať nový"}.
{"Registered users", "Registrovaní používatelia"}.
{"Online users", "Online používatelia"}.
{"Outgoing S2S servers", "Servery S2S pre odchádzajúcu komunikáciu"}.
{"Change Password", "Zmeniť heslo"}.
{"Connected Resources:", "Pripojené zdroje:"}.
{"Password:", "Heslo:"}.
{"None", "Nič"}.
{"Node ", "Uzol "}.
{"DB Management", "Správa databázy"}.
{"Listened Ports Management", "Správa otvorených portov"}.
{"Restart", "Reštart"}.
{"Stop", "Stop"}.
{"RPC call error", "Chyba RPC volania"}.
{"DB Tables at ", "Databázové tabuľky na "}.
{"Name", "Meno"}.
{"Storage Type", "Typ úložiska"}.
{"Size", "Veľkosť"}.
{"Memory", "Pamäť"}.
{"Backup Management at ", "Správa záloh na "}.
{"Store a backup in a file", "Uložiť zálohu do súboru "}.
{"OK", "OK"}.
{"Restore a backup from a file", "Obnoviť zálohu zo súboru"}.
{"Install a database fallback from a file", "Inštalovať fallback pre databázu zo súboru"}.
{"Dump a database in a text file", "Uložiť databázu do textového súboru"}.
{"Restore a database from a text file", "Obnoviť databázu z textového súboru"}.
{"Listened Ports at ", "Otvorené porty na "}.
{"~p statistics", "~p štatistiky"}.
{"Uptime", "Uptime"}.
{"CPU Time", "Čas procesoru"}.
{"Transactions commited", "Transakcie potvrdená"}.
{"Transactions aborted", "Transakcie zrušená"}.
{"Transactions restarted", "Transakcie reštartovaná"}.
{"Transactions logged", "Transakcie zaznamenaná"}.
{"Port", "Port"}.
{"Module", "Modul"}.
{"Options", "Nastavenia"}.
{"Update", "Aktualizovať"}.
{"Delete", "Zmazať"}.
{"Add User", "Pridať používateľa"}.
{"Offline messages", "Offline správy"}.
{"Last Activity", "Posledná aktivita"}.
{"Never", "Nikdy"}.
{"~s offline messages queue", "~s offline správy"}.
{"Time", "Čas"}.
{"From", "Od"}.
{"To", "Pre"}.
{"Packet", "Paket"}.
{"Offline messages:", "Offline správy:"}.
{"Roster", "Zoznam kontaktov"}.
{"Nickname", "Prezývka"}.
{"Subscription", "Prihlásenie"}.
{"Pending", "Čakajúce"}.
{"Groups", "Skupiny"}.
{"Remove", "Odstrániť"}.
{"Add JID", "Pridať JID"}.
{"User ", "Používateľ "}.
{"Roster of ", "Zoznam kontaktov "}.
{"Shared Roster", "Zdieľaný zoznam kontaktov"}.
{"Online", "Online"}.
{"Validate", "Overiť"}.
{"Not found", "Nenájdené"}.
{"Shared roster groups", "Skupiny pre zdieľaný zoznam kontaktov"}.
{"Name:", "Meno:"}.
{"Description:", "Popis:"}.
{"Members:", "Členovia:"}.
{"Displayed Groups:", "Zobrazené skupiny:"}.
{"Group ", "Skupina "}.
{"Users last activity", "Posledná aktivita používateľa"}.
{"Period: ", "Čas:"}.
{"Last month", "Posledný mesiac"}.
{"Last year", "Posledný rok"}.
{"All activity", "Všetky aktivity"}.
{"Show Ordinary Table", "Zobraziť bežnú tabuľku"}.
{"Show Integral Table", "Zobraziť kompletnú tabuľku"}.
{"Start", "Štart"}.
{"Modules Management", "Správa modulov"}.
{"Modules at ", "Moduly na "}.
{"No data", "Žiadne dáta"}.
{"Virtual Hosts", "Virtuálne servery"}.
{"ejabberd virtual hosts", "Ejabberd virtuálne servery"}.
{"Host", "Server"}.
{"ejabberd Web Interface", "Ejabberd Web rozhranie"}.
% mod_vcard_odbc.erl
{"Erlang Jabber Server\nCopyright (c) 2002-2005 Alexey Shchepin", "Erlang Jabber Server\nCopyright (c) 2002-2005 Alexey Shchepin"}.
{"Fill in the form to search for any matching Jabber User (Add * to the end of field to match substring)", "Pre vyhľadanie Jabber používateľa vyplňte formulár (pridajte znak * na koniec, pre vyhľadanie podreťazca)"}.
{"ejabberd vCard module\nCopyright (c) 2003-2005 Alexey Shchepin", "Ejabberd vCard modul\nCopyright (c) 2003-2005 Alexey Shchepin"}.
{"JID", "JID"}.
% ejabberd_c2s.erl
{"Use of STARTTLS required", "Použitie STARTTLS je vyžadované"}.
{"Replaced by new connection", "Nahradené novým spojením"}.
% mod_configure.erl
{"DB Tables Configuration at ", "Databázové tabuľky s konfiguráciou na "}.
% mod_vcard_ldap.erl
{"Given Name", "Meno"}.
% mod_pubsub/mod_pubsub.erl
{"ejabberd pub/sub module\nCopyright (c) 2003-2005 Alexey Shchepin", "Ejabberd pub/sub modul\nCopyright (c) 2003-2005 Alexey Shchepin"}.
{[], " "}.
{"Node Creator", "Tvorca uzlu"}.
{"Deliver payloads with event notifications", "Doručovanie payload s upozorňovaním na udalosti"}.
{"Notify subscribers when the node configuration changes", "Upozorniť prihlásených používateľov na zmenu nastavenia uzlu"}.
{"Notify subscribers when the node is deleted", "Upozorniť prihlásených používateľov na zmazanie uzlu"}.
{"Notify subscribers when items are removed from the node", "Upozorniť prihlásených používateľov na odstránenie položiek z uzlu"}.
{"Persist items to storage", "Uložiť položky natrvalo do úložiska"}.
{"Max # of items to persist", "Maximálny počet položiek, ktoré je možné natrvalo uložiť"}.
{"Whether to allow subscriptions", "Povoliť prihlasovanie"}.
{"Specify the subscriber model", "Špecifikovať prihlasovací model"}.
{"Specify the publisher model", "Špecifikovať model publikovania"}.
{"Max payload size in bytes", "Maximálny payload v bajtoch"}.
{"Send items to new subscribers", "Odoslať položky novým používateľom"}.
{"Only deliver notifications to available users", "Doručovať upozornenia len aktuálne prihláseným používateľom"}.
{"Specify the current subscription approver", "Zadať súčasného schvaľovateľa prihlásení "}.
% web/ejabberd_web_admin.erl
{"ejabberd (c) 2002-2005 Alexey Shchepin, 2004-2005 Process One", "Ejabberd (c) 2002-2005 Alexey Shchepin, 2004-2005 Process One"}.
{"(raw)", "(raw)"}.
{"raw", "raw"}.
{"Authenticated users", "Autentifikovaný používatelia"}.
% mod_irc/mod_irc.erl
{"ejabberd IRC module\nCopyright (c) 2003-2005 Alexey Shchepin", "Ejabberd IRC module\nCopyright (c) 2003-2005 Alexey Shchepin"}.
{"If you want to specify different encodings for IRC servers, fill this list with values in format '{\"irc server\", \"encoding\"}'. By default this service use \"~s\" encoding.", "Ak chcete zadať iné kódovania pre IRC servery, vyplnte zoznam s hodnotami vo formáte '{\"irc server\",\"encoding\"}'. Predvolené kódovanie pre túto službu je \"~s\"."}.
% mod_muc/mod_muc.erl
{"Room creation is denied by service policy", "Vytváranie miestnosti nie je povolené"}.
{"ejabberd MUC module\nCopyright (c) 2003-2005 Alexey Shchepin", "Ejabberd MUC modul\nCopyright (c) 2003-2005 Alexey Shchepin"}.
% Local Variables:
% mode: erlang
% End:
% /usr/home/src/ejabberd/ejabberd/src/mod_vcard_odbc.erl
{"Erlang Jabber Server\nCopyright (c) 2002-2006 Alexey Shchepin", "Erlang Jabber Server\nCopyright (c) 2002-2006 Alexey Shchepin"}.
{"Email", "E-mail"}.
{"ejabberd vCard module\nCopyright (c) 2003-2006 Alexey Shchepin", "Ejabberd vCard modul\nCopyright (c) 2003-2006 Alexey Shchepin"}.
{"Search Results for ", "Hľadať výsledky pre "}.
{"Jabber ID", "Jabber ID"}.
% /usr/home/src/ejabberd/ejabberd/src/mod_adhoc.erl
{"Commands", "Príkazy"}.
{"Ping", "Ping"}.
{"Pong", "Pong"}.
% /usr/home/src/ejabberd/ejabberd/src/ejabberd_c2s.erl
{"Replaced by new connection", "Nahradené novým spojením"}.
% /usr/home/src/ejabberd/ejabberd/src/mod_announce.erl
{"Really delete message of the day?", "Skutočne zmazať správu dňa?"}.
{"Subject", "Predmet"}.
{"Message body", "Telo správy"}.
{"No body provided for announce message", "Správa neobsahuje text"}.
{"Announcements", "Oznámenia"}.
{"Send announcement to all users", "Odoslať oznam všetkým používateľom"}.
{"Send announcement to all online users", "Odoslať zoznam všetkým online používateľom"}.
{"Send announcement to all online users on all hosts", "Odoslať oznam všetkým online používateľom na všetkých serveroch"}.
{"Set message of the day and send to online users", "Nastaviť správu dňa a odoslať ju online používateľom"}.
{"Update message of the day (don't send)", "Aktualizovať správu dňa (neodosielať)"}.
{"Delete message of the day", "Zmazať správu dňa"}.
% /usr/home/src/ejabberd/ejabberd/src/mod_configure.erl
{"Database", "Databáza"}.
{"Outgoing s2s Connections", "Odchdazájuce s2s spojenie"}.
{"Import Users From jabberd 1.4 Spool Files", "Importovať používateľov z jabber 1.4 spool súborov"}.
{"Database Tables Configuration at ", "Konfigurácia databázových tabuliek "}.
% /usr/home/src/ejabberd/ejabberd/src/mod_pubsub/mod_pubsub.erl
{"ejabberd pub/sub module\nCopyright (c) 2003-2006 Alexey Shchepin", "ejabberd pub/sub modul\nCopyright (c) 2003-2006 Alexey Shchepin"}.
% /usr/home/src/ejabberd/ejabberd/src/web/ejabberd_web_admin.erl
{"ejabberd Web Interface", "Ejabberd Web rozhranie"}.
{"Administration", "Administrácia"}.
{"ejabberd (c) 2002-2006 Alexey Shchepin, 2004-2006 Process One", "Ejabberd (c) 2002-2006 Alexey Shchepin, 2004-2006 Process One"}.
{"(Raw)", "(Raw)"}.
{"Submitted", "Odoslané"}.
{"Bad format", "Zlý formát"}.
{"Raw", "Raw"}.
{"Users Last Activity", "Posledná aktivita používateľa"}.
{"Registered Users", "Registrovaní používatelia"}.
{"Offline Messages", "Offline správy"}.
{"Registered Users:", "Registrovaní používatelia:"}.
{"Authenticated Users:", "Autentifikovaný používatelia:"}.
{"Online Users:", "Online používatelia:"}.
{"Outgoing s2s Connections:", "Odchádzajúce s2s spojenia:"}.
{"Outgoing s2s Servers:", "Odchádzajúce s2s servery:"}.
{"Offline Messages:", "Offline správy"}.
{"~s's Offline Messages Queue", "~s Offline správy"}.
{"Add Jabber ID", "Pridať JID"}.
{"No Data", "Žiadne dáta"}.
{"Listened Ports", "Otvorené portov"}.
{"RPC Call Error", "Chyba RPC volania"}.
{"Database Tables at ", "Databázové tabuľky na "}.
{"Backup of ", "Záloha na "}.
{"Remark that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately.", "Podotýkame, že tieto nastavenia budú zálohované do zabudovanej Mnesia databázy. Ak používate ODBC modul, musíte zálohovať vašu SQL databázu separátne."}.
{"Store binary backup:", "Uložiť binárnu zálohu:"}.
{"Restore binary backup immediately:", "Okamžite obnoviť binárnu zálohu:"}.
{"Restore binary backup after next ejabberd restart (requires less memory):", "Obnoviť binárnu zálohu pri nasledujúcom reštarte Ejabberd (vyžaduje menej pamäte)"}.
{"Store plain text backup:", "Uložiť zálohu do textového súboru:"}.
{"Restore plain text backup immediately:", "Okamžite obnoviť zálohu z textového súboru:"}.
{"Statistics of ~p", "Štatistiky ~p"}.
{"Uptime:", "Uptime"}.
{"CPU Time:", "Čas procesoru"}.
{"Transactions Commited:", "Transakcie potvrdená"}.
{"Transactions Aborted:", "Transakcie zrušená"}.
{"Transactions Restarted:", "Transakcie reštartovaná"}.
{"Transactions Logged:", "Transakcie zaznamenaná"}.
{"Update ", "Aktualizovať "}.
{"Update plan", "Aktualizovať plán"}.
{"Updated modules", "Aktualizované moduly"}.
{"Update script", "Aktualizované skripty"}.
{"Low level update script", "Nízkoúrovňový aktualizačný skript"}.
{"Script check", "Kontrola skriptu"}.
{"Not Found", "Nenájdené"}.
{"Shared Roster Groups", "Skupiny pre zdieľaný zoznam kontaktov"}.
% /usr/home/src/ejabberd/ejabberd/src/mod_irc/mod_irc.erl
{"ejabberd IRC module\nCopyright (c) 2003-2006 Alexey Shchepin", "Ejabberd IRC modul\nCopyright (c) 2003-2006 Alexey Shchepin"}.
% /usr/home/src/ejabberd/ejabberd/src/mod_muc/mod_muc_log.erl
{"Chatroom configuration modified", "Nastavenie diskusnej miestnosti bolo zmenené"}.
{"joins the room", "vstúpil(a) do miestnosti"}.
{"leaves the room", "odišiel(a) z miestnosti"}.
{"has been kicked", "bol(a) vyhodený(á) z miestnosti"}.
{"has been banned", "bol(a) zablokovaný(á)"}.
{"is now known as", "sa premenoval(a) na"}.
{"Monday", "Pondelok"}.
{"Tuesday", "Utorok"}.
{"Wednesday", "Streda"}.
{"Thursday", "Štvrtok"}.
{"Friday", "Piatok"}.
{"Saturday", "Sobota"}.
{"Sunday", "Nedeľa"}.
{"January", "Január"}.
{"February", "Február"}.
{"March", "Marec"}.
{"April", "Apríl"}.
{"May", "Máj"}.
{"June", "Jún"}.
{"July", "Júl"}.
{"August", "August"}.
{"September", "September"}.
{"October", "Október"}.
{"November", "November"}.
{"December", "December"}.
{"Room Configuration", "Nastavenia miestnosti"}.
% /usr/home/src/ejabberd/ejabberd/src/mod_muc/mod_muc.erl
{"You must fill in field \"Nickname\" in the form", "Musíte vyplniť políčko \"Prezývka\" vo formulári"}.
{"ejabberd MUC module\nCopyright (c) 2003-2006 Alexey Shchepin", "Ejabberd MUC modul\nCopyright (c) 2003-2006 Alexey Shchepin"}.
% /usr/home/src/ejabberd/ejabberd/src/mod_muc/mod_muc_room.erl
{"This room is not anonymous", "Táto miestnosť nie je anonymná"}.
{"Make room persistent", "Nastaviť miestnosť ako trvalú"}.
{"Make room public searchable", "Nastaviť miestnosť ako verejne prehľadávateľnú"}.
{"Make participants list public", "Nastaviť zoznam zúčastnených ako verejný"}.
{"Make room password protected", "Chrániť miestnosť heslom"}.
{"Make room semianonymous", "Nastaviť miestnosť ako čiastočne anonymnú"}.
{"Make room members-only", "Nastaviť miestnosť len pre členov"}.
{"Make room moderated", "Nastaviť miestnosť ako moderovanú"}.
{"Default users as participants", "Používatelia sú implicitne členmi"}.
{"Allow users to change subject", "Povoliť používateľom zmeniť tému tejto miestnosti"}.
{"Allow users to send private messages", "Povoliť používateľom odosielať súkromné správy"}.
{"Allow users to query other users", "Povoliť používateľom odosielať požiadavky (query) ostatným používateľom"}.
{"Allow users to send invites", "povoliť používateľom posielanie pozvánok"}.
{"Enable logging", "Zapnúť zaznamenávanie histórie"}.
{"Description", "Popis"}.
{"Number of occupants", "Počet zúčastnených"}.
+1 -3
View File
@@ -210,9 +210,7 @@
"Дозволити користувачам надсилати запрошення"}.
{"Make room password protected", "Зробити кімнату захищеною паролем"}.
{"Password", "Пароль"}.
{"Present real JIDs to", "Зробити реальні JID учасників видимими"}.
{"moderators only", "тільки модераторам"}.
{"anyone", "всім учасникам"}.
{"Make room semianonymous", "Зробити кімнату напіванонімною"}.
{"Enable logging", "Включити журнал роботи"}.
{"Only moderators and participants are allowed to change subject in this room",
"Тільки модератори та учасники можуть змінювати тему в цій кімнаті"}.
+2 -3
View File
@@ -13,13 +13,12 @@ OUTDIR = ..
EFLAGS = -I .. -pz ..
OBJS = \
$(OUTDIR)/ejabberd_odbc.beam \
$(OUTDIR)/ejabberd_odbc_sup.beam \
$(OUTDIR)/odbc_queries.beam
$(OUTDIR)/ejabberd_odbc_sup.beam
all: $(OBJS)
$(OUTDIR)/%.beam: %.erl
@ERLC@ -W $(EFLAGS) -D@db_type@ -o $(OUTDIR) $<
@ERLC@ -W $(EFLAGS) -o $(OUTDIR) $<
clean:
+1 -6
View File
@@ -6,8 +6,7 @@ EFLAGS = -I .. -pz ..
OBJS = \
$(OUTDIR)\ejabberd_odbc.beam \
$(OUTDIR)\ejabberd_odbc_sup.beam \
$(OUTDIR)\odbc_queries.beam
$(OUTDIR)\ejabberd_odbc_sup.beam
ALL : $(OBJS)
@@ -19,7 +18,3 @@ $(OUTDIR)\ejabberd_odbc.beam : ejabberd_odbc.erl
$(OUTDIR)\ejabberd_odbc_sup.beam : ejabberd_odbc_sup.erl
erlc -W $(EFLAGS) -o $(OUTDIR) ejabberd_odbc_sup.erl
$(OUTDIR)\odbc_queries.beam : odbc_queries.erl
erlc -W $(EFLAGS) -o $(OUTDIR) -D$(DBTYPE) odbc_queries.erl
+11 -2
View File
@@ -87,7 +87,16 @@ sql_query_t(Query) ->
%% Escape character that will confuse an SQL engine
escape(S) when is_list(S) ->
[odbc_queries:escape(C) || C <- S].
[escape(C) || C <- S];
escape($\0) -> "\\0";
escape($\n) -> "\\n";
escape($\t) -> "\\t";
escape($\b) -> "\\b";
escape($\r) -> "\\r";
escape($') -> "\\'";
escape($") -> "\\\"";
escape($\\) -> "\\\\";
escape(C) -> C.
%% Escape character that will confuse an SQL engine
%% Percent and underscore only need to be escaped for pattern matching like
@@ -96,7 +105,7 @@ escape_like(S) when is_list(S) ->
[escape_like(C) || C <- S];
escape_like($%) -> "\\%";
escape_like($_) -> "\\_";
escape_like(C) -> odbc_queries:escape(C).
escape_like(C) -> escape(C).
%%%----------------------------------------------------------------------
-899
View File
@@ -1,899 +0,0 @@
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
exec sp_dboption N'ejabberd', N'autoclose', N'false'
GO
exec sp_dboption N'ejabberd', N'bulkcopy', N'true'
GO
exec sp_dboption N'ejabberd', N'trunc. log', N'false'
GO
exec sp_dboption N'ejabberd', N'torn page detection', N'true'
GO
exec sp_dboption N'ejabberd', N'read only', N'false'
GO
exec sp_dboption N'ejabberd', N'dbo use', N'false'
GO
exec sp_dboption N'ejabberd', N'single', N'false'
GO
exec sp_dboption N'ejabberd', N'autoshrink', N'false'
GO
exec sp_dboption N'ejabberd', N'ANSI null default', N'false'
GO
exec sp_dboption N'ejabberd', N'recursive triggers', N'false'
GO
exec sp_dboption N'ejabberd', N'ANSI nulls', N'false'
GO
exec sp_dboption N'ejabberd', N'concat null yields null', N'false'
GO
exec sp_dboption N'ejabberd', N'cursor close on commit', N'false'
GO
exec sp_dboption N'ejabberd', N'default to local cursor', N'false'
GO
exec sp_dboption N'ejabberd', N'quoted identifier', N'false'
GO
exec sp_dboption N'ejabberd', N'ANSI warnings', N'false'
GO
exec sp_dboption N'ejabberd', N'auto create statistics', N'true'
GO
exec sp_dboption N'ejabberd', N'auto update statistics', N'true'
GO
use [ejabberd]
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[last]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[last]
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[rostergroups]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[rostergroups]
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[rosterusers]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[rosterusers]
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[spool]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[spool]
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[users]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[users]
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[vcard]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[vcard]
GO
CREATE TABLE [dbo].[last] (
[username] [varchar] (250) NOT NULL ,
[seconds] [varchar] (50) NOT NULL ,
[state] [varchar] (100) NULL ,
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[rostergroups] (
[username] [varchar] (250) NOT NULL ,
[jid] [varchar] (250) NOT NULL ,
[grp] [varchar] (100) NOT NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[rosterusers] (
[username] [varchar] (250) NOT NULL ,
[jid] [varchar] (250) NOT NULL ,
[nick] [varchar] (50) NULL ,
[subscription] [char] (1) NOT NULL ,
[ask] [char] (1) NOT NULL ,
[askmessage] [varchar] (250) NULL ,
[server] [char] (1) NOT NULL ,
[subscribe] [varchar] (200) NULL ,
[type] [varchar] (50) NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[spool] (
[id] [numeric](19, 0) IDENTITY (1, 1) NOT NULL ,
[username] [varchar] (250) NOT NULL ,
[xml] [text] NULL ,
[notifyprocessed] [bit] NULL ,
[created] [datetime] NULL ,
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
CREATE TABLE [dbo].[users] (
[username] [varchar] (250) NOT NULL ,
[password] [varchar] (50) NOT NULL ,
[created] [datetime] NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[vcard] (
[username] [varchar] (250) NOT NULL ,
[full_name] [varchar] (250) NULL ,
[first_name] [varchar] (50) NULL ,
[last_name] [varchar] (50) NULL ,
[nick_name] [varchar] (50) NULL ,
[url] [varchar] (1024) NULL ,
[address1] [varchar] (50) NULL ,
[address2] [varchar] (50) NULL ,
[locality] [varchar] (50) NULL ,
[region] [varchar] (50) NULL ,
[pcode] [varchar] (50) NULL ,
[country] [varchar] (50) NULL ,
[telephone] [varchar] (50) NULL ,
[email] [varchar] (250) NULL ,
[orgname] [varchar] (50) NULL ,
[orgunit] [varchar] (50) NULL ,
[title] [varchar] (50) NULL ,
[role] [varchar] (50) NULL ,
[b_day] [datetime] NULL ,
[descr] [varchar] (500) NULL
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[last] WITH NOCHECK ADD
CONSTRAINT [PK_last] PRIMARY KEY CLUSTERED
(
[username]
) WITH FILLFACTOR = 90 ON [PRIMARY]
GO
ALTER TABLE [dbo].[rostergroups] WITH NOCHECK ADD
CONSTRAINT [PK_rostergroups] PRIMARY KEY CLUSTERED
(
[username],
[jid],
[grp]
) WITH FILLFACTOR = 90 ON [PRIMARY]
GO
ALTER TABLE [dbo].[spool] WITH NOCHECK ADD
CONSTRAINT [PK_spool] PRIMARY KEY CLUSTERED
(
[username],
[id]
) WITH FILLFACTOR = 90 ON [PRIMARY]
GO
ALTER TABLE [dbo].[users] WITH NOCHECK ADD
CONSTRAINT [PK_users] PRIMARY KEY CLUSTERED
(
[username]
) WITH FILLFACTOR = 90 ON [PRIMARY]
GO
ALTER TABLE [dbo].[vcard] WITH NOCHECK ADD
CONSTRAINT [PK_vcard] PRIMARY KEY CLUSTERED
(
[username]
) WITH FILLFACTOR = 90 ON [PRIMARY]
GO
CREATE CLUSTERED INDEX [IX_rosterusers_user] ON [dbo].[rosterusers]([username]) WITH FILLFACTOR = 90 ON [PRIMARY]
GO
ALTER TABLE [dbo].[last] WITH NOCHECK ADD
CONSTRAINT [DF_last_updated] DEFAULT (getdate()) FOR [Modify_Date]
GO
ALTER TABLE [dbo].[spool] WITH NOCHECK ADD
CONSTRAINT [DF_spool_notifyprocessed] DEFAULT (0) FOR [notifyprocessed],
CONSTRAINT [DF_spool_created] DEFAULT (getdate()) FOR [created],
CONSTRAINT [DF_spool_MustDelete] DEFAULT (0) FOR [MustDelete]
GO
ALTER TABLE [dbo].[users] WITH NOCHECK ADD
CONSTRAINT [DF_users_created] DEFAULT (getdate()) FOR [created]
GO
CREATE INDEX [IX_rostergroups_jid] ON [dbo].[rostergroups]([jid]) WITH FILLFACTOR = 90 ON [PRIMARY]
GO
CREATE INDEX [IX_rostergroups_user] ON [dbo].[rostergroups]([username]) WITH FILLFACTOR = 90 ON [PRIMARY]
GO
CREATE INDEX [IX_rosterusers_jid] ON [dbo].[rosterusers]([username], [jid]) WITH FILLFACTOR = 90 ON [PRIMARY]
GO
CREATE INDEX [IX_spool_user] ON [dbo].[spool]([username]) WITH FILLFACTOR = 90 ON [PRIMARY]
GO
CREATE INDEX [IX_spool_process] ON [dbo].[spool]([created], [notifyprocessed]) WITH FILLFACTOR = 90 ON [PRIMARY]
GO
CREATE INDEX [IK_Spool_Del] ON [dbo].[spool]([MustDelete]) WITH FILLFACTOR = 90 ON [PRIMARY]
GO
CREATE INDEX [IK_Spool_Created] ON [dbo].[spool]([created]) WITH FILLFACTOR = 90 ON [PRIMARY]
GO
/*********************************************************/
/** These store procedures are for use with ejabberd **/
/** 1.1 and Microsoft Sql Server 2000 **/
/** **/
/** The stored procedures reduce the need to sql **/
/** compilation of the database and also allow for also **/
/** provide each of database integration. The store **/
/** procedure have been optimized to increase database **/
/** performance and a reduction of 80% in CPU was **/
/** achive over the use of standard sql. **/
/*********************************************************/
/****** Object: StoredProcedure [dbo].[add_roster] ******/
/** Add or update user entries in the roster **/
/*********************************************************/
CREATE PROCEDURE [dbo].[add_roster]
@Username varchar(250),
@JID varchar(250),
@Nick varchar(50),
@Subscription char(1),
@Ask char(1),
@AskMessage varchar(250),
@Server char(1),
@Subscribe varchar(200),
@Type varchar(50),
@Grp varchar(100)
AS
BEGIN
BEGIN TRANSACTION
--- Update Roster if user exist else add roster item
IF EXISTS (SELECT username FROM rosterusers WITH (NOLOCK) WHERE rosterusers.username=@Username AND rosterusers.jid=@JID)
BEGIN
UPDATE rosterusers
SET rosterusers.username=@Username,
rosterusers.jid=@JID,
rosterusers.nick=@Nick,
rosterusers.subscription=@Subscription,
rosterusers.ask=@Ask,
rosterusers.askmessage=@AskMessage,
rosterusers.server=@Server,
rosterusers.subscribe=@Subscribe,
rosterusers.type=@Type
WHERE (rosterusers.username=@Username) AND (rosterusers.jid=@JID);
END
ELSE
BEGIN
INSERT INTO rosterusers
( rosterusers.username,
rosterusers.jid,
rosterusers.nick,
rosterusers.subscription,
rosterusers.ask,
rosterusers.askmessage,
rosterusers.server,
rosterusers.subscribe,
rosterusers.type
)
VALUES
( @Username,
@JID,
@Nick,
@Subscription,
@Ask,
@AskMessage,
@Server,
@Subscribe,
@Type
);
END
--- Update Roster Groups if exist else add group entry
IF NOT EXISTS (SELECT username FROM rostergroups WITH (NOLOCK) WHERE rostergroups.username=@Username AND rostergroups.jid=@JID AND rostergroups.grp=@Grp)
BEGIN
INSERT INTO rostergroups
( rostergroups.username,
rostergroups.jid,
rostergroups.grp
)
VALUES
( @Username,
@JID,
@Grp
);
END
COMMIT
END
GO
/***************************************************************/
/****** Object: StoredProcedure [dbo].[add_roster_group] ******/
/** Add or update user group entries in the roster groups **/
/***************************************************************/
CREATE PROCEDURE [dbo].[add_roster_group]
@Username varchar(250),
@JID varchar(250),
@Grp varchar(100)
AS
BEGIN
--- Update Roster Groups if exist else add group
IF NOT EXISTS (SELECT username FROM rostergroups WHERE rostergroups.username=@Username AND rostergroups.jid=@JID AND rostergroups.grp=@Grp)
BEGIN
INSERT INTO rostergroups
( rostergroups.username,
rostergroups.jid,
rostergroups.grp
)
VALUES
( @Username,
@JID,
@Grp
)
END
END
GO
/***************************************************************/
/****** Object: StoredProcedure [dbo].[add_roster_user] ******/
/** Add or update user entries in the roster **/
/***************************************************************/
CREATE PROCEDURE [dbo].[add_roster_user]
@Username varchar(250),
@JID varchar(250),
@Nick varchar(50),
@Subscription char(1),
@Ask char(1),
@AskMessage varchar(250),
@Server char(1),
@Subscribe varchar(200),
@Type varchar(50),
@Grp varchar(100) = Null
AS
BEGIN
BEGIN TRANSACTION
--- Update Roster Users if exist of add new user
IF EXISTS (SELECT username FROM rosterusers WHERE rosterusers.username=@Username AND rosterusers.jid=@JID)
BEGIN
UPDATE rosterusers
SET rosterusers.username=@Username,
rosterusers.jid=@JID,
rosterusers.nick=@Nick,
rosterusers.subscription=@Subscription,
rosterusers.ask=@Ask,
rosterusers.askmessage=@AskMessage,
rosterusers.server=@Server,
rosterusers.subscribe=@Subscribe,
rosterusers.type=@Type
WHERE (rosterusers.username=@Username) AND (rosterusers.jid=@JID);
END
ELSE
BEGIN
INSERT INTO rosterusers
( rosterusers.username,
rosterusers.jid,
rosterusers.nick,
rosterusers.subscription,
rosterusers.ask,
rosterusers.askmessage,
rosterusers.server,
rosterusers.subscribe,
rosterusers.type
)
VALUES
( @Username,
@JID,
@Nick,
@Subscription,
@Ask,
@AskMessage,
@Server,
@Subscribe,
@Type
);
END
--- Update Roster Group if exist of add new group
IF @Grp IS NOT NULL
EXECUTE [dbo].[add_roster_group] @Username, @JID, @Grp
COMMIT
END
GO
/***************************************************************/
/****** Object: StoredProcedure [dbo].[del_roster_groups] ******/
/** Remove user group entries from the roster groups table **/
/***************************************************************/
CREATE PROCEDURE [dbo].[del_roster_groups]
@Username varchar(250),
@JID varchar(250)
AS
BEGIN
DELETE FROM rostergroups
WITH (ROWLOCK)
WHERE (rostergroups.username = @Username) AND (rostergroups.jid = @JID);
END
GO
/***************************************************************/
/****** Object: StoredProcedure [dbo].[add_spool] ******/
/** Add a entry to the spool table **/
/***************************************************************/
CREATE PROCEDURE [dbo].[add_spool]
@Username varchar(250),
@XML varchar(8000)
AS
BEGIN
INSERT INTO spool
( spool.username,
spool.xml
)
VALUES
( @Username,
@XML
)
END
GO
/***************************************************************/
/****** Object: StoredProcedure [dbo].[add_user] ******/
/** Add or update user entries to jabber **/
/***************************************************************/
CREATE PROCEDURE [dbo].[add_user]
@Username varchar(200),
@Password varchar(50)
AS
BEGIN
INSERT INTO users
( username,
[password]
)
VALUES
( @Username,
@Password
);
END
GO
/******************************************************************/
/****** Object: StoredProcedure [dbo].[set_password] **/
/** Update users password **/
/******************************************************************/
CREATE PROCEDURE [dbo].[set_password]
@Username varchar(200),
@Password varchar(50)
AS
BEGIN
IF EXISTS (SELECT username FROM users WITH (NOLOCK) WHERE username=@Username)
BEGIN
UPDATE users SET username=@Username, password=@Password WHERE username=@Username;
END
ELSE
BEGIN
INSERT INTO users (username, password) VALUES (@Username, @Password);
END
END
GO
/******************************************************************/
/****** Object: StoredProcedure [dbo].[get_password] **/
/** Retrive the user password **/
/******************************************************************/
CREATE PROCEDURE [dbo].[get_password]
@Username varchar(200)
AS
BEGIN
SELECT users.password as password
FROM users WITH (NOLOCK)
WHERE username=@Username;
END
GO
/***************************************************************/
/****** Object: StoredProcedure [dbo].[clean_spool_msg] ******/
/** Delete messages older that 3 days from spool **/
/***************************************************************/
CREATE PROCEDURE [dbo].[clean_spool_msg]
AS
DECLARE
@dt datetime,
@myRowCount int
BEGIN
-- Delete small amounts because if locks the database table
SET ROWCOUNT 500
SET @myRowCount = 1
WHILE (@myRowCount) > 0
BEGIN
BEGIN TRANSACTION
SELECT @dt = DATEADD(d, -3, GETDATE())
DELETE FROM spool
WITH (ROWLOCK)
WHERE (MustDelete=1) OR (Created < @dt);
SET @myRowCount = @@RowCount
COMMIT
END
END
GO
/***************************************************************/
/****** Object: StoredProcedure [dbo].[del_last] ******/
/** Delete an entry from the last table **/
/***************************************************************/
CREATE PROCEDURE [dbo].[del_last]
@Username varchar(250)
AS
BEGIN
DELETE FROM [last]
WITH (ROWLOCK)
WHERE [last].username=@Username;
END
GO
/***************************************************************/
/****** Object: StoredProcedure [dbo].[del_roster] ******/
/** Delete an entry from the roster **/
/***************************************************************/
CREATE PROCEDURE [dbo].[del_roster]
@Username varchar(250),
@JID varchar(250)
AS
BEGIN
BEGIN TRANSACTION
DELETE FROM rosterusers
WITH (ROWLOCK)
WHERE (rosterusers.username = @Username) AND (rosterusers.jid = @JID);
DELETE FROM rostergroups
WITH (ROWLOCK)
WHERE (rostergroups.username = @Username) AND (rostergroups.jid = @JID);
COMMIT
END
GO
/***************************************************************/
/****** Object: StoredProcedure [dbo].[del_spool_msg] ******/
/** Delete an entry from the spool table **/
/***************************************************************/
CREATE PROCEDURE [dbo].[del_spool_msg]
@Username varchar(250)
AS
BEGIN
DELETE FROM spool
WITH (ROWLOCK)
WHERE spool.username=@Username;
END
GO
/***************************************************************/
/****** Object: StoredProcedure [dbo].[del_user] ******/
/** Delete an entry from the user table **/
/***************************************************************/
CREATE PROCEDURE [dbo].[del_user]
@Username varchar(200)
AS
BEGIN
DELETE FROM users
WITH (ROWLOCK)
WHERE username=@Username;
END
GO
/******************************************************************/
/****** Object: StoredProcedure [dbo].[del_user_return_password]**/
/** Delete an entry from the user table and return user password **/
/******************************************************************/
CREATE PROCEDURE [dbo].[del_user_return_password]
@Username varchar(250)
AS
DECLARE
@Pwd varchar(50)
BEGIN
EXECUTE @Pwd = dbo.get_password @Username
DELETE FROM users
WITH (ROWLOCK)
WHERE username=@Username
SELECT @Pwd;
END
GO
/******************************************************************/
/****** Object: StoredProcedure [dbo].[del_user_roster] **/
/** Delete the users roster **/
/******************************************************************/
CREATE PROCEDURE [dbo].[del_user_roster]
@Username varchar(250)
AS
BEGIN
BEGIN TRANSACTION
DELETE FROM rosterusers
WITH (ROWLOCK)
WHERE rosterusers.username = @Username;
DELETE FROM rostergroups
WITH (ROWLOCK)
WHERE rostergroups.username = @Username;
COMMIT
END
GO
/******************************************************************/
/****** Object: StoredProcedure [dbo].[get_and_del_spool_msg] **/
/** Fetch and delete the users offline messages **/
/******************************************************************/
CREATE PROCEDURE [dbo].[get_and_del_spool_msg]
@Username varchar(250)
AS
DECLARE
@vSpool table( username varchar(1),
xml varchar(1))
BEGIN
IF EXISTS (SELECT username FROM spool with (nolock) WHERE spool.username=@Username)
BEGIN
SELECT spool.username AS username,
spool.xml AS xml
FROM spool WITH (NOLOCK)
WHERE spool.username=@Username;
DELETE spool
WITH (ROWLOCK)
WHERE spool.username=@Username
END
ELSE
BEGIN
SELECT * FROM @vSpool;
END
END
GO
/******************************************************************/
/****** Object: StoredProcedure [dbo].[get_last] **/
/** Retrive the last user login **/
/******************************************************************/
CREATE PROCEDURE [dbo].[get_last]
@Username varchar(250)
AS
BEGIN
SELECT last.seconds AS seconds,
last.state AS state
FROM last WITH (NOLOCK)
WHERE last.username=@Username;
END
GO
/******************************************************************/
/****** Object: StoredProcedure [dbo].[get_roster] **/
/** Retrive the user roster **/
/******************************************************************/
CREATE PROCEDURE [dbo].[get_roster]
@Username varchar(200)
AS
DECLARE
@vRosterusers table( username varchar(1),
jid varchar(1),
nick varchar(1),
subscription varchar(1),
ask varchar(1),
askmessage varchar(1),
server varchar(1),
subscribe varchar(1),
type varchar(1))
BEGIN
IF EXISTS (SELECT username FROM rosterusers with (nolock) WHERE rosterusers.username = @Username)
BEGIN
SELECT rosterusers.username AS username,
rosterusers.jid AS jid,
rosterusers.nick AS nick,
rosterusers.subscription AS subscription,
rosterusers.ask AS ask,
rosterusers.askmessage AS askmessage,
rosterusers.server AS server,
rosterusers.subscribe AS subscribe,
rosterusers.type AS type
FROM rosterusers WITH (NOLOCK)
WHERE rosterusers.username = @Username;
END
ELSE
BEGIN
SELECT * FROM @vRosterusers
END
END
GO
/******************************************************************/
/****** Object: StoredProcedure [dbo].[get_roster_by_jid] **/
/** Retrive the user roster via JID **/
/******************************************************************/
CREATE PROCEDURE [dbo].[get_roster_by_jid]
@Username varchar(200),
@JID varchar(250)
AS
DECLARE
@vRosterusers table( username varchar(1),
jid varchar(1),
nick varchar(1),
subscription varchar(1),
ask varchar(1),
askmessage varchar(1),
server varchar(1),
subscribe varchar(1),
type varchar(1))
BEGIN
IF EXISTS (SELECT username FROM rosterusers with (nolock) WHERE (rosterusers.username = @Username) AND (rosterusers.jid = @JID))
BEGIN
SELECT rosterusers.username AS username,
rosterusers.jid AS jid,
rosterusers.nick AS nick,
rosterusers.subscription AS subscription,
rosterusers.ask AS ask,
rosterusers.askmessage AS askmessage,
rosterusers.server AS server,
rosterusers.subscribe AS subscribe,
rosterusers.type AS type
FROM rosterusers WITH (NOLOCK)
WHERE (rosterusers.username = @Username) AND (rosterusers.jid = @JID);
END
ELSE
BEGIN
SELECT * FROM @vRosterusers
END
END
GO
/******************************************************************/
/****** Object: StoredProcedure [dbo].[get_roster_jid_groups] **/
/** Retrieve the user roster groups **/
/******************************************************************/
CREATE PROCEDURE [dbo].[get_roster_jid_groups]
@Username varchar(200)
AS
DECLARE
@vrostergroups table( jid varchar(1),
grp varchar(1))
BEGIN
IF EXISTS (SELECT username FROM rostergroups with (nolock) WHERE rostergroups.username = @Username)
BEGIN
SELECT rostergroups.jid AS jid,
rostergroups.grp AS grp
FROM rostergroups WITH (NOLOCK)
WHERE rostergroups.username = @Username;
END
ELSE
BEGIN
SELECT * FROM @vrostergroups
END
END
GO
/******************************************************************/
/****** Object: StoredProcedure [dbo].[get_roster_groups] **/
/** Retrive the user roster groups **/
/******************************************************************/
CREATE PROCEDURE [dbo].[get_roster_groups]
@Username varchar(200),
@JID varchar(250)
AS
DECLARE
@vrostergroups table( grp varchar(1))
BEGIN
IF EXISTS (SELECT username FROM rostergroups with (nolock) WHERE rostergroups.username = @Username)
BEGIN
SELECT rostergroups.grp AS grp
FROM rostergroups WITH (NOLOCK)
WHERE (rostergroups.username = @Username) AND (rostergroups.jid = @JID);
END
ELSE
BEGIN
SELECT * FROM @vrostergroups
END
END
GO
/******************************************************************/
/****** Object: StoredProcedure [dbo].[get_rostergroup_by_jid] **/
/** Retrive the user roster groups via JID **/
/******************************************************************/
CREATE PROCEDURE [dbo].[get_rostergroup_by_jid]
@Username varchar(250),
@JID varchar(250)
AS
DECLARE
@vrostergroups table(grp varchar(1))
BEGIN
IF EXISTS (SELECT username FROM rostergroups with (nolock) WHERE rostergroups.username=@Username AND rostergroups.jid=@JID)
BEGIN
SELECT rostergroups.grp AS grp
FROM rostergroups WITH (NOLOCK)
WHERE rostergroups.username=@Username AND rostergroups.jid=@JID;
END
ELSE
BEGIN
SELECT * FROM @vrostergroups
END
END
GO
/******************************************************************/
/****** Object: StoredProcedure [dbo].[get_subscription] **/
/** Retrive the user subscription requests **/
/******************************************************************/
CREATE PROCEDURE [dbo].[get_subscription]
@Username varchar(250),
@JID varchar(250)
AS
DECLARE
@vrosterusers table( subscription varchar(1))
BEGIN
IF EXISTS (SELECT username FROM rosterusers with (nolock) WHERE rosterusers.username=@Username AND rosterusers.jid=@JID)
BEGIN
SELECT rosterusers.subscription AS subscription
FROM rosterusers WITH (NOLOCK)
WHERE rosterusers.username=@Username AND rosterusers.jid=@JID;
END
ELSE
BEGIN
SELECT * FROM @vrosterusers
END
END
GO
/******************************************************************/
/****** Object: StoredProcedure [dbo].[list_users] **/
/** Retrive a list of all users **/
/******************************************************************/
CREATE PROCEDURE [dbo].[list_users]
AS
BEGIN
SELECT users.username AS username FROM users WITH (NOLOCK);
END
GO
/******************************************************************/
/****** Object: StoredProcedure [dbo].[set_last] **/
/** Update users last login status **/
/******************************************************************/
CREATE PROCEDURE [dbo].[set_last]
@Username varchar(250),
@Seconds varchar(50),
@State varchar(100)
AS
BEGIN
IF EXISTS (SELECT username FROM [last] WITH (NOLOCK) WHERE username=@Username)
BEGIN
UPDATE [last]
SET [last].username = @Username,
[last].seconds = @Seconds,
[last].state = @State
WHERE last.username=@Username;
END
ELSE
BEGIN
INSERT INTO [last]
( [last].username,
[last].seconds,
[last].state
)
VALUES
( @Username,
@Seconds,
@State
)
END
END
GO
-3
View File
@@ -19,7 +19,6 @@ CREATE TABLE rosterusers (
nick text,
subscription character(1) NOT NULL,
ask character(1) NOT NULL,
askmessage text,
server character(1) NOT NULL,
subscribe text,
type text
@@ -92,5 +91,3 @@ CREATE INDEX i_vcard_search_lemail ON vcard_search(lemail);
CREATE INDEX i_vcard_search_lorgname ON vcard_search(lorgname);
CREATE INDEX i_vcard_search_lorgunit ON vcard_search(lorgunit);
--- To update from 1.x:
-- ALTER TABLE rosterusers ADD COLUMN askmessage text AFTER ask;
-434
View File
@@ -1,434 +0,0 @@
%% Copyrigh 2006, Process-one
%% This module is intended to take into account relational databases behaviour
%% differences
-module(odbc_queries).
-author("mickael.remond@process-one.net").
-export([get_db_type/0,
sql_transaction/2,
get_last/2,
set_last_t/4,
del_last/2,
get_password/2,
set_password_t/3,
add_user/3,
del_user/2,
del_user_return_password/3,
list_users/1,
add_spool_sql/2,
add_spool/2,
get_and_del_spool_msg_t/2,
del_spool_msg/2,
get_roster/2,
get_roster_jid_groups/2,
get_roster_groups/3,
del_user_roster_t/2,
get_roster_by_jid/3,
get_rostergroup_by_jid/3,
del_roster/3,
del_roster_sql/2,
update_roster/5,
update_roster_sql/4,
roster_subscribe/4,
get_subscription/3,
escape/1]).
%-define(generic, true).
%-define(mssql, true).
%% -----------------
%% Generic queries
-ifdef(generic).
get_db_type() ->
generic.
sql_transaction(LServer, F) ->
ejabberd_odbc:sql_transaction(LServer, F).
get_last(LServer, Username) ->
ejabberd_odbc:sql_query(
LServer,
["select seconds, state from last "
"where username='", Username, "'"]).
set_last_t(LServer, Username, Seconds, State) ->
%% MREMOND: I think this should be turn into a non transactional behaviour
ejabberd_odbc:sql_transaction(
LServer,
[["delete from last where username='", Username, "';"],
["insert into last(username, seconds, state) "
"values ('", Username, "', '", Seconds, "', '", State, "');"]]).
del_last(LServer, Username) ->
ejabberd_odbc:sql_query(
LServer,
["delete from last where username='", Username, "'"]).
get_password(LServer, Username) ->
ejabberd_odbc:sql_query(
LServer,
["select password from users "
"where username='", Username, "';"]).
set_password_t(LServer, Username, Pass) ->
ejabberd_odbc:sql_transaction(
LServer,
[["delete from users where username='", Username ,"';"],
["insert into users(username, password) "
"values ('", Username, "', '", Pass, "');"]]).
add_user(LServer, Username, Pass) ->
ejabberd_odbc:sql_query(
LServer,
["insert into users(username, password) "
"values ('", Username, "', '", Pass, "');"]).
del_user(LServer, Username) ->
ejabberd_odbc:sql_query(
LServer,
["delete from users where username='", Username ,"';"]).
del_user_return_password(_LServer, Username, Pass) ->
ejabberd_odbc:sql_query_t(
["select password from users where username='",
Username, "';"]),
ejabberd_odbc:sql_query_t(["delete from users "
"where username='", Username,
"' and password='", Pass, "';"]).
list_users(LServer) ->
ejabberd_odbc:sql_query(
LServer,
"select username from users").
add_spool_sql(Username, XML) ->
["insert into spool(username, xml) "
"values ('", Username, "', '",
XML,
"');"].
add_spool(LServer, Queries) ->
ejabberd_odbc:sql_transaction(
LServer, Queries).
get_and_del_spool_msg_t(LServer, Username) ->
F = fun() ->
Result = ejabberd_odbc:sql_query_t(
["select username, xml from spool where username='", Username, "'"
" order by seq;"]),
ejabberd_odbc:sql_query_t(
["delete from spool where username='", Username, "';"]),
Result
end,
ejabberd_odbc:sql_transaction(LServer,F).
del_spool_msg(LServer, Username) ->
ejabberd_odbc:sql_query(
LServer,
["delete from spool where username='", Username, "';"]).
get_roster(LServer, Username) ->
ejabberd_odbc:sql_query(
LServer,
["select username, jid, nick, subscription, ask, "
"askmessage, server, subscribe, type from rosterusers "
"where username='", Username, "'"]).
get_roster_jid_groups(LServer, Username) ->
ejabberd_odbc:sql_query(
LServer,
["select jid, grp from rostergroups "
"where username='", Username, "'"]).
get_roster_groups(_LServer, Username, SJID) ->
ejabberd_odbc:sql_query_t(
["select grp from rostergroups "
"where username='", Username, "' "
"and jid='", SJID, "';"]).
del_user_roster_t(LServer, Username) ->
ejabberd_odbc:sql_transaction(
LServer,
fun() ->
ejabberd_odbc:sql_query_t(
["delete from rosterusers "
" where username='", Username, "';"]),
ejabberd_odbc:sql_query_t(
["delete from rostergroups "
" where username='", Username, "';"])
end).
get_roster_by_jid(_LServer, Username, SJID) ->
ejabberd_odbc:sql_query_t(
["select username, jid, nick, subscription, "
"ask, askmessage, server, subscribe, type from rosterusers "
"where username='", Username, "' "
"and jid='", SJID, "';"]).
get_rostergroup_by_jid(LServer, Username, SJID) ->
ejabberd_odbc:sql_query(
LServer,
["select grp from rostergroups "
"where username='", Username, "' "
"and jid='", SJID, "'"]).
del_roster(_LServer, Username, SJID) ->
ejabberd_odbc:sql_query_t(
["delete from rosterusers "
" where username='", Username, "' "
" and jid='", SJID, "';"]),
ejabberd_odbc:sql_query_t(
["delete from rostergroups "
" where username='", Username, "' "
" and jid='", SJID, "';"]).
del_roster_sql(Username, SJID) ->
[["delete from rosterusers "
" where username='", Username, "' "
" and jid='", SJID, "';"],
["delete from rostergroups "
" where username='", Username, "' "
" and jid='", SJID, "';"]].
update_roster(_LServer, Username, SJID, ItemVals, ItemGroups) ->
ejabberd_odbc:sql_query_t(
["delete from rosterusers "
" where username='", Username, "' "
" and jid='", SJID, "';"]),
ejabberd_odbc:sql_query_t(
["insert into rosterusers("
" username, jid, nick, "
" subscription, ask, askmessage, "
" server, subscribe, type) "
" values (", ItemVals, ");"]),
ejabberd_odbc:sql_query_t(
["delete from rostergroups "
" where username='", Username, "' "
" and jid='", SJID, "';"]),
lists:foreach(fun(ItemGroup) ->
ejabberd_odbc:sql_query_t(
["insert into rostergroups("
" username, jid, grp) "
" values (", ItemGroup, ");"])
end,
ItemGroups).
update_roster_sql(Username, SJID, ItemVals, ItemGroups) ->
[["delete from rosterusers "
" where username='", Username, "' "
" and jid='", SJID, "';"],
["insert into rosterusers("
" username, jid, nick, "
" subscription, ask, askmessage"
" server, subscribe, type) "
" values (", ItemVals, ");"],
["delete from rostergroups "
" where username='", Username, "' "
" and jid='", SJID, "';"],
[["insert into rostergroups("
" username, jid, grp) "
" values (", ItemGroup, ");"] ||
ItemGroup <- ItemGroups]].
roster_subscribe(_LServer, Username, SJID, ItemVals) ->
ejabberd_odbc:sql_query_t(
["delete from rosterusers "
" where username='", Username, "' "
" and jid='", SJID, "';"]),
ejabberd_odbc:sql_query_t(
["insert into rosterusers("
" username, jid, nick, "
" subscription, ask, askmessage, "
" server, subscribe, type) "
" values (", ItemVals, ");"]).
get_subscription(LServer, Username, SJID) ->
ejabberd_odbc:sql_query(
LServer,
["select subscription from rosterusers "
"where username='", Username, "' "
"and jid='", SJID, "'"]).
%% Characters to escape
escape($\0) -> "\\0";
escape($\n) -> "\\n";
escape($\t) -> "\\t";
escape($\b) -> "\\b";
escape($\r) -> "\\r";
escape($') -> "\\'";
escape($") -> "\\\"";
escape($\\) -> "\\\\";
escape(C) -> C.
-endif.
%% -----------------
%% MSSQL queries
-ifdef(mssql).
get_db_type() ->
mssql.
sql_transaction(_LServer, F) ->
{atomic, catch F()}.
get_last(LServer, Username) ->
ejabberd_odbc:sql_query(
LServer,
["EXECUTE dbo.get_last '", Username, "'"]).
set_last_t(LServer, Username, Seconds, State) ->
Result = ejabberd_odbc:sql_query(
LServer,
["EXECUTE dbo.set_last '", Username, "', '", Seconds,
"', '", State, "'"]),
{atomic, Result}.
del_last(LServer, Username) ->
ejabberd_odbc:sql_query(
LServer,
["EXECUTE dbo.del_last '", Username, "'"]).
get_password(LServer, Username) ->
ejabberd_odbc:sql_query(
LServer,
["EXECUTE dbo.get_password '", Username, "'"]).
set_password_t(LServer, Username, Pass) ->
Result = ejabberd_odbc:sql_query(
LServer,
["EXECUTE dbo.set_password '", Username, "', '", Pass, "'"]),
{atomic, Result}.
add_user(LServer, Username, Pass) ->
ejabberd_odbc:sql_query(
LServer,
["EXECUTE dbo.add_user '", Username, "', '", Pass, "'"]).
del_user(LServer, Username) ->
ejabberd_odbc:sql_query(
LServer,
["EXECUTE dbo.del_user '", Username ,"'"]).
del_user_return_password(LServer, Username, Pass) ->
ejabberd_odbc:sql_query(
LServer,
["EXECUTE dbo.del_user_return_password '", Username, "'"]),
Pass.
list_users(LServer) ->
ejabberd_odbc:sql_query(
LServer,
"EXECUTE dbo.list_users").
add_spool_sql(Username, XML) ->
["EXECUTE dbo.add_spool '", Username, "' , '",XML,"'"].
add_spool(LServer, Queries) ->
lists:foreach(fun(Query) ->
ejabberd_odbc:sql_query(LServer, Query)
end,
Queries).
get_and_del_spool_msg_t(LServer, Username) ->
[Result] = case ejabberd_odbc:sql_query(
LServer,
["EXECUTE dbo.get_and_del_spool_msg '", Username, "'"]) of
Rs when list(Rs) ->
lists:filter(fun({selected, _Header, _Row}) ->
true;
({updated, _N}) ->
false
end,
Rs);
Rs -> [Rs]
end,
{atomic, Result}.
del_spool_msg(LServer, Username) ->
ejabberd_odbc:sql_query(
LServer,
["EXECUTE dbo.del_spool_msg '", Username, "'"]).
get_roster(LServer, Username) ->
ejabberd_odbc:sql_query(
LServer,
["EXECUTE dbo.get_roster '", Username, "'"]).
get_roster_jid_groups(LServer, Username) ->
ejabberd_odbc:sql_query(
LServer,
["EXECUTE dbo.get_roster_jid_groups '", Username, "'"]).
get_roster_groups(LServer, Username, SJID) ->
ejabberd_odbc:sql_query(
LServer,
["EXECUTE dbo.get_roster_groups '", Username, "' , '", SJID, "'"]).
del_user_roster_t(LServer, Username) ->
Result = ejabberd_odbc:sql_query(
LServer,
["EXECUTE dbo.del_user_roster '", Username, "'"]),
{atomic, Result}.
get_roster_by_jid(LServer, Username, SJID) ->
ejabberd_odbc:sql_query(
LServer,
["EXECUTE dbo.get_roster_by_jid '", Username, "' , '", SJID, "'"]).
get_rostergroup_by_jid(LServer, Username, SJID) ->
ejabberd_odbc:sql_query(
LServer,
["EXECUTE dbo.get_rostergroup_by_jid '", Username, "' , '", SJID, "'"]).
del_roster(LServer, Username, SJID) ->
ejabberd_odbc:sql_query(
LServer,
["EXECUTE dbo.del_roster '", Username, "', '", SJID, "'"]).
del_roster_sql(Username, SJID) ->
["EXECUTE dbo.del_roster '", Username, "', '", SJID, "'"].
update_roster(LServer, Username, SJID, ItemVals, ItemGroups) ->
Query1 = ["EXECUTE dbo.del_roster '", Username, "', '", SJID, "' "],
ejabberd_odbc:sql_query(LServer, lists:flatten(Query1)),
Query2 = ["EXECUTE dbo.add_roster_user ", ItemVals],
ejabberd_odbc:sql_query(LServer, lists:flatten(Query2)),
Query3 = ["EXECUTE dbo.del_roster_groups '", Username, "', '", SJID, "' "],
ejabberd_odbc:sql_query(LServer, lists:flatten(Query3)),
lists:foreach(fun(ItemGroup) ->
Query = ["EXECUTE dbo.add_roster_group ",
ItemGroup],
ejabberd_odbc:sql_query(LServer,
lists:flatten(Query))
end,
ItemGroups).
update_roster_sql(Username, SJID, ItemVals, ItemGroups) ->
["BEGIN TRANSACTION ",
"EXECUTE dbo.del_roster_groups '", Username, "','", SJID, "' ",
"EXECUTE dbo.add_roster_user ", ItemVals, " "] ++
[lists:flatten("EXECUTE dbo.add_roster_group ", ItemGroup, " ")
|| ItemGroup <- ItemGroups] ++
["COMMIT"].
roster_subscribe(LServer, _Username, _SJID, ItemVals) ->
catch ejabberd_odbc:sql_query(
LServer,
["EXECUTE dbo.add_roster_user ", ItemVals]).
get_subscription(LServer, Username, SJID) ->
ejabberd_odbc:sql_query(
LServer,
["EXECUTE dbo.get_subscription '", Username, "' , '", SJID, "'"]).
%% Characters to escape
escape($\0) -> "\\0";
escape($\t) -> "\\t";
escape($\b) -> "\\b";
escape($\r) -> "\\r";
escape($') -> "\''";
escape($") -> "\\\"";
escape(C) -> C.
-endif.
+6 -13
View File
@@ -18,7 +18,6 @@ CREATE TABLE rosterusers (
nick text,
subscription character(1) NOT NULL,
ask character(1) NOT NULL,
askmessage text,
server character(1) NOT NULL,
subscribe text,
"type" text
@@ -37,6 +36,12 @@ CREATE TABLE rostergroups (
CREATE INDEX pk_rosterg_user_jid ON rostergroups USING btree (username, jid);
--- To update from previous table definition:
-- CREATE SEQUENCE spool_seq_seq;
-- ALTER TABLE spool ADD COLUMN seq integer;
-- ALTER TABLE spool ALTER COLUMN seq SET DEFAULT nextval('spool_seq_seq');
-- UPDATE spool SET seq = DEFAULT;
-- ALTER TABLE spool ALTER COLUMN seq SET NOT NULL;
CREATE TABLE spool (
username text NOT NULL,
@@ -90,15 +95,3 @@ CREATE INDEX i_vcard_search_llocality ON vcard_search(llocality);
CREATE INDEX i_vcard_search_lemail ON vcard_search(lemail);
CREATE INDEX i_vcard_search_lorgname ON vcard_search(lorgname);
CREATE INDEX i_vcard_search_lorgunit ON vcard_search(lorgunit);
--- To update from 0.9.8:
-- CREATE SEQUENCE spool_seq_seq;
-- ALTER TABLE spool ADD COLUMN seq integer;
-- ALTER TABLE spool ALTER COLUMN seq SET DEFAULT nextval('spool_seq_seq');
-- UPDATE spool SET seq = DEFAULT;
-- ALTER TABLE spool ALTER COLUMN seq SET NOT NULL;
--- To update from 1.x:
-- ALTER TABLE rosterusers ADD COLUMN askmessage text;
-- UPDATE rosterusers SET askmessage = '';
-- ALTER TABLE rosterusers ALTER COLUMN askmessage SET NOT NULL;
+1 -8
View File
@@ -6,13 +6,6 @@ CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@ @ERLANG_LIBS@
ifeq ($(shell uname),Darwin)
DYNAMIC_LIB_CFLAGS = -fPIC -bundle -flat_namespace -undefined suppress
else
# Assume Linux-style dynamic library flags
DYNAMIC_LIB_CFLAGS = -fpic -shared
endif
SUBDIRS =
ERLSHLIBS = ../stringprep_drv.so
@@ -33,7 +26,7 @@ $(OUTDIR)/%.beam: %.erl
$(ERLSHLIBS): ../%.so: %.c uni_data.c uni_norm.c
gcc -Wall -O2 $(CFLAGS) $(LDFLAGS) $(INCLUDES) \
$(subst ../,,$(subst .so,.c,$@)) $(LIBS) \
-o $@ $(DYNAMIC_LIB_CFLAGS)
-o $@ -fpic -shared
clean:
rm -f $(OBJS) $(ERLSHLIBS)
+1 -8
View File
@@ -6,13 +6,6 @@ CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@ @SSL_LIBS@ @ERLANG_LIBS@
ifeq ($(shell uname),Darwin)
DYNAMIC_LIB_CFLAGS = -fPIC -bundle -flat_namespace -undefined suppress
else
# Assume Linux-style dynamic library flags
DYNAMIC_LIB_CFLAGS = -fpic -shared
endif
SUBDIRS =
ERLSHLIBS = ../tls_drv.so
@@ -33,7 +26,7 @@ $(OUTDIR)/%.beam: %.erl
$(ERLSHLIBS): ../%.so: %.c
$(CC) -Wall $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) \
$(subst ../,,$(subst .so,.c,$@)) $(LIBS) \
-o $@ -fpic $(DYNAMIC_LIB_CFLAGS)
-o $@ -fpic -shared
clean:
rm -f $(OBJS) $(ERLSHLIBS)
+2 -19
View File
@@ -64,26 +64,10 @@ static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
#define die_unless(cond, errstr) \
if (!(cond)) \
{ \
int errstrlen = strlen(errstr); \
unsigned long error_code = ERR_get_error(); \
char *error_string = error_code ? \
ERR_error_string(error_code, NULL) : \
NULL; \
int error_string_length = error_string ? \
strlen(error_string) : 0; \
if (error_code) \
rlen = errstrlen + error_string_length + 3; \
else \
rlen = errstrlen + 1; \
rlen = strlen(errstr) + 1; \
b = driver_alloc_binary(rlen); \
b->orig_bytes[0] = 1; \
strncpy(b->orig_bytes + 1, errstr, errstrlen); \
if (error_code) { \
strncpy(b->orig_bytes + 1 + errstrlen, \
": ", 2); \
strncpy(b->orig_bytes + 3 + errstrlen, \
error_string, error_string_length); \
} \
strncpy(b->orig_bytes + 1, errstr, rlen - 1); \
*rbuf = (char *)b; \
return rlen; \
}
@@ -100,7 +84,6 @@ static int tls_drv_control(ErlDrvData handle,
ErlDrvBinary *b;
X509 *cert;
ERR_clear_error();
switch (command)
{
case SET_CERTIFICATE_FILE_ACCEPT:
+5 -26
View File
@@ -133,17 +133,13 @@ process_header(State, Data) ->
SockMod = State#state.sockmod,
Socket = State#state.socket,
case Data of
{ok, {http_request, Method, Uri, Version}} ->
{ok, {http_request, Method, Path, Version}} ->
KeepAlive = case Version of
{1, 1} ->
true;
_ ->
false
end,
Path = case Uri of
{absoluteURI, _Scheme, _Host, _Port, P} -> {abs_path, P};
_ -> Uri
end,
State#state{request_method = Method,
request_version = Version,
request_path = Path,
@@ -720,27 +716,10 @@ parse_req(Line) ->
"*" ->
% Is this correct?
"*";
_ ->
case string:str(URI, "://") of
0 ->
% Relative URI
% ex: /index.html
{abs_path, URI};
N ->
% Absolute URI
% ex: http://localhost/index.html
% Remove scheme
% ex: URI2 = localhost/index.html
URI2 = string:substr(URI, N + 3),
% Look for the start of the path
% (or the lack of a path thereof)
case string:chr(URI2, $/) of
0 -> {abs_path, "/"};
M -> {abs_path,
string:substr(URI2, M + 1)}
end
end
P ->
% FIXME: Handle
% absolute URIs
{abs_path, P}
end,
case VersionStr of
[] ->
+8 -45
View File
@@ -36,8 +36,7 @@
key,
output = "",
input = "",
waiting_input = false, %% {ReceiverPid, Tag}
last_receiver,
waiting_input = false,
timer}).
%-define(DBGFSM, true).
@@ -195,7 +194,7 @@ handle_event(Event, StateName, StateData) ->
%% {stop, Reason, Reply, NewStateData}
%%----------------------------------------------------------------------
handle_sync_event({send, Packet}, From, StateName, StateData) ->
Output = StateData#state.output ++ [lists:flatten(Packet)],
Output = [StateData#state.output | Packet],
Reply = ok,
{reply, Reply, StateName, StateData#state{output = Output}};
@@ -204,12 +203,9 @@ handle_sync_event(activate, From, StateName, StateData) ->
"" ->
{reply, ok, StateName, StateData#state{waiting_input = From}};
Input ->
{Receiver, _Tag} = From,
Receiver ! {tcp, {http_poll, self()}, list_to_binary(Input)},
From ! {tcp, {http_poll, self()}, list_to_binary(Input)},
{reply, ok, StateName, StateData#state{input = "",
waiting_input = false,
last_receiver = From
}}
waiting_input = false}}
end;
handle_sync_event(stop, From, StateName, StateData) ->
@@ -235,7 +231,7 @@ handle_sync_event({http_put, Key, NewKey, Packet},
Allow ->
case StateData#state.waiting_input of
false ->
Input = [StateData#state.input|Packet],
Input = [StateData#state.input | Packet],
Reply = ok,
{reply, Reply, StateName, StateData#state{input = Input,
key = NewKey}};
@@ -247,7 +243,6 @@ handle_sync_event({http_put, Key, NewKey, Packet},
Reply = ok,
{reply, Reply, StateName,
StateData#state{waiting_input = false,
last_receiver = Receiver,
key = NewKey,
timer = Timer}}
end;
@@ -292,18 +287,10 @@ terminate(Reason, StateName, StateData) ->
end),
case StateData#state.waiting_input of
false ->
%% We are testing this case due to "socket activation": If we pass
%% here and the "socket" is not ready to receive, the tcp_closed
%% will be lost.
case StateData#state.last_receiver of
undefined -> ok;
Receiver ->
Receiver ! {tcp_closed, {http_poll, self()}}
end;
{Receiver, _Tag} ->
Receiver ! {tcp_closed, {http_poll, self()}}
ok;
Receiver ->
gen_fsm:reply(Receiver, {error, closed})
end,
resend_messages(StateData#state.output),
ok.
%%%----------------------------------------------------------------------
@@ -354,27 +341,3 @@ cancel_timer(Timer) ->
ok
end.
%% Resend the polled messages
resend_messages(Messages) ->
lists:foreach(fun(Packet) ->
resend_message(Packet)
end, Messages).
%% This function is used to resend messages that have been polled but not
%% delivered.
resend_message(Packet) ->
ParsedPacket = xml_stream:parse_element(Packet),
From = get_jid("from", ParsedPacket),
To = get_jid("to", ParsedPacket),
io:format("MREMOND: Resend ~p ~p ~p~n",[From,To, ParsedPacket]),
ejabberd_router:route(From, To, ParsedPacket).
%% Type can be "from" or "to"
%% Parsed packet is a parsed Jabber packet.
get_jid(Type, ParsedPacket) ->
case xml:get_tag_attr(Type, ParsedPacket) of
{value, StringJid} ->
jlib:string_to_jid(StringJid);
false ->
jlib:make_jid("","","")
end.
+14 -16
View File
@@ -5,8 +5,8 @@
%%% Created : 9 Apr 2004 by Alexey Shchepin <alexey@sevcom.net>
%%% Id : $Id$
%%%----------------------------------------------------------------------
%%% Copyright (c) 2004-2006 Alexey Shchepin
%%% Copyright (c) 2004-2006 Process One
%%% Copyright (c) 2004-2005 Alexey Shchepin
%%% Copyright (c) 2004-2005 Process One
%%%----------------------------------------------------------------------
-module(ejabberd_web_admin).
@@ -1229,7 +1229,7 @@ list_vhosts(Lang) ->
list_users(Host, Query, Lang, URLFunc) ->
Res = list_users_parse_query(Query, Host),
Res = list_users_parse_query(Query),
Users = ejabberd_auth:get_vh_registered_users(Host),
SUsers = lists:sort([{S, U} || {U, S} <- Users]),
FUsers =
@@ -1262,32 +1262,28 @@ list_users(Host, Query, Lang, URLFunc) ->
[?XE("table",
[?XE("tr",
[?XC("td", ?T("User") ++ ":"),
?XE("td", [?INPUT("text", "newusername", "")]),
?XE("td", [?C([" @ ", Host])])
?XE("td", [?INPUT("text", "newusername", "")])
]),
?XE("tr",
[?XC("td", ?T("Password") ++ ":"),
?XE("td", [?INPUT("password", "newuserpassword", "")]),
?X("td")
?XE("td", [?INPUT("password", "newuserpassword", "")])
]),
?XE("tr",
[?X("td"),
?XAE("td", [{"class", "alignright"}],
[?INPUTT("submit", "addnewuser", "Add User")]),
?X("td")
[?INPUTT("submit", "addnewuser", "Add User")])
])]),
?P] ++
FUsers)].
%% Parse user creation query and try register:
list_users_parse_query(Query, Host) ->
list_users_parse_query(Query) ->
case lists:keysearch("addnewuser", 1, Query) of
{value, _} ->
{value, {_, Username}} =
{value, {_, JIDString}} =
lists:keysearch("newusername", 1, Query),
{value, {_, Password}} =
lists:keysearch("newuserpassword", 1, Query),
case jlib:string_to_jid(Username++"@"++Host) of
case jlib:string_to_jid(JIDString) of
error ->
error;
#jid{user = User, server = Server} ->
@@ -2183,8 +2179,10 @@ node_backup_parse_query(Node, Query) ->
rpc:call(Node, mnesia,
backup, [Path]);
"restore" ->
rpc:call(Node, ejabberd_admin,
restore, [Path]);
rpc:call(Node, mnesia,
restore,
[Path, [{default_op,
keep_tables}]]);
"fallback" ->
rpc:call(Node, mnesia,
install_fallback, [Path]);
@@ -2586,7 +2584,7 @@ shared_roster_group_parse_query(Host, Group, Query) ->
OldMembers = mod_shared_roster:get_group_explicit_users(
Host, Group),
SJIDs = string:tokens(SMembers, ", \r\n"),
SJIDs = string:tokens(SMembers, "\r\n"),
NewMembers =
lists:foldl(
fun(_SJID, error) -> error;