From 5274fee8a71cc5901649b984bc4488c9677feadf Mon Sep 17 00:00:00 2001
From: Max Kellermann <max@duempel.org>
Date: Wed, 22 Dec 2010 19:46:41 +0100
Subject: playlist_song: add flag "secure"

Optionally allow all local files.

"Insecure" mode is used for printing playlists.
---
 src/command.c        |  2 +-
 src/playlist_print.c |  2 +-
 src/playlist_queue.c |  8 ++++----
 src/playlist_queue.h |  6 ++++--
 src/playlist_song.c  | 12 +++++++-----
 src/playlist_song.h  |  8 +++++++-
 6 files changed, 24 insertions(+), 14 deletions(-)

diff --git a/src/command.c b/src/command.c
index 781547b44..ccdaf264a 100644
--- a/src/command.c
+++ b/src/command.c
@@ -747,7 +747,7 @@ handle_load(struct client *client, G_GNUC_UNUSED int argc, char *argv[])
 {
 	enum playlist_result result;
 
-	result = playlist_open_into_queue(argv[1], &g_playlist);
+	result = playlist_open_into_queue(argv[1], &g_playlist, true);
 	if (result != PLAYLIST_RESULT_NO_SUCH_LIST)
 		return result;
 
diff --git a/src/playlist_print.c b/src/playlist_print.c
index 89ab2e5ab..b79dd6fa5 100644
--- a/src/playlist_print.c
+++ b/src/playlist_print.c
@@ -153,7 +153,7 @@ playlist_provider_print(struct client *client, const char *uri,
 	char *base_uri = uri != NULL ? g_path_get_dirname(uri) : NULL;
 
 	while ((song = playlist_plugin_read(playlist)) != NULL) {
-		song = playlist_check_translate_song(song, base_uri);
+		song = playlist_check_translate_song(song, base_uri, false);
 		if (song == NULL)
 			continue;
 
diff --git a/src/playlist_queue.c b/src/playlist_queue.c
index 635e23a28..43621da9f 100644
--- a/src/playlist_queue.c
+++ b/src/playlist_queue.c
@@ -27,14 +27,14 @@
 
 enum playlist_result
 playlist_load_into_queue(const char *uri, struct playlist_provider *source,
-			 struct playlist *dest)
+			 struct playlist *dest, bool secure)
 {
 	enum playlist_result result;
 	struct song *song;
 	char *base_uri = uri != NULL ? g_path_get_dirname(uri) : NULL;
 
 	while ((song = playlist_plugin_read(source)) != NULL) {
-		song = playlist_check_translate_song(song, base_uri);
+		song = playlist_check_translate_song(song, base_uri, secure);
 		if (song == NULL)
 			continue;
 
@@ -53,7 +53,7 @@ playlist_load_into_queue(const char *uri, struct playlist_provider *source,
 }
 
 enum playlist_result
-playlist_open_into_queue(const char *uri, struct playlist *dest)
+playlist_open_into_queue(const char *uri, struct playlist *dest, bool secure)
 {
 	struct input_stream *is;
 	struct playlist_provider *playlist = playlist_open_any(uri, &is);
@@ -61,7 +61,7 @@ playlist_open_into_queue(const char *uri, struct playlist *dest)
 		return PLAYLIST_RESULT_NO_SUCH_LIST;
 
 	enum playlist_result result =
-		playlist_load_into_queue(uri, playlist, dest);
+		playlist_load_into_queue(uri, playlist, dest, secure);
 	playlist_plugin_close(playlist);
 
 	if (is != NULL)
diff --git a/src/playlist_queue.h b/src/playlist_queue.h
index 530d4b4be..9ffa51198 100644
--- a/src/playlist_queue.h
+++ b/src/playlist_queue.h
@@ -26,6 +26,8 @@
 
 #include "playlist.h"
 
+#include <stdbool.h>
+
 struct playlist_provider;
 struct playlist;
 
@@ -38,14 +40,14 @@ struct playlist;
  */
 enum playlist_result
 playlist_load_into_queue(const char *uri, struct playlist_provider *source,
-			 struct playlist *dest);
+			 struct playlist *dest, bool secure);
 
 /**
  * Opens a playlist with a playlist plugin and append to the specified
  * play queue.
  */
 enum playlist_result
-playlist_open_into_queue(const char *uri, struct playlist *dest);
+playlist_open_into_queue(const char *uri, struct playlist *dest, bool secure);
 
 #endif
 
diff --git a/src/playlist_song.c b/src/playlist_song.c
index 1e8e98795..572672bca 100644
--- a/src/playlist_song.c
+++ b/src/playlist_song.c
@@ -84,7 +84,8 @@ apply_song_metadata(struct song *dest, const struct song *src)
 }
 
 struct song *
-playlist_check_translate_song(struct song *song, const char *base_uri)
+playlist_check_translate_song(struct song *song, const char *base_uri,
+			      bool secure)
 {
 	struct song *dest;
 
@@ -111,16 +112,17 @@ playlist_check_translate_song(struct song *song, const char *base_uri)
 			? map_uri_fs(base_uri)
 			: map_directory_fs(db_get_root());
 
-		if (prefix == NULL || !g_str_has_prefix(uri, prefix) ||
-		    uri[strlen(prefix)] != '/') {
+		if (prefix != NULL && g_str_has_prefix(uri, prefix) &&
+		    uri[strlen(prefix)] == '/')
+			uri += strlen(prefix) + 1;
+		else if (!secure) {
 			/* local files must be relative to the music
-			   directory */
+			   directory when "secure" is enabled */
 			g_free(prefix);
 			song_free(song);
 			return NULL;
 		}
 
-		uri += strlen(prefix) + 1;
 		g_free(prefix);
 	}
 
diff --git a/src/playlist_song.h b/src/playlist_song.h
index 5a2e4c2b0..29335e5ac 100644
--- a/src/playlist_song.h
+++ b/src/playlist_song.h
@@ -20,12 +20,18 @@
 #ifndef MPD_PLAYLIST_SONG_H
 #define MPD_PLAYLIST_SONG_H
 
+#include <stdbool.h>
+
 /**
  * Verifies the song, returns NULL if it is unsafe.  Translate the
  * song to a new song object within the database, if it is a local
  * file.  The old song object is freed.
+ *
+ * @param secure if true, then local files are only allowed if they
+ * are relative to base_uri
  */
 struct song *
-playlist_check_translate_song(struct song *song, const char *base_uri);
+playlist_check_translate_song(struct song *song, const char *base_uri,
+			      bool secure);
 
 #endif
-- 
cgit v1.2.3