aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/command.c18
-rw-r--r--src/mapper.c7
-rw-r--r--src/playlist.c26
-rw-r--r--src/playlist.h8
-rw-r--r--src/song.c4
-rw-r--r--src/song.h2
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