diff options
author | Max Kellermann <max@duempel.org> | 2013-10-20 13:41:04 +0200 |
---|---|---|
committer | Max Kellermann <max@duempel.org> | 2013-10-20 13:41:04 +0200 |
commit | 5ec843dcc89737bb2ca9e428415d9a052c5a753d (patch) | |
tree | 17fea4f30c52810ece404200698f1975610f2c3b /src/AllCommands.cxx | |
parent | a78b2d84ed7c2a82c69c56125036e70b009a87b0 (diff) | |
download | mpd-5ec843dcc89737bb2ca9e428415d9a052c5a753d.tar.gz mpd-5ec843dcc89737bb2ca9e428415d9a052c5a753d.tar.xz mpd-5ec843dcc89737bb2ca9e428415d9a052c5a753d.zip |
*Commands: move to src/command/
Diffstat (limited to 'src/AllCommands.cxx')
-rw-r--r-- | src/AllCommands.cxx | 375 |
1 files changed, 0 insertions, 375 deletions
diff --git a/src/AllCommands.cxx b/src/AllCommands.cxx deleted file mode 100644 index 2271aeff2..000000000 --- a/src/AllCommands.cxx +++ /dev/null @@ -1,375 +0,0 @@ -/* - * Copyright (C) 2003-2012 The Music Player Daemon Project - * http://www.musicpd.org - * - * 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. - */ - -#include "config.h" -#include "AllCommands.hxx" -#include "QueueCommands.hxx" -#include "PlayerCommands.hxx" -#include "PlaylistCommands.hxx" -#include "DatabaseCommands.hxx" -#include "OutputCommands.hxx" -#include "MessageCommands.hxx" -#include "OtherCommands.hxx" -#include "Permission.hxx" -#include "tag/TagType.h" -#include "protocol/Result.hxx" -#include "Client.hxx" -#include "util/Tokenizer.hxx" -#include "util/Error.hxx" - -#ifdef ENABLE_SQLITE -#include "StickerCommands.hxx" -#include "StickerDatabase.hxx" -#endif - -#include <assert.h> -#include <string.h> - -/* - * The most we ever use is for search/find, and that limits it to the - * number of tags we can have. Add one for the command, and one extra - * to catch errors clients may send us - */ -#define COMMAND_ARGV_MAX (2+(TAG_NUM_OF_ITEM_TYPES*2)) - -/* if min: -1 don't check args * - * if max: -1 no max args */ -struct command { - const char *cmd; - unsigned permission; - int min; - int max; - CommandResult (*handler)(Client &client, int argc, char **argv); -}; - -/* don't be fooled, this is the command handler for "commands" command */ -static CommandResult -handle_commands(Client &client, int argc, char *argv[]); - -static CommandResult -handle_not_commands(Client &client, int argc, char *argv[]); - -/** - * The command registry. - * - * This array must be sorted! - */ -static const struct command commands[] = { - { "add", PERMISSION_ADD, 1, 1, handle_add }, - { "addid", PERMISSION_ADD, 1, 2, handle_addid }, - { "channels", PERMISSION_READ, 0, 0, handle_channels }, - { "clear", PERMISSION_CONTROL, 0, 0, handle_clear }, - { "clearerror", PERMISSION_CONTROL, 0, 0, handle_clearerror }, - { "close", PERMISSION_NONE, -1, -1, handle_close }, - { "commands", PERMISSION_NONE, 0, 0, handle_commands }, - { "config", PERMISSION_ADMIN, 0, 0, handle_config }, - { "consume", PERMISSION_CONTROL, 1, 1, handle_consume }, - { "count", PERMISSION_READ, 2, -1, handle_count }, - { "crossfade", PERMISSION_CONTROL, 1, 1, handle_crossfade }, - { "currentsong", PERMISSION_READ, 0, 0, handle_currentsong }, - { "decoders", PERMISSION_READ, 0, 0, handle_decoders }, - { "delete", PERMISSION_CONTROL, 1, 1, handle_delete }, - { "deleteid", PERMISSION_CONTROL, 1, 1, handle_deleteid }, - { "disableoutput", PERMISSION_ADMIN, 1, 1, handle_disableoutput }, - { "enableoutput", PERMISSION_ADMIN, 1, 1, handle_enableoutput }, - { "find", PERMISSION_READ, 2, -1, handle_find }, - { "findadd", PERMISSION_READ, 2, -1, handle_findadd}, - { "idle", PERMISSION_READ, 0, -1, handle_idle }, - { "kill", PERMISSION_ADMIN, -1, -1, handle_kill }, - { "list", PERMISSION_READ, 1, -1, handle_list }, - { "listall", PERMISSION_READ, 0, 1, handle_listall }, - { "listallinfo", PERMISSION_READ, 0, 1, handle_listallinfo }, - { "listplaylist", PERMISSION_READ, 1, 1, handle_listplaylist }, - { "listplaylistinfo", PERMISSION_READ, 1, 1, handle_listplaylistinfo }, - { "listplaylists", PERMISSION_READ, 0, 0, handle_listplaylists }, - { "load", PERMISSION_ADD, 1, 2, handle_load }, - { "lsinfo", PERMISSION_READ, 0, 1, handle_lsinfo }, - { "mixrampdb", PERMISSION_CONTROL, 1, 1, handle_mixrampdb }, - { "mixrampdelay", PERMISSION_CONTROL, 1, 1, handle_mixrampdelay }, - { "move", PERMISSION_CONTROL, 2, 2, handle_move }, - { "moveid", PERMISSION_CONTROL, 2, 2, handle_moveid }, - { "next", PERMISSION_CONTROL, 0, 0, handle_next }, - { "notcommands", PERMISSION_NONE, 0, 0, handle_not_commands }, - { "outputs", PERMISSION_READ, 0, 0, handle_devices }, - { "password", PERMISSION_NONE, 1, 1, handle_password }, - { "pause", PERMISSION_CONTROL, 0, 1, handle_pause }, - { "ping", PERMISSION_NONE, 0, 0, handle_ping }, - { "play", PERMISSION_CONTROL, 0, 1, handle_play }, - { "playid", PERMISSION_CONTROL, 0, 1, handle_playid }, - { "playlist", PERMISSION_READ, 0, 0, handle_playlist }, - { "playlistadd", PERMISSION_CONTROL, 2, 2, handle_playlistadd }, - { "playlistclear", PERMISSION_CONTROL, 1, 1, handle_playlistclear }, - { "playlistdelete", PERMISSION_CONTROL, 2, 2, handle_playlistdelete }, - { "playlistfind", PERMISSION_READ, 2, -1, handle_playlistfind }, - { "playlistid", PERMISSION_READ, 0, 1, handle_playlistid }, - { "playlistinfo", PERMISSION_READ, 0, 1, handle_playlistinfo }, - { "playlistmove", PERMISSION_CONTROL, 3, 3, handle_playlistmove }, - { "playlistsearch", PERMISSION_READ, 2, -1, handle_playlistsearch }, - { "plchanges", PERMISSION_READ, 1, 1, handle_plchanges }, - { "plchangesposid", PERMISSION_READ, 1, 1, handle_plchangesposid }, - { "previous", PERMISSION_CONTROL, 0, 0, handle_previous }, - { "prio", PERMISSION_CONTROL, 2, -1, handle_prio }, - { "prioid", PERMISSION_CONTROL, 2, -1, handle_prioid }, - { "random", PERMISSION_CONTROL, 1, 1, handle_random }, - { "readmessages", PERMISSION_READ, 0, 0, handle_read_messages }, - { "rename", PERMISSION_CONTROL, 2, 2, handle_rename }, - { "repeat", PERMISSION_CONTROL, 1, 1, handle_repeat }, - { "replay_gain_mode", PERMISSION_CONTROL, 1, 1, - handle_replay_gain_mode }, - { "replay_gain_status", PERMISSION_READ, 0, 0, - handle_replay_gain_status }, - { "rescan", PERMISSION_CONTROL, 0, 1, handle_rescan }, - { "rm", PERMISSION_CONTROL, 1, 1, handle_rm }, - { "save", PERMISSION_CONTROL, 1, 1, handle_save }, - { "search", PERMISSION_READ, 2, -1, handle_search }, - { "searchadd", PERMISSION_ADD, 2, -1, handle_searchadd }, - { "searchaddpl", PERMISSION_CONTROL, 3, -1, handle_searchaddpl }, - { "seek", PERMISSION_CONTROL, 2, 2, handle_seek }, - { "seekcur", PERMISSION_CONTROL, 1, 1, handle_seekcur }, - { "seekid", PERMISSION_CONTROL, 2, 2, handle_seekid }, - { "sendmessage", PERMISSION_CONTROL, 2, 2, handle_send_message }, - { "setvol", PERMISSION_CONTROL, 1, 1, handle_setvol }, - { "shuffle", PERMISSION_CONTROL, 0, 1, handle_shuffle }, - { "single", PERMISSION_CONTROL, 1, 1, handle_single }, - { "stats", PERMISSION_READ, 0, 0, handle_stats }, - { "status", PERMISSION_READ, 0, 0, handle_status }, -#ifdef ENABLE_SQLITE - { "sticker", PERMISSION_ADMIN, 3, -1, handle_sticker }, -#endif - { "stop", PERMISSION_CONTROL, 0, 0, handle_stop }, - { "subscribe", PERMISSION_READ, 1, 1, handle_subscribe }, - { "swap", PERMISSION_CONTROL, 2, 2, handle_swap }, - { "swapid", PERMISSION_CONTROL, 2, 2, handle_swapid }, - { "tagtypes", PERMISSION_READ, 0, 0, handle_tagtypes }, - { "toggleoutput", PERMISSION_ADMIN, 1, 1, handle_toggleoutput }, - { "unsubscribe", PERMISSION_READ, 1, 1, handle_unsubscribe }, - { "update", PERMISSION_CONTROL, 0, 1, handle_update }, - { "urlhandlers", PERMISSION_READ, 0, 0, handle_urlhandlers }, -}; - -static const unsigned num_commands = sizeof(commands) / sizeof(commands[0]); - -static bool -command_available(gcc_unused const struct command *cmd) -{ -#ifdef ENABLE_SQLITE - if (strcmp(cmd->cmd, "sticker") == 0) - return sticker_enabled(); -#endif - - return true; -} - -/* don't be fooled, this is the command handler for "commands" command */ -static CommandResult -handle_commands(Client &client, - gcc_unused int argc, gcc_unused char *argv[]) -{ - const unsigned permission = client.GetPermission(); - const struct command *cmd; - - for (unsigned i = 0; i < num_commands; ++i) { - cmd = &commands[i]; - - if (cmd->permission == (permission & cmd->permission) && - command_available(cmd)) - client_printf(client, "command: %s\n", cmd->cmd); - } - - return CommandResult::OK; -} - -static CommandResult -handle_not_commands(Client &client, - gcc_unused int argc, gcc_unused char *argv[]) -{ - const unsigned permission = client.GetPermission(); - const struct command *cmd; - - for (unsigned i = 0; i < num_commands; ++i) { - cmd = &commands[i]; - - if (cmd->permission != (permission & cmd->permission)) - client_printf(client, "command: %s\n", cmd->cmd); - } - - return CommandResult::OK; -} - -void command_init(void) -{ -#ifndef NDEBUG - /* ensure that the command list is sorted */ - for (unsigned i = 0; i < num_commands - 1; ++i) - assert(strcmp(commands[i].cmd, commands[i + 1].cmd) < 0); -#endif -} - -void command_finish(void) -{ -} - -static const struct command * -command_lookup(const char *name) -{ - unsigned a = 0, b = num_commands, i; - int cmp; - - /* binary search */ - do { - i = (a + b) / 2; - - cmp = strcmp(name, commands[i].cmd); - if (cmp == 0) - return &commands[i]; - else if (cmp < 0) - b = i; - else if (cmp > 0) - a = i + 1; - } while (a < b); - - return nullptr; -} - -static bool -command_check_request(const struct command *cmd, Client &client, - unsigned permission, int argc, char *argv[]) -{ - int min = cmd->min + 1; - int max = cmd->max + 1; - - if (cmd->permission != (permission & cmd->permission)) { - command_error(client, ACK_ERROR_PERMISSION, - "you don't have permission for \"%s\"", - cmd->cmd); - return false; - } - - if (min == 0) - return true; - - if (min == max && max != argc) { - command_error(client, ACK_ERROR_ARG, - "wrong number of arguments for \"%s\"", - argv[0]); - return false; - } else if (argc < min) { - command_error(client, ACK_ERROR_ARG, - "too few arguments for \"%s\"", argv[0]); - return false; - } else if (argc > max && max /* != 0 */ ) { - command_error(client, ACK_ERROR_ARG, - "too many arguments for \"%s\"", argv[0]); - return false; - } else - return true; -} - -static const struct command * -command_checked_lookup(Client &client, unsigned permission, - int argc, char *argv[]) -{ - const struct command *cmd; - - current_command = ""; - - if (argc == 0) - return nullptr; - - cmd = command_lookup(argv[0]); - if (cmd == nullptr) { - command_error(client, ACK_ERROR_UNKNOWN, - "unknown command \"%s\"", argv[0]); - return nullptr; - } - - current_command = cmd->cmd; - - if (!command_check_request(cmd, client, permission, argc, argv)) - return nullptr; - - return cmd; -} - -CommandResult -command_process(Client &client, unsigned num, char *line) -{ - Error error; - char *argv[COMMAND_ARGV_MAX] = { nullptr }; - const struct command *cmd; - CommandResult ret = CommandResult::ERROR; - - command_list_num = num; - - /* get the command name (first word on the line) */ - - Tokenizer tokenizer(line); - argv[0] = tokenizer.NextWord(error); - if (argv[0] == nullptr) { - current_command = ""; - if (tokenizer.IsEnd()) - command_error(client, ACK_ERROR_UNKNOWN, - "No command given"); - else - command_error(client, ACK_ERROR_UNKNOWN, - "%s", error.GetMessage()); - - current_command = nullptr; - - return CommandResult::ERROR; - } - - unsigned argc = 1; - - /* now parse the arguments (quoted or unquoted) */ - - while (argc < COMMAND_ARGV_MAX && - (argv[argc] = - tokenizer.NextParam(error)) != nullptr) - ++argc; - - /* some error checks; we have to set current_command because - command_error() expects it to be set */ - - current_command = argv[0]; - - if (argc >= COMMAND_ARGV_MAX) { - command_error(client, ACK_ERROR_ARG, "Too many arguments"); - current_command = nullptr; - return CommandResult::ERROR; - } - - if (!tokenizer.IsEnd()) { - command_error(client, ACK_ERROR_ARG, "%s", error.GetMessage()); - current_command = nullptr; - return CommandResult::ERROR; - } - - /* look up and invoke the command handler */ - - cmd = command_checked_lookup(client, client.GetPermission(), - argc, argv); - if (cmd) - ret = cmd->handler(client, argc, argv); - - current_command = nullptr; - command_list_num = 0; - - return ret; -} |