diff --git a/include/global/DataStore.hpp b/include/global/DataStore.hpp
index 3d0cd31..a72d962 100644
--- a/include/global/DataStore.hpp
+++ b/include/global/DataStore.hpp
@@ -95,6 +95,7 @@ namespace Configs {
bool sub_clear = false;
bool sub_insecure = false;
int sub_auto_update = -30;
+ bool sub_send_hwid = false;
// Security
bool skip_cert = false;
diff --git a/include/ui/setting/dialog_basic_settings.ui b/include/ui/setting/dialog_basic_settings.ui
index bb06225..e71e833 100644
--- a/include/ui/setting/dialog_basic_settings.ui
+++ b/include/ui/setting/dialog_basic_settings.ui
@@ -551,6 +551,13 @@
+ -
+
+
+ Includes sending HWID, model, and OS version
+
+
+
-
diff --git a/src/global/Configs.cpp b/src/global/Configs.cpp
index ad509ce..1a41674 100644
--- a/src/global/Configs.cpp
+++ b/src/global/Configs.cpp
@@ -279,6 +279,7 @@ namespace Configs {
_add(new configItem("sub_clear", &sub_clear, itemType::boolean));
_add(new configItem("sub_insecure", &sub_insecure, itemType::boolean));
_add(new configItem("sub_auto_update", &sub_auto_update, itemType::integer));
+ _add(new configItem("sub_send_hwid", &sub_send_hwid, itemType::boolean));
_add(new configItem("start_minimal", &start_minimal, itemType::boolean));
_add(new configItem("max_log_line", &max_log_line, itemType::integer));
_add(new configItem("splitter_state", &splitter_state, itemType::string));
diff --git a/src/global/HTTPRequestHelper.cpp b/src/global/HTTPRequestHelper.cpp
index 1f7ff81..dd01bda 100644
--- a/src/global/HTTPRequestHelper.cpp
+++ b/src/global/HTTPRequestHelper.cpp
@@ -1,3 +1,9 @@
+#include
+#ifdef Q_OS_WIN
+ #include
+#endif
+#undef boolean
+
#include "include/global/HTTPRequestHelper.hpp"
#include
@@ -13,6 +19,91 @@
namespace Configs_network {
+ namespace {
+ struct DeviceDetails {
+ QString hwid;
+ QString os;
+ QString osVersion;
+ QString model;
+ };
+
+#ifdef Q_OS_WIN
+ static QString readRegistryStringValue(const QString &keyPath, const QString &valueName) {
+ HKEY hKey = nullptr;
+ std::wstring keyPathW = keyPath.toStdWString();
+ LONG res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, keyPathW.c_str(), 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
+ if (res != ERROR_SUCCESS) return QString();
+ DWORD type = 0;
+ DWORD cbData = 0;
+ res = RegQueryValueExW(hKey, (LPCWSTR)valueName.utf16(), nullptr, &type, nullptr, &cbData);
+ if (res != ERROR_SUCCESS || type != REG_SZ) {
+ RegCloseKey(hKey);
+ return QString();
+ }
+ std::vector buffer(cbData/sizeof(wchar_t) + 1);
+ res = RegQueryValueExW(hKey, (LPCWSTR)valueName.utf16(), nullptr, nullptr, reinterpret_cast(buffer.data()), &cbData);
+ if (res != ERROR_SUCCESS) {
+ RegCloseKey(hKey);
+ return QString();
+ }
+ RegCloseKey(hKey);
+ return QString::fromWCharArray(buffer.data());
+ }
+#endif
+
+ static DeviceDetails GetDeviceDetails() {
+ DeviceDetails details;
+
+#ifdef Q_OS_WIN
+ const QString regPath = QString::fromUtf8("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\SoftwareProtectionPlatform\\Plugins\\Objects\\msft:rm/algorithm/hwid/4.0");
+ const QString valueName = QString::fromUtf8("ModuleId");
+ details.hwid = readRegistryStringValue(regPath, valueName);
+
+ if (details.hwid.isEmpty()) {
+ auto productId = QSysInfo::machineUniqueId();
+ if (productId.isEmpty()) productId = QSysInfo::productType().toUtf8();
+ details.hwid = QString("%1-%2").arg(QSysInfo::machineHostName(), QString::fromUtf8(productId));
+ }
+
+ details.os = QStringLiteral("Windows");
+
+ VersionInfo info;
+ WinVersion::GetVersion(info);
+ details.osVersion = QString("%1.%2.%3").arg(info.Major).arg(info.Minor).arg(info.BuildNum);
+
+ details.model = QSysInfo::prettyProductName();
+#elif defined(Q_OS_LINUX)
+ QString mid;
+ QFile f1("/etc/machine-id");
+ if (f1.exists() && f1.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ mid = QString::fromUtf8(f1.readAll()).trimmed();
+ f1.close();
+ } else {
+ QFile f2("/var/lib/dbus/machine-id");
+ if (f2.exists() && f2.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ mid = QString::fromUtf8(f2.readAll()).trimmed();
+ f2.close();
+ }
+ }
+ details.hwid = mid;
+ details.os = QStringLiteral("Linux");
+ details.osVersion = QSysInfo::kernelVersion();
+ details.model = QSysInfo::prettyProductName();
+#elif defined(Q_OS_MACOS)
+ details.hwid = QSysInfo::machineUniqueId();
+ details.os = QStringLiteral("macOS");
+ details.osVersion = QSysInfo::productVersion();
+ details.model = QSysInfo::prettyProductName();
+#else
+ details.hwid = QSysInfo::machineUniqueId();
+ details.os = QSysInfo::productType();
+ details.osVersion = QSysInfo::productVersion();
+ details.model = QSysInfo::prettyProductName();
+#endif
+ return details;
+ }
+}
+
HTTPResponse NetworkRequestHelper::HttpGet(const QString &url) {
QNetworkRequest request;
QNetworkAccessManager accessManager;
@@ -35,6 +126,15 @@ namespace Configs_network {
c.setPeerVerifyMode(QSslSocket::PeerVerifyMode::VerifyNone);
request.setSslConfiguration(c);
}
+ //Attach HWID and device info headers if enabled in settings
+ if (Configs::dataStore->sub_send_hwid && !request.url().toString().contains("/throneproj/")) {
+ auto details = GetDeviceDetails();
+
+ if (!details.hwid.isEmpty()) request.setRawHeader("x-hwid", details.hwid.toUtf8());
+ if (!details.os.isEmpty()) request.setRawHeader("x-device-os", details.os.toUtf8());
+ if (!details.osVersion.isEmpty()) request.setRawHeader("x-ver-os", details.osVersion.toUtf8());
+ if (!details.model.isEmpty()) request.setRawHeader("x-device-model", details.model.toUtf8());
+ }
//
auto _reply = accessManager.get(request);
connect(_reply, &QNetworkReply::sslErrors, _reply, [](const QList &errors) {
diff --git a/src/ui/setting/dialog_basic_settings.cpp b/src/ui/setting/dialog_basic_settings.cpp
index 76c2d6c..34fe948 100644
--- a/src/ui/setting/dialog_basic_settings.cpp
+++ b/src/ui/setting/dialog_basic_settings.cpp
@@ -116,6 +116,7 @@ DialogBasicSettings::DialogBasicSettings(QWidget *parent)
D_LOAD_BOOL(sub_use_proxy)
D_LOAD_BOOL(sub_clear)
D_LOAD_BOOL(sub_insecure)
+ D_LOAD_BOOL(sub_send_hwid)
D_LOAD_INT_ENABLE(sub_auto_update, sub_auto_update_enable)
// Core
@@ -200,6 +201,7 @@ void DialogBasicSettings::accept() {
D_SAVE_BOOL(sub_use_proxy)
D_SAVE_BOOL(sub_clear)
D_SAVE_BOOL(sub_insecure)
+ D_SAVE_BOOL(sub_send_hwid)
D_SAVE_INT_ENABLE(sub_auto_update, sub_auto_update_enable)
// Core