playlist: added support for adding songs not in the music database
Clients which have authenticated via unix socket may add local files to the MPD playlist, provided that they own the file.
This commit is contained in:
parent
0b44cad2ce
commit
8c0060fae4
@ -229,6 +229,10 @@ static int print_playlist_result(struct client *client,
|
|||||||
command_error(client, ACK_ERROR_SYSTEM, strerror(errno));
|
command_error(client, ACK_ERROR_SYSTEM, strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
case PLAYLIST_RESULT_DENIED:
|
||||||
|
command_error(client, ACK_ERROR_NO_EXIST, "Access denied");
|
||||||
|
return -1;
|
||||||
|
|
||||||
case PLAYLIST_RESULT_NO_SUCH_SONG:
|
case PLAYLIST_RESULT_NO_SUCH_SONG:
|
||||||
command_error(client, ACK_ERROR_NO_EXIST, "No such song");
|
command_error(client, ACK_ERROR_NO_EXIST, "No such song");
|
||||||
return -1;
|
return -1;
|
||||||
@ -444,6 +448,12 @@ static int handleAdd(struct client *client,
|
|||||||
char *path = argv[1];
|
char *path = argv[1];
|
||||||
enum playlist_result result;
|
enum playlist_result result;
|
||||||
|
|
||||||
|
if (path[0] == '/') {
|
||||||
|
result = playlist_append_file(path, client_get_uid(client),
|
||||||
|
NULL);
|
||||||
|
return print_playlist_result(client, result);
|
||||||
|
}
|
||||||
|
|
||||||
if (isRemoteUrl(path))
|
if (isRemoteUrl(path))
|
||||||
return addToPlaylist(path, NULL);
|
return addToPlaylist(path, NULL);
|
||||||
|
|
||||||
@ -461,7 +471,13 @@ static int handleAddId(struct client *client,
|
|||||||
int argc, char *argv[])
|
int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int added_id;
|
int added_id;
|
||||||
enum playlist_result result = addToPlaylist(argv[1], &added_id);
|
enum playlist_result result;
|
||||||
|
|
||||||
|
if (argv[1][0] == '/')
|
||||||
|
result = playlist_append_file(argv[1], client_get_uid(client),
|
||||||
|
&added_id);
|
||||||
|
else
|
||||||
|
result = addToPlaylist(argv[1], &added_id);
|
||||||
|
|
||||||
if (result != PLAYLIST_RESULT_SUCCESS)
|
if (result != PLAYLIST_RESULT_SUCCESS)
|
||||||
return print_playlist_result(client, result);
|
return print_playlist_result(client, result);
|
||||||
|
@ -96,9 +96,12 @@ map_directory_child_fs(const struct directory *directory, const char *name,
|
|||||||
const char *
|
const char *
|
||||||
map_song_fs(const struct song *song, char *buffer)
|
map_song_fs(const struct song *song, char *buffer)
|
||||||
{
|
{
|
||||||
assert(song->parent != NULL);
|
assert(song_is_file(song));
|
||||||
|
|
||||||
return map_directory_child_fs(song->parent, song->url, buffer);
|
if (song_in_database(song))
|
||||||
|
return map_directory_child_fs(song->parent, song->url, buffer);
|
||||||
|
else
|
||||||
|
return utf8_to_fs_charset(buffer, song->url);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
|
@ -521,6 +521,32 @@ static void clearPlayerQueue(void)
|
|||||||
pc_cancel();
|
pc_cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum playlist_result
|
||||||
|
playlist_append_file(const char *path, int uid, int *added_id)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct stat st;
|
||||||
|
struct song *song;
|
||||||
|
|
||||||
|
if (uid <= 0)
|
||||||
|
/* unauthenticated client */
|
||||||
|
return PLAYLIST_RESULT_DENIED;
|
||||||
|
|
||||||
|
ret = stat(path, &st);
|
||||||
|
if (ret < 0)
|
||||||
|
return PLAYLIST_RESULT_ERRNO;
|
||||||
|
|
||||||
|
if (st.st_uid != (uid_t)uid)
|
||||||
|
/* client is not owner */
|
||||||
|
return PLAYLIST_RESULT_DENIED;
|
||||||
|
|
||||||
|
song = song_file_load(path, NULL);
|
||||||
|
if (song == NULL)
|
||||||
|
return PLAYLIST_RESULT_NO_SUCH_SONG;
|
||||||
|
|
||||||
|
return addSongToPlaylist(song, added_id);
|
||||||
|
}
|
||||||
|
|
||||||
static struct song *
|
static struct song *
|
||||||
song_by_url(const char *url)
|
song_by_url(const char *url)
|
||||||
{
|
{
|
||||||
|
@ -32,6 +32,7 @@ struct client;
|
|||||||
enum playlist_result {
|
enum playlist_result {
|
||||||
PLAYLIST_RESULT_SUCCESS,
|
PLAYLIST_RESULT_SUCCESS,
|
||||||
PLAYLIST_RESULT_ERRNO,
|
PLAYLIST_RESULT_ERRNO,
|
||||||
|
PLAYLIST_RESULT_DENIED,
|
||||||
PLAYLIST_RESULT_NO_SUCH_SONG,
|
PLAYLIST_RESULT_NO_SUCH_SONG,
|
||||||
PLAYLIST_RESULT_NO_SUCH_LIST,
|
PLAYLIST_RESULT_NO_SUCH_LIST,
|
||||||
PLAYLIST_RESULT_LIST_EXISTS,
|
PLAYLIST_RESULT_LIST_EXISTS,
|
||||||
@ -72,6 +73,13 @@ void clearPlaylist(void);
|
|||||||
|
|
||||||
int clearStoredPlaylist(const char *utf8file);
|
int clearStoredPlaylist(const char *utf8file);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends a local file (outside the music database) to the playlist,
|
||||||
|
* but only if the file's owner is equal to the specified uid.
|
||||||
|
*/
|
||||||
|
enum playlist_result
|
||||||
|
playlist_append_file(const char *path, int uid, int *added_id);
|
||||||
|
|
||||||
enum playlist_result addToPlaylist(const char *file, int *added_id);
|
enum playlist_result addToPlaylist(const char *file, int *added_id);
|
||||||
|
|
||||||
int addToStoredPlaylist(const char *file, const char *utf8file);
|
int addToStoredPlaylist(const char *file, const char *utf8file);
|
||||||
|
@ -54,7 +54,7 @@ song_remote_new(const char *url)
|
|||||||
struct song *
|
struct song *
|
||||||
song_file_new(const char *path, struct directory *parent)
|
song_file_new(const char *path, struct directory *parent)
|
||||||
{
|
{
|
||||||
assert(parent != NULL);
|
assert((parent == NULL) == (*path == '/'));
|
||||||
|
|
||||||
return song_alloc(path, parent);
|
return song_alloc(path, parent);
|
||||||
}
|
}
|
||||||
@ -65,7 +65,7 @@ song_file_load(const char *path, struct directory *parent)
|
|||||||
struct song *song;
|
struct song *song;
|
||||||
bool ret;
|
bool ret;
|
||||||
|
|
||||||
assert(parent != NULL);
|
assert((parent == NULL) == (*path == '/'));
|
||||||
|
|
||||||
if (strchr(path, '\n')) {
|
if (strchr(path, '\n')) {
|
||||||
DEBUG("newSong: '%s' is not a valid uri\n", path);
|
DEBUG("newSong: '%s' is not a valid uri\n", path);
|
||||||
|
@ -76,7 +76,7 @@ song_in_database(const struct song *song)
|
|||||||
static inline bool
|
static inline bool
|
||||||
song_is_file(const struct song *song)
|
song_is_file(const struct song *song)
|
||||||
{
|
{
|
||||||
return song_in_database(song);
|
return song_in_database(song) || song->url[0] == '/';
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user