mirror of
				https://github.com/ciphervance/supercell-wx.git
				synced 2025-10-31 17:20:06 +00:00 
			
		
		
		
	Merge pull request #324 from AdenKoperczak/high_privilege_warning
High privilege warning
This commit is contained in:
		
						commit
						6ef24bf4ed
					
				
					 7 changed files with 210 additions and 14 deletions
				
			
		|  | @ -51,9 +51,11 @@ find_package(Qt${QT_VERSION_MAJOR} | ||||||
| set(SRC_EXE_MAIN source/scwx/qt/main/main.cpp) | set(SRC_EXE_MAIN source/scwx/qt/main/main.cpp) | ||||||
| 
 | 
 | ||||||
| set(HDR_MAIN source/scwx/qt/main/application.hpp | set(HDR_MAIN source/scwx/qt/main/application.hpp | ||||||
|  |              source/scwx/qt/main/check_privilege.hpp | ||||||
|              source/scwx/qt/main/main_window.hpp |              source/scwx/qt/main/main_window.hpp | ||||||
|              source/scwx/qt/main/process_validation.hpp) |              source/scwx/qt/main/process_validation.hpp) | ||||||
| set(SRC_MAIN source/scwx/qt/main/application.cpp | set(SRC_MAIN source/scwx/qt/main/application.cpp | ||||||
|  |              source/scwx/qt/main/check_privilege.cpp | ||||||
|              source/scwx/qt/main/main_window.cpp |              source/scwx/qt/main/main_window.cpp | ||||||
|              source/scwx/qt/main/process_validation.cpp) |              source/scwx/qt/main/process_validation.cpp) | ||||||
| set(UI_MAIN  source/scwx/qt/main/main_window.ui) | set(UI_MAIN  source/scwx/qt/main/main_window.ui) | ||||||
|  |  | ||||||
							
								
								
									
										136
									
								
								scwx-qt/source/scwx/qt/main/check_privilege.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										136
									
								
								scwx-qt/source/scwx/qt/main/check_privilege.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,136 @@ | ||||||
|  | #include <scwx/qt/settings/general_settings.hpp> | ||||||
|  | #include <scwx/qt/main/check_privilege.hpp> | ||||||
|  | #include <QtGlobal> | ||||||
|  | #include <QStandardPaths> | ||||||
|  | #include <filesystem> | ||||||
|  | #include <QObject> | ||||||
|  | #include <QMessageBox> | ||||||
|  | #include <QCheckBox> | ||||||
|  | 
 | ||||||
|  | #ifdef _WIN32 | ||||||
|  | #   include <windows.h> | ||||||
|  | #else | ||||||
|  | #   include <unistd.h> | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | namespace scwx::qt::main | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | bool is_high_privilege() | ||||||
|  | { | ||||||
|  | #if defined(_WIN32) | ||||||
|  |    bool            isAdmin = false; | ||||||
|  |    HANDLE          token   = NULL; | ||||||
|  |    TOKEN_ELEVATION elevation; | ||||||
|  |    DWORD           elevationSize = sizeof(TOKEN_ELEVATION); | ||||||
|  | 
 | ||||||
|  |    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) | ||||||
|  |    { | ||||||
|  |       return false; | ||||||
|  |    } | ||||||
|  |    if (!GetTokenInformation( | ||||||
|  |           token, TokenElevation, &elevation, elevationSize, &elevationSize)) | ||||||
|  |    { | ||||||
|  |       CloseHandle(token); | ||||||
|  |       return false; | ||||||
|  |    } | ||||||
|  |    isAdmin = elevation.TokenIsElevated; | ||||||
|  |    CloseHandle(token); | ||||||
|  |    return isAdmin; | ||||||
|  | #elif defined(Q_OS_UNIX) | ||||||
|  |    // On UNIX root is always uid 0. On Linux this is enforced by the kernel.
 | ||||||
|  |    return geteuid() == 0; | ||||||
|  | #else | ||||||
|  |    return false; | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #if defined(_WIN32) | ||||||
|  | static const QString message = QObject::tr( | ||||||
|  |    "Supercell Wx has been run with administrator permissions. It is " | ||||||
|  |    "recommended to run it without administrator permissions Do you wish to " | ||||||
|  |    "continue?"); | ||||||
|  | #elif defined(Q_OS_UNIX) | ||||||
|  | static const QString message = QObject::tr( | ||||||
|  |    "Supercell Wx has been run as root. It is recommended to run it as a normal " | ||||||
|  |    "user. Do you wish to continue?"); | ||||||
|  | #else | ||||||
|  | static const QString message = QObject::tr(""); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | static const QString title = QObject::tr("Supercell Wx"); | ||||||
|  | static const QString checkBoxText = | ||||||
|  |    QObject::tr("Do not show this warning again."); | ||||||
|  | 
 | ||||||
|  | class PrivilegeChecker::Impl | ||||||
|  | { | ||||||
|  | public: | ||||||
|  |    explicit Impl() : | ||||||
|  |        highPrivilege_ {is_high_privilege()}, | ||||||
|  |        dialog_ {QMessageBox::Icon::Warning, title, message}, | ||||||
|  |        checkBox_(new QCheckBox(checkBoxText, &dialog_)) | ||||||
|  |    { | ||||||
|  |       const std::string appDataPath { | ||||||
|  |          QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) | ||||||
|  |             .toStdString()}; | ||||||
|  |       hasAppData_ = std::filesystem::exists(appDataPath); | ||||||
|  | 
 | ||||||
|  |       dialog_.setStandardButtons(QMessageBox::Yes | QMessageBox::No); | ||||||
|  |       dialog_.setDefaultButton(QMessageBox::No); | ||||||
|  |       dialog_.setCheckBox(checkBox_); | ||||||
|  |    }; | ||||||
|  | 
 | ||||||
|  |    bool hasAppData_; | ||||||
|  |    bool firstCheckCheckBoxState_ {true}; | ||||||
|  |    bool highPrivilege_; | ||||||
|  | 
 | ||||||
|  |    QMessageBox dialog_; | ||||||
|  |    QCheckBox*  checkBox_; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | PrivilegeChecker::PrivilegeChecker() : | ||||||
|  |     p(std::make_unique<PrivilegeChecker::Impl>()) | ||||||
|  | { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | PrivilegeChecker::~PrivilegeChecker() = default; | ||||||
|  | 
 | ||||||
|  | bool PrivilegeChecker::pre_settings_check() | ||||||
|  | { | ||||||
|  |    if (p->hasAppData_ || !p->highPrivilege_) | ||||||
|  |    { | ||||||
|  |       return false; | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    const int result            = p->dialog_.exec(); | ||||||
|  |    p->firstCheckCheckBoxState_ = p->checkBox_->isChecked(); | ||||||
|  | 
 | ||||||
|  |    return result != QMessageBox::Yes; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool PrivilegeChecker::post_settings_check() | ||||||
|  | { | ||||||
|  |    auto& highPrivilegeWarningEnabled = | ||||||
|  |       settings::GeneralSettings::Instance().high_privilege_warning_enabled(); | ||||||
|  |    if (!highPrivilegeWarningEnabled.GetValue() || !p->highPrivilege_) | ||||||
|  |    { | ||||||
|  |       return false; | ||||||
|  |    } | ||||||
|  |    else if (!p->hasAppData_) | ||||||
|  |    { | ||||||
|  |       highPrivilegeWarningEnabled.StageValue(!p->firstCheckCheckBoxState_); | ||||||
|  |       return false; | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    switch (p->dialog_.exec()) | ||||||
|  |    { | ||||||
|  |    case QMessageBox::Yes: | ||||||
|  |       highPrivilegeWarningEnabled.StageValue(!p->checkBox_->isChecked()); | ||||||
|  |       return false; | ||||||
|  |    case QMessageBox::No: | ||||||
|  |    default: | ||||||
|  |       return true; | ||||||
|  |    } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | } // namespace scwx::qt::main
 | ||||||
							
								
								
									
										30
									
								
								scwx-qt/source/scwx/qt/main/check_privilege.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								scwx-qt/source/scwx/qt/main/check_privilege.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,30 @@ | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <memory> | ||||||
|  | 
 | ||||||
|  | namespace scwx::qt::main | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | bool is_high_privilege(); | ||||||
|  | 
 | ||||||
|  | class PrivilegeChecker | ||||||
|  | { | ||||||
|  | public: | ||||||
|  |    explicit PrivilegeChecker(); | ||||||
|  |    ~PrivilegeChecker(); | ||||||
|  | 
 | ||||||
|  |    PrivilegeChecker(const PrivilegeChecker&)             = delete; | ||||||
|  |    PrivilegeChecker& operator=(const PrivilegeChecker&)  = delete; | ||||||
|  |    PrivilegeChecker(const PrivilegeChecker&&)            = delete; | ||||||
|  |    PrivilegeChecker& operator=(const PrivilegeChecker&&) = delete; | ||||||
|  | 
 | ||||||
|  |    // returning true means check failed.
 | ||||||
|  |    bool pre_settings_check(); | ||||||
|  |    bool post_settings_check(); | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |    class Impl; | ||||||
|  |    std::unique_ptr<Impl> p; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | } // namespace scwx::qt::main
 | ||||||
|  | @ -13,6 +13,7 @@ | ||||||
| #include <scwx/qt/settings/general_settings.hpp> | #include <scwx/qt/settings/general_settings.hpp> | ||||||
| #include <scwx/qt/types/qt_types.hpp> | #include <scwx/qt/types/qt_types.hpp> | ||||||
| #include <scwx/qt/ui/setup/setup_wizard.hpp> | #include <scwx/qt/ui/setup/setup_wizard.hpp> | ||||||
|  | #include <scwx/qt/main/check_privilege.hpp> | ||||||
| #include <scwx/network/cpr.hpp> | #include <scwx/network/cpr.hpp> | ||||||
| #include <scwx/util/environment.hpp> | #include <scwx/util/environment.hpp> | ||||||
| #include <scwx/util/logger.hpp> | #include <scwx/util/logger.hpp> | ||||||
|  | @ -78,6 +79,13 @@ int main(int argc, char* argv[]) | ||||||
|       QStandardPaths::setTestModeEnabled(true); |       QStandardPaths::setTestModeEnabled(true); | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|  |    // Test to see if scwx was run with high privilege
 | ||||||
|  |    scwx::qt::main::PrivilegeChecker privilegeChecker; | ||||||
|  |    if (privilegeChecker.pre_settings_check()) | ||||||
|  |    { | ||||||
|  |       return 0; | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|    // Start the io_context main loop
 |    // Start the io_context main loop
 | ||||||
|    boost::asio::io_context& ioContext = scwx::util::io_context(); |    boost::asio::io_context& ioContext = scwx::util::io_context(); | ||||||
|    auto                     work      = boost::asio::make_work_guard(ioContext); |    auto                     work      = boost::asio::make_work_guard(ioContext); | ||||||
|  | @ -117,20 +125,27 @@ int main(int argc, char* argv[]) | ||||||
|    // Check process modules for compatibility
 |    // Check process modules for compatibility
 | ||||||
|    scwx::qt::main::CheckProcessModules(); |    scwx::qt::main::CheckProcessModules(); | ||||||
| 
 | 
 | ||||||
|    // Run initial setup if required
 |    int result = 0; | ||||||
|    if (scwx::qt::ui::setup::SetupWizard::IsSetupRequired()) |    if (privilegeChecker.post_settings_check()) | ||||||
|    { |    { | ||||||
|       scwx::qt::ui::setup::SetupWizard w; |       result = 1; | ||||||
|       w.show(); |  | ||||||
|       a.exec(); |  | ||||||
|    } |    } | ||||||
| 
 |    else | ||||||
|    // Run Qt main loop
 |  | ||||||
|    int result; |  | ||||||
|    { |    { | ||||||
|       scwx::qt::main::MainWindow w; |       // Run initial setup if required
 | ||||||
|       w.show(); |       if (scwx::qt::ui::setup::SetupWizard::IsSetupRequired()) | ||||||
|       result = a.exec(); |       { | ||||||
|  |          scwx::qt::ui::setup::SetupWizard w; | ||||||
|  |          w.show(); | ||||||
|  |          a.exec(); | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       // Run Qt main loop
 | ||||||
|  |       { | ||||||
|  |          scwx::qt::main::MainWindow w; | ||||||
|  |          w.show(); | ||||||
|  |          result = a.exec(); | ||||||
|  |       } | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|    // Deinitialize application
 |    // Deinitialize application
 | ||||||
|  |  | ||||||
|  | @ -80,6 +80,7 @@ public: | ||||||
|       warningsProvider_.SetDefault(defaultWarningsProviderValue); |       warningsProvider_.SetDefault(defaultWarningsProviderValue); | ||||||
|       cursorIconAlwaysOn_.SetDefault(false); |       cursorIconAlwaysOn_.SetDefault(false); | ||||||
|       radarSiteThreshold_.SetDefault(0.0); |       radarSiteThreshold_.SetDefault(0.0); | ||||||
|  |       highPrivilegeWarningEnabled_.SetDefault(true); | ||||||
| 
 | 
 | ||||||
|       fontSizes_.SetElementMinimum(1); |       fontSizes_.SetElementMinimum(1); | ||||||
|       fontSizes_.SetElementMaximum(72); |       fontSizes_.SetElementMaximum(72); | ||||||
|  | @ -175,6 +176,8 @@ public: | ||||||
|    SettingsVariable<std::string> warningsProvider_ {"warnings_provider"}; |    SettingsVariable<std::string> warningsProvider_ {"warnings_provider"}; | ||||||
|    SettingsVariable<bool>        cursorIconAlwaysOn_ {"cursor_icon_always_on"}; |    SettingsVariable<bool>        cursorIconAlwaysOn_ {"cursor_icon_always_on"}; | ||||||
|    SettingsVariable<double>      radarSiteThreshold_ {"radar_site_threshold"}; |    SettingsVariable<double>      radarSiteThreshold_ {"radar_site_threshold"}; | ||||||
|  |    SettingsVariable<bool>        highPrivilegeWarningEnabled_ { | ||||||
|  |       "high_privilege_warning_enabled"}; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| GeneralSettings::GeneralSettings() : | GeneralSettings::GeneralSettings() : | ||||||
|  | @ -210,7 +213,8 @@ GeneralSettings::GeneralSettings() : | ||||||
|                       &p->updateNotificationsEnabled_, |                       &p->updateNotificationsEnabled_, | ||||||
|                       &p->warningsProvider_, |                       &p->warningsProvider_, | ||||||
|                       &p->cursorIconAlwaysOn_, |                       &p->cursorIconAlwaysOn_, | ||||||
|                       &p->radarSiteThreshold_}); |                       &p->radarSiteThreshold_, | ||||||
|  |                       &p->highPrivilegeWarningEnabled_}); | ||||||
|    SetDefaults(); |    SetDefaults(); | ||||||
| } | } | ||||||
| GeneralSettings::~GeneralSettings() = default; | GeneralSettings::~GeneralSettings() = default; | ||||||
|  | @ -375,6 +379,11 @@ SettingsVariable<double>& GeneralSettings::radar_site_threshold() const | ||||||
|    return p->radarSiteThreshold_; |    return p->radarSiteThreshold_; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | SettingsVariable<bool>& GeneralSettings::high_privilege_warning_enabled() const | ||||||
|  | { | ||||||
|  |    return p->highPrivilegeWarningEnabled_; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| bool GeneralSettings::Shutdown() | bool GeneralSettings::Shutdown() | ||||||
| { | { | ||||||
|    bool dataChanged = false; |    bool dataChanged = false; | ||||||
|  | @ -385,6 +394,7 @@ bool GeneralSettings::Shutdown() | ||||||
|    dataChanged |= p->loopTime_.Commit(); |    dataChanged |= p->loopTime_.Commit(); | ||||||
|    dataChanged |= p->processModuleWarningsEnabled_.Commit(); |    dataChanged |= p->processModuleWarningsEnabled_.Commit(); | ||||||
|    dataChanged |= p->trackLocation_.Commit(); |    dataChanged |= p->trackLocation_.Commit(); | ||||||
|  |    dataChanged |= p->highPrivilegeWarningEnabled_.Commit(); | ||||||
| 
 | 
 | ||||||
|    return dataChanged; |    return dataChanged; | ||||||
| } | } | ||||||
|  | @ -429,7 +439,9 @@ bool operator==(const GeneralSettings& lhs, const GeneralSettings& rhs) | ||||||
|               rhs.p->updateNotificationsEnabled_ && |               rhs.p->updateNotificationsEnabled_ && | ||||||
|            lhs.p->warningsProvider_ == rhs.p->warningsProvider_ && |            lhs.p->warningsProvider_ == rhs.p->warningsProvider_ && | ||||||
|            lhs.p->cursorIconAlwaysOn_ == rhs.p->cursorIconAlwaysOn_ && |            lhs.p->cursorIconAlwaysOn_ == rhs.p->cursorIconAlwaysOn_ && | ||||||
|            lhs.p->radarSiteThreshold_ == rhs.p->radarSiteThreshold_); |            lhs.p->radarSiteThreshold_ == rhs.p->radarSiteThreshold_ && | ||||||
|  |            lhs.p->highPrivilegeWarningEnabled_ == | ||||||
|  |               rhs.p->highPrivilegeWarningEnabled_); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } // namespace settings
 | } // namespace settings
 | ||||||
|  |  | ||||||
|  | @ -56,6 +56,7 @@ public: | ||||||
|    SettingsVariable<std::string>& warnings_provider() const; |    SettingsVariable<std::string>& warnings_provider() const; | ||||||
|    SettingsVariable<bool>&        cursor_icon_always_on() const; |    SettingsVariable<bool>&        cursor_icon_always_on() const; | ||||||
|    SettingsVariable<double>&      radar_site_threshold() const; |    SettingsVariable<double>&      radar_site_threshold() const; | ||||||
|  |    SettingsVariable<bool>&        high_privilege_warning_enabled() const; | ||||||
| 
 | 
 | ||||||
|    static GeneralSettings& Instance(); |    static GeneralSettings& Instance(); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1 +1 @@ | ||||||
| Subproject commit 24ececcd183d3b8961e5638da89f0eb36309cd6b | Subproject commit 1f3e1259130a5eb4a6df37d721fe6c8301213e7e | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Dan Paulat
						Dan Paulat