Skip to content

Commit

Permalink
Use ansi codepage for internal multibyte strings on windows (fixes de…
Browse files Browse the repository at this point in the history
  • Loading branch information
albertony committed Dec 11, 2020
1 parent e032d14 commit 818c3b5
Show file tree
Hide file tree
Showing 15 changed files with 312 additions and 76 deletions.
14 changes: 7 additions & 7 deletions src/gui/src/CommandProcess.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/

#include "CommandProcess.h"
#include "QUtility.h"

#include <QProcess>
#include <stdexcept>
Expand All @@ -32,29 +33,28 @@ QString CommandProcess::run()
QProcess process;
process.setReadChannel(QProcess::StandardOutput);
process.start(m_Command, m_Arguments);
bool success = process.waitForStarted();

bool success = process.waitForStarted();
QString output, error;
if (success)
{
if (!m_Input.isEmpty()) {
process.write(m_Input.toStdString().c_str());
process.write(toStdString(m_Input).c_str());
}

if (process.waitForFinished()) {
output = process.readAllStandardOutput().trimmed();
error = process.readAllStandardError().trimmed();
output = fromByteArrayString(process.readAllStandardOutput().trimmed());
error = fromByteArrayString(process.readAllStandardError().trimmed());
}
}

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

emit finished();
Expand Down
4 changes: 2 additions & 2 deletions src/gui/src/Fingerprint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

#include "Fingerprint.h"

#include "common/DataDirectories.h"
#include "QUtility.h"

#include <QDir>
#include <QTextStream>
Expand Down Expand Up @@ -125,7 +125,7 @@ void Fingerprint::persistDirectory()

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

return QString("%1/%2")
.arg(profileDir)
Expand Down
5 changes: 3 additions & 2 deletions src/gui/src/IpcClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*/

#include "IpcClient.h"
#include "QUtility.h"
#include <QTcpSocket>
#include <QHostAddress>
#include <iostream>
Expand Down Expand Up @@ -104,8 +105,8 @@ void IpcClient::sendCommand(const QString& command, ElevateMode const elevate)

stream.writeRawData(kIpcMsgCommand, 4);

std::string stdStringCommand = command.toStdString();
const char* charCommand = stdStringCommand.c_str();
std::string stringCommand = toUtf8String(command);
const char* charCommand = stringCommand.c_str();
int length = (int)strlen(charCommand);

char lenBuf[4];
Expand Down
3 changes: 1 addition & 2 deletions src/gui/src/MainWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
#include "ProcessorArch.h"
#include "SslCertificate.h"
#include "ShutdownCh.h"
#include "common/DataDirectories.h"

#include <QtCore>
#include <QtGui>
Expand Down Expand Up @@ -526,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::fromStdString("\"" + DataDirectories::profile() + "\"");
args << "--profile-dir \"" << profilePath() << "\"";
#endif

if ((barrierType() == barrierClient && !clientArgs(args, app))
Expand Down
55 changes: 55 additions & 0 deletions src/gui/src/QUtility.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#include "ProcessorArch.h"
#include "CommandProcess.h"
#include "common/DataDirectories.h"

#if defined(Q_OS_LINUX)
#include <QProcess>
Expand All @@ -27,6 +28,7 @@
#if defined(Q_OS_WIN)
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include "common/win32/StringConverters.h"
#endif

void setIndexFromItemData(QComboBox* comboBox, const QVariant& itemData)
Expand Down Expand Up @@ -113,3 +115,56 @@ QString getOSInformation()

return result;
}

QString fromStdString(const std::string& str)
{
// Convert from ANSI encoded std::string on Windows, not UTF-8 which is what QString::fromStdString does.
#if defined(Q_OS_WIN)
return QString::fromStdWString(wide_from_ansi(str));
#else
QString::fromStdString(str);
#endif
}

std::string toStdString(const QString& str)
{
// Convert to ANSI encoded std::string on Windows, not UTF-8 which is what QString::toStdString does.
#if defined(Q_OS_WIN)
return ansi_from_wide(str.toStdWString());
#else
str.toStdString();
#endif
}

std::string toUtf8String(const QString& str)
{
// Convert to UTF-8 encoded std::string, which is what QString::toStdString does.
// Just to be explicit when UTF-8 is intended (e.g. for network communication), and not
// just a standard std::string, which may or may not be UTF-8 (usually ANSI on Windows).
return str.toStdString();
}

QString fromByteArrayString(const QByteArray& str)
{
// Convert from ANSI encoded raw byte string on Windows, not UTF-8 which is what QString(QByteArray) does.
#if defined(Q_OS_WIN)
return QString::fromStdWString(wide_from_ansi(str.constData(), str.count()));
#else
return QString::fromStdString(str);
#endif
}

QByteArray toByteArrayString(const QString& str)
{
// Convert to ANSI encoded raw byte string on Windows, not UTF-8 which is what QString::toUtf8 does.
#if defined(Q_OS_WIN)
return QByteArray::fromStdString(ansi_from_wide(str.toStdWString()));
#else
return str.toUtf8();
#endif
}

QString profilePath()
{
return fromStdString(DataDirectories::profile());
}
12 changes: 12 additions & 0 deletions src/gui/src/QUtility.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

#include "ProcessorArch.h"

#include <QString>
#include <QByteArray>
#include <QComboBox>
#include <QVariant>
#include <QCryptographicHash>
Expand All @@ -29,3 +31,13 @@ QString hash(const QString& string);
QString getFirstMacAddress();
qProcessorArch getProcessorArch();
QString getOSInformation();

QString fromStdString(const std::string& str);
std::string toStdString(const QString& str);

QString fromByteArrayString(const QByteArray& str);
QByteArray toByteArrayString(const QString& str);

std::string toUtf8String(const QString& str);

QString profilePath();
47 changes: 21 additions & 26 deletions src/gui/src/SslCertificate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

#include "SslCertificate.h"
#include "Fingerprint.h"
#include "common/DataDirectories.h"
#include "QUtility.h"

#include <QProcess>
#include <QDir>
Expand All @@ -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 = profilePath();
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 @@ -72,13 +72,11 @@ std::pair<bool, std::string> SslCertificate::runTool(const QStringList& args)
process.start(program, args);

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

QString standardError;
QString standardOutput, standardError;
if (success && process.waitForFinished())
{
output = process.readAllStandardOutput().trimmed().toStdString();
standardError = process.readAllStandardError().trimmed();
standardOutput = fromByteArrayString(process.readAllStandardOutput().trimmed());
standardError = fromByteArrayString(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, standardError};
}

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);

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, toStdString(path).c_str());
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;
};
9 changes: 8 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 "common/win32/StringConverters.h"

#include "arch/win32/ArchMiscWindows.h"
#include "arch/win32/XArchWindows.h"
Expand Down Expand Up @@ -250,14 +251,20 @@ DaemonApp::logFilename()
return logFilename;
}

static std::string from_ipc_string(const std::string& msg)
{
// Client sends UTF-8 encoded narrow strings (QString::toStdString()), convert to ANSI encoding used
return ansi_from_utf8(msg);
}

void
DaemonApp::handleIpcMessage(const Event& e, void*)
{
IpcMessage* m = static_cast<IpcMessage*>(e.getDataObject());
switch (m->type()) {
case kIpcCommand: {
IpcCommandMessage* cm = static_cast<IpcCommandMessage*>(m);
String command = cm->command();
String command = from_ipc_string(cm->command());

// if empty quotes, clear.
if (command == "\"\"") {
Expand Down
Loading

0 comments on commit 818c3b5

Please sign in to comment.