Skip to content

Commit

Permalink
Use ansi codepage for internal multibyte strings on windows (fixes #976
Browse files Browse the repository at this point in the history
…, fixes #974, fixes #444)
  • Loading branch information
albertony committed Dec 11, 2020
1 parent e032d14 commit f6e2222
Show file tree
Hide file tree
Showing 12 changed files with 138 additions and 81 deletions.
19 changes: 10 additions & 9 deletions src/gui/src/CommandProcess.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,34 +30,35 @@ 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.toStdString().c_str());
process.write(m_Input.toLocal8Bit());
}

if (process.waitForFinished()) {
output = process.readAllStandardOutput().trimmed();
error = process.readAllStandardError().trimmed();
standardOutput = QString::fromLocal8Bit(process.readAllStandardOutput().trimmed());
standardError = QString::fromLocal8Bit(process.readAllStandardError().trimmed());
}
}

int code = process.exitCode();
if (!error.isEmpty() || !success || code != 0)
{
throw std::runtime_error(
QString("Code: %1\nError: %2")
.arg(process.exitCode())
.arg(error.isEmpty() ? "Unknown" : error)
.toStdString());
std::string(
QString("Code: %1\nError: %2")
.arg(process.exitCode())
.arg(standardError.isEmpty() ? "Unknown" : standardError)
.toLocal8Bit().constData()));
}

emit finished();

return output;
return standardOutput;
}
4 changes: 1 addition & 3 deletions src/gui/src/Fingerprint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@

#include "Fingerprint.h"

#include "common/DataDirectories.h"

#include <QDir>
#include <QTextStream>

Expand Down Expand Up @@ -125,7 +123,7 @@ void Fingerprint::persistDirectory()

QString Fingerprint::directoryPath()
{
auto profileDir = QString::fromStdString(DataDirectories::profile());
auto profilePath = QString::fromLocal8Bit(DataDirectories::profile());

return QString("%1/%2")
.arg(profileDir)
Expand Down
8 changes: 3 additions & 5 deletions src/gui/src/IpcClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,14 +104,12 @@ void IpcClient::sendCommand(const QString& command, ElevateMode const elevate)

stream.writeRawData(kIpcMsgCommand, 4);

std::string stdStringCommand = command.toStdString();
const char* charCommand = stdStringCommand.c_str();
int length = (int)strlen(charCommand);
QByteArray utf8Command = command.toUtf8();

char lenBuf[4];
intToBytes(length, lenBuf, 4);
intToBytes(utf8Command.size(), lenBuf, 4);
stream.writeRawData(lenBuf, 4);
stream.writeRawData(charCommand, length);
stream.writeRawData(utf8Command.constData(), utf8Command.size());

char elevateBuf[1];
// Refer to enum ElevateMode documentation for why this flag is mapped this way
Expand Down
2 changes: 1 addition & 1 deletion src/gui/src/MainWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,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::fromStdString("\"" + DataDirectories::profile() + "\"");
args << "--profile-dir" << QString::fromLocal8Bit("\"" + DataDirectories::profile() + "\"");
#endif

if ((barrierType() == barrierClient && !clientArgs(args, app))
Expand Down
45 changes: 20 additions & 25 deletions src/gui/src/SslCertificate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,13 @@ static const char kConfigFile[] = "barrier.conf";
SslCertificate::SslCertificate(QObject *parent) :
QObject(parent)
{
m_ProfileDir = DataDirectories::profile();
if (m_ProfileDir.empty()) {
m_ProfileDir = QString::fromLocal8Bit(DataDirectories::profile());
if (m_ProfileDir.isEmpty()) {
emit error(tr("Failed to get profile directory."));
}
}

std::pair<bool, std::string> SslCertificate::runTool(const QStringList& args)
std::pair<bool, QString> SslCertificate::runTool(const QStringList& args)
{
QString program;
#if defined(Q_OS_WIN)
Expand All @@ -68,17 +68,15 @@ std::pair<bool, std::string> SslCertificate::runTool(const QStringList& args)
#endif

QProcess process;
QString standardOutput, standardError;
process.setEnvironment(environment);
process.start(program, args);

bool success = process.waitForStarted();
std::string output;

QString standardError;
if (success && process.waitForFinished())
{
output = process.readAllStandardOutput().trimmed().toStdString();
standardError = process.readAllStandardError().trimmed();
standardOutput = QString::fromLocal8Bit(process.readAllStandardOutput().trimmed());
standardError = QString::fromLocal8Bit(process.readAllStandardError().trimmed());
}

int code = process.exitCode();
Expand All @@ -89,15 +87,15 @@ std::pair<bool, std::string> SslCertificate::runTool(const QStringList& args)
.arg(program)
.arg(process.exitCode())
.arg(standardError.isEmpty() ? "Unknown" : standardError));
return {false, output};
return {false, standardOutput};
}

return {true, output};
return {true, standardOutput};
}

void SslCertificate::generateCertificate()
{
auto filename = QString::fromStdString(getCertificatePath());
auto filename = getCertificatePath();

QFile file(filename);
if (!file.exists() || !isCertificateValid(filename)) {
Expand All @@ -122,7 +120,7 @@ void SslCertificate::generateCertificate()
arguments.append("-newkey");
arguments.append("rsa:2048");

QDir sslDir(QString::fromStdString(getCertificateDirectory()));
QDir sslDir(getCertificateDirectory());
if (!sslDir.exists()) {
sslDir.mkpath(".");
}
Expand Down Expand Up @@ -159,35 +157,32 @@ 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
auto i = output.find_first_of('=');
if (i != std::string::npos) {
i++;
auto fingerprint = output.substr(
i, output.size() - i);
QString fingerprint = ret.second;
auto i = fingerprint.indexOf('=');
if (i != -1) {
fingerprint.remove(0, i+1);

Fingerprint::local().trust(QString::fromStdString(fingerprint), false);
Fingerprint::local().trust(fingerprint, false);
emit info(tr("SSL fingerprint generated."));
}
else {
emit error(tr("Failed to find SSL fingerprint."));
}
}

std::string SslCertificate::getCertificatePath()
QString SslCertificate::getCertificatePath()
{
return getCertificateDirectory() + QDir::separator().toLatin1() + kCertificateFilename;
return getCertificateDirectory() + QDir::separator() + kCertificateFilename;
}

std::string SslCertificate::getCertificateDirectory()
QString SslCertificate::getCertificateDirectory()
{
return m_ProfileDir + QDir::separator().toLatin1() + kSslDir;
return m_ProfileDir + QDir::separator() + kSslDir;
}

bool SslCertificate::isCertificateValid(const QString& path)
Expand All @@ -198,7 +193,7 @@ bool SslCertificate::isCertificateValid(const QString& path)

BIO* bio = BIO_new(BIO_s_file());

auto ret = BIO_read_filename(bio, path.toStdString().c_str());
auto ret = BIO_read_filename(bio, path.toLocal8Bit().constData());
if (!ret) {
emit info(tr("Could not read from default certificate file."));
BIO_free_all(bio);
Expand Down
8 changes: 4 additions & 4 deletions src/gui/src/SslCertificate.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,13 @@ public slots:
void generateFinished();

private:
std::pair<bool, std::string> runTool(const QStringList& args);
std::pair<bool, QString> runTool(const QStringList& args);
void generateFingerprint(const QString& certificateFilename);

std::string getCertificatePath();
std::string getCertificateDirectory();
QString getCertificatePath();
QString getCertificateDirectory();

bool isCertificateValid(const QString& path);
private:
std::string m_ProfileDir;
QString m_ProfileDir;
};
3 changes: 2 additions & 1 deletion src/lib/barrier/win32/DaemonApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#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"
Expand Down Expand Up @@ -257,7 +258,7 @@ DaemonApp::handleIpcMessage(const Event& e, void*)
switch (m->type()) {
case kIpcCommand: {
IpcCommandMessage* cm = static_cast<IpcCommandMessage*>(m);
String command = cm->command();
String command = Unicode::UTF8ToText(cm->command());

// if empty quotes, clear.
if (command == "\"\"") {
Expand Down
28 changes: 3 additions & 25 deletions src/lib/common/win32/DataDirectories.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,34 +16,12 @@
*/

#include "../DataDirectories.h"

#include <Shlobj.h>

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;
}
#include "KnownFolderPaths.h"

const std::string& DataDirectories::profile()
{
if (_profile.empty())
_profile = known_folder_path(FOLDERID_LocalAppData) + "\\Barrier";
_profile = localAppDataPath() + "\\Barrier";
return _profile;
}
const std::string& DataDirectories::profile(const std::string& path)
Expand All @@ -55,7 +33,7 @@ const std::string& DataDirectories::profile(const std::string& path)
const std::string& DataDirectories::global()
{
if (_global.empty())
_global = known_folder_path(FOLDERID_ProgramData) + "\\Barrier";
_global = programDataPath() + "\\Barrier";
return _global;
}
const std::string& DataDirectories::global(const std::string& path)
Expand Down
63 changes: 63 additions & 0 deletions src/lib/common/win32/KnownFolderPaths.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/

#include "KnownFolderPaths.h"

#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <Shlobj.h>

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);
}
24 changes: 24 additions & 0 deletions src/lib/common/win32/KnownFolderPaths.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/

#pragma once

#include <string>

std::string desktopPath();
std::string localAppDataPath();
std::string programDataPath();
3 changes: 2 additions & 1 deletion src/lib/ipc/IpcLogOutputter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "base/EventQueue.h"
#include "base/TMethodEventJob.h"
#include "base/TMethodJob.h"
#include "base/Unicode.h"

enum EIpcLogOutputter {
kBufferMaxSize = 1000,
Expand Down Expand Up @@ -196,7 +197,7 @@ IpcLogOutputter::sendBuffer()
return;
}

IpcLogLineMessage message(getChunk(kMaxSendLines));
IpcLogLineMessage message(Unicode::textToUTF8(getChunk(kMaxSendLines)));
m_sending = true;
m_ipcServer.send(message, kIpcClientGui);
m_sending = false;
Expand Down
Loading

0 comments on commit f6e2222

Please sign in to comment.