From b809028bda7a19d42c0e76f5abda977598f80921 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Sun, 1 Mar 2009 00:02:33 +0000 Subject: [PATCH] uses iconv by default on linux to convert filenames from utf-8 to the current locale --- include/libtorrent/config.hpp | 8 +++ include/libtorrent/escape_string.hpp | 9 +++ include/libtorrent/storage.hpp | 6 -- src/escape_string.cpp | 61 ++++++++++++++++ src/file.cpp | 14 ++-- src/storage.cpp | 100 +++++++++++++-------------- 6 files changed, 138 insertions(+), 60 deletions(-) diff --git a/include/libtorrent/config.hpp b/include/libtorrent/config.hpp index 00ab52483..0c627c7a7 100644 --- a/include/libtorrent/config.hpp +++ b/include/libtorrent/config.hpp @@ -102,5 +102,13 @@ POSSIBILITY OF SUCH DAMAGE. #define TORRENT_UPNP_LOGGING #endif +#if !TORRENT_USE_WPATH && defined TORRENT_LINUX +// libiconv presnce, not implemented yet +#define TORRENT_USE_LOCALE_FILENAMES 1 +#else +#define TORRENT_USE_LOCALE_FILENAMES 0 +#endif + + #endif // TORRENT_CONFIG_HPP_INCLUDED diff --git a/include/libtorrent/escape_string.hpp b/include/libtorrent/escape_string.hpp index b40011ef8..5a8ef0cb3 100644 --- a/include/libtorrent/escape_string.hpp +++ b/include/libtorrent/escape_string.hpp @@ -61,6 +61,15 @@ namespace libtorrent std::string const& url, std::string argument); TORRENT_EXPORT std::string to_hex(std::string const& s); + +#if TORRENT_USE_WPATH + TORRENT_EXPORT std::wstring convert_to_wstring(std::string const& s); +#endif + +#if TORRENT_USE_LOCALE_FILENAMES + TORRENT_EXPORT std::string convert_to_native(std::string const& s); +#endif + } #endif // TORRENT_ESCAPE_STRING_HPP_INCLUDED diff --git a/include/libtorrent/storage.hpp b/include/libtorrent/storage.hpp index ae6470c5d..85701fba7 100644 --- a/include/libtorrent/storage.hpp +++ b/include/libtorrent/storage.hpp @@ -81,12 +81,6 @@ namespace libtorrent storage_mode_compact }; -#if TORRENT_USE_WPATH - - TORRENT_EXPORT std::wstring safe_convert(std::string const& s); - -#endif - TORRENT_EXPORT std::vector > get_filesizes( file_storage const& t , fs::path p); diff --git a/src/escape_string.cpp b/src/escape_string.cpp index 5abc3f58f..19231fad7 100644 --- a/src/escape_string.cpp +++ b/src/escape_string.cpp @@ -48,6 +48,22 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/assert.hpp" #include "libtorrent/escape_string.hpp" +#if TORRENT_USE_WPATH + +#ifdef BOOST_WINDOWS +#include +#endif + +#include +#include "libtorrent/utf8.hpp" + +#endif + +#if TORRENT_USE_LOCALE_FILENAMES +#include +#include +#endif + namespace libtorrent { @@ -393,5 +409,50 @@ namespace libtorrent return ret; } +#if TORRENT_USE_WPATH + std::wstring convert_to_wstring(std::string const& s) + { + std::wstring ret; + int result = libtorrent::utf8_wchar(s, ret); +#ifndef BOOST_WINDOWS + return ret; +#else + if (result == 0) return ret; + + ret.clear(); + const char* end = &s[0] + s.size(); + for (const char* i = &s[0]; i < end;) + { + wchar_t c = '.'; + int result = std::mbtowc(&c, i, end - i); + if (result > 0) i += result; + else ++i; + ret += c; + } + return ret; +#endif + } +#endif + +#if TORRENT_USE_LOCALE_FILENAMES + std::string convert_to_native(std::string const& s) + { + // the empty string represents the local dependent encoding + static iconv_t iconv_handle = iconv_open("", "UTF-8"); + if (iconv_handle == iconv_t(-1)) return s; + std::string ret; + size_t insize = s.size(); + size_t outsize = insize * 4; + ret.resize(outsize); + char const* in = &s[0]; + char* out = &ret[0]; + size_t retval = iconv(iconv_handle, (char**)&in, &insize, + &out, &outsize); + if (retval == (size_t)-1) return s; + ret.resize(outsize); + return ret; + } +#endif + } diff --git a/src/file.cpp b/src/file.cpp index 79d6e95ea..c6f41b674 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -65,9 +65,9 @@ BOOST_STATIC_ASSERT(sizeof(lseek(0, 0, 0)) >= 8); #include #include -#if TORRENT_USE_WPATH -// for safe_convert -#include "libtorrent/storage.hpp" +#if TORRENT_USE_WPATH || TORRENT_USE_LOCALE_FILENAMES +// for convert_to_wstring and convert_to_native +#include "libtorrent/escape_string.hpp" #endif #include "libtorrent/assert.hpp" @@ -179,7 +179,7 @@ namespace libtorrent }; #if TORRENT_USE_WPATH - m_path = safe_convert(path.external_file_string()); + m_path = convert_to_wstring(path.external_file_string()); #else m_path = utf8_native(path.external_file_string()); #endif @@ -220,8 +220,14 @@ namespace libtorrent #else static const int no_buffer_flag[] = {0, 0}; #endif + +#if TORRENT_USE_LOCALE_FILENAMES + m_fd = ::open(convert_to_native(path.external_file_string()).c_str() + , mode_array[mode & rw_mask] | no_buffer_flag[(mode & no_buffer) >> 2], permissions); +#else m_fd = ::open(path.external_file_string().c_str() , mode_array[mode & rw_mask] | no_buffer_flag[(mode & no_buffer) >> 2], permissions); +#endif #ifdef TORRENT_LINUX // workaround for linux bug diff --git a/src/storage.cpp b/src/storage.cpp index 538ce4822..6002e4218 100644 --- a/src/storage.cpp +++ b/src/storage.cpp @@ -100,43 +100,9 @@ POSSIBILITY OF SUCH DAMAGE. #include #endif -#if TORRENT_USE_WPATH - -#ifdef BOOST_WINDOWS -#include -#else -#include -#endif - -#include -#include "libtorrent/utf8.hpp" -#include "libtorrent/buffer.hpp" - -namespace libtorrent -{ - std::wstring safe_convert(std::string const& s) - { - std::wstring ret; - int result = libtorrent::utf8_wchar(s, ret); -#ifndef BOOST_WINDOWS - return ret; -#else - if (result == 0) return ret; - - ret.clear(); - const char* end = &s[0] + s.size(); - for (const char* i = &s[0]; i < end;) - { - wchar_t c = '.'; - int result = std::mbtowc(&c, i, end - i); - if (result > 0) i += result; - else ++i; - ret += c; - } - return ret; -#endif - } -} +#if TORRENT_USE_WPATH || TORRENT_USE_LOCALE_FILENAMES +// for convert_to_wstring and convert_to_native +#include "libtorrent/escape_string.hpp" #endif namespace fs = boost::filesystem; @@ -222,7 +188,9 @@ namespace libtorrent size_type size = 0; std::time_t time = 0; #if TORRENT_USE_WPATH - fs::wpath f = safe_convert((p / i->path).string()); + fs::wpath f = convert_to_wstring((p / i->path).string()); +#elif TORRENT_USE_LOCALE_FILENAMES + fs::path f = convert_to_native((p / i->path).string()); #else fs::path f = p / i->path; #endif @@ -273,7 +241,9 @@ namespace libtorrent if (i->pad_file) continue; #if TORRENT_USE_WPATH - fs::wpath f = safe_convert((p / i->path).string()); + fs::wpath f = convert_to_wstring((p / i->path).string()); +#elif TORRENT_USE_LOCALE_FILENAMES + fs::path f = convert_to_native(p / i->path); #else fs::path f = p / i->path; #endif @@ -535,9 +505,13 @@ namespace libtorrent last_path = dir; #if TORRENT_USE_WPATH - fs::wpath wp = safe_convert(last_path.string()); + fs::wpath wp = convert_to_wstring(last_path.string()); if (!exists(wp)) create_directories(wp); +#elif TORRENT_USE_LOCALE_FILENAMES + fs::path p = convert_to_native(last_path.string()); + if (!exists(p)) + create_directories(p); #else if (!exists(last_path)) create_directories(last_path); @@ -558,7 +532,7 @@ namespace libtorrent #endif #if TORRENT_USE_WPATH - fs::wpath file_path = safe_convert((m_save_path / file_iter->path).string()); + fs::wpath file_path = convert_to_wstring((m_save_path / file_iter->path).string()); #else fs::path file_path = m_save_path / file_iter->path; #endif @@ -609,8 +583,11 @@ namespace libtorrent m_pool.release(old_name); #if TORRENT_USE_WPATH - fs::wpath old_path = safe_convert(old_name.string()); - fs::wpath new_path = safe_convert((m_save_path / new_filename).string()); + fs::wpath old_path = convert_to_wstring(old_name.string()); + fs::wpath new_path = convert_to_wstring((m_save_path / new_filename).string()); +#elif TORRENT_USE_LOCALE_FILENAMES + fs::path const& old_path = convert_to_native(old_name.string()); + fs::path new_path = convert_to_native((m_save_path / new_filename).string()); #else fs::path const& old_path = old_name; fs::path new_path = m_save_path / new_filename; @@ -686,12 +663,18 @@ namespace libtorrent } #if TORRENT_USE_WPATH try - { fs::remove(safe_convert(p)); } + { fs::remove(convert_to_wstring(p)); } catch (std::exception& e) { error = errno; error_file = p; } +#elif TORRENT_USE_LOCALE_FILENAMES + if (std::remove(convert_to_native(p).c_str()) != 0 && errno != ENOENT) + { + error = errno; + error_file = p; + } #else if (std::remove(p.c_str()) != 0 && errno != ENOENT) { @@ -709,12 +692,18 @@ namespace libtorrent { #if TORRENT_USE_WPATH try - { fs::remove(safe_convert(*i)); } + { fs::remove(convert_to_wstring(*i)); } catch (std::exception& e) { error = errno; error_file = *i; } +#elif TORRENT_USE_LOCALE_FILENAMES + if (std::remove(convert_to_native(*i).c_str()) != 0 && errno != ENOENT) + { + error = errno; + error_file = *i; + } #else if (std::remove(i->c_str()) != 0 && errno != ENOENT) { @@ -903,9 +892,9 @@ namespace libtorrent } } } - return match_filesizes(files(), m_save_path, file_sizes , !full_allocation_mode, &error); + } // returns true on success @@ -922,11 +911,17 @@ namespace libtorrent save_path = complete(save_path); #if TORRENT_USE_WPATH - fs::wpath wp = safe_convert(save_path.string()); + fs::wpath wp = convert_to_wstring(save_path.string()); if (!exists(wp)) create_directory(wp); else if (!is_directory(wp)) return false; +#elif TORRENT_USE_LOCALE_FILENAMES + fs::path p = convert_to_native(save_path.string()); + if (!exists(p)) + create_directory(p); + else if (!is_directory(p)) + return false; #else if (!exists(save_path)) create_directory(save_path); @@ -937,8 +932,11 @@ namespace libtorrent m_pool.release(this); #if TORRENT_USE_WPATH - old_path = safe_convert((m_save_path / files().name()).string()); - new_path = safe_convert((save_path / files().name()).string()); + old_path = convert_to_wstring((m_save_path / files().name()).string()); + new_path = convert_to_wstring((save_path / files().name()).string()); +#elif TORRENT_USE_LOCALE_FILENAMES + old_path = convert_to_native((m_save_path / files().name()).string()); + new_path = convert_to_native((save_path / files().name().string())); #else old_path = m_save_path / files().name(); new_path = save_path / files().name(); @@ -1858,8 +1856,10 @@ ret: { #endif #if TORRENT_USE_WPATH - fs::wpath wf = safe_convert(f.string()); + fs::wpath wf = convert_to_wstring(f.string()); file_exists = exists(wf); +#elif TORRENT_USE_LOCALE_FILENAMES + file_exists = exists(convert_to_native(f.string())); #else file_exists = exists(f); #endif