Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
M
mpd
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Иван Мажукин
mpd
Commits
f072cbbb
Commit
f072cbbb
authored
Oct 22, 2015
by
Max Kellermann
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
LocateUri: new library to classify URIs in a standard way
parent
1a5b66b7
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
474 additions
and
186 deletions
+474
-186
Makefile.am
Makefile.am
+2
-0
LocateUri.cxx
src/LocateUri.cxx
+120
-0
LocateUri.hxx
src/LocateUri.hxx
+109
-0
SongLoader.cxx
src/SongLoader.cxx
+32
-34
SongLoader.hxx
src/SongLoader.hxx
+6
-1
CommandError.cxx
src/command/CommandError.cxx
+4
-0
FileCommands.cxx
src/command/FileCommands.cxx
+48
-61
FileCommands.hxx
src/command/FileCommands.hxx
+3
-2
OtherCommands.cxx
src/command/OtherCommands.cxx
+97
-59
QueueCommands.cxx
src/command/QueueCommands.cxx
+53
-29
No files found.
Makefile.am
View file @
f072cbbb
...
...
@@ -168,6 +168,7 @@ libmpd_a_SOURCES = \
src/ReplayGainConfig.cxx src/ReplayGainConfig.hxx
\
src/ReplayGainInfo.cxx src/ReplayGainInfo.hxx
\
src/DetachedSong.cxx src/DetachedSong.hxx
\
src/LocateUri.cxx src/LocateUri.hxx
\
src/SongUpdate.cxx
\
src/SongLoader.cxx src/SongLoader.hxx
\
src/SongPrint.cxx src/SongPrint.hxx
\
...
...
@@ -2141,6 +2142,7 @@ test_test_translate_song_SOURCES = \
src/PlaylistError.cxx
\
src/DetachedSong.cxx
\
src/SongLoader.cxx
\
src/LocateUri.cxx
\
src/Log.cxx
\
test
/test_translate_song.cxx
test_test_translate_song_CPPFLAGS
=
$(AM_CPPFLAGS)
$(CPPUNIT_CFLAGS)
-DCPPUNIT_HAVE_RTTI
=
0
...
...
src/LocateUri.cxx
0 → 100644
View file @
f072cbbb
/*
* Copyright (C) 2003-2015 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 "LocateUri.hxx"
#include "client/Client.hxx"
#include "fs/AllocatedPath.hxx"
#include "ls.hxx"
#include "util/UriUtil.hxx"
#include "util/StringUtil.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#ifdef ENABLE_DATABASE
#include "storage/StorageInterface.hxx"
#endif
const
Domain
locate_uri_domain
(
"locate_uri"
);
static
LocatedUri
LocateFileUri
(
const
char
*
uri
,
const
Client
*
client
,
#ifdef ENABLE_DATABASE
const
Storage
*
storage
,
#endif
Error
&
error
)
{
auto
path
=
AllocatedPath
::
FromUTF8
(
uri
,
error
);
if
(
path
.
IsNull
())
return
LocatedUri
::
Unknown
();
#ifdef ENABLE_DATABASE
if
(
storage
!=
nullptr
)
{
const
char
*
suffix
=
storage
->
MapToRelativeUTF8
(
uri
);
if
(
suffix
!=
nullptr
)
/* this path was relative to the music
directory */
return
LocatedUri
(
LocatedUri
::
Type
::
RELATIVE
,
suffix
);
}
#endif
if
(
client
!=
nullptr
&&
!
client
->
AllowFile
(
path
,
error
))
return
LocatedUri
::
Unknown
();
return
LocatedUri
(
LocatedUri
::
Type
::
PATH
,
uri
,
std
::
move
(
path
));
}
static
LocatedUri
LocateAbsoluteUri
(
const
char
*
uri
,
#ifdef ENABLE_DATABASE
const
Storage
*
storage
,
#endif
Error
&
error
)
{
if
(
!
uri_supported_scheme
(
uri
))
{
error
.
Set
(
locate_uri_domain
,
"Unsupported URI scheme"
);
return
LocatedUri
::
Unknown
();
}
#ifdef ENABLE_DATABASE
if
(
storage
!=
nullptr
)
{
const
char
*
suffix
=
storage
->
MapToRelativeUTF8
(
uri
);
if
(
suffix
!=
nullptr
)
return
LocatedUri
(
LocatedUri
::
Type
::
RELATIVE
,
suffix
);
}
#endif
return
LocatedUri
(
LocatedUri
::
Type
::
ABSOLUTE
,
uri
);
}
LocatedUri
LocateUri
(
const
char
*
uri
,
const
Client
*
client
,
#ifdef ENABLE_DATABASE
const
Storage
*
storage
,
#endif
Error
&
error
)
{
/* skip the obsolete "file://" prefix */
const
char
*
path_utf8
=
StringAfterPrefix
(
uri
,
"file://"
);
if
(
path_utf8
!=
nullptr
)
{
if
(
!
PathTraitsUTF8
::
IsAbsolute
(
path_utf8
))
{
error
.
Set
(
locate_uri_domain
,
"Malformed file:// URI"
);
return
LocatedUri
::
Unknown
();
}
return
LocateFileUri
(
path_utf8
,
client
,
#ifdef ENABLE_DATABASE
storage
,
#endif
error
);
}
else
if
(
PathTraitsUTF8
::
IsAbsolute
(
uri
))
return
LocateFileUri
(
uri
,
client
,
#ifdef ENABLE_DATABASE
storage
,
#endif
error
);
else
if
(
uri_has_scheme
(
uri
))
return
LocateAbsoluteUri
(
uri
,
#ifdef ENABLE_DATABASE
storage
,
#endif
error
);
else
return
LocatedUri
(
LocatedUri
::
Type
::
RELATIVE
,
uri
);
}
src/LocateUri.hxx
0 → 100644
View file @
f072cbbb
/*
* Copyright (C) 2003-2015 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_LOCATE_URI_HXX
#define MPD_LOCATE_URI_HXX
#include "check.h"
#include "Compiler.h"
#include "fs/AllocatedPath.hxx"
#ifdef WIN32
#include <windows.h>
/* damn you, windows.h! */
#ifdef ABSOLUTE
#undef ABSOLUTE
#endif
#ifdef RELATIVE
#undef RELATIVE
#endif
#endif
class
Domain
;
class
Error
;
class
Client
;
#ifdef ENABLE_DATABASE
class
Storage
;
#endif
struct
LocatedUri
{
enum
class
Type
{
/**
* Failed to parse the URI.
*/
UNKNOWN
,
/**
* An absolute URI with a supported scheme.
*/
ABSOLUTE
,
/**
* A relative URI path.
*/
RELATIVE
,
/**
* A local file. The #path attribute is valid.
*/
PATH
,
}
type
;
const
char
*
canonical_uri
;
/**
* Contains the local file path if type==FILE.
*/
AllocatedPath
path
;
LocatedUri
(
Type
_type
,
const
char
*
_uri
,
AllocatedPath
&&
_path
=
AllocatedPath
::
Null
())
:
type
(
_type
),
canonical_uri
(
_uri
),
path
(
std
::
move
(
_path
))
{}
gcc_const
static
LocatedUri
Unknown
()
{
return
LocatedUri
(
Type
::
UNKNOWN
,
nullptr
);
}
bool
IsUnknown
()
const
{
return
type
==
Type
::
UNKNOWN
;
}
};
extern
const
Domain
locate_uri_domain
;
/**
* Classify a URI.
*
* @param client the #Client that is used to determine whether a local
* file is allowed; nullptr disables the check and allows all local
* files
* @param storage a #Storage instance which may be used to convert
* absolute URIs to relative ones, using Storage::MapToRelativeUTF8();
* that feature is disabled if this parameter is nullptr
*/
LocatedUri
LocateUri
(
const
char
*
uri
,
const
Client
*
client
,
#ifdef ENABLE_DATABASE
const
Storage
*
storage
,
#endif
Error
&
error
);
#endif
src/SongLoader.cxx
View file @
f072cbbb
...
...
@@ -19,19 +19,15 @@
#include "config.h"
#include "SongLoader.hxx"
#include "LocateUri.hxx"
#include "client/Client.hxx"
#include "db/DatabaseSong.hxx"
#include "storage/StorageInterface.hxx"
#include "ls.hxx"
#include "fs/AllocatedPath.hxx"
#include "fs/Traits.hxx"
#include "util/UriUtil.hxx"
#include "util/Error.hxx"
#include "DetachedSong.hxx"
#include "PlaylistError.hxx"
#include <assert.h>
#include <string.h>
#ifdef ENABLE_DATABASE
...
...
@@ -57,7 +53,7 @@ SongLoader::LoadFromDatabase(const char *uri, Error &error) const
}
DetachedSong
*
SongLoader
::
LoadFile
(
const
char
*
path_utf8
,
Error
&
error
)
const
SongLoader
::
LoadFile
(
const
char
*
path_utf8
,
Path
path_fs
,
Error
&
error
)
const
{
#ifdef ENABLE_DATABASE
if
(
storage
!=
nullptr
)
{
...
...
@@ -69,13 +65,6 @@ SongLoader::LoadFile(const char *path_utf8, Error &error) const
}
#endif
const
auto
path_fs
=
AllocatedPath
::
FromUTF8
(
path_utf8
,
error
);
if
(
path_fs
.
IsNull
())
return
nullptr
;
if
(
client
!=
nullptr
&&
!
client
->
AllowFile
(
path_fs
,
error
))
return
nullptr
;
DetachedSong
*
song
=
new
DetachedSong
(
path_utf8
);
if
(
!
song
->
LoadFile
(
path_fs
))
{
error
.
Set
(
playlist_domain
,
int
(
PlaylistResult
::
NO_SUCH_SONG
),
...
...
@@ -88,6 +77,27 @@ SongLoader::LoadFile(const char *path_utf8, Error &error) const
}
DetachedSong
*
SongLoader
::
LoadSong
(
const
LocatedUri
&
located_uri
,
Error
&
error
)
const
{
switch
(
located_uri
.
type
)
{
case
LocatedUri
:
:
Type
::
UNKNOWN
:
gcc_unreachable
();
case
LocatedUri
:
:
Type
::
ABSOLUTE
:
return
new
DetachedSong
(
located_uri
.
canonical_uri
);
case
LocatedUri
:
:
Type
::
RELATIVE
:
return
LoadFromDatabase
(
located_uri
.
canonical_uri
,
error
);
case
LocatedUri
:
:
Type
::
PATH
:
return
LoadFile
(
located_uri
.
canonical_uri
,
located_uri
.
path
,
error
);
}
gcc_unreachable
();
}
DetachedSong
*
SongLoader
::
LoadSong
(
const
char
*
uri_utf8
,
Error
&
error
)
const
{
#if !CLANG_CHECK_VERSION(3,6)
...
...
@@ -95,25 +105,13 @@ SongLoader::LoadSong(const char *uri_utf8, Error &error) const
assert
(
uri_utf8
!=
nullptr
);
#endif
if
(
memcmp
(
uri_utf8
,
"file:///"
,
8
)
==
0
)
/* absolute path */
return
LoadFile
(
uri_utf8
+
7
,
error
);
else
if
(
PathTraitsUTF8
::
IsAbsolute
(
uri_utf8
))
/* absolute path */
return
LoadFile
(
uri_utf8
,
error
);
else
if
(
uri_has_scheme
(
uri_utf8
))
{
/* remove URI */
if
(
!
uri_supported_scheme
(
uri_utf8
))
{
error
.
Set
(
playlist_domain
,
int
(
PlaylistResult
::
NO_SUCH_SONG
),
"Unsupported URI scheme"
);
return
nullptr
;
}
return
new
DetachedSong
(
uri_utf8
);
}
else
{
/* URI relative to the music directory */
return
LoadFromDatabase
(
uri_utf8
,
error
);
}
const
auto
located_uri
=
LocateUri
(
uri_utf8
,
client
,
#ifdef ENABLE_DATABASE
storage
,
#endif
error
);
if
(
located_uri
.
IsUnknown
())
return
nullptr
;
return
LoadSong
(
located_uri
,
error
);
}
src/SongLoader.hxx
View file @
f072cbbb
...
...
@@ -29,7 +29,9 @@ class Client;
class
Database
;
class
Storage
;
class
DetachedSong
;
class
Path
;
class
Error
;
struct
LocatedUri
;
/**
* A utility class that loads a #DetachedSong object by its URI. If
...
...
@@ -66,6 +68,8 @@ public:
}
#endif
DetachedSong
*
LoadSong
(
const
LocatedUri
&
uri
,
Error
&
error
)
const
;
gcc_nonnull_all
DetachedSong
*
LoadSong
(
const
char
*
uri_utf8
,
Error
&
error
)
const
;
...
...
@@ -74,7 +78,8 @@ private:
DetachedSong
*
LoadFromDatabase
(
const
char
*
uri
,
Error
&
error
)
const
;
gcc_nonnull_all
DetachedSong
*
LoadFile
(
const
char
*
path_utf8
,
Error
&
error
)
const
;
DetachedSong
*
LoadFile
(
const
char
*
path_utf8
,
Path
path_fs
,
Error
&
error
)
const
;
};
#endif
src/command/CommandError.cxx
View file @
f072cbbb
...
...
@@ -20,6 +20,7 @@
#include "config.h"
#include "CommandError.hxx"
#include "db/DatabaseError.hxx"
#include "LocateUri.hxx"
#include "client/Response.hxx"
#include "util/Error.hxx"
#include "Log.hxx"
...
...
@@ -114,6 +115,9 @@ print_error(Response &r, const Error &error)
return
CommandResult
::
ERROR
;
}
#endif
}
else
if
(
error
.
IsDomain
(
locate_uri_domain
))
{
r
.
Error
(
ACK_ERROR_ARG
,
error
.
GetMessage
());
return
CommandResult
::
ERROR
;
}
else
if
(
error
.
IsDomain
(
errno_domain
))
{
r
.
Error
(
ACK_ERROR_SYSTEM
,
strerror
(
error
.
GetCode
()));
return
CommandResult
::
ERROR
;
...
...
src/command/FileCommands.cxx
View file @
f072cbbb
...
...
@@ -39,8 +39,8 @@
#include "fs/AllocatedPath.hxx"
#include "fs/FileInfo.hxx"
#include "fs/DirectoryReader.hxx"
#include "LocateUri.hxx"
#include "TimePrint.hxx"
#include "ls.hxx"
#include <assert.h>
#include <sys/stat.h>
...
...
@@ -70,21 +70,12 @@ skip_path(Path name_fs)
#endif
CommandResult
handle_listfiles_local
(
Client
&
client
,
Response
&
r
,
const
char
*
path_utf8
)
handle_listfiles_local
(
Response
&
r
,
const
char
*
path_utf8
,
Path
path_fs
)
{
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
);
DirectoryReader
reader
(
path_fs
);
if
(
reader
.
HasFailed
())
{
Error
error
;
error
.
FormatErrno
(
"Failed to open '%s'"
,
path_utf8
);
return
print_error
(
r
,
error
);
}
...
...
@@ -172,11 +163,6 @@ static constexpr tag_handler print_comment_handler = {
static
CommandResult
read_stream_comments
(
Response
&
r
,
const
char
*
uri
)
{
if
(
!
uri_supported_scheme
(
uri
))
{
r
.
Error
(
ACK_ERROR_NO_EXIST
,
"unsupported URI scheme"
);
return
CommandResult
::
ERROR
;
}
if
(
!
tag_stream_scan
(
uri
,
print_comment_handler
,
&
r
))
{
r
.
Error
(
ACK_ERROR_NO_EXIST
,
"Failed to load file"
);
return
CommandResult
::
ERROR
;
...
...
@@ -201,63 +187,64 @@ read_file_comments(Response &r, const Path path_fs)
}
static
const
char
*
translate_uri
(
const
char
*
uri
)
static
CommandResult
read_db_comments
(
Client
&
client
,
Response
&
r
,
const
char
*
uri
)
{
if
(
memcmp
(
uri
,
"file:///"
,
8
)
==
0
)
/* drop the "file://", leave only an absolute path
(starting with a slash) */
return
uri
+
7
;
#ifdef ENABLE_DATABASE
const
Storage
*
storage
=
client
.
GetStorage
();
if
(
storage
==
nullptr
)
{
#else
(
void
)
client
;
(
void
)
uri
;
#endif
r
.
Error
(
ACK_ERROR_NO_EXIST
,
"No database"
);
return
CommandResult
::
ERROR
;
#ifdef ENABLE_DATABASE
}
{
AllocatedPath
path_fs
=
storage
->
MapFS
(
uri
);
if
(
!
path_fs
.
IsNull
())
return
read_file_comments
(
r
,
path_fs
);
}
return
uri
;
{
const
std
::
string
uri2
=
storage
->
MapUTF8
(
uri
);
if
(
uri_has_scheme
(
uri2
.
c_str
()))
return
read_stream_comments
(
r
,
uri2
.
c_str
());
}
r
.
Error
(
ACK_ERROR_NO_EXIST
,
"No such file"
);
return
CommandResult
::
ERROR
;
#endif
}
CommandResult
handle_read_comments
(
Client
&
client
,
Request
args
,
Response
&
r
)
{
assert
(
args
.
size
==
1
);
const
char
*
const
uri
=
translate_uri
(
args
.
front
());
if
(
PathTraitsUTF8
::
IsAbsolute
(
uri
))
{
/* read comments from arbitrary local file */
const
char
*
path_utf8
=
uri
;
AllocatedPath
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
);
const
char
*
const
uri
=
args
.
front
();
return
read_file_comments
(
r
,
path_fs
);
}
else
if
(
uri_has_scheme
(
uri
))
{
return
read_stream_comments
(
r
,
uri
);
}
else
{
Error
error
;
const
auto
located_uri
=
LocateUri
(
uri
,
&
client
,
#ifdef ENABLE_DATABASE
const
Storage
*
storage
=
client
.
GetStorage
();
if
(
storage
==
nullptr
)
{
nullptr
,
#endif
r
.
Error
(
ACK_ERROR_NO_EXIST
,
"No database"
);
return
CommandResult
::
ERROR
;
#ifdef ENABLE_DATABASE
}
error
);
switch
(
located_uri
.
type
)
{
case
LocatedUri
:
:
Type
::
UNKNOWN
:
return
print_error
(
r
,
error
);
{
AllocatedPath
path_fs
=
storage
->
MapFS
(
uri
);
if
(
!
path_fs
.
IsNull
())
return
read_file_comments
(
r
,
path_fs
);
}
case
LocatedUri
:
:
Type
::
ABSOLUTE
:
return
read_stream_comments
(
r
,
located_uri
.
canonical_uri
);
{
const
std
::
string
uri2
=
storage
->
MapUTF8
(
uri
);
if
(
uri_has_scheme
(
uri2
.
c_str
()))
return
read_stream_comments
(
r
,
uri2
.
c_str
());
}
case
LocatedUri
:
:
Type
::
RELATIVE
:
return
read_db_comments
(
client
,
r
,
located_uri
.
canonical_uri
);
r
.
Error
(
ACK_ERROR_NO_EXIST
,
"No such file"
);
return
CommandResult
::
ERROR
;
#endif
case
LocatedUri
:
:
Type
::
PATH
:
return
read_file_comments
(
r
,
located_uri
.
path
);
}
gcc_unreachable
();
}
src/command/FileCommands.hxx
View file @
f072cbbb
...
...
@@ -25,10 +25,11 @@
class
Client
;
class
Request
;
class
Response
;
class
Path
;
CommandResult
handle_listfiles_local
(
Client
&
client
,
Response
&
response
,
const
char
*
path_utf8
);
handle_listfiles_local
(
Response
&
response
,
const
char
*
path_utf8
,
Path
path_fs
);
CommandResult
handle_read_comments
(
Client
&
client
,
Request
request
,
Response
&
response
);
...
...
src/command/OtherCommands.cxx
View file @
f072cbbb
...
...
@@ -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
...
...
src/command/QueueCommands.cxx
View file @
f072cbbb
...
...
@@ -25,13 +25,14 @@
#include "db/Selection.hxx"
#include "SongFilter.hxx"
#include "SongLoader.hxx"
#include "DetachedSong.hxx"
#include "LocateUri.hxx"
#include "queue/Playlist.hxx"
#include "PlaylistPrint.hxx"
#include "client/Client.hxx"
#include "client/Response.hxx"
#include "Partition.hxx"
#include "BulkEdit.hxx"
#include "ls.hxx"
#include "util/ConstBuffer.hxx"
#include "util/UriUtil.hxx"
#include "util/NumberParser.hxx"
...
...
@@ -42,15 +43,42 @@
#include <string.h>
static
const
char
*
translate_uri
(
const
char
*
uri
)
static
CommandResult
AddUri
(
Client
&
client
,
const
LocatedUri
&
uri
,
Response
&
r
)
{
if
(
memcmp
(
uri
,
"file:///"
,
8
)
==
0
)
/* drop the "file://", leave only an absolute path
(starting with a slash) */
return
uri
+
7
;
Error
error
;
DetachedSong
*
song
=
SongLoader
(
client
).
LoadSong
(
uri
,
error
);
if
(
song
==
nullptr
)
return
print_error
(
r
,
error
);
auto
&
partition
=
client
.
partition
;
unsigned
id
=
partition
.
playlist
.
AppendSong
(
partition
.
pc
,
std
::
move
(
*
song
),
error
);
delete
song
;
if
(
id
==
0
)
return
print_error
(
r
,
error
);
return
uri
;
return
CommandResult
::
OK
;
}
static
CommandResult
AddDatabaseSelection
(
Client
&
client
,
const
char
*
uri
,
Response
&
r
)
{
#ifdef ENABLE_DATABASE
const
ScopeBulkEdit
bulk_edit
(
client
.
partition
);
const
DatabaseSelection
selection
(
uri
,
true
);
Error
error
;
return
AddFromDatabase
(
client
.
partition
,
selection
,
error
)
?
CommandResult
::
OK
:
print_error
(
r
,
error
);
#else
(
void
)
client
;
(
void
)
uri
;
r
.
Error
(
ACK_ERROR_NO_EXIST
,
"No database"
);
return
CommandResult
::
ERROR
;
#endif
}
CommandResult
...
...
@@ -65,36 +93,32 @@ handle_add(Client &client, Request args, Response &r)
here */
uri
=
""
;
uri
=
translate_uri
(
uri
);
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
);
if
(
uri_has_scheme
(
uri
)
||
PathTraitsUTF8
::
IsAbsolute
(
uri
))
{
const
SongLoader
loader
(
client
);
Error
error
;
unsigned
id
=
client
.
partition
.
AppendURI
(
loader
,
uri
,
error
);
if
(
id
==
0
)
return
print_error
(
r
,
error
);
case
LocatedUri
:
:
Type
::
ABSOLUTE
:
case
LocatedUri
:
:
Type
::
PATH
:
return
AddUri
(
client
,
located_uri
,
r
);
return
CommandResult
::
OK
;
case
LocatedUri
:
:
Type
::
RELATIVE
:
return
AddDatabaseSelection
(
client
,
located_uri
.
canonical_uri
,
r
);
}
#ifdef ENABLE_DATABASE
const
ScopeBulkEdit
bulk_edit
(
client
.
partition
);
const
DatabaseSelection
selection
(
uri
,
true
);
Error
error
;
return
AddFromDatabase
(
client
.
partition
,
selection
,
error
)
?
CommandResult
::
OK
:
print_error
(
r
,
error
);
#else
r
.
Error
(
ACK_ERROR_NO_EXIST
,
"No database"
);
return
CommandResult
::
ERROR
;
#endif
gcc_unreachable
();
}
CommandResult
handle_addid
(
Client
&
client
,
Request
args
,
Response
&
r
)
{
const
char
*
const
uri
=
translate_uri
(
args
.
front
()
);
const
char
*
const
uri
=
args
.
front
(
);
const
SongLoader
loader
(
client
);
Error
error
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment