Merge pull request #1340 from p12tic/use-utf8

Use UTF8 internally and convert to UTF16 at the edge.
This commit is contained in:
Povilas Kanapickas 2021-10-30 01:22:09 +03:00 committed by GitHub
commit fce7615e42
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 242 additions and 156 deletions

View File

@ -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;
}

View File

@ -16,7 +16,8 @@
*/
#include "Fingerprint.h"
#include "QUtility.h"
#include "common/DataDirectories.h"
#include <QDir>
#include <QTextStream>
@ -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);
}

View File

@ -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

View File

@ -31,6 +31,7 @@
#include "ProcessorArch.h"
#include "SslCertificate.h"
#include "ShutdownCh.h"
#include "common/DataDirectories.h"
#include <QtCore>
#include <QtGui>
@ -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))

View File

@ -19,7 +19,6 @@
#include "ProcessorArch.h"
#include "CommandProcess.h"
#include "common/DataDirectories.h"
#if defined(Q_OS_LINUX)
#include <QProcess>
@ -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());
}

View File

@ -29,4 +29,3 @@ QString hash(const QString& string);
QString getFirstMacAddress();
qProcessorArch getProcessorArch();
QString getOSInformation();
QString profilePath();

View File

@ -17,7 +17,7 @@
#include "SslCertificate.h"
#include "Fingerprint.h"
#include "QUtility.h"
#include "common/DataDirectories.h"
#include <QProcess>
#include <QDir>
@ -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<bool, QString> SslCertificate::runTool(const QStringList& args)
std::pair<bool, std::string> SslCertificate::runTool(const QStringList& args)
{
QString program;
#if defined(Q_OS_WIN)
@ -68,15 +68,17 @@ std::pair<bool, QString> 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<bool, QString> 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);

View File

@ -36,13 +36,13 @@ signals:
void generateFinished();
private:
std::pair<bool, QString> runTool(const QStringList& args);
std::pair<bool, std::string> 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;
};

View File

@ -18,6 +18,7 @@
#include "barrier/DropHelper.h"
#include "base/Log.h"
#include "io/fstream.h"
#include <fstream>
@ -35,7 +36,7 @@ DropHelper::writeToDir(const String& destination, DragFileList& fileList, String
dropTarget.append("/");
#endif
dropTarget.append(fileList.at(0).getFilename());
file.open(dropTarget.c_str(), std::ios::out | std::ios::binary);
barrier::open_utf8_path(file, dropTarget, std::ios::out | std::ios::binary);
if (!file.is_open()) {
LOG((CLOG_ERR "drop file failed: can not open %s", dropTarget.c_str()));
}

View File

@ -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<IpcCommandMessage*>(m);
String command = Unicode::UTF8ToText(cm->command());
String command = cm->command();
// if empty quotes, clear.
if (command == "\"\"") {

View File

@ -20,7 +20,7 @@
#include "base/TMethodJob.h"
#include "arch/Arch.h"
#include "base/String.h"
#include "io/fstream.h"
#include <fstream>
enum EFileLogOutputter {
@ -260,7 +260,7 @@ FileLogOutputter::write(ELevel level, const char *message)
bool moveFile = false;
std::ofstream m_handle;
m_handle.open(m_fileName.c_str(), std::fstream::app);
barrier::open_utf8_path(m_handle, m_fileName, std::fstream::app);
if (m_handle.is_open() && m_handle.fail() != true) {
m_handle << message << std::endl;

View File

@ -16,12 +16,26 @@
*/
#include "../DataDirectories.h"
#include "KnownFolderPaths.h"
#include "encoding_utilities.h"
#include <Shlobj.h>
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 = win_wchar_to_utf8(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 +47,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)

View File

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

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <string>
std::string desktopPath();
std::string localAppDataPath();
std::string programDataPath();

View File

@ -0,0 +1,37 @@
/*
barrier -- mouse and keyboard sharing utility
Copyright (C) Barrier contributors
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 "encoding_utilities.h"
#include <stringapiset.h>
std::string win_wchar_to_utf8(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::vector<WCHAR> utf8_to_win_char(const std::string& str)
{
int result_len = MultiByteToWideChar(CP_UTF8, 0, str.data(), str.size(), NULL, 0);
std::vector<WCHAR> result;
result.resize(result_len + 1, 0);
MultiByteToWideChar(CP_UTF8, 0, str.data(), str.size(), result.data(), result_len);
return result;
}

View File

@ -0,0 +1,28 @@
/*
barrier -- mouse and keyboard sharing utility
Copyright (C) Barrier contributors
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/>.
*/
#ifndef BARRIER_LIB_COMMON_WIN32_ENCODING_UTILITIES_H
#define BARRIER_LIB_COMMON_WIN32_ENCODING_UTILITIES_H
#include <windows.h>
#include <string>
#include <vector>
std::string win_wchar_to_utf8(const WCHAR* utfStr);
std::vector<WCHAR> utf8_to_win_char(const std::string& str);
#endif

57
src/lib/io/fstream.cpp Normal file
View File

@ -0,0 +1,57 @@
/*
barrier -- mouse and keyboard sharing utility
Copyright (C) Barrier contributors
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 "fstream.h"
#if SYSAPI_WIN32
#include "common/win32/encoding_utilities.h"
#endif
#include <fstream>
namespace barrier {
namespace {
template<class Stream>
void open_utf8_path_impl(Stream& stream, const std::string& path, std::ios_base::openmode mode)
{
#if SYSAPI_WIN32
// on Windows we need to use a private constructor from wchar_t* string.
auto wchar_path = utf8_to_win_char(path);
stream.open(wchar_path.data(), mode);
#else
stream.open(path.c_str(), mode);
#endif
}
} // namespace
void open_utf8_path(std::ifstream& stream, const std::string& path, std::ios_base::openmode mode)
{
open_utf8_path_impl(stream, path, mode);
}
void open_utf8_path(std::ofstream& stream, const std::string& path, std::ios_base::openmode mode)
{
open_utf8_path_impl(stream, path, mode);
}
void open_utf8_path(std::fstream& stream, const std::string& path, std::ios_base::openmode mode)
{
open_utf8_path_impl(stream, path, mode);
}
} // namespace barrier

35
src/lib/io/fstream.h Normal file
View File

@ -0,0 +1,35 @@
/*
barrier -- mouse and keyboard sharing utility
Copyright (C) Barrier contributors
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/>.
*/
#ifndef BARRIER_LIB_IO_FSTREAM_H
#define BARRIER_LIB_IO_FSTREAM_H
#include <iosfwd>
#include <ios>
namespace barrier {
void open_utf8_path(std::ifstream& stream, const std::string& path,
std::ios_base::openmode mode = std::ios_base::in);
void open_utf8_path(std::ofstream& stream, const std::string& path,
std::ios_base::openmode mode = std::ios_base::out);
void open_utf8_path(std::fstream& stream, const std::string& path,
std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out);
} // namespace barrier
#endif

View File

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

View File

@ -25,6 +25,7 @@
#include "base/Log.h"
#include "base/String.h"
#include "common/DataDirectories.h"
#include "io/fstream.h"
#include <openssl/ssl.h>
#include <openssl/err.h>
@ -708,7 +709,7 @@ SecureSocket::verifyCertFingerprint()
// check if this fingerprint exist
std::string fileLine;
std::ifstream file;
file.open(trustedServersFilename.c_str());
barrier::open_utf8_path(file, trustedServersFilename);
if (!file.is_open()) {
LOG((CLOG_NOTE "Unable to open trustedServersFile: %s", trustedServersFilename.c_str() ));

View File

@ -41,9 +41,9 @@
#include "base/IEventQueue.h"
#include "base/TMethodEventJob.h"
#include "base/TMethodJob.h"
#include "common/win32/KnownFolderPaths.h"
#include <string.h>
#include <Shlobj.h>
#include <comutil.h>
#include <algorithm>
@ -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;