diff options
-rw-r--r-- | src/command.c | 18 | ||||
-rw-r--r-- | src/mapper.c | 7 | ||||
-rw-r--r-- | src/playlist.c | 26 | ||||
-rw-r--r-- | src/playlist.h | 8 | ||||
-rw-r--r-- | src/song.c | 4 | ||||
-rw-r--r-- | src/song.h | 2 |
6 files changed, 59 insertions, 6 deletions
diff --git a/src/command.c b/src/command.c index 3174faf70..b141bda45 100644 --- a/src/command.c +++ b/src/command.c @@ -229,6 +229,10 @@ static int print_playlist_result(struct client *client, command_error(client, ACK_ERROR_SYSTEM, strerror(errno)); return -1; + case PLAYLIST_RESULT_DENIED: + command_error(client, ACK_ERROR_NO_EXIST, "Access denied"); + return -1; + case PLAYLIST_RESULT_NO_SUCH_SONG: command_error(client, ACK_ERROR_NO_EXIST, "No such song"); return -1; @@ -444,6 +448,12 @@ static int handleAdd(struct client *client, char *path = argv[1]; 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)) return addToPlaylist(path, NULL); @@ -461,7 +471,13 @@ static int handleAddId(struct client *client, int argc, char *argv[]) { 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) return print_playlist_result(client, result); diff --git a/src/mapper.c b/src/mapper.c index b1ac6f86c..1b704e55e 100644 --- a/src/mapper.c +++ b/src/mapper.c @@ -96,9 +96,12 @@ map_directory_child_fs(const struct directory *directory, const char *name, const char * 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 * diff --git a/src/playlist.c b/src/playlist.c index dfbc31514..0dae1a92b 100644 --- a/src/playlist.c +++ b/src/playlist.c @@ -521,6 +521,32 @@ static void clearPlayerQueue(void) 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 * song_by_url(const char *url) { diff --git a/src/playlist.h b/src/playlist.h index e50f57bc4..e104a48e2 100644 --- a/src/playlist.h +++ b/src/playlist.h @@ -32,6 +32,7 @@ struct client; enum playlist_result { PLAYLIST_RESULT_SUCCESS, PLAYLIST_RESULT_ERRNO, + PLAYLIST_RESULT_DENIED, PLAYLIST_RESULT_NO_SUCH_SONG, PLAYLIST_RESULT_NO_SUCH_LIST, PLAYLIST_RESULT_LIST_EXISTS, @@ -72,6 +73,13 @@ void clearPlaylist(void); 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); int addToStoredPlaylist(const char *file, const char *utf8file); diff --git a/src/song.c b/src/song.c index b4ab28cab..9bc44f4a0 100644 --- a/src/song.c +++ b/src/song.c @@ -54,7 +54,7 @@ song_remote_new(const char *url) struct song * song_file_new(const char *path, struct directory *parent) { - assert(parent != NULL); + assert((parent == NULL) == (*path == '/')); return song_alloc(path, parent); } @@ -65,7 +65,7 @@ song_file_load(const char *path, struct directory *parent) struct song *song; bool ret; - assert(parent != NULL); + assert((parent == NULL) == (*path == '/')); if (strchr(path, '\n')) { DEBUG("newSong: '%s' is not a valid uri\n", path); diff --git a/src/song.h b/src/song.h index 6016b8d93..e5413fb17 100644 --- a/src/song.h +++ b/src/song.h @@ -76,7 +76,7 @@ song_in_database(const struct song *song) static inline bool song_is_file(const struct song *song) { - return song_in_database(song); + return song_in_database(song) || song->url[0] == '/'; } #endif |