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); } }
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 }