From 9eca69d092897f8a7724698c78b787fb8021ab80 Mon Sep 17 00:00:00 2001
From: Christophe Romain <christophe.romain@process-one.net>
Date: Thu, 30 Apr 2015 09:02:06 +0200
Subject: [PATCH] Remove modules included in ejabberd 15.04

---
 mod_admin_extra/COPYING                  |  343 -----
 mod_admin_extra/ChangeLog                |  117 --
 mod_admin_extra/README.txt               |   83 --
 mod_admin_extra/conf/mod_admin_extra.yml |   23 -
 mod_admin_extra/mod_admin_extra.spec     |    5 -
 mod_admin_extra/src/mod_admin_extra.erl  | 1583 ----------------------
 mod_admin_extra/src/mod_ecomm_test.erl   |  426 ------
 mod_muc_admin/COPYING                    |  343 -----
 mod_muc_admin/ChangeLog                  |   80 --
 mod_muc_admin/README.txt                 |   43 -
 mod_muc_admin/conf/mod_muc_admin.yml     |    2 -
 mod_muc_admin/mod_muc_admin.spec         |    5 -
 mod_muc_admin/src/mod_muc_admin.erl      |  876 ------------
 13 files changed, 3929 deletions(-)
 delete mode 100644 mod_admin_extra/COPYING
 delete mode 100644 mod_admin_extra/ChangeLog
 delete mode 100644 mod_admin_extra/README.txt
 delete mode 100644 mod_admin_extra/conf/mod_admin_extra.yml
 delete mode 100644 mod_admin_extra/mod_admin_extra.spec
 delete mode 100644 mod_admin_extra/src/mod_admin_extra.erl
 delete mode 100644 mod_admin_extra/src/mod_ecomm_test.erl
 delete mode 100644 mod_muc_admin/COPYING
 delete mode 100644 mod_muc_admin/ChangeLog
 delete mode 100644 mod_muc_admin/README.txt
 delete mode 100644 mod_muc_admin/conf/mod_muc_admin.yml
 delete mode 100644 mod_muc_admin/mod_muc_admin.spec
 delete mode 100644 mod_muc_admin/src/mod_muc_admin.erl

diff --git a/mod_admin_extra/COPYING b/mod_admin_extra/COPYING
deleted file mode 100644
index e21e8c4..0000000
--- a/mod_admin_extra/COPYING
+++ /dev/null
@@ -1,343 +0,0 @@
-As a special exception, the authors give permission to link this program
-with the OpenSSL library and distribute the resulting binary.
-
-		    GNU GENERAL PUBLIC LICENSE
-		       Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-			    Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users.  This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it.  (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.)  You can apply it to
-your programs, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-  To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have.  You must make sure that they, too, receive or can get the
-source code.  And you must show them these terms so they know their
-rights.
-
-  We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
-  Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software.  If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary.  To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-
-		    GNU GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License.  The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language.  (Hereinafter, translation is included without limitation in
-the term "modification".)  Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
-  1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
-  2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) You must cause the modified files to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    b) You must cause any work that you distribute or publish, that in
-    whole or in part contains or is derived from the Program or any
-    part thereof, to be licensed as a whole at no charge to all third
-    parties under the terms of this License.
-
-    c) If the modified program normally reads commands interactively
-    when run, you must cause it, when started running for such
-    interactive use in the most ordinary way, to print or display an
-    announcement including an appropriate copyright notice and a
-    notice that there is no warranty (or else, saying that you provide
-    a warranty) and that users may redistribute the program under
-    these conditions, and telling the user how to view a copy of this
-    License.  (Exception: if the Program itself is interactive but
-    does not normally print such an announcement, your work based on
-    the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
-    a) Accompany it with the complete corresponding machine-readable
-    source code, which must be distributed under the terms of Sections
-    1 and 2 above on a medium customarily used for software interchange; or,
-
-    b) Accompany it with a written offer, valid for at least three
-    years, to give any third party, for a charge no more than your
-    cost of physically performing source distribution, a complete
-    machine-readable copy of the corresponding source code, to be
-    distributed under the terms of Sections 1 and 2 above on a medium
-    customarily used for software interchange; or,
-
-    c) Accompany it with the information you received as to the offer
-    to distribute corresponding source code.  (This alternative is
-    allowed only for noncommercial distribution and only if you
-    received the program in object code or executable form with such
-    an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it.  For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable.  However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License.  Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
-  5. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Program or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
-  6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
-  7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-  8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded.  In such case, this License incorporates
-the limitation as if written in the body of this License.
-
-  9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation.  If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
-  10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission.  For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this.  Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
-			    NO WARRANTY
-
-  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
-  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
-		     END OF TERMS AND CONDITIONS
-
-	    How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License along
-    with this program; if not, write to the Free Software Foundation, Inc.,
-    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
-    Gnomovision version 69, Copyright (C) year  name of author
-    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-    This is free software, and you are welcome to redistribute it
-    under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License.  Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
-  `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
-  <signature of Ty Coon>, 1 April 1989
-  Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs.  If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library.  If this is what you want to do, use the GNU Library General
-Public License instead of this License.
diff --git a/mod_admin_extra/ChangeLog b/mod_admin_extra/ChangeLog
deleted file mode 100644
index 0049160..0000000
--- a/mod_admin_extra/ChangeLog
+++ /dev/null
@@ -1,117 +0,0 @@
-2009-06-15  Badlop  <badlop@process-one.net>
-
-	* src/mod_admin_extra.erl: Added command to check the password by
-	providing a MD5 or SHA hash.
-
-2009-02-16  Badlop  <badlop@process-one.net>
-
-	* src/mod_admin_extra.erl: Fix srg_user_add arguments
-
-2009-02-09  Badlop  <badlop@process-one.net>
-
-	* src/mod_admin_extra.erl: Calculation of 'stats registeredusers'
-	works also with non-internal authentication methods (thanks to
-	Francois de Metz)(EJAB-864)
-
-2009-01-27  Badlop  <badlop@process-one.net>
-
-	* README.txt: Explicitely mention that this module does not work
-	with any ejabberd 2.0.x or older
-
-	* src/mod_admin_extra.erl: In the srg_create command, allow to
-	separate group identifiers in the Display argument with escaped
-	newline character. Explain this possibility in the command long
-	description.
-
-2008-11-10  Badlop  <badlop@process-one.net>
-
-	* src/mod_admin_extra.erl: Renamed command send_message to
-	send_message_headline. New command send_message_chat. (thanks to
-	Xyu)
-
-2008-10-31  Badlop  <badlop@process-one.net>
-
-	* src/mod_admin_extra.erl: Deleted the duplicated command
-	delete_older_messages (EJAB-814). Rename the other delete_older_*
-	commands.
-
-2008-10-12  Badlop  <badlop@process-one.net>
-
-	* README.txt: It requires ejabberd trunk SVN 1635 or newer
-
-	* src/mod_admin_extra.erl: Renamed mod_ctlextra to
-	mod_admin_extra, as it now implements ejabberd commands instead of
-	ejabberdctl commands
-
-2008-04-26  Badlop  <badlop@process-one.net>
-
-	* src/mod_ctlextra.erl: New command: ban-account
-	* README.txt: Documented new command
-
-2008-04-04  Badlop  <badlop@process-one.net>
-
-	* src/mod_ctlextra.erl: Added new command
-	rosteritem-purge [options]
-
-2008-03-19  Badlop  <badlop@process-one.net>
-
-	* src/mod_ctlextra.erl: Added two new commands for administration
-	of Shared Roster Groups: "srg-list-groups host" and "srg-get-info
-	group host" (thanks to Taylor Laramie)
-
-2008-03-09  Badlop  <badlop@process-one.net>
-
-	* src/mod_ctlextra.erl: Show the result of each table export
-
-2008-03-04  Badlop  <badlop@process-one.net>
-
-	* src/mod_ctlextra.erl: New command 'stats
-	onlineusersnode'. Removed old unusued code.
-
-	* README.txt: Updated module page
-
-2008-01-20  Badlop  <badlop@process-one.net>
-
-	* src/mod_ctlextra.erl: Allow to define group name with spaces
-	* README.txt: Likewise
-
-2007-11-14  Badlop  <badlop@ono.com>
-
-	* src/mod_ctlextra.erl: Updated to ejabberd SVN.
-
-2007-09-08  Badlop  <badlop@ono.com>
-
-	* src/mod_ctlextra.erl: Bugfix: unregister commands when module 
-	stops. Removed all MUC-related commands. 
-
-2007-08-29  Badlop  <badlop@ono.com>
-
-	* src/mod_ctlextra.erl: Added command: stats uptime-seconds.
-
-2007-08-24  Badlop  <badlop@ono.com>
-
-	* src/mod_ctlextra.erl: Fixed bug in vcard-set command that 
-	forgot second level attributes.
-
-2007-08-23  Badlop  <badlop@ono.com>
-
-	* src/mod_ctlextra.erl: Command add-rosteritem now pushes the 
-	roster item to the client. New command rem-rosteritem.
-
-2007-08-19  Badlop  <badlop@ono.com>
-
-	* src/mod_ctlextra.erl: Now vcard-get and vcard-set are more 
-	compatible with mod_vcard_odbc and mod_vcard_ldap.
-
-2007-08-16  Badlop  <badlop@ono.com>
-
-	* src/mod_ctlextra.erl: add-rosteritem only adds an item in a 
-	roster.
-
-2007-08-07  Badlop  <badlop@ono.com>
-
-	* src/mod_ctlextra.erl: Fixed indentation.
-
-	* ChangeLog: New file to track changes.
-
-	* README.txt: Removed Changelog section.
diff --git a/mod_admin_extra/README.txt b/mod_admin_extra/README.txt
deleted file mode 100644
index bb9d107..0000000
--- a/mod_admin_extra/README.txt
+++ /dev/null
@@ -1,83 +0,0 @@
-
-
-	mod_admin_extra - Additional ejabberd commands
-
-	NOTE: This module is included in ejabberd since 15.04
-
-	Author: Badlop
-	Homepage: http://www.ejabberd.im/mod_admin_extra
-
-
-	CONFIGURATION
-	=============
-
-Add the module to your ejabberd.yml, on the modules section:
-modules:
-  mod_admin_extra: {}
-
-The configurable options are:
-- module_resource:
-  Indicate the resource that the XMPP stanzas must use in the FROM or TO JIDs.
-  This is only useful in the vcard set and get commands.
-  The default value is "mod_admin_extra".
-
-In this example configuration, the users vcards can only be modified
-by executing mod_admin_extra commands.
-Notice that this needs the patch
- https://support.process-one.net/browse/EJAB-797
-acl:
-  adminextraresource:
-    resource: "modadminextraf8x,31ad"
-access:
-  vcard_set:
-    adminextraresource: allow
-    all: deny
-modules:
-  mod_admin_extra:
-    module_resource: "modadminextraf8x,31ad"
-  mod_vcard:
-    access_set: vcard_set
-
-
-	USAGE
-	=====
-
-Now you have several new commands in ejabberdctl.
-
-Description of some commands:
-
- - vcard-*
-   Example: ejabberdctl vcard-get joe myjab.net email
-
- - pushroster*
-   The file used by 'pushroster' and 'pushroster-all' must be placed:
-     - Windows: on the directory were you installed ejabberd: 
-       'C:/Program Files/ejabberd'
-     - Other OS: on the same directory where the .beam files are.
-   Example content for the roster file:
-   [{<<"bob">>, <<"example.org">>, <<"workers">>, <<"Bob">>},
-    {<<"mart">>, <<"example.org">>, <<"workers">>, <<"Mart">>},
-    {<<"Rich">>, <<"example.org">>, <<"bosses">>, <<"Rich">>}].
-
- - srg-create
-   If you want to put a group Name with blankspaces, use the characters 
-   "' and '" to define when the Name starts and ends.
-   For example:
-   ejabberdctl srg-create g1 example.org "'Group number 1'" this_is_g1 g1
-
- - ban-account
-
-   This command kicks all the connected sessions of the account from the
-   server.  It also changes his password to another randomly
-   generated, so he can't login anymore unless a server administrator
-   changes him again the password.
-
-   It is possible to define the reason of the ban.  The new password
-   also includes the reason and the date and time of the ban.
-
-   For example, if this command is called:
-     ejabberdctl vhost example.org ban-account boby Spammed several MUC rooms
-   then the sessions of the local account which JID is boby@example.org
-   will be kicked, and its password will be set to something like this:
-     BANNED_ACCOUNT--20080425T21:45:07--2176635--Spammed_several_MUC_rooms
-
diff --git a/mod_admin_extra/conf/mod_admin_extra.yml b/mod_admin_extra/conf/mod_admin_extra.yml
deleted file mode 100644
index c568a70..0000000
--- a/mod_admin_extra/conf/mod_admin_extra.yml
+++ /dev/null
@@ -1,23 +0,0 @@
-# The configurable options are:
-# - module_resource:
-#   Indicate the resource that the XMPP stanzas must use in the FROM or TO JIDs.
-#   This is only useful in the vcard set and get commands.
-#   The default value is "mod_admin_extra".
-# 
-# In this example configuration, the users vcards can only be modified
-# by executing mod_admin_extra commands.
-
-acl:
-  adminextraresource:
-    - "resource": "modadminextraf8x,31ad"
-
-access:
-  vcard_set:
-    adminextraresource: allow
-    all: deny
-
-modules:
-  mod_admin_extra:
-    - "module_resource": "modadminextraf8x,31ad"
-  mod_vcard:
-    - "access_set": "vcard_set"
diff --git a/mod_admin_extra/mod_admin_extra.spec b/mod_admin_extra/mod_admin_extra.spec
deleted file mode 100644
index a4c575d..0000000
--- a/mod_admin_extra/mod_admin_extra.spec
+++ /dev/null
@@ -1,5 +0,0 @@
-author: "Badlop <badlop at process-one.net>"
-category: "admin"
-summary: "Additional ejabberd commands"
-home: "https://github.com/processone/mod_admin_extra"
-url: "git@github.com:processone/mod_admin_extra.git"
diff --git a/mod_admin_extra/src/mod_admin_extra.erl b/mod_admin_extra/src/mod_admin_extra.erl
deleted file mode 100644
index 043b6f3..0000000
--- a/mod_admin_extra/src/mod_admin_extra.erl
+++ /dev/null
@@ -1,1583 +0,0 @@
-%%%-------------------------------------------------------------------
-%%% File    : mod_admin_extra.erl
-%%% Author  : Badlop <badlop@process-one.net>
-%%% Purpose : Contributed administrative functions and commands
-%%% Created : 10 Aug 2008 by Badlop <badlop@process-one.net>
-%%%
-%%%
-%%% ejabberd, Copyright (C) 2002-2008   ProcessOne
-%%%
-%%% This program is free software; you can redistribute it and/or
-%%% modify it under the terms of the GNU General Public License as
-%%% published by the Free Software Foundation; either version 2 of the
-%%% License, or (at your option) any later version.
-%%%
-%%% This program is distributed in the hope that it will be useful,
-%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
-%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-%%% General Public License for more details.
-%%%
-%%% You should have received a copy of the GNU General Public License along
-%%% with this program; if not, write to the Free Software Foundation, Inc.,
-%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-%%%
-%%%-------------------------------------------------------------------
-
--module(mod_admin_extra).
--author('badlop@process-one.net').
-
--behaviour(gen_mod).
-
--include("logger.hrl").
-
--export([start/2, stop/1,
-	 %% Node
-	 compile/1,
-	 load_config/1,
-	 get_cookie/0,
-	 remove_node/1,
-	 export2odbc/2,
-	 %% Accounts
-	 set_password/3,
-	 check_password_hash/4,
-	 delete_old_users/1,
-	 delete_old_users_vhost/2,
-	 ban_account/3,
-	 num_active_users/2,
-	 %% Sessions
-	 num_resources/2,
-	 resource_num/3,
-	 kick_session/4,
-	 status_num/2, status_num/1,
-	 status_list/2, status_list/1,
-	 connected_users_info/0,
-	 connected_users_vhost/1,
-	 set_presence/7,
-	 user_sessions_info/2,
-	 %% Vcard
-	 set_nickname/3,
-	 get_vcard/3,
-	 get_vcard/4,
-	 get_vcard_multi/4,
-	 set_vcard/4,
-	 set_vcard/5,
-	 %% Roster
-	 add_rosteritem/7,
-	 delete_rosteritem/4,
-	 process_rosteritems/5,
-	 get_roster/2,
-	 push_roster/3,
-	 push_roster_all/1,
-	 push_alltoall/2,
-	 %% mod_last
-	 get_last/2,
-	 set_last/4,
-	 %% mod_private
-	 private_get/4,
-	 private_set/3,
-	 %% mod_shared_roster
-	 srg_create/5,
-	 srg_delete/2,
-	 srg_list/1,
-	 srg_get_info/2,
-	 srg_get_members/2,
-	 srg_user_add/4,
-	 srg_user_del/4,
-	 %% Stanza
-	 send_message/5,
-	 send_stanza_c2s/4,
-	 privacy_set/3,
-	 %% Stats
-	 stats/1, stats/2
-	]).
-
--include("ejabberd.hrl").
--include("ejabberd_commands.hrl").
--include("mod_roster.hrl").
--include("jlib.hrl").
-
-%% Copied from ejabberd_sm.erl
--record(session, {sid, usr, us, priority, info}).
-
-
-%%%
-%%% gen_mod
-%%%
-
-start(_Host, _Opts) ->
-    ejabberd_commands:register_commands(commands()).
-
-stop(_Host) ->
-    ejabberd_commands:unregister_commands(commands()).
-
-
-%%%
-%%% Register commands
-%%%
-
-commands() ->
-    Vcard1FieldsString = "Some vcard field names in get/set_vcard are:\n"
-	" FN		- Full Name\n"
-	" NICKNAME	- Nickname\n"
-	" BDAY		- Birthday\n"
-	" TITLE		- Work: Position\n"
-	" ROLE		- Work: Role",
-
-    Vcard2FieldsString = "Some vcard field names and subnames in get/set_vcard2 are:\n"
-	" N FAMILY	- Family name\n"
-	" N GIVEN	- Given name\n"
-	" N MIDDLE	- Middle name\n"
-	" ADR CTRY	- Address: Country\n"
-	" ADR LOCALITY	- Address: City\n"
-	" TEL HOME      - Telephone: Home\n"
-	" TEL CELL      - Telephone: Cellphone\n"
-	" TEL WORK      - Telephone: Work\n"
-	" TEL VOICE     - Telephone: Voice\n"
-	" EMAIL USERID	- E-Mail Address\n"
-	" ORG ORGNAME	- Work: Company\n"
-	" ORG ORGUNIT	- Work: Department",
-
-    VcardXEP = "For a full list of vCard fields check XEP-0054: vcard-temp at "
-	"http://www.xmpp.org/extensions/xep-0054.html",
-
-    [
-     #ejabberd_commands{name = compile, tags = [erlang],
-			desc = "Recompile and reload Erlang source code file",
-			module = ?MODULE, function = compile,
-			args = [{file, string}],
-			result = {res, rescode}},
-     #ejabberd_commands{name = load_config, tags = [server],
-			desc = "Load ejabberd configuration file",
-			module = ?MODULE, function = load_config,
-			args = [{file, string}],
-			result = {res, rescode}},
-     #ejabberd_commands{name = get_cookie, tags = [erlang],
-			desc = "Get the Erlang cookie of this node",
-			module = ?MODULE, function = get_cookie,
-			args = [],
-			result = {cookie, string}},
-     #ejabberd_commands{name = remove_node, tags = [erlang],
-			desc = "Remove an ejabberd node from Mnesia clustering config",
-			module = ?MODULE, function = remove_node,
-			args = [{node, string}],
-			result = {res, rescode}},
-     #ejabberd_commands{name = export2odbc, tags = [mnesia], %% Copied to ejabberd 2.1.x after 11
-			desc = "Export Mnesia tables to files in directory",
-			module = ?MODULE, function = export2odbc,
-			args = [{host, string}, {path, string}],
-			result = {res, rescode}},
-
-     #ejabberd_commands{name = num_active_users, tags = [accounts, stats],
-			desc = "Get number of users active in the last days",
-			module = ?MODULE, function = num_active_users,
-			args = [{host, binary}, {days, integer}],
-			result = {users, integer}},
-     #ejabberd_commands{name = delete_old_users, tags = [accounts, purge],
-			desc = "Delete users that didn't log in last days, or that never logged",
-			module = ?MODULE, function = delete_old_users,
-			args = [{days, integer}],
-			result = {res, restuple}},
-     #ejabberd_commands{name = delete_old_users_vhost, tags = [accounts, purge],
-			desc = "Delete users that didn't log in last days in vhost, or that never logged",
-			module = ?MODULE, function = delete_old_users_vhost,
-			args = [{host, binary}, {days, integer}],
-			result = {res, restuple}},
-
-     #ejabberd_commands{name = check_account, tags = [accounts],
-			desc = "Check if an account exists or not",
-			module = ejabberd_auth, function = is_user_exists,
-			args = [{user, binary}, {host, binary}],
-			result = {res, rescode}},
-     #ejabberd_commands{name = check_password, tags = [accounts],
-			desc = "Check if a password is correct",
-			module = ejabberd_auth, function = check_password,
-			args = [{user, binary}, {host, binary}, {password, binary}],
-			result = {res, rescode}},
-     #ejabberd_commands{name = check_password_hash, tags = [accounts],
-			desc = "Check if the password hash is correct",
-			longdesc = "Allowed hash methods: md5, sha.",
-			module = ?MODULE, function = check_password_hash,
-			args = [{user, binary}, {host, binary}, {passwordhash, binary}, {hashmethod, binary}],
-			result = {res, rescode}},
-     #ejabberd_commands{name = change_password, tags = [accounts],
-			desc = "Change the password of an account",
-			module = ?MODULE, function = set_password,
-			args = [{user, binary}, {host, binary}, {newpass, binary}],
-			result = {res, rescode}},
-     #ejabberd_commands{name = ban_account, tags = [accounts],
-			desc = "Ban an account: kick sessions and set random password",
-			module = ?MODULE, function = ban_account,
-			args = [{user, binary}, {host, binary}, {reason, binary}],
-			result = {res, rescode}},
-
-     #ejabberd_commands{name = num_resources, tags = [session],
-			desc = "Get the number of resources of a user",
-			module = ?MODULE, function = num_resources,
-			args = [{user, binary}, {host, binary}],
-			result = {resources, integer}},
-     #ejabberd_commands{name = resource_num, tags = [session],
-			desc = "Resource string of a session number",
-			module = ?MODULE, function = resource_num,
-			args = [{user, binary}, {host, binary}, {num, integer}],
-			result = {resource, string}},
-     #ejabberd_commands{name = kick_session, tags = [session],
-			desc = "Kick a user session",
-			module = ?MODULE, function = kick_session,
-			args = [{user, binary}, {host, binary}, {resource, binary}, {reason, binary}],
-			result = {res, rescode}},
-     #ejabberd_commands{name = status_num_host, tags = [session, stats],
-			desc = "Number of logged users with this status in host",
-			module = ?MODULE, function = status_num,
-			args = [{host, binary}, {status, binary}],
-			result = {users, integer}},
-     #ejabberd_commands{name = status_num, tags = [session, stats],
-			desc = "Number of logged users with this status",
-			module = ?MODULE, function = status_num,
-			args = [{status, binary}],
-			result = {users, integer}},
-     #ejabberd_commands{name = status_list_host, tags = [session],
-			desc = "List of users logged in host with their statuses",
-			module = ?MODULE, function = status_list,
-			args = [{host, binary}, {status, binary}],
-			result = {users, {list,
-					  {userstatus, {tuple, [
-								{user, string},
-								{host, string},
-								{resource, string},
-								{priority, integer},
-								{status, string}
-							       ]}}
-					 }}},
-     #ejabberd_commands{name = status_list, tags = [session],
-			desc = "List of logged users with this status",
-			module = ?MODULE, function = status_list,
-			args = [{status, binary}],
-			result = {users, {list,
-					  {userstatus, {tuple, [
-								{user, string},
-								{host, string},
-								{resource, string},
-								{priority, integer},
-								{status, string}
-							       ]}}
-					 }}},
-     #ejabberd_commands{name = connected_users_info,
-			tags = [session],
-			desc = "List all established sessions and their information",
-			module = ?MODULE, function = connected_users_info,
-			args = [],
-			result = {connected_users_info,
-				  {list,
-				   {sessions, {tuple,
-					       [{jid, string},
-						{connection, string},
-						{ip, string},
-						{port, integer},
-						{priority, integer},
-						{node, string},
-						{uptime, integer}
-					       ]}}
-				  }}},
-     #ejabberd_commands{name = connected_users_vhost,
-                       tags = [session],
-                       desc = "Get the list of established sessions in a vhost",
-                       module = ?MODULE, function = connected_users_vhost,
-                       args = [{host, string}],
-                       result = {connected_users_vhost, {list, {sessions, string}}}},
-     #ejabberd_commands{name = user_sessions_info,
-			tags = [session],
-			desc = "Get information about all sessions of a user",
-			module = ?MODULE, function = user_sessions_info,
-			args = [{user, binary}, {host, binary}],
-			result = {sessions_info,
-				  {list,
-				   {session, {tuple,
-					      [{connection, string},
-					       {ip, string},
-					       {port, integer},
-					       {priority, integer},
-					       {node, string},
-					       {uptime, integer},
-					       {status, string},
-					       {resource, string},
-					       {statustext, string}
-					      ]}}
-				  }}},
-
-     #ejabberd_commands{name = set_presence,
-			tags = [session],
-			desc = "Set presence of a session",
-			module = ?MODULE, function = set_presence,
-			args = [{user, binary}, {host, binary},
-				{resource, binary}, {type, binary},
-				{show, binary}, {status, binary},
-				{priority, binary}],
-			result = {res, rescode}},
-
-     #ejabberd_commands{name = set_nickname, tags = [vcard],
-			desc = "Set nickname in a user's vCard",
-			module = ?MODULE, function = set_nickname,
-			args = [{user, binary}, {host, binary}, {nickname, binary}],
-			result = {res, rescode}},
-     #ejabberd_commands{name = get_vcard, tags = [vcard],
-			desc = "Get content from a vCard field",
-			longdesc = Vcard1FieldsString ++ "\n" ++ Vcard2FieldsString ++ "\n\n" ++ VcardXEP,
-			module = ?MODULE, function = get_vcard,
-			args = [{user, binary}, {host, binary}, {name, binary}],
-			result = {content, string}},
-     #ejabberd_commands{name = get_vcard2, tags = [vcard],
-			desc = "Get content from a vCard field",
-			longdesc = Vcard2FieldsString ++ "\n\n" ++ Vcard1FieldsString ++ "\n" ++ VcardXEP,
-			module = ?MODULE, function = get_vcard,
-			args = [{user, binary}, {host, binary}, {name, binary}, {subname, binary}],
-			result = {content, string}},
-     #ejabberd_commands{name = get_vcard2_multi, tags = [vcard],
-			desc = "Get multiple contents from a vCard field",
-			longdesc = Vcard2FieldsString ++ "\n\n" ++ Vcard1FieldsString ++ "\n" ++ VcardXEP,
-			module = ?MODULE, function = get_vcard_multi,
-			args = [{user, binary}, {host, binary}, {name, binary}, {subname, binary}],
-			result = {contents, {list, {value, string}}}},
-
-     #ejabberd_commands{name = set_vcard, tags = [vcard],
-			desc = "Set content in a vCard field",
-			longdesc = Vcard1FieldsString ++ "\n" ++ Vcard2FieldsString ++ "\n\n" ++ VcardXEP,
-			module = ?MODULE, function = set_vcard,
-			args = [{user, binary}, {host, binary}, {name, binary}, {content, binary}],
-			result = {res, rescode}},
-     #ejabberd_commands{name = set_vcard2, tags = [vcard],
-			desc = "Set content in a vCard subfield",
-			longdesc = Vcard2FieldsString ++ "\n\n" ++ Vcard1FieldsString ++ "\n" ++ VcardXEP,
-			module = ?MODULE, function = set_vcard,
-			args = [{user, binary}, {host, binary}, {name, binary}, {subname, binary}, {content, binary}],
-			result = {res, rescode}},
-     #ejabberd_commands{name = set_vcard2_multi, tags = [vcard],
-			desc = "Set multiple contents in a vCard subfield",
-			longdesc = Vcard2FieldsString ++ "\n\n" ++ Vcard1FieldsString ++ "\n" ++ VcardXEP,
-			module = ?MODULE, function = set_vcard,
-			args = [{user, binary}, {host, binary}, {name, binary}, {subname, binary}, {contents, {list, binary}}],
-			result = {res, rescode}},
-
-     #ejabberd_commands{name = add_rosteritem, tags = [roster],
-			desc = "Add an item to a user's roster (supports ODBC)",
-			module = ?MODULE, function = add_rosteritem,
-			args = [{localuser, binary}, {localserver, binary},
-				{user, binary}, {server, binary},
-				{nick, binary}, {group, binary},
-				{subs, binary}],
-			result = {res, rescode}},
-     %%{"", "subs= none, from, to or both"},
-     %%{"", "example: add-roster peter localhost mike server.com MiKe Employees both"},
-     %%{"", "will add mike@server.com to peter@localhost roster"},
-     #ejabberd_commands{name = delete_rosteritem, tags = [roster],
-			desc = "Delete an item from a user's roster (supports ODBC)",
-			module = ?MODULE, function = delete_rosteritem,
-			args = [{localuser, binary}, {localserver, binary},
-				{user, binary}, {server, binary}],
-			result = {res, rescode}},
-     #ejabberd_commands{name = process_rosteritems, tags = [roster],
-			desc = "List or delete rosteritems that match filtering options",
-			longdesc = "Explanation of each argument:\n"
-			" - action: what to do with each rosteritem that "
-			"matches all the filtering options\n"
-			" - subs: subscription type\n"
-			" - asks: pending subscription\n"
-			" - users: the JIDs of the local user\n"
-			" - contacts: the JIDs of the contact in the roster\n"
-			"\n"
-			"Allowed values in the arguments:\n"
-			"  ACTION = list | delete\n"
-			"  SUBS = SUB[:SUB]* | any\n"
-			"  SUB = none | from | to | both\n"
-			"  ASKS = ASK[:ASK]* | any\n"
-			"  ASK = none | out | in\n"
-			"  USERS = JID[:JID]* | any\n"
-			"  CONTACTS = JID[:JID]* | any\n"
-			"  JID = characters valid in a JID, and can use the "
-			"globs: *, ?, ! and [...]\n"
-			"\n"
-			"This example will list roster items with subscription "
-			"'none', 'from' or 'to' that have any ask property, of "
-			"local users which JID is in the virtual host "
-			"'example.org' and that the contact JID is either a "
-			"bare server name (without user part) or that has a "
-			"user part and the server part contains the word 'icq'"
-			":\n  list none:from:to any *@example.org *:*@*icq*",
-			module = ?MODULE, function = process_rosteritems,
-			args = [{action, string}, {subs, string},
-				{asks, string}, {users, string},
-				{contacts, string}],
-			result = {response,
-				  {list,
-				   {pairs, {tuple,
-					       [{user, string},
-						{contact, string}
-					       ]}}
-				  }}},
-     #ejabberd_commands{name = get_roster, tags = [roster],
-			desc = "Get roster of a local user",
-			module = ?MODULE, function = get_roster,
-			args = [{user, binary}, {host, binary}],
-			result = {contacts, {list, {contact, {tuple, [
-								      {jid, string},
-								      {nick, string},
-								      {subscription, string},
-								      {ask, string},
-								      {group, string}
-								     ]}}}}},
-     #ejabberd_commands{name = push_roster, tags = [roster],
-			desc = "Push template roster from file to a user",
-			module = ?MODULE, function = push_roster,
-			args = [{file, string}, {user, string}, {host, string}],
-			result = {res, rescode}},
-     #ejabberd_commands{name = push_roster_all, tags = [roster],
-			desc = "Push template roster from file to all those users",
-			module = ?MODULE, function = push_roster_all,
-			args = [{file, string}],
-			result = {res, rescode}},
-     #ejabberd_commands{name = push_alltoall, tags = [roster],
-			desc = "Add all the users to all the users of Host in Group",
-			module = ?MODULE, function = push_alltoall,
-			args = [{host, string}, {group, string}],
-			result = {res, rescode}},
-
-     #ejabberd_commands{name = get_last, tags = [last],
-			desc = "Get last activity information",
-			longdesc = "Timestamp is the seconds since"
-			"1970-01-01 00:00:00 UTC, for example: date +%s",
-			module = ?MODULE, function = get_last,
-			args = [{user, binary}, {host, binary}],
-			result = {last_activity, string}},
-     #ejabberd_commands{name = set_last, tags = [last],
-			desc = "Set last activity information",
-			longdesc = "Timestamp is the seconds since"
-			"1970-01-01 00:00:00 UTC, for example: date +%s",
-			module = ?MODULE, function = set_last,
-			args = [{user, string}, {host, string}, {timestamp, integer}, {status, string}],
-			result = {res, rescode}},
-
-     #ejabberd_commands{name = private_get, tags = [private],
-			desc = "Get some information from a user private storage",
-			module = ?MODULE, function = private_get,
-			args = [{user, binary}, {host, binary}, {element, binary}, {ns, binary}],
-			result = {res, string}},
-     #ejabberd_commands{name = private_set, tags = [private],
-			desc = "Set to the user private storage",
-			module = ?MODULE, function = private_set,
-			args = [{user, binary}, {host, binary}, {element, binary}],
-			result = {res, rescode}},
-
-     #ejabberd_commands{name = srg_create, tags = [shared_roster_group],
-			desc = "Create a Shared Roster Group",
-			longdesc = "If you want to specify several group "
-			"identifiers in the Display argument,\n"
-			"put  \\ \" around the argument and\nseparate the "
-			"identifiers with \\ \\ n\n"
-			"For example:\n"
-			"  ejabberdctl srg_create group3 localhost "
-			"name desc \\\"group1\\\\ngroup2\\\"",
-			module = ?MODULE, function = srg_create,
-			args = [{group, binary}, {host, binary},
-				{name, binary}, {description, binary}, {display, binary}],
-			result = {res, rescode}},
-     #ejabberd_commands{name = srg_delete, tags = [shared_roster_group],
-			desc = "Delete a Shared Roster Group",
-			module = ?MODULE, function = srg_delete,
-			args = [{group, binary}, {host, binary}],
-			result = {res, rescode}},
-     #ejabberd_commands{name = srg_list, tags = [shared_roster_group],
-			desc = "List the Shared Roster Groups in Host",
-			module = ?MODULE, function = srg_list,
-			args = [{host, binary}],
-			result = {groups, {list, {id, string}}}},
-     #ejabberd_commands{name = srg_get_info, tags = [shared_roster_group],
-			desc = "Get info of a Shared Roster Group",
-			module = ?MODULE, function = srg_get_info,
-			args = [{group, binary}, {host, binary}],
-			result = {informations, {list, {information, {tuple, [{key, string}, {value, string}]}}}}},
-     #ejabberd_commands{name = srg_get_members, tags = [shared_roster_group],
-			desc = "Get members of a Shared Roster Group",
-			module = ?MODULE, function = srg_get_members,
-			args = [{group, binary}, {host, binary}],
-			result = {members, {list, {member, string}}}},
-     #ejabberd_commands{name = srg_user_add, tags = [shared_roster_group],
-			desc = "Add the JID user@host to the Shared Roster Group",
-			module = ?MODULE, function = srg_user_add,
-			args = [{user, binary}, {host, binary}, {group, binary}, {grouphost, binary}],
-			result = {res, rescode}},
-     #ejabberd_commands{name = srg_user_del, tags = [shared_roster_group],
-			desc = "Delete this JID user@host from the Shared Roster Group",
-			module = ?MODULE, function = srg_user_del,
-			args = [{user, binary}, {host, binary}, {group, binary}, {grouphost, binary}],
-			result = {res, rescode}},
-
-     #ejabberd_commands{name = send_message, tags = [stanza],
-			desc = "Send a message to a local or remote bare of full JID",
-			module = ?MODULE, function = send_message,
-			args = [{type, binary}, {from, binary}, {to, binary},
-				{subject, binary}, {body, binary}],
-			result = {res, rescode}},
-     #ejabberd_commands{name = send_stanza_c2s, tags = [stanza],
-			desc = "Send a stanza as if sent from a c2s session",
-			module = ?MODULE, function = send_stanza_c2s,
-			args = [{user, binary}, {host, binary}, {resource, binary}, {stanza, binary}],
-			result = {res, rescode}},
-     #ejabberd_commands{name = privacy_set, tags = [stanza],
-			desc = "Send a IQ set privacy stanza for a local account",
-			module = ?MODULE, function = privacy_set,
-			args = [{user, binary}, {host, binary}, {xmlquery, binary}],
-			result = {res, rescode}},
-
-     #ejabberd_commands{name = stats, tags = [stats],
-			desc = "Get statistical value: registeredusers onlineusers onlineusersnode uptimeseconds",
-			module = ?MODULE, function = stats,
-			args = [{name, binary}],
-			result = {stat, integer}},
-     #ejabberd_commands{name = stats_host, tags = [stats],
-			desc = "Get statistical value for this host: registeredusers onlineusers",
-			module = ?MODULE, function = stats,
-			args = [{name, binary}, {host, binary}],
-			result = {stat, integer}}
-    ].
-
-
-%%%
-%%% Node
-%%%
-
-compile(File) ->
-    compile:file(File).
-
-load_config(Path) ->
-    ok = ejabberd_config:load_file(Path).
-
-get_cookie() ->
-    atom_to_list(erlang:get_cookie()).
-
-remove_node(Node) ->
-    mnesia:del_table_copy(schema, list_to_atom(Node)),
-    ok.
-
-export2odbc(Host, Directory) ->
-    Tables = [
-	      {export_last, last},
-	      {export_offline, offline},
-	      {export_passwd, passwd},
-	      {export_private_storage, private_storage},
-	      {export_roster, roster},
-	      {export_vcard, vcard},
-	      {export_vcard_search, vcard_search}],
-    Export = fun({TableFun, Table}) ->
-		     Filename = filename:join([Directory, atom_to_list(Table)++".txt"]),
-		     io:format("Trying to export Mnesia table '~p' on Host '~s' to file '~s'~n", [Table, Host, Filename]),
-		     Res = (catch ejd2odbc:TableFun(Host, Filename)),
-		     io:format("  Result: ~p~n", [Res])
-	     end,
-    lists:foreach(Export, Tables),
-    ok.
-
-
-%%%
-%%% Accounts
-%%%
-
-set_password(User, Host, Password) ->
-    case ejabberd_auth:set_password(User, Host, Password) of
-	ok ->
-	    ok;
-	_ ->
-	    error
-    end.
-
-%% Copied some code from ejabberd_commands.erl
-check_password_hash(User, Host, PasswordHash, HashMethod) ->
-    AccountPass = ejabberd_auth:get_password_s(User, Host),
-    AccountPassHash = case HashMethod of
-			  "md5" -> get_md5(AccountPass);
-			  "sha" -> get_sha(AccountPass);
-			  _ -> undefined
-		      end,
-    case AccountPassHash of
-	undefined -> error;
-	PasswordHash -> ok;
-	_ -> error
-    end.
-get_md5(AccountPass) ->
-    lists:flatten([io_lib:format("~.16B", [X])
-		   || X <- binary_to_list(crypto:md5(AccountPass))]).
-get_sha(AccountPass) ->
-    lists:flatten([io_lib:format("~.16B", [X])
-		   || X <- binary_to_list(crypto:sha(AccountPass))]).
-
-num_active_users(Host, Days) ->
-    list_last_activity(Host, true, Days).
-
-%% Code based on ejabberd/src/web/ejabberd_web_admin.erl
-list_last_activity(Host, Integral, Days) ->
-    {MegaSecs, Secs, _MicroSecs} = now(),
-    TimeStamp = MegaSecs * 1000000 + Secs,
-    TS = TimeStamp - Days * 86400,
-    case catch mnesia:dirty_select(
-		 last_activity, [{{last_activity, {'_', Host}, '$1', '_'},
-				  [{'>', '$1', TS}],
-				  [{'trunc', {'/',
-					      {'-', TimeStamp, '$1'},
-					      86400}}]}]) of
-							      {'EXIT', _Reason} ->
-		 [];
-	       Vals ->
-		 Hist = histogram(Vals, Integral),
-		 if
-		     Hist == [] ->
-			 0;
-		     true ->
-			 Left = Days - length(Hist),
-			 Tail = if
-				    Integral ->
-					lists:duplicate(Left, lists:last(Hist));
-				    true ->
-					lists:duplicate(Left, 0)
-				end,
-			 lists:nth(Days, Hist ++ Tail)
-		 end
-	 end.
-histogram(Values, Integral) ->
-    histogram(lists:sort(Values), Integral, 0, 0, []).
-histogram([H | T], Integral, Current, Count, Hist) when Current == H ->
-    histogram(T, Integral, Current, Count + 1, Hist);
-histogram([H | _] = Values, Integral, Current, Count, Hist) when Current < H ->
-    if
-	Integral ->
-	    histogram(Values, Integral, Current + 1, Count, [Count | Hist]);
-	true ->
-	    histogram(Values, Integral, Current + 1, 0, [Count | Hist])
-    end;
-histogram([], _Integral, _Current, Count, Hist) ->
-    if
-	Count > 0 ->
-	    lists:reverse([Count | Hist]);
-	true ->
-	    lists:reverse(Hist)
-    end.
-
-
-delete_old_users(Days) ->
-    %% Get the list of registered users
-    Users = ejabberd_auth:dirty_get_registered_users(),
-
-    {removed, N, UR} = delete_old_users(Days, Users),
-    {ok, io_lib:format("Deleted ~p users: ~p", [N, UR])}.
-
-delete_old_users_vhost(Host, Days) ->
-    %% Get the list of registered users
-    Users = ejabberd_auth:get_vh_registered_users(Host),
-
-    {removed, N, UR} = delete_old_users(Days, Users),
-    {ok, io_lib:format("Deleted ~p users: ~p", [N, UR])}.
-
-delete_old_users(Days, Users) ->
-    %% Convert older time
-    SecOlder = Days*24*60*60,
-
-    %% Get current time
-    {MegaSecs, Secs, _MicroSecs} = now(),
-    TimeStamp_now = MegaSecs * 1000000 + Secs,
-
-    %% For a user, remove if required and answer true
-    F = fun({LUser, LServer}) ->
-		%% Check if the user is logged
-		case ejabberd_sm:get_user_resources(LUser, LServer) of
-		    %% If it isnt
-		    [] ->
-			%% Look for his last_activity
-			case (get_lastactivity_module(LServer)):get_last_info(LUser, LServer) of
-			    %% If it is
-			    %% existent:
-			    {ok, TimeStamp, _Status} ->
-				%% get his age
-				Sec = TimeStamp_now - TimeStamp,
-				%% If he is
-				if
-				    %% younger than SecOlder:
-				    Sec < SecOlder ->
-					%% do nothing
-					false;
-				    %% older:
-				    true ->
-					%% remove the user
-					ejabberd_auth:remove_user(LUser, LServer),
-					true
-				end;
-			    %% nonexistent:
-			    not_found ->
-				%% remove the user
-				ejabberd_auth:remove_user(LUser, LServer),
-				true
-			end;
-		    %% Else
-		    _ ->
-			%% do nothing
-			false
-		end
-	end,
-    %% Apply the function to every user in the list
-    Users_removed = lists:filter(F, Users),
-    {removed, length(Users_removed), Users_removed}.
-
-get_lastactivity_module(Server) ->
-    case lists:member(mod_last, gen_mod:loaded_modules(Server)) of
-        true -> mod_last;
-        _ -> mod_last_odbc
-    end.
-
-
-%%
-%% Ban account
-
-ban_account(User, Host, ReasonText) ->
-    Reason = prepare_reason(ReasonText),
-    kick_sessions(User, Host, Reason),
-    set_random_password(User, Host, Reason),
-    ok.
-
-kick_sessions(User, Server, Reason) ->
-    lists:map(
-      fun(Resource) ->
-	      kick_this_session(User, Server, Resource, Reason)
-      end,
-      get_resources(User, Server)).
-
-get_resources(User, Server) ->
-    lists:map(
-      fun(Session) ->
-	      element(3, Session#session.usr)
-      end,
-      get_sessions(User, Server)).
-
-get_sessions(User, Server) ->
-    LUser = jlib:nodeprep(User),
-    LServer = jlib:nameprep(Server),
-    Sessions =  mnesia:dirty_index_read(session, {LUser, LServer}, #session.us),
-    true = is_list(Sessions),
-    Sessions.
-
-set_random_password(User, Server, Reason) ->
-    NewPass = build_random_password(Reason),
-    set_password_auth(User, Server, NewPass).
-
-build_random_password(Reason) ->
-    Date = jlib:timestamp_to_iso(calendar:universal_time()),
-    RandomString = randoms:get_string(),
-    <<"BANNED_ACCOUNT--", Date/binary, "--", RandomString/binary, "--", Reason/binary>>.
-
-set_password_auth(User, Server, Password) ->
-    ok = ejabberd_auth:set_password(User, Server, Password).
-
-prepare_reason([]) ->
-    <<"Kicked by administrator">>;
-prepare_reason([Reason]) ->
-    Reason;
-prepare_reason(Reason) when is_binary(Reason) ->
-    Reason.
-
-%%%
-%%% Sessions
-%%%
-
-num_resources(User, Host) ->
-    length(ejabberd_sm:get_user_resources(User, Host)).
-
-resource_num(User, Host, Num) ->
-    Resources = ejabberd_sm:get_user_resources(User, Host),
-    case (0<Num) and (Num=<length(Resources)) of
-	true ->
-	    lists:nth(Num, Resources);
-	false ->
-	    lists:flatten(io_lib:format("Error: Wrong resource number: ~p", [Num]))
-    end.
-
-kick_session(User, Server, Resource, ReasonText) ->
-    kick_this_session(User, Server, Resource, prepare_reason(ReasonText)),
-    ok.
-
-kick_this_session(User, Server, Resource, Reason) ->
-    ejabberd_sm:route(jlib:make_jid(<<"">>, <<"">>, <<"">>),
-                      jlib:make_jid(User, Server, Resource),
-                      {broadcast, {exit, Reason}}).
-
-status_num(Host, Status) ->
-    length(get_status_list(Host, Status)).
-status_num(Status) ->
-    status_num(<<"all">>, Status).
-status_list(Host, Status) ->
-    Res = get_status_list(Host, Status),
-    [{U, S, R, P, St} || {U, S, R, P, St} <- Res].
-status_list(Status) ->
-    status_list(<<"all">>, Status).
-
-
-get_status_list(Host, Status_required) ->
-    %% Get list of all logged users
-    Sessions = ejabberd_sm:dirty_get_my_sessions_list(),
-    %% Reformat the list
-    Sessions2 = [ {Session#session.usr, Session#session.sid, Session#session.priority} || Session <- Sessions],
-    Fhost = case Host of
-		<<"all">> ->
-		    %% All hosts are requested, so dont filter at all
-		    fun(_, _) -> true end;
-		_ ->
-		    %% Filter the list, only Host is interesting
-		    fun(A, B) -> A == B end
-	    end,
-    Sessions3 = [ {Pid, Server, Priority} || {{_User, Server, _Resource}, {_, Pid}, Priority} <- Sessions2, apply(Fhost, [Server, Host])],
-    %% For each Pid, get its presence
-    Sessions4 = [ {catch ejabberd_c2s:get_presence(Pid), Server, Priority} || {Pid, Server, Priority} <- Sessions3],
-    %% Filter by status
-    Fstatus = case Status_required of
-		  <<"all">> ->
-		      fun(_, _) -> true end;
-		  _ ->
-		      fun(A, B) -> A == B end
-	      end,
-    [{User, Server, Resource, Priority, stringize(Status_text)}
-     || {{User, Resource, Status, Status_text}, Server, Priority} <- Sessions4,
-	apply(Fstatus, [Status, Status_required])].
-
-connected_users_info() ->
-    USRIs = dirty_get_sessions_list2(),
-    CurrentSec = calendar:datetime_to_gregorian_seconds({date(), time()}),
-    lists:map(
-      fun([{U, S, R}, {Now, Pid}, Priority, Info]) ->
-	      Conn = proplists:get_value(conn, Info),
-	      {Ip, Port} = proplists:get_value(ip, Info),
-	      IPS = inet_parse:ntoa(Ip),
-	      NodeS = atom_to_list(node(Pid)),
-	      Uptime = CurrentSec - calendar:datetime_to_gregorian_seconds(
-				      calendar:now_to_local_time(Now)),
-	      PriorityI = case Priority of
-			      PI when is_integer(PI) -> PI;
-			      _ -> nil
-			  end,
-	      {[U, $@, S, $/, R], atom_to_list(Conn), IPS, Port, PriorityI, NodeS, Uptime}
-      end,
-      USRIs).
-
-connected_users_vhost(Host) ->
-    USRs = ejabberd_sm:get_vh_session_list(Host),
-    [ [U, $@, S, $/, R] || {U, S, R} <- USRs].
-
-%% Code copied from ejabberd_sm.erl and customized
-dirty_get_sessions_list2() ->
-    mnesia:dirty_select(
-      session,
-      [{#session{usr = '$1', sid = '$2', priority = '$3', info = '$4', _ = '_'},
-	[],
-	[['$1', '$2', '$3', '$4']]}]).
-
-%% Make string more print-friendly
-stringize(String) ->
-    %% Replace newline characters with other code
-    ejabberd_regexp:greplace(String, <<"\n">>, <<"\\n">>).
-
-set_presence(User, Host, Resource, Type, Show, Status, Priority) ->
-    Pid = ejabberd_sm:get_session_pid(User, Host, Resource),
-    USR = jlib:jid_to_string(jlib:make_jid(User, Host, Resource)),
-    US = jlib:jid_to_string(jlib:make_jid(User, Host, <<>>)),
-    Message = {route_xmlstreamelement,
-	       {xmlel, <<"presence">>,
-		[{<<"from">>, USR}, {<<"to">>, US}, {<<"type">>, Type}],
-		[{xmlel, <<"show">>, [], [{xmlcdata, Show}]},
-		 {xmlel, <<"status">>, [], [{xmlcdata, Status}]},
-		 {xmlel, <<"priority">>, [], [{xmlcdata, Priority}]}]}},
-    Pid ! Message.
-
-user_sessions_info(User, Host) ->
-    CurrentSec = calendar:datetime_to_gregorian_seconds({date(), time()}),
-    US = {User, Host},
-    Sessions = case catch mnesia:dirty_index_read(session, US, #session.us) of
-		   {'EXIT', _Reason} ->
-		       [];
-		   Ss ->
-		       Ss
-	       end,
-    lists:map(
-      fun(Session) ->
-	      {_U, _S, Resource} = Session#session.usr,
-	      {Now, Pid} = Session#session.sid,
-	      {_U, _Resource, Status, StatusText} = ejabberd_c2s:get_presence(Pid),
-	      Info = Session#session.info,
-	      Priority = Session#session.priority,
-	      Conn = proplists:get_value(conn, Info),
-	      {Ip, Port} = proplists:get_value(ip, Info),
-	      IPS = inet_parse:ntoa(Ip),
-	      NodeS = atom_to_list(node(Pid)),
-	      Uptime = CurrentSec - calendar:datetime_to_gregorian_seconds(
-				      calendar:now_to_local_time(Now)),
-	      {atom_to_list(Conn), IPS, Port, Priority, NodeS, Uptime, Status, Resource, StatusText}
-      end,
-      Sessions).
-
-
-%%%
-%%% Vcard
-%%%
-
-set_nickname(User, Host, Nickname) ->
-    R = mod_vcard:process_sm_iq(
-	  {jid, User, Host, <<>>, User, Host, <<>>},
-	  {jid, User, Host, <<>>, User, Host, <<>>},
-	  {iq, <<>>, set, <<>>, <<"en">>,
-	   {xmlel, <<"vCard">>, [
-	     {<<"xmlns">>, <<"vcard-temp">>}], [
-		{xmlel, <<"NICKNAME">>, [], [{xmlcdata, Nickname}]}
-            ]
-	  }}),
-    case R of
-	{iq, <<>>, result, <<>>, _L, []} ->
-	    ok;
-	_ ->
-	    error
-    end.
-
-get_vcard(User, Host, Name) ->
-    [Res | _] = get_vcard_content(User, Host, [Name]),
-    Res.
-
-get_vcard(User, Host, Name, Subname) ->
-    [Res | _] = get_vcard_content(User, Host, [Name, Subname]),
-    Res.
-
-get_vcard_multi(User, Host, Name, Subname) ->
-    get_vcard_content(User, Host, [Name, Subname]).
-
-set_vcard(User, Host, Name, SomeContent) ->
-    set_vcard_content(User, Host, [Name], SomeContent).
-
-set_vcard(User, Host, Name, Subname, SomeContent) ->
-    set_vcard_content(User, Host, [Name, Subname], SomeContent).
-
-
-%%
-%% Internal vcard
-
-get_module_resource(Server) ->
-    case gen_mod:get_module_opt(Server, ?MODULE, module_resource, fun(A) -> A end, none) of
-	none -> list_to_binary(atom_to_list(?MODULE));
-	R when is_binary(R) -> R
-    end.
-
-get_vcard_content(User, Server, Data) ->
-    [{_, Module, Function, _Opts}] = ets:lookup(sm_iqtable, {?NS_VCARD, Server}),
-    JID = jlib:make_jid(User, Server, get_module_resource(Server)),
-    IQ = #iq{type = get, xmlns = ?NS_VCARD},
-    IQr = Module:Function(JID, JID, IQ),
-    [A1] = IQr#iq.sub_el,
-    case A1#xmlel.children of
-	[_|_] ->
-	    case get_vcard(Data, A1) of
-		[false] -> throw(error_no_value_found_in_vcard);
-		ElemList -> ?DEBUG("ELS ~p", [ElemList]), [xml:get_tag_cdata(Elem) || Elem <- ElemList]
-	    end;
-	[] ->
-	    throw(error_no_vcard_found)
-    end.
-
-get_vcard([<<"TEL">>, TelType], {_, _, _, OldEls}) ->
-    {TakenEl, _NewEls} = take_vcard_tel(TelType, OldEls, [], not_found),
-    [TakenEl];
-
-get_vcard([Data1, Data2], A1) ->
-    case get_subtag(A1, Data1) of
-	[false] -> [false];
-	A2List ->
-	    lists:flatten([get_vcard([Data2], A2) || A2 <- A2List])
-    end;
-
-get_vcard([Data], A1) ->
-    get_subtag(A1, Data).
-
-get_subtag(Xmlelement, Name) ->
-    [xml:get_subtag(Xmlelement, Name)].
-
-set_vcard_content(User, Server, Data, SomeContent) ->
-    ContentList = case SomeContent of
-	[Bin | _] when is_binary(Bin) -> SomeContent;
-	Bin when is_binary(Bin) -> [SomeContent]
-    end,
-    [{_, Module, Function, _Opts}] = ets:lookup(sm_iqtable, {?NS_VCARD, Server}),
-    JID = jlib:make_jid(User, Server, get_module_resource(Server)),
-    IQ = #iq{type = get, xmlns = ?NS_VCARD},
-    IQr = Module:Function(JID, JID, IQ),
-
-    %% Get old vcard
-    A4 = case IQr#iq.sub_el of
-	     [A1] ->
-		 {_, _, _, A2} = A1,
-		 update_vcard_els(Data, ContentList, A2);
-	     [] ->
-		 update_vcard_els(Data, ContentList, [])
-	 end,
-
-    %% Build new vcard
-    SubEl = {xmlel, <<"vCard">>, [{<<"xmlns">>,<<"vcard-temp">>}], A4},
-    IQ2 = #iq{type=set, sub_el = SubEl},
-
-    Module:Function(JID, JID, IQ2),
-    ok.
-
-take_vcard_tel(TelType, [{xmlel, <<"TEL">>, _, SubEls}=OldEl | OldEls], NewEls, Taken) ->
-    {Taken2, NewEls2} = case lists:keymember(TelType, 2, SubEls) of
-	true -> {xml:get_subtag(OldEl, <<"NUMBER">>), NewEls};
-	false -> {Taken, [OldEl | NewEls]}
-    end,
-    take_vcard_tel(TelType, OldEls, NewEls2, Taken2);
-take_vcard_tel(TelType, [OldEl | OldEls], NewEls, Taken) ->
-    take_vcard_tel(TelType, OldEls, [OldEl | NewEls], Taken);
-take_vcard_tel(_TelType, [], NewEls, Taken) ->
-    {Taken, NewEls}.
-
-update_vcard_els([<<"TEL">>, TelType], [TelValue], OldEls) ->
-    {_, NewEls} = take_vcard_tel(TelType, OldEls, [], not_found),
-    NewEl = {xmlel,<<"TEL">>,[],
-             [{xmlel,TelType,[],[]},
-              {xmlel,<<"NUMBER">>,[],[{xmlcdata,TelValue}]}]},
-    [NewEl | NewEls];
-
-update_vcard_els(Data, ContentList, Els1) ->
-    Els2 = lists:keysort(2, Els1),
-    [Data1 | Data2] = Data,
-    NewEls = case Data2 of
-		[] ->
-		    [{xmlel, Data1, [], [{xmlcdata,Content}]} || Content <- ContentList];
-		[D2] ->
-		    OldEl = case lists:keysearch(Data1, 2, Els2) of
-				{value, A} -> A;
-				false -> {xmlel, Data1, [], []}
-			    end,
-		    {xmlel, _, _, ContentOld1} = OldEl,
-		    Content2 = [{xmlel, D2, [], [{xmlcdata,Content}]} || Content <- ContentList],
-		    ContentOld2 = [A || {_, X, _, _} = A <- ContentOld1, X/=D2],
-		    ContentOld3 = lists:keysort(2, ContentOld2),
-		    ContentNew = lists:keymerge(2, Content2, ContentOld3),
-		    [{xmlel, Data1, [], ContentNew}]
-	    end,
-    Els3 = lists:keydelete(Data1, 2, Els2),
-    lists:keymerge(2, NewEls, Els3).
-
-
-%%%
-%%% Roster
-%%%
-
-add_rosteritem(LocalUser, LocalServer, User, Server, Nick, Group, Subs) ->
-    case add_rosteritem(LocalUser, LocalServer, User, Server, Nick, Group, Subs, []) of
-	{atomic, ok} ->
-	    push_roster_item(LocalUser, LocalServer, User, Server, {add, Nick, Subs, Group}),
-	    ok;
-	_ ->
-	    error
-    end.
-
-add_rosteritem(LU, LS, User, Server, Nick, Group, Subscription, Xattrs) ->
-    subscribe(LU, LS, User, Server, Nick, Group, Subscription, Xattrs).
-
-subscribe(LU, LS, User, Server, Nick, Group, Subscription, _Xattrs) ->
-    ItemEl = build_roster_item(User, Server, {add, Nick, Subscription, Group}),
-    mod_roster:set_items(
-	LU, LS,
-	{xmlel, <<"query">>,
-            [{<<"xmlns">>, <<"jabber:iq:roster">>}],
-            [ItemEl]}).
-
-delete_rosteritem(LocalUser, LocalServer, User, Server) ->
-    case unsubscribe(LocalUser, LocalServer, User, Server) of
-	{atomic, ok} ->
-	    push_roster_item(LocalUser, LocalServer, User, Server, remove),
-	    ok;
-	_  ->
-	    error
-    end.
-
-unsubscribe(LU, LS, User, Server) ->
-    ItemEl = build_roster_item(User, Server, remove),
-    mod_roster:set_items(
-	LU, LS,
-	{xmlel, <<"query">>,
-            [{<<"xmlns">>, <<"jabber:iq:roster">>}],
-            [ItemEl]}).
-
-%% -----------------------------
-%% Get Roster
-%% -----------------------------
-
-get_roster(User, Server) ->
-    Items = ejabberd_hooks:run_fold(roster_get, Server, [], [{User, Server}]),
-    make_roster_xmlrpc(Items).
-
-%% Note: if a contact is in several groups, the contact is returned
-%% several times, each one in a different group.
-make_roster_xmlrpc(Roster) ->
-    lists:foldl(
-      fun(Item, Res) ->
-	      JIDS = jlib:jid_to_string(Item#roster.jid),
-	      Nick = Item#roster.name,
-	      Subs = atom_to_list(Item#roster.subscription),
-	      Ask = atom_to_list(Item#roster.ask),
-	      Groups = case Item#roster.groups of
-			   [] -> [<<>>];
-			   Gs -> Gs
-		       end,
-	      ItemsX = [{JIDS, Nick, Subs, Ask, Group} || Group <- Groups],
-	      ItemsX ++ Res
-      end,
-      [],
-      Roster).
-
-
-%%-----------------------------
-%% Push Roster from file
-%%-----------------------------
-
-push_roster(File, User, Server) ->
-    {ok, [Roster]} = file:consult(File),
-    subscribe_roster({User, Server, <<>>, User}, Roster).
-
-push_roster_all(File) ->
-    {ok, [Roster]} = file:consult(File),
-    subscribe_all(Roster).
-
-subscribe_all(Roster) ->
-    subscribe_all(Roster, Roster).
-subscribe_all([], _) ->
-    ok;
-subscribe_all([User1 | Users], Roster) ->
-    subscribe_roster(User1, Roster),
-    subscribe_all(Users, Roster).
-
-subscribe_roster(_, []) ->
-    ok;
-%% Do not subscribe a user to itself
-subscribe_roster({Name, Server, Group, Nick}, [{Name, Server, _, _} | Roster]) ->
-    subscribe_roster({Name, Server, Group, Nick}, Roster);
-%% Subscribe Name2 to Name1
-subscribe_roster({Name1, Server1, Group1, Nick1}, [{Name2, Server2, Group2, Nick2} | Roster]) ->
-    subscribe(Name1, Server1, Name2, Server2, Nick2, Group2, <<"both">>, []),
-    subscribe_roster({Name1, Server1, Group1, Nick1}, Roster).
-
-push_alltoall(S, G) ->
-    Users = ejabberd_auth:get_vh_registered_users(S),
-    Users2 = build_list_users(G, Users, []),
-    subscribe_all(Users2),
-    ok.
-
-build_list_users(_Group, [], Res) ->
-    Res;
-build_list_users(Group, [{User, Server}|Users], Res) ->
-    build_list_users(Group, Users, [{User, Server, Group, User}|Res]).
-
-%% @spec(LU, LS, U, S, Action) -> ok
-%%       Action = {add, Nick, Subs, Group} | remove
-%% @doc Push to the roster of account LU@LS the contact U@S.
-%% The specific action to perform is defined in Action.
-push_roster_item(LU, LS, U, S, Action) ->
-    lists:foreach(fun(R) ->
-			  push_roster_item(LU, LS, R, U, S, Action)
-		  end, ejabberd_sm:get_user_resources(LU, LS)).
-
-push_roster_item(LU, LS, R, U, S, Action) ->
-    LJID = jlib:make_jid(LU, LS, R),
-    BroadcastEl = build_broadcast(U, S, Action),
-    ejabberd_sm:route(LJID, LJID, BroadcastEl),
-    Item = build_roster_item(U, S, Action),
-    ResIQ = build_iq_roster_push(Item),
-    ejabberd_router:route(LJID, LJID, ResIQ).
-
-build_roster_item(U, S, {add, Nick, Subs, Group}) ->
-    {xmlel, <<"item">>,
-     [{<<"jid">>, jlib:jid_to_string(jlib:make_jid(U, S, <<>>))},
-      {<<"name">>, Nick},
-      {<<"subscription">>, Subs}],
-     [{xmlel, <<"group">>, [], [{xmlcdata, Group}]}]
-    };
-build_roster_item(U, S, remove) ->
-    {xmlel, <<"item">>,
-     [{<<"jid">>, jlib:jid_to_string(jlib:make_jid(U, S, <<>>))},
-      {<<"subscription">>, <<"remove">>}],
-     []
-    }.
-
-build_iq_roster_push(Item) ->
-    {xmlel, <<"iq">>,
-     [{<<"type">>, <<"set">>}, {<<"id">>, <<"push">>}],
-     [{xmlel, <<"query">>,
-       [{<<"xmlns">>, ?NS_ROSTER}],
-       [Item]
-      }
-     ]
-    }.
-
-build_broadcast(U, S, {add, _Nick, Subs, _Group}) ->
-    build_broadcast(U, S, list_to_atom(binary_to_list(Subs)));
-build_broadcast(U, S, remove) ->
-    build_broadcast(U, S, none);
-%% @spec (U::binary(), S::binary(), Subs::atom()) -> any()
-%% Subs = both | from | to | none
-build_broadcast(U, S, SubsAtom) when is_atom(SubsAtom) ->
-    {broadcast, {item, {U, S, <<>>}, SubsAtom}}.
-
-%%%
-%%% Last Activity
-%%%
-
-get_last(User, Server) ->
-    Mod = get_lastactivity_module(Server),
-    case ejabberd_sm:get_user_resources(User, Server) of
-        [] ->
-            case Mod:get_last_info(User, Server) of
-                not_found ->
-                    "Never";
-                {ok, Shift, _Status} ->
-                    TimeStamp = {Shift div 1000000,
-                        Shift rem 1000000,
-                        0},
-                    {{Year, Month, Day}, {Hour, Minute, Second}} =
-                        calendar:now_to_local_time(TimeStamp),
-                    lists:flatten(
-                        io_lib:format(
-                            "~w-~.2.0w-~.2.0w ~.2.0w:~.2.0w:~.2.0w",
-                            [Year, Month, Day, Hour, Minute, Second]))
-            end;
-        _ ->
-            "Online"
-    end.
-
-set_last(User, Server, Timestamp, Status) ->
-    Mod = get_lastactivity_module(Server),
-    Mod:store_last_info(User, Server, Timestamp, Status).
-
-%%%
-%%% Private Storage
-%%%
-
-%% Example usage:
-%% $ ejabberdctl private_set badlop localhost "\<aa\ xmlns=\'bb\'\>Cluth\</aa\>"
-%% $ ejabberdctl private_get badlop localhost aa bb
-%% <aa xmlns='bb'>Cluth</aa>
-
-private_get(Username, Host, Element, Ns) ->
-    From = jlib:make_jid(Username, Host, <<>>),
-    To = jlib:make_jid(Username, Host, <<>>),
-    IQ = {iq, <<>>, get, ?NS_PRIVATE, <<>>,
-	  {xmlel, <<"query">>,
-	   [{<<"xmlns">>,?NS_PRIVATE}],
-	   [{xmlel, Element, [{<<"xmlns">>, Ns}], []}]}},
-    ResIq = mod_private:process_sm_iq(From, To, IQ),
-    [{xmlel, <<"query">>,
-      [{<<"xmlns">>, <<"jabber:iq:private">>}],
-      [SubEl]}] = ResIq#iq.sub_el,
-    binary_to_list(xml:element_to_binary(SubEl)).
-
-private_set(Username, Host, ElementString) ->
-    case xml_stream:parse_element(ElementString) of
-	{error, Error} ->
-	    io:format("Error found parsing the element:~n  ~p~nError: ~p~n",
-		      [ElementString, Error]),
-	    error;
-	Xml ->
-	    private_set2(Username, Host, Xml)
-    end.
-
-private_set2(Username, Host, Xml) ->
-    From = jlib:make_jid(Username, Host, <<>>),
-    To = jlib:make_jid(Username, Host, <<>>),
-    IQ = {iq, <<>>, set, ?NS_PRIVATE, <<>>,
-	  {xmlel, <<"query">>,
-	   [{<<"xmlns">>, ?NS_PRIVATE}],
-	   [Xml]}},
-    mod_private:process_sm_iq(From, To, IQ),
-    ok.
-
-%%%
-%%% Shared Roster Groups
-%%%
-
-srg_create(Group, Host, Name, Description, Display) ->
-    DisplayList = case Display of
-	<<>> -> [];
-	_ -> ejabberd_regexp:split(Display, <<"\\\\n">>)
-    end,
-    Opts = [{name, Name},
-	    {displayed_groups, DisplayList},
-	    {description, Description}],
-    {atomic, ok} = mod_shared_roster:create_group(Host, Group, Opts),
-    ok.
-
-srg_delete(Group, Host) ->
-    {atomic, ok} = mod_shared_roster:delete_group(Host, Group),
-    ok.
-
-srg_list(Host) ->
-    lists:sort(mod_shared_roster:list_groups(Host)).
-
-srg_get_info(Group, Host) ->
-    Opts = case mod_shared_roster:get_group_opts(Host,Group) of
-	Os when is_list(Os) -> Os;
-	error -> []
-    end,
-    [{jlib:atom_to_binary(Title),
-      io_lib:format("~p", [btl(Value)])} || {Title, Value} <- Opts].
-
-btl([]) -> [];
-btl([B|L]) -> [btl(B)|btl(L)];
-btl(B) -> binary_to_list(B).
-
-srg_get_members(Group, Host) ->
-    Members = mod_shared_roster:get_group_explicit_users(Host,Group),
-    [jlib:jid_to_string(jlib:make_jid(MUser, MServer, <<>>))
-     || {MUser, MServer} <- Members].
-
-srg_user_add(User, Host, Group, GroupHost) ->
-    {atomic, ok} = mod_shared_roster:add_user_to_group(GroupHost, {User, Host}, Group),
-    ok.
-
-srg_user_del(User, Host, Group, GroupHost) ->
-    {atomic, ok} = mod_shared_roster:remove_user_from_group(GroupHost, {User, Host}, Group),
-    ok.
-
-
-%%%
-%%% Stanza
-%%%
-
-%% @doc Send a message to a Jabber account.
-%% @spec (Type::binary(), From::binary(), To::binary(), Subject::binary(), Body::binary()) -> ok
-send_message(Type, From, To, Subject, Body) ->
-    Packet = build_packet(Type, Subject, Body),
-    send_packet_all_resources(From, To, Packet).
-
-%% @doc Send a packet to a Jabber account.
-%% If a resource was specified in the JID,
-%% the packet is sent only to that specific resource.
-%% If no resource was specified in the JID,
-%% and the user is remote or local but offline,
-%% the packet is sent to the bare JID.
-%% If the user is local and is online in several resources,
-%% the packet is sent to all its resources.
-send_packet_all_resources(FromJIDString, ToJIDString, Packet) ->
-    FromJID = jlib:string_to_jid(FromJIDString),
-    ToJID = jlib:string_to_jid(ToJIDString),
-    ToUser = ToJID#jid.user,
-    ToServer = ToJID#jid.server,
-    case ToJID#jid.resource of
-	<<>> ->
-	    send_packet_all_resources(FromJID, ToUser, ToServer, Packet);
-	Res ->
-	    send_packet_all_resources(FromJID, ToUser, ToServer, Res, Packet)
-    end.
-
-send_packet_all_resources(FromJID, ToUser, ToServer, Packet) ->
-    case ejabberd_sm:get_user_resources(ToUser, ToServer) of
-	[] ->
-	    send_packet_all_resources(FromJID, ToUser, ToServer, <<>>, Packet);
-	ToResources ->
-	    lists:foreach(
-	      fun(ToResource) ->
-		      send_packet_all_resources(FromJID, ToUser, ToServer,
-						ToResource, Packet)
-	      end,
-	      ToResources)
-    end.
-
-send_packet_all_resources(FromJID, ToU, ToS, ToR, Packet) ->
-    ToJID = jlib:make_jid(ToU, ToS, ToR),
-    ejabberd_router:route(FromJID, ToJID, Packet).
-
-build_packet(Type, Subject, Body) ->
-    Tail = if Subject == <<"">>; Type == <<"chat">> -> [];
-	      true -> [{xmlel, <<"subject">>, [], [{xmlcdata, Subject}]}]
-	   end,
-    {xmlel, <<"message">>,
-     [{<<"type">>, Type}, {<<"id">>, randoms:get_string()}],
-     [{xmlel, <<"body">>, [], [{xmlcdata, Body}]} | Tail]
-    }.
-
-send_stanza_c2s(Username, Host, Resource, Stanza) ->
-    C2sPid = ejabberd_sm:get_session_pid(Username, Host, Resource),
-    XmlEl = xml_stream:parse_element(Stanza),
-    p1_fsm:send_event(C2sPid, {xmlstreamelement, XmlEl}).
-
-privacy_set(Username, Host, QueryS) ->
-    From = jlib:make_jid(Username, Host, <<"">>),
-    To = jlib:make_jid(<<"">>, Host, <<"">>),
-    QueryEl = xml_stream:parse_element(QueryS),
-    StanzaEl = {xmlel, <<"iq">>, [{<<"type">>, <<"set">>}], [QueryEl]},
-    IQ = jlib:iq_query_info(StanzaEl),
-    ejabberd_hooks:run_fold(
-		     privacy_iq_set,
-		     Host,
-		     {error, ?ERR_FEATURE_NOT_IMPLEMENTED},
-		     [From, To, IQ]
-		    ),
-    ok.
-
-%%%
-%%% Stats
-%%%
-
-stats(Name) ->
-    case Name of
-	<<"uptimeseconds">> -> trunc(element(1, erlang:statistics(wall_clock))/1000);
-	<<"registeredusers">> -> lists:foldl(fun(Host, Sum) -> ejabberd_auth:get_vh_registered_users_number(Host) + Sum end, 0, ?MYHOSTS);
-	<<"onlineusersnode">> -> length(ejabberd_sm:dirty_get_my_sessions_list());
-	<<"onlineusers">> -> length(ejabberd_sm:dirty_get_sessions_list())
-    end.
-
-stats(Name, Host) ->
-    case Name of
-	<<"registeredusers">> -> ejabberd_auth:get_vh_registered_users_number(Host);
-	<<"onlineusers">> -> length(ejabberd_sm:get_vh_session_list(Host))
-    end.
-
-
-
-%%-----------------------------
-%% Purge roster items
-%%-----------------------------
-
-process_rosteritems(ActionS, SubsS, AsksS, UsersS, ContactsS) ->
-    Action = case ActionS of
-		 "list" -> list;
-		 "delete" -> delete
-	     end,
-
-    Subs = lists:foldl(
-	     fun(any, _) -> [none, from, to, both];
-		(Sub, Subs) -> [Sub | Subs]
-	     end,
-	     [],
-	     [list_to_atom(S) || S <- string:tokens(SubsS, ":")]
-	    ),
-
-    Asks = lists:foldl(
-	     fun(any, _) -> [none, out, in];
-		(Ask, Asks) -> [Ask | Asks]
-	     end,
-	     [],
-	     [list_to_atom(S) || S <- string:tokens(AsksS, ":")]
-	    ),
-
-    Users = lists:foldl(
-	      fun("any", _) -> ["*", "*@*"];
-		 (U, Us) -> [U | Us]
-	      end,
-	      [],
-	      [S || S <- string:tokens(UsersS, ":")]
-	     ),
-
-    Contacts = lists:foldl(
-		 fun("any", _) -> ["*", "*@*"];
-		    (U, Us) -> [U | Us]
-		 end,
-		 [],
-		 [S || S <- string:tokens(ContactsS, ":")]
-		),
-
-    rosteritem_purge({Action, Subs, Asks, Users, Contacts}).
-
-%% @spec ({Action::atom(), Subs::[atom()], Asks::[atom()], User::string(), Contact::string()}) -> {atomic, ok}
-rosteritem_purge(Options) ->
-    Num_rosteritems = mnesia:table_info(roster, size),
-    io:format("There are ~p roster items in total.~n", [Num_rosteritems]),
-    Key = mnesia:dirty_first(roster),
-    rip(Key, Options, {0, Num_rosteritems, 0, 0}, []).
-
-rip('$end_of_table', _Options, Counters, Res) ->
-    print_progress_line(Counters),
-    Res;
-rip(Key, Options, {Pr, NT, NV, ND}, Res) ->
-    Key_next = mnesia:dirty_next(roster, Key),
-    {Action, _, _, _, _} = Options,
-    {ND2, Res2} = case decide_rip(Key, Options) of
-	      true ->
-		  Jids = apply_action(Action, Key),
-		  {ND+1, [Jids | Res]};
-	      false ->
-		  {ND, Res}
-	  end,
-    NV2 = NV+1,
-    Pr2 = print_progress_line({Pr, NT, NV2, ND2}),
-    rip(Key_next, Options, {Pr2, NT, NV2, ND2}, Res2).
-
-apply_action(list, Key) ->
-    {User, Server, JID} = Key,
-    {RUser, RServer, _} = JID,
-    Jid1string = <<User/binary, "@", Server/binary>>,
-    Jid2string = <<RUser/binary, "@", RServer/binary>>,
-    io:format("Matches: ~s ~s~n", [Jid1string, Jid2string]),
-    {Jid1string, Jid2string};
-apply_action(delete, Key) ->
-    R = apply_action(list, Key),
-    mnesia:dirty_delete(roster, Key),
-    R.
-
-print_progress_line({_Pr, 0, _NV, _ND}) ->
-    ok;
-print_progress_line({Pr, NT, NV, ND}) ->
-    Pr2 = trunc((NV/NT)*100),
-    case Pr == Pr2 of
-	true ->
-	    ok;
-	false ->
-	    io:format("Progress ~p% - visited ~p - deleted ~p~n", [Pr2, NV, ND])
-    end,
-    Pr2.
-
-decide_rip(Key, {_Action, Subs, Asks, User, Contact}) ->
-    case catch mnesia:dirty_read(roster, Key) of
-	[RI] ->
-	    lists:member(RI#roster.subscription, Subs)
-		andalso lists:member(RI#roster.ask, Asks)
-		andalso decide_rip_jid(RI#roster.us, User)
-		andalso decide_rip_jid(RI#roster.jid, Contact);
-	_ ->
-	    false
-    end.
-
-%% Returns true if the server of the JID is included in the servers
-decide_rip_jid({UName, UServer, _UResource}, Match_list) ->
-    decide_rip_jid({UName, UServer}, Match_list);
-decide_rip_jid({UName, UServer}, Match_list) ->
-    lists:any(
-      fun(Match_string) ->
-	      MJID = jlib:string_to_jid(list_to_binary(Match_string)),
-	      MName = MJID#jid.luser,
-	      MServer = MJID#jid.lserver,
-	      Is_server = is_glob_match(UServer, MServer),
-	      case MName of
-		  <<>> when UName == <<>> ->
-		      Is_server;
-		  <<>> ->
-		      false;
-		  _ ->
-		      Is_server
-			  andalso is_glob_match(UName, MName)
-	      end
-      end,
-      Match_list).
-
-%% Copied from ejabberd-2.0.0/src/acl.erl
-is_regexp_match(String, RegExp) ->
-    case ejabberd_regexp:run(String, RegExp) of
-	nomatch ->
-	    false;
-	match ->
-	    true;
-	{error, ErrDesc} ->
-	    io:format(
-	      "Wrong regexp ~p in ACL: ~p",
-	      [RegExp, ErrDesc]),
-	    false
-    end.
-is_glob_match(String, <<"!", Glob/binary>>) ->
-    not is_regexp_match(String, ejabberd_regexp:sh_to_awk(Glob));
-is_glob_match(String, Glob) ->
-    is_regexp_match(String, ejabberd_regexp:sh_to_awk(Glob)).
diff --git a/mod_admin_extra/src/mod_ecomm_test.erl b/mod_admin_extra/src/mod_ecomm_test.erl
deleted file mode 100644
index 99ff641..0000000
--- a/mod_admin_extra/src/mod_ecomm_test.erl
+++ /dev/null
@@ -1,426 +0,0 @@
-%%%-------------------------------------------------------------------
-%%% File    : mod_ecomm_test.erl
-%%% Author  : Badlop <badlop@process-one.net>
-%%% Purpose : Simple commands for testing
-%%% Created : 10 Aug 2008 by Badlop <badlop@process-one.net>
-%%%
-%%%
-%%% ejabberd, Copyright (C) 2002-2008   ProcessOne
-%%%
-%%% This program is free software; you can redistribute it and/or
-%%% modify it under the terms of the GNU General Public License as
-%%% published by the Free Software Foundation; either version 2 of the
-%%% License, or (at your option) any later version.
-%%%
-%%% This program is distributed in the hope that it will be useful,
-%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
-%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-%%% General Public License for more details.
-%%%
-%%% You should have received a copy of the GNU General Public License along
-%%% with this program; if not, write to the Free Software Foundation, Inc.,
-%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-%%%
-%%%-------------------------------------------------------------------
-
--module(mod_ecomm_test).
--author('badlop@process-one.net').
-
--behaviour(gen_mod).
-
--export([start/2, stop/1,
-	 %% Take: test arguments
-	 take_integer/1,
-	 take_string/1,
-	 take_integer_string/2,
-	 take_tuple_2integer/1,
-	 take_tuple_2string/1,
-	 take_list_integer/1,
-	 take_list_string/1,
-	 %% Echo: test arguments and result
-	 echo_integer/1,
-	 echo_string/1,
-	 echo_integer_string/2,
-	 echo_list_integer/1,
-	 echo_list_string/1,
-	 echo_integer_list_string/2,
-	 echo_isatils/4,
-	 %% Tell: test result
-	 tell_atom/1,
-	 tell_rescode/1,
-	 tell_restuple/1,
-	 tell_tuple_3integer/0,
-	 tell_tuple_3string/0,
-	 tell_tuple_3atom/0,
-	 tell_tuple_3list/0,
-	 tell_list_3integer/0,
-	 tell_list_3string/0,
-	 tell_list_3atom/0,
-	 tell_list_3tuple/0,
-	 %% Realistic
-	 this_crashes/1,
-	 this_wrong_args/1,
-	 this_wrong_return/0,
-	 pow/2, seq/2, substrs/1, splitjid/1, splitjids/1
-	]).
-
--include("ejabberd.hrl").
--include("ejabberd_commands.hrl").
--include("jlib.hrl").
-
-start(_Host, _Opts) ->
-    ejabberd_commands:register_commands(commands()).
-
-stop(_Host) ->
-    ejabberd_commands:unregister_commands(commands()).
-
-%%%
-%%% ejabberd commands
-%%%
-
-commands() ->
-    [
-
-     #ejabberd_commands{name = take_integer, tags = [test],
-		       desc = "Take Integer in args, give Integer zero",
-		       module = ?MODULE, function = take_integer,
-		       args = [{thisinteger, integer}],
-		       result = {zero, integer}},
-
-     #ejabberd_commands{name = take_string, tags = [test],
-		       desc = "Take String, give Integer zero",
-		       module = ?MODULE, function = take_string,
-		       args = [{thisstring, string}],
-		       result = {zero, integer}},
-
-     #ejabberd_commands{name = take_integer_string, tags = [test],
-		       desc = "Take integer and string, give Integer zero",
-		       module = ?MODULE, function = take_integer_string,
-		       args = [{thisinteger, integer}, {thisstring, string}],
-		       result = {zero, integer}},
-
-     %% Not supported by ejabberd_ctl
-     #ejabberd_commands{name = take_tuple_2integer, tags = [test],
-		       desc = "Take Tuple of two integers, give Integer zero",
-		       module = ?MODULE, function = take_tuple_2integer,
-		       args = [{thistuple, {tuple, [{thisinteger1, integer}, {thisinteger2, integer}]}}],
-		       result = {zero, integer}},
-     %% Not supported by ejabberd_ctl
-     #ejabberd_commands{name = take_tuple_2string, tags = [test],
-		       desc = "Take Tuple of two strings, give Integer zero",
-		       module = ?MODULE, function = take_tuple_2string,
-		       args = [{thistuple, {tuple, [{thisstring1, string}, {thisstring2, string}]}}],
-		       result = {zero, integer}},
-     %% Not supported by ejabberd_ctl
-     #ejabberd_commands{name = take_list_integer, tags = [test],
-		       desc = "Take List of integers, give Integer zero",
-		       module = ?MODULE, function = take_list_integer,
-		       args = [{thislist, {list, {thisinteger, integer}}}],
-		       result = {zero, integer}},
-     %% Not supported by ejabberd_ctl
-     #ejabberd_commands{name = take_list_string, tags = [test],
-		       desc = "Take List of strings, give Integer zero",
-		       module = ?MODULE, function = take_list_string,
-		       args = [{thislist, {list, {thisstring, string}}}],
-		       result = {zero, integer}},
-
-     #ejabberd_commands{name = echo_integer, tags = [test],
-		       desc = "Echo Integer",
-		       module = ?MODULE, function = echo_integer,
-		       args = [{thisinteger, integer}],
-		       result = {thatinteger, integer}},
-     #ejabberd_commands{name = echo_string, tags = [test],
-		       desc = "Echo String",
-		       module = ?MODULE, function = echo_string,
-		       args = [{thisstring, string}],
-		       result = {thatstring, string}},
-     #ejabberd_commands{name = echo_integer_string, tags = [test],
-		       desc = "Echo integer and string, in result as a tuple",
-		       module = ?MODULE, function = echo_integer_string,
-		       args = [{thisinteger, integer}, {thisstring, string}],
-		       result = {thistuple, {tuple, [{thisinteger, integer}, {thisstring, string}]}}},
-     %% Not supported by ejabberd_ctl
-     #ejabberd_commands{name = echo_list_integer, tags = [test],
-		       desc = "Echo List of integers",
-		       module = ?MODULE, function = echo_list_integer,
-		       args = [{thislist, {list, {thisinteger, integer}}}],
-		       result = {thatlist, {list, {thatinteger, integer}}}},
-     %% Not supported by ejabberd_ctl
-     #ejabberd_commands{name = echo_list_string, tags = [test],
-		       desc = "Echo List of strings",
-		       module = ?MODULE, function = echo_list_string,
-		       args = [{thislist, {list, {thisstring, string}}}],
-		       result = {thatlist, {list, {thatstring, string}}}},
-     %% Not supported by ejabberd_ctl
-     #ejabberd_commands{name = echo_integer_list_string, tags = [test],
-		       desc = "Echo an integer and List of strings",
-		       module = ?MODULE, function = echo_integer_list_string,
-		       args = [{thisinteger, integer}, {thislist, {list, {thisstring, string}}}],
-		       result = {thistuple, {tuple, [{thatinteger, integer}, {thatlist, {list, {thatstring, string}}}]}}},
-     %% Not supported by ejabberd_ctl
-     #ejabberd_commands{name = echo_isatils, tags = [test],
-		       desc = "Echo integer, string, atom and tuple of integer and list of strings",
-		       module = ?MODULE, function = echo_isatils,
-		       args = [{thisinteger, integer},
-			       {thisstring, string},
-			       {thisatom, atom},
-			       {thistuple, {tuple, [
-						    {listlen, integer},
-						    {thislist, {list, {contentstring, string}}}
-						   ]}}
-			      ],
-		       result = {results, {tuple, [{thatinteger, integer},
-						   {thatstring, string},
-						   {thatatom, atom},
-						   {thattuple, {tuple, [
-									{listlen, integer},
-									{thatlist, {list, {contentstring, string}}}
-								       ]}}
-						  ]}}},
-
-     #ejabberd_commands{name = tell_atom, tags = [test],
-		       desc = "Tell Atom, give Integer zero",
-		       module = ?MODULE, function = tell_atom,
-		       args = [{thisinteger, integer}],
-		       result = {thisatom, atom}},
-     #ejabberd_commands{name = tell_rescode, tags = [test],
-		       desc = "Tell rescode",
-		       module = ?MODULE, function = tell_rescode,
-		       args = [{thisinteger, integer}],
-		       result = {res, rescode}},
-     #ejabberd_commands{name = tell_restuple, tags = [test],
-		       desc = "Tell restuple",
-		       module = ?MODULE, function = tell_restuple,
-		       args = [{thisinteger, integer}],
-		       result = {res, restuple}},
-     #ejabberd_commands{name = tell_tuple_3integer, tags = [test],
-		       desc = "Tell a tuple with 3 integers",
-		       module = ?MODULE, function = tell_tuple_3integer,
-		       args = [],
-		       result = {thattuple, {tuple, [{first, integer},
-						     {second, integer},
-						     {third, integer}]}}},
-     #ejabberd_commands{name = tell_tuple_3string, tags = [test],
-		       desc = "Tell a tuple with 3 strings",
-		       module = ?MODULE, function = tell_tuple_3string,
-		       args = [],
-		       result = {thattuple, {tuple, [{first, string},
-						     {second, string},
-						     {third, string}]}}},
-     #ejabberd_commands{name = tell_tuple_3atom, tags = [test],
-		       desc = "Tell a tuple with 3 atoms",
-		       module = ?MODULE, function = tell_tuple_3atom,
-		       args = [],
-		       result = {thattuple, {tuple, [{first, atom},
-						     {second, atom},
-						     {third, atom}]}}},
-     #ejabberd_commands{name = tell_tuple_3list, tags = [test],
-		       desc = "Tell a tuple with 3 lists",
-		       module = ?MODULE, function = tell_tuple_3list,
-		       args = [],
-		       result = {thattuple, {tuple,
-					     [{first, {list,
-						       {thisinteger, integer}}},
-					      {second, {list,
-							{thisstring, string}}},
-					      {third, {list,
-						       {thisatom, atom}}}]}}},
-
-     #ejabberd_commands{name = tell_list_3integer, tags = [test],
-		       desc = "Tell a list with 3 integers",
-		       module = ?MODULE, function = tell_list_3integer,
-		       args = [],
-		       result = {thatlist, {list, {thisinteger, integer}}}},
-     #ejabberd_commands{name = tell_list_3string, tags = [test],
-		       desc = "Tell a list with 3 strings",
-		       module = ?MODULE, function = tell_list_3string,
-		       args = [],
-		       result = {thatlist, {list, {thisstring, string}}}},
-     #ejabberd_commands{name = tell_list_3atom, tags = [test],
-		       desc = "Tell a list with 3 atoms",
-		       module = ?MODULE, function = tell_list_3atom,
-		       args = [],
-		       result = {thatlist, {list, {thisatom, atom}}}},
-     #ejabberd_commands{name = tell_list_3tuple, tags = [test],
-		       desc = "Tell a list with 3 tuples",
-		       module = ?MODULE, function = tell_list_3tuple,
-		       args = [],
-		       result = {thatlist, {list, {thistuple,
-						   {tuple,
-						    [{thisinteger, integer},
-						     {thistring, string},
-						     {thisatom, atom}]}}}}},
-
-     #ejabberd_commands{name = this_crashes, tags = [test],
-		       desc = "This command crashes: test+5",
-		       module = ?MODULE, function = this_crashes,
-		       args = [{aninteger, integer}],
-		       result = {result, integer}},
-     #ejabberd_commands{name = this_wrong_args, tags = [test],
-		       desc = "This problematic command defines 2 arguments but function expects 1",
-		       module = ?MODULE, function = this_wrong_args,
-		       args = [{a, integer}, {b, integer}],
-		       result = {result, integer}},
-     #ejabberd_commands{name = this_wrong_return, tags = [test],
-		       desc = "This problematic command doesn't give a proper return",
-		       module = ?MODULE, function = this_wrong_return,
-		       args = [],
-		       result = {result, integer}},
-
-     #ejabberd_commands{name = pow, tags = [test],
-			desc = "Return the power of base for exponent",
-			longdesc = "This is an example command. The formula is:\n"
-			" power = base ^ exponent",
-			module = ?MODULE, function = pow,
-			args = [{base, integer}, {exponent, integer}],
-			result = {power, integer}},
-
-     #ejabberd_commands{name = seq, tags = [test],
-		       desc = "Return list of integers between two integers",
-		       module = ?MODULE, function = seq,
-		       args = [{from, integer}, {to, integer}],
-		       result = {sequence, {list, {intermediate, integer}}}},
-
-     #ejabberd_commands{name = substrs, tags = [test],
-		       desc = "Return list of substrings of length increasing",
-		       module = ?MODULE, function = substrs,
-		       args = [{word, string}],
-		       result = {substrings, {list, {miniword, string}}}},
-
-     #ejabberd_commands{name = splitjid, tags = [test],
-		       desc = "Split JID in parts: user, server, resource",
-		       module = ?MODULE, function = splitjid,
-		       args = [{jid, string}],
-		       result = {jidparts, {tuple, [{user, string},
-						    {server, string},
-						    {resource, string}]}}},
-
-     %% Not supported by ejabberd_ctl because uses 'list' in the arguments
-     #ejabberd_commands{name = splitjids, tags = [test],
-		       desc = "Split JIDs in parts: user, server, resource",
-		       module = ?MODULE, function = splitjids,
-		       args = [{jids, {list, {jid, string}}}],
-		       result = {jidsparts,
-				 {list, {jidparts,
-					 {tuple, [{user, string},
-						  {server, string},
-						  {resource, string}]}}}}}
-
-    ].
-
-%%%
-%%% Take
-%%%
-
-take_integer(A) when is_integer(A) -> 0.
-take_string(A) when is_list(A) -> 0.
-take_integer_string(A, B)
-  when is_integer(A) and is_list(B) ->
-    0.
-take_tuple_2integer({A, B})
-  when is_integer(A) and is_integer(B) ->
-    0.
-take_tuple_2string({A, B})
-  when is_list(A) and is_list(B) ->
-    0.
-take_list_integer(L)
-  when is_list(L) ->
-    true = lists:all(fun(A) -> is_integer(A) end, L),
-    0.
-take_list_string(L)
-  when is_list(L) ->
-    true = lists:all(fun(A) -> is_list(A) end, L),
-    0.
-
-%%%
-%%% Echo
-%%%
-
-echo_integer(A) when is_integer(A) -> A.
-echo_string(A) when is_list(A) -> A.
-echo_integer_string(A, B) when is_integer(A) and is_list(B) -> {A, B}.
-echo_list_integer(L)
-  when is_list(L) ->
-    true = lists:all(fun(A) -> is_integer(A) end, L),
-    L.
-echo_list_string(L)
-  when is_list(L) ->
-    true = lists:all(fun(A) -> is_list(A) end, L),
-    L.
-echo_integer_list_string(I, L)
-  when is_integer(I) and is_list(L) ->
-    true = lists:all(fun(A) -> is_list(A) end, L),
-    {I, L}.
-echo_isatils(I, S, A, {II, L})
-  when is_integer(I) and is_list(S) and is_atom(A) and is_integer(II) and is_list(L) ->
-    true = lists:all(fun(SS) -> is_list(SS) end, L),
-    {I, S, A, {I, L}}.
-
-
-%%%
-%%% Tell
-%%%
-
-tell_atom(0) -> zero;
-tell_atom(1) -> one;
-tell_atom(A) when is_integer(A) -> greater_than_one.
-
-tell_rescode(0) -> ok;
-tell_rescode(1) -> true;
-tell_rescode(2) -> error;
-tell_rescode(3) -> false;
-tell_rescode(4) -> whatever.
-
-tell_restuple(0) -> {ok, "All OK"};
-tell_restuple(1) -> {true, "Successful result"};
-tell_restuple(2) -> {error, "This is an error message"}.
-
-tell_tuple_3integer() -> {123, 456, 789}.
-tell_tuple_3string() -> {"Tell", "me", "a tuple please"}.
-tell_tuple_3atom() -> {ok, works, perfectly}.
-tell_tuple_3list() -> {[1, 23, 456], ["Tell", "me"], [all, is, ok]}.
-
-tell_list_3integer() -> [123, 456, 789].
-tell_list_3string() -> ["Tell", "me", "a tuple please"].
-tell_list_3atom() -> [ok, works, perfectly].
-tell_list_3tuple() ->
-    [{123, "abcdefghijkl", first},
-     {593, "this string", morning},
-     {999, "Sleeping dog", not_seen}].
-
-
-%%%
-%%% Realistic
-%%%
-
-%% This function will crash for sure
-this_crashes(Integer) ->
-    test + Integer.
-
-this_wrong_args(Integer) ->
-    Integer + 1.
-
-this_wrong_return() ->
-    "this is a string".
-
-pow(Base, Exponent) ->
-    PowFloat = math:pow(Base, Exponent),
-    round(PowFloat).
-
-seq(From, To) ->
-    lists:seq(From, To).
-
-%% For "stick" returns: s st sti stic stick
-substrs(Word) ->
-    Lengths = lists:seq(1, string:len(Word)),
-    [string:substr(Word, 1, Length) || Length <- Lengths].
-
-splitjid(String) ->
-    JID = jlib:string_to_jid(String),
-    {JID#jid.user,
-     JID#jid.server,
-     JID#jid.resource}.
-
-splitjids(Strings) ->
-    [splitjid(String) || String <- Strings].
-
diff --git a/mod_muc_admin/COPYING b/mod_muc_admin/COPYING
deleted file mode 100644
index e21e8c4..0000000
--- a/mod_muc_admin/COPYING
+++ /dev/null
@@ -1,343 +0,0 @@
-As a special exception, the authors give permission to link this program
-with the OpenSSL library and distribute the resulting binary.
-
-		    GNU GENERAL PUBLIC LICENSE
-		       Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-			    Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users.  This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it.  (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.)  You can apply it to
-your programs, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-  To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have.  You must make sure that they, too, receive or can get the
-source code.  And you must show them these terms so they know their
-rights.
-
-  We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
-  Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software.  If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary.  To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-
-		    GNU GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License.  The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language.  (Hereinafter, translation is included without limitation in
-the term "modification".)  Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
-  1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
-  2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) You must cause the modified files to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    b) You must cause any work that you distribute or publish, that in
-    whole or in part contains or is derived from the Program or any
-    part thereof, to be licensed as a whole at no charge to all third
-    parties under the terms of this License.
-
-    c) If the modified program normally reads commands interactively
-    when run, you must cause it, when started running for such
-    interactive use in the most ordinary way, to print or display an
-    announcement including an appropriate copyright notice and a
-    notice that there is no warranty (or else, saying that you provide
-    a warranty) and that users may redistribute the program under
-    these conditions, and telling the user how to view a copy of this
-    License.  (Exception: if the Program itself is interactive but
-    does not normally print such an announcement, your work based on
-    the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
-    a) Accompany it with the complete corresponding machine-readable
-    source code, which must be distributed under the terms of Sections
-    1 and 2 above on a medium customarily used for software interchange; or,
-
-    b) Accompany it with a written offer, valid for at least three
-    years, to give any third party, for a charge no more than your
-    cost of physically performing source distribution, a complete
-    machine-readable copy of the corresponding source code, to be
-    distributed under the terms of Sections 1 and 2 above on a medium
-    customarily used for software interchange; or,
-
-    c) Accompany it with the information you received as to the offer
-    to distribute corresponding source code.  (This alternative is
-    allowed only for noncommercial distribution and only if you
-    received the program in object code or executable form with such
-    an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it.  For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable.  However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License.  Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
-  5. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Program or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
-  6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
-  7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-  8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded.  In such case, this License incorporates
-the limitation as if written in the body of this License.
-
-  9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation.  If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
-  10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission.  For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this.  Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
-			    NO WARRANTY
-
-  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
-  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
-		     END OF TERMS AND CONDITIONS
-
-	    How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License along
-    with this program; if not, write to the Free Software Foundation, Inc.,
-    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
-    Gnomovision version 69, Copyright (C) year  name of author
-    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-    This is free software, and you are welcome to redistribute it
-    under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License.  Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
-  `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
-  <signature of Ty Coon>, 1 April 1989
-  Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs.  If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library.  If this is what you want to do, use the GNU Library General
-Public License instead of this License.
diff --git a/mod_muc_admin/ChangeLog b/mod_muc_admin/ChangeLog
deleted file mode 100644
index 5ebbea3..0000000
--- a/mod_muc_admin/ChangeLog
+++ /dev/null
@@ -1,80 +0,0 @@
-2009-07-01  Badlop  <badlop@process-one.net>
-
-	* src/mod_muc_admin.erl: Fix change_room_option
-
-2009-06-02  Badlop  <badlop@process-one.net>
-
-	* src/mod_muc_admin.erl: Destroy the room before forgetting it.
-
-2008-12-02  Badlop  <badlop@process-one.net>
-
-	* src/mod_muc_admin.erl: Include mod_muc_room.hrl
-	* README.txt: Likewise
-
-2008-11-17  Badlop  <badlop@process-one.net>
-
-	* src/mod_muc_admin.erl: Fix include of web hrl (thanks to Johnny)
-
-2008-10-12  Badlop  <badlop@process-one.net>
-
-	* src/mod_muc_admin.erl: Update from ctl to commands (EJAB-694)
-
-2008-09-30  Badlop  <badlop@process-one.net>
-
-	* src/mod_muc_admin.erl: Update record definitions to ejabberd
-	trunk SVN
-
-2008-05-16  Badlop  <badlop@process-one.net>
-
-	* src/mod_muc_admin.erl: New exported function
-	set_affiliation/4 (thanks to Darren Ferguson)
-
-2008-05-12  Badlop  <badlop@process-one.net>
-
-	* src/mod_muc_admin.erl: Added new function: change_room_option/4
-
-2008-05-06  Badlop  <badlop@process-one.net>
-
-	* src/mod_muc_admin.erl: New exported functions create_room and
-	destroy_room (thanks to Darren Ferguson)
-
-2008-04-04  Badlop  <badlop@process-one.net>
-
-	* src/mod_muc_admin.erl: New command muc-create-file to create the
-	rooms indicated in the file
-
-2008-03-29  Badlop  <badlop@process-one.net>
-
-	* src/mod_muc_admin.erl: Improvements in the list of rooms of web
-	admin: show timestamp of last message, sorting by any column.
-
-2008-03-19  Badlop  <badlop@process-one.net>
-
-	* src/mod_muc_admin.erl (join): Copied the new function
-	string:join/2 introduced in Erlang R12
-
-	* README.txt: Clarified requirements
-
-	* src/mod_muc_admin.erl (split_roomjid): Small fix
-
-2008-02-01  Badlop  <badlop@process-one.net>
-
-	* src/mod_muc_admin.erl: New command: muc-unregister-nick.
-
-2007-12-26  Badlop  <badlop@process-one.net>
-
-	* src/mod_muc_admin.erl: Translate menu items of webadmin hooks in
-	each module (EJAB-485)
-
-2007-11-15  Badlop  <badlop@ono.com>
-
-	* src/mod_muc_admin.erl: New command: muc-destroy-file. 
-
-2007-09-09  Badlop  <badlop@ono.com>
-
-	* src/mod_muc_admin.erl: Added Web Admin and List rooms.
-
-2007-09-08  Badlop  <badlop@ono.com>
-
-	* mod_muc_admin: Initial commit.
-
diff --git a/mod_muc_admin/README.txt b/mod_muc_admin/README.txt
deleted file mode 100644
index 272a35a..0000000
--- a/mod_muc_admin/README.txt
+++ /dev/null
@@ -1,43 +0,0 @@
-
-
-	mod_muc_admin - Administrative features for MUC
-
-	NOTE: This module is included in ejabberd since 15.04
-
-	Homepage: http://www.ejabberd.im/mod_muc_admin
-	Author: Badlop
-
-This module implements several ejabberd commands that can be
-executed using ejabberdctl.
-
-It also implements Web Admin pages to view the list of existing
-rooms.
-
-
-	CONFIGURATION
-	=============
-
-Add the module to your ejabberd.yml, on the modules section:
-modules:
-  mod_muc_admin: {}
-
-
-	EJABBERD COMMANDS
-	=================
-
-Description of some commands:
-
- - muc-unusued-*
-   Those commands related to MUC require an ejabberd version newer than 1.1.x.
-   The room characteristics used to decide if a room is unusued:
-    - Days since the last message or subject change:
-        greater or equal to the command argument
-    - Number of participants: 0
-    - Persistent: not important
-    - Has history: not important
-    - Days since last join, leave, room config or affiliation edit:
-        not important
-    - Just created: no
-   Note that ejabberd does not keep room history after a module restart, so
-   the history of all rooms is emtpy after a module or server start.
-
diff --git a/mod_muc_admin/conf/mod_muc_admin.yml b/mod_muc_admin/conf/mod_muc_admin.yml
deleted file mode 100644
index 9d22951..0000000
--- a/mod_muc_admin/conf/mod_muc_admin.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-modules:
-  mod_muc_admin: {}
diff --git a/mod_muc_admin/mod_muc_admin.spec b/mod_muc_admin/mod_muc_admin.spec
deleted file mode 100644
index 128d534..0000000
--- a/mod_muc_admin/mod_muc_admin.spec
+++ /dev/null
@@ -1,5 +0,0 @@
-author: "Badlop <badlop at process-one.net>"
-category: "admin"
-summary: "Administrative features for MUC"
-home: "https://github.com/processone/ejabberd-contrib/tree/master/"
-url: "git@github.com:processone/ejabberd-contrib.git"
diff --git a/mod_muc_admin/src/mod_muc_admin.erl b/mod_muc_admin/src/mod_muc_admin.erl
deleted file mode 100644
index 5408d94..0000000
--- a/mod_muc_admin/src/mod_muc_admin.erl
+++ /dev/null
@@ -1,876 +0,0 @@
-%%%----------------------------------------------------------------------
-%%% File    : mod_muc_admin.erl
-%%% Author  : Badlop <badlop@ono.com>
-%%% Purpose : Tools for additional MUC administration
-%%% Created : 8 Sep 2007 by Badlop <badlop@ono.com>
-%%% Id      : $Id: mod_muc_admin.erl 1133 2012-10-17 22:13:06Z badlop $
-%%%----------------------------------------------------------------------
-
--module(mod_muc_admin).
--author('badlop@ono.com').
-
--behaviour(gen_mod).
-
--export([
-	 start/2, stop/1, % gen_mod API
-	 muc_online_rooms/1,
-	 muc_unregister_nick/1,
-	 create_room/3, destroy_room/3,
-	 create_rooms_file/1, destroy_rooms_file/1,
-	 rooms_unused_list/2, rooms_unused_destroy/2,
-	 get_room_occupants/2,
-	 get_room_occupants_number/2,
-	 send_direct_invitation/4,
-	 change_room_option/4,
-	 set_room_affiliation/4,
-	 get_room_affiliations/2,
-	 web_menu_main/2, web_page_main/2, % Web Admin API
-	 web_menu_host/3, web_page_host/3
-	]).
-
--include("ejabberd.hrl").
--include("logger.hrl").
--include("jlib.hrl").
--include("mod_muc_room.hrl").
--include("ejabberd_http.hrl").
--include("ejabberd_web_admin.hrl").
--include("ejabberd_commands.hrl").
-
-%% Copied from mod_muc/mod_muc.erl
--record(muc_online_room, {name_host, pid}).
-
-%%----------------------------
-%% gen_mod
-%%----------------------------
-
-start(Host, _Opts) ->
-    ejabberd_commands:register_commands(commands()),
-    ejabberd_hooks:add(webadmin_menu_main, ?MODULE, web_menu_main, 50),
-    ejabberd_hooks:add(webadmin_menu_host, Host, ?MODULE, web_menu_host, 50),
-    ejabberd_hooks:add(webadmin_page_main, ?MODULE, web_page_main, 50),
-    ejabberd_hooks:add(webadmin_page_host, Host, ?MODULE, web_page_host, 50).
-
-stop(Host) ->
-    ejabberd_commands:unregister_commands(commands()),
-    ejabberd_hooks:delete(webadmin_menu_main, ?MODULE, web_menu_main, 50),
-    ejabberd_hooks:delete(webadmin_menu_host, Host, ?MODULE, web_menu_host, 50),
-    ejabberd_hooks:delete(webadmin_page_main, ?MODULE, web_page_main, 50),
-    ejabberd_hooks:delete(webadmin_page_host, Host, ?MODULE, web_page_host, 50).
-
-%%%
-%%% Register commands
-%%%
-
-commands() ->
-    [
-     #ejabberd_commands{name = muc_online_rooms, tags = [muc],
-		       desc = "List existing rooms ('global' to get all vhosts)",
-		       module = ?MODULE, function = muc_online_rooms,
-		       args = [{host, binary}],
-		       result = {rooms, {list, {room, string}}}},
-     #ejabberd_commands{name = muc_unregister_nick, tags = [muc],
-		       desc = "Unregister the nick in the MUC service",
-		       module = ?MODULE, function = muc_unregister_nick,
-		       args = [{nick, binary}],
-		       result = {res, rescode}},
-
-     #ejabberd_commands{name = create_room, tags = [muc_room],
-		       desc = "Create a MUC room name@service in host",
-		       module = ?MODULE, function = create_room,
-		       args = [{name, binary}, {service, binary},
-			       {host, binary}],
-		       result = {res, rescode}},
-     #ejabberd_commands{name = destroy_room, tags = [muc_room],
-		       desc = "Destroy a MUC room",
-		       module = ?MODULE, function = destroy_room,
-		       args = [{name, binary}, {service, binary},
-			       {host, binary}],
-		       result = {res, rescode}},
-     #ejabberd_commands{name = create_rooms_file, tags = [muc],
-		       desc = "Create the rooms indicated in file",
-		       module = ?MODULE, function = create_rooms_file,
-		       args = [{file, string}],
-		       result = {res, rescode}},
-     #ejabberd_commands{name = destroy_rooms_file, tags = [muc],
-		       desc = "Destroy the rooms indicated in file",
-		       module = ?MODULE, function = destroy_rooms_file,
-		       args = [{file, string}],
-		       result = {res, rescode}},
-     #ejabberd_commands{name = rooms_unused_list, tags = [muc],
-		       desc = "List the rooms that are unused for many days in host",
-		       module = ?MODULE, function = rooms_unused_list,
-		       args = [{host, binary}, {days, integer}],
-		       result = {rooms, {list, {room, string}}}},
-     #ejabberd_commands{name = rooms_unused_destroy, tags = [muc],
-		       desc = "Destroy the rooms that are unused for many days in host",
-		       module = ?MODULE, function = rooms_unused_destroy,
-		       args = [{host, binary}, {days, integer}],
-		       result = {rooms, {list, {room, string}}}},
-
-     #ejabberd_commands{name = get_room_occupants, tags = [muc_room],
-			desc = "Get the list of occupants of a MUC room",
-			module = ?MODULE, function = get_room_occupants,
-			args = [{name, binary}, {service, binary}],
-			result = {occupants, {list,
-					      {occupant, {tuple,
-							  [{jid, string},
-							   {nick, string},
-							   {role, string}
-							  ]}}
-					     }}},
-
-     #ejabberd_commands{name = get_room_occupants_number, tags = [muc_room],
-			desc = "Get the number of occupants of a MUC room",
-			module = ?MODULE, function = get_room_occupants_number,
-			args = [{name, binary}, {service, binary}],
-			result = {occupants, integer}},
-
-     #ejabberd_commands{name = send_direct_invitation, tags = [muc_room],
-			desc = "Send a direct invitation to several destinations",
-			longdesc = "Password and Message can also be: none. Users JIDs are separated with : ",
-			module = ?MODULE, function = send_direct_invitation,
-		        args = [{room, binary}, {password, binary}, {reason, binary}, {users, string}],
-		        result = {res, rescode}},
-
-     #ejabberd_commands{name = change_room_option, tags = [muc_room],
-		       desc = "Change an option in a MUC room",
-		       module = ?MODULE, function = change_room_option,
-		       args = [{name, binary}, {service, binary},
-			       {option, string}, {value, string}],
-		       result = {res, rescode}},
-
-     #ejabberd_commands{name = set_room_affiliation, tags = [muc_room],
-		       desc = "Change an affiliation in a MUC room",
-		       module = ?MODULE, function = set_room_affiliation,
-		       args = [{name, binary}, {service, binary},
-			       {jid, binary}, {affiliation, string}],
-		       result = {res, rescode}},
-     #ejabberd_commands{name = get_room_affiliations, tags = [muc_room],
-			desc = "Get the list of affiliations of a MUC room",
-			module = ?MODULE, function = get_room_affiliations,
-			args = [{name, binary}, {service, binary}],
-			result = {affiliations, {list,
-						 {affiliation, {tuple,
-								[{username, string},
-								 {domain, string},
-								 {affiliation, atom},
-								 {reason, string}
-								]}}
-						}}}
-    ].
-
-
-%%%
-%%% ejabberd commands
-%%%
-
-muc_online_rooms(ServerHost) ->
-    MUCHost = find_host(ServerHost),
-    Rooms = ets:tab2list(muc_online_room),
-    lists:foldl(
-      fun({_, {Roomname, Host}, _}, Results) ->
-	      case MUCHost of
-		  global ->
-		      [<<Roomname/binary, "@", Host/binary>> | Results];
-		  Host ->
-		      [<<Roomname/binary, "@", Host/binary>> | Results];
-		  _ ->
-		      Results
-	      end
-      end,
-      [],
-      Rooms).
-
-muc_unregister_nick(Nick) ->
-    F2 = fun(N) ->
-		 [{_,Key,_}] = mnesia:index_read(muc_registered, N, 3),
-		 mnesia:delete({muc_registered, Key})
-	 end,
-    case mnesia:transaction(F2, [Nick], 1) of
-	{atomic, ok} ->
-	    ok;
-	{aborted, _Error} ->
-	    error
-    end.
-
-
-%%----------------------------
-%% Ad-hoc commands
-%%----------------------------
-
-
-%%----------------------------
-%% Web Admin
-%%----------------------------
-
-%%---------------
-%% Web Admin Menu
-
-web_menu_main(Acc, Lang) ->
-    Acc ++ [{<<"muc">>, ?T(<<"Multi-User Chat">>)}].
-
-web_menu_host(Acc, _Host, Lang) ->
-    Acc ++ [{<<"muc">>, ?T(<<"Multi-User Chat">>)}].
-
-
-%%---------------
-%% Web Admin Page
-
--define(TDTD(L, N),
-	?XE(<<"tr">>, [?XCT(<<"td">>, L),
-		       ?XC(<<"td">>, jlib:integer_to_binary(N))
-		      ])).
-
-web_page_main(_, #request{path=[<<"muc">>], lang = Lang} = _Request) ->
-    Res = [?XC(<<"h1">>, <<"Multi-User Chat">>),
-	   ?XC(<<"h3">>, <<"Statistics">>),
-	   ?XAE(<<"table">>, [],
-		[?XE(<<"tbody">>, [?TDTD(<<"Total rooms">>, ets:info(muc_online_room, size)),
-				   ?TDTD(<<"Permanent rooms">>, mnesia:table_info(muc_room, size)),
-				   ?TDTD(<<"Registered nicknames">>, mnesia:table_info(muc_registered, size))
-				  ])
-		]),
-	   ?XE(<<"ul">>, [?LI([?ACT(<<"rooms">>, <<"List of rooms">>)])])
-	  ],
-    {stop, Res};
-
-web_page_main(_, #request{path=[<<"muc">>, <<"rooms">>], q = Q, lang = Lang} = _Request) ->
-    Sort_query = get_sort_query(Q),
-    Res = make_rooms_page(global, Lang, Sort_query),
-    {stop, Res};
-
-web_page_main(Acc, _) -> Acc.
-
-web_page_host(_, Host,
-	      #request{path = [<<"muc">>],
-		       q = Q,
-		       lang = Lang} = _Request) ->
-    Sort_query = get_sort_query(Q),
-    Res = make_rooms_page(find_host(Host), Lang, Sort_query),
-    {stop, Res};
-web_page_host(Acc, _, _) -> Acc.
-
-
-%% Returns: {normal | reverse, Integer}
-get_sort_query(Q) ->
-    case catch get_sort_query2(Q) of
-	{ok, Res} -> Res;
-	_ -> {normal, 1}
-    end.
-
-get_sort_query2(Q) ->
-    {value, {_, String}} = lists:keysearch(<<"sort">>, 1, Q),
-    Integer = list_to_integer(String),
-    case Integer >= 0 of
-	true -> {ok, {normal, Integer}};
-	false -> {ok, {reverse, abs(Integer)}}
-    end.
-
-make_rooms_page(Host, Lang, {Sort_direction, Sort_column}) ->
-    Rooms_names = get_rooms(Host),
-    Rooms_infos = build_info_rooms(Rooms_names),
-    Rooms_sorted = sort_rooms(Sort_direction, Sort_column, Rooms_infos),
-    Rooms_prepared = prepare_rooms_infos(Rooms_sorted),
-    TList = lists:map(
-	      fun(Room) ->
-		      ?XE(<<"tr">>, [?XC(<<"td">>, E) || E <- Room])
-	      end, Rooms_prepared),
-    Titles = [<<"Jabber ID">>,
-	      <<"# participants">>,
-	      <<"Last message">>,
-	      <<"Public">>,
-	      <<"Persistent">>,
-	      <<"Logging">>,
-	      <<"Just created">>,
-	      <<"Title">>],
-    {Titles_TR, _} =
-	lists:mapfoldl(
-	  fun(Title, Num_column) ->
-		  NCS = jlib:integer_to_binary(Num_column),
-		  TD = ?XE(<<"td">>, [?CT(Title),
-				      ?C(<<" ">>),
-				      ?ACT(<<"?sort=", NCS/binary>>, <<"<">>),
-				      ?C(<<" ">>),
-				      ?ACT(<<"?sort=-", NCS/binary>>, <<">">>)]),
-		  {TD, Num_column+1}
-	  end,
-	  1,
-	  Titles),
-    [?XC(<<"h1">>, <<"Multi-User Chat">>),
-     ?XC(<<"h2">>, <<"Rooms">>),
-     ?XE(<<"table">>,
-	 [?XE(<<"thead">>,
-	      [?XE(<<"tr">>, Titles_TR)]
-	     ),
-	  ?XE(<<"tbody">>, TList)
-	 ]
-	)
-    ].
-
-sort_rooms(Direction, Column, Rooms) ->
-    Rooms2 = lists:keysort(Column, Rooms),
-    case Direction of
-	normal -> Rooms2;
-	reverse -> lists:reverse(Rooms2)
-    end.
-
-build_info_rooms(Rooms) ->
-    [build_info_room(Room) || Room <- Rooms].
-
-build_info_room({Name, Host, Pid}) ->
-    C = get_room_config(Pid),
-    Title = C#config.title,
-    Public = C#config.public,
-    Persistent = C#config.persistent,
-    Logging = C#config.logging,
-
-    S = get_room_state(Pid),
-    Just_created = S#state.just_created,
-    Num_participants = length(dict:fetch_keys(S#state.users)),
-
-    History = (S#state.history)#lqueue.queue,
-    Ts_last_message =
-	case queue:is_empty(History) of
-	    true ->
-		<<"A long time ago">>;
-	    false ->
-		Last_message1 = queue:last(History),
-		{_, _, _, Ts_last, _} = Last_message1,
-		jlib:timestamp_to_iso(Ts_last)
-	end,
-
-    {<<Name/binary, "@", Host/binary>>,
-     Num_participants,
-     Ts_last_message,
-     Public,
-     Persistent,
-     Logging,
-     Just_created,
-     Title}.
-
-prepare_rooms_infos(Rooms) ->
-    [prepare_room_info(Room) || Room <- Rooms].
-prepare_room_info(Room_info) ->
-    {NameHost,
-     Num_participants,
-     Ts_last_message,
-     Public,
-     Persistent,
-     Logging,
-     Just_created,
-     Title} = Room_info,
-    [NameHost,
-     jlib:integer_to_binary(Num_participants),
-     Ts_last_message,
-     jlib:atom_to_binary(Public),
-     jlib:atom_to_binary(Persistent),
-     jlib:atom_to_binary(Logging),
-     jlib:atom_to_binary(Just_created),
-     Title].
-
-
-%%----------------------------
-%% Create/Delete Room
-%%----------------------------
-
-%% @spec (Name::binary(), Host::binary(), ServerHost::binary()) ->
-%%       ok | error
-%% @doc Create a room immediately with the default options.
-create_room(Name, Host, ServerHost) ->
-
-    %% Get the default room options from the muc configuration
-    DefRoomOpts = gen_mod:get_module_opt(ServerHost, mod_muc,
-					 default_room_options, fun(X) -> X end, []),
-
-    %% Store the room on the server, it is not started yet though at this point
-    mod_muc:store_room(ServerHost, Host, Name, DefRoomOpts),
-
-    %% Get all remaining mod_muc parameters that might be utilized
-    Access = gen_mod:get_module_opt(ServerHost, mod_muc, access, fun(X) -> X end, all),
-    AcCreate = gen_mod:get_module_opt(ServerHost, mod_muc, access_create, fun(X) -> X end, all),
-    AcAdmin = gen_mod:get_module_opt(ServerHost, mod_muc, access_admin, fun(X) -> X end, none),
-    AcPer = gen_mod:get_module_opt(ServerHost, mod_muc, access_persistent, fun(X) -> X end, all),
-    _PersistHistory = gen_mod:get_module_opt(ServerHost, mod_muc, persist_history, fun(X) -> X end, false),
-    HistorySize = gen_mod:get_module_opt(ServerHost, mod_muc, history_size, fun(X) -> X end, 20),
-    RoomShaper = gen_mod:get_module_opt(ServerHost, mod_muc, room_shaper, fun(X) -> X end, none),
-
-    %% If the room does not exist yet in the muc_online_room
-    case mnesia:dirty_read(muc_online_room, {Name, Host}) of
-        [] ->
-	    %% Start the room
-	    {ok, Pid} = mod_muc_room:start(
-			  Host,
-			  ServerHost,
-			  {Access, AcCreate, AcAdmin, AcPer},
-			  Name,
-			  HistorySize,
-			  RoomShaper,
-			  DefRoomOpts),
-	    {atomic, ok} = register_room(Host, Name, Pid),
-	    ok;
-	_ ->
-	    error
-    end.
-
-register_room(Host, Name, Pid) ->
-    F = fun() ->
-		mnesia:write(#muc_online_room{name_host = {Name, Host},
-					      pid = Pid})
-	end,
-    mnesia:transaction(F).
-
-%% Create the room only in the database.
-%% It is required to restart the MUC service for the room to appear.
-muc_create_room(ServerHost, {Name, Host, _}, DefRoomOpts) ->
-    io:format("Creating room ~s@~s~n", [Name, Host]),
-    mod_muc:store_room(ServerHost, Host, Name, DefRoomOpts).
-
-%% @spec (Name::binary(), Host::binary(), ServerHost::binary()) ->
-%%       ok | {error, room_not_exists}
-%% @doc Destroy the room immediately.
-%% If the room has participants, they are not notified that the room was destroyed;
-%% they will notice when they try to chat and receive an error that the room doesn't exist.
-destroy_room(Name, Service, _Server) ->
-    case mnesia:dirty_read(muc_online_room, {Name, Service}) of
-	[R] ->
-	    Pid = R#muc_online_room.pid,
-	    gen_fsm:send_all_state_event(Pid, destroy),
-	    ok;
-	[] ->
-	    error
-    end.
-
-destroy_room({N, H, SH}) ->
-    io:format("Destroying room: ~s@~s - vhost: ~s~n", [N, H, SH]),
-    destroy_room(N, H, SH).
-
-
-%%----------------------------
-%% Destroy Rooms in File
-%%----------------------------
-
-%% The format of the file is: one chatroom JID per line
-%% The file encoding must be UTF-8
-
-destroy_rooms_file(Filename) ->
-    {ok, F} = file:open(Filename, [read]),
-    RJID = read_room(F),
-    Rooms = read_rooms(F, RJID, []),
-    file:close(F),
-    [destroy_room(A) || A <- Rooms],
-	ok.
-
-read_rooms(_F, eof, L) ->
-    L;
-
-read_rooms(F, RJID, L) ->
-    RJID2 = read_room(F),
-    read_rooms(F, RJID2, [RJID | L]).
-
-read_room(F) ->
-    case io:get_line(F, "") of
-	eof -> eof;
-	String ->
-	    case io_lib:fread("~s", String) of
-		{ok, [RoomJID], _} -> split_roomjid(RoomJID);
-		{error, What} ->
-		    io:format("Parse error: what: ~p~non the line: ~p~n~n", [What, String])
-	    end
-    end.
-
-%% This function is quite rudimentary
-%% and may not be accurate
-split_roomjid(RoomJID) ->
-    [Name, Host] = string:tokens(RoomJID, "@"),
-    [_MUC_service_name | ServerHostList] = string:tokens(Host, "."),
-    ServerHost = join(ServerHostList, "."),
-    {Name, Host, ServerHost}.
-
-%% This function is copied from string:join/2 in Erlang/OTP R12B-1
-%% Note that string:join/2 is not implemented in Erlang/OTP R11B
-join([H|T], Sep) ->
-    H ++ lists:concat([Sep ++ X || X <- T]).
-
-
-%%----------------------------
-%% Create Rooms in File
-%%----------------------------
-
-create_rooms_file(Filename) ->
-    {ok, F} = file:open(Filename, [read]),
-    RJID = read_room(F),
-    Rooms = read_rooms(F, RJID, []),
-    file:close(F),
-    %% Read the default room options defined for the first virtual host
-    DefRoomOpts = gen_mod:get_module_opt(?MYNAME, mod_muc,
-					 default_room_options, []),
-    [muc_create_room(?MYNAME, A, DefRoomOpts) || A <- Rooms],
-	ok.
-
-
-%%----------------------------
-%% List/Delete Unused Rooms
-%%----------------------------
-
-%%---------------
-%% Control
-
-rooms_unused_list(Host, Days) ->
-    rooms_unused_report(list, Host, Days).
-rooms_unused_destroy(Host, Days) ->
-    rooms_unused_report(destroy, Host, Days).
-
-rooms_unused_report(Action, Host, Days) ->
-    {NA, NP, RP} = muc_unused(Action, Host, Days),
-    io:format("Unused rooms: ~p out of ~p~n", [NP, NA]),
-    [[R, <<"@">>, H] || {R, H, _P} <- RP].
-
-muc_unused(Action, ServerHost, Days) ->
-    Host = find_host(ServerHost),
-    muc_unused2(Action, ServerHost, Host, Days).
-
-muc_unused2(Action, ServerHost, Host, Last_allowed) ->
-    %% Get all required info about all existing rooms
-    Rooms_all = get_rooms(Host),
-
-    %% Decide which ones pass the requirements
-    Rooms_pass = decide_rooms(Rooms_all, Last_allowed),
-
-    Num_rooms_all = length(Rooms_all),
-    Num_rooms_pass = length(Rooms_pass),
-
-    %% Perform the desired action for matching rooms
-    act_on_rooms(Action, Rooms_pass, ServerHost),
-
-    {Num_rooms_all, Num_rooms_pass, Rooms_pass}.
-
-%%---------------
-%% Get info
-
-get_rooms(Host) ->
-    Get_room_names = fun(Room_reg, Names) ->
-			     Pid = Room_reg#muc_online_room.pid,
-			     case {Host, Room_reg#muc_online_room.name_host} of
-				 {Host, {Name1, Host}} ->
-				     [{Name1, Host, Pid} | Names];
-				 {global, {Name1, Host1}} ->
-				     [{Name1, Host1, Pid} | Names];
-				 _ ->
-				     Names
-			     end
-		     end,
-    ets:foldr(Get_room_names, [], muc_online_room).
-
-get_room_config(Room_pid) ->
-    {ok, R} = gen_fsm:sync_send_all_state_event(Room_pid, get_config),
-    R.
-
-get_room_state(Room_pid) ->
-    {ok, R} = gen_fsm:sync_send_all_state_event(Room_pid, get_state),
-    R.
-
-%%---------------
-%% Decide
-
-decide_rooms(Rooms, Last_allowed) ->
-    Decide = fun(R) -> decide_room(R, Last_allowed) end,
-    lists:filter(Decide, Rooms).
-
-decide_room({_Room_name, _Host, Room_pid}, Last_allowed) ->
-    C = get_room_config(Room_pid),
-    Persistent = C#config.persistent,
-
-    S = get_room_state(Room_pid),
-    Just_created = S#state.just_created,
-
-    Room_users = S#state.users,
-    Num_users = length(?DICT:to_list(Room_users)),
-
-    History = (S#state.history)#lqueue.queue,
-    Ts_now = calendar:now_to_universal_time(now()),
-    Ts_uptime = uptime_seconds(),
-    {Has_hist, Last} = case queue:is_empty(History) of
-			   true ->
-			       {false, Ts_uptime};
-			   false ->
-			       Last_message = queue:last(History),
-			       {_, _, _, Ts_last, _} = Last_message,
-			       Ts_diff =
-				   calendar:datetime_to_gregorian_seconds(Ts_now)
-				   - calendar:datetime_to_gregorian_seconds(Ts_last),
-			       {true, Ts_diff}
-		       end,
-
-    case {Persistent, Just_created, Num_users, Has_hist, seconds_to_days(Last)} of
-	{_true, false, 0, _, Last_days}
-	when Last_days >= Last_allowed ->
-	    true;
-	_ ->
-	    false
-    end.
-
-seconds_to_days(S) ->
-    S div (60*60*24).
-
-%%---------------
-%% Act
-
-act_on_rooms(Action, Rooms, ServerHost) ->
-    ServerHosts = [ {A, find_host(A)} || A <- ?MYHOSTS ],
-    Delete = fun({_N, H, _Pid} = Room) ->
-		     SH = case ServerHost of
-			      global -> find_serverhost(H, ServerHosts);
-			      O -> O
-			  end,
-
-		     act_on_room(Action, Room, SH)
-	     end,
-    lists:foreach(Delete, Rooms).
-
-find_serverhost(Host, ServerHosts) ->
-    {value, {ServerHost, Host}} = lists:keysearch(Host, 2, ServerHosts),
-    ServerHost.
-
-act_on_room(destroy, {N, H, Pid}, SH) ->
-    gen_fsm:send_all_state_event(
-      Pid, {destroy, <<"Room destroyed by rooms_unused_destroy.">>}),
-    mod_muc:room_destroyed(H, N, Pid, SH),
-    mod_muc:forget_room(SH, H, N);
-
-act_on_room(list, _, _) ->
-    ok.
-
-
-%%----------------------------
-%% Change Room Option
-%%----------------------------
-
-get_room_occupants(Room, Host) ->
-    case get_room_pid(Room, Host) of
-	room_not_found -> throw({error, room_not_found});
-	Pid -> get_room_occupants(Pid)
-    end.
-
-get_room_occupants(Pid) ->
-    S = get_room_state(Pid),
-    lists:map(
-      fun({_LJID, Info}) ->
-	      {jlib:jid_to_string(Info#user.jid),
-	       Info#user.nick,
-	       atom_to_list(Info#user.role)}
-      end,
-      dict:to_list(S#state.users)).
-
-get_room_occupants_number(Room, Host) ->
-    length(get_room_occupants(Room, Host)).
-
-%%----------------------------
-%% Send Direct Invitation
-%%----------------------------
-%% http://xmpp.org/extensions/xep-0249.html
-
-send_direct_invitation(RoomString, Password, Reason, UsersString) ->
-    RoomJid = jlib:string_to_jid(RoomString),
-    XmlEl = build_invitation(Password, Reason, RoomString),
-    UsersStrings = get_users_to_invite(RoomJid, UsersString),
-    [send_direct_invitation(RoomJid, jlib:string_to_jid(list_to_binary(UserStrings)), XmlEl)
-     || UserStrings <- UsersStrings],
-    timer:sleep(1000),
-    ok.
-
-get_users_to_invite(RoomJid, UsersString) ->
-    UsersStrings = string:tokens(UsersString, ":"),
-    OccupantsTuples = get_room_occupants(RoomJid#jid.luser,
-					 RoomJid#jid.lserver),
-    OccupantsJids = [jlib:string_to_jid(JidString)
-		     || {JidString, _Nick, _} <- OccupantsTuples],
-    lists:filter(
-	fun(UserString) ->
-	    UserJid = jlib:string_to_jid(list_to_binary(UserString)),
-	    %% [{"badlop@localhost/work","badlop","moderator"}]
-	    lists:all(fun(OccupantJid) ->
-		UserJid#jid.luser /= OccupantJid#jid.luser
-		orelse UserJid#jid.lserver /= OccupantJid#jid.lserver
-	    end,
-	    OccupantsJids)
-	end,
-	UsersStrings).
-
-build_invitation(Password, Reason, RoomString) ->
-    PasswordAttrList = case Password of
-	<<"none">> -> [];
-	_ -> [{<<"password">>, Password}]
-    end,
-    ReasonAttrList = case Reason of
-	<<"none">> -> [];
-	_ -> [{<<"reason">>, Reason}]
-    end,
-    XAttrs = [{<<"xmlns">>, ?NS_XCONFERENCE},
-	      {<<"jid">>, RoomString}]
-	++ PasswordAttrList
-	++ ReasonAttrList,
-    XEl = {xmlel, <<"x">>, XAttrs, []},
-    {xmlel, <<"message">>, [], [XEl]}.
-
-send_direct_invitation(FromJid, UserJid, XmlEl) ->
-    ejabberd_router:route(FromJid, UserJid, XmlEl).
-
-%%----------------------------
-%% Change Room Option
-%%----------------------------
-
-%% @spec(Name::string(), Service::string(), Option::string(), Value) -> ok
-%%       Value = atom() | integer() | string()
-%% @doc Change an option in an existing room.
-%% Requires the name of the room, the MUC service where it exists,
-%% the option to change (for example title or max_users),
-%% and the value to assign to the new option.
-%% For example:
-%%   change_room_option("testroom", "conference.localhost", "title", "Test Room")
-change_room_option(Name, Service, Option, Value) when is_atom(Option) ->
-    Pid = get_room_pid(Name, Service),
-    {ok, _} = change_room_option(Pid, Option, Value),
-    ok;
-change_room_option(Name, Service, OptionString, ValueString) ->
-    Option = list_to_atom(OptionString),
-    Value = case Option of
-	title -> ValueString;
-	description -> ValueString;
-	password -> ValueString;
-	max_users -> list_to_integer(ValueString);
-	_ -> list_to_atom(ValueString)
-    end,
-    change_room_option(Name, Service, Option, Value).
-
-change_room_option(Pid, Option, Value) ->
-    Config = get_room_config(Pid),
-    Config2 = change_option(Option, Value, Config),
-    gen_fsm:sync_send_all_state_event(Pid, {change_config, Config2}).
-
-%% @doc Get the Pid of an existing MUC room, or 'room_not_found'.
-get_room_pid(Name, Service) ->
-    case mnesia:dirty_read(muc_online_room, {Name, Service}) of
-	[] ->
-	    room_not_found;
-	[Room] ->
-	    Room#muc_online_room.pid
-    end.
-
-%% It is required to put explicitely all the options because
-%% the record elements are replaced at compile time.
-%% So, this can't be parametrized.
-change_option(Option, Value, Config) ->
-    case Option of
-	allow_change_subj -> Config#config{allow_change_subj = Value};
-	allow_private_messages -> Config#config{allow_private_messages = Value};
-	allow_query_users -> Config#config{allow_query_users = Value};
-	allow_user_invites -> Config#config{allow_user_invites = Value};
-	anonymous -> Config#config{anonymous = Value};
-	logging -> Config#config{logging = Value};
-	max_users -> Config#config{max_users = Value};
-	members_by_default -> Config#config{members_by_default = Value};
-	members_only -> Config#config{members_only = Value};
-	moderated -> Config#config{moderated = Value};
-	password -> Config#config{password = Value};
-	password_protected -> Config#config{password_protected = Value};
-	persistent -> Config#config{persistent = Value};
-	public -> Config#config{public = Value};
-	public_list -> Config#config{public_list = Value};
-	title -> Config#config{title = Value}
-    end.
-
-
-%%----------------------------
-%% Get Room Affiliations
-%%----------------------------
-
-%% @spec(Name::binary(), Service::binary()) ->
-%%    [{JID::string(), Domain::string(), Role::string(), Reason::string()}]
-%% @doc Get the affiliations of  the room Name@Service.
-get_room_affiliations(Name, Service) ->
-    case mnesia:dirty_read(muc_online_room, {Name, Service}) of
-	[R] ->
-	    %% Get the PID of the online room, then request its state
-	    Pid = R#muc_online_room.pid,
-	    {ok, StateData} = gen_fsm:sync_send_all_state_event(Pid, get_state),
-	    Affiliations = ?DICT:to_list(StateData#state.affiliations),
-	    lists:map(
-	      fun({{Uname, Domain, _Res}, {Aff, Reason}}) when is_atom(Aff)->
-		      {Uname, Domain, Aff, Reason};
-		 ({{Uname, Domain, _Res}, Aff}) when is_atom(Aff)->
-		      {Uname, Domain, Aff, <<>>}
-	      end, Affiliations);
-	[] ->
-	    throw({error, "The room does not exist."})
-    end.
-
-%%----------------------------
-%% Change Room Affiliation
-%%----------------------------
-
-%% @spec(Name, Service, JID, AffiliationString) -> ok | {error, Error}
-%%       Name = binary()
-%%       Service = binary()
-%%       JID = binary()
-%%       AffiliationString = "outcast" | "none" | "member" | "admin" | "owner"
-%% @doc Set the affiliation of JID in the room Name@Service.
-%% If the affiliation is 'none', the action is to remove,
-%% In any other case the action will be to create the affiliation.
-set_room_affiliation(Name, Service, JID, AffiliationString) ->
-    Affiliation = list_to_atom(AffiliationString),
-    case mnesia:dirty_read(muc_online_room, {Name, Service}) of
-	[R] ->
-	    %% Get the PID for the online room so we can get the state of the room
-	    Pid = R#muc_online_room.pid,
-	    {ok, StateData} = gen_fsm:sync_send_all_state_event(Pid, {process_item_change, {jlib:string_to_jid(JID), affiliation, Affiliation, <<"">>}, <<"">>}),
-	    mod_muc:store_room(StateData#state.server_host, StateData#state.host, StateData#state.room, make_opts(StateData)),
-	    ok;
-	[] ->
-	    error
-    end.
-
--define(MAKE_CONFIG_OPT(Opt), {Opt, Config#config.Opt}).
-
-make_opts(StateData) ->
-    Config = StateData#state.config,
-    [
-     ?MAKE_CONFIG_OPT(title),
-     ?MAKE_CONFIG_OPT(allow_change_subj),
-     ?MAKE_CONFIG_OPT(allow_query_users),
-     ?MAKE_CONFIG_OPT(allow_private_messages),
-     ?MAKE_CONFIG_OPT(public),
-     ?MAKE_CONFIG_OPT(public_list),
-     ?MAKE_CONFIG_OPT(persistent),
-     ?MAKE_CONFIG_OPT(moderated),
-     ?MAKE_CONFIG_OPT(members_by_default),
-     ?MAKE_CONFIG_OPT(members_only),
-     ?MAKE_CONFIG_OPT(allow_user_invites),
-     ?MAKE_CONFIG_OPT(password_protected),
-     ?MAKE_CONFIG_OPT(password),
-     ?MAKE_CONFIG_OPT(anonymous),
-     ?MAKE_CONFIG_OPT(logging),
-     ?MAKE_CONFIG_OPT(max_users),
-     {affiliations, ?DICT:to_list(StateData#state.affiliations)},
-     {subject, StateData#state.subject},
-     {subject_author, StateData#state.subject_author}
-    ].
-
-
-%%----------------------------
-%% Utils
-%%----------------------------
-
-uptime_seconds() ->
-    trunc(element(1, erlang:statistics(wall_clock))/1000).
-
-find_host(global) ->
-    global;
-find_host("global") ->
-    global;
-find_host(<<"global">>) ->
-    global;
-find_host(ServerHost) when is_list(ServerHost) ->
-    find_host(list_to_binary(ServerHost));
-find_host(ServerHost) ->
-    gen_mod:get_module_opt_host(ServerHost, mod_muc, <<"conference.@HOST@">>).
-