diff --git a/Makefile.am b/Makefile.am index 39c2ee4db..dea7bdb56 100644 --- a/Makefile.am +++ b/Makefile.am @@ -85,6 +85,7 @@ src_mpd_SOURCES = \ src/command/PlayerCommands.cxx src/command/PlayerCommands.hxx \ src/command/PlaylistCommands.cxx src/command/PlaylistCommands.hxx \ src/command/DatabaseCommands.cxx src/command/DatabaseCommands.hxx \ + src/command/FileCommands.cxx src/command/FileCommands.hxx \ src/command/OutputCommands.cxx src/command/OutputCommands.hxx \ src/command/MessageCommands.cxx src/command/MessageCommands.hxx \ src/command/OtherCommands.cxx src/command/OtherCommands.hxx \ diff --git a/NEWS b/NEWS index 7e7cd5ff8..1294e8581 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,7 @@ ver 0.18 (2012/??/??) - allow tilde paths for socket - default filesystem charset is UTF-8 instead of ISO-8859-1 * protocol: + - new command "readcomments" lists arbitrary file tags - new command "toggleoutput" - search for album artist falls back to the artist tag - re-add the "volume" command diff --git a/doc/protocol.xml b/doc/protocol.xml index d40d6586d..234db46db 100644 --- a/doc/protocol.xml +++ b/doc/protocol.xml @@ -1582,6 +1582,32 @@ OK + + + + readcomments + URI + + + + + Read "comments" (i.e. key-value pairs) from the file + specified by "URI". This "URI" can be a path relative + to the music directory or a URL in the form + "file:///foo/bar.ogg". + + + The response consists of lines in the form "KEY: VALUE". + Comments with suspicious characters (e.g. newlines) are + ignored silently. + + + The meaning of these depends on the codec, and not all + decoder plugins support it. For example, on Ogg files, + this lists the Vorbis comments. + + + diff --git a/src/command/AllCommands.cxx b/src/command/AllCommands.cxx index b83b42a29..0ab5953d0 100644 --- a/src/command/AllCommands.cxx +++ b/src/command/AllCommands.cxx @@ -23,6 +23,7 @@ #include "PlayerCommands.hxx" #include "PlaylistCommands.hxx" #include "DatabaseCommands.hxx" +#include "FileCommands.hxx" #include "OutputCommands.hxx" #include "MessageCommands.hxx" #include "OtherCommands.hxx" @@ -127,6 +128,7 @@ static const struct command commands[] = { { "prio", PERMISSION_CONTROL, 2, -1, handle_prio }, { "prioid", PERMISSION_CONTROL, 2, -1, handle_prioid }, { "random", PERMISSION_CONTROL, 1, 1, handle_random }, + { "readcomments", PERMISSION_READ, 1, 1, handle_read_comments }, { "readmessages", PERMISSION_READ, 0, 0, handle_read_messages }, { "rename", PERMISSION_CONTROL, 2, 2, handle_rename }, { "repeat", PERMISSION_CONTROL, 1, 1, handle_repeat }, diff --git a/src/command/FileCommands.cxx b/src/command/FileCommands.cxx new file mode 100644 index 000000000..f3cbaa2ef --- /dev/null +++ b/src/command/FileCommands.cxx @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2003-2013 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 "FileCommands.hxx" +#include "CommandError.hxx" +#include "protocol/Ack.hxx" +#include "protocol/Result.hxx" +#include "ClientFile.hxx" +#include "Client.hxx" +#include "util/CharUtil.hxx" +#include "util/Error.hxx" +#include "tag/TagHandler.hxx" +#include "TagFile.hxx" +#include "Mapper.hxx" +#include "fs/AllocatedPath.hxx" + +#include + +gcc_pure +static bool +IsValidName(const char *p) +{ + if (!IsAlphaASCII(*p)) + return false; + + while (*++p) { + const char ch = *p; + if (!IsAlphaASCII(ch) && ch != '_' && ch != '-') + return false; + } + + return true; +} + +gcc_pure +static bool +IsValidValue(const char *p) +{ + while (*p) { + const char ch = *p++; + + if ((unsigned char)ch >= 0x20) + return false; + } + + return true; +} + +static void +print_pair(const char *key, const char *value, void *ctx) +{ + Client &client = *(Client *)ctx; + + if (IsValidName(key) && IsValidValue(value)) + client_printf(client, "%s: %s\n", key, value); +} + +static constexpr tag_handler print_comment_handler = { + nullptr, + nullptr, + print_pair, +}; + +CommandResult +handle_read_comments(Client &client, gcc_unused int argc, char *argv[]) +{ + assert(argc == 2); + + const char *const uri = argv[1]; + + AllocatedPath path_fs = AllocatedPath::Null(); + + if (memcmp(uri, "file:///", 8) == 0) { + /* read comments from arbitrary local file */ + const char *path_utf8 = uri + 7; + path_fs = AllocatedPath::FromUTF8(path_utf8); + if (path_fs.IsNull()) { + command_error(client, ACK_ERROR_NO_EXIST, + "unsupported file name"); + return CommandResult::ERROR; + } + + Error error; + if (!client_allow_file(client, path_fs, error)) + return print_error(client, error); + } else if (*uri != '/') { + path_fs = map_uri_fs(uri); + if (path_fs.IsNull()) { + command_error(client, ACK_ERROR_NO_EXIST, + "No such file"); + return CommandResult::ERROR; + } + } else { + command_error(client, ACK_ERROR_NO_EXIST, "No such file"); + return CommandResult::ERROR; + } + + if (!tag_file_scan(path_fs.c_str(), &print_comment_handler, &client)) { + command_error(client, ACK_ERROR_NO_EXIST, + "Failed to load file"); + return CommandResult::ERROR; + } + + return CommandResult::OK; +} diff --git a/src/command/FileCommands.hxx b/src/command/FileCommands.hxx new file mode 100644 index 000000000..523d9369f --- /dev/null +++ b/src/command/FileCommands.hxx @@ -0,0 +1,30 @@ +/* + * 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. + */ + +#ifndef MPD_FILE_COMMANDS_HXX +#define MPD_FILE_COMMANDS_HXX + +#include "CommandResult.hxx" + +class Client; + +CommandResult +handle_read_comments(Client &client, int argc, char *argv[]); + +#endif