From 8945540dc9ca7756a5df66bf472e712ec1a96af0 Mon Sep 17 00:00:00 2001 From: Sonny Scroggin Date: Fri, 2 May 2014 17:12:54 -0500 Subject: [PATCH] ejabberd_xmlrpc is now included with ejabberd 13.12 --- ejabberd_xmlrpc/COPYING | 343 --------------- ejabberd_xmlrpc/ChangeLog | 130 ------ ejabberd_xmlrpc/Emakefile | 2 - ejabberd_xmlrpc/README.txt | 536 ------------------------ ejabberd_xmlrpc/build.bat | 1 - ejabberd_xmlrpc/build.sh | 2 - ejabberd_xmlrpc/ebin/.keepme | 0 ejabberd_xmlrpc/src/ejabberd_xmlrpc.erl | 467 --------------------- 8 files changed, 1481 deletions(-) delete mode 100644 ejabberd_xmlrpc/COPYING delete mode 100644 ejabberd_xmlrpc/ChangeLog delete mode 100644 ejabberd_xmlrpc/Emakefile delete mode 100644 ejabberd_xmlrpc/README.txt delete mode 100644 ejabberd_xmlrpc/build.bat delete mode 100755 ejabberd_xmlrpc/build.sh delete mode 100644 ejabberd_xmlrpc/ebin/.keepme delete mode 100644 ejabberd_xmlrpc/src/ejabberd_xmlrpc.erl diff --git a/ejabberd_xmlrpc/COPYING b/ejabberd_xmlrpc/COPYING deleted file mode 100644 index 8b325f5..0000000 --- a/ejabberd_xmlrpc/COPYING +++ /dev/null @@ -1,343 +0,0 @@ -As a special exception, the authors give permission to link this program -with the OpenSSL library and distribute the resulting binary. - - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 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. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -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. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. diff --git a/ejabberd_xmlrpc/ChangeLog b/ejabberd_xmlrpc/ChangeLog deleted file mode 100644 index f7a0342..0000000 --- a/ejabberd_xmlrpc/ChangeLog +++ /dev/null @@ -1,130 +0,0 @@ -2009-09-11 Badlop - - * src/ejabberd_xmlrpc.erl: Update to work with ejabberd 2.1.0 - -2009-04-28 Badlop - - * src/ejabberd_xmlrpc.erl: Improve handling of errors in arguments - -2009-04-17 Badlop - - * src/ejabberd_xmlrpc.erl: Change access_commands to use the new - AccessCommands feature of ejabberd. Syntax is similar (EJAB-910) - -2009-03-02 Badlop - - * src/ejabberd_xmlrpc.erl: Replace the listener option 'access' - with the much more powerful 'access_commands', that allows to - grant selective permission to execute commands with certain - arguments - * README.txt: Likewise - -2009-02-24 Badlop - - * src/ejabberd_xmlrpc.erl: Update to work with recent ejabberd - trunk SVN (thanks to Artem Yurov) - * README.txt: Likewise - -2008-10-21 Badlop - - * README.txt: Updated PHP example - -2008-10-12 Badlop - - * src/ejabberd_xmlrpc.erl: Major rewrite of mod_xmlrpc to be an - ejabberd independent listener, and to be a frontend of ejabberd - commands (EJAB-694) - -2008-08-31 Badlop - - * README.txt: Added Java example client and fixed the PHP - example (thanks to Calder) - -2008-07-24 Badlop - - * src/mod_xmlrpc.erl: Fixed typo in get_roster - -2008-07-08 Badlop - - * src/mod_xmlrpc.erl: Detect if mod_roster or mod_roster_odbc is - enabled. New call send_message (thanks to Darren Ferguson) - * README.txt: Likewise - -2008-05-20 Badlop - - * src/mod_xmlrpc.erl: New call get_roster; works only with - mod_roster_odbc - * README.txt: Likewise - -2008-05-19 Badlop - - * src/mod_xmlrpc.erl: New function check_account (thanks to - Zbyszek Żółkiewski) - * README.txt: Likewise - -2008-05-18 Badlop - - * README.txt: Added example client in PHP (thanks to Zbyszek - Żółkiewski) - - * src/mod_xmlrpc.erl: Convert from DOS to Unix line format - * README.txt: Likewise - * ChangeLog: Likewise - -2008-05-16 Badlop - - * src/mod_xmlrpc.erl: New calls muc_room_change_option and - muc_room_set_affiliation. Improved calls add_rosteritem and - delete_rosteritem: they push the changed roster item to connected - resources (thanks to Darren Ferguson). New call check_password. - * README.txt: Likewise - -2008-05-06 Badlop - - * src/mod_xmlrpc.erl: Added new calls delete_account, - delete_rosteritem, create_muc_room and destroy_muc_room (thanks to - Darren Ferguson) - * README.txt: Likewise - -2008-02-29 Badlop - - * src/mod_xmlrpc.erl: Added module options: maxsessions, timeout - * README.txt: Likewise - -2007-08-24 Badlop - - * README.txt: Removed requirement of Xmerl 0.20, since it is - included in Erlang/OTP. Instead, require updated XMLRPC-Erlang. - -2007-08-21 Badlop - - * README.txt: New Ruby example (thanks to Diddek). Patched xmlrpc - Erlang library for Ruby compatibility (thanks to Cstar). - - * mod_xmlrpc/*: Initial commit. - -Old Changelog: - -0.2.4 - 7 November 2006 - * Fixed a bug that required clients to provide attributes in a fixed order - -0.2.3 - 22 September 2006 - * New feature: bind to a specific IP address, requires the patched XML-RPC-Erlang-1.13-IP (thanks to Zeank) - -0.2.2 - 15 August 2006 - * Fixed small bug on resource_num (thanks to Flipkick) - -0.2.1 - 20 July 2006 - * Fixed small bug on add_rosteritem (thanks to Leonexis) - -0.2.0 - 16 April 2006 - * Added two new calls: num_resources and resouce_num - * Added support for vhosts - -0.1.2 - 28 December 2005 - * Now compatible with ejabberd 1.0.0 - * The XMLRPC server is started only once, not once for every virtual host - * Added comments for handlers. Every available handler must be explained - -0.1.0 - 4 April 2005 - * Initial version diff --git a/ejabberd_xmlrpc/Emakefile b/ejabberd_xmlrpc/Emakefile deleted file mode 100644 index fb9dc10..0000000 --- a/ejabberd_xmlrpc/Emakefile +++ /dev/null @@ -1,2 +0,0 @@ -{'../ejabberd-dev/src/gen_mod', [{outdir, "../ejabberd-dev/ebin"},{i,"../ejabberd-dev/include"}]}. -{'src/ejabberd_xmlrpc', [{outdir, "ebin"},{i,"../ejabberd-dev/include"}]}. diff --git a/ejabberd_xmlrpc/README.txt b/ejabberd_xmlrpc/README.txt deleted file mode 100644 index f5b46f9..0000000 --- a/ejabberd_xmlrpc/README.txt +++ /dev/null @@ -1,536 +0,0 @@ - - ejabberd_xmlrpc - XML-RPC server - - Homepage: http://www.ejabberd.im/ejabberd_xmlrpc - Author: Badlop - - - DESCRIPTION - ----------- - -ejabberd_xmlrpc is an ejabberd listener that starts a XML-RPC server -and waits for external calls. - -ejabberd_xmlrpc implements some example calls that can be used to test -during the development of a new XML-RPC client. But most -importantly, ejabberd_xmlrpc is also a frontend to execute ejabberd -commands. This way a XML-RPC client can execute any ejabberd command. - -This allows external programs written in any language like websites or -administrative tools to communicate with ejabberd to get information -or to make changes without the need to know ejabberd internals. One -example usage is a corporate site in PHP that creates a Jabber user -every time a new user is created on the website. - -Some benefits of interfacing with the Jabber server by XML-RPC instead -of modifying directly the database are: - - external programs are more simple and easy to develop and debug - - can communicate with a server in a different machine, and even on Internet - - - REQUIREMENTS - ------------ - - ejabberd 2.1.0 or higher - XMLRPC-Erlang 1.13 with IP, Ruby and Xmerl 1.x patches - Optional: mod_admin_extra implements many ejabberd commands for general server administration - Optional: mod_muc_admin implements ejabberd commands for MUC administration - - - CONFIGURE EJABBERD - ------------------ - -1. You need to get and install XMLRPC-Erlang. -You can download XMLRPC-Erlang binary files from - http://www.ejabberd.im/ejabberd_xmlrpc -or compile it yourself: - wget http://www.ejabberd.im/files/contributions/xmlrpc-1.13-ipr2.tgz - tar -xzvf xmlrpc-1.13-ipr2.tgz - cd xmlrpc-1.13/src - make - cd ../../ -Then you can copy the *.beam files to ejabberd ebin directory, -or add an option like this to the ejabberd start script: -$ erl -pa '/home/jabber/xmlrpc-1.13/ebin' ... - -2. Configure ejabberd to start this listener at startup: -edit ejabberd.cfg and add on the 'listen' section: -{listen, [ - {4560, ejabberd_xmlrpc, []}, - ... - ]}. - -3. Start ejabberd. - -4. Verify that ejabberd is listening in that port: -$ netstat -n -l | grep 4560 -tcp 0 0 0.0.0.0:4560 0.0.0.0:* LISTEN - -5. If there is any problem, check ejabberd.log and sasl.log files - - - CONFIGURE - --------- - -The listener allow several configurable options: - - {maxsessions, Integer} - Number of concurrent connections allowed. - Default: 10 - - {timeout, Integer} - Timeout of the connections, expressed in milliseconds. - Default: 5000 - - {access_commands, AccessCommands} - This option allows to define a list of access restrictions. - If this option is present, then XML-RPC calls must include as - first argument a struct with a user, server and password of an - account in ejabberd that has privileges in Access. - If the option is not present, such struct must not be provided. - The default value is to not define any restriction: [] - When one or several access restrictions are defined and the - XML-RPC call provides authentication for an account, each - restriction is verified until one matches completely: - the account matches the Access rule, - the command name is listed in CommandNames, - and the provided arguments do not contradict Arguments. - There is more information about AccessCommands in the ejabberd Guide. - - -Example configuration: XML-RPC calls can execute any command, with any -argument, and no authentication information must be provided: -{listen, [ - {4560, ejabberd_xmlrpc, [{maxsessions, 10}, {timeout, 5000}]}, - ... - ]}. - -In this case authentication information must be provided, but it is -enough that the account exists and the password is valid to execute -any command: -{listen, [ - {4560, ejabberd_xmlrpc, [{maxsessions, 10}, {timeout, 5000}, - {access_commands, [{all, all, []}]}]}, - ... - ]}. - -In this example the local Jabber account xmlrpc-robot@jabber.example.org -can execute any command with no argument restriction: -{acl, xmlrpcbot, {user, "xmlrpc-robot", "jabber.example.org"}}. -{access, xmlrpcaccess, [{allow, xmlrpcbot}]}. -{listen, [ - {4560, ejabberd_xmlrpc, [{maxsessions, 10}, {timeout, 5000}, - {access_commands, [{xmlrpcaccess, all, []}]}]}, - ... - ]}. - -Finally, in this complex example the listener only listens in port -4560 of IP address 127.0.0.1, and several access restrictions are -defined (the corresponding ACL and ACCESS are not shown): -{listen, [ - {{4560, "127.0.0.1"}, ejabberd_xmlrpc, [ - {access_commands, [ - %% This bot can execute any command: - {xmlrpc_bot, all, []}, - %% This bot can execute any command, - %% but if a 'host' argument is provided, it must be "example.org": - {xmlrpc_bot_all_example, all, [{host, "example.org"}]}, - %% This bot can only execute the command 'dump'. No argument restriction: - {xmlrpc_bot_backups, [dump], []} - %% This bot can only execute the command 'register', - %% and if argument 'host' is provided, it must be "example.org": - {xmlrpc_bot_reg_example, [register], [{host, "example.org"}]}, - %% This bot can execute the commands 'register' and 'unregister', - %% if argument host is provided, it must be "test.org": - {xmlrpc_bot_reg_test, [register, unregister], [{host, "test.org"}]} - ]} - ]}, - ... - ]}. - -Example configuration in ejabberd 13, using YAML formatting: -acl: - restxmlrpcadmin: - user: - - "admin": "example.com" - xmlrpcadmin: - user: - - "adminjabber": "example.org" - rpcadmin: - user: - - "admin1": "example.net" - -access: - restxmlrpcaccess: - restxmlrpcadmin: allow - admin: allow - xmlrpcaccess: - xmlrpcadmin: allow - rpcaccess: - rpcadmin: allow - -listen: -- - #ip: "127.0.0.1" - port: 4560 - module: ejabberd_xmlrpc - timeout: 30000 - maxsessions: 20 - access_commands: - restxmlrpcaccess: - all : [] - xmlrpcaccess: - commands: [register,status] - options: [] - rpcaccess: - commands: [unregister,status] - options: [] - - - USAGE - ----- - -You can send calls to http://host:4560/ - -Call: Arguments: Returns: - - -- debug -echothis String String -echothisnew struct[{sentence, String}] struct[{repeated, String}] -multhis struct[{a, Integer}, {b, Integer}] Integer -multhisnew struct[{a, Integer}, {b, Integer}] struct[{mu, Integer}] - - -- statistics -tellme_title String String -tellme_value String String -tellme String struct[{title, String}, {value. String}] - - -With ejabberd_xmlrpc you can execute any ejabberd command with a XML-RPC call. - -1. Get a list of available ejabberd commands, for example: -$ ejabberdctl help -Available commands in this ejabberd node: - connected_users List all established sessions - connected_users_number Get the number of established sessions - delete_expired_messages Delete expired offline messages from database - delete_old_messages days Delete offline messages older than DAYS - dump file Dump the database to text file - register user host password Register a user - registered_users host List all registered users in HOST - reopen_log Reopen the log files - restart Restart ejabberd - restore file Restore the database from backup file - status Get ejabberd status - stop Stop ejabberd - unregister user host Unregister a user - user_resources user host List user's connected resources - -2. When you found the command you want to call, get some additional - help of the arguments and result: -$ ejabberdctl help user_resources - Command Name: user_resources - Arguments: user::string - host::string - Returns: resources::[ resource::string ] - Tags: session - Description: List user's connected resources - -3. You can try to execute the command in the shell for the account testuser@localhost: -$ ejabberdctl user_resources testuser localhost -Home -Psi - -4. Now implement the proper XML-RPC call in your XML-RPC client. - This example will use the Erlang library: -$ erl -1> xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, user_resources, [{struct, [{user, "testuser"}, {host, "localhost"}]}]}). -{ok,{response,[{struct,[{resources,{array,[{struct,[{resource,"Home"}]}, - {struct,[{resource,"Psi"}]}]}}]}]}} - -5. Note: if ejabberd_xmlrpc has the option 'access_commands' - configured with some access restriction (see the example - configurations provided above), the XML-RPC must include first an - argument providing information of a valid account. For example: -1> xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, user_resources, [ - {struct, [{user, "adminuser"}, {server, "localhost"}, {password, "aeiou"}]}, - {struct, [{user, "testuser"}, {host, "localhost"}]} ]}). - - -Arguments in XML-RPC calls can be provided in any order; -This module will sort the arguments before calling the ejabberd command. - -If auth is provided in the call when ejabberd_xmlrpc does not require it, -the call will return the error: -112 Unknown call - - - - EXAMPLE IN PHP - -------------- - -This is an XML-RPC client in PHP, thanks to Zbyszek Żółkiewski and Calder. -It requires "allow_url_fopen = On" in your php.ini. - -------- -"testuser", "host"=>"localhost"); -$request = xmlrpc_encode_request('user_resources', $param, (array('encoding' => 'utf-8'))); - -$context = stream_context_create(array('http' => array( - 'method' => "POST", - 'header' => "User-Agent: XMLRPC::Client mod_xmlrpc\r\n" . - "Content-Type: text/xml\r\n" . - "Content-Length: ".strlen($request), - 'content' => $request -))); - -$file = file_get_contents("http://127.0.0.1:4560/RPC2", false, $context); - -$response = xmlrpc_decode($file); - -if (xmlrpc_is_fault($response)) { - trigger_error("xmlrpc: $response[faultString] ($response[faultCode])"); -} else { - print_r($response); -} - -?> -------- - -The response, following the example would be like this: -------- -$ php5 call.php -Array -( - [resources] => Array - ( - [0] => Array - ( - [resource] => Home - ) - [1] => Array - ( - [resource] => Psi - ) - ) -) -------- - -If you configured the option access_commands, you have to provide authentication -information by replacing the first lime with something like this: -------- -$param_auth=array("user"=>"analloweduser", "server"=>"localhost", "password"=>"MyPasS997"); -$param_comm=array("user"=>"testuser", "host"=>"localhost"); -$param=array($param_auth, $param_comm); -------- - - - **** WARNING: all the remaining text was written for mod_xmlrpc and - is NOT valid for ejabberd_xmlrpc **** - - - TEST - ---- - - - You can easily try the XML-RPC server starting a new Erlang Virtual Machine - and making calls to ejabberd's XML-RPC: - -1. Start Erlang with this option: -$ erl -pa '/home/jabber/xmlrpc-1.13/ebin' - -2. Now on the Erlang console, write commands and check the results: - -1> xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, echothis, [800]}). -{ok,{response,[800]}} - -2> xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, echothis, ["blot cloc 557.889 kg"]}). -{ok,{response,["blot cloc 557.889 kg"]}} - -3> xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, multhis, [{struct,[{a, 83}, {b, 689}]}]}). -{ok,{response,[57187]}} - -4> xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, register, -[{struct, [{user, "ggeo"}, {host, "example.com"}, {password, "gogo11"}]}]}). -{ok,{response,[0]}} - -5> xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, register, -[{struct, [{user, "ggeo"}, {host, "example.com"}, {password, "gogo11"}]}]}). -{ok,{response,[409]}} - -6> xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, muc_room_change_option, -[{struct, [{name, "test"}, {service, "conference.localhost"}, - {option, "title"}, {value, "Test Room"}]}]}). - -7> xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, muc_room_set_affiliation, -[{struct, [{name, "test"}, {service, "conference.example.com"}, -{jid, "ex@example.com"}, {affiliation, "member"}]}]}). - -8> xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, muc_room_set_affiliation, -[{struct, [{name, "test"}, {service, "conference.example.com"}, -{jid, "ex@example.com"}, {affiliation, "none"}]}]}). - - - - Some possible XML-RPC error messages: - - + Client: connection refused: wrong IP, wrong port, the server is not started... - -2> xmlrpc:call({127, 0, 0, 1}, 44444, "/", {call, echothis, [800]}). -{error,econnrefused} - - + Client: bad value: a800 is a string, so it must be put into "" - -7> xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, echothis, [a800]}). -{error,{bad_value,a800}} - - + Server: unknown call: you sent a call that the server does not implement - -3> xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, bububu, [800]}). -{ok,{response,{fault,-1,"Unknown call: {call,bububu,[800]}"}}} - - - EXAMPLE IN PYTHON - ----------------- - -This is an example XML-RPC client in Python, thanks to Diddek: -------- -import xmlrpclib - -server_url = 'http://127.0.0.1:4560'; -server = xmlrpclib.Server(server_url); - -params = {} -params["user"] = "ggeo" -params["host"] = "localhost" -params["password"] = "gogo11" - -result = server.register(params) -print result -------- - -This Python example shows how to provide authentication in the call, thanks to Muelli: -------- -import xmlrpclib - -server_url = 'http://127.0.0.1:4560' -server = xmlrpclib.ServerProxy(server_url) - -EJABBERD_XMLRPC_LOGIN = {'user': 'adminuser', 'server': 'localhost', 'password': 'aeiou'} - -def ejabberdctl(command, data): - fn = getattr(server, command) - return fn(EJABBERD_XMLRPC_LOGIN, data) - -result = ejabberdctl('register', {'user':'ggeo', 'host':'localhost', 'password':'gogo11'}) -print result -------- - - - EXAMPLE IN RUBY - --------------- - -This is an example XML-RPC client in Ruby, thanks to Diddek: -------- -require 'xmlrpc/client' - -host = "172.16.29.6:4560" -timeout = 3000000 -client = XMLRPC::Client.new2("http://#{host}", "#{host}", timeout) -result = client.call("echothis", "800") -puts result -------- - - - EXAMPLE IN JAVA - --------------- - -This is an XML-RPC client in Java, thanks to Calder. -It requires Apache XML-RPC available at http://ws.apache.org/xmlrpc/ - -------- -import java.net.URL; -import java.util.HashMap; -import java.util.Map; - -import org.apache.xmlrpc.client.XmlRpcClient; -import org.apache.xmlrpc.client.XmlRpcClientConfigImpl; - -public class Test { - - public static void main(String[] args) { - try { - XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl(); - config.setServerURL(new URL("http://127.0.0.1:4560/RPC2")); - XmlRpcClient client = new XmlRpcClient(); - client.setConfig(config); - - /* Command string */ - String command = "check_password"; - - /* Parameters as struct */ - Map struct = new HashMap(); - struct.put("user", "test1"); - struct.put("host", "localhost"); - struct.put("password", "test"); - - Object[] params = new Object[]{struct}; - Integer result = (Integer) client.execute(command, params); - System.out.println(result); - } catch (Exception e) { - System.out.println(e); - } - } - -} -------- - - - EXAMPLE IN C# - ------------- - -This is an XML-RPC client in C#, thanks to Mitchel Constantin. - -------- -// Copyright: 2010 Weavver, Inc. -// Author: Mitchel Constantin -// License: Public Domain (Limited to this file) - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using CookComputing.XmlRpc; - -namespace Weavver.Vendors.ProcessOne -{ - public struct send_message_chat - { - public string from; - public string to; - public string body; - } - public struct status {} - public class ejabberdRPC - { - [XmlRpcUrl("http://205.134.225.18:4560/RPC2")] - public interface IStateName : IXmlRpcProxy - { - [XmlRpcMethod("send_message_chat")] - object SendMessageChat(send_message_chat message); - [XmlRpcMethod("status")] - object Status(status s); - } - public CookComputing.XmlRpc.XmlRpcStruct SendMessageChat(send_message_chat message) - { - IStateName proxy = XmlRpcProxyGen.Create(); - proxy.KeepAlive = false; - return (CookComputing.XmlRpc.XmlRpcStruct) proxy.SendMessageChat(message); - } - public CookComputing.XmlRpc.XmlRpcStruct Status(status status) - { - IStateName proxy = XmlRpcProxyGen.Create(); - proxy.KeepAlive = false; - return (CookComputing.XmlRpc.XmlRpcStruct) proxy.Status(status); - } - } -} -------- diff --git a/ejabberd_xmlrpc/build.bat b/ejabberd_xmlrpc/build.bat deleted file mode 100644 index fff9b3b..0000000 --- a/ejabberd_xmlrpc/build.bat +++ /dev/null @@ -1 +0,0 @@ -erl -pa ../../ejabberd-dev/trunk/ebin -pa ebin -make diff --git a/ejabberd_xmlrpc/build.sh b/ejabberd_xmlrpc/build.sh deleted file mode 100755 index f0a0cfa..0000000 --- a/ejabberd_xmlrpc/build.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -erl -pa ../ejabberd-dev/ebin -pz ebin -make diff --git a/ejabberd_xmlrpc/ebin/.keepme b/ejabberd_xmlrpc/ebin/.keepme deleted file mode 100644 index e69de29..0000000 diff --git a/ejabberd_xmlrpc/src/ejabberd_xmlrpc.erl b/ejabberd_xmlrpc/src/ejabberd_xmlrpc.erl deleted file mode 100644 index 0e958a1..0000000 --- a/ejabberd_xmlrpc/src/ejabberd_xmlrpc.erl +++ /dev/null @@ -1,467 +0,0 @@ -%%%---------------------------------------------------------------------- -%%% File : ejabberd_xmlrpc.erl -%%% Author : Badlop -%%% Purpose : XML-RPC server that frontends ejabberd commands -%%% Created : 21 Aug 2007 by Badlop -%%% Id : $Id: ejabberd_xmlrpc.erl 595 2008-05-20 11:39:31Z badlop $ -%%%---------------------------------------------------------------------- - -%%% TODO: Implement a command in ejabberdctl 'help COMMAND LANGUAGE' that shows -%%% a coding example to call that command in a specific language (python, php). - -%%% TODO: Remove support for plaintext password - -%%% TODO: commands strings should be strings without ~n - --module(ejabberd_xmlrpc). --author('badlop@process-one.net'). - --export([ - start_listener/2, - handler/2, - socket_type/0 - ]). - --include("ejabberd.hrl"). --include("mod_roster.hrl"). --include("jlib.hrl"). - --record(state, {access_commands, auth = noauth, get_auth}). - - -%% Test: - -%% xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, take_integer, [{struct, [{thisinteger, 5}]}]}). -%% {ok,{response,[{struct,[{zero,0}]}]}} -%% -%% xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, echo_string, [{struct, [{thisstring, "abcd"}]}]}). -%% {ok,{response,[{struct,[{thatstring,"abcd"}]}]}} -%% -%% xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, tell_tuple_3integer, [{struct, [{thisstring, "abcd"}]}]}). -%% {ok,{response, -%% [{struct, -%% [{thattuple, -%% {array, -%% [{struct,[{first,123}]}, -%% {struct,[{second,456}]}, -%% {struct,[{third,789}]}]}}]}]}} -%% -%% xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, pow, [{struct, [{base, 5}, {exponent, 7}]}]}). -%% {ok,{response,[{struct,[{pow,78125}]}]}} -%% -%% xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, seq, [{struct, [{from, 3}, {to, 7}]}]}). -%% {ok,{response,[{array,[{struct,[{intermediate,3}]}, -%% {struct,[{intermediate,4}]}, -%% {struct,[{intermediate,5}]}, -%% {struct,[{intermediate,6}]}, -%% {struct,[{intermediate,7}]}]}]}} -%% -%% xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, substrs, [{struct, [{word, "abcd"}]}]}). -%% NO: -%% {ok,{response,[{array,[{struct,[{miniword,"a"}]}, -%% {struct,[{miniword,"ab"}]}, -%% {struct,[{miniword,"abc"}]}, -%% {struct,[{miniword,"abcd"}]}]}]}} -%% {ok,{response, -%% [{struct, -%% [{substrings, -%% {array, -%% [{struct,[{miniword,"a"}]}, -%% {struct,[{miniword,"ab"}]}, -%% {struct,[{miniword,"abc"}]}, -%% {struct,[{miniword,"abcd"}]}]}}]}]}} -%% -%% xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, splitjid, [{struct, [{jid, "abcd@localhost/work"}]}]}). -%% {ok,{response, -%% [{struct, -%% [{jidparts, -%% {array, -%% [{struct,[{user,"abcd"}]}, -%% {struct,[{server,"localhost"}]}, -%% {struct,[{resource,"work"}]}]}}]}]}} -%% -%% xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, echo_integer_string, [{struct, [{thisstring, "abc"}, {thisinteger, 55}]}]}). -%% {ok,{response, -%% [{struct, -%% [{thistuple, -%% {array, -%% [{struct,[{thisinteger,55}]}, -%% {struct,[{thisstring,"abc"}]}]}}]}]}} -%% -%% -%% xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, echo_list_integer, [{struct, [{thislist, {array, [{struct, [{thisinteger, 55}, {thisinteger, 4567}]}]}}]}]}). -%% {ok,{response, -%% [{struct, -%% [{thatlist, -%% {array, -%% [{struct,[{thatinteger,55}]}, -%% {struct,[{thatinteger,4567}]}]}}]}]}} -%% -%% -%% xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, echo_integer_list_string, [{struct, [{thisinteger, 123456}, {thislist, {array, [{struct, [{thisstring, "abc"}, {thisstring, "bobo baba"}]}]}}]}]}). -%% {ok, -%% {response, -%% [{struct, -%% [{thistuple, -%% {array, -%% [{struct,[{thatinteger,123456}]}, -%% {struct, -%% [{thatlist, -%% {array, -%% [{struct,[{thatstring,"abc"}]}, -%% {struct,[{thatstring,"bobo baba"}]}]}}]}]}}]}]}} -%% -%% xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, take_tuple_2integer, [{struct, [{thistuple, {array, [{struct, [{thisinteger1, 55}, {thisinteger2, 4567}]}]}}]}]}). -%% {ok,{response,[{struct,[{zero,0}]}]}} -%% -%% xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, echo_isatils, [{struct, -%% [{thisinteger, 123456990}, -%% {thisstring, "This is ISATILS"}, -%% {thisatom, "test_isatils"}, -%% {thistuple, {array, [{struct, [ -%% {listlen, 2}, -%% {thislist, {array, [{struct, [ -%% {contentstring, "word1"}, -%% {contentstring, "word 2"} -%% ]}]}} -%% ]}]}} -%% ]}]}). -%% {ok,{response, -%% [{struct, -%% [{results, -%% {array, -%% [{struct,[{thatinteger,123456990}]}, -%% {struct,[{thatstring,"This is ISATILS"}]}, -%% {struct,[{thatatom,"test_isatils"}]}, -%% {struct, -%% [{thattuple, -%% {array, -%% [{struct,[{listlen,123456990}]}, -%% {struct,[{thatlist,...}]}]}}]}]}}]}]}} - -%% ecommand doesn't exist: -%% xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, echo_integer_string2, [{struct, [{thisstring, "abc"}]}]}). -%% {ok,{response,{fault,-1, "Unknown call: {call,echo_integer_string2,[{struct,[{thisstring,\"abc\"}]}]}"}}} -%% -%% Duplicated argument: -%% xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, echo_integer_string, [{struct, [{thisstring, "abc"}, {thisinteger, 44}, {thisinteger, 55}]}]}). -%% {ok,{response,{fault,-104, "Error -104\nAttribute 'thisinteger' duplicated:\n[{thisstring,\"abc\"},{thisinteger,44},{thisinteger,55}]"}}} -%% -%% Missing argument: -%% xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, echo_integer_string, [{struct, [{thisstring, "abc"}]}]}). -%% {ok,{response,{fault,-106, "Error -106\nRequired attribute 'thisinteger' not found:\n[{thisstring,\"abc\"}]"}}} -%% -%% Duplicated tuple element: -%% xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, take_tuple_2integer, [{struct, [{thistuple, {array, [{struct, [{thisinteger1, 55}, {thisinteger1, 66}, {thisinteger2, 4567}]}]}}]}]}). -%% {ok,{response,{fault,-104, "Error -104\nAttribute 'thisinteger1' defined multiple times:\n[{thisinteger1,55},{thisinteger1,66},{thisinteger2,4567}]"}}} -%% -%% Missing element in tuple: -%% xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, take_tuple_2integer, [{struct, [{thistuple, {array, [{struct, [{thisinteger1, 55}, {thisintegerc, 66}, {thisinteger, 4567}]}]}}]}]}). -%% {ok,{response,{fault,-106, "Error -106\nRequired attribute 'thisinteger2' not found:\n[{thisintegerc,66},{thisinteger,4567}]"}}} -%% -%% The ecommand crashed: -%% xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, this_crashes, [{struct, []}]}). -%% {ok,{response,{fault,-100, "Error -100\nA problem 'error' occurred executing the command this_crashes with arguments []: badarith"}}} - - -%% ----------------------------- -%% Listener interface -%% ----------------------------- - -start_listener({Port, Ip, tcp = _TranportProtocol}, Opts) -> - %% get options - MaxSessions = gen_mod:get_opt(maxsessions, Opts, 10), - Timeout = gen_mod:get_opt(timeout, Opts, 5000), - AccessCommands = gen_mod:get_opt(access_commands, Opts, []), - GetAuth = case [ACom || {Ac, _, _} = ACom <- AccessCommands, Ac /= all] of - [] -> false; - _ -> true - end, - - %% start the XML-RPC server - Handler = {?MODULE, handler}, - State = #state{access_commands = AccessCommands, get_auth = GetAuth}, - xmlrpc:start_link(Ip, Port, MaxSessions, Timeout, Handler, State). - -socket_type() -> - independent. - - -%% ----------------------------- -%% Access verification -%% ----------------------------- - -%% @spec (AuthList) -> {User, Server, Password} -%% where -%% AuthList = [{user, string()}, {server, string()}, {password, string()}] -%% It may throw: {error, missing_auth_arguments, Attr} -get_auth(AuthList) -> - %% Check AuthList contains all the required data - [User, Server, Password] = - try get_attrs([user, server, password], AuthList) of - [U, S, P] -> [U, S, P] - catch - exit:{attribute_not_found, Attr, _} -> - throw({error, missing_auth_arguments, Attr}) - end, - {User, Server, Password}. - - -%% ----------------------------- -%% Handlers -%% ----------------------------- - -%% Call: Arguments: Returns: - - -%% ............................. -%% Access verification - -%% xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, echothis, [152]}). -%% {ok,{response,{fault,-103, "Error -103\nRequired authentication: {call,echothis,[152]}"}}} -%% -%% xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, echothis, [{struct, [{user, "badlop"}, {server, "localhost"}, {password, "ada"}]}, 152]}). -%% {ok,{response,{fault,-103, -%% "Error -103\nAuthentication non valid: [{user,\"badlop\"},\n -%% {server,\"localhost\"},\n -%% {password,\"ada\"}]"}}} -%% -%% xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, echothis, [{struct, [{user, "badlop"}, {server, "localhost"}, {password, "ada90ada"}]}, 152]}). -%% {ok,{response,[152]}} -%% -%% xmlrpc:call({127, 0, 0, 1}, 4560, "/", {call, echothis, [{struct, [{user, "badlop"}, {server, "localhost"}, {password, "79C1574A43BC995F2B145A299EF97277"}]}, 152]}). -%% {ok,{response,[152]}} - -handler(#state{get_auth = true, auth = noauth} = State, {call, Method, [{struct, AuthList} | Arguments] = AllArgs}) -> - try get_auth(AuthList) of - Auth -> - handler(State#state{get_auth = false, auth = Auth}, {call, Method, Arguments}) - catch - {error, missing_auth_arguments, _Attr} -> - handler(State#state{get_auth = false, auth = noauth}, {call, Method, AllArgs}) - end; - - -%% ............................. -%% Debug - -%% echothis String String -handler(_State, {call, echothis, [A]}) -> - {false, {response, [A]}}; - -%% echothisnew struct[{sentence, String}] struct[{repeated, String}] -handler(_State, {call, echothisnew, [{struct, [{sentence, A}]}]}) -> - {false, {response, [{struct, [{repeated, A}]}]}}; - -%% multhis struct[{a, Integer}, {b, Integer}] Integer -handler(_State, {call, multhis, [{struct, [{a, A}, {b, B}]}]}) -> - {false, {response, [A*B]}}; - -%% multhisnew struct[{a, Integer}, {b, Integer}] struct[{mu, Integer}] -handler(_State, {call, multhisnew, [{struct, [{a, A}, {b, B}]}]}) -> - {false, {response, [{struct, [{mu, A*B}]}]}}; - -%% ............................. -%% Statistics - -%% tellme_title String String -handler(_State, {call, tellme_title, [A]}) -> - {false, {response, [get_title(A)]}}; - -%% tellme_value String String -handler(_State, {call, tellme_value, [A]}) -> - N = node(), - {false, {response, [get_value(N, A)]}}; - -%% tellme String struct[{title, String}, {value. String}] -handler(_State, {call, tellme, [A]}) -> - N = node(), - T = {title, get_title(A)}, - V = {value, get_value(N, A)}, - R = {struct, [T, V]}, - {false, {response, [R]}}; - -%% ............................. -%% ejabberd commands - -handler(State, {call, Command, []}) -> - %% The XMLRPC request may not contain a struct parameter, - %% but our internal functions need such struct, even if it's empty - %% So let's add it and do a recursive call: - handler(State, {call, Command, [{struct, []}]}); - -handler(State, {call, Command, [{struct, AttrL}]} = Payload) -> - case ejabberd_commands:get_command_format(Command) of - {error, command_unknown} -> - build_fault_response(-112, "Unknown call: ~p", [Payload]); - {ArgsF, ResultF} -> - try_do_command(State#state.access_commands, State#state.auth, Command, AttrL, ArgsF, ResultF) - end; - -%% If no other guard matches -handler(_State, Payload) -> - build_fault_response(-112, "Unknown call: ~p", [Payload]). - - -%% ----------------------------- -%% Command -%% ----------------------------- - -try_do_command(AccessCommands, Auth, Command, AttrL, ArgsF, ResultF) -> - try do_command(AccessCommands, Auth, Command, AttrL, ArgsF, ResultF) of - {command_result, ResultFormatted} -> - {false, {response, [ResultFormatted]}} - catch - exit:{duplicated_attribute, ExitAt, ExitAtL} -> - build_fault_response(-114, "Attribute '~p' duplicated:~n~p", [ExitAt, ExitAtL]); - exit:{attribute_not_found, ExitAt, ExitAtL} -> - build_fault_response(-116, "Required attribute '~p' not found:~n~p", [ExitAt, ExitAtL]); - exit:{additional_unused_args, ExitAtL} -> - build_fault_response(-120, "The call provided additional unused arguments:~n~p", [ExitAtL]); - throw:Why -> - build_fault_response(-118, "A problem '~p' occurred executing the command ~p with arguments~n~p", [Why, Command, AttrL]) - end. - -build_fault_response(Code, ParseString, ParseArgs) -> - FaultString = "Error " ++ integer_to_list(Code) ++ "\n" ++ - lists:flatten(io_lib:format(ParseString, ParseArgs)), - ?WARNING_MSG(FaultString, []), %% Show Warning message in ejabberd log file - {false, {response, {fault, Code, FaultString}}}. - -do_command(AccessCommands, Auth, Command, AttrL, ArgsF, ResultF) -> - ArgsFormatted = format_args(AttrL, ArgsF), - Result = ejabberd_commands:execute_command(AccessCommands, Auth, Command, ArgsFormatted), - ResultFormatted = format_result(Result, ResultF), - {command_result, ResultFormatted}. - - -%%----------------------------- -%% Format arguments -%%----------------------------- - -get_attrs(Attribute_names, L) -> - [get_attr(A, L) || A <- Attribute_names]. - -get_attr(A, L) -> - case lists:keysearch(A, 1, L) of - {value, {A, Value}} -> Value; - false -> - %% Report the error and then force a crash - exit({attribute_not_found, A, L}) - end. - -%% Get an element from a list and delete it. -%% The element must be defined once and only once, -%% otherwise the function crashes on purpose. -get_elem_delete(A, L) -> - case proplists:get_all_values(A, L) of - [Value] -> - {Value, proplists:delete(A, L)}; - [_, _ | _] -> - %% Crash reporting the error - exit({duplicated_attribute, A, L}); - [] -> - %% Report the error and then force a crash - exit({attribute_not_found, A, L}) - end. - - -format_args(Args, ArgsFormat) -> - {ArgsRemaining, R} = - lists:foldl( - fun({ArgName, ArgFormat}, {Args1, Res}) -> - {ArgValue, Args2} = get_elem_delete(ArgName, Args1), - Formatted = format_arg(ArgValue, ArgFormat), - {Args2, Res ++ [Formatted]} - end, - {Args, []}, - ArgsFormat), - case ArgsRemaining of - [] -> R; - L when is_list(L) -> - exit({additional_unused_args, L}) - end. -format_arg({array, [{struct, Elements}]}, {list, {ElementDefName, ElementDefFormat}}) - when is_list(Elements) -> - lists:map( - fun({ElementName, ElementValue}) -> - true = (ElementDefName == ElementName), - format_arg(ElementValue, ElementDefFormat) - end, - Elements); -format_arg({array, [{struct, Elements}]}, {tuple, ElementsDef}) - when is_list(Elements) -> - FormattedList = format_args(Elements, ElementsDef), - list_to_tuple(FormattedList); -format_arg({array, Elements}, {list, ElementsDef}) - when is_list(Elements) and is_atom(ElementsDef) -> - [format_arg(Element, ElementsDef) || Element <- Elements]; -format_arg(Arg, integer) - when is_integer(Arg) -> - Arg; -format_arg(Arg, string) - when is_list(Arg) -> - Arg. - - -%% ----------------------------- -%% Result -%% ----------------------------- - -format_result({error, Error}, _) -> - throw({error, Error}); - -format_result(String, string) -> - lists:flatten(String); - -format_result(Atom, {Name, atom}) -> - {struct, [{Name, atom_to_list(Atom)}]}; - -format_result(Int, {Name, integer}) -> - {struct, [{Name, Int}]}; - -format_result(String, {Name, string}) -> - {struct, [{Name, lists:flatten(String)}]}; - -format_result(Code, {Name, rescode}) -> - {struct, [{Name, make_status(Code)}]}; - -format_result({Code, Text}, {Name, restuple}) -> - {struct, [{Name, make_status(Code)}, - {text, lists:flatten(Text)}]}; - -%% Result is a list of something: [something()] -format_result(Elements, {Name, {list, ElementsDef}}) -> - FormattedList = lists:map( - fun(Element) -> - format_result(Element, ElementsDef) - end, - Elements), - {struct, [{Name, {array, FormattedList}}]}; - -%% Result is a tuple with several elements: {something1(), something2(), ...} -format_result(ElementsTuple, {Name, {tuple, ElementsDef}}) -> - ElementsList = tuple_to_list(ElementsTuple), - ElementsAndDef = lists:zip(ElementsList, ElementsDef), - FormattedList = lists:map( - fun({Element, ElementDef}) -> - format_result(Element, ElementDef) - end, - ElementsAndDef), - {struct, [{Name, {array, FormattedList}}]}. -%% TODO: should be struct instead of array? - - -make_status(ok) -> 0; -make_status(true) -> 0; -make_status(false) -> 1; -make_status(error) -> 1; -make_status(_) -> 1. - - -%% ----------------------------- -%% Internal -%% ----------------------------- - -get_title(A) -> mod_statsdx:get_title(A). -get_value(N, A) -> mod_statsdx:get(N, [A]).