diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/DatabaseSave.cxx | 6 | ||||
-rw-r--r-- | src/Main.cxx | 3 | ||||
-rw-r--r-- | src/Mapper.cxx | 3 | ||||
-rw-r--r-- | src/PlaylistFile.cxx | 7 | ||||
-rw-r--r-- | src/fs/Charset.cxx | 113 | ||||
-rw-r--r-- | src/fs/Charset.hxx | 50 | ||||
-rw-r--r-- | src/fs/Config.cxx | 70 | ||||
-rw-r--r-- | src/fs/Config.hxx | 31 | ||||
-rw-r--r-- | src/fs/Path.cxx | 117 | ||||
-rw-r--r-- | src/fs/Path.hxx | 22 |
10 files changed, 282 insertions, 140 deletions
diff --git a/src/DatabaseSave.cxx b/src/DatabaseSave.cxx index 452a7828a..67df236ef 100644 --- a/src/DatabaseSave.cxx +++ b/src/DatabaseSave.cxx @@ -27,7 +27,7 @@ #include "TextFile.hxx" #include "tag/Tag.hxx" #include "tag/TagSettings.h" -#include "fs/Path.hxx" +#include "fs/Charset.hxx" #include "util/Error.hxx" #include "Log.hxx" @@ -57,7 +57,7 @@ db_save_internal(FILE *fp, const Directory *music_root) fprintf(fp, DB_FORMAT_PREFIX "%u\n", DB_FORMAT); fprintf(fp, "%s%s\n", DIRECTORY_MPD_VERSION, VERSION); fprintf(fp, "%s%s\n", DIRECTORY_FS_CHARSET, - Path::GetFSCharset().c_str()); + GetFSCharset().c_str()); for (unsigned i = 0; i < TAG_NUM_OF_ITEM_TYPES; ++i) if (!ignore_tag_items[i]) @@ -110,7 +110,7 @@ db_load_internal(TextFile &file, Directory *music_root, Error &error) found_charset = true; new_charset = line + sizeof(DIRECTORY_FS_CHARSET) - 1; - const std::string &old_charset = Path::GetFSCharset(); + const std::string &old_charset = GetFSCharset(); if (!old_charset.empty() && strcmp(new_charset, old_charset.c_str())) { error.Format(db_domain, diff --git a/src/Main.cxx b/src/Main.cxx index 3c88fc3c4..14820f0db 100644 --- a/src/Main.cxx +++ b/src/Main.cxx @@ -49,6 +49,7 @@ #include "event/Loop.hxx" #include "IOThread.hxx" #include "fs/Path.hxx" +#include "fs/Config.hxx" #include "PlaylistRegistry.hxx" #include "ZeroconfGlue.hxx" #include "DecoderList.hxx" @@ -412,7 +413,7 @@ int mpd_main(int argc, char *argv[]) GlobalEvents::Register(GlobalEvents::SHUTDOWN, shutdown_event_emitted); #endif - Path::GlobalInit(); + ConfigureFS(); if (!glue_mapper_init(error)) { LogError(error); diff --git a/src/Mapper.cxx b/src/Mapper.cxx index 6e3b894dd..b89f83cd7 100644 --- a/src/Mapper.cxx +++ b/src/Mapper.cxx @@ -26,6 +26,7 @@ #include "Directory.hxx" #include "Song.hxx" #include "fs/Path.hxx" +#include "fs/Charset.hxx" #include "fs/FileSystem.hxx" #include "fs/DirectoryReader.hxx" #include "util/Domain.hxx" @@ -236,7 +237,7 @@ map_fs_to_utf8(const char *path_fs) return std::string(); } - return Path::ToUTF8(path_fs); + return PathToUTF8(path_fs); } const Path & diff --git a/src/PlaylistFile.cxx b/src/PlaylistFile.cxx index 19085f496..ea6b3c914 100644 --- a/src/PlaylistFile.cxx +++ b/src/PlaylistFile.cxx @@ -33,6 +33,7 @@ #include "Idle.hxx" #include "fs/Limits.hxx" #include "fs/Path.hxx" +#include "fs/Charset.hxx" #include "fs/FileSystem.hxx" #include "fs/DirectoryReader.hxx" #include "util/UriUtil.hxx" @@ -158,7 +159,7 @@ LoadPlaylistFileInfo(PlaylistInfo &info, char *name = g_strndup(name_fs_str, name_length + 1 - sizeof(PLAYLIST_FILE_SUFFIX)); - std::string name_utf8 = Path::ToUTF8(name); + std::string name_utf8 = PathToUTF8(name); g_free(name); if (name_utf8.empty()) return false; @@ -248,7 +249,7 @@ LoadPlaylistFile(const char *utf8path, Error &error) uri_utf8 = map_fs_to_utf8(s); if (uri_utf8.empty()) { if (Path::IsAbsoluteFS(s)) { - uri_utf8 = Path::ToUTF8(s); + uri_utf8 = PathToUTF8(s); if (uri_utf8.empty()) continue; @@ -257,7 +258,7 @@ LoadPlaylistFile(const char *utf8path, Error &error) continue; } } else { - uri_utf8 = Path::ToUTF8(s); + uri_utf8 = PathToUTF8(s); if (uri_utf8.empty()) continue; } diff --git a/src/fs/Charset.cxx b/src/fs/Charset.cxx new file mode 100644 index 000000000..5a06bf949 --- /dev/null +++ b/src/fs/Charset.cxx @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2003-2013 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "Charset.hxx" +#include "Domain.hxx" +#include "Limits.hxx" +#include "system/FatalError.hxx" +#include "util/Error.hxx" +#include "util/Domain.hxx" +#include "Log.hxx" + +#include <glib.h> + +#include <assert.h> +#include <string.h> + +/** + * Maximal number of bytes required to represent path name in UTF-8 + * (including nul-terminator). + * This value is a rought estimate of upper bound. + * It's based on path name limit in bytes (MPD_PATH_MAX) + * and assumption that some weird encoding could represent some UTF-8 4 byte + * sequences with single byte. + */ +static constexpr size_t MPD_PATH_MAX_UTF8 = (MPD_PATH_MAX - 1) * 4 + 1; + +static std::string fs_charset; + +gcc_pure +static bool +IsSupportedCharset(const char *charset) +{ + /* convert a space to check if the charset is valid */ + char *test = g_convert(" ", 1, charset, "UTF-8", NULL, NULL, NULL); + if (test == NULL) + return false; + + g_free(test); + return true; +} + +void +SetFSCharset(const char *charset) +{ + assert(charset != NULL); + + if (!IsSupportedCharset(charset)) + FormatFatalError("invalid filesystem charset: %s", charset); + + fs_charset = charset; + + FormatDebug(path_domain, + "SetFSCharset: fs charset is: %s", fs_charset.c_str()); +} + +const std::string & +GetFSCharset() +{ + return fs_charset; +} + +std::string +PathToUTF8(const char *path_fs) +{ + if (path_fs == nullptr) + return std::string(); + + GIConv conv = g_iconv_open("utf-8", fs_charset.c_str()); + if (conv == reinterpret_cast<GIConv>(-1)) + return std::string(); + + // g_iconv() does not need nul-terminator, + // std::string could be created without it too. + char path_utf8[MPD_PATH_MAX_UTF8 - 1]; + char *in = const_cast<char *>(path_fs); + char *out = path_utf8; + size_t in_left = strlen(path_fs); + size_t out_left = sizeof(path_utf8); + + size_t ret = g_iconv(conv, &in, &in_left, &out, &out_left); + + g_iconv_close(conv); + + if (ret == static_cast<size_t>(-1) || in_left > 0) + return std::string(); + + return std::string(path_utf8, sizeof(path_utf8) - out_left); +} + +char * +PathFromUTF8(const char *path_utf8) +{ + return g_convert(path_utf8, -1, + fs_charset.c_str(), "utf-8", + nullptr, nullptr, nullptr); +} diff --git a/src/fs/Charset.hxx b/src/fs/Charset.hxx new file mode 100644 index 000000000..58b5a090a --- /dev/null +++ b/src/fs/Charset.hxx @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2003-2013 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_FS_CHARSET_HXX +#define MPD_FS_CHARSET_HXX + +#include "check.h" +#include "Compiler.h" + +#include <string> + +/** + * Gets file system character set name. + */ +gcc_const +const std::string & +GetFSCharset(); + +void +SetFSCharset(const char *charset); + +/** + * Convert the path to UTF-8. + * Returns empty string on error or if #path_fs is null pointer. + */ +gcc_pure +std::string +PathToUTF8(const char *path_fs); + +gcc_malloc +char * +PathFromUTF8(const char *path_utf8); + +#endif diff --git a/src/fs/Config.cxx b/src/fs/Config.cxx new file mode 100644 index 000000000..e08e9f0bf --- /dev/null +++ b/src/fs/Config.cxx @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2003-2013 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "Config.hxx" +#include "Charset.hxx" +#include "Domain.hxx" +#include "ConfigGlobal.hxx" +#include "Log.hxx" +#include "Compiler.h" + +#include <glib.h> + +#include <assert.h> +#include <string.h> + +#ifdef WIN32 +#include <windows.h> // for GetACP() +#include <stdio.h> // for sprintf() +#endif + +void +ConfigureFS() +{ + const char *charset = NULL; + + charset = config_get_string(CONF_FS_CHARSET, NULL); + if (charset == NULL) { +#ifndef WIN32 + const gchar **encodings; + g_get_filename_charsets(&encodings); + + if (encodings[0] != NULL && *encodings[0] != '\0') + charset = encodings[0]; +#else + /* Glib claims that file system encoding is always utf-8 + * on native Win32 (i.e. not Cygwin). + * However this is true only if <gstdio.h> helpers are used. + * MPD uses regular <stdio.h> functions. + * Those functions use encoding determined by GetACP(). */ + static char win_charset[13]; + sprintf(win_charset, "cp%u", GetACP()); + charset = win_charset; +#endif + } + + if (charset) { + SetFSCharset(charset); + } else { + LogDebug(path_domain, + "setting filesystem charset to ISO-8859-1"); + SetFSCharset("ISO-8859-1"); + } +} diff --git a/src/fs/Config.hxx b/src/fs/Config.hxx new file mode 100644 index 000000000..9d7035706 --- /dev/null +++ b/src/fs/Config.hxx @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2003-2013 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_FS_CONFIG_HXX +#define MPD_FS_CONFIG_HXX + +#include "check.h" + +/** + * Performs global one-time initialization of this class. + */ +void +ConfigureFS(); + +#endif diff --git a/src/fs/Path.cxx b/src/fs/Path.cxx index be2661f63..4a4292d05 100644 --- a/src/fs/Path.cxx +++ b/src/fs/Path.cxx @@ -20,11 +20,8 @@ #include "config.h" #include "Path.hxx" #include "Domain.hxx" -#include "Limits.hxx" -#include "ConfigGlobal.hxx" -#include "system/FatalError.hxx" +#include "Charset.hxx" #include "util/Error.hxx" -#include "Log.hxx" #include "Compiler.h" #include <glib.h> @@ -37,18 +34,6 @@ #include <stdio.h> // for sprintf() #endif -/** - * Maximal number of bytes required to represent path name in UTF-8 - * (including nul-terminator). - * This value is a rought estimate of upper bound. - * It's based on path name limit in bytes (MPD_PATH_MAX) - * and assumption that some weird encoding could represent some UTF-8 4 byte - * sequences with single byte. - */ -static constexpr size_t MPD_PATH_MAX_UTF8 = (MPD_PATH_MAX - 1) * 4 + 1; - -static std::string fs_charset; - inline Path::Path(Donate, pointer _value) :value(_value) { g_free(_value); @@ -63,42 +48,9 @@ Path::Build(const_pointer a, const_pointer b) return Path(Donate(), g_build_filename(a, b, nullptr)); } -std::string Path::ToUTF8(const_pointer path_fs) -{ - if (path_fs == nullptr) - return std::string(); - - GIConv conv = g_iconv_open("utf-8", fs_charset.c_str()); - if (conv == reinterpret_cast<GIConv>(-1)) - return std::string(); - - // g_iconv() does not need nul-terminator, - // std::string could be created without it too. - char path_utf8[MPD_PATH_MAX_UTF8 - 1]; - char *in = const_cast<char *>(path_fs); - char *out = path_utf8; - size_t in_left = strlen(path_fs); - size_t out_left = sizeof(path_utf8); - - size_t ret = g_iconv(conv, &in, &in_left, &out, &out_left); - - g_iconv_close(conv); - - if (ret == static_cast<size_t>(-1) || in_left > 0) - return std::string(); - - return std::string(path_utf8, sizeof(path_utf8) - out_left); -} - Path Path::FromUTF8(const char *path_utf8) { - gchar *p; - - p = g_convert(path_utf8, -1, - fs_charset.c_str(), "utf-8", - NULL, NULL, NULL); - - return Path(Donate(), p); + return Path(Donate(), ::PathFromUTF8(path_utf8)); } Path @@ -119,69 +71,10 @@ Path::GetDirectoryName() const return Path(Donate(), g_path_get_dirname(value.c_str())); } -gcc_pure -static bool -IsSupportedCharset(const char *charset) -{ - /* convert a space to check if the charset is valid */ - char *test = g_convert(" ", 1, charset, "UTF-8", NULL, NULL, NULL); - if (test == NULL) - return false; - - g_free(test); - return true; -} - -static void -SetFSCharset(const char *charset) +std::string +Path::ToUTF8() const { - assert(charset != NULL); - - if (!IsSupportedCharset(charset)) - FormatFatalError("invalid filesystem charset: %s", charset); - - fs_charset = charset; - - FormatDebug(path_domain, - "SetFSCharset: fs charset is: %s", fs_charset.c_str()); -} - -const std::string &Path::GetFSCharset() -{ - return fs_charset; -} - -void Path::GlobalInit() -{ - const char *charset = NULL; - - charset = config_get_string(CONF_FS_CHARSET, NULL); - if (charset == NULL) { -#ifndef WIN32 - const gchar **encodings; - g_get_filename_charsets(&encodings); - - if (encodings[0] != NULL && *encodings[0] != '\0') - charset = encodings[0]; -#else - /* Glib claims that file system encoding is always utf-8 - * on native Win32 (i.e. not Cygwin). - * However this is true only if <gstdio.h> helpers are used. - * MPD uses regular <stdio.h> functions. - * Those functions use encoding determined by GetACP(). */ - static char win_charset[13]; - sprintf(win_charset, "cp%u", GetACP()); - charset = win_charset; -#endif - } - - if (charset) { - SetFSCharset(charset); - } else { - LogDebug(path_domain, - "setting filesystem charset to ISO-8859-1"); - SetFSCharset("ISO-8859-1"); - } + return ::PathToUTF8(value.c_str()); } const char * diff --git a/src/fs/Path.hxx b/src/fs/Path.hxx index 10709219b..38112feee 100644 --- a/src/fs/Path.hxx +++ b/src/fs/Path.hxx @@ -130,23 +130,6 @@ public: static Path FromUTF8(const char *path_utf8, Error &error); /** - * Convert the path to UTF-8. - * Returns empty string on error or if #path_fs is null pointer. - */ - gcc_pure - static std::string ToUTF8(const_pointer path_fs); - - /** - * Performs global one-time initialization of this class. - */ - static void GlobalInit(); - - /** - * Gets file system character set name. - */ - static const std::string &GetFSCharset(); - - /** * Copy a #Path object. */ Path &operator=(const Path &) = default; @@ -209,9 +192,8 @@ public: * Returns empty string on error or if this instance is "nulled" * (#IsNull returns true). */ - std::string ToUTF8() const { - return ToUTF8(value.c_str()); - } + gcc_pure + std::string ToUTF8() const; /** * Gets directory name of this path. |