enum playlist_result
playlist_append_file(struct playlist *playlist, const char *path, int uid,
		     unsigned *added_id)
{
	int ret;
	struct stat st;
	struct song *song;

	if (uid < 0) {
		g_debug("unauthenticated client: %d", uid);
		return PLAYLIST_RESULT_DENIED;
    }

	ret = stat(path, &st);
	if (ret < 0)
		return PLAYLIST_RESULT_ERRNO;

	if (st.st_uid != (uid_t)uid && (st.st_mode & 0444) != 0444) {
		g_debug("client is not owner: %d (%o)", st.st_uid, st.st_mode);
		return PLAYLIST_RESULT_DENIED;
    }

	song = song_file_load(path, NULL);
	if (song == NULL)
		return PLAYLIST_RESULT_NO_SUCH_SONG;

	return playlist_append_song(playlist, song, added_id);
}
예제 #2
0
enum playlist_result
playlist_append_file(struct playlist *playlist, struct player_control *pc,
		     const char *path, int uid, unsigned *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 && (st.st_mode & 0444) != 0444)
		/* client is not owner */
		return PLAYLIST_RESULT_DENIED;

	song = song_file_load(path, NULL);
	if (song == NULL)
		return PLAYLIST_RESULT_NO_SUCH_SONG;

	return playlist_append_song(playlist, pc, song, added_id);
}
예제 #3
0
static void
update_regular_file(struct directory *directory,
		    const char *name, const struct stat *st)
{
	const char *suffix = uri_get_suffix(name);
	const struct decoder_plugin* plugin;
#ifdef ENABLE_ARCHIVE
	const struct archive_plugin *archive;
#endif
	if (suffix == NULL)
		return;

	if ((plugin = decoder_plugin_from_suffix(suffix, false)) != NULL)
	{
		struct song* song = songvec_find(&directory->songs, name);

		if (!(song != NULL && st->st_mtime == song->mtime &&
		      !walk_discard) &&
			plugin->container_scan != NULL)
		{
			if (update_container_file(directory, name, st, plugin))
			{
				if (song != NULL)
					delete_song(directory, song);

				return;
			}
		}

		if (song == NULL) {
			song = song_file_load(name, directory);
			if (song == NULL) {
				g_debug("ignoring unrecognized file %s/%s",
					directory_get_path(directory), name);
				return;
			}

			songvec_add(&directory->songs, song);
			modified = true;
			g_message("added %s/%s",
				  directory_get_path(directory), name);
		} else if (st->st_mtime != song->mtime || walk_discard) {
			g_message("updating %s/%s",
				  directory_get_path(directory), name);
			if (!song_file_update(song)) {
				g_debug("deleting unrecognized file %s/%s",
					directory_get_path(directory), name);
				delete_song(directory, song);
			}

			modified = true;
		}
#ifdef ENABLE_ARCHIVE
	} else if ((archive = archive_plugin_from_suffix(suffix))) {
		update_archive_file(directory, name, st, archive);
#endif
	}
}
예제 #4
0
static struct song *
playlist_check_load_song(const struct song *song, const char *uri, bool secure)
{
	struct song *dest;

	if (uri_has_scheme(uri)) {
		dest = song_remote_new(uri);
	} else if (g_path_is_absolute(uri) && secure) {
		dest = song_file_load(uri, NULL);
		if (dest == NULL)
			return NULL;
	} else {
		dest = db_get_song(uri);
		if (dest == NULL)
			/* not found in database */
			return NULL;
	}

	return apply_song_metadata(dest, song);
}
예제 #5
0
static void
update_archive_tree(struct directory *directory, char *name)
{
	struct directory *subdir;
	struct song *song;
	char *tmp;

	tmp = strchr(name, '/');
	if (tmp) {
		*tmp = 0;
		//add dir is not there already
		if ((subdir = dirvec_find(&directory->children, name)) == NULL) {
		        //create new directory
		        subdir = make_subdir(directory, name);
			subdir->device = DEVICE_INARCHIVE;
		}
		//create directories first
		update_archive_tree(subdir, tmp+1);
	} else {
		if (strlen(name) == 0) {
			g_warning("archive returned directory only");
			return;
		}
		//add file
		song = songvec_find(&directory->songs, name);
		if (song == NULL) {
			song = song_file_load(name, directory);
			if (song != NULL) {
				songvec_add(&directory->songs, song);
				modified = true;
				g_message("added %s/%s",
					  directory_get_path(directory), name);
			}
		}
	}
}
예제 #6
0
static void
update_song_file2(struct directory *directory,
		  const char *name, const struct stat *st,
		  const struct decoder_plugin *plugin)
{
	db_lock();
	struct song *song = directory_get_song(directory, name);
	db_unlock();

	if (!directory_child_access(directory, name, R_OK)) {
		g_warning("no read permissions on %s/%s",
			  directory_get_path(directory), name);
		if (song != NULL) {
			db_lock();
			delete_song(directory, song);
			db_unlock();
		}

		return;
	}

	if (!(song != NULL && st->st_mtime == song->mtime &&
	      !walk_discard) &&
	    update_container_file(directory, name, st, plugin)) {
		if (song != NULL) {
			db_lock();
			delete_song(directory, song);
			db_unlock();
		}

		return;
	}

	if (song == NULL) {
		g_debug("reading %s/%s",
			directory_get_path(directory), name);
		song = song_file_load(name, directory);
		if (song == NULL) {
			g_debug("ignoring unrecognized file %s/%s",
				directory_get_path(directory), name);
			return;
		}

		db_lock();
		directory_add_song(directory, song);
		db_unlock();

		modified = true;
		g_message("added %s/%s",
			  directory_get_path(directory), name);
	} else if (st->st_mtime != song->mtime || walk_discard) {
		g_message("updating %s/%s",
			  directory_get_path(directory), name);
		if (!song_file_update(song)) {
			g_debug("deleting unrecognized file %s/%s",
				directory_get_path(directory), name);
			db_lock();
			delete_song(directory, song);
			db_unlock();
		}

		modified = true;
	}
}
예제 #7
0
struct song *
playlist_check_translate_song(struct song *song, const char *base_uri,
			      bool secure)
{
	struct song *dest;

	if (song_in_database(song))
		/* already ok */
		return song;

	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 *prefix = mapper_get_music_directory();

		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 when "secure" is enabled */
			song_free(song);
			return NULL;
		}

		base_uri = NULL;
	}

	if (base_uri != NULL)
		uri = g_build_filename(base_uri, uri, NULL);
	else
		uri = g_strdup(uri);

	if (uri_has_scheme(uri)) {
		dest = song_remote_new(uri);
		g_free(uri);
	} else if (g_path_is_absolute(uri) && secure) {
		dest = song_file_load(uri, NULL);
		if (dest == NULL) {
			song_free(song);
			return NULL;
		}
	} else {
		dest = db_get_song(uri);
		g_free(uri);
		if (dest == NULL) {
			/* not found in database */
			song_free(song);
			return dest;
		}
	}

	dest = apply_song_metadata(dest, song);
	song_free(song);

	return dest;
}