Ejemplo n.º 1
0
struct song *
playlist_check_translate_song(struct song *song, const char *base_uri,
			      bool secure)
{
	if (song_in_database(song))
		/* already ok */
		return song;

	const char *uri = song->uri;

	if (uri_has_scheme(uri)) {
		if (uri_supported_scheme(uri))
			/* valid remote song */
			return song;
		else {
			/* unsupported remote song */
			song_free(song);
			return NULL;
		}
	}

	if (base_uri != NULL && strcmp(base_uri, ".") == 0)
		/* g_path_get_dirname() returns "." when there is no
		   directory name in the given path; clear that now,
		   because it would break the database lookup
		   functions */
		base_uri = NULL;

	if (g_path_is_absolute(uri)) {
		/* XXX fs_charset vs utf8? */
		const char *suffix = map_to_relative_path(uri);
		assert(suffix != NULL);

		if (suffix != uri)
			uri = suffix;
		else if (!secure) {
			/* local files must be relative to the music
			   directory when "secure" is enabled */
			song_free(song);
			return NULL;
		}

		base_uri = NULL;
	}

	char *allocated = NULL;
	if (base_uri != NULL)
		uri = allocated = g_build_filename(base_uri, uri, NULL);

	struct song *dest = playlist_check_load_song(song, uri, secure);
	song_free(song);
	g_free(allocated);
	return dest;
}
void
song_print_uri(struct client *client, struct song *song)
{
	if (song_in_database(song) && !directory_is_root(song->parent)) {
		client_printf(client, "%s%s/%s\n", SONG_FILE,
			      directory_get_path(song->parent), song->uri);
	} else {
		char *allocated;
		const char *uri;

		uri = allocated = uri_remove_auth(song->uri);
		if (uri == NULL)
			uri = song->uri;

		client_printf(client, "%s%s\n", SONG_FILE,
			      map_to_relative_path(uri));

		g_free(allocated);
	}
}
Ejemplo n.º 3
0
static bool
skip_symlink(const struct directory *directory, const char *utf8_name)
{
#ifndef WIN32
	char buffer[MPD_PATH_MAX];
	char *path_fs;
	const char *p;
	ssize_t ret;

	path_fs = map_directory_child_fs(directory, utf8_name);
	if (path_fs == NULL)
		return true;

	ret = readlink(path_fs, buffer, sizeof(buffer));
	g_free(path_fs);
	if (ret < 0)
		/* don't skip if this is not a symlink */
		return errno != EINVAL;

	if (!follow_inside_symlinks && !follow_outside_symlinks) {
		/* ignore all symlinks */
		return true;
	} else if (follow_inside_symlinks && follow_outside_symlinks) {
		/* consider all symlinks */
		return false;
	}

	if (g_path_is_absolute(buffer)) {
		/* if the symlink points to an absolute path, see if
		   that path is inside the music directory */
		const char *relative = map_to_relative_path(buffer);
		return relative > buffer
			? !follow_inside_symlinks
			: !follow_outside_symlinks;
	}

	p = buffer;
	while (*p == '.') {
		if (p[1] == '.' && G_IS_DIR_SEPARATOR(p[2])) {
			/* "../" moves to parent directory */
			directory = directory->parent;
			if (directory == NULL) {
				/* we have moved outside the music
				   directory - skip this symlink
				   if such symlinks are not allowed */
				return !follow_outside_symlinks;
			}
			p += 3;
		} else if (G_IS_DIR_SEPARATOR(p[1]))
			/* eliminate "./" */
			p += 2;
		else
			break;
	}

	/* we are still in the music directory, so this symlink points
	   to a song which is already in the database - skip according
	   to the follow_inside_symlinks param*/
	return !follow_inside_symlinks;
#else
	/* no symlink checking on WIN32 */

	(void)directory;
	(void)utf8_name;

	return false;
#endif
}