From 16462c54b3503e77bc48c2486234531d7bc31b6d Mon Sep 17 00:00:00 2001 From: Andre Heinecke Date: Wed, 18 Jul 2018 11:27:46 +0200 Subject: [PATCH] qt: Handle encoding for diagnostics * lang/qt/src/threadedjobmixin.cpp (fromEncoding) (stringFromGpgOutput): New helpers. (markupDiagnostics): Use it. -- The Problem is that on my western windows system GnuPG gets CP 437 as GetConsoleOutputCP and prints in that codepage. In a W32 GUI Application we get 0 as GetConsoleOutputCP and 1252 with GetACP. The only thing that seemed to somehow match was GetOEMCP but that might just be luck and it might still be broken in other windows languages. This code is also used in Kleopatra so it might make sense to make it public once it is demonstrated that it works on most systems. --- lang/qt/src/threadedjobmixin.cpp | 54 +++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/lang/qt/src/threadedjobmixin.cpp b/lang/qt/src/threadedjobmixin.cpp index 8fed77c2..cd7c494f 100644 --- a/lang/qt/src/threadedjobmixin.cpp +++ b/lang/qt/src/threadedjobmixin.cpp @@ -53,6 +53,58 @@ using namespace QGpgME; using namespace GpgME; +#ifdef Q_OS_WIN +#include + +static QString fromEncoding (unsigned int src_encoding, const char *data) +{ + int n = MultiByteToWideChar(src_encoding, 0, data, -1, NULL, 0); + if (n < 0) { + return QString(); + } + + wchar_t *result = (wchar_t *) malloc ((n+1) * sizeof *result); + + n = MultiByteToWideChar(src_encoding, 0, data, -1, result, n); + if (n < 0) { + free(result); + return QString(); + } + const auto ret = QString::fromWCharArray(result, n); + free(result); + return ret; +} +#endif + +static QString stringFromGpgOutput(const QByteArray &ba) +{ +#ifdef Q_OS_WIN + /* Qt on Windows uses GetACP while GnuPG prefers + * GetConsoleOutputCP. + * + * As we are not a console application GetConsoleOutputCP + * usually returns 0. + * From experience the closest thing that let's us guess + * what GetConsoleOutputCP returns for a console application + * it appears to be the OEMCP. + */ + unsigned int cpno = GetConsoleOutputCP (); + if (!cpno) { + cpno = GetOEMCP(); + } + if (!cpno) { + cpno = GetACP(); + } + if (!cpno) { + return QString(); + } + + return fromEncoding(cpno, ba.constData()); +#else + return QString::fromLocal8Bit(ba); +#endif +} + static QString markupDiagnostics(const QString &data) { // First ensure that we don't have html in the diag. @@ -76,7 +128,7 @@ QString _detail::audit_log_as_html(Context *ctx, GpgME::Error &err) return QString::fromLocal8Bit(err.asString()); } const QByteArray ba = dp.data(); - return markupDiagnostics(QString::fromUtf8(ba.data(), ba.size())); + return markupDiagnostics(stringFromGpgOutput(ba)); } if (ctx->protocol() == CMS) {