tdf#160260: make poppler wrapper executable Unicode-aware on Windows

Change-Id: I76dc31ee14d1794fa73f990e641540ff941c7201
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/165735
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
This commit is contained in:
Mike Kaganski
2024-04-03 12:40:06 +05:00
parent f09b9b2785
commit 7b9905df45

View File

@@ -21,6 +21,8 @@
#ifdef _WIN32 #ifdef _WIN32
# include <io.h> # include <io.h>
# include <fcntl.h> /*_O_BINARY*/ # include <fcntl.h> /*_O_BINARY*/
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#endif #endif
#ifndef SYSTEM_POPPLER #ifndef SYSTEM_POPPLER
#include <string> // std::string #include <string> // std::string
@@ -30,24 +32,58 @@
FILE* g_binary_out=stderr; FILE* g_binary_out=stderr;
static const char *ownerPassword = "\001"; #ifdef _WIN32
static const char *userPassword = "\001";
static const char *outputFile = "\001";
static const char *options = "\001";
int main(int argc, char **argv) // Use Unicode API
static const wchar_t *ownerPassword = nullptr;
static const wchar_t *userPassword = nullptr;
static const wchar_t *outputFile = nullptr;
static const wchar_t *options = L"";
#define TO_STRING_VIEW(s) std::wstring_view(L##s)
using my_string = std::wstring;
// Poppler expects UTF-8 strings on Windows - see its openFile in poppler/goo/gfile.cc.
static std::string myStringToStdString(std::wstring_view s)
{ {
int k = 0; int len = WideCharToMultiByte(CP_UTF8, 0, s.data(), s.size(), nullptr, 0, nullptr, nullptr);
char* buff = static_cast<char*>(_alloca(len * sizeof(char)));
len = WideCharToMultiByte(CP_UTF8, 0, s.data(), s.size(), buff, len, nullptr, nullptr);
return std::string(buff, len);
}
#else // ! _WIN32
static const char *ownerPassword = nullptr;
static const char *userPassword = nullptr;
static const char *outputFile = nullptr;
static const char *options = "";
#define TO_STRING_VIEW(s) std::string_view(s)
using my_string = std::string;
static std::string myStringToStdString(std::string&& s) { return std::move(s); }
#endif
#ifdef _WIN32
int wmain(int argc, wchar_t **argv)
#else
int main(int argc, char **argv)
#endif
{
int k = 1;
while (k < argc) while (k < argc)
{ {
if (!strcmp(argv[k], "-f")) if (argv[k] == TO_STRING_VIEW("-f"))
{ {
outputFile = argv[k+1]; outputFile = argv[k+1];
argc -= 2; argc -= 2;
for (int j = k; j < argc; ++j) for (int j = k; j < argc; ++j)
argv[j] = argv[j+2]; argv[j] = argv[j+2];
} }
else if (!strcmp(argv[k], "-o")) else if (argv[k] == TO_STRING_VIEW("-o"))
{ {
options = argv[k+1]; options = argv[k+1];
argc -= 2; argc -= 2;
@@ -55,14 +91,14 @@ int main(int argc, char **argv)
argv[j] = argv[j+2]; argv[j] = argv[j+2];
} }
else if (!strcmp(argv[k], "-opw")) else if (argv[k] == TO_STRING_VIEW("-opw"))
{ {
ownerPassword = argv[k+1]; ownerPassword = argv[k+1];
argc -= 2; argc -= 2;
for (int j = k; j < argc; ++j) for (int j = k; j < argc; ++j)
argv[j] = argv[j+2]; argv[j] = argv[j+2];
} }
else if (!strcmp(argv[k], "-upw")) else if (argv[k] == TO_STRING_VIEW("-upw"))
{ {
userPassword = argv[k+1]; userPassword = argv[k+1];
argc -= 2; argc -= 2;
@@ -79,10 +115,10 @@ int main(int argc, char **argv)
/* Creates an absolute path to the poppler_data directory, by taking the path /* Creates an absolute path to the poppler_data directory, by taking the path
* to the xpdfimport executable (provided in argv[0], and concatenating a * to the xpdfimport executable (provided in argv[0], and concatenating a
* relative path to the poppler_data directory from the program directory. */ * relative path to the poppler_data directory from the program directory. */
const std::string execPath = argv[0]; const my_string execPath = argv[0];
const std::size_t filenameStartPos = execPath.find_last_of("/\\")+1; const std::size_t filenameStartPos = execPath.find_last_of(TO_STRING_VIEW("/\\")) + 1;
const std::string programPath = execPath.substr(0,filenameStartPos); const my_string programPath = execPath.substr(0, filenameStartPos);
const std::string popplerDataPath = programPath + "../" LIBO_SHARE_FOLDER "/xpdfimport/poppler_data"; const std::string popplerDataPath = myStringToStdString(programPath + my_string(TO_STRING_VIEW("../" LIBO_SHARE_FOLDER "/xpdfimport/poppler_data")));
const char* datadir = popplerDataPath.c_str(); const char* datadir = popplerDataPath.c_str();
#endif #endif
@@ -115,22 +151,26 @@ int main(int argc, char **argv)
} }
// PDFDoc takes over ownership for all strings below // PDFDoc takes over ownership for all strings below
GooString* pFileName = new GooString(argv[1]); GooString* pFileName = new GooString(myStringToStdString(argv[1]));
GooString* pErrFileName = new GooString(argv[2]); GooString* pErrFileName = new GooString(myStringToStdString(argv[2]));
// check for password string(s) // check for password string(s)
GooString* pOwnerPasswordStr( aPwBuf[0] != 0 GooString* pOwnerPasswordStr( aPwBuf[0] != 0
? new GooString( aPwBuf ) ? new GooString( aPwBuf )
: (ownerPassword[0] != '\001' : (ownerPassword
? new GooString(ownerPassword) ? new GooString(myStringToStdString(ownerPassword))
: nullptr ) ); : nullptr ) );
GooString* pUserPasswordStr( aPwBuf[0] != 0 GooString* pUserPasswordStr( aPwBuf[0] != 0
? new GooString( aPwBuf ) ? new GooString( aPwBuf )
: (userPassword[0] != '\001' : (userPassword
? new GooString(userPassword) ? new GooString(myStringToStdString(userPassword))
: nullptr ) ); : nullptr ) );
if( outputFile[0] != '\001' ) if (outputFile)
#if defined _WIN32
g_binary_out = _wfopen(outputFile, L"wb");
#else
g_binary_out = fopen(outputFile,"wb"); g_binary_out = fopen(outputFile,"wb");
#endif
#ifdef _WIN32 #ifdef _WIN32
// Win actually modifies output for O_TEXT file mode, so need to // Win actually modifies output for O_TEXT file mode, so need to
@@ -160,7 +200,7 @@ int main(int argc, char **argv)
PDFDoc &rDoc = aDoc.isOk()? aDoc: aErrDoc; PDFDoc &rDoc = aDoc.isOk()? aDoc: aErrDoc;
pdfi::PDFOutDev aOutDev(&rDoc); pdfi::PDFOutDev aOutDev(&rDoc);
if (!strcmp(options, "SkipImages")) { if (options == TO_STRING_VIEW("SkipImages")) {
aOutDev.setSkipImages(true); aOutDev.setSkipImages(true);
} }