Remove modules included in ejabberd 15.04
This commit is contained in:
parent
e5336f02db
commit
9eca69d092
|
@ -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.
|
|
@ -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.
|
|
@ -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
|
||||
|
|
@ -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"
|
|
@ -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"
|
File diff suppressed because it is too large
Load Diff
|
@ -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].
|
||||
|
|
@ -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.
|
|
@ -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.
|
||||
|
|
@ -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.
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
modules:
|
||||
mod_muc_admin: {}
|
|
@ -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"
|
|
@ -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@">>).
|
||||
|
Loading…
Reference in New Issue