aboutsummaryrefslogtreecommitdiffstats
path: root/libqpdf/QUtil.cc
diff options
context:
space:
mode:
authorJay Berkenbilt <ejb@ql.org>2019-04-21 00:14:32 +0200
committerJay Berkenbilt <ejb@ql.org>2019-04-21 03:00:43 +0200
commit011695dfdf52e7a83f0eeceb85d0d2c06e7df7da (patch)
tree0ba571e7bd78d546e9b99b5804be9cfdc23673fc /libqpdf/QUtil.cc
parent4ccb29912a28e78b130091b8e66ccaa79c626ae7 (diff)
downloadqpdf-011695dfdf52e7a83f0eeceb85d0d2c06e7df7da.tar.zst
Support Unicode in filenames (fixes #298)
Diffstat (limited to 'libqpdf/QUtil.cc')
-rw-r--r--libqpdf/QUtil.cc33
1 files changed, 32 insertions, 1 deletions
diff --git a/libqpdf/QUtil.cc b/libqpdf/QUtil.cc
index 7ea3f5e7..816c2dfa 100644
--- a/libqpdf/QUtil.cc
+++ b/libqpdf/QUtil.cc
@@ -354,11 +354,42 @@ FILE*
QUtil::safe_fopen(char const* filename, char const* mode)
{
FILE* f = 0;
+#ifdef _WIN32
+ // Convert the utf-8 encoded filename argument to wchar_t*. First,
+ // convert to utf16, then to wchar_t*. Note that u16 will start
+ // with the UTF16 marker, which we skip.
+ std::string u16 = utf8_to_utf16(filename);
+ size_t len = u16.length();
+ size_t wlen = (len / 2) - 1;
+ PointerHolder<wchar_t> wfilenamep(true, new wchar_t[wlen + 1]);
+ wchar_t* wfilename = wfilenamep.getPointer();
+ wfilename[wlen] = 0;
+ for (unsigned int i = 2; i < len; i += 2)
+ {
+ wfilename[(i/2) - 1] =
+ static_cast<wchar_t>(
+ (static_cast<unsigned char>(u16.at(i)) << 8) +
+ static_cast<unsigned char>(u16.at(i+1)));
+ }
+ PointerHolder<wchar_t> wmodep(true, new wchar_t(strlen(mode) + 1));
+ wchar_t* wmode = wmodep.getPointer();
+ wmode[strlen(mode)] = 0;
+ for (size_t i = 0; i < strlen(mode); ++i)
+ {
+ wmode[i] = mode[i];
+ }
+
#ifdef _MSC_VER
- errno_t err = fopen_s(&f, filename, mode);
+ errno_t err = _wfopen_s(&f, wfilename, wmode);
if (err != 0)
{
errno = err;
+ }
+#else
+ f = _wfopen(wfilename, wmode);
+#endif
+ if (f == 0)
+ {
throw_system_error(std::string("open ") + filename);
}
#else