Files
amnezia-client/client/utilities.cpp
T

247 lines
6.7 KiB
C++
Raw Normal View History

2020-12-26 15:03:51 +03:00
#include <QCoreApplication>
2020-12-26 23:17:20 +03:00
#include <QDebug>
2020-12-26 15:03:51 +03:00
#include <QDir>
#include <QProcess>
2021-04-04 23:12:36 +03:00
#include <QRandomGenerator>
#include <QRegularExpression>
2020-12-26 15:03:51 +03:00
#include <QStandardPaths>
#include <QUrl>
#include <QJsonDocument>
#include <QJsonObject>
2020-12-26 15:03:51 +03:00
#include "utilities.h"
2023-08-23 00:20:59 +05:00
#include "version.h"
2020-12-26 15:03:51 +03:00
2021-04-04 23:12:36 +03:00
QString Utils::getRandomString(int len)
{
const QString possibleCharacters("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
QString randomString;
2023-08-23 00:20:59 +05:00
for (int i = 0; i < len; ++i) {
2021-04-04 23:12:36 +03:00
quint32 index = QRandomGenerator::global()->generate() % possibleCharacters.length();
QChar nextChar = possibleCharacters.at(index);
randomString.append(nextChar);
}
return randomString;
}
2020-12-26 15:03:51 +03:00
QString Utils::VerifyJsonString(const QString &source)
{
QJsonParseError error;
QJsonDocument doc = QJsonDocument::fromJson(source.toUtf8(), &error);
Q_UNUSED(doc)
if (error.error == QJsonParseError::NoError) {
return "";
} else {
qDebug() << "WARNING: Json parse returns: " + error.errorString();
return error.errorString();
}
}
QJsonObject Utils::JsonFromString(const QString &string)
{
auto removeComment = string.trimmed();
if (removeComment != string.trimmed()) {
qDebug() << "Some comments have been removed from the json.";
}
QJsonDocument doc = QJsonDocument::fromJson(removeComment.toUtf8());
return doc.object();
}
QString Utils::SafeBase64Decode(QString string)
{
QByteArray ba = string.replace(QChar('-'), QChar('+')).replace(QChar('_'), QChar('/')).toUtf8();
return QByteArray::fromBase64(ba, QByteArray::Base64Option::OmitTrailingEquals);
}
QString Utils::JsonToString(const QJsonObject &json, QJsonDocument::JsonFormat format)
{
QJsonDocument doc;
doc.setObject(json);
return doc.toJson(format);
}
QString Utils::JsonToString(const QJsonArray &array, QJsonDocument::JsonFormat format)
{
QJsonDocument doc;
doc.setArray(array);
return doc.toJson(format);
}
2023-08-23 00:20:59 +05:00
bool Utils::initializePath(const QString &path)
2020-12-26 23:17:20 +03:00
{
QDir dir;
if (!dir.mkpath(path)) {
qWarning().noquote() << QString("Cannot initialize path: '%1'").arg(path);
return false;
}
return true;
}
2023-08-23 00:20:59 +05:00
bool Utils::createEmptyFile(const QString &path)
2020-12-26 23:17:20 +03:00
{
QFile f(path);
return f.open(QIODevice::WriteOnly | QIODevice::Truncate);
2020-12-26 15:03:51 +03:00
}
2023-08-23 00:20:59 +05:00
QString Utils::executable(const QString &baseName, bool absPath)
2020-12-26 15:03:51 +03:00
{
QString ext;
#ifdef Q_OS_WIN
ext = ".exe";
#endif
const QString fileName = baseName + ext;
if (!absPath) {
return fileName;
}
return QCoreApplication::applicationDirPath() + "/" + fileName;
}
2023-08-23 00:20:59 +05:00
QString Utils::usrExecutable(const QString &baseName)
2021-08-04 10:08:00 -07:00
{
if (QFileInfo::exists("/usr/sbin/" + baseName))
return ("/usr/sbin/" + baseName);
else
return ("/usr/bin/" + baseName);
}
bool Utils::processIsRunning(const QString &fileName, const bool fullFlag)
2020-12-26 15:03:51 +03:00
{
#ifdef Q_OS_WIN
QProcess process;
process.setReadChannel(QProcess::StandardOutput);
2021-01-06 17:12:24 +03:00
process.setProcessChannelMode(QProcess::MergedChannels);
2023-08-23 00:20:59 +05:00
process.start("wmic.exe",
QStringList() << "/OUTPUT:STDOUT"
<< "PROCESS"
<< "get"
<< "Caption");
2020-12-26 15:03:51 +03:00
process.waitForStarted();
process.waitForFinished();
QString processData(process.readAll());
2023-08-23 00:20:59 +05:00
QStringList processList = processData.split(QRegularExpression("[\r\n]"), Qt::SkipEmptyParts);
foreach (const QString &rawLine, processList) {
2020-12-26 15:03:51 +03:00
const QString line = rawLine.simplified();
if (line.isEmpty()) {
continue;
}
if (line == fileName) {
return true;
}
}
return false;
2021-09-15 08:03:28 -07:00
#elif defined(Q_OS_IOS)
return false;
2020-12-26 15:03:51 +03:00
#else
QProcess process;
process.setProcessChannelMode(QProcess::MergedChannels);
process.start("pgrep", QStringList({ fullFlag ? "-f" : "", fileName }));
2020-12-26 15:03:51 +03:00
process.waitForFinished();
if (process.exitStatus() == QProcess::NormalExit) {
if (fullFlag) {
return (process.readLine().toUInt() > 0);
} else {
return (process.readAll().toUInt() > 0);
}
2020-12-26 15:03:51 +03:00
}
return false;
#endif
}
2021-03-18 18:45:08 +03:00
void Utils::killProcessByName(const QString &name)
2023-08-23 00:20:59 +05:00
{
2021-03-18 18:45:08 +03:00
qDebug().noquote() << "Kill process" << name;
#ifdef Q_OS_WIN
2023-05-20 18:44:19 +01:00
QProcess::execute("taskkill", QStringList() << "/IM" << name << "/F");
2021-09-15 08:03:28 -07:00
#elif defined Q_OS_IOS
return;
2021-03-18 18:45:08 +03:00
#else
QProcess::execute(QString("pkill %1").arg(name));
#endif
}
2022-08-10 22:15:00 +03:00
QString Utils::openVpnExecPath()
{
#ifdef Q_OS_WIN
return Utils::executable("openvpn/openvpn", true);
#elif defined Q_OS_LINUX
2023-08-08 18:16:01 -04:00
// We have service that runs OpenVPN on Linux. We need to make same
// path for client and service.
return Utils::executable("../../client/bin/openvpn", true);
2022-08-10 22:15:00 +03:00
#else
return Utils::executable("/openvpn", true);
#endif
}
QString Utils::wireguardExecPath()
{
#ifdef Q_OS_WIN
return Utils::executable("wireguard/wireguard-service", true);
#elif defined Q_OS_LINUX
return Utils::usrExecutable("wg-quick");
2023-07-15 14:19:48 -07:00
#elif defined Q_OS_MAC
2022-08-10 22:15:00 +03:00
return Utils::executable("/wireguard", true);
2023-07-15 14:19:48 -07:00
#else
return {};
2022-08-10 22:15:00 +03:00
#endif
}
QString Utils::certUtilPath()
{
#ifdef Q_OS_WIN
QString winPath = QString::fromUtf8(qgetenv("windir"));
2023-03-19 11:58:22 +00:00
return winPath + "\\system32\\certutil.exe";
2022-08-10 22:15:00 +03:00
#else
return "";
#endif
}
2024-03-27 11:02:34 +00:00
QString Utils::tun2socksPath()
{
#ifdef Q_OS_WIN
return Utils::executable("xray/tun2socks", true);
#elif defined Q_OS_LINUX
// We have service that runs OpenVPN on Linux. We need to make same
// path for client and service.
return Utils::executable("../../client/bin/tun2socks", true);
#else
return Utils::executable("/tun2socks", true);
#endif
}
2021-03-18 18:45:08 +03:00
#ifdef Q_OS_WIN
// Inspired from http://stackoverflow.com/a/15281070/1529139
// and http://stackoverflow.com/q/40059902/1529139
bool Utils::signalCtrl(DWORD dwProcessId, DWORD dwCtrlEvent)
{
bool success = false;
DWORD thisConsoleId = GetCurrentProcessId();
// Leave current console if it exists
// (otherwise AttachConsole will return ERROR_ACCESS_DENIED)
bool consoleDetached = (FreeConsole() != FALSE);
2023-08-23 00:20:59 +05:00
if (AttachConsole(dwProcessId) != FALSE) {
2021-03-18 18:45:08 +03:00
// Add a fake Ctrl-C handler for avoid instant kill is this console
// WARNING: do not revert it or current program will be also killed
SetConsoleCtrlHandler(nullptr, true);
success = (GenerateConsoleCtrlEvent(dwCtrlEvent, 0) != FALSE);
FreeConsole();
}
2023-08-23 00:20:59 +05:00
if (consoleDetached) {
2021-03-18 18:45:08 +03:00
// Create a new console if previous was deleted by OS
2023-08-23 00:20:59 +05:00
if (AttachConsole(thisConsoleId) == FALSE) {
2021-03-18 18:45:08 +03:00
int errorCode = GetLastError();
if (errorCode == 31) // 31=ERROR_GEN_FAILURE
{
AllocConsole();
}
}
}
return success;
}
2021-09-24 13:14:35 +03:00
2021-03-18 18:45:08 +03:00
#endif