mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
Bug 795134 - Improper handle of unicode character in username
Part 1: gnc-filename-utils didn't manage the encoding differences between Windows (UTF16) and GLib (UTF-8).
This commit is contained in:
parent
451bbd53d9
commit
35cd165bec
@ -81,7 +81,11 @@ static int gnucash_show_version = 0;
|
||||
static int debugging = 0;
|
||||
static int extra = 0;
|
||||
static gchar **log_flags = NULL;
|
||||
static gchar *log_to_filename = NULL;
|
||||
#ifdef __MINGW64__
|
||||
static wchar_t *log_to_filename = NULL;
|
||||
#else
|
||||
static char *log_to_filename = NULL;
|
||||
#endif
|
||||
static int nofile = 0;
|
||||
static const gchar *gsettings_prefix = NULL;
|
||||
static const char *add_quotes_file = NULL;
|
||||
@ -679,7 +683,12 @@ gnc_log_init()
|
||||
{
|
||||
if (log_to_filename != NULL)
|
||||
{
|
||||
qof_log_init_filename_special(log_to_filename);
|
||||
#ifdef __MINGW64__
|
||||
char* filename = g_utf16_to_utf8(log_to_filename, -1, NULL, NULL, NULL);
|
||||
#else
|
||||
char* filename = log_to_filename;
|
||||
#endif
|
||||
qof_log_init_filename_special(filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -66,14 +66,19 @@ extern "C" {
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/locale.hpp>
|
||||
#include <codecvt>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
|
||||
#if PLATFORM(WINDOWS)
|
||||
#include <codecvt>
|
||||
#include <locale>
|
||||
using codecvt = std::codecvt_utf8<wchar_t, 0x10FFFF, std::little_endian>;
|
||||
using string = std::wstring;
|
||||
#else
|
||||
using codecvt = std::codecvt;
|
||||
using string = std::string;
|
||||
#endif
|
||||
static codecvt cvt;
|
||||
static std::locale bfs_locale(std::locale(), new codecvt);
|
||||
|
||||
namespace bfs = boost::filesystem;
|
||||
namespace bst = boost::system;
|
||||
@ -366,7 +371,8 @@ gnc_validate_directory (const bfs::path &dirname)
|
||||
* we need to overrule it during build (when guile interferes)
|
||||
* and testing.
|
||||
*/
|
||||
auto home_dir = bfs::path (g_get_home_dir ());
|
||||
bfs::path home_dir(g_get_home_dir(), cvt);
|
||||
home_dir.imbue(bfs_locale);
|
||||
auto homedir_exists = bfs::exists(home_dir);
|
||||
auto is_descendant = dir_is_descendant (dirname, home_dir);
|
||||
if (!homedir_exists && is_descendant)
|
||||
@ -432,11 +438,16 @@ copy_recursive(const bfs::path& src, const bfs::path& dest)
|
||||
for(auto direntry = bfs::recursive_directory_iterator(src);
|
||||
direntry != bfs::recursive_directory_iterator(); ++direntry)
|
||||
{
|
||||
auto cur_str = direntry->path().string();
|
||||
#ifdef G_OS_WIN32
|
||||
string cur_str = direntry->path().wstring();
|
||||
#else
|
||||
string cur_str = direntry->path().string();
|
||||
#endif
|
||||
auto cur_len = cur_str.size();
|
||||
auto rel_str = std::string(cur_str, old_len, cur_len - old_len);
|
||||
auto relpath = bfs::path(rel_str).relative_path();
|
||||
auto newpath = bfs::absolute (relpath, dest);
|
||||
string rel_str(cur_str, old_len, cur_len - old_len);
|
||||
bfs::path relpath(rel_str, cvt);
|
||||
auto newpath = bfs::absolute (relpath.relative_path(), dest);
|
||||
newpath.imbue(bfs_locale);
|
||||
bfs::copy(direntry->path(), newpath);
|
||||
}
|
||||
}
|
||||
@ -458,31 +469,27 @@ copy_recursive(const bfs::path& src, const bfs::path& dest)
|
||||
* So this function is a copy of glib's internal get_special_folder
|
||||
* and minimally adjusted to fetch CSIDL_APPDATA
|
||||
*/
|
||||
static char *
|
||||
win32_get_userdata_home (void)
|
||||
static bfs::path
|
||||
get_user_data_dir ()
|
||||
{
|
||||
wchar_t path[MAX_PATH+1];
|
||||
HRESULT hr;
|
||||
LPITEMIDLIST pidl = NULL;
|
||||
BOOL b;
|
||||
char *retval = NULL;
|
||||
|
||||
hr = SHGetSpecialFolderLocation (NULL, CSIDL_APPDATA, &pidl);
|
||||
if (hr == S_OK)
|
||||
{
|
||||
b = SHGetPathFromIDListW (pidl, path);
|
||||
if (b)
|
||||
{
|
||||
std::wstring_convert<std::codecvt_utf8<wchar_t>> utf8_conv;
|
||||
retval = g_strdup(utf8_conv.to_bytes(path).c_str());
|
||||
}
|
||||
CoTaskMemFree (pidl);
|
||||
}
|
||||
bfs::path retval(path, cvt);
|
||||
retval.imbue(bfs_locale);
|
||||
return retval;
|
||||
}
|
||||
#elif defined MAC_INTEGRATION
|
||||
static char*
|
||||
quarz_get_userdata_home(void)
|
||||
static bfs::path
|
||||
get_user_data_dir()
|
||||
{
|
||||
char *retval = NULL;
|
||||
NSFileManager*fm = [NSFileManager defaultManager];
|
||||
@ -492,9 +499,14 @@ quarz_get_userdata_home(void)
|
||||
{
|
||||
NSURL* dirUrl = [appSupportDir objectAtIndex:0];
|
||||
NSString* dirPath = [dirUrl path];
|
||||
retval = g_strdup([dirPath UTF8String]);
|
||||
}
|
||||
return retval;
|
||||
return [dirPath UTF8String];
|
||||
}
|
||||
#else
|
||||
static bfs::path
|
||||
get_user_data_dir()
|
||||
{
|
||||
return g_get_user_data_dir();
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -508,22 +520,8 @@ static bfs::path
|
||||
get_userdata_home(void)
|
||||
{
|
||||
auto try_tmp_dir = true;
|
||||
gchar *data_dir = NULL;
|
||||
auto userdata_home = bfs::path();
|
||||
auto userdata_home = get_user_data_dir();
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
data_dir = win32_get_userdata_home ();
|
||||
#elif defined MAC_INTEGRATION
|
||||
data_dir = quarz_get_userdata_home ();
|
||||
#endif
|
||||
|
||||
if (data_dir)
|
||||
{
|
||||
userdata_home = data_dir;
|
||||
g_free(data_dir);
|
||||
}
|
||||
else
|
||||
userdata_home = g_get_user_data_dir();
|
||||
|
||||
/* g_get_user_data_dir doesn't check whether the path exists nor attempts to
|
||||
* create it. So while it may return an actual path we may not be able to use it.
|
||||
@ -548,7 +546,9 @@ get_userdata_home(void)
|
||||
Hopefully we can always write there. */
|
||||
if (try_tmp_dir)
|
||||
{
|
||||
userdata_home = bfs::path (g_get_tmp_dir ()) / g_get_user_name ();
|
||||
bfs::path newpath(g_get_tmp_dir (), cvt);
|
||||
newpath.imbue(bfs_locale);
|
||||
userdata_home = std::move(newpath);
|
||||
}
|
||||
g_assert(!userdata_home.empty());
|
||||
|
||||
@ -564,33 +564,21 @@ get_userdata_home(void)
|
||||
static bfs::path
|
||||
get_userconfig_home(void)
|
||||
{
|
||||
gchar *config_dir = NULL;
|
||||
auto userconfig_home = bfs::path();
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
config_dir = win32_get_userdata_home ();
|
||||
#elif defined MAC_INTEGRATION
|
||||
config_dir = quarz_get_userdata_home ();
|
||||
#endif
|
||||
|
||||
/* On Windows and Macs the data directory is used, for Linux
|
||||
$HOME/.config is used */
|
||||
if (config_dir)
|
||||
{
|
||||
userconfig_home = config_dir;
|
||||
g_free(config_dir);
|
||||
}
|
||||
else
|
||||
userconfig_home = g_get_user_config_dir();
|
||||
|
||||
return userconfig_home;
|
||||
#if defined (G_OS_WIN32) || defined (MAC_INTEGRATION)
|
||||
return get_user_data_dir();
|
||||
#else
|
||||
return g_get_user_config_dir();
|
||||
#endif
|
||||
}
|
||||
|
||||
static std::string migrate_gnc_datahome()
|
||||
{
|
||||
auto success = false;
|
||||
// Specify location of dictionaries
|
||||
auto old_dir = bfs::path(g_get_home_dir()) / ".gnucash";
|
||||
bfs::path old_dir(g_get_home_dir(), cvt);
|
||||
old_dir += ".gnucash";
|
||||
|
||||
bl::generator gen;
|
||||
gen.add_messages_path(gnc_path_get_datadir());
|
||||
@ -760,7 +748,9 @@ gnc_filepath_init (void)
|
||||
* issues when the build environment is not a complete environment (like
|
||||
* it could be missing a valid home directory). */
|
||||
auto env_build_dir = g_getenv ("GNC_BUILDDIR");
|
||||
build_dir = bfs::path(env_build_dir ? env_build_dir : "");
|
||||
bfs::path new_dir(env_build_dir ? env_build_dir : "", cvt);
|
||||
new_dir.imbue(bfs_locale);
|
||||
build_dir = std::move(new_dir);
|
||||
auto running_uninstalled = (g_getenv ("GNC_UNINSTALLED") != NULL);
|
||||
if (running_uninstalled && !build_dir.empty())
|
||||
{
|
||||
@ -787,7 +777,9 @@ gnc_filepath_init (void)
|
||||
auto gnc_userdata_home_env = g_getenv ("GNC_DATA_HOME");
|
||||
if (gnc_userdata_home_env)
|
||||
{
|
||||
gnc_userdata_home = bfs::path (gnc_userdata_home_env);
|
||||
bfs::path newdir(gnc_userdata_home_env, cvt);
|
||||
newdir.imbue(bfs_locale);
|
||||
gnc_userdata_home = std::move(newdir);
|
||||
try
|
||||
{
|
||||
gnc_userdata_home_exists = bfs::exists (gnc_userdata_home);
|
||||
|
@ -166,7 +166,7 @@ qof_log_init_filename(const gchar* log_filename)
|
||||
#if PLATFORM(WINDOWS)
|
||||
/* MSVC compiler: Somehow the OS thinks file descriptor from above
|
||||
* still isn't open. So we open normally with the file name and that's it. */
|
||||
fout = fopen(fname, "wb");
|
||||
fout = g_fopen(fname, "wb");
|
||||
#else
|
||||
/* We must not overwrite /dev/null */
|
||||
g_assert(g_strcmp0(log_filename, "/dev/null") != 0);
|
||||
|
Loading…
Reference in New Issue
Block a user