diff options
author | Jay Berkenbilt <ejb@ql.org> | 2019-04-21 00:14:32 +0200 |
---|---|---|
committer | Jay Berkenbilt <ejb@ql.org> | 2019-04-21 03:00:43 +0200 |
commit | 011695dfdf52e7a83f0eeceb85d0d2c06e7df7da (patch) | |
tree | 0ba571e7bd78d546e9b99b5804be9cfdc23673fc /libqpdf/QUtil.cc | |
parent | 4ccb29912a28e78b130091b8e66ccaa79c626ae7 (diff) | |
download | qpdf-011695dfdf52e7a83f0eeceb85d0d2c06e7df7da.tar.zst |
Support Unicode in filenames (fixes #298)
Diffstat (limited to 'libqpdf/QUtil.cc')
-rw-r--r-- | libqpdf/QUtil.cc | 33 |
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 |