aboutsummaryrefslogtreecommitdiffstats
path: root/src/command/OtherCommands.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'src/command/OtherCommands.cxx')
-rw-r--r--src/command/OtherCommands.cxx156
1 files changed, 97 insertions, 59 deletions
diff --git a/src/command/OtherCommands.cxx b/src/command/OtherCommands.cxx
index 09b951b03..b4a23fe4b 100644
--- a/src/command/OtherCommands.cxx
+++ b/src/command/OtherCommands.cxx
@@ -25,6 +25,7 @@
#include "CommandError.hxx"
#include "db/Uri.hxx"
#include "storage/StorageInterface.hxx"
+#include "LocateUri.hxx"
#include "DetachedSong.hxx"
#include "SongPrint.hxx"
#include "TagPrint.hxx"
@@ -122,31 +123,49 @@ handle_listfiles(Client &client, Request args, Response &r)
/* default is root directory */
const auto uri = args.GetOptional(0, "");
- if (memcmp(uri, "file:///", 8) == 0)
- /* list local directory */
- return handle_listfiles_local(client, r, uri + 7);
-
+ Error error;
+ const auto located_uri = LocateUri(uri, &client,
#ifdef ENABLE_DATABASE
- if (uri_has_scheme(uri))
- /* use storage plugin to list remote directory */
- return handle_listfiles_storage(r, uri);
+ nullptr,
+#endif
+ error);
- /* must be a path relative to the configured
- music_directory */
+ switch (located_uri.type) {
+ case LocatedUri::Type::UNKNOWN:
+ return print_error(r, error);
- if (client.partition.instance.storage != nullptr)
- /* if we have a storage instance, obtain a list of
- files from it */
- return handle_listfiles_storage(r,
- *client.partition.instance.storage,
- uri);
+ case LocatedUri::Type::ABSOLUTE:
+#ifdef ENABLE_DATABASE
+ /* use storage plugin to list remote directory */
+ return handle_listfiles_storage(r, located_uri.canonical_uri);
+#else
+ r.Error(ACK_ERROR_NO_EXIST, "No database");
+ return CommandResult::ERROR;
+#endif
- /* fall back to entries from database if we have no storage */
- return handle_listfiles_db(client, r, uri);
+ case LocatedUri::Type::RELATIVE:
+#ifdef ENABLE_DATABASE
+ if (client.partition.instance.storage != nullptr)
+ /* if we have a storage instance, obtain a list of
+ files from it */
+ return handle_listfiles_storage(r,
+ *client.partition.instance.storage,
+ uri);
+
+ /* fall back to entries from database if we have no storage */
+ return handle_listfiles_db(client, r, uri);
#else
- r.Error(ACK_ERROR_NO_EXIST, "No database");
- return CommandResult::ERROR;
+ r.Error(ACK_ERROR_NO_EXIST, "No database");
+ return CommandResult::ERROR;
#endif
+
+ case LocatedUri::Type::PATH:
+ /* list local directory */
+ return handle_listfiles_local(r, located_uri.canonical_uri,
+ located_uri.path);
+ }
+
+ gcc_unreachable();
}
static constexpr tag_handler print_tag_handler = {
@@ -155,54 +174,26 @@ static constexpr tag_handler print_tag_handler = {
nullptr,
};
-CommandResult
-handle_lsinfo(Client &client, Request args, Response &r)
+static CommandResult
+handle_lsinfo_absolute(Response &r, const char *uri)
{
- /* default is root directory */
- const auto uri = args.GetOptional(0, "");
-
- if (memcmp(uri, "file:///", 8) == 0) {
- /* print information about an arbitrary local file */
- const char *path_utf8 = uri + 7;
- const auto path_fs = AllocatedPath::FromUTF8(path_utf8);
-
- if (path_fs.IsNull()) {
- r.Error(ACK_ERROR_NO_EXIST, "unsupported file name");
- return CommandResult::ERROR;
- }
-
- Error error;
- if (!client.AllowFile(path_fs, error))
- return print_error(r, error);
-
- DetachedSong song(path_utf8);
- if (!song.LoadFile(path_fs)) {
- r.Error(ACK_ERROR_NO_EXIST, "No such file");
- return CommandResult::ERROR;
- }
-
- song_print_info(r, client.partition, song);
- return CommandResult::OK;
+ if (!tag_stream_scan(uri, print_tag_handler, &r)) {
+ r.Error(ACK_ERROR_NO_EXIST, "No such file");
+ return CommandResult::ERROR;
}
- if (uri_has_scheme(uri)) {
- if (!uri_supported_scheme(uri)) {
- r.Error(ACK_ERROR_NO_EXIST, "unsupported URI scheme");
- return CommandResult::ERROR;
- }
-
- if (!tag_stream_scan(uri, print_tag_handler, &r)) {
- r.Error(ACK_ERROR_NO_EXIST, "No such file");
- return CommandResult::ERROR;
- }
-
- return CommandResult::OK;
- }
+ return CommandResult::OK;
+}
+static CommandResult
+handle_lsinfo_relative(Client &client, Response &r, const char *uri)
+{
#ifdef ENABLE_DATABASE
CommandResult result = handle_lsinfo2(client, uri, r);
if (result != CommandResult::OK)
return result;
+#else
+ (void)client;
#endif
if (isRootDirectory(uri)) {
@@ -219,6 +210,53 @@ handle_lsinfo(Client &client, Request args, Response &r)
return CommandResult::OK;
}
+static CommandResult
+handle_lsinfo_path(Client &client, Response &r,
+ const char *path_utf8, Path path_fs)
+{
+ DetachedSong song(path_utf8);
+ if (!song.LoadFile(path_fs)) {
+ r.Error(ACK_ERROR_NO_EXIST, "No such file");
+ return CommandResult::ERROR;
+ }
+
+ song_print_info(r, client.partition, song);
+ return CommandResult::OK;
+}
+
+CommandResult
+handle_lsinfo(Client &client, Request args, Response &r)
+{
+ /* default is root directory */
+ const auto uri = args.GetOptional(0, "");
+
+ Error error;
+ const auto located_uri = LocateUri(uri, &client,
+#ifdef ENABLE_DATABASE
+ nullptr,
+#endif
+ error);
+
+ switch (located_uri.type) {
+ case LocatedUri::Type::UNKNOWN:
+ return print_error(r, error);
+
+ case LocatedUri::Type::ABSOLUTE:
+ return handle_lsinfo_absolute(r, located_uri.canonical_uri);
+
+ case LocatedUri::Type::RELATIVE:
+ return handle_lsinfo_relative(client, r,
+ located_uri.canonical_uri);
+
+ case LocatedUri::Type::PATH:
+ /* print information about an arbitrary local file */
+ return handle_lsinfo_path(client, r, located_uri.canonical_uri,
+ located_uri.path);
+ }
+
+ gcc_unreachable();
+}
+
#ifdef ENABLE_DATABASE
static CommandResult