aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2008-10-15 22:35:13 +0200
committerMax Kellermann <max@duempel.org>2008-10-15 22:35:13 +0200
commit8c0060fae44a94bdfe978d8d4a66589f5a03a074 (patch)
treefde581584c25e5e74d8a8336f54dc61d4a5f67db /src
parent0b44cad2ce2c6433f395650a5a70cf8b3473673c (diff)
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.
Diffstat (limited to 'src')
-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 3174faf7..b141bda4 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 b1ac6f86..1b704e55 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 dfbc3151..0dae1a92 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 e50f57bc..e104a48e 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 b4ab28ca..9bc44f4a 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 6016b8d9..e5413fb1 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