From 1ae89728593fce4a40882fa133b9db269015da8f Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 13 Aug 2012 23:37:50 +0200 Subject: mapper: fix non-UTF8 music directory name Duplicate the music_dir variable: one encoded in UTF-8, and another one using the configured filesystem character set. This fixes an ancient MPD bug. --- NEWS | 1 + src/command.c | 2 +- src/inotify_update.c | 4 +-- src/mapper.c | 89 +++++++++++++++++++++++++++++++++------------------- src/mapper.h | 15 +++++++-- 5 files changed, 74 insertions(+), 37 deletions(-) diff --git a/NEWS b/NEWS index d2393e502..812d03908 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,7 @@ ver 0.17.2 (2012/??/??) * protocol: - fix crash in local file check +* mapper: fix non-UTF8 music directory name ver 0.17.1 (2012/07/31) diff --git a/src/command.c b/src/command.c index 86d216a75..329b7d51a 100644 --- a/src/command.c +++ b/src/command.c @@ -1544,7 +1544,7 @@ handle_config(struct client *client, return COMMAND_RETURN_ERROR; } - const char *path = mapper_get_music_directory(); + const char *path = mapper_get_music_directory_utf8(); if (path != NULL) client_printf(client, "music_directory: %s\n", path); diff --git a/src/inotify_update.c b/src/inotify_update.c index 02e55ee0b..3f4a8c0c4 100644 --- a/src/inotify_update.c +++ b/src/inotify_update.c @@ -266,7 +266,7 @@ mpd_inotify_callback(int wd, unsigned mask, (mask & IN_ISDIR) != 0) { /* a sub directory was changed: register those in inotify */ - const char *root = mapper_get_music_directory(); + const char *root = mapper_get_music_directory_fs(); const char *path_fs; char *allocated = NULL; @@ -308,7 +308,7 @@ mpd_inotify_init(unsigned max_depth) g_debug("initializing inotify"); - const char *path = mapper_get_music_directory(); + const char *path = mapper_get_music_directory_fs(); if (path == NULL) { g_debug("no music directory configured"); return; diff --git a/src/mapper.c b/src/mapper.c index d230f5d92..6a968e32d 100644 --- a/src/mapper.c +++ b/src/mapper.c @@ -36,10 +36,24 @@ #include #include -static char *music_dir; -static size_t music_dir_length; +/** + * The absolute path of the music directory encoded in UTF-8. + */ +static char *music_dir_utf8; +static size_t music_dir_utf8_length; -static char *playlist_dir; +/** + * The absolute path of the music directory encoded in the filesystem + * character set. + */ +static char *music_dir_fs; +static size_t music_dir_fs_length; + +/** + * The absolute path of the playlist directory encoded in the + * filesystem character set. + */ +static char *playlist_dir_fs; /** * Duplicate a string, chop all trailing slashes. @@ -86,20 +100,21 @@ check_directory(const char *path) } static void -mapper_set_music_dir(const char *path) +mapper_set_music_dir(const char *path_utf8) { - check_directory(path); + music_dir_utf8 = strdup_chop_slash(path_utf8); + music_dir_utf8_length = strlen(music_dir_utf8); - music_dir = strdup_chop_slash(path); - music_dir_length = strlen(music_dir); + music_dir_fs = utf8_to_fs_charset(music_dir_utf8); + check_directory(music_dir_fs); + music_dir_fs_length = strlen(music_dir_fs); } static void -mapper_set_playlist_dir(const char *path) +mapper_set_playlist_dir(const char *path_utf8) { - check_directory(path); - - playlist_dir = g_strdup(path); + playlist_dir_fs = utf8_to_fs_charset(path_utf8); + check_directory(playlist_dir_fs); } void mapper_init(const char *_music_dir, const char *_playlist_dir) @@ -113,23 +128,31 @@ void mapper_init(const char *_music_dir, const char *_playlist_dir) void mapper_finish(void) { - g_free(music_dir); - g_free(playlist_dir); + g_free(music_dir_utf8); + g_free(music_dir_fs); + g_free(playlist_dir_fs); } const char * -mapper_get_music_directory(void) +mapper_get_music_directory_utf8(void) { - return music_dir; + return music_dir_utf8; +} + +const char * +mapper_get_music_directory_fs(void) +{ + return music_dir_fs; } const char * map_to_relative_path(const char *path_utf8) { - return music_dir != NULL && - memcmp(path_utf8, music_dir, music_dir_length) == 0 && - G_IS_DIR_SEPARATOR(path_utf8[music_dir_length]) - ? path_utf8 + music_dir_length + 1 + return music_dir_utf8 != NULL && + memcmp(path_utf8, music_dir_utf8, + music_dir_utf8_length) == 0 && + G_IS_DIR_SEPARATOR(path_utf8[music_dir_utf8_length]) + ? path_utf8 + music_dir_utf8_length + 1 : path_utf8; } @@ -141,14 +164,14 @@ map_uri_fs(const char *uri) assert(uri != NULL); assert(*uri != '/'); - if (music_dir == NULL) + if (music_dir_fs == NULL) return NULL; uri_fs = utf8_to_fs_charset(uri); if (uri_fs == NULL) return NULL; - path_fs = g_build_filename(music_dir, uri_fs, NULL); + path_fs = g_build_filename(music_dir_fs, uri_fs, NULL); g_free(uri_fs); return path_fs; @@ -157,10 +180,11 @@ map_uri_fs(const char *uri) char * map_directory_fs(const struct directory *directory) { - assert(music_dir != NULL); + assert(music_dir_utf8 != NULL); + assert(music_dir_fs != NULL); if (directory_is_root(directory)) - return g_strdup(music_dir); + return g_strdup(music_dir_fs); return map_uri_fs(directory_get_path(directory)); } @@ -168,9 +192,10 @@ map_directory_fs(const struct directory *directory) char * map_directory_child_fs(const struct directory *directory, const char *name) { - char *name_fs, *parent_fs, *path; + assert(music_dir_utf8 != NULL); + assert(music_dir_fs != NULL); - assert(music_dir != NULL); + char *name_fs, *parent_fs, *path; /* check for invalid or unauthorized base names */ if (*name == 0 || strchr(name, '/') != NULL || @@ -208,11 +233,11 @@ map_song_fs(const struct song *song) char * map_fs_to_utf8(const char *path_fs) { - if (music_dir != NULL && - strncmp(path_fs, music_dir, music_dir_length) == 0 && - G_IS_DIR_SEPARATOR(path_fs[music_dir_length])) + if (music_dir_fs != NULL && + strncmp(path_fs, music_dir_fs, music_dir_fs_length) == 0 && + G_IS_DIR_SEPARATOR(path_fs[music_dir_fs_length])) /* remove musicDir prefix */ - path_fs += music_dir_length + 1; + path_fs += music_dir_fs_length + 1; else if (G_IS_DIR_SEPARATOR(path_fs[0])) /* not within musicDir */ return NULL; @@ -226,7 +251,7 @@ map_fs_to_utf8(const char *path_fs) const char * map_spl_path(void) { - return playlist_dir; + return playlist_dir_fs; } char * @@ -234,7 +259,7 @@ map_spl_utf8_to_fs(const char *name) { char *filename_utf8, *filename_fs, *path; - if (playlist_dir == NULL) + if (playlist_dir_fs == NULL) return NULL; filename_utf8 = g_strconcat(name, PLAYLIST_FILE_SUFFIX, NULL); @@ -243,7 +268,7 @@ map_spl_utf8_to_fs(const char *name) if (filename_fs == NULL) return NULL; - path = g_build_filename(playlist_dir, filename_fs, NULL); + path = g_build_filename(playlist_dir_fs, filename_fs, NULL); g_free(filename_fs); return path; diff --git a/src/mapper.h b/src/mapper.h index ed4a60b56..d6184a175 100644 --- a/src/mapper.h +++ b/src/mapper.h @@ -36,9 +36,20 @@ void mapper_init(const char *_music_dir, const char *_playlist_dir); void mapper_finish(void); +/** + * Return the absolute path of the music directory encoded in UTF-8. + */ +G_GNUC_CONST +const char * +mapper_get_music_directory_utf8(void); + +/** + * Return the absolute path of the music directory encoded in the + * filesystem character set. + */ G_GNUC_CONST const char * -mapper_get_music_directory(void); +mapper_get_music_directory_fs(void); /** * Returns true if a music directory was configured. @@ -47,7 +58,7 @@ G_GNUC_CONST static inline bool mapper_has_music_directory(void) { - return mapper_get_music_directory() != NULL; + return mapper_get_music_directory_utf8() != NULL; } /** -- cgit v1.2.3