From 15a955ff2139c2cc94f382135f8d412c50b74b75 Mon Sep 17 00:00:00 2001 From: Povilas Kanapickas Date: Sat, 30 Oct 2021 00:52:55 +0300 Subject: [PATCH] Revert "Use ansi codepage for internal multibyte strings on windows" This reverts commit 402801e0a66a902475723c13f3a03bac2b7fd503. We should use UTF8 throughout the application and convert to platform encodings only at the edge. Otherwise it's not clear which data uses which encoding and we result in extremele brittle system. --- src/gui/src/CommandProcess.cpp | 21 ++++---- src/gui/src/Fingerprint.cpp | 7 ++- src/gui/src/IpcClient.cpp | 8 +-- src/gui/src/MainWindow.cpp | 3 +- src/gui/src/QUtility.cpp | 9 ---- src/gui/src/QUtility.h | 1 - src/gui/src/SslCertificate.cpp | 49 ++++++++++-------- src/gui/src/SslCertificate.h | 8 +-- src/lib/barrier/win32/DaemonApp.cpp | 3 +- src/lib/common/win32/DataDirectories.cpp | 28 ++++++++-- src/lib/common/win32/KnownFolderPaths.cpp | 63 ----------------------- src/lib/common/win32/KnownFolderPaths.h | 24 --------- src/lib/ipc/IpcLogOutputter.cpp | 3 +- src/lib/platform/MSWindowsScreen.cpp | 12 +++-- 14 files changed, 87 insertions(+), 152 deletions(-) delete mode 100644 src/lib/common/win32/KnownFolderPaths.cpp delete mode 100644 src/lib/common/win32/KnownFolderPaths.h diff --git a/src/gui/src/CommandProcess.cpp b/src/gui/src/CommandProcess.cpp index 57397ae7..c85e847b 100644 --- a/src/gui/src/CommandProcess.cpp +++ b/src/gui/src/CommandProcess.cpp @@ -30,35 +30,34 @@ CommandProcess::CommandProcess(QString cmd, QStringList arguments, QString input QString CommandProcess::run() { QProcess process; - QString standardOutput, standardError; process.setReadChannel(QProcess::StandardOutput); process.start(m_Command, m_Arguments); bool success = process.waitForStarted(); + QString output, error; if (success) { if (!m_Input.isEmpty()) { - process.write(m_Input.toLocal8Bit()); + process.write(m_Input.toStdString().c_str()); } if (process.waitForFinished()) { - standardOutput = QString::fromLocal8Bit(process.readAllStandardOutput().trimmed()); - standardError = QString::fromLocal8Bit(process.readAllStandardError().trimmed()); + output = process.readAllStandardOutput().trimmed(); + error = process.readAllStandardError().trimmed(); } } int code = process.exitCode(); - if (!standardError.isEmpty() || !success || code != 0) + if (!error.isEmpty() || !success || code != 0) { throw std::runtime_error( - std::string( - QString("Code: %1\nError: %2") - .arg(process.exitCode()) - .arg(standardError.isEmpty() ? "Unknown" : standardError) - .toLocal8Bit().constData())); + QString("Code: %1\nError: %2") + .arg(process.exitCode()) + .arg(error.isEmpty() ? "Unknown" : error) + .toStdString()); } emit finished(); - return standardOutput; + return output; } diff --git a/src/gui/src/Fingerprint.cpp b/src/gui/src/Fingerprint.cpp index 0e4588f8..cc1ce3bf 100644 --- a/src/gui/src/Fingerprint.cpp +++ b/src/gui/src/Fingerprint.cpp @@ -16,7 +16,8 @@ */ #include "Fingerprint.h" -#include "QUtility.h" + +#include "common/DataDirectories.h" #include #include @@ -123,8 +124,10 @@ void Fingerprint::persistDirectory() QString Fingerprint::directoryPath() { + auto profileDir = QString::fromStdString(DataDirectories::profile()); + return QString("%1/%2") - .arg(profilePath()) + .arg(profileDir) .arg(kDirName); } diff --git a/src/gui/src/IpcClient.cpp b/src/gui/src/IpcClient.cpp index b8b1bcb1..1b0e147a 100644 --- a/src/gui/src/IpcClient.cpp +++ b/src/gui/src/IpcClient.cpp @@ -104,12 +104,14 @@ void IpcClient::sendCommand(const QString& command, ElevateMode const elevate) stream.writeRawData(kIpcMsgCommand, 4); - QByteArray utf8Command = command.toUtf8(); + std::string stdStringCommand = command.toStdString(); + const char* charCommand = stdStringCommand.c_str(); + int length = (int)strlen(charCommand); char lenBuf[4]; - intToBytes(utf8Command.size(), lenBuf, 4); + intToBytes(length, lenBuf, 4); stream.writeRawData(lenBuf, 4); - stream.writeRawData(utf8Command.constData(), utf8Command.size()); + stream.writeRawData(charCommand, length); char elevateBuf[1]; // Refer to enum ElevateMode documentation for why this flag is mapped this way diff --git a/src/gui/src/MainWindow.cpp b/src/gui/src/MainWindow.cpp index 5d4ee8fe..40050782 100644 --- a/src/gui/src/MainWindow.cpp +++ b/src/gui/src/MainWindow.cpp @@ -31,6 +31,7 @@ #include "ProcessorArch.h" #include "SslCertificate.h" #include "ShutdownCh.h" +#include "common/DataDirectories.h" #include #include @@ -524,7 +525,7 @@ void MainWindow::startBarrier() // launched the process (e.g. when launched with elevation). setting the // profile dir on launch ensures it uses the same profile dir is used // no matter how its relaunched. - args << "--profile-dir" << QString("\"%1\"").arg(profilePath()); + args << "--profile-dir" << QString::fromStdString("\"" + DataDirectories::profile() + "\""); #endif if ((barrierType() == barrierClient && !clientArgs(args, app)) diff --git a/src/gui/src/QUtility.cpp b/src/gui/src/QUtility.cpp index 932bf146..2d05fc36 100644 --- a/src/gui/src/QUtility.cpp +++ b/src/gui/src/QUtility.cpp @@ -19,7 +19,6 @@ #include "ProcessorArch.h" #include "CommandProcess.h" -#include "common/DataDirectories.h" #if defined(Q_OS_LINUX) #include @@ -113,11 +112,3 @@ QString getOSInformation() return result; } - -QString profilePath() -{ - // Get path to current profile directory, properly converted - // from an OS locale std::string to Unicode QString. - auto localePath = DataDirectories::profile(); - return QString::fromLocal8Bit(localePath.c_str(), localePath.size()); -} diff --git a/src/gui/src/QUtility.h b/src/gui/src/QUtility.h index 7c05fd00..62a60825 100644 --- a/src/gui/src/QUtility.h +++ b/src/gui/src/QUtility.h @@ -29,4 +29,3 @@ QString hash(const QString& string); QString getFirstMacAddress(); qProcessorArch getProcessorArch(); QString getOSInformation(); -QString profilePath(); diff --git a/src/gui/src/SslCertificate.cpp b/src/gui/src/SslCertificate.cpp index 84ce5459..9dc93ce8 100644 --- a/src/gui/src/SslCertificate.cpp +++ b/src/gui/src/SslCertificate.cpp @@ -17,7 +17,7 @@ #include "SslCertificate.h" #include "Fingerprint.h" -#include "QUtility.h" +#include "common/DataDirectories.h" #include #include @@ -43,13 +43,13 @@ static const char kConfigFile[] = "barrier.conf"; SslCertificate::SslCertificate(QObject *parent) : QObject(parent) { - m_ProfileDir = profilePath(); - if (m_ProfileDir.isEmpty()) { + m_ProfileDir = DataDirectories::profile(); + if (m_ProfileDir.empty()) { emit error(tr("Failed to get profile directory.")); } } -std::pair SslCertificate::runTool(const QStringList& args) +std::pair SslCertificate::runTool(const QStringList& args) { QString program; #if defined(Q_OS_WIN) @@ -68,15 +68,17 @@ std::pair SslCertificate::runTool(const QStringList& args) #endif QProcess process; - QString standardOutput, standardError; process.setEnvironment(environment); process.start(program, args); - bool success = process.waitForStarted(); + bool success = process.waitForStarted(); + std::string output; + + QString standardError; if (success && process.waitForFinished()) { - standardOutput = QString::fromLocal8Bit(process.readAllStandardOutput().trimmed()); - standardError = QString::fromLocal8Bit(process.readAllStandardError().trimmed()); + output = process.readAllStandardOutput().trimmed().toStdString(); + standardError = process.readAllStandardError().trimmed(); } int code = process.exitCode(); @@ -87,15 +89,15 @@ std::pair SslCertificate::runTool(const QStringList& args) .arg(program) .arg(process.exitCode()) .arg(standardError.isEmpty() ? "Unknown" : standardError)); - return {false, standardOutput}; + return {false, output}; } - return {true, standardOutput}; + return {true, output}; } void SslCertificate::generateCertificate() { - auto filename = getCertificatePath(); + auto filename = QString::fromStdString(getCertificatePath()); QFile file(filename); if (!file.exists() || !isCertificateValid(filename)) { @@ -120,7 +122,7 @@ void SslCertificate::generateCertificate() arguments.append("-newkey"); arguments.append("rsa:2048"); - QDir sslDir(getCertificateDirectory()); + QDir sslDir(QString::fromStdString(getCertificateDirectory())); if (!sslDir.exists()) { sslDir.mkpath("."); } @@ -157,17 +159,20 @@ void SslCertificate::generateFingerprint(const QString& certificateFilename) auto ret = runTool(arguments); bool success = ret.first; + std::string output = ret.second; + if (!success) { return; } // find the fingerprint from the tool output - QString fingerprint = ret.second; - auto i = fingerprint.indexOf('='); - if (i != -1) { - fingerprint.remove(0, i+1); + auto i = output.find_first_of('='); + if (i != std::string::npos) { + i++; + auto fingerprint = output.substr( + i, output.size() - i); - Fingerprint::local().trust(fingerprint, false); + Fingerprint::local().trust(QString::fromStdString(fingerprint), false); emit info(tr("SSL fingerprint generated.")); } else { @@ -175,14 +180,14 @@ void SslCertificate::generateFingerprint(const QString& certificateFilename) } } -QString SslCertificate::getCertificatePath() +std::string SslCertificate::getCertificatePath() { - return getCertificateDirectory() + QDir::separator() + kCertificateFilename; + return getCertificateDirectory() + QDir::separator().toLatin1() + kCertificateFilename; } -QString SslCertificate::getCertificateDirectory() +std::string SslCertificate::getCertificateDirectory() { - return m_ProfileDir + QDir::separator() + kSslDir; + return m_ProfileDir + QDir::separator().toLatin1() + kSslDir; } bool SslCertificate::isCertificateValid(const QString& path) @@ -193,7 +198,7 @@ bool SslCertificate::isCertificateValid(const QString& path) BIO* bio = BIO_new(BIO_s_file()); - auto ret = BIO_read_filename(bio, path.toLocal8Bit().constData()); + auto ret = BIO_read_filename(bio, path.toStdString().c_str()); if (!ret) { emit info(tr("Could not read from default certificate file.")); BIO_free_all(bio); diff --git a/src/gui/src/SslCertificate.h b/src/gui/src/SslCertificate.h index e8ae2738..2fe807a2 100644 --- a/src/gui/src/SslCertificate.h +++ b/src/gui/src/SslCertificate.h @@ -36,13 +36,13 @@ signals: void generateFinished(); private: - std::pair runTool(const QStringList& args); + std::pair runTool(const QStringList& args); void generateFingerprint(const QString& certificateFilename); - QString getCertificatePath(); - QString getCertificateDirectory(); + std::string getCertificatePath(); + std::string getCertificateDirectory(); bool isCertificateValid(const QString& path); private: - QString m_ProfileDir; + std::string m_ProfileDir; }; diff --git a/src/lib/barrier/win32/DaemonApp.cpp b/src/lib/barrier/win32/DaemonApp.cpp index f8cf591a..88e6b4ef 100644 --- a/src/lib/barrier/win32/DaemonApp.cpp +++ b/src/lib/barrier/win32/DaemonApp.cpp @@ -34,7 +34,6 @@ #include "base/log_outputters.h" #include "base/Log.h" #include "common/DataDirectories.h" -#include "base/Unicode.h" #include "arch/win32/ArchMiscWindows.h" #include "arch/win32/XArchWindows.h" @@ -258,7 +257,7 @@ DaemonApp::handleIpcMessage(const Event& e, void*) switch (m->type()) { case kIpcCommand: { IpcCommandMessage* cm = static_cast(m); - String command = Unicode::UTF8ToText(cm->command()); + String command = cm->command(); // if empty quotes, clear. if (command == "\"\"") { diff --git a/src/lib/common/win32/DataDirectories.cpp b/src/lib/common/win32/DataDirectories.cpp index 62250b10..b6d77be5 100644 --- a/src/lib/common/win32/DataDirectories.cpp +++ b/src/lib/common/win32/DataDirectories.cpp @@ -16,12 +16,34 @@ */ #include "../DataDirectories.h" -#include "KnownFolderPaths.h" + +#include + +std::string unicode_to_mb(const WCHAR* utfStr) +{ + int utfLength = lstrlenW(utfStr); + int mbLength = WideCharToMultiByte(CP_UTF8, 0, utfStr, utfLength, NULL, 0, NULL, NULL); + std::string mbStr(mbLength, 0); + WideCharToMultiByte(CP_UTF8, 0, utfStr, utfLength, &mbStr[0], mbLength, NULL, NULL); + return mbStr; +} + +std::string known_folder_path(const KNOWNFOLDERID& id) +{ + std::string path; + WCHAR* buffer; + HRESULT result = SHGetKnownFolderPath(id, 0, NULL, &buffer); + if (result == S_OK) { + path = unicode_to_mb(buffer); + CoTaskMemFree(buffer); + } + return path; +} const std::string& DataDirectories::profile() { if (_profile.empty()) - _profile = localAppDataPath() + "\\Barrier"; + _profile = known_folder_path(FOLDERID_LocalAppData) + "\\Barrier"; return _profile; } const std::string& DataDirectories::profile(const std::string& path) @@ -33,7 +55,7 @@ const std::string& DataDirectories::profile(const std::string& path) const std::string& DataDirectories::global() { if (_global.empty()) - _global = programDataPath() + "\\Barrier"; + _global = known_folder_path(FOLDERID_ProgramData) + "\\Barrier"; return _global; } const std::string& DataDirectories::global(const std::string& path) diff --git a/src/lib/common/win32/KnownFolderPaths.cpp b/src/lib/common/win32/KnownFolderPaths.cpp deleted file mode 100644 index 23ccc84a..00000000 --- a/src/lib/common/win32/KnownFolderPaths.cpp +++ /dev/null @@ -1,63 +0,0 @@ -/* -* barrier -- mouse and keyboard sharing utility -* Copyright (C) 2018 Debauchee Open Source Group -* -* This package is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* found in the file LICENSE that should have accompanied this file. -* -* This package is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ - -#include "KnownFolderPaths.h" - -#define WIN32_LEAN_AND_MEAN -#include -#include - -static std::string wide_to_mb(const wchar_t* source, int length) -{ - int ansiLength = WideCharToMultiByte(CP_ACP, 0, source, length, NULL, 0, NULL, NULL); - if (ansiLength > 0) { - std::string ansiString(ansiLength, 0); - ansiLength = WideCharToMultiByte(CP_ACP, 0, source, length, &ansiString[0], ansiLength, NULL, NULL); - if (ansiLength > 0) { - return ansiString; - } - } - return {}; -} - -static std::string known_folder_path(const KNOWNFOLDERID& id) -{ - std::string path; - WCHAR* buffer; - HRESULT result = SHGetKnownFolderPath(id, 0, NULL, &buffer); - if (result == S_OK) { - auto length = lstrlenW(buffer); - path = wide_to_mb(buffer, length); - CoTaskMemFree(buffer); - } - return path; -} - -std::string desktopPath() -{ - return known_folder_path(FOLDERID_Desktop); -} - -std::string localAppDataPath() -{ - return known_folder_path(FOLDERID_LocalAppData); -} - -std::string programDataPath() -{ - return known_folder_path(FOLDERID_ProgramData); -} diff --git a/src/lib/common/win32/KnownFolderPaths.h b/src/lib/common/win32/KnownFolderPaths.h deleted file mode 100644 index 81b650ec..00000000 --- a/src/lib/common/win32/KnownFolderPaths.h +++ /dev/null @@ -1,24 +0,0 @@ -/* -* barrier -- mouse and keyboard sharing utility -* Copyright (C) 2018 Debauchee Open Source Group -* -* This package is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* found in the file LICENSE that should have accompanied this file. -* -* This package is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ - -#pragma once - -#include - -std::string desktopPath(); -std::string localAppDataPath(); -std::string programDataPath(); diff --git a/src/lib/ipc/IpcLogOutputter.cpp b/src/lib/ipc/IpcLogOutputter.cpp index c895dc12..223f52f7 100644 --- a/src/lib/ipc/IpcLogOutputter.cpp +++ b/src/lib/ipc/IpcLogOutputter.cpp @@ -29,7 +29,6 @@ #include "base/EventQueue.h" #include "base/TMethodEventJob.h" #include "base/TMethodJob.h" -#include "base/Unicode.h" enum EIpcLogOutputter { kBufferMaxSize = 1000, @@ -197,7 +196,7 @@ IpcLogOutputter::sendBuffer() return; } - IpcLogLineMessage message(Unicode::textToUTF8(getChunk(kMaxSendLines))); + IpcLogLineMessage message(getChunk(kMaxSendLines)); m_sending = true; m_ipcServer.send(message, kIpcClientGui); m_sending = false; diff --git a/src/lib/platform/MSWindowsScreen.cpp b/src/lib/platform/MSWindowsScreen.cpp index 739a1e25..2449ba7c 100644 --- a/src/lib/platform/MSWindowsScreen.cpp +++ b/src/lib/platform/MSWindowsScreen.cpp @@ -41,9 +41,9 @@ #include "base/IEventQueue.h" #include "base/TMethodEventJob.h" #include "base/TMethodJob.h" -#include "common/win32/KnownFolderPaths.h" #include +#include #include #include @@ -1916,12 +1916,14 @@ const std::string& MSWindowsScreen::getDropTarget() const { if (m_dropTargetPath.empty()) { - m_dropTargetPath = desktopPath(); - if (!m_dropTargetPath.empty()) { - LOG((CLOG_DEBUG "using desktop for drop target: %s", m_dropTargetPath.c_str())); + // SHGetFolderPath is deprecated in vista, but use it for xp support. + char desktopPath[MAX_PATH]; + if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_DESKTOP, NULL, 0, desktopPath))) { + m_dropTargetPath = std::string(desktopPath); + LOG((CLOG_INFO "using desktop for drop target: %s", m_dropTargetPath.c_str())); } else { - LOG((CLOG_ERR "failed to get desktop path, no drop target available")); + LOG((CLOG_ERR "failed to get desktop path, no drop target available, error=%d", GetLastError())); } } return m_dropTargetPath;