From f58e95c96f4c88e968f4b6ce8306034d34787963 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Mon, 26 Sep 2016 15:46:57 +0100 Subject: [PATCH 001/101] v1.8.4 beta --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 963d84e3..fe96198b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,8 +17,8 @@ # Version number for Synergy set(VERSION_MAJOR 1) set(VERSION_MINOR 8) -set(VERSION_REV 3) -set(VERSION_STAGE stable) +set(VERSION_REV 4) +set(VERSION_STAGE beta) set(VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REV}") cmake_minimum_required(VERSION 2.6) From a70a2bf864f8726aae6fb7f90117bb0371fc24bb Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Tue, 27 Sep 2016 11:37:16 +0100 Subject: [PATCH 002/101] #5329 Fix build date in about dialog --- src/gui/src/AboutDialog.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/gui/src/AboutDialog.cpp b/src/gui/src/AboutDialog.cpp index 6fc1d57e..1d2f5888 100644 --- a/src/gui/src/AboutDialog.cpp +++ b/src/gui/src/AboutDialog.cpp @@ -32,7 +32,9 @@ AboutDialog::AboutDialog(QWidget* parent, const QString& synergyApp) : version = version + '-' + VERSION_STAGE + '-' + VERSION_REVISION; m_pLabelSynergyVersion->setText(version); - m_pLabelBuildDate->setText(QDate::currentDate().toString()); + QString buildDateString = QString::fromLocal8Bit(__DATE__).simplified(); + QDate buildDate = QLocale("en_US").toDate(buildDateString, "MMM d yyyy"); + m_pLabelBuildDate->setText(buildDate.toString(Qt::SystemLocaleLongDate)); // change default size based on os #if defined(Q_OS_MAC) From 665bd91dbda59edf2dafa42deb62d5dc0905204c Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Tue, 27 Sep 2016 12:02:18 +0100 Subject: [PATCH 003/101] #5628 Move SSL socket code from plugin to lib/net --- src/lib/{plugin/ns => net}/SecureListenSocket.cpp | 0 src/lib/{plugin/ns => net}/SecureListenSocket.h | 0 src/lib/{plugin/ns => net}/SecureSocket.cpp | 0 src/lib/{plugin/ns => net}/SecureSocket.h | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename src/lib/{plugin/ns => net}/SecureListenSocket.cpp (100%) rename src/lib/{plugin/ns => net}/SecureListenSocket.h (100%) rename src/lib/{plugin/ns => net}/SecureSocket.cpp (100%) rename src/lib/{plugin/ns => net}/SecureSocket.h (100%) diff --git a/src/lib/plugin/ns/SecureListenSocket.cpp b/src/lib/net/SecureListenSocket.cpp similarity index 100% rename from src/lib/plugin/ns/SecureListenSocket.cpp rename to src/lib/net/SecureListenSocket.cpp diff --git a/src/lib/plugin/ns/SecureListenSocket.h b/src/lib/net/SecureListenSocket.h similarity index 100% rename from src/lib/plugin/ns/SecureListenSocket.h rename to src/lib/net/SecureListenSocket.h diff --git a/src/lib/plugin/ns/SecureSocket.cpp b/src/lib/net/SecureSocket.cpp similarity index 100% rename from src/lib/plugin/ns/SecureSocket.cpp rename to src/lib/net/SecureSocket.cpp diff --git a/src/lib/plugin/ns/SecureSocket.h b/src/lib/net/SecureSocket.h similarity index 100% rename from src/lib/plugin/ns/SecureSocket.h rename to src/lib/net/SecureSocket.h From 76b2558f1a218764c4b29d244dce5e4e13d73bec Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Tue, 27 Sep 2016 12:16:20 +0100 Subject: [PATCH 004/101] #5617 Delete the plugin infrastructure --- src/gui/res/PluginWizardPageBase.ui | 137 ------------- src/gui/src/Plugin.cpp | 73 ------- src/gui/src/Plugin.h | 53 ----- src/gui/src/PluginManager.cpp | 186 ----------------- src/gui/src/PluginManager.h | 75 ------- src/gui/src/PluginWizardPage.cpp | 206 ------------------- src/gui/src/PluginWizardPage.h | 66 ------ src/lib/CMakeLists.txt | 1 - src/lib/arch/IArchPlugin.h | 80 -------- src/lib/arch/unix/ArchPluginUnix.cpp | 239 ---------------------- src/lib/arch/unix/ArchPluginUnix.h | 53 ----- src/lib/arch/win32/ArchPluginWindows.cpp | 250 ----------------------- src/lib/arch/win32/ArchPluginWindows.h | 57 ------ src/lib/common/PluginVersion.cpp | 36 ---- src/lib/common/PluginVersion.h | 31 --- src/lib/plugin/CMakeLists.txt | 28 --- src/lib/plugin/ns/CMakeLists.txt | 128 ------------ src/lib/plugin/ns/ns.cpp | 127 ------------ src/lib/plugin/ns/ns.h | 41 ---- src/lib/plugin/winmmjoy/CMakeLists.txt | 32 --- src/lib/plugin/winmmjoy/winmmjoy.cpp | 106 ---------- src/lib/plugin/winmmjoy/winmmjoy.h | 72 ------- 22 files changed, 2077 deletions(-) delete mode 100644 src/gui/res/PluginWizardPageBase.ui delete mode 100644 src/gui/src/Plugin.cpp delete mode 100644 src/gui/src/Plugin.h delete mode 100644 src/gui/src/PluginManager.cpp delete mode 100644 src/gui/src/PluginManager.h delete mode 100644 src/gui/src/PluginWizardPage.cpp delete mode 100644 src/gui/src/PluginWizardPage.h delete mode 100644 src/lib/arch/IArchPlugin.h delete mode 100644 src/lib/arch/unix/ArchPluginUnix.cpp delete mode 100644 src/lib/arch/unix/ArchPluginUnix.h delete mode 100644 src/lib/arch/win32/ArchPluginWindows.cpp delete mode 100644 src/lib/arch/win32/ArchPluginWindows.h delete mode 100644 src/lib/common/PluginVersion.cpp delete mode 100644 src/lib/common/PluginVersion.h delete mode 100644 src/lib/plugin/CMakeLists.txt delete mode 100644 src/lib/plugin/ns/CMakeLists.txt delete mode 100644 src/lib/plugin/ns/ns.cpp delete mode 100644 src/lib/plugin/ns/ns.h delete mode 100644 src/lib/plugin/winmmjoy/CMakeLists.txt delete mode 100644 src/lib/plugin/winmmjoy/winmmjoy.cpp delete mode 100644 src/lib/plugin/winmmjoy/winmmjoy.h diff --git a/src/gui/res/PluginWizardPageBase.ui b/src/gui/res/PluginWizardPageBase.ui deleted file mode 100644 index dfb7a978..00000000 --- a/src/gui/res/PluginWizardPageBase.ui +++ /dev/null @@ -1,137 +0,0 @@ - - - PluginWizardPage - - - - 0 - 0 - 400 - 300 - - - - Setup Synergy - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Please wait... - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - diff --git a/src/gui/src/Plugin.cpp b/src/gui/src/Plugin.cpp deleted file mode 100644 index 50079da2..00000000 --- a/src/gui/src/Plugin.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2015-2016 Symless Ltd. - * - * 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 . - */ - -#include "Plugin.h" - -#include "CoreInterface.h" - -static const char kBaseUrl[] = "http://symless.com/files"; -static const char kDefaultVersion[] = "1.1"; -static const char kWinPackagePlatform32[] = "Windows-x86"; -static const char kWinPackagePlatform64[] = "Windows-x64"; -static const char kMacPackagePlatform[] = "MacOSX%1-i386"; -static const char kLinuxPackagePlatformDeb32[] = "Linux-i686-deb"; -static const char kLinuxPackagePlatformDeb64[] = "Linux-x86_64-deb"; -static const char kLinuxPackagePlatformRpm32[] = "Linux-i686-rpm"; -static const char kLinuxPackagePlatformRpm64[] = "Linux-x86_64-rpm"; - -#if defined(Q_OS_WIN) -static const char kWinPluginExt[] = ".dll"; -static const char kInstallerPluginLocation[] = "Plugins"; -#elif defined(Q_OS_MAC) -static const char kMacPluginPrefix[] = "lib"; -static const char kMacPluginExt[] = ".dylib"; -static const char kInstallerPluginLocation[] = "plugins"; // TODO: Fix for mac -#else -static const char kLinuxPluginPrefix[] = "lib"; -static const char kLinuxPluginExt[] = ".so"; -// /usr/bin becomes /usr/bin/../lib/syn... -static const char kInstallerPluginLocation[] = "../lib/synergy/plugins"; -#endif - -QString Plugin::getOsSpecificExt() -{ - -#if defined(Q_OS_WIN) - return kWinPluginExt; -#elif defined(Q_OS_MAC) - return kMacPluginExt; -#else - return kLinuxPluginExt; -#endif -} - -QString Plugin::getOsSpecificName(const QString& pluginName) -{ - QString result = pluginName; -#if defined(Q_OS_WIN) - result.append(getOsSpecificExt()); -#elif defined(Q_OS_MAC) - result = kMacPluginPrefix + pluginName + getOsSpecificExt(); -#else - result = kLinuxPluginPrefix + pluginName + getOsSpecificExt(); -#endif - return result; -} - -QString Plugin::getOsSpecificInstallerLocation() { - return kInstallerPluginLocation; -} diff --git a/src/gui/src/Plugin.h b/src/gui/src/Plugin.h deleted file mode 100644 index bec6a1c2..00000000 --- a/src/gui/src/Plugin.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2015-2016 Symless Ltd. - * - * 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 . - */ -#ifndef PLUGIN_H -#define PLUGIN_H - -#include -#include -#include - -#include "SslCertificate.h" -#include "CoreInterface.h" -#include "DataDownloader.h" - -class Plugin : public QObject -{ - Q_OBJECT - -public: - //Plugin(); - //~PluginManager(); - - static QString getOsSpecificName(const QString& pluginName); - static QString getOsSpecificExt(); - static QString getOsSpecificLocation(); - static QString getOsSpecificInstallerLocation(); - static QString getOsSpecificUserLocation(); - -public slots: - -private: -// CoreInterface m_CoreInterface; - -signals: - -private: - -}; - -#endif // PLUGIN_H diff --git a/src/gui/src/PluginManager.cpp b/src/gui/src/PluginManager.cpp deleted file mode 100644 index b498751a..00000000 --- a/src/gui/src/PluginManager.cpp +++ /dev/null @@ -1,186 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2015-2016 Symless Ltd. - * - * 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 . - */ - -#include "PluginManager.h" - -#include "CoreInterface.h" -#include "DataDownloader.h" -#include "QUtility.h" -#include "ProcessorArch.h" -#include "Fingerprint.h" -#include "Plugin.h" -#include "../lib/common/PluginVersion.h" - -#include - -#include -#include -#include -#include - - -PluginManager::PluginManager() : - m_PluginList() -{ - init(); -} - -PluginManager::~PluginManager() -{ -} - -void PluginManager::init() -{ - m_PluginDir = m_CoreInterface.getPluginDir(); - if (m_PluginDir.isEmpty()) { - emit error(tr("Failed to get plugin directory.")); - } - - m_ProfileDir = m_CoreInterface.getProfileDir(); - if (m_ProfileDir.isEmpty()) { - emit error(tr("Failed to get profile directory.")); - } - - m_InstalledDir = m_CoreInterface.getInstalledDir(); - if (m_InstalledDir.isEmpty()) { - emit error(tr("Failed to get installed directory.")); - } -} - -bool PluginManager::exist(QString name) -{ - CoreInterface coreInterface; - QString PluginDir = coreInterface.getPluginDir(); - QString pluginName = Plugin::getOsSpecificName(name); - QString filename; - filename.append(PluginDir); - filename.append(QDir::separator()).append(pluginName); - QFile file(filename); - bool exist = false; - if (file.exists()) { - exist = true; - } - - return exist; -} - -void PluginManager::copyPlugins() -{ - try { - // Get the Directory where plugins are put on installation - // If it doesn't exist, there is nothing to do - QString srcDirName(m_InstalledDir.append(QDir::separator()) - .append(Plugin::getOsSpecificInstallerLocation())); - - QDir srcDir(srcDirName); - if (!srcDir.exists()) { - emit info( - tr("No plugins found to copy from %1") - .arg(srcDirName)); - emit copyFinished(); - } - - // Get the directory where Plugins are installed into Synergy - // If it doesn't exist make it - QString destDirName = m_PluginDir; - - QDir destDir(destDirName); - if (!destDir.exists()) { - destDir.mkpath("."); - } - // Run through the list of plugins and copy them - for ( int i = 0 ; i < m_PluginList.size() ; i++ ) { - // Get a file entry for the plugin using the full path - QFile file(srcDirName + QDir::separator() + m_PluginList.at(i)); - - // construct the destination file name - QString newName(destDirName + QDir::separator() + m_PluginList.at(i)); - - // Check to see if the plugin already exists - QFile newFile(newName); - if(newFile.exists()) { - // If it does, delete it. TODO: Check to see if same and leave - bool result = newFile.remove(); - if( !result ) { - emit error( - tr( "Unable to delete plugin:\n%1\n" - "Please stop synergy and run the wizard again.") - .arg(newName)); - return; - } - } - // make a copy of the plugin in the new location - #if defined(Q_OS_WIN) - bool result = file.copy(newName); - #else - bool result = file.link(newName); - #endif - if ( !result ) { - emit error( - tr("Failed to copy plugin '%1' to: %2\n%3\n" - "Please stop synergy and run the wizard again.") - .arg(m_PluginList.at(i)) - .arg(newName) - .arg(file.errorString())); - return; - } - else { - emit info( - tr("Copying '%1' plugin (%2/%3)...") - .arg(m_PluginList.at(i)) - .arg(i+1) - .arg(m_PluginList.size())); - } - } - } - catch (std::exception& e) - { - emit error(tr( "An error occurred while trying to copy the " - "plugin list. Please contact the help desk, and " - "provide the following details.\n\n%1").arg(e.what())); - } - - emit copyFinished(); - return; -} - -void PluginManager::queryPluginList() -{ - try { - setDone(false); - QString extension = "*" + Plugin::getOsSpecificExt(); - QStringList nameFilter(extension); - - QString installDir(m_CoreInterface.getInstalledDir() - .append(QDir::separator()) - .append(Plugin::getOsSpecificInstallerLocation())); - - QString searchDirectory(installDir); - QDir directory(searchDirectory); - m_PluginList = directory.entryList(nameFilter); - setDone(true); - } - catch (std::exception& e) - { - setDone(true); - emit error(tr( "An error occurred while trying to load the " - "plugin list. Please contact the help desk, and " - "provide the following details.\n\n%1").arg(e.what())); - } - emit queryPluginDone(); - return; -} diff --git a/src/gui/src/PluginManager.h b/src/gui/src/PluginManager.h deleted file mode 100644 index b1450fda..00000000 --- a/src/gui/src/PluginManager.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2015-2016 Symless Ltd. - * - * 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 . - */ - -#ifndef PLUGINMANAGER_H -#define PLUGINMANAGER_H - -#include -#include -#include - -#include "SslCertificate.h" -#include "CoreInterface.h" -#include "DataDownloader.h" -#include "Plugin.h" - -class PluginManager : public QObject -{ - Q_OBJECT - -public: - PluginManager(); - ~PluginManager(); - - void init(); - - int pluginCount() { return m_PluginList.count(); } - QStringList& getPluginList() { return m_PluginList; } - - bool isDone() { return done; } - void setDone(bool b) { done = b; } - static bool exist(QString name); - -public slots: - void copyPlugins(); - void queryPluginList(); - -private: - QString getPluginUrl(const QString& pluginName); - bool runProgram( - const QString& program, - const QStringList& args, - const QStringList& env); - -signals: - void error(QString e); - void info(QString i); - void updateCopyStatus(int); - void copyFinished(); - void queryPluginDone(); - -private: - QStringList m_PluginList; - QString m_PluginDir; - QString m_ProfileDir; - QString m_InstalledDir; - CoreInterface m_CoreInterface; - SslCertificate m_SslCertificate; - bool done; -}; - -#endif // PLUGINMANAGER_H diff --git a/src/gui/src/PluginWizardPage.cpp b/src/gui/src/PluginWizardPage.cpp deleted file mode 100644 index 8be20752..00000000 --- a/src/gui/src/PluginWizardPage.cpp +++ /dev/null @@ -1,206 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2015-2016 Symless Ltd. - * - * 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 . - */ - -#include "PluginWizardPage.h" -#include "ui_PluginWizardPageBase.h" - -#include "SslCertificate.h" -#include "PluginManager.h" -#include "MainWindow.h" -#include "EditionType.h" - -#include -#include -#include - -PluginWizardPage::PluginWizardPage(MainWindow& mainWindow, QWidget *parent) : - QWizardPage(parent), - m_Finished(false), - m_Edition(Unknown), - m_pSslCertificate(NULL), - m_mainWindow(mainWindow) -{ - setupUi(this); - - QMovie *movie = new QMovie(":/res/image/spinning-wheel.gif"); - m_pLabelSpinning->setMovie(movie); - movie->start(); - - m_pSslCertificate = new SslCertificate(this); -} - -PluginWizardPage::~PluginWizardPage() -{ - delete m_pSslCertificate; -} - -void PluginWizardPage::changeEvent(QEvent *e) -{ - QWizardPage::changeEvent(e); - switch (e->type()) { - case QEvent::LanguageChange: - retranslateUi(this); - break; - default: - break; - } -} - -void PluginWizardPage::initializePage() -{ - QWizardPage::initializePage(); - - if (m_Edition != Pro) { - updateStatus(tr("Setup complete.")); - showFinished(); - return; - } - - m_pLabelSpinning->show(); - - QThread* thread = new QThread; - - connect(&m_PluginManager, - SIGNAL(error(QString)), - this, - SLOT(showError(QString))); - - connect(&m_PluginManager, - SIGNAL(info(QString)), - this, - SLOT(updateStatus(QString))); - - connect(&m_PluginManager, - SIGNAL(queryPluginDone()), - this, - SLOT(queryPluginDone())); - - connect(&m_PluginManager, - SIGNAL(queryPluginDone()), - thread, - SLOT(quit())); - - connect(&m_PluginManager, - SIGNAL(error(QString)), - thread, - SLOT(quit())); - - connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); - - m_PluginManager.moveToThread(thread); - thread->start(); - - QMetaObject::invokeMethod(&m_PluginManager, "queryPluginList", Qt::QueuedConnection); -} - -void PluginWizardPage::queryPluginDone() -{ - QStringList pluginList = m_PluginManager.getPluginList(); - if (pluginList.isEmpty()) { - updateStatus(tr("Setup complete.")); - showFinished(); - } - else { - m_mainWindow.stopSynergy(); - copyPlugins(); - m_mainWindow.startSynergy(); - } -} - -void PluginWizardPage::copyPlugins() -{ - m_pThread = new QThread; - - connect(&m_PluginManager, - SIGNAL(copyFinished()), - this, - SLOT(generateCertificate())); - - connect(&m_PluginManager, - SIGNAL(error(QString)), - m_pThread, - SLOT(quit())); - - connect(m_pThread, - SIGNAL(finished()), - m_pThread, - SLOT(deleteLater())); - - updateStatus( - tr("Copying plugins...")); - - m_PluginManager.moveToThread(m_pThread); - m_pThread->start(); - - QMetaObject::invokeMethod( - &m_PluginManager, - "copyPlugins", - Qt::QueuedConnection); -} - -void PluginWizardPage::generateCertificate() -{ - connect(m_pSslCertificate, - SIGNAL(generateFinished()), - this, - SLOT(finished())); - - connect(m_pSslCertificate, - SIGNAL(generateFinished()), - m_pThread, - SLOT(quit())); - - updateStatus(tr("Generating SSL certificate...")); - - QMetaObject::invokeMethod( - m_pSslCertificate, - "generateCertificate", - Qt::QueuedConnection); -} - -void PluginWizardPage::showError(QString error) -{ - updateStatus(tr("Error: %1").arg(error)); - showFinished(); -} - - -void PluginWizardPage::updateStatus(QString info) -{ - m_pLabelStatus->setText(info); -} - -void PluginWizardPage::finished() -{ - // TODO: we should check if ns plugin exists - m_mainWindow.appConfig().setCryptoEnabled(true); - - updateStatus(tr("Plugins installed successfully.")); - showFinished(); -} - -void PluginWizardPage::showFinished() -{ - m_pLabelSpinning->hide(); - m_Finished = true; - emit completeChanged(); -} - -bool PluginWizardPage::isComplete() const -{ - return m_Finished; -} diff --git a/src/gui/src/PluginWizardPage.h b/src/gui/src/PluginWizardPage.h deleted file mode 100644 index d4319786..00000000 --- a/src/gui/src/PluginWizardPage.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2015-2016 Symless Ltd. - * - * 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 . - */ - -#ifndef PLUGINWIZARDPAGE_H -#define PLUGINWIZARDPAGE_H - -#include "AppConfig.h" - -#include "ui_PluginWizardPageBase.h" -#include "PluginManager.h" -#include - -class SslCertificate; -class MainWindow; - -class PluginWizardPage : public QWizardPage, public Ui::PluginWizardPage { - - Q_OBJECT - -public: - PluginWizardPage(MainWindow& mainWindow, QWidget *parent = 0); - ~PluginWizardPage(); - - void setFinished(bool b) { m_Finished = b; } - void setEdition(int edition) { m_Edition = edition; } - - bool isComplete() const; - void initializePage(); - -protected: - void changeEvent(QEvent *e); - -protected slots: - void showError(QString error); - void updateStatus(QString info); - void queryPluginDone(); - void generateCertificate(); - void finished(); - -private: - void copyPlugins(); - void showFinished(); - -private: - bool m_Finished; - int m_Edition; - PluginManager m_PluginManager; - SslCertificate* m_pSslCertificate; - QThread* m_pThread; - MainWindow& m_mainWindow; -}; -#endif // PLUGINWIZARDPAGE_H diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index 8eba5dff..48beb80a 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -23,7 +23,6 @@ add_subdirectory(ipc) add_subdirectory(mt) add_subdirectory(net) add_subdirectory(platform) -add_subdirectory(plugin) add_subdirectory(server) add_subdirectory(synergy) diff --git a/src/lib/arch/IArchPlugin.h b/src/lib/arch/IArchPlugin.h deleted file mode 100644 index e91ed65f..00000000 --- a/src/lib/arch/IArchPlugin.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2012-2016 Symless Ltd. - * Copyright (C) 2012 Nick Bolton - * - * 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 . - */ - -#pragma once - -#include "common/IInterface.h" -#include "common/stdmap.h" -#include "base/String.h" - -class IEventQueue; - -//! Interface for plugin manager. -/*! -A plugin manager should load all 3rd party plugins from the plugins dir, -and then look for common function names in the plugins. -*/ -class IArchPlugin : public IInterface { -public: - //! @name manipulators - //@{ - - //!Load plugins - /*! - Scan the plugins dir and load plugins. - */ - virtual void load() = 0; - - //!Unload plugins - /*! - Look through the loaded plugins and unload them. - */ - virtual void unload() = 0; - - //! Init the common parts - /*! - Initializes common parts like log and arch. - */ - virtual void init(void* log, void* arch) = 0; - - //! Init the event part - /*! - Initializes event parts. - */ - virtual void initEvent(void* eventTarget, IEventQueue* events) = 0; - - //! Check if exists - /*! - Returns true if the plugin exists and is loaded. - */ - virtual bool exists(const char* name) = 0; - - //! Invoke function - /*! - Invokes a function from the plugin. - */ - virtual void* invoke(const char* plugin, - const char* command, - void** args, - void* library = NULL) = 0; - - //@} - -protected: - typedef std::map PluginTable; -}; diff --git a/src/lib/arch/unix/ArchPluginUnix.cpp b/src/lib/arch/unix/ArchPluginUnix.cpp deleted file mode 100644 index edf53d17..00000000 --- a/src/lib/arch/unix/ArchPluginUnix.cpp +++ /dev/null @@ -1,239 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2012-2016 Symless Ltd. - * Copyright (C) 2012 Nick Bolton - * - * 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 . - */ - -#include "arch/unix/ArchPluginUnix.h" - -#include "arch/unix/XArchUnix.h" -#include "common/PluginVersion.h" -#include "base/IEventQueue.h" -#include "base/Event.h" -#include "base/Log.h" - -#include -#include -#include -#include - -typedef void (*initFunc)(void*, void*); -typedef int (*initEventFunc)(void (*sendEvent)(const char*, void*)); -typedef void* (*invokeFunc)(const char*, void*); -typedef void (*cleanupFunc)(); - -void* g_eventTarget = NULL; -IEventQueue* g_events = NULL; - -ArchPluginUnix::ArchPluginUnix() -{ -} - -ArchPluginUnix::~ArchPluginUnix() -{ -} - -void -ArchPluginUnix::load() -{ - String pluginsDir = getPluginsDir(); - LOG((CLOG_DEBUG "plugins dir: %s", pluginsDir.c_str())); - - struct dirent* de = NULL; - DIR* dir = NULL; - - dir = opendir(pluginsDir.c_str()); - if (dir == NULL) { - LOG((CLOG_DEBUG "can't open plugins dir: %s", - pluginsDir.c_str())); - return; - } - - std::vector plugins; - while ((de = readdir(dir)) != NULL) { - // ignore hidden files and diretories like .. and . - if (de->d_name[0] != '.') { - plugins.push_back(de->d_name); - } - } - closedir(dir); - - std::vector::iterator it; - for (it = plugins.begin(); it != plugins.end(); ++it) { - String filename = *it; - String path = synergy::string::sprintf( - "%s/%s", pluginsDir.c_str(), filename.c_str()); - String name = synergy::string::removeFileExt(filename.substr(3)); - - LOG((CLOG_DEBUG "loading plugin: %s", filename.c_str())); - void* handle = dlopen(path.c_str(), RTLD_LAZY); - - if (handle == NULL) { - LOG((CLOG_ERR "failed to load plugin '%s', error: %s", - filename.c_str(), dlerror())); - continue; - } - - - String expectedVersion = getExpectedPluginVersion(name.c_str()); - String currentVersion = getCurrentVersion(name, handle); - - if (currentVersion.empty() || (expectedVersion != currentVersion)) { - LOG((CLOG_ERR - "failed to load plugin '%s', " - "expected version %s but was %s", - filename.c_str(), - expectedVersion.c_str(), - currentVersion.empty() ? "unknown" : currentVersion.c_str())); - - dlclose(handle); - continue; - } - - LOG((CLOG_DEBUG "plugin loaded: %s (version %s)", - filename.c_str(), - currentVersion.c_str())); - - m_pluginTable.insert(std::make_pair(name, handle)); - } -} - -void -ArchPluginUnix::unload() -{ - PluginTable::iterator it; - for (it = m_pluginTable.begin(); it != m_pluginTable.end(); it++) { - cleanupFunc cleanup = (cleanupFunc)dlsym(it->second, "cleanup"); - if (cleanup != NULL) { - cleanup(); - } - else { - LOG((CLOG_DEBUG "no cleanup function in %s", it->first.c_str())); - } - - LOG((CLOG_DEBUG "unloading plugin: %s", it->first.c_str())); - dlclose(it->second); - } -} - -void -ArchPluginUnix::init(void* log, void* arch) -{ - PluginTable::iterator it; - for (it = m_pluginTable.begin(); it != m_pluginTable.end(); it++) { - initFunc initPlugin = (initFunc)dlsym(it->second, "init"); - if (initPlugin != NULL) { - initPlugin(log, arch); - } - else { - LOG((CLOG_DEBUG "no init function in %s", it->first.c_str())); - } - } -} - -void -ArchPluginUnix::initEvent(void* eventTarget, IEventQueue* events) -{ - g_eventTarget = eventTarget; - g_events = events; - - PluginTable::iterator it; - for (it = m_pluginTable.begin(); it != m_pluginTable.end(); it++) { - initEventFunc initEventPlugin = (initEventFunc)dlsym(it->second, "initEvent"); - if (initEventPlugin != NULL) { - initEventPlugin(&sendEvent); - } - else { - LOG((CLOG_DEBUG "no init event function in %s", it->first.c_str())); - } - } -} - -bool -ArchPluginUnix::exists(const char* name) -{ - PluginTable::iterator it; - it = m_pluginTable.find(name); - return it != m_pluginTable.end() ? true : false; -} - -void* -ArchPluginUnix::invoke( - const char* plugin, - const char* command, - void** args, - void* library) -{ - void* lib = NULL; - - if (library == NULL) { - PluginTable::iterator it; - it = m_pluginTable.find(plugin); - if (it != m_pluginTable.end()) { - lib = it->second; - } - else { - LOG((CLOG_DEBUG "invoke command failed, plugin: %s command: %s", - plugin, command)); - return NULL; - } - } - else { - lib = library; - } - - invokeFunc invokePlugin = (invokeFunc)dlsym(lib, "invoke"); - void* result = NULL; - if (invokePlugin != NULL) { - result = invokePlugin(command, args); - } - else { - LOG((CLOG_DEBUG "no invoke function in %s", plugin)); - } - - return result; -} - -String -ArchPluginUnix::getPluginsDir() -{ - return ARCH->getPluginDirectory(); -} - -String -ArchPluginUnix::getCurrentVersion(const String& name, void* handle) -{ - char* version = (char*)invoke(name.c_str(), "version", NULL, handle); - if (version == NULL) { - return ""; - } - - return version; -} - -void -sendEvent(const char* eventName, void* data) -{ - LOG((CLOG_DEBUG5 "plugin sending event")); - Event::Type type = g_events->getRegisteredType(eventName); - g_events->addEvent(Event(type, g_eventTarget, data)); -} - -void -log(const char* text) -{ - LOG((CLOG_DEBUG "plugin: %s", text)); -} - diff --git a/src/lib/arch/unix/ArchPluginUnix.h b/src/lib/arch/unix/ArchPluginUnix.h deleted file mode 100644 index 84ce185e..00000000 --- a/src/lib/arch/unix/ArchPluginUnix.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2012-2016 Symless Ltd. - * Copyright (C) 2012 Nick Bolton - * - * 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 . - */ - -#pragma once - -#include "arch/IArchPlugin.h" - -#define ARCH_PLUGIN ArchPluginUnix - -class IEventQueue; - -//! Unix implementation of IArchPlugin -class ArchPluginUnix : public IArchPlugin { -public: - ArchPluginUnix(); - virtual ~ArchPluginUnix(); - - // IArchPlugin overrides - void load(); - void unload(); - void init(void* log, void* arch); - void initEvent(void* eventTarget, IEventQueue* events); - bool exists(const char* name); - virtual void* invoke(const char* pluginName, - const char* functionName, - void** args, - void* library = NULL); - -private: - String getPluginsDir(); - String getCurrentVersion(const String& name, void* handle); - -private: - PluginTable m_pluginTable; -}; - -void sendEvent(const char* text, void* data); -void log(const char* text); diff --git a/src/lib/arch/win32/ArchPluginWindows.cpp b/src/lib/arch/win32/ArchPluginWindows.cpp deleted file mode 100644 index 7e498cb2..00000000 --- a/src/lib/arch/win32/ArchPluginWindows.cpp +++ /dev/null @@ -1,250 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2012-2016 Symless Ltd. - * Copyright (C) 2012 Nick Bolton - * - * 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 . - */ - -#include "arch/win32/ArchPluginWindows.h" -#include "arch/win32/XArchWindows.h" -#include "common/PluginVersion.h" -#include "base/Log.h" -#include "base/IEventQueue.h" -#include "base/Event.h" -#include "synergy/Screen.h" - -#define WIN32_LEAN_AND_MEAN -#include -#include - -typedef void (*initFunc)(void*, void*); -typedef int (*initEventFunc)(void (*sendEvent)(const char*, void*)); -typedef void* (*invokeFunc)(const char*, void**); -typedef void (*cleanupFunc)(); - -void* g_eventTarget = NULL; -IEventQueue* g_events = NULL; -static const char * kPre174Plugin = "Pre-1.7.v"; - -ArchPluginWindows::ArchPluginWindows() -{ -} - -ArchPluginWindows::~ArchPluginWindows() -{ -} - -void -ArchPluginWindows::load() -{ - String dir = getPluginsDir(); - LOG((CLOG_DEBUG "plugins dir: %s", dir.c_str())); - - String pattern = String(dir).append("\\*.dll"); - std::vector plugins; - getFilenames(pattern, plugins); - - std::vector::iterator it; - for (it = plugins.begin(); it != plugins.end(); ++it) { - String filename = *it; - String name = synergy::string::removeFileExt(filename); - String path = synergy::string::sprintf( - "%s\\%s", dir.c_str(), filename.c_str()); - - LOG((CLOG_DEBUG "loading plugin: %s", filename.c_str())); - HINSTANCE handle = LoadLibrary(path.c_str()); - void* voidHandle = reinterpret_cast(handle); - - if (handle == NULL) { - String error = XArchEvalWindows().eval(); - LOG((CLOG_ERR "failed to load plugin '%s', error: %s", - filename.c_str(), error.c_str())); - continue; - } - - String expectedVersion = getExpectedPluginVersion(name.c_str()); - String currentVersion = getCurrentVersion(name.c_str(), voidHandle); - - if (currentVersion.empty() || (expectedVersion != currentVersion)) { - LOG((CLOG_ERR - "failed to load plugin '%s', " - "expected version %s but was %s", - filename.c_str(), - expectedVersion.c_str(), - currentVersion.empty() ? "unknown" : currentVersion.c_str())); - - FreeLibrary(handle); - continue; - } - - LOG((CLOG_DEBUG "plugin loaded: %s (version %s)", - filename.c_str(), - currentVersion.c_str())); - - m_pluginTable.insert(std::make_pair(name, voidHandle)); - } -} - -void -ArchPluginWindows::unload() -{ - PluginTable::iterator it; - HINSTANCE lib; - for (it = m_pluginTable.begin(); it != m_pluginTable.end(); it++) { - lib = reinterpret_cast(it->second); - cleanupFunc cleanup = (cleanupFunc)GetProcAddress(lib, "cleanup"); - if (cleanup != NULL) { - cleanup(); - } - else { - LOG((CLOG_DEBUG "no cleanup function in %s", it->first.c_str())); - } - - LOG((CLOG_DEBUG "unloading plugin: %s", it->first.c_str())); - FreeLibrary(lib); - } -} - -void -ArchPluginWindows::init(void* log, void* arch) -{ - PluginTable::iterator it; - HINSTANCE lib; - for (it = m_pluginTable.begin(); it != m_pluginTable.end(); it++) { - lib = reinterpret_cast(it->second); - initFunc initPlugin = (initFunc)GetProcAddress(lib, "init"); - if (initPlugin != NULL) { - initPlugin(log, arch); - } - else { - LOG((CLOG_DEBUG "no init function in %s", it->first.c_str())); - } - } -} - -void -ArchPluginWindows::initEvent(void* eventTarget, IEventQueue* events) -{ - g_eventTarget = eventTarget; - g_events = events; - - PluginTable::iterator it; - HINSTANCE lib; - for (it = m_pluginTable.begin(); it != m_pluginTable.end(); it++) { - lib = reinterpret_cast(it->second); - initEventFunc initEventPlugin = (initEventFunc)GetProcAddress(lib, "initEvent"); - if (initEventPlugin != NULL) { - initEventPlugin(&sendEvent); - } - else { - LOG((CLOG_DEBUG "no init event function in %s", it->first.c_str())); - } - } -} - - -bool -ArchPluginWindows::exists(const char* name) -{ - PluginTable::iterator it; - it = m_pluginTable.find(name); - return it != m_pluginTable.end() ? true : false; -} - -void* -ArchPluginWindows::invoke( - const char* plugin, - const char* command, - void** args, - void* library) -{ - HINSTANCE lib = NULL; - - if (library == NULL) { - PluginTable::iterator it; - it = m_pluginTable.find(plugin); - if (it != m_pluginTable.end()) { - lib = reinterpret_cast(it->second); - } - else { - LOG((CLOG_DEBUG "invoke command failed, plugin: %s command: %s", - plugin, command)); - return NULL; - } - } - else { - lib = reinterpret_cast(library); - } - - invokeFunc invokePlugin = (invokeFunc)GetProcAddress(lib, "invoke"); - void* result = NULL; - if (invokePlugin != NULL) { - result = invokePlugin(command, args); - } - else { - LOG((CLOG_DEBUG "no invoke function in %s", plugin)); - } - - return result; -} - -void -ArchPluginWindows::getFilenames(const String& pattern, std::vector& filenames) -{ - WIN32_FIND_DATA data; - HANDLE find = FindFirstFile(pattern.c_str(), &data); - if (find == INVALID_HANDLE_VALUE) { - FindClose(find); - LOG((CLOG_DEBUG "plugins dir is empty: %s", pattern.c_str())); - return; - } - - do { - filenames.push_back(data.cFileName); - } while (FindNextFile(find, &data)); - - FindClose(find); -} - -String -ArchPluginWindows::getPluginsDir() -{ - return ARCH->getPluginDirectory(); -} - -String -ArchPluginWindows::getCurrentVersion(const String& name, void* handle) -{ - char* version = (char*)invoke(name.c_str(), "version", NULL, handle); - if (version == NULL) { - return ""; - } - - return version; -} - - -void -sendEvent(const char* eventName, void* data) -{ - LOG((CLOG_DEBUG5 "plugin sending event")); - Event::Type type = g_events->getRegisteredType(eventName); - g_events->addEvent(Event(type, g_eventTarget, data)); -} - -void -log(const char* text) -{ - LOG((CLOG_DEBUG "plugin: %s", text)); -} diff --git a/src/lib/arch/win32/ArchPluginWindows.h b/src/lib/arch/win32/ArchPluginWindows.h deleted file mode 100644 index dc61ead9..00000000 --- a/src/lib/arch/win32/ArchPluginWindows.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2012-2016 Symless Ltd. - * Copyright (C) 2012 Nick Bolton - * - * 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 . - */ - -#pragma once - -#include "arch/IArchPlugin.h" - -#include - -#define ARCH_PLUGIN ArchPluginWindows - -class Screen; -class IEventQueue; - -//! Windows implementation of IArchPlugin -class ArchPluginWindows : public IArchPlugin { -public: - ArchPluginWindows(); - virtual ~ArchPluginWindows(); - - // IArchPlugin overrides - void load(); - void unload(); - void init(void* log, void* arch); - void initEvent(void* eventTarget, IEventQueue* events); - bool exists(const char* name); - void* invoke(const char* pluginName, - const char* functionName, - void** args, - void* library = NULL); - -private: - void getFilenames(const String& pattern, std::vector& filenames); - String getPluginsDir(); - String getCurrentVersion(const String& name, void* handle); - -private: - PluginTable m_pluginTable; -}; - -void sendEvent(const char* text, void* data); -void log(const char* text); diff --git a/src/lib/common/PluginVersion.cpp b/src/lib/common/PluginVersion.cpp deleted file mode 100644 index 4ccacead..00000000 --- a/src/lib/common/PluginVersion.cpp +++ /dev/null @@ -1,36 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2015-2016 Symless Ltd. - * - * 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 . - */ - -#include "PluginVersion.h" - -#include - -static const char kUnknownVersion[] = "unknown"; -const char* s_pluginNames[] = { "ns" }; -static const char* s_pluginVersions[] = { "1.3" }; - -const char* getExpectedPluginVersion(const char* name) -{ - for (int i = 0; i < kPluginCount; i++) { - if (strcmp(name, s_pluginNames[i]) == 0) { - return s_pluginVersions[i]; - break; - } - } - - return kUnknownVersion; -} diff --git a/src/lib/common/PluginVersion.h b/src/lib/common/PluginVersion.h deleted file mode 100644 index b2f6bae2..00000000 --- a/src/lib/common/PluginVersion.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2015-2016 Symless Ltd. - * - * 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 . - */ - -#pragma once - -enum EPluginType { - kSecureSocket, - kPluginCount -}; - -extern const char* s_pluginNames[]; - -//! Get expected plugin version -/*! -Returns the plugin version expected by the plugin loader. -*/ -const char* getExpectedPluginVersion(const char* name); diff --git a/src/lib/plugin/CMakeLists.txt b/src/lib/plugin/CMakeLists.txt deleted file mode 100644 index 237da989..00000000 --- a/src/lib/plugin/CMakeLists.txt +++ /dev/null @@ -1,28 +0,0 @@ -# synergy -- mouse and keyboard sharing utility -# Copyright (C) 2012-2016 Symless Ltd. -# Copyright (C) 2012 Nick Bolton -# -# 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 . - -if (WIN32) - add_subdirectory(winmmjoy) -endif() - -if (APPLE) - # 10.7 should be supported, but gives is a _NXArgv linker error - if (OSX_TARGET_MINOR GREATER 7) - add_subdirectory(ns) - endif() -else() - add_subdirectory(ns) -endif() diff --git a/src/lib/plugin/ns/CMakeLists.txt b/src/lib/plugin/ns/CMakeLists.txt deleted file mode 100644 index 80b56741..00000000 --- a/src/lib/plugin/ns/CMakeLists.txt +++ /dev/null @@ -1,128 +0,0 @@ -# synergy -- mouse and keyboard sharing utility -# Copyright (C) 2015-2016 Symless Ltd. -# -# 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 . - -file(GLOB headers "*.h") -file(GLOB sources "*.cpp") - -if (SYNERGY_ADD_HEADERS) - list(APPEND sources ${headers}) -endif() - -if (WIN32) - if(CMAKE_SIZEOF_VOID_P EQUAL 8) - set(OPENSSL_PLAT_DIR openssl-win64) - else() - set(OPENSSL_PLAT_DIR openssl-win32) - endif() - set(OPENSSL_INCLUDE ../../../../ext/${OPENSSL_PLAT_DIR}/inc32) -endif() - -if (APPLE) - set(OPENSSL_PLAT_DIR openssl-osx) - set(OPENSSL_INCLUDE ../../../../ext/${OPENSSL_PLAT_DIR}/include) -endif() - -include_directories( - ../../../lib/ - ../../../.. - ${OPENSSL_INCLUDE} -) - -add_library(ns SHARED ${sources}) - -if (WIN32) - set(OPENSSL_LIBS - ${CMAKE_SOURCE_DIR}/ext/${OPENSSL_PLAT_DIR}/out32dll/libeay32.lib - ${CMAKE_SOURCE_DIR}/ext/${OPENSSL_PLAT_DIR}/out32dll/ssleay32.lib - ) -endif() - -if (UNIX) - if (APPLE) - set(OPENSSL_LIBS - ${CMAKE_SOURCE_DIR}/ext/${OPENSSL_PLAT_DIR}/libssl.a - ${CMAKE_SOURCE_DIR}/ext/${OPENSSL_PLAT_DIR}/libcrypto.a - ) - else() - set(OPENSSL_LIBS ssl crypto) - endif() -endif() - -target_link_libraries(ns - arch base client common io mt net ipc platform server synergy ${libs} ${OPENSSL_LIBS}) - -if (WIN32) - add_custom_command( - TARGET ns - POST_BUILD - COMMAND xcopy /Y /Q - ..\\..\\..\\..\\..\\lib\\${CMAKE_CFG_INTDIR}\\ns.* - ..\\..\\..\\..\\..\\bin\\${CMAKE_CFG_INTDIR}\\plugins\\ - ) - add_custom_command( - TARGET ns - POST_BUILD - COMMAND xcopy /Y /Q - ..\\..\\..\\..\\..\\ext\\${OPENSSL_PLAT_DIR}\\out32dll\\libeay32.* - ..\\..\\..\\..\\..\\bin\\${CMAKE_CFG_INTDIR} - ) - add_custom_command( - TARGET ns - POST_BUILD - COMMAND xcopy /Y /Q - ..\\..\\..\\..\\..\\ext\\${OPENSSL_PLAT_DIR}\\out32dll\\ssleay32.* - ..\\..\\..\\..\\..\\bin\\${CMAKE_CFG_INTDIR} - ) -endif() - -if (UNIX) - if (APPLE) - add_custom_command( - TARGET ns - POST_BUILD - COMMAND - mkdir -p - ${CMAKE_SOURCE_DIR}/bin/${CMAKE_CFG_INTDIR}/plugins - && - cp - ${CMAKE_SOURCE_DIR}/lib/${CMAKE_CFG_INTDIR}/libns.* - ${CMAKE_SOURCE_DIR}/bin/${CMAKE_CFG_INTDIR}/plugins/ - ) - else() - if (CMAKE_BUILD_TYPE STREQUAL Debug) - add_custom_command( - TARGET ns - POST_BUILD - COMMAND mkdir -p - ${CMAKE_SOURCE_DIR}/bin/debug/plugins - && - cp - ${CMAKE_SOURCE_DIR}/lib/debug/libns.* - ${CMAKE_SOURCE_DIR}/bin/debug/plugins/ - ) - else() - add_custom_command( - TARGET ns - POST_BUILD - COMMAND mkdir -p - ${CMAKE_SOURCE_DIR}/bin/plugins - && - cp - ${CMAKE_SOURCE_DIR}/lib/libns.* - ${CMAKE_SOURCE_DIR}/bin/plugins/ - ) - endif() - endif() -endif() diff --git a/src/lib/plugin/ns/ns.cpp b/src/lib/plugin/ns/ns.cpp deleted file mode 100644 index 17ba322f..00000000 --- a/src/lib/plugin/ns/ns.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2015-2016 Symless Ltd - * - * 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 . - */ - -#include "ns.h" - -#include "SecureSocket.h" -#include "SecureListenSocket.h" -#include "arch/Arch.h" -#include "common/PluginVersion.h" -#include "base/Log.h" - -#include -#include -#include -#include - -SecureSocket* g_secureSocket = NULL; -SecureListenSocket* g_secureListenSocket = NULL; -Arch* g_arch = NULL; -Log* g_log = NULL; - -std::string -helperGetLibsUsed(void) -{ - std::stringstream libs(ARCH->getLibsUsed()); - std::string msg; - std::string pid; - std::getline(libs,pid); - - while( std::getline(libs,msg) ) { - LOG(( CLOG_DEBUG "libs:%s",msg.c_str())); - } - return pid; -} - -extern "C" { -void -init(void* log, void* arch) -{ - if (g_log == NULL) { - g_log = new Log(reinterpret_cast(log)); - } - - if (g_arch == NULL) { - Arch::setInstance(reinterpret_cast(arch)); - } - - LOG(( CLOG_DEBUG "library use: %s", helperGetLibsUsed().c_str())); -} - -int -initEvent(void (*sendEvent)(const char*, void*)) -{ - return 0; -} - -void* -invoke(const char* command, void** args) -{ - IEventQueue* arg1 = NULL; - SocketMultiplexer* arg2 = NULL; - if (args != NULL) { - arg1 = reinterpret_cast(args[0]); - arg2 = reinterpret_cast(args[1]); - } - - if (strcmp(command, "getSocket") == 0) { - if (g_secureSocket != NULL) { - delete g_secureSocket; - } - g_secureSocket = new SecureSocket(arg1, arg2); - g_secureSocket->initSsl(false); - return g_secureSocket; - } - else if (strcmp(command, "getListenSocket") == 0) { - if (g_secureListenSocket != NULL) { - delete g_secureListenSocket; - } - g_secureListenSocket = new SecureListenSocket(arg1, arg2); - return g_secureListenSocket; - } - else if (strcmp(command, "deleteSocket") == 0) { - if (g_secureSocket != NULL) { - delete g_secureSocket; - g_secureSocket = NULL; - } - } - else if (strcmp(command, "deleteListenSocket") == 0) { - if (g_secureListenSocket != NULL) { - delete g_secureListenSocket; - g_secureListenSocket = NULL; - } - } - else if (strcmp(command, "version") == 0) { - return (void*)getExpectedPluginVersion(s_pluginNames[kSecureSocket]); - } - - return NULL; -} - -void -cleanup() -{ - if (g_secureSocket != NULL) { - delete g_secureSocket; - } - - if (g_secureListenSocket != NULL) { - delete g_secureListenSocket; - } -} - -} diff --git a/src/lib/plugin/ns/ns.h b/src/lib/plugin/ns/ns.h deleted file mode 100644 index 39999110..00000000 --- a/src/lib/plugin/ns/ns.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2015-2016 Symless Ltd - * - * 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 . - */ - -#pragma once - -#if defined _WIN32 -#define WIN32_LEAN_AND_MEAN -#include - -#if defined(ns_EXPORTS) -#define NS_API __declspec(dllexport) -#else -#define NS_API __declspec(dllimport) -#endif - -#else -#define NS_API -#endif - -extern "C" { - -NS_API void init(void* log, void* arch); -NS_API int initEvent(void (*sendEvent)(const char*, void*)); -NS_API void* invoke(const char* command, void** args); -NS_API void cleanup(); - -} diff --git a/src/lib/plugin/winmmjoy/CMakeLists.txt b/src/lib/plugin/winmmjoy/CMakeLists.txt deleted file mode 100644 index b07915bf..00000000 --- a/src/lib/plugin/winmmjoy/CMakeLists.txt +++ /dev/null @@ -1,32 +0,0 @@ -# synergy -- mouse and keyboard sharing utility -# Copyright (C) 2012-2016 Symless Ltd. -# Copyright (C) 2012 Nick Bolton -# -# 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 . - -file(GLOB headers "*.h") -file(GLOB sources "*.cpp") - -if (SYNERGY_ADD_HEADERS) - list(APPEND sources ${headers}) -endif() - -add_library(winmmjoy SHARED ${sources}) - -add_custom_command( - TARGET winmmjoy - POST_BUILD - COMMAND xcopy /Y /Q - ..\\..\\..\\..\\..\\lib\\${CMAKE_CFG_INTDIR}\\winmmjoy.* - ..\\..\\..\\..\\..\\bin\\${CMAKE_CFG_INTDIR}\\plugins\\ -) diff --git a/src/lib/plugin/winmmjoy/winmmjoy.cpp b/src/lib/plugin/winmmjoy/winmmjoy.cpp deleted file mode 100644 index d6306e82..00000000 --- a/src/lib/plugin/winmmjoy/winmmjoy.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2012-2016 Symless Ltd. - * Copyright (C) 2012 Nick Bolton - * - * 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 . - */ - -#include "winmmjoy.h" - -#include -#include -#include - -#pragma comment(lib, "winmm.lib") - -std::stringstream _logStream; -#define LOG(s) \ - _logStream.str(""); \ - _logStream << "winmmjoy: " << s << std::endl; \ - s_log(_logStream.str().c_str()) - -static bool s_running = true; -static void (*s_sendEvent)(const char*, void*) = NULL; -static void (*s_log)(const char*) = NULL; - -extern "C" { - -void -init(void* log, void* arch) -{ -} - -int -initEvent(void (*sendEvent)(const char*, void*)) -{ - s_sendEvent = sendEvent; - CreateThread(NULL, 0, mainLoop, NULL, 0, NULL); - return 0; -} - -void -cleanup() -{ - s_running = false; -} - -} - -DWORD WINAPI -mainLoop(void* data) -{ - // TODO: use a different message - e.g. DPLG%s (data - plugin) - const char* buttonsEvent = "IPrimaryScreen::getGameDeviceButtonsEvent"; - const char* sticksEvent = "IPrimaryScreen::getGameDeviceSticksEvent"; - const char* triggersEvent = "IPrimaryScreen::getGameDeviceTriggersEvent"; - - JOYINFOEX joyInfo; - ZeroMemory(&joyInfo, sizeof(joyInfo)); - joyInfo.dwSize = sizeof(joyInfo); - joyInfo.dwFlags = JOY_RETURNALL; - - // note: synergy data is often 16-bit, where winmm is 32-bit. - UINT index = JOYSTICKID1; - DWORD buttons, buttonsLast = 0; - DWORD xPos, xPosLast = 0; - DWORD yPos, yPosLast = 0; - - while (s_running) { - - if (joyGetPosEx(index, &joyInfo) != JOYERR_NOERROR) { - Sleep(1000); - continue; - } - - buttons = joyInfo.dwButtons; - xPos = joyInfo.dwXpos; - yPos = joyInfo.dwYpos; - - if (buttons != buttonsLast) { - s_sendEvent(buttonsEvent, - new CGameDeviceButtonInfo(index, (GameDeviceButton)joyInfo.dwButtons)); - } - - if (xPos != xPosLast || yPos != yPosLast) { - s_sendEvent(sticksEvent, - new CGameDeviceStickInfo(index, (short)xPos, (short)yPos, 0, 0)); - } - - buttonsLast = buttons; - xPosLast = xPos; - yPosLast = yPos; - Sleep(1); - } - return 0; -} diff --git a/src/lib/plugin/winmmjoy/winmmjoy.h b/src/lib/plugin/winmmjoy/winmmjoy.h deleted file mode 100644 index 712bd6d9..00000000 --- a/src/lib/plugin/winmmjoy/winmmjoy.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2012-2016 Symless Ltd. - * Copyright (C) 2012 Nick Bolton - * - * 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 . - */ - -#pragma once - -#define WIN32_LEAN_AND_MEAN -#include - -#if defined(winmmjoy_EXPORTS) -#define WINMMJOY_API __declspec(dllexport) -#else -#define WINMMJOY_API __declspec(dllimport) -#endif - -extern "C" { - -WINMMJOY_API void init(void* log, void* arch); -WINMMJOY_API int initEvent(void (*sendEvent)(const char*, void*)); -WINMMJOY_API void cleanup(); - -} - -DWORD WINAPI mainLoop(void* data); - -typedef unsigned char GameDeviceID; -typedef unsigned short GameDeviceButton; - -class CGameDeviceButtonInfo { -public: - CGameDeviceButtonInfo(GameDeviceID id, GameDeviceButton buttons) : - m_id(id), m_buttons(buttons) { } -public: - GameDeviceID m_id; - GameDeviceButton m_buttons; -}; - -class CGameDeviceStickInfo { -public: - CGameDeviceStickInfo(GameDeviceID id, short x1, short y1, short x2, short y2) : - m_id(id), m_x1(x1), m_x2(x2), m_y1(y1), m_y2(y2) { } -public: - GameDeviceID m_id; - short m_x1; - short m_x2; - short m_y1; - short m_y2; -}; - -class CGameDeviceTriggerInfo { -public: - CGameDeviceTriggerInfo(GameDeviceID id, unsigned char t1, unsigned char t2) : - m_id(id), m_t1(t1), m_t2(t2) { } -public: - GameDeviceID m_id; - unsigned char m_t1; - unsigned char m_t2; -}; From 27ccddbea434a4c436600c5b46779db47b369dc3 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Tue, 27 Sep 2016 12:23:09 +0100 Subject: [PATCH 005/101] #5617 Remove plugin infra from ClientListener --- src/lib/server/ClientListener.cpp | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/src/lib/server/ClientListener.cpp b/src/lib/server/ClientListener.cpp index cf64bc30..8e750ea0 100644 --- a/src/lib/server/ClientListener.cpp +++ b/src/lib/server/ClientListener.cpp @@ -46,14 +46,6 @@ ClientListener::ClientListener(const NetworkAddress& address, assert(m_socketFactory != NULL); try { - // create listen socket - if (enableCrypto) { - m_useSecureNetwork = ARCH->plugin().exists(s_pluginNames[kSecureSocket]); - if (m_useSecureNetwork == false) { - LOG((CLOG_NOTE "crypto disabled because of ns plugin not available")); - } - } - m_listen = m_socketFactory->createListen(m_useSecureNetwork); // setup event handler @@ -250,13 +242,5 @@ ClientListener::handleClientDisconnected(const Event&, void* vclient) void ClientListener::cleanupListenSocket() { - if (!m_useSecureNetwork) { - delete m_listen; - } - else { - ARCH->plugin().invoke( - s_pluginNames[kSecureSocket], - "deleteListenSocket", - NULL); - } + delete m_listen; } From 5774f5a29197887d33bceb63bee4dc75c25d72ea Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Tue, 27 Sep 2016 12:25:40 +0100 Subject: [PATCH 006/101] #5617 Remove plugin infra from Client --- src/lib/client/Client.cpp | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/src/lib/client/Client.cpp b/src/lib/client/Client.cpp index 748c8cb7..b1a5268f 100644 --- a/src/lib/client/Client.cpp +++ b/src/lib/client/Client.cpp @@ -18,7 +18,6 @@ #include "client/Client.h" -#include "../plugin/ns/SecureSocket.h" #include "client/ServerProxy.h" #include "synergy/Screen.h" #include "synergy/FileChunk.h" @@ -33,6 +32,7 @@ #include "net/TCPSocket.h" #include "net/IDataSocket.h" #include "net/ISocketFactory.h" +#include "net/SecureSocket.h" #include "arch/Arch.h" #include "base/Log.h" #include "base/IEventQueue.h" @@ -99,13 +99,6 @@ Client::Client( new TMethodEventJob(this, &Client::handleFileRecieveCompleted)); } - - if (m_args.m_enableCrypto) { - m_useSecureNetwork = ARCH->plugin().exists(s_pluginNames[kSecureSocket]); - if (m_useSecureNetwork == false) { - LOG((CLOG_NOTE "crypto disabled because of ns plugin not available")); - } - } } Client::~Client() @@ -593,13 +586,6 @@ Client::cleanupStream() { delete m_stream; m_stream = NULL; - - // PacketStreamFilter doen't adopt secure socket, because - // we need to tell the dynamic lib that allocated this object - // to do the deletion. - if (m_useSecureNetwork) { - ARCH->plugin().invoke(s_pluginNames[kSecureSocket], "deleteSocket", NULL); - } } void From dc93b063b7f12d7cf006297136b91b5b46d6da5e Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Tue, 27 Sep 2016 12:29:03 +0100 Subject: [PATCH 007/101] #5617 Remove plugin infra from TCPSocketFactory --- src/lib/net/TCPSocketFactory.cpp | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/src/lib/net/TCPSocketFactory.cpp b/src/lib/net/TCPSocketFactory.cpp index 9f8dc029..a639710a 100644 --- a/src/lib/net/TCPSocketFactory.cpp +++ b/src/lib/net/TCPSocketFactory.cpp @@ -17,9 +17,9 @@ */ #include "net/TCPSocketFactory.h" - #include "net/TCPSocket.h" #include "net/TCPListenSocket.h" +#include "net/SecureListenSocket.h" #include "arch/Arch.h" #include "common/PluginVersion.h" #include "base/Log.h" @@ -45,12 +45,7 @@ TCPSocketFactory::create(bool secure) const { IDataSocket* socket = NULL; if (secure) { - void* args[2] = { - m_events, - m_socketMultiplexer - }; - socket = static_cast( - ARCH->plugin().invoke(s_pluginNames[kSecureSocket], "getSocket", args)); + socket = new SecureSocket(m_events, m_socketMultiplexer); } else { socket = new TCPSocket(m_events, m_socketMultiplexer); @@ -64,12 +59,7 @@ TCPSocketFactory::createListen(bool secure) const { IListenSocket* socket = NULL; if (secure) { - void* args[2] = { - m_events, - m_socketMultiplexer - }; - socket = static_cast( - ARCH->plugin().invoke(s_pluginNames[kSecureSocket], "getListenSocket", args)); + socket = new SecureListenSocket(m_events, m_socketMultiplexer); } else { socket = new TCPListenSocket(m_events, m_socketMultiplexer); From f7e588dfff1ce2072db8c858ba3923cb76e91bfa Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Tue, 27 Sep 2016 12:31:24 +0100 Subject: [PATCH 008/101] #5617 Remove plugin directory support --- src/lib/arch/unix/ArchFileUnix.cpp | 20 -------------------- src/lib/arch/win32/ArchFileWindows.cpp | 18 ------------------ 2 files changed, 38 deletions(-) diff --git a/src/lib/arch/unix/ArchFileUnix.cpp b/src/lib/arch/unix/ArchFileUnix.cpp index 9dcc0b07..4aaddae4 100644 --- a/src/lib/arch/unix/ArchFileUnix.cpp +++ b/src/lib/arch/unix/ArchFileUnix.cpp @@ -104,20 +104,6 @@ ArchFileUnix::getLogDirectory() return "/var/log"; } -std::string -ArchFileUnix::getPluginDirectory() -{ - if (!m_pluginDirectory.empty()) { - return m_pluginDirectory; - } - -#if WINAPI_XWINDOWS - return getProfileDirectory().append("/plugins"); -#else - return getProfileDirectory().append("/Plugins"); -#endif -} - std::string ArchFileUnix::getProfileDirectory() { @@ -155,9 +141,3 @@ ArchFileUnix::setProfileDirectory(const String& s) { m_profileDirectory = s; } - -void -ArchFileUnix::setPluginDirectory(const String& s) -{ - m_pluginDirectory = s; -} diff --git a/src/lib/arch/win32/ArchFileWindows.cpp b/src/lib/arch/win32/ArchFileWindows.cpp index 373df72c..322323a4 100644 --- a/src/lib/arch/win32/ArchFileWindows.cpp +++ b/src/lib/arch/win32/ArchFileWindows.cpp @@ -139,18 +139,6 @@ ArchFileWindows::getLogDirectory() return getInstalledDirectory(); } -std::string -ArchFileWindows::getPluginDirectory() -{ - if (!m_pluginDirectory.empty()) { - return m_pluginDirectory; - } - - std::string dir = getProfileDirectory(); - dir.append("\\Plugins"); - return dir; -} - std::string ArchFileWindows::getProfileDirectory() { @@ -195,9 +183,3 @@ ArchFileWindows::setProfileDirectory(const String& s) { m_profileDirectory = s; } - -void -ArchFileWindows::setPluginDirectory(const String& s) -{ - m_pluginDirectory = s; -} From 85227f41a1827a286a5e966ab6f310823f052759 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Tue, 27 Sep 2016 12:33:34 +0100 Subject: [PATCH 009/101] #5617 Remove plugin infra from ServerApp --- src/lib/synergy/ServerApp.cpp | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/lib/synergy/ServerApp.cpp b/src/lib/synergy/ServerApp.cpp index 0153f9a2..52e4331f 100644 --- a/src/lib/synergy/ServerApp.cpp +++ b/src/lib/synergy/ServerApp.cpp @@ -707,11 +707,6 @@ ServerApp::mainLoop() return kExitFailed; } - // load all available plugins. - ARCH->plugin().load(); - // pass log and arch into plugins. - ARCH->plugin().init(Log::getInstance(), Arch::getInstance()); - // start server, etc appUtil().startNode(); @@ -721,9 +716,6 @@ ServerApp::mainLoop() initIpcClient(); } - // init event for all available plugins. - ARCH->plugin().initEvent(m_serverScreen->getEventTarget(), m_events); - // handle hangup signal by reloading the server's configuration ARCH->setSignalHandler(Arch::kHANGUP, &reloadSignalHandler, NULL); m_events->adoptHandler(m_events->forServerApp().reloadConfig(), @@ -780,9 +772,6 @@ ServerApp::mainLoop() cleanupIpcClient(); } - // unload all plugins. - ARCH->plugin().unload(); - return kExitSuccess; } From 011da60cca63f4068211f7f3ea635d30605b7b00 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Tue, 27 Sep 2016 12:35:15 +0100 Subject: [PATCH 010/101] #5617 Remove plugin infra from ClientApp --- src/lib/synergy/ClientApp.cpp | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/lib/synergy/ClientApp.cpp b/src/lib/synergy/ClientApp.cpp index 6adac9b9..54f9f687 100644 --- a/src/lib/synergy/ClientApp.cpp +++ b/src/lib/synergy/ClientApp.cpp @@ -455,11 +455,6 @@ ClientApp::mainLoop() SocketMultiplexer multiplexer; setSocketMultiplexer(&multiplexer); - // load all available plugins. - ARCH->plugin().load(); - // pass log and arch into plugins. - ARCH->plugin().init(Log::getInstance(), Arch::getInstance()); - // start client, etc appUtil().startNode(); @@ -469,9 +464,6 @@ ClientApp::mainLoop() initIpcClient(); } - // init event for all available plugins. - ARCH->plugin().initEvent(m_clientScreen->getEventTarget(), m_events); - // run event loop. if startClient() failed we're supposed to retry // later. the timer installed by startClient() will take care of // that. @@ -506,9 +498,6 @@ ClientApp::mainLoop() cleanupIpcClient(); } - // unload all plugins. - ARCH->plugin().unload(); - return kExitSuccess; } From a2ad4cb0dca7d2e4abdb24961eef2b01777b3c4c Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Tue, 27 Sep 2016 12:43:05 +0100 Subject: [PATCH 011/101] #5617 Remove plugin args from ArgParser --- src/lib/synergy/ArgParser.cpp | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/lib/synergy/ArgParser.cpp b/src/lib/synergy/ArgParser.cpp index 431a91b7..a77a8d85 100644 --- a/src/lib/synergy/ArgParser.cpp +++ b/src/lib/synergy/ArgParser.cpp @@ -189,18 +189,10 @@ ArgParser::parseToolArgs(ToolArgs& args, int argc, const char* const* argv) args.m_loginAuthenticate = true; return true; } - else if (isArg(i, argc, argv, NULL, "--get-plugin-list", 0)) { - args.m_getPluginList = true; - return true; - } else if (isArg(i, argc, argv, NULL, "--get-installed-dir", 0)) { args.m_getInstalledDir = true; return true; } - else if (isArg(i, argc, argv, NULL, "--get-plugin-dir", 0)) { - args.m_getPluginDir = true; - return true; - } else if (isArg(i, argc, argv, NULL, "--get-profile-dir", 0)) { args.m_getProfileDir = true; return true; @@ -330,9 +322,6 @@ ArgParser::parseGenericArgs(int argc, const char* const* argv, int& i) else if (isArg(i, argc, argv, NULL, "--profile-dir", 1)) { argsBase().m_profileDirectory = argv[++i]; } - else if (isArg(i, argc, argv, NULL, "--plugin-dir", 1)) { - argsBase().m_pluginDirectory = argv[++i]; - } else { // option not supported here return false; @@ -348,6 +337,10 @@ ArgParser::parseDeprecatedArgs(int argc, const char* const* argv, int& i) LOG((CLOG_NOTE "--crypto-pass is deprecated")); i++; return true; + } else if (isArg(i, argc, argv, NULL, "--plugin-dir", 1)) { + LOG((CLOG_NOTE "--plugin-dir is deprecated")); + ++i; + return true; } return false; From aee8e2874e030fb64d9741d219910d600fd3573a Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Tue, 27 Sep 2016 12:51:16 +0100 Subject: [PATCH 012/101] #5617 Remove plugins from Windows installer --- src/setup/win32/Product.wxs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/setup/win32/Product.wxs b/src/setup/win32/Product.wxs index 552f76d1..03a309e8 100644 --- a/src/setup/win32/Product.wxs +++ b/src/setup/win32/Product.wxs @@ -27,7 +27,6 @@ - @@ -70,7 +69,6 @@ - @@ -140,11 +138,5 @@ - - - - - - From 77d6b83b0c254aeb85a2edc7b8a01ba31d7dd554 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Tue, 27 Sep 2016 12:54:09 +0100 Subject: [PATCH 013/101] #5617 Remove stray PluginVersion includes --- src/lib/client/Client.cpp | 1 - src/lib/net/TCPSocketFactory.cpp | 1 - src/lib/server/ClientListener.cpp | 1 - 3 files changed, 3 deletions(-) diff --git a/src/lib/client/Client.cpp b/src/lib/client/Client.cpp index b1a5268f..4090c351 100644 --- a/src/lib/client/Client.cpp +++ b/src/lib/client/Client.cpp @@ -38,7 +38,6 @@ #include "base/IEventQueue.h" #include "base/TMethodEventJob.h" #include "base/TMethodJob.h" -#include "common/PluginVersion.h" #include "common/stdexcept.h" #include diff --git a/src/lib/net/TCPSocketFactory.cpp b/src/lib/net/TCPSocketFactory.cpp index a639710a..3fcb249f 100644 --- a/src/lib/net/TCPSocketFactory.cpp +++ b/src/lib/net/TCPSocketFactory.cpp @@ -21,7 +21,6 @@ #include "net/TCPListenSocket.h" #include "net/SecureListenSocket.h" #include "arch/Arch.h" -#include "common/PluginVersion.h" #include "base/Log.h" // diff --git a/src/lib/server/ClientListener.cpp b/src/lib/server/ClientListener.cpp index 8e750ea0..3bd7656b 100644 --- a/src/lib/server/ClientListener.cpp +++ b/src/lib/server/ClientListener.cpp @@ -25,7 +25,6 @@ #include "net/IListenSocket.h" #include "net/ISocketFactory.h" #include "net/XSocket.h" -#include "common/PluginVersion.h" #include "base/Log.h" #include "base/IEventQueue.h" #include "base/TMethodEventJob.h" From 45ef3e1080a45460e64c88ce52a4e967c5611047 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Tue, 27 Sep 2016 12:57:30 +0100 Subject: [PATCH 014/101] #5617 Remove plugin interface from Arch --- src/lib/arch/Arch.h | 4 ---- src/lib/arch/IArchFile.h | 14 -------------- src/lib/arch/unix/ArchFileUnix.h | 3 --- src/lib/arch/win32/ArchFileWindows.h | 3 --- 4 files changed, 24 deletions(-) diff --git a/src/lib/arch/Arch.h b/src/lib/arch/Arch.h index 3c5a23ff..42be6eb8 100644 --- a/src/lib/arch/Arch.h +++ b/src/lib/arch/Arch.h @@ -50,7 +50,6 @@ # include "arch/win32/ArchSystemWindows.h" # include "arch/win32/ArchTaskBarWindows.h" # include "arch/win32/ArchTimeWindows.h" -# include "arch/win32/ArchPluginWindows.h" # include "arch/win32/ArchInternetWindows.h" #elif SYSAPI_UNIX # include "arch/unix/ArchConsoleUnix.h" @@ -66,7 +65,6 @@ # include "arch/unix/ArchSystemUnix.h" # include "arch/unix/ArchTaskBarXWindows.h" # include "arch/unix/ArchTimeUnix.h" -# include "arch/unix/ArchPluginUnix.h" # include "arch/unix/ArchInternetUnix.h" #endif @@ -122,12 +120,10 @@ public: static void setInstance(Arch* s) { s_instance = s; } - ARCH_PLUGIN& plugin() const { return (ARCH_PLUGIN&)m_plugin; } ARCH_INTERNET& internet() const { return (ARCH_INTERNET&)m_internet; } private: static Arch* s_instance; - ARCH_PLUGIN m_plugin; ARCH_INTERNET m_internet; }; diff --git a/src/lib/arch/IArchFile.h b/src/lib/arch/IArchFile.h index bcbba6e0..da6623f2 100644 --- a/src/lib/arch/IArchFile.h +++ b/src/lib/arch/IArchFile.h @@ -63,13 +63,6 @@ public: */ virtual std::string getLogDirectory() = 0; - //! Get plugins directory - /*! - Returns the plugin files directory. If no plugin directory is set, - this will return the plugin folder within the user's profile. - */ - virtual std::string getPluginDirectory() = 0; - //! Get user's profile directory /*! Returns the user's profile directory. If no profile directory is set, @@ -95,11 +88,4 @@ public: Returns the user's profile directory. */ virtual void setProfileDirectory(const String& s) = 0; - - //@} - //! Set the user's plugin directory - /* - Returns the user's plugin directory. - */ - virtual void setPluginDirectory(const String& s) = 0; }; diff --git a/src/lib/arch/unix/ArchFileUnix.h b/src/lib/arch/unix/ArchFileUnix.h index cbf78668..6d3f1e3c 100644 --- a/src/lib/arch/unix/ArchFileUnix.h +++ b/src/lib/arch/unix/ArchFileUnix.h @@ -34,14 +34,11 @@ public: virtual std::string getSystemDirectory(); virtual std::string getInstalledDirectory(); virtual std::string getLogDirectory(); - virtual std::string getPluginDirectory(); virtual std::string getProfileDirectory(); virtual std::string concatPath(const std::string& prefix, const std::string& suffix); virtual void setProfileDirectory(const String& s); - virtual void setPluginDirectory(const String& s); private: String m_profileDirectory; - String m_pluginDirectory; }; diff --git a/src/lib/arch/win32/ArchFileWindows.h b/src/lib/arch/win32/ArchFileWindows.h index cdb8e4a2..032b796e 100644 --- a/src/lib/arch/win32/ArchFileWindows.h +++ b/src/lib/arch/win32/ArchFileWindows.h @@ -34,14 +34,11 @@ public: virtual std::string getSystemDirectory(); virtual std::string getInstalledDirectory(); virtual std::string getLogDirectory(); - virtual std::string getPluginDirectory(); virtual std::string getProfileDirectory(); virtual std::string concatPath(const std::string& prefix, const std::string& suffix); virtual void setProfileDirectory(const String& s); - virtual void setPluginDirectory(const String& s); private: String m_profileDirectory; - String m_pluginDirectory; }; From b1a991e8cd224e9d0d265666c4617211713ce528 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Tue, 27 Sep 2016 13:05:55 +0100 Subject: [PATCH 015/101] #5617 Revert "Remove plugin directory support" This reverts commit fc697d2ab79bbd2d607c97658c986b629a1280ed. --- src/lib/arch/unix/ArchFileUnix.cpp | 20 ++++++++++++++++++++ src/lib/arch/win32/ArchFileWindows.cpp | 18 ++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/src/lib/arch/unix/ArchFileUnix.cpp b/src/lib/arch/unix/ArchFileUnix.cpp index 4aaddae4..9dcc0b07 100644 --- a/src/lib/arch/unix/ArchFileUnix.cpp +++ b/src/lib/arch/unix/ArchFileUnix.cpp @@ -104,6 +104,20 @@ ArchFileUnix::getLogDirectory() return "/var/log"; } +std::string +ArchFileUnix::getPluginDirectory() +{ + if (!m_pluginDirectory.empty()) { + return m_pluginDirectory; + } + +#if WINAPI_XWINDOWS + return getProfileDirectory().append("/plugins"); +#else + return getProfileDirectory().append("/Plugins"); +#endif +} + std::string ArchFileUnix::getProfileDirectory() { @@ -141,3 +155,9 @@ ArchFileUnix::setProfileDirectory(const String& s) { m_profileDirectory = s; } + +void +ArchFileUnix::setPluginDirectory(const String& s) +{ + m_pluginDirectory = s; +} diff --git a/src/lib/arch/win32/ArchFileWindows.cpp b/src/lib/arch/win32/ArchFileWindows.cpp index 322323a4..373df72c 100644 --- a/src/lib/arch/win32/ArchFileWindows.cpp +++ b/src/lib/arch/win32/ArchFileWindows.cpp @@ -139,6 +139,18 @@ ArchFileWindows::getLogDirectory() return getInstalledDirectory(); } +std::string +ArchFileWindows::getPluginDirectory() +{ + if (!m_pluginDirectory.empty()) { + return m_pluginDirectory; + } + + std::string dir = getProfileDirectory(); + dir.append("\\Plugins"); + return dir; +} + std::string ArchFileWindows::getProfileDirectory() { @@ -183,3 +195,9 @@ ArchFileWindows::setProfileDirectory(const String& s) { m_profileDirectory = s; } + +void +ArchFileWindows::setPluginDirectory(const String& s) +{ + m_pluginDirectory = s; +} From b55b8f00383be23b314e84f51632388408653129 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Tue, 27 Sep 2016 13:08:12 +0100 Subject: [PATCH 016/101] #5617 Revert "Remove plugin args from ArgParser" This reverts commit cd58a8f0d0abe344d8e31a817386f613c7acde25. --- src/lib/synergy/ArgParser.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/lib/synergy/ArgParser.cpp b/src/lib/synergy/ArgParser.cpp index a77a8d85..431a91b7 100644 --- a/src/lib/synergy/ArgParser.cpp +++ b/src/lib/synergy/ArgParser.cpp @@ -189,10 +189,18 @@ ArgParser::parseToolArgs(ToolArgs& args, int argc, const char* const* argv) args.m_loginAuthenticate = true; return true; } + else if (isArg(i, argc, argv, NULL, "--get-plugin-list", 0)) { + args.m_getPluginList = true; + return true; + } else if (isArg(i, argc, argv, NULL, "--get-installed-dir", 0)) { args.m_getInstalledDir = true; return true; } + else if (isArg(i, argc, argv, NULL, "--get-plugin-dir", 0)) { + args.m_getPluginDir = true; + return true; + } else if (isArg(i, argc, argv, NULL, "--get-profile-dir", 0)) { args.m_getProfileDir = true; return true; @@ -322,6 +330,9 @@ ArgParser::parseGenericArgs(int argc, const char* const* argv, int& i) else if (isArg(i, argc, argv, NULL, "--profile-dir", 1)) { argsBase().m_profileDirectory = argv[++i]; } + else if (isArg(i, argc, argv, NULL, "--plugin-dir", 1)) { + argsBase().m_pluginDirectory = argv[++i]; + } else { // option not supported here return false; @@ -337,10 +348,6 @@ ArgParser::parseDeprecatedArgs(int argc, const char* const* argv, int& i) LOG((CLOG_NOTE "--crypto-pass is deprecated")); i++; return true; - } else if (isArg(i, argc, argv, NULL, "--plugin-dir", 1)) { - LOG((CLOG_NOTE "--plugin-dir is deprecated")); - ++i; - return true; } return false; From 5f5153f450737666b1c782f23f9f69c4edd9d400 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Tue, 27 Sep 2016 13:15:44 +0100 Subject: [PATCH 017/101] #5617 Remove the plugin wizard from GUI --- src/gui/gui.pro | 11 +---------- src/gui/src/MainWindow.h | 3 +-- src/gui/src/SetupWizard.cpp | 5 ----- src/gui/src/SetupWizard.h | 2 -- 4 files changed, 2 insertions(+), 19 deletions(-) diff --git a/src/gui/gui.pro b/src/gui/gui.pro index 408d44dd..28eca39e 100644 --- a/src/gui/gui.pro +++ b/src/gui/gui.pro @@ -16,8 +16,7 @@ FORMS += res/MainWindowBase.ui \ res/HotkeyDialogBase.ui \ res/SettingsDialogBase.ui \ res/SetupWizardBase.ui \ - res/AddClientDialogBase.ui \ - res/PluginWizardPageBase.ui + res/AddClientDialogBase.ui SOURCES += src/main.cpp \ src/MainWindow.cpp \ src/AboutDialog.cpp \ @@ -54,14 +53,10 @@ SOURCES += src/main.cpp \ src/DataDownloader.cpp \ src/AddClientDialog.cpp \ src/CommandProcess.cpp \ - src/PluginWizardPage.cpp \ - src/PluginManager.cpp \ src/CoreInterface.cpp \ src/Fingerprint.cpp \ src/SslCertificate.cpp \ - src/Plugin.cpp \ src/WebClient.cpp \ - ../lib/common/PluginVersion.cpp \ src/SubscriptionManager.cpp \ src/ActivationNotifier.cpp HEADERS += src/MainWindow.h \ @@ -101,15 +96,11 @@ HEADERS += src/MainWindow.h \ src/AddClientDialog.h \ src/CommandProcess.h \ src/EditionType.h \ - src/PluginWizardPage.h \ src/ProcessorArch.h \ - src/PluginManager.h \ src/CoreInterface.h \ src/Fingerprint.h \ src/SslCertificate.h \ - src/Plugin.h \ src/WebClient.h \ - ../lib/common/PluginVersion.h \ src/SubscriptionManager.h \ src/ActivationNotifier.h \ src/ElevateMode.h diff --git a/src/gui/src/MainWindow.h b/src/gui/src/MainWindow.h index 87380f96..d6d14055 100644 --- a/src/gui/src/MainWindow.h +++ b/src/gui/src/MainWindow.h @@ -63,8 +63,7 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase friend class QSynergyApplication; friend class SetupWizard; - friend class PluginWizardPage; - + public: enum qSynergyState { diff --git a/src/gui/src/SetupWizard.cpp b/src/gui/src/SetupWizard.cpp index 3d23b017..ed574e04 100644 --- a/src/gui/src/SetupWizard.cpp +++ b/src/gui/src/SetupWizard.cpp @@ -33,8 +33,6 @@ SetupWizard::SetupWizard(MainWindow& mainWindow, bool startMain) : m_LoginAttemps(0) { setupUi(this); - m_pPluginPage = new PluginWizardPage(mainWindow); - addPage(m_pPluginPage); #if defined(Q_OS_MAC) @@ -114,7 +112,6 @@ bool SetupWizard::validateCurrentPage() return false; } else { - m_pPluginPage->setEdition(m_Edition); return true; } } @@ -132,8 +129,6 @@ bool SetupWizard::validateCurrentPage() return false; } - m_pPluginPage->setEdition(m_Edition); - return true; } } diff --git a/src/gui/src/SetupWizard.h b/src/gui/src/SetupWizard.h index 34b301a2..fd6dcd14 100644 --- a/src/gui/src/SetupWizard.h +++ b/src/gui/src/SetupWizard.h @@ -19,7 +19,6 @@ #include "ui_SetupWizardBase.h" #include "SynergyLocale.h" -#include "PluginWizardPage.h" #include #include @@ -50,7 +49,6 @@ private: bool m_StartMain; SynergyLocale m_Locale; int m_Edition; - PluginWizardPage* m_pPluginPage; int m_LoginAttemps; private slots: From c3889667ba3a0b3a52db4e6a239c55642430fee3 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Tue, 27 Sep 2016 13:22:23 +0100 Subject: [PATCH 018/101] #5617 Remove online check for plugins --- src/lib/synergy/ToolApp.cpp | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/lib/synergy/ToolApp.cpp b/src/lib/synergy/ToolApp.cpp index b024bfe9..e6695f51 100644 --- a/src/lib/synergy/ToolApp.cpp +++ b/src/lib/synergy/ToolApp.cpp @@ -174,19 +174,6 @@ ToolApp::loginAuth() void ToolApp::getPluginList() { - String credentials; - std::cin >> credentials; - - size_t separator = credentials.find(':'); - String email = credentials.substr(0, separator); - String password = credentials.substr(separator + 1, credentials.length()); - - std::stringstream ss; - ss << JSON_URL << "plugins/"; - ss << "?email=" << ARCH->internet().urlEncode(email); - ss << "&password=" << password; - - std::cout << ARCH->internet().get(ss.str()) << std::endl; } void From 79fc6239fd82b9c17562dbb6f2ce948afa978efa Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Tue, 27 Sep 2016 14:43:14 +0100 Subject: [PATCH 019/101] #5617 Revert "Remove plugin interface from Arch" This reverts commit 4613edc17ced61d6aca80cff661323ede0cb9d30. --- src/lib/arch/Arch.h | 4 ++++ src/lib/arch/IArchFile.h | 14 ++++++++++++++ src/lib/arch/unix/ArchFileUnix.h | 3 +++ src/lib/arch/win32/ArchFileWindows.h | 3 +++ 4 files changed, 24 insertions(+) diff --git a/src/lib/arch/Arch.h b/src/lib/arch/Arch.h index 42be6eb8..3c5a23ff 100644 --- a/src/lib/arch/Arch.h +++ b/src/lib/arch/Arch.h @@ -50,6 +50,7 @@ # include "arch/win32/ArchSystemWindows.h" # include "arch/win32/ArchTaskBarWindows.h" # include "arch/win32/ArchTimeWindows.h" +# include "arch/win32/ArchPluginWindows.h" # include "arch/win32/ArchInternetWindows.h" #elif SYSAPI_UNIX # include "arch/unix/ArchConsoleUnix.h" @@ -65,6 +66,7 @@ # include "arch/unix/ArchSystemUnix.h" # include "arch/unix/ArchTaskBarXWindows.h" # include "arch/unix/ArchTimeUnix.h" +# include "arch/unix/ArchPluginUnix.h" # include "arch/unix/ArchInternetUnix.h" #endif @@ -120,10 +122,12 @@ public: static void setInstance(Arch* s) { s_instance = s; } + ARCH_PLUGIN& plugin() const { return (ARCH_PLUGIN&)m_plugin; } ARCH_INTERNET& internet() const { return (ARCH_INTERNET&)m_internet; } private: static Arch* s_instance; + ARCH_PLUGIN m_plugin; ARCH_INTERNET m_internet; }; diff --git a/src/lib/arch/IArchFile.h b/src/lib/arch/IArchFile.h index da6623f2..bcbba6e0 100644 --- a/src/lib/arch/IArchFile.h +++ b/src/lib/arch/IArchFile.h @@ -63,6 +63,13 @@ public: */ virtual std::string getLogDirectory() = 0; + //! Get plugins directory + /*! + Returns the plugin files directory. If no plugin directory is set, + this will return the plugin folder within the user's profile. + */ + virtual std::string getPluginDirectory() = 0; + //! Get user's profile directory /*! Returns the user's profile directory. If no profile directory is set, @@ -88,4 +95,11 @@ public: Returns the user's profile directory. */ virtual void setProfileDirectory(const String& s) = 0; + + //@} + //! Set the user's plugin directory + /* + Returns the user's plugin directory. + */ + virtual void setPluginDirectory(const String& s) = 0; }; diff --git a/src/lib/arch/unix/ArchFileUnix.h b/src/lib/arch/unix/ArchFileUnix.h index 6d3f1e3c..cbf78668 100644 --- a/src/lib/arch/unix/ArchFileUnix.h +++ b/src/lib/arch/unix/ArchFileUnix.h @@ -34,11 +34,14 @@ public: virtual std::string getSystemDirectory(); virtual std::string getInstalledDirectory(); virtual std::string getLogDirectory(); + virtual std::string getPluginDirectory(); virtual std::string getProfileDirectory(); virtual std::string concatPath(const std::string& prefix, const std::string& suffix); virtual void setProfileDirectory(const String& s); + virtual void setPluginDirectory(const String& s); private: String m_profileDirectory; + String m_pluginDirectory; }; diff --git a/src/lib/arch/win32/ArchFileWindows.h b/src/lib/arch/win32/ArchFileWindows.h index 032b796e..cdb8e4a2 100644 --- a/src/lib/arch/win32/ArchFileWindows.h +++ b/src/lib/arch/win32/ArchFileWindows.h @@ -34,11 +34,14 @@ public: virtual std::string getSystemDirectory(); virtual std::string getInstalledDirectory(); virtual std::string getLogDirectory(); + virtual std::string getPluginDirectory(); virtual std::string getProfileDirectory(); virtual std::string concatPath(const std::string& prefix, const std::string& suffix); virtual void setProfileDirectory(const String& s); + virtual void setPluginDirectory(const String& s); private: String m_profileDirectory; + String m_pluginDirectory; }; From 645627114184f502f2ea5c1157e4a257c153d621 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Tue, 27 Sep 2016 14:44:13 +0100 Subject: [PATCH 020/101] #5617 Remove plugin interface from Arch --- src/lib/arch/Arch.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/lib/arch/Arch.h b/src/lib/arch/Arch.h index 3c5a23ff..42be6eb8 100644 --- a/src/lib/arch/Arch.h +++ b/src/lib/arch/Arch.h @@ -50,7 +50,6 @@ # include "arch/win32/ArchSystemWindows.h" # include "arch/win32/ArchTaskBarWindows.h" # include "arch/win32/ArchTimeWindows.h" -# include "arch/win32/ArchPluginWindows.h" # include "arch/win32/ArchInternetWindows.h" #elif SYSAPI_UNIX # include "arch/unix/ArchConsoleUnix.h" @@ -66,7 +65,6 @@ # include "arch/unix/ArchSystemUnix.h" # include "arch/unix/ArchTaskBarXWindows.h" # include "arch/unix/ArchTimeUnix.h" -# include "arch/unix/ArchPluginUnix.h" # include "arch/unix/ArchInternetUnix.h" #endif @@ -122,12 +120,10 @@ public: static void setInstance(Arch* s) { s_instance = s; } - ARCH_PLUGIN& plugin() const { return (ARCH_PLUGIN&)m_plugin; } ARCH_INTERNET& internet() const { return (ARCH_INTERNET&)m_internet; } private: static Arch* s_instance; - ARCH_PLUGIN m_plugin; ARCH_INTERNET m_internet; }; From 52c8763d97c0ff0b1122e0468ed752a714de27d3 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Tue, 27 Sep 2016 14:46:48 +0100 Subject: [PATCH 021/101] #5617 Add SecureSocket to TCPSocketFactory --- src/lib/net/TCPSocketFactory.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib/net/TCPSocketFactory.cpp b/src/lib/net/TCPSocketFactory.cpp index 3fcb249f..87d4caa3 100644 --- a/src/lib/net/TCPSocketFactory.cpp +++ b/src/lib/net/TCPSocketFactory.cpp @@ -19,6 +19,7 @@ #include "net/TCPSocketFactory.h" #include "net/TCPSocket.h" #include "net/TCPListenSocket.h" +#include "net/SecureSocket.h" #include "net/SecureListenSocket.h" #include "arch/Arch.h" #include "base/Log.h" From 5db78acab4da367a9bd42997e769ae631e086391 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Tue, 27 Sep 2016 15:01:58 +0100 Subject: [PATCH 022/101] #5628 Link Synergy core against OpenSSL --- src/CMakeLists.txt | 32 ++++++++++++++++++++++++++++++ src/cmd/synergyc/CMakeLists.txt | 2 +- src/cmd/synergyd/CMakeLists.txt | 2 +- src/cmd/synergyp/CMakeLists.txt | 2 +- src/cmd/synergys/CMakeLists.txt | 2 +- src/cmd/syntool/CMakeLists.txt | 2 +- src/lib/net/CMakeLists.txt | 1 + src/test/integtests/CMakeLists.txt | 2 +- src/test/unittests/CMakeLists.txt | 2 +- 9 files changed, 40 insertions(+), 7 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d75c0adc..237ba484 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -14,6 +14,38 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +if (WIN32) + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(OPENSSL_PLAT_DIR openssl-win64) + else() + set(OPENSSL_PLAT_DIR openssl-win32) + endif() + set(OPENSSL_INCLUDE ${CMAKE_SOURCE_DIR}/ext/${OPENSSL_PLAT_DIR}/inc32) +endif() + +if (APPLE) + set(OPENSSL_PLAT_DIR openssl-osx) + set(OPENSSL_INCLUDE ${CMAKE_SOURCE_DIR}/ext/${OPENSSL_PLAT_DIR}/include) +endif() + +if (WIN32) + set(OPENSSL_LIBS + ${CMAKE_SOURCE_DIR}/ext/${OPENSSL_PLAT_DIR}/out32dll/libeay32.lib + ${CMAKE_SOURCE_DIR}/ext/${OPENSSL_PLAT_DIR}/out32dll/ssleay32.lib + ) +endif() + +if (UNIX) + if (APPLE) + set(OPENSSL_LIBS + ${CMAKE_SOURCE_DIR}/ext/${OPENSSL_PLAT_DIR}/libssl.a + ${CMAKE_SOURCE_DIR}/ext/${OPENSSL_PLAT_DIR}/libcrypto.a + ) + else() + set(OPENSSL_LIBS ssl crypto) + endif() +endif() + add_subdirectory(lib) add_subdirectory(cmd) add_subdirectory(micro) diff --git a/src/cmd/synergyc/CMakeLists.txt b/src/cmd/synergyc/CMakeLists.txt index 11d428d4..22bbe257 100644 --- a/src/cmd/synergyc/CMakeLists.txt +++ b/src/cmd/synergyc/CMakeLists.txt @@ -58,7 +58,7 @@ endif() add_executable(synergyc ${sources}) target_link_libraries(synergyc - arch base client common io mt net ipc platform server synergy ${libs}) + arch base client common io mt net ipc platform server synergy ${libs} ${OPENSSL_LIBS}) if (CONF_CPACK) install(TARGETS diff --git a/src/cmd/synergyd/CMakeLists.txt b/src/cmd/synergyd/CMakeLists.txt index 1caa35b5..005648f3 100644 --- a/src/cmd/synergyd/CMakeLists.txt +++ b/src/cmd/synergyd/CMakeLists.txt @@ -35,7 +35,7 @@ else() endif() target_link_libraries(synergyd - arch base common io ipc mt net platform synergy ${libs}) + arch base common io ipc mt net platform synergy ${libs} ${OPENSSL_LIBS}) if (CONF_CPACK) install(TARGETS diff --git a/src/cmd/synergyp/CMakeLists.txt b/src/cmd/synergyp/CMakeLists.txt index 171ef999..c9989252 100644 --- a/src/cmd/synergyp/CMakeLists.txt +++ b/src/cmd/synergyp/CMakeLists.txt @@ -63,7 +63,7 @@ else() endif() target_link_libraries(synergyp - arch base client common io mt net ipc platform server synergy client ${libs}) + arch base client common io mt net ipc platform server synergy client ${libs} ${OPENSSL_LIBS}) if (CONF_CPACK) install(TARGETS diff --git a/src/cmd/synergys/CMakeLists.txt b/src/cmd/synergys/CMakeLists.txt index c749e09a..2474bcc6 100644 --- a/src/cmd/synergys/CMakeLists.txt +++ b/src/cmd/synergys/CMakeLists.txt @@ -58,7 +58,7 @@ endif() add_executable(synergys ${sources}) target_link_libraries(synergys - arch base client common io mt net ipc platform server synergy ${libs}) + arch base client common io mt net ipc platform server synergy ${libs} ${OPENSSL_LIBS}) if (CONF_CPACK) install(TARGETS diff --git a/src/cmd/syntool/CMakeLists.txt b/src/cmd/syntool/CMakeLists.txt index 7f10c010..ffbb61aa 100644 --- a/src/cmd/syntool/CMakeLists.txt +++ b/src/cmd/syntool/CMakeLists.txt @@ -29,7 +29,7 @@ endif() add_executable(syntool ${sources}) target_link_libraries(syntool - synergy arch base client common io ipc mt net platform server ${libs}) + synergy arch base client common io ipc mt net platform server ${libs} ${OPENSSL_LIBS}) if (CONF_CPACK) install(TARGETS diff --git a/src/lib/net/CMakeLists.txt b/src/lib/net/CMakeLists.txt index ee50fe36..6e3527e4 100644 --- a/src/lib/net/CMakeLists.txt +++ b/src/lib/net/CMakeLists.txt @@ -23,6 +23,7 @@ endif() include_directories( ../ + ${OPENSSL_INCLUDE} ) if (UNIX) diff --git a/src/test/integtests/CMakeLists.txt b/src/test/integtests/CMakeLists.txt index bde35c2f..2f1ca7f3 100644 --- a/src/test/integtests/CMakeLists.txt +++ b/src/test/integtests/CMakeLists.txt @@ -68,4 +68,4 @@ endif() add_executable(integtests ${sources}) target_link_libraries(integtests - arch base client common io ipc mt net platform server synergy gtest gmock ${libs}) + arch base client common io ipc mt net platform server synergy gtest gmock ${libs} ${OPENSSL_LIBS}) diff --git a/src/test/unittests/CMakeLists.txt b/src/test/unittests/CMakeLists.txt index 4cacdf93..4cdab9bf 100644 --- a/src/test/unittests/CMakeLists.txt +++ b/src/test/unittests/CMakeLists.txt @@ -68,4 +68,4 @@ endif() add_executable(unittests ${sources}) target_link_libraries(unittests - arch base client server common io net platform server synergy mt ipc gtest gmock ${libs}) + arch base client server common io net platform server synergy mt ipc gtest gmock ${libs} ${OPENSSL_LIBS}) From 1fceb2b6462857d0761e0a8a41eb5be0841c8373 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Tue, 27 Sep 2016 15:53:50 +0100 Subject: [PATCH 023/101] #5617 Remove PluginManager from MainWindow --- src/gui/src/MainWindow.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/gui/src/MainWindow.cpp b/src/gui/src/MainWindow.cpp index 332fcbd6..fa1f48ec 100644 --- a/src/gui/src/MainWindow.cpp +++ b/src/gui/src/MainWindow.cpp @@ -23,7 +23,6 @@ #include "MainWindow.h" #include "Fingerprint.h" -#include "PluginManager.h" #include "AboutDialog.h" #include "ServerConfigDialog.h" #include "SettingsDialog.h" From 964e6d2f12a92584100a108dd376480781f89c33 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Tue, 27 Sep 2016 16:11:51 +0100 Subject: [PATCH 024/101] #5617 Remove PluginManager from SettingsDialog --- src/gui/src/SettingsDialog.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/gui/src/SettingsDialog.cpp b/src/gui/src/SettingsDialog.cpp index 5d5b53d2..8f754490 100644 --- a/src/gui/src/SettingsDialog.cpp +++ b/src/gui/src/SettingsDialog.cpp @@ -18,7 +18,6 @@ #include "SettingsDialog.h" -#include "PluginManager.h" #include "CoreInterface.h" #include "SynergyLocale.h" #include "QSynergyApplication.h" @@ -61,13 +60,7 @@ SettingsDialog::SettingsDialog(QWidget* parent, AppConfig& config) : m_pComboElevate->hide(); #endif - if (!PluginManager::exist(networkSecurity)) { - m_pGroupNetworkSecurity->setEnabled(false); - m_pCheckBoxEnableCrypto->setChecked(false); - } - else { - m_pCheckBoxEnableCrypto->setChecked(m_AppConfig.getCryptoEnabled()); - } + m_pCheckBoxEnableCrypto->setChecked(m_AppConfig.getCryptoEnabled()); } void SettingsDialog::accept() From e18f8c62e7a1eaf6ee2b7e4852309d5df20ead06 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Tue, 27 Sep 2016 16:20:29 +0100 Subject: [PATCH 025/101] #5617 Remove plugins support from toolchain --- ext/toolchain/commands1.py | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/ext/toolchain/commands1.py b/ext/toolchain/commands1.py index 79cfc6f1..7f357029 100644 --- a/ext/toolchain/commands1.py +++ b/ext/toolchain/commands1.py @@ -741,16 +741,6 @@ class InternalCommands: shutil.copy(targetDir + "/synergys", bundleBinDir) shutil.copy(targetDir + "/syntool", bundleBinDir) - # Copy all generated plugins to the package - bundlePluginDir = bundleBinDir + "plugins" - pluginDir = targetDir + "/plugins" - print "Copying plugins dirtree: " + pluginDir - if os.path.isdir(pluginDir): - print "Copying to: " + bundlePluginDir - shutil.copytree(pluginDir, bundlePluginDir) - else: - print "pluginDir doesn't exist, skipping" - self.loadConfig() if not self.macIdentity: raise Exception("run config with --mac-identity") @@ -1151,14 +1141,12 @@ class InternalCommands: controlFile.close() targetBin = '%s/%s/usr/bin' % (debDir, package) - targetPlugin = '%s/%s/usr/lib/synergy/plugins' % (debDir, package) targetShare = '%s/%s/usr/share' % (debDir, package) targetApplications = "%s/applications" % targetShare targetIcons = "%s/icons" % targetShare targetDocs = "%s/doc/%s" % (targetShare, self.project) os.makedirs(targetBin) - os.makedirs(targetPlugin) os.makedirs(targetApplications) os.makedirs(targetIcons) os.makedirs(targetDocs) @@ -1176,17 +1164,6 @@ class InternalCommands: if err != 0: raise Exception('strip failed: ' + str(err)) - pluginDir = "%s/plugins" % binDir - - pluginFiles = [ 'libns.so'] - for f in pluginFiles: - shutil.copy("%s/%s" % (pluginDir, f), targetPlugin) - target = "%s/%s" % (targetPlugin, f) - os.chmod(target, 0o0644) - err = os.system("strip " + target) - if err != 0: - raise Exception('strip failed: ' + str(err)) - shutil.copy("%s/synergy.desktop" % resDir, targetApplications) shutil.copy("%s/synergy.ico" % resDir, targetIcons) @@ -1402,13 +1379,6 @@ class InternalCommands: packageTarget = filename ftp.upload(packageSource, packageTarget) - if type != 'src': - pluginsDir = binDir + '/plugins' - nsPluginSource = self.findLibraryFile(type, pluginsDir, 'ns') - if nsPluginSource: - nsPluginTarget = self.getLibraryDistFilename(type, pluginsDir, 'ns') - ftp.upload(nsPluginSource, nsPluginTarget, "plugins") - def getLibraryDistFilename(self, type, dir, name): (platform, packageExt, libraryExt) = self.getDistributePlatformInfo(type) firstPart = '%s-%s-%s' % (name, self.getVersionForFilename(), platform) From 3b5940ac185d1c38133e113535f3dc2413f76e40 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Tue, 27 Sep 2016 16:44:19 +0100 Subject: [PATCH 026/101] #5628 Restore copying of SSL libs on Windows --- src/lib/net/CMakeLists.txt | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/lib/net/CMakeLists.txt b/src/lib/net/CMakeLists.txt index 6e3527e4..60a14499 100644 --- a/src/lib/net/CMakeLists.txt +++ b/src/lib/net/CMakeLists.txt @@ -34,6 +34,30 @@ endif() add_library(net STATIC ${sources}) +if (WIN32) + add_custom_command( + TARGET net + POST_BUILD + COMMAND xcopy /Y /Q + ..\\..\\..\\..\\lib\\${CMAKE_CFG_INTDIR}\\ns.* + ..\\..\\..\\..\\bin\\${CMAKE_CFG_INTDIR}\\plugins\\ + ) + add_custom_command( + TARGET net + POST_BUILD + COMMAND xcopy /Y /Q + ..\\..\\..\\..\\ext\\${OPENSSL_PLAT_DIR}\\out32dll\\libeay32.* + ..\\..\\..\\..\\bin\\${CMAKE_CFG_INTDIR} + ) + add_custom_command( + TARGET net + POST_BUILD + COMMAND xcopy /Y /Q + ..\\..\\..\\..\\ext\\${OPENSSL_PLAT_DIR}\\out32dll\\ssleay32.* + ..\\..\\..\\..\\bin\\${CMAKE_CFG_INTDIR} + ) +endif() + if (UNIX) target_link_libraries(net mt io) endif() From f4f57e1f95730b68a30a84e9cc076451e1db962b Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Tue, 27 Sep 2016 16:53:29 +0100 Subject: [PATCH 027/101] #5617 Remove plugins from RPM spec --- res/synergy.spec.in | 3 --- 1 file changed, 3 deletions(-) diff --git a/res/synergy.spec.in b/res/synergy.spec.in index 16b695e3..3f0c88f9 100644 --- a/res/synergy.spec.in +++ b/res/synergy.spec.in @@ -20,7 +20,6 @@ source=%{_topdir}/../.. mkdir -p %{buildroot}/%{_datarootdir}/applications mkdir -p %{buildroot}/%{_datarootdir}/icons mkdir -p %{buildroot}/%{_bindir} -mkdir -p %{buildroot}/%{_bindir}/../lib/synergy/plugins cp $source/bin/synergy %{buildroot}%{_bindir} cp $source/bin/synergyc %{buildroot}%{_bindir} @@ -29,7 +28,6 @@ cp $source/bin/synergyd %{buildroot}%{_bindir} cp $source/bin/syntool %{buildroot}%{_bindir} cp $source/res/synergy.desktop %{buildroot}%{_datarootdir}/applications cp $source/res/synergy.ico %{buildroot}%{_datarootdir}/icons -cp $source/bin/plugins/* %{buildroot}%{_bindir}/../lib/synergy/plugins %files %defattr(755,root,root,-) @@ -40,7 +38,6 @@ cp $source/bin/plugins/* %{buildroot}%{_bindir}/../lib/synergy/plugins %{_bindir}/syntool %attr(644,-,-) %{_datarootdir}/applications/synergy.desktop %attr(644,-,-) %{_datarootdir}/icons/synergy.ico -%attr(644,-,-) %{_bindir}/../lib/synergy/plugins/* %changelog * Thu Mar 20 2014 Nick Bolton From 0d84e4eed6bf3e328cdb82da4f2ff6dbdae4922f Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Tue, 27 Sep 2016 17:02:44 +0100 Subject: [PATCH 028/101] #5617 Make PacketStreamFilter adopt all socket types --- src/lib/client/Client.cpp | 3 +-- src/lib/server/ClientListener.cpp | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/lib/client/Client.cpp b/src/lib/client/Client.cpp index 4090c351..001bf2fa 100644 --- a/src/lib/client/Client.cpp +++ b/src/lib/client/Client.cpp @@ -152,8 +152,7 @@ Client::connect() // filter socket messages, including a packetizing filter m_stream = socket; - bool adopt = !m_useSecureNetwork; - m_stream = new PacketStreamFilter(m_events, m_stream, adopt); + m_stream = new PacketStreamFilter(m_events, m_stream, true); // connect LOG((CLOG_DEBUG1 "connecting to server")); diff --git a/src/lib/server/ClientListener.cpp b/src/lib/server/ClientListener.cpp index 3bd7656b..f8d07c19 100644 --- a/src/lib/server/ClientListener.cpp +++ b/src/lib/server/ClientListener.cpp @@ -155,8 +155,7 @@ ClientListener::handleClientAccepted(const Event&, void* vsocket) IDataSocket* socket = static_cast(vsocket); // filter socket messages, including a packetizing filter - bool adopt = !m_useSecureNetwork; - synergy::IStream* stream = new PacketStreamFilter(m_events, socket, adopt); + synergy::IStream* stream = new PacketStreamFilter(m_events, socket, true); assert(m_server != NULL); // create proxy for unknown client From 55a2d1231fe86e7e856ac6da5462e3c5293d173a Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Wed, 28 Sep 2016 11:24:33 +0100 Subject: [PATCH 029/101] #5628 Initialize SSL on secure client sockets --- src/lib/net/TCPSocketFactory.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/lib/net/TCPSocketFactory.cpp b/src/lib/net/TCPSocketFactory.cpp index 87d4caa3..e205a9fa 100644 --- a/src/lib/net/TCPSocketFactory.cpp +++ b/src/lib/net/TCPSocketFactory.cpp @@ -43,15 +43,14 @@ TCPSocketFactory::~TCPSocketFactory() IDataSocket* TCPSocketFactory::create(bool secure) const { - IDataSocket* socket = NULL; if (secure) { - socket = new SecureSocket(m_events, m_socketMultiplexer); + SecureSocket* secureSocket = new SecureSocket(m_events, m_socketMultiplexer); + secureSocket->initSsl (false); + return secureSocket; } else { - socket = new TCPSocket(m_events, m_socketMultiplexer); + return new TCPSocket(m_events, m_socketMultiplexer); } - - return socket; } IListenSocket* From 45da1dfc7c54584708284f65adbac76cd10c3d0c Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Wed, 28 Sep 2016 11:37:33 +0100 Subject: [PATCH 030/101] #5628 Make enableCrypto directly enable SSL --- src/lib/client/Client.cpp | 2 +- src/lib/server/ClientListener.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/client/Client.cpp b/src/lib/client/Client.cpp index 001bf2fa..d984be4c 100644 --- a/src/lib/client/Client.cpp +++ b/src/lib/client/Client.cpp @@ -71,7 +71,7 @@ Client::Client( m_sendFileThread(NULL), m_writeToDropDirThread(NULL), m_socket(NULL), - m_useSecureNetwork(false), + m_useSecureNetwork(args.m_enableCrypto), m_args(args), m_enableClipboard(true) { diff --git a/src/lib/server/ClientListener.cpp b/src/lib/server/ClientListener.cpp index f8d07c19..a9777aae 100644 --- a/src/lib/server/ClientListener.cpp +++ b/src/lib/server/ClientListener.cpp @@ -40,7 +40,7 @@ ClientListener::ClientListener(const NetworkAddress& address, m_socketFactory(socketFactory), m_server(NULL), m_events(events), - m_useSecureNetwork(false) + m_useSecureNetwork(enableCrypto) { assert(m_socketFactory != NULL); From 663e3f5854a8a632cb6afc34596c27e2faa58065 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Thu, 29 Sep 2016 13:45:06 +0100 Subject: [PATCH 031/101] #5629 Add rudimentary activation dialog --- src/gui/gui.pro | 9 ++++++--- src/gui/res/MainWindowBase.ui | 10 +++++++++- src/gui/src/MainWindow.cpp | 8 ++++++++ src/gui/src/MainWindow.h | 2 +- 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/gui/gui.pro b/src/gui/gui.pro index 28eca39e..df0887e6 100644 --- a/src/gui/gui.pro +++ b/src/gui/gui.pro @@ -16,7 +16,8 @@ FORMS += res/MainWindowBase.ui \ res/HotkeyDialogBase.ui \ res/SettingsDialogBase.ui \ res/SetupWizardBase.ui \ - res/AddClientDialogBase.ui + res/AddClientDialogBase.ui \ + res/ActivationDialog.ui SOURCES += src/main.cpp \ src/MainWindow.cpp \ src/AboutDialog.cpp \ @@ -58,7 +59,8 @@ SOURCES += src/main.cpp \ src/SslCertificate.cpp \ src/WebClient.cpp \ src/SubscriptionManager.cpp \ - src/ActivationNotifier.cpp + src/ActivationNotifier.cpp \ + src/ActivationDialog.cpp HEADERS += src/MainWindow.h \ src/AboutDialog.h \ src/ServerConfig.h \ @@ -103,7 +105,8 @@ HEADERS += src/MainWindow.h \ src/WebClient.h \ src/SubscriptionManager.h \ src/ActivationNotifier.h \ - src/ElevateMode.h + src/ElevateMode.h \ + src/ActivationDialog.h RESOURCES += res/Synergy.qrc RC_FILE = res/win/Synergy.rc macx { diff --git a/src/gui/res/MainWindowBase.ui b/src/gui/res/MainWindowBase.ui index 0a47e0d3..fa7955cc 100644 --- a/src/gui/res/MainWindowBase.ui +++ b/src/gui/res/MainWindowBase.ui @@ -1,4 +1,4 @@ - + MainWindowBase @@ -489,6 +489,14 @@ + + + Activate + + + Activate + + diff --git a/src/gui/src/MainWindow.cpp b/src/gui/src/MainWindow.cpp index fa1f48ec..966736e6 100644 --- a/src/gui/src/MainWindow.cpp +++ b/src/gui/src/MainWindow.cpp @@ -27,6 +27,7 @@ #include "ServerConfigDialog.h" #include "SettingsDialog.h" #include "SetupWizard.h" +#include "ActivationDialog.h" #include "ZeroconfService.h" #include "DataDownloader.h" #include "CommandProcess.h" @@ -263,6 +264,7 @@ void MainWindow::createMenuBar() m_pMenuFile->addAction(m_pActionStopSynergy); m_pMenuFile->addSeparator(); m_pMenuFile->addAction(m_pActionWizard); + m_pMenuFile->addAction(m_pActivate); m_pMenuFile->addAction(m_pActionSave); m_pMenuFile->addSeparator(); m_pMenuFile->addAction(m_pActionQuit); @@ -1150,6 +1152,12 @@ void MainWindow::on_m_pActionWizard_triggered() wizard.exec(); } +void MainWindow::on_m_pActivate_triggered() +{ + ActivationDialog activationDialog; + activationDialog.exec(); +} + void MainWindow::on_m_pButtonApply_clicked() { restartSynergy(); diff --git a/src/gui/src/MainWindow.h b/src/gui/src/MainWindow.h index d6d14055..b08709a7 100644 --- a/src/gui/src/MainWindow.h +++ b/src/gui/src/MainWindow.h @@ -113,7 +113,6 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase void serverDetected(const QString name); void setEdition(int type); void updateLocalFingerprint(); - public slots: void appendLogRaw(const QString& text); void appendLogInfo(const QString& text); @@ -130,6 +129,7 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase void on_m_pActionAbout_triggered(); void on_m_pActionSettings_triggered(); void on_m_pActionWizard_triggered(); + void on_m_pActivate_triggered(); void synergyFinished(int exitCode, QProcess::ExitStatus); void trayActivated(QSystemTrayIcon::ActivationReason reason); void stopSynergy(); From 81ae0c211a25510734017cc4d56e2a6852a33cef Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Thu, 29 Sep 2016 13:53:44 +0100 Subject: [PATCH 032/101] #5629 Move activation widgets to new activation dialog --- src/gui/res/ActivationDialog.ui | 218 +++++++++++++++++++++++++++++++ src/gui/src/ActivationDialog.cpp | 14 ++ src/gui/src/ActivationDialog.h | 22 ++++ 3 files changed, 254 insertions(+) create mode 100644 src/gui/res/ActivationDialog.ui create mode 100644 src/gui/src/ActivationDialog.cpp create mode 100644 src/gui/src/ActivationDialog.h diff --git a/src/gui/res/ActivationDialog.ui b/src/gui/res/ActivationDialog.ui new file mode 100644 index 00000000..20b483d1 --- /dev/null +++ b/src/gui/res/ActivationDialog.ui @@ -0,0 +1,218 @@ + + + ActivationDialog + + + + 0 + 0 + 564 + 385 + + + + Dialog + + + + + 30 + 340 + 521 + 32 + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + 30 + 244 + 521 + 70 + + + + + + + 30 + 60 + 520 + 24 + + + + + 75 + true + + + + &Account login + + + true + + + + + + 30 + 214 + 520 + 24 + + + + + 75 + true + + + + &Serial key + + + + + + 30 + 20 + 520 + 18 + + + + Enable your <a href="http://symless.com/pricing?source=gui">Synergy Pro</a> and Synergy Basic features. + + + true + + + + + + 30 + 100 + 285 + 92 + + + + + QFormLayout::AllNonFixedFieldsGrow + + + 20 + + + 10 + + + + + Email: + + + + + + + + 0 + 0 + + + + + 200 + 20 + + + + QLineEdit::Normal + + + + + + + + 0 + 0 + + + + + 200 + 20 + + + + QLineEdit::Password + + + + + + + <a href="https://symless.com/account/reset/?source=gui">Forgot password</a> + + + true + + + + + + + Password: + + + + + + + + + + buttonBox + accepted() + ActivationDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + ActivationDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/gui/src/ActivationDialog.cpp b/src/gui/src/ActivationDialog.cpp new file mode 100644 index 00000000..a08ac114 --- /dev/null +++ b/src/gui/src/ActivationDialog.cpp @@ -0,0 +1,14 @@ +#include "ActivationDialog.h" +#include "ui_ActivationDialog.h" + +ActivationDialog::ActivationDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::ActivationDialog) +{ + ui->setupUi(this); +} + +ActivationDialog::~ActivationDialog() +{ + delete ui; +} diff --git a/src/gui/src/ActivationDialog.h b/src/gui/src/ActivationDialog.h new file mode 100644 index 00000000..52dbd4e0 --- /dev/null +++ b/src/gui/src/ActivationDialog.h @@ -0,0 +1,22 @@ +#ifndef ACTIVATIONDIALOG_H +#define ACTIVATIONDIALOG_H + +#include + +namespace Ui { +class ActivationDialog; +} + +class ActivationDialog : public QDialog +{ + Q_OBJECT + +public: + explicit ActivationDialog(QWidget *parent = 0); + ~ActivationDialog(); + +private: + Ui::ActivationDialog *ui; +}; + +#endif // ACTIVATIONDIALOG_H From d4646b1cc6f857f6baf1a34d913da9c925bad1ef Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Thu, 29 Sep 2016 16:14:09 +0100 Subject: [PATCH 033/101] #5629 Add activation cancellation dialog --- src/gui/gui.pro | 9 ++- src/gui/res/CancelActivationDialog.ui | 89 ++++++++++++++++++++++++++ src/gui/src/CancelActivationDialog.cpp | 14 ++++ src/gui/src/CancelActivationDialog.h | 22 +++++++ 4 files changed, 131 insertions(+), 3 deletions(-) create mode 100644 src/gui/res/CancelActivationDialog.ui create mode 100644 src/gui/src/CancelActivationDialog.cpp create mode 100644 src/gui/src/CancelActivationDialog.h diff --git a/src/gui/gui.pro b/src/gui/gui.pro index df0887e6..ee4ba52b 100644 --- a/src/gui/gui.pro +++ b/src/gui/gui.pro @@ -17,7 +17,8 @@ FORMS += res/MainWindowBase.ui \ res/SettingsDialogBase.ui \ res/SetupWizardBase.ui \ res/AddClientDialogBase.ui \ - res/ActivationDialog.ui + res/ActivationDialog.ui \ + res/CancelActivationDialog.ui SOURCES += src/main.cpp \ src/MainWindow.cpp \ src/AboutDialog.cpp \ @@ -60,7 +61,8 @@ SOURCES += src/main.cpp \ src/WebClient.cpp \ src/SubscriptionManager.cpp \ src/ActivationNotifier.cpp \ - src/ActivationDialog.cpp + src/ActivationDialog.cpp \ + src/CancelActivationDialog.cpp HEADERS += src/MainWindow.h \ src/AboutDialog.h \ src/ServerConfig.h \ @@ -106,7 +108,8 @@ HEADERS += src/MainWindow.h \ src/SubscriptionManager.h \ src/ActivationNotifier.h \ src/ElevateMode.h \ - src/ActivationDialog.h + src/ActivationDialog.h \ + src/CancelActivationDialog.h RESOURCES += res/Synergy.qrc RC_FILE = res/win/Synergy.rc macx { diff --git a/src/gui/res/CancelActivationDialog.ui b/src/gui/res/CancelActivationDialog.ui new file mode 100644 index 00000000..2c6ef41b --- /dev/null +++ b/src/gui/res/CancelActivationDialog.ui @@ -0,0 +1,89 @@ + + + CancelActivationDialog + + + + 0 + 0 + 400 + 156 + + + + Cancel Activation + + + + + + Are you sure? + +If you don't activate Synergy you'll be missing out on some great features + + + true + + + true + + + + + + + <html><head/><body><p><a href="https://symless.com/pricing?source=gui"><span style=" text-decoration: underline; color:#0000ff;">Buy now</span></a></p></body></html> + + + true + + + + + + + Qt::Horizontal + + + QDialogButtonBox::No|QDialogButtonBox::Yes + + + + + + + + + buttonBox + accepted() + CancelActivationDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + CancelActivationDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/gui/src/CancelActivationDialog.cpp b/src/gui/src/CancelActivationDialog.cpp new file mode 100644 index 00000000..074b76bb --- /dev/null +++ b/src/gui/src/CancelActivationDialog.cpp @@ -0,0 +1,14 @@ +#include "CancelActivationDialog.h" +#include "ui_CancelActivationDialog.h" + +CancelActivationDialog::CancelActivationDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::CancelActivationDialog) +{ + ui->setupUi(this); +} + +CancelActivationDialog::~CancelActivationDialog() +{ + delete ui; +} diff --git a/src/gui/src/CancelActivationDialog.h b/src/gui/src/CancelActivationDialog.h new file mode 100644 index 00000000..b90af083 --- /dev/null +++ b/src/gui/src/CancelActivationDialog.h @@ -0,0 +1,22 @@ +#ifndef CANCELACTIVATIONDIALOG_H +#define CANCELACTIVATIONDIALOG_H + +#include + +namespace Ui { +class CancelActivationDialog; +} + +class CancelActivationDialog : public QDialog +{ + Q_OBJECT + +public: + explicit CancelActivationDialog(QWidget *parent = 0); + ~CancelActivationDialog(); + +private: + Ui::CancelActivationDialog *ui; +}; + +#endif // CANCELACTIVATIONDIALOG_H From 0d5d7e11c06a5b599e904a03ec4777bf50f268ef Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Thu, 29 Sep 2016 16:16:49 +0100 Subject: [PATCH 034/101] #5629 Simplify Activation dialog --- src/gui/res/ActivationDialog.ui | 297 ++++++++++++++------------------ 1 file changed, 129 insertions(+), 168 deletions(-) diff --git a/src/gui/res/ActivationDialog.ui b/src/gui/res/ActivationDialog.ui index 20b483d1..63e9e261 100644 --- a/src/gui/res/ActivationDialog.ui +++ b/src/gui/res/ActivationDialog.ui @@ -6,179 +6,140 @@ 0 0 - 564 - 385 + 440 + 314 Dialog - - - - 30 - 340 - 521 - 32 - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - 30 - 244 - 521 - 70 - - - - - - - 30 - 60 - 520 - 24 - - - - - 75 - true - - - - &Account login - - - true - - - - - - 30 - 214 - 520 - 24 - - - - - 75 - true - - - - &Serial key - - - - - - 30 - 20 - 520 - 18 - - - - Enable your <a href="http://symless.com/pricing?source=gui">Synergy Pro</a> and Synergy Basic features. - - - true - - - - - - 30 - 100 - 285 - 92 - - - - - QFormLayout::AllNonFixedFieldsGrow - - - 20 - - - 10 - - - - - Email: - - - - - - - - 0 - 0 - - - - - 200 - 20 - - - - QLineEdit::Normal - - - - - - - - 0 - 0 - - - - - 200 - 20 - - - - QLineEdit::Password - - - - - - - <a href="https://symless.com/account/reset/?source=gui">Forgot password</a> - - - true - - - - - - - Password: - - - - - + + + + + + 75 + true + + + + &Account login + + + true + + + + + + + QFormLayout::AllNonFixedFieldsGrow + + + 20 + + + 10 + + + + + Email: + + + + + + + + 0 + 0 + + + + + 200 + 20 + + + + QLineEdit::Normal + + + + + + + Password: + + + + + + + + 0 + 0 + + + + + 200 + 20 + + + + QLineEdit::Password + + + + + + + + + + 75 + true + + + + &Serial key + + + + + + + Found on your <a href="https://symless.com/account/?source=gui">account</a> page. + + + true + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + From 60a4e627795bda1ffb85baa915e695ef1886b5f1 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Thu, 29 Sep 2016 16:17:38 +0100 Subject: [PATCH 035/101] #5629 Enable activation cancellation dialog --- src/gui/src/ActivationDialog.cpp | 9 +++++++++ src/gui/src/ActivationDialog.h | 3 +++ src/gui/src/MainWindow.cpp | 2 +- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/gui/src/ActivationDialog.cpp b/src/gui/src/ActivationDialog.cpp index a08ac114..da7e934a 100644 --- a/src/gui/src/ActivationDialog.cpp +++ b/src/gui/src/ActivationDialog.cpp @@ -1,5 +1,6 @@ #include "ActivationDialog.h" #include "ui_ActivationDialog.h" +#include "CancelActivationDialog.h" ActivationDialog::ActivationDialog(QWidget *parent) : QDialog(parent), @@ -12,3 +13,11 @@ ActivationDialog::~ActivationDialog() { delete ui; } + +void ActivationDialog::reject() +{ + CancelActivationDialog cancelActivationDialog(this); + if (QDialog::Accepted == cancelActivationDialog.exec()) { + QDialog::reject(); + } +} diff --git a/src/gui/src/ActivationDialog.h b/src/gui/src/ActivationDialog.h index 52dbd4e0..396c4104 100644 --- a/src/gui/src/ActivationDialog.h +++ b/src/gui/src/ActivationDialog.h @@ -14,6 +14,9 @@ class ActivationDialog : public QDialog public: explicit ActivationDialog(QWidget *parent = 0); ~ActivationDialog(); + +public slots: + void reject(); private: Ui::ActivationDialog *ui; diff --git a/src/gui/src/MainWindow.cpp b/src/gui/src/MainWindow.cpp index 966736e6..64f9f425 100644 --- a/src/gui/src/MainWindow.cpp +++ b/src/gui/src/MainWindow.cpp @@ -1154,7 +1154,7 @@ void MainWindow::on_m_pActionWizard_triggered() void MainWindow::on_m_pActivate_triggered() { - ActivationDialog activationDialog; + ActivationDialog activationDialog (this); activationDialog.exec(); } From d48f6801f0a8ef79845a5b7025f2257f7e7e1900 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Mon, 3 Oct 2016 13:44:21 +0100 Subject: [PATCH 036/101] Disable DPI scaling on core binaries --- res/dpiaware.manifest | 8 ++++++++ src/cmd/synergyc/CMakeLists.txt | 9 +++++++++ src/cmd/synergyd/CMakeLists.txt | 9 +++++++++ src/cmd/synergys/CMakeLists.txt | 9 +++++++++ 4 files changed, 35 insertions(+) create mode 100644 res/dpiaware.manifest diff --git a/res/dpiaware.manifest b/res/dpiaware.manifest new file mode 100644 index 00000000..5de107ba --- /dev/null +++ b/res/dpiaware.manifest @@ -0,0 +1,8 @@ + + + + + true + + + \ No newline at end of file diff --git a/src/cmd/synergyc/CMakeLists.txt b/src/cmd/synergyc/CMakeLists.txt index 11d428d4..922ee324 100644 --- a/src/cmd/synergyc/CMakeLists.txt +++ b/src/cmd/synergyc/CMakeLists.txt @@ -60,6 +60,15 @@ add_executable(synergyc ${sources}) target_link_libraries(synergyc arch base client common io mt net ipc platform server synergy ${libs}) +if (WIN32) + ADD_CUSTOM_COMMAND( + TARGET synergyc + POST_BUILD + COMMAND "mt.exe" -manifest \"${CMAKE_SOURCE_DIR}\\res\\dpiaware.manifest\" -inputresource:\"$\"\;\#1 -outputresource:\"$\"\;\#1 + COMMENT "Adding display aware manifest..." + ) +endif() + if (CONF_CPACK) install(TARGETS synergyc diff --git a/src/cmd/synergyd/CMakeLists.txt b/src/cmd/synergyd/CMakeLists.txt index 1caa35b5..49a6a7f8 100644 --- a/src/cmd/synergyd/CMakeLists.txt +++ b/src/cmd/synergyd/CMakeLists.txt @@ -37,6 +37,15 @@ endif() target_link_libraries(synergyd arch base common io ipc mt net platform synergy ${libs}) +if (WIN32) + ADD_CUSTOM_COMMAND( + TARGET synergyd + POST_BUILD + COMMAND "mt.exe" -manifest \"${CMAKE_SOURCE_DIR}\\res\\dpiaware.manifest\" -inputresource:\"$\"\;\#1 -outputresource:\"$\"\;\#1 + COMMENT "Adding display aware manifest..." + ) +endif() + if (CONF_CPACK) install(TARGETS synergyd diff --git a/src/cmd/synergys/CMakeLists.txt b/src/cmd/synergys/CMakeLists.txt index c749e09a..3e2faad1 100644 --- a/src/cmd/synergys/CMakeLists.txt +++ b/src/cmd/synergys/CMakeLists.txt @@ -60,6 +60,15 @@ add_executable(synergys ${sources}) target_link_libraries(synergys arch base client common io mt net ipc platform server synergy ${libs}) +if (WIN32) + ADD_CUSTOM_COMMAND( + TARGET synergys + POST_BUILD + COMMAND "mt.exe" -manifest \"${CMAKE_SOURCE_DIR}\\res\\dpiaware.manifest\" -inputresource:\"$\"\;\#1 -outputresource:\"$\"\;\#1 + COMMENT "Adding display aware manifest..." + ) +endif() + if (CONF_CPACK) install(TARGETS synergys From 8788faffdd031a6967bcebe4a6783e609d10534c Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Mon, 3 Oct 2016 14:41:53 +0100 Subject: [PATCH 037/101] Enable Windows 7 compatibility mode for core binaries --- res/dpiaware.manifest | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/res/dpiaware.manifest b/res/dpiaware.manifest index 5de107ba..743e3369 100644 --- a/res/dpiaware.manifest +++ b/res/dpiaware.manifest @@ -1,8 +1,15 @@ - - - - - true - - - \ No newline at end of file + + + + + + + + + + + true + + + + From 0f95c6e941c9a8b545f3903e4e1842c229d60fe7 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Fri, 30 Sep 2016 15:03:49 +0100 Subject: [PATCH 038/101] #5629 Complete activation support for activation dialog --- src/gui/res/ActivationDialog.ui | 24 ++--- src/gui/res/CancelActivationDialog.ui | 2 +- src/gui/src/ActivationDialog.cpp | 147 +++++++++++++++++++++++++- src/gui/src/ActivationDialog.h | 13 ++- src/gui/src/AppConfig.cpp | 91 +++++++++++++++- src/gui/src/AppConfig.h | 75 ++++++------- src/gui/src/EditionType.h | 6 +- src/gui/src/MainWindow.cpp | 20 +--- src/gui/src/MainWindow.h | 4 +- src/gui/src/QUtility.cpp | 17 +++ src/gui/src/QUtility.h | 1 + src/gui/src/SetupWizard.cpp | 9 +- src/gui/src/SubscriptionManager.cpp | 4 +- src/gui/src/WebClient.cpp | 96 +++++++---------- src/gui/src/WebClient.h | 16 +-- 15 files changed, 375 insertions(+), 150 deletions(-) diff --git a/src/gui/res/ActivationDialog.ui b/src/gui/res/ActivationDialog.ui index 63e9e261..fb700f91 100644 --- a/src/gui/res/ActivationDialog.ui +++ b/src/gui/res/ActivationDialog.ui @@ -11,7 +11,7 @@ - Dialog + Activate Synergy @@ -51,17 +51,11 @@ - + 0 0 - - - 200 - 20 - - QLineEdit::Normal @@ -77,17 +71,11 @@ - + 0 0 - - - 200 - 20 - - QLineEdit::Password @@ -120,6 +108,9 @@ + + false + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> @@ -127,6 +118,9 @@ p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> + + false + diff --git a/src/gui/res/CancelActivationDialog.ui b/src/gui/res/CancelActivationDialog.ui index 2c6ef41b..b98733f6 100644 --- a/src/gui/res/CancelActivationDialog.ui +++ b/src/gui/res/CancelActivationDialog.ui @@ -7,7 +7,7 @@ 0 0 400 - 156 + 165 diff --git a/src/gui/src/ActivationDialog.cpp b/src/gui/src/ActivationDialog.cpp index da7e934a..df0d1618 100644 --- a/src/gui/src/ActivationDialog.cpp +++ b/src/gui/src/ActivationDialog.cpp @@ -1,12 +1,44 @@ #include "ActivationDialog.h" #include "ui_ActivationDialog.h" #include "CancelActivationDialog.h" +#include "AppConfig.h" +#include "WebClient.h" +#include "EditionType.h" +#include "ActivationNotifier.h" +#include "MainWindow.h" +#include "QUtility.h" +#include "SubscriptionManager.h" -ActivationDialog::ActivationDialog(QWidget *parent) : +#include +#include +#include + +ActivationDialog::ActivationDialog(QWidget* parent, AppConfig& appConfig) : QDialog(parent), - ui(new Ui::ActivationDialog) + ui(new Ui::ActivationDialog), + m_appConfig (&appConfig) { ui->setupUi(this); + + ui->m_pLineEditEmail->setText(appConfig.activateEmail()); + ui->m_pTextEditSerialKey->setText(appConfig.serialKey()); + + if (!appConfig.serialKey().isEmpty()) { + ui->m_pRadioButtonActivate->setAutoExclusive(false); + ui->m_pRadioButtonSubscription->setAutoExclusive(false); + ui->m_pRadioButtonActivate->setChecked(false); + ui->m_pRadioButtonSubscription->setChecked(true); + ui->m_pRadioButtonActivate->setAutoExclusive(true); + ui->m_pRadioButtonSubscription->setAutoExclusive(true); + ui->m_pTextEditSerialKey->setFocus(); + ui->m_pTextEditSerialKey->moveCursor(QTextCursor::End); + } else { + if (ui->m_pLineEditEmail->text().isEmpty()) { + ui->m_pLineEditEmail->setFocus(); + } else { + ui->m_pLineEditPassword->setFocus(); + } + } } ActivationDialog::~ActivationDialog() @@ -14,10 +46,121 @@ ActivationDialog::~ActivationDialog() delete ui; } +void ActivationDialog::notifyActivation(QString identity) +{ + ActivationNotifier* notifier = new ActivationNotifier(); + notifier->setIdentity(identity); + + QThread* thread = new QThread(); + connect(notifier, SIGNAL(finished()), thread, SLOT(quit())); + connect(notifier, SIGNAL(finished()), notifier, SLOT(deleteLater())); + connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); + + notifier->moveToThread(thread); + thread->start(); + + QMetaObject::invokeMethod(notifier, "notify", Qt::QueuedConnection); +} + void ActivationDialog::reject() { CancelActivationDialog cancelActivationDialog(this); if (QDialog::Accepted == cancelActivationDialog.exec()) { + notifyActivation("skip:unknown"); QDialog::reject(); } } + +void ActivationDialog::on_m_pRadioButtonSubscription_toggled(bool checked) +{ + if (checked) { + ui->m_pLineEditEmail->setEnabled(false); + ui->m_pLineEditPassword->setEnabled(false); + ui->m_pTextEditSerialKey->setEnabled(true); + ui->m_pTextEditSerialKey->setFocus(); + } +} + +void ActivationDialog::on_m_pRadioButtonActivate_toggled(bool checked) +{ + if (checked) { + ui->m_pLineEditEmail->setEnabled(true); + ui->m_pLineEditPassword->setEnabled(true); + ui->m_pTextEditSerialKey->setEnabled(false); + if (ui->m_pLineEditEmail->text().isEmpty()) { + ui->m_pLineEditEmail->setFocus(); + } else { + ui->m_pLineEditPassword->setFocus(); + } + } +} + +void ActivationDialog::accept() +{ + QMessageBox message; + QString error; + int edition = Unregistered; + + try { + if (ui->m_pRadioButtonActivate->isChecked()) { + WebClient webClient; + QString email = ui->m_pLineEditEmail->text(); + QString password = ui->m_pLineEditPassword->text(); + + if (!webClient.setEmail (email, error)) { + message.critical (this, "Invalid Email Address", tr("%1").arg(error)); + return; + } + else if (!webClient.setPassword (password, error)) { + message.critical (this, "Invalid Password", tr("%1").arg(error)); + return; + } + else if (!webClient.getEdition (edition, error)) { + message.critical (this, "Activation Error", + tr("An error occurred while trying to activate Synergy. " + "The Symless server returned the following error:\n\n%1").arg(error)); + return; + } + + m_appConfig->setActivateEmail (email); + m_appConfig->clearSerialKey(); + ui->m_pTextEditSerialKey->clear(); + notifyActivation ("login:" + m_appConfig->activateEmail()); + } + else { + QString serialKey = ui->m_pTextEditSerialKey->toPlainText(); + + if (!m_appConfig->setSerialKey (serialKey, error)) { + message.critical (this, "Invalid Serial Key", tr("%1").arg(error)); + return; + } + + SubscriptionManager subscriptionManager (this, *m_appConfig, edition); + if (!subscriptionManager.activateSerial (serialKey)) { + return; + } + m_appConfig->setActivateEmail(""); + notifyActivation ("serial:" + m_appConfig->serialKey()); + } + } + catch (std::exception& e) { + message.critical (this, "Unknown Error", + tr("An error occurred while trying to activate Synergy. " + "Please contact the helpdesk, and provide the " + "following details.\n\n%1").arg(e.what())); + return; + } + + m_appConfig->setEdition(edition); + m_appConfig->saveSettings(); + + message.information (this, "Activated!", + tr("Thanks for activating %1!").arg + (getEditionName (edition))); + MainWindow& mainWindow = dynamic_cast(*this->parent()); + mainWindow.setEdition(edition); + mainWindow.updateLocalFingerprint(); + mainWindow.settings().sync(); + + QDialog::accept(); +} diff --git a/src/gui/src/ActivationDialog.h b/src/gui/src/ActivationDialog.h index 396c4104..6fb926cc 100644 --- a/src/gui/src/ActivationDialog.h +++ b/src/gui/src/ActivationDialog.h @@ -7,19 +7,30 @@ namespace Ui { class ActivationDialog; } +class AppConfig; + class ActivationDialog : public QDialog { Q_OBJECT public: - explicit ActivationDialog(QWidget *parent = 0); + explicit ActivationDialog(QWidget *parent, AppConfig& appConfig); ~ActivationDialog(); public slots: void reject(); + void accept(); + +protected: + void notifyActivation (QString identity); private: Ui::ActivationDialog *ui; + AppConfig* m_appConfig; + +private slots: + void on_m_pRadioButtonSubscription_toggled(bool checked); + void on_m_pRadioButtonActivate_toggled(bool checked); }; #endif // ACTIVATIONDIALOG_H diff --git a/src/gui/src/AppConfig.cpp b/src/gui/src/AppConfig.cpp index a48bbc04..6347c6cf 100644 --- a/src/gui/src/AppConfig.cpp +++ b/src/gui/src/AppConfig.cpp @@ -73,6 +73,18 @@ AppConfig::~AppConfig() saveSettings(); } +const QString &AppConfig::screenName() const { return m_ScreenName; } + +int AppConfig::port() const { return m_Port; } + +const QString &AppConfig::interface() const { return m_Interface; } + +int AppConfig::logLevel() const { return m_LogLevel; } + +bool AppConfig::logToFile() const { return m_LogToFile; } + +const QString &AppConfig::logFilename() const { return m_LogFilename; } + QString AppConfig::synergyLogDir() const { #if defined(Q_OS_WIN) @@ -116,6 +128,16 @@ QString AppConfig::logLevelText() const return logLevelNames[logLevel()]; } +ProcessMode AppConfig::processMode() const { return m_ProcessMode; } + +bool AppConfig::wizardShouldRun() const { return m_WizardLastRun < kWizardVersion; } + +const QString &AppConfig::language() const { return m_Language; } + +bool AppConfig::startedBefore() const { return m_StartedBefore; } + +bool AppConfig::autoConfig() const { return m_AutoConfig; } + void AppConfig::loadSettings() { m_ScreenName = settings().value("screenName", QHostInfo::localHostName()).toString(); @@ -135,7 +157,7 @@ void AppConfig::loadSettings() } m_ElevateMode = static_cast(elevateMode.toInt()); m_AutoConfigPrompted = settings().value("autoConfigPrompted", false).toBool(); - m_Edition = settings().value("edition", Unknown).toInt(); + m_Edition = settings().value("edition", Unregistered).toInt(); m_ActivateEmail = settings().value("activateEmail", "").toString(); m_CryptoEnabled = settings().value("cryptoEnabled", false).toBool(); m_AutoHide = settings().value("autoHide", false).toBool(); @@ -168,17 +190,84 @@ void AppConfig::saveSettings() settings().setValue("lastExpiringWarningTime", m_LastExpiringWarningTime); } +QSettings &AppConfig::settings() { return *m_pSettings; } + +void AppConfig::setScreenName(const QString &s) { m_ScreenName = s; } + +void AppConfig::setPort(int i) { m_Port = i; } + +void AppConfig::setInterface(const QString &s) { m_Interface = s; } + +void AppConfig::setLogLevel(int i) { m_LogLevel = i; } + +void AppConfig::setLogToFile(bool b) { m_LogToFile = b; } + +void AppConfig::setLogFilename(const QString &s) { m_LogFilename = s; } + +void AppConfig::setWizardHasRun() { m_WizardLastRun = kWizardVersion; } + +void AppConfig::setLanguage(const QString language) { m_Language = language; } + +void AppConfig::setStartedBefore(bool b) { m_StartedBefore = b; } + +void AppConfig::setElevateMode(ElevateMode em) { m_ElevateMode = em; } + void AppConfig::setAutoConfig(bool autoConfig) { m_AutoConfig = autoConfig; } +bool AppConfig::autoConfigPrompted() { return m_AutoConfigPrompted; } + void AppConfig::setAutoConfigPrompted(bool prompted) { m_AutoConfigPrompted = prompted; } +void AppConfig::setEdition(int e) { m_Edition = e; } + +int AppConfig::edition() { return m_Edition; } + +bool AppConfig::setActivateEmail(QString e) { + m_ActivateEmail = e; + return true; +} + +QString AppConfig::activateEmail() { return m_ActivateEmail; } + +bool AppConfig::setSerialKey(QString serial, QString& errorOut) { + if (serial.isEmpty()) { + errorOut = "Your serial key cannot be blank."; + return false; + } + m_Serialkey = serial; + return true; +} + +void AppConfig::clearSerialKey() +{ + m_Serialkey.clear(); +} + +QString AppConfig::serialKey() { return m_Serialkey; } + +int AppConfig::lastExpiringWarningTime() const { return m_LastExpiringWarningTime; } + +void AppConfig::setLastExpiringWarningTime(int t) { m_LastExpiringWarningTime = t; } + +QString AppConfig::synergysName() const { return m_SynergysName; } + +QString AppConfig::synergycName() const { return m_SynergycName; } + ElevateMode AppConfig::elevateMode() { return m_ElevateMode; } + +void AppConfig::setCryptoEnabled(bool e) { m_CryptoEnabled = e; } + +bool AppConfig::getCryptoEnabled() { return m_CryptoEnabled; } + +void AppConfig::setAutoHide(bool b) { m_AutoHide = b; } + +bool AppConfig::getAutoHide() { return m_AutoHide; } diff --git a/src/gui/src/AppConfig.h b/src/gui/src/AppConfig.h index 43e35c7f..df391bfb 100644 --- a/src/gui/src/AppConfig.h +++ b/src/gui/src/AppConfig.h @@ -58,33 +58,34 @@ class AppConfig ~AppConfig(); public: - const QString& screenName() const { return m_ScreenName; } - int port() const { return m_Port; } - const QString& interface() const { return m_Interface; } - int logLevel() const { return m_LogLevel; } - bool logToFile() const { return m_LogToFile; } - const QString& logFilename() const { return m_LogFilename; } + const QString& screenName() const; + int port() const; + const QString& interface() const; + int logLevel() const; + bool logToFile() const; + const QString& logFilename() const; const QString logFilenameCmd() const; QString logLevelText() const; - ProcessMode processMode() const { return m_ProcessMode; } - bool wizardShouldRun() const { return m_WizardLastRun < kWizardVersion; } - const QString& language() const { return m_Language; } - bool startedBefore() const { return m_StartedBefore; } - bool autoConfig() const { return m_AutoConfig; } + ProcessMode processMode() const; + bool wizardShouldRun() const; + const QString& language() const; + bool startedBefore() const; + bool autoConfig() const; void setAutoConfig(bool autoConfig); - bool autoConfigPrompted() { return m_AutoConfigPrompted; } + bool autoConfigPrompted(); void setAutoConfigPrompted(bool prompted); - void setEdition(int e) { m_Edition = e; } - int edition() { return m_Edition; } - void setActivateEmail(QString e) { m_ActivateEmail = e; } - QString activateEmail() { return m_ActivateEmail; } - void setSerialKey(QString serial) { m_Serialkey = serial; } - QString serialKey() { return m_Serialkey; } - int lastExpiringWarningTime() const { return m_LastExpiringWarningTime; } - void setLastExpiringWarningTime(int t) { m_LastExpiringWarningTime = t; } + void setEdition(int e); + int edition(); + bool setActivateEmail(QString e); + QString activateEmail(); + bool setSerialKey(QString serial, QString& error); + void clearSerialKey(); + QString serialKey(); + int lastExpiringWarningTime() const; + void setLastExpiringWarningTime(int t); - QString synergysName() const { return m_SynergysName; } - QString synergycName() const { return m_SynergycName; } + QString synergysName() const; + QString synergycName() const; QString synergyProgramDir() const; QString synergyLogDir() const; @@ -92,25 +93,25 @@ class AppConfig void persistLogDir(); ElevateMode elevateMode(); - void setCryptoEnabled(bool e) { m_CryptoEnabled = e; } - bool getCryptoEnabled() { return m_CryptoEnabled; } - void setAutoHide(bool b) { m_AutoHide = b; } - bool getAutoHide() { return m_AutoHide; } + void setCryptoEnabled(bool e); + bool getCryptoEnabled(); + void setAutoHide(bool b); + bool getAutoHide(); void saveSettings(); protected: - QSettings& settings() { return *m_pSettings; } - void setScreenName(const QString& s) { m_ScreenName = s; } - void setPort(int i) { m_Port = i; } - void setInterface(const QString& s) { m_Interface = s; } - void setLogLevel(int i) { m_LogLevel = i; } - void setLogToFile(bool b) { m_LogToFile = b; } - void setLogFilename(const QString& s) { m_LogFilename = s; } - void setWizardHasRun() { m_WizardLastRun = kWizardVersion; } - void setLanguage(const QString language) { m_Language = language; } - void setStartedBefore(bool b) { m_StartedBefore = b; } - void setElevateMode(ElevateMode em) { m_ElevateMode = em; } + QSettings& settings(); + void setScreenName(const QString& s); + void setPort(int i); + void setInterface(const QString& s); + void setLogLevel(int i); + void setLogToFile(bool b); + void setLogFilename(const QString& s); + void setWizardHasRun(); + void setLanguage(const QString language); + void setStartedBefore(bool b); + void setElevateMode(ElevateMode em); void loadSettings(); diff --git a/src/gui/src/EditionType.h b/src/gui/src/EditionType.h index d294cda5..5869a32b 100644 --- a/src/gui/src/EditionType.h +++ b/src/gui/src/EditionType.h @@ -18,11 +18,13 @@ #ifndef EDITIONTYPE_H #define EDITIONTYPE_H -enum qEditionType { +/* Do not reorder these! */ + +enum EditionType { Basic, Pro, Trial, - Unknown + Unregistered }; #endif // EDITIONTYPE_H diff --git a/src/gui/src/MainWindow.cpp b/src/gui/src/MainWindow.cpp index 64f9f425..15c20d12 100644 --- a/src/gui/src/MainWindow.cpp +++ b/src/gui/src/MainWindow.cpp @@ -1015,23 +1015,9 @@ void MainWindow::serverDetected(const QString name) } } -void MainWindow::setEdition(int type) +void MainWindow::setEdition(int edition) { - QString title; - if (type == Basic) { - title = "Synergy Basic"; - } - else if (type == Pro) { - title = "Synergy Pro"; - } - else if (type == Trial) { - title = "Synergy Trial"; - } - else { - title = "Synergy (UNREGISTERED)"; - } - - setWindowTitle(title); + setWindowTitle(getEditionName(edition)); } void MainWindow::updateLocalFingerprint() @@ -1154,7 +1140,7 @@ void MainWindow::on_m_pActionWizard_triggered() void MainWindow::on_m_pActivate_triggered() { - ActivationDialog activationDialog (this); + ActivationDialog activationDialog (this, this->appConfig()); activationDialog.exec(); } diff --git a/src/gui/src/MainWindow.h b/src/gui/src/MainWindow.h index b08709a7..8788e4a2 100644 --- a/src/gui/src/MainWindow.h +++ b/src/gui/src/MainWindow.h @@ -33,6 +33,7 @@ #include "VersionChecker.h" #include "IpcClient.h" #include "Ipc.h" +#include "ActivationDialog.h" #include @@ -63,6 +64,7 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase friend class QSynergyApplication; friend class SetupWizard; + friend class ActivationDialog; public: enum qSynergyState @@ -111,7 +113,7 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase void autoAddScreen(const QString name); void updateZeroconfService(); void serverDetected(const QString name); - void setEdition(int type); + void setEdition(int edition); void updateLocalFingerprint(); public slots: void appendLogRaw(const QString& text); diff --git a/src/gui/src/QUtility.cpp b/src/gui/src/QUtility.cpp index a21343ec..ca2c52c0 100644 --- a/src/gui/src/QUtility.cpp +++ b/src/gui/src/QUtility.cpp @@ -19,6 +19,7 @@ #include "ProcessorArch.h" #include "CommandProcess.h" +#include "EditionType.h" #if defined(Q_OS_LINUX) #include @@ -42,6 +43,22 @@ void setIndexFromItemData(QComboBox* comboBox, const QVariant& itemData) } } +QString +getEditionName (int edition) { + if (edition == Basic) { + return "Synergy Basic"; + } + else if (edition == Pro) { + return "Synergy Pro"; + } + else if (edition == Trial) { + return "Synergy Trial"; + } + else { + return "Synergy (UNREGISTERED)"; + } +} + QString hash(const QString& string) { QByteArray data = string.toUtf8(); diff --git a/src/gui/src/QUtility.h b/src/gui/src/QUtility.h index 0738d96c..ca00d06f 100644 --- a/src/gui/src/QUtility.h +++ b/src/gui/src/QUtility.h @@ -29,3 +29,4 @@ QString hash(const QString& string); QString getFirstMacAddress(); qProcessorArch getProcessorArch(); QString getOSInformation(); +QString getEditionName (int edition); diff --git a/src/gui/src/SetupWizard.cpp b/src/gui/src/SetupWizard.cpp index ed574e04..6a28c2f8 100644 --- a/src/gui/src/SetupWizard.cpp +++ b/src/gui/src/SetupWizard.cpp @@ -29,7 +29,7 @@ SetupWizard::SetupWizard(MainWindow& mainWindow, bool startMain) : m_MainWindow(mainWindow), m_StartMain(startMain), - m_Edition(Unknown), + m_Edition(Unregistered), m_LoginAttemps(0) { setupUi(this); @@ -76,7 +76,7 @@ bool SetupWizard::validateCurrentPage() message.setWindowTitle(tr("Setup Synergy")); message.setIcon(QMessageBox::Information); - if (currentPage() == m_pActivatePage) + /*if (currentPage() == m_pActivatePage) { if (m_pRadioButtonActivate->isChecked()) { if (m_pLineEditEmail->text().isEmpty() || @@ -136,7 +136,8 @@ bool SetupWizard::validateCurrentPage() return true; } } - else if (currentPage() == m_pNodePage) + else */ + if (currentPage() == m_pNodePage) { bool result = m_pClientRadioButton->isChecked() || m_pServerRadioButton->isChecked(); @@ -201,7 +202,7 @@ void SetupWizard::accept() if (m_pRadioButtonSubscription->isChecked()) { - appConfig.setSerialKey(m_pTextEditSerialKey->toPlainText()); + //appConfig.setSerialKey(m_pTextEditSerialKey->toPlainText()); notifyActivation("serial:" + m_pTextEditSerialKey->toPlainText()); } diff --git a/src/gui/src/SubscriptionManager.cpp b/src/gui/src/SubscriptionManager.cpp index 52096a11..107bdff1 100644 --- a/src/gui/src/SubscriptionManager.cpp +++ b/src/gui/src/SubscriptionManager.cpp @@ -39,7 +39,7 @@ SubscriptionManager::SubscriptionManager(QWidget* parent, AppConfig& appConfig, bool SubscriptionManager::activateSerial(const QString& serial) { - m_Edition = Unknown; + m_Edition = Unregistered; persistDirectory(); CoreInterface coreInterface; QString output; @@ -62,7 +62,7 @@ bool SubscriptionManager::activateSerial(const QString& serial) bool SubscriptionManager::checkSubscription() { - m_Edition = Unknown; + m_Edition = Unregistered; persistDirectory(); CoreInterface coreInterface; QString output; diff --git a/src/gui/src/WebClient.cpp b/src/gui/src/WebClient.cpp index 4b4b999b..a0a6118a 100644 --- a/src/gui/src/WebClient.cpp +++ b/src/gui/src/WebClient.cpp @@ -25,76 +25,60 @@ #include #include -int WebClient::getEdition( - const QString& email, - const QString& password, - QMessageBox& message, - QWidget* w) -{ - QString responseJson; - int edition = Unknown; - try { - responseJson = request(email, password); - } - catch (std::exception& e) - { - message.critical( - w, "Error", - tr("An error occurred while trying to sign in. " - "Please contact the helpdesk, and provide the " - "following details.\n\n%1").arg(e.what())); - return edition; - } +bool +WebClient::getEdition (int& edition, QString& errorOut) { + QString responseJson = request(); + + /* TODO: This is horrible and should be ripped out as soon as we move + * to Qt 5. See issue #5630 + */ QRegExp resultRegex(".*\"result\".*:.*(true|false).*"); - if (resultRegex.exactMatch(responseJson)) { + if (resultRegex.exactMatch (responseJson)) { QString boolString = resultRegex.cap(1); if (boolString == "true") { QRegExp editionRegex(".*\"edition\".*:.*\"([^\"]+)\".*"); if (editionRegex.exactMatch(responseJson)) { QString e = editionRegex.cap(1); edition = e.toInt(); + return true; + } else { + throw std::runtime_error ("Unrecognised server response."); } - - return edition; + } else { + errorOut = tr("Login failed. Invalid email or password."); + return false; } - else if (boolString == "false") { - message.critical( - w, "Error", - tr("Login failed, invalid email or password.")); - - return edition; - } - } - else { + } else { QRegExp errorRegex(".*\"error\".*:.*\"([^\"]+)\".*"); - if (errorRegex.exactMatch(responseJson)) { - - // replace "\n" with real new lines. - QString error = errorRegex.cap(1).replace("\\n", "\n"); - message.critical( - w, "Error", - tr("Login failed, an error occurred.\n\n%1").arg(error)); - - return edition; + if (errorRegex.exactMatch (responseJson)) { + errorOut = errorRegex.cap(1).replace("\\n", "\n"); + return false; + } else { + throw std::runtime_error ("Unrecognised server response."); } } - - message.critical( - w, "Error", - tr("Login failed, an error occurred.\n\nServer response:\n\n%1") - .arg(responseJson)); - - return edition; } -QString WebClient::request( - const QString& email, - const QString& password) -{ +bool +WebClient::setEmail (QString email, QString& errorOut) { + if (email.isEmpty()) { + errorOut = tr("Your email address cannot be left blank."); + return false; + } + m_Email = email; + return true; +} + +bool +WebClient::setPassword (QString password, QString&) { + m_Password = password; + return true; +} + +QString +WebClient::request() { QStringList args("--login-auth"); - // hash password in case it contains interesting chars. - QString credentials(email + ":" + hash(password) + "\n"); - - return m_CoreInterface.run(args, credentials); + QString credentials (m_Email + ":" + hash(m_Password) + "\n"); + return m_CoreInterface.run (args, credentials); } diff --git a/src/gui/src/WebClient.h b/src/gui/src/WebClient.h index 100b63d1..7ff6e2be 100644 --- a/src/gui/src/WebClient.h +++ b/src/gui/src/WebClient.h @@ -32,21 +32,15 @@ class WebClient : public QObject Q_OBJECT public: - int getEdition(const QString& email, - const QString& password, - QMessageBox& message, - QWidget* w); - void setEmail(QString& e) { m_Email = e; } - void setPassword(QString& p) { m_Password = p; } - + bool getEdition (int& edition, QString& errorOut); + bool setEmail (QString email, QString& errorOut); + bool setPassword (QString password, QString& errorOut); signals: void error(QString e); private: - QString request(const QString& email, - const QString& password); - -private: + QString request(); + QString m_Email; QString m_Password; CoreInterface m_CoreInterface; From 6033f0c946d22f02d277fbc4e0622d810c4809bb Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Fri, 30 Sep 2016 15:21:12 +0100 Subject: [PATCH 039/101] #5629 Minor grammar tweaks --- src/gui/src/ActivationDialog.cpp | 3 +-- src/gui/src/SubscriptionManager.cpp | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/gui/src/ActivationDialog.cpp b/src/gui/src/ActivationDialog.cpp index df0d1618..8f1fb8c7 100644 --- a/src/gui/src/ActivationDialog.cpp +++ b/src/gui/src/ActivationDialog.cpp @@ -155,8 +155,7 @@ void ActivationDialog::accept() m_appConfig->saveSettings(); message.information (this, "Activated!", - tr("Thanks for activating %1!").arg - (getEditionName (edition))); + tr("Thanks for activating %1!").arg (getEditionName (edition))); MainWindow& mainWindow = dynamic_cast(*this->parent()); mainWindow.setEdition(edition); mainWindow.updateLocalFingerprint(); diff --git a/src/gui/src/SubscriptionManager.cpp b/src/gui/src/SubscriptionManager.cpp index 107bdff1..77e0a91c 100644 --- a/src/gui/src/SubscriptionManager.cpp +++ b/src/gui/src/SubscriptionManager.cpp @@ -98,7 +98,7 @@ void SubscriptionManager::checkError(QString& error) } else { QMessageBox::warning(m_pParent, tr("Subscription error"), - tr("An error occurred while trying to activate using a serial key. " + tr("An error occurred while trying to activate Synergy using your serial key. " "Please contact the helpdesk, and provide the " "following details.\n\n%1").arg(error)); } From 088ac82e186b82d3e36e2cf9c8ca0682221ae024 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Fri, 30 Sep 2016 15:35:04 +0100 Subject: [PATCH 040/101] #5629 Remove activation from the wizard --- src/gui/res/SetupWizardBase.ui | 208 --------------------------------- src/gui/src/SetupWizard.cpp | 138 ---------------------- src/gui/src/SetupWizard.h | 4 - 3 files changed, 350 deletions(-) diff --git a/src/gui/res/SetupWizardBase.ui b/src/gui/res/SetupWizardBase.ui index 6788a3d5..8c089886 100644 --- a/src/gui/res/SetupWizardBase.ui +++ b/src/gui/res/SetupWizardBase.ui @@ -120,214 +120,6 @@ - - - Activate - - - - - - Enable your <a href="http://symless.com/pricing?source=gui">Synergy Pro</a> and Synergy Basic features. - - - true - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 10 - - - - - - - - - 75 - true - - - - &Account login - - - true - - - - - - - QFormLayout::AllNonFixedFieldsGrow - - - 20 - - - 10 - - - - - Email: - - - - - - - - 0 - 0 - - - - - 200 - 20 - - - - QLineEdit::Normal - - - - - - - Password: - - - - - - - - 0 - 0 - - - - - 200 - 20 - - - - QLineEdit::Password - - - - - - - <a href="https://symless.com/account/reset/?source=gui">Forgot password</a> - - - true - - - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 10 - - - - - - - - - 75 - true - - - - &Serial key - - - - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 10 - - - - - - - - S&kip activation - - - - - - - color: rgb(100, 100, 100); - - - You will see UNREGISTERED in the window title (not recommended). - - - true - - - - - - - Qt::Vertical - - - QSizePolicy::Expanding - - - - 20 - 500 - - - - - - diff --git a/src/gui/src/SetupWizard.cpp b/src/gui/src/SetupWizard.cpp index 6a28c2f8..a9dab840 100644 --- a/src/gui/src/SetupWizard.cpp +++ b/src/gui/src/SetupWizard.cpp @@ -57,13 +57,6 @@ SetupWizard::SetupWizard(MainWindow& mainWindow, bool startMain) : m_Locale.fillLanguageComboBox(m_pComboLanguage); setIndexFromItemData(m_pComboLanguage, m_MainWindow.appConfig().language()); - AppConfig& appConfig = m_MainWindow.appConfig(); - - m_pLineEditEmail->setText(appConfig.activateEmail()); - m_pTextEditSerialKey->setText(appConfig.serialKey()); - - m_pTextEditSerialKey->setEnabled(false); - } SetupWizard::~SetupWizard() @@ -76,67 +69,6 @@ bool SetupWizard::validateCurrentPage() message.setWindowTitle(tr("Setup Synergy")); message.setIcon(QMessageBox::Information); - /*if (currentPage() == m_pActivatePage) - { - if (m_pRadioButtonActivate->isChecked()) { - if (m_pLineEditEmail->text().isEmpty() || - m_pLineEditPassword->text().isEmpty()) { - message.setText(tr("Please enter your email address and password.")); - message.exec(); - return false; - } - else { - WebClient webClient; - m_Edition = webClient.getEdition( - m_pLineEditEmail->text(), - m_pLineEditPassword->text(), - message, - this); - - if (m_Edition == Unknown) { - m_LoginAttemps++; - if (m_LoginAttemps == kMaximiumLoginAttemps) { - m_LoginAttemps = 0; - - QMessageBox::StandardButton reply = - QMessageBox::information( - this, tr("Setup Synergy"), - tr("Would you like to use your serial key instead?"), - QMessageBox::Yes | QMessageBox::No); - - if (reply == QMessageBox::Yes) { - m_pRadioButtonSubscription->setChecked(true); - } - } - - return false; - } - else { - return true; - } - } - } - else if (m_pRadioButtonSubscription->isChecked()) { - if (m_pTextEditSerialKey->toPlainText().isEmpty()) { - message.setText(tr("Please enter your subscription serial key.")); - message.exec(); - return false; - } - else { - // create subscription file in profile directory - SubscriptionManager subscriptionManager(this, m_MainWindow.appConfig(), m_Edition); - if (!subscriptionManager.activateSerial(m_pTextEditSerialKey->toPlainText())) { - return false; - } - - return true; - } - } - else { - return true; - } - } - else */ if (currentPage() == m_pNodePage) { bool result = m_pClientRadioButton->isChecked() || @@ -194,31 +126,6 @@ void SetupWizard::accept() settings.setValue("groupServerChecked", false); } - if (m_pRadioButtonActivate->isChecked()) { - appConfig.setActivateEmail(m_pLineEditEmail->text()); - - notifyActivation("login:" + m_pLineEditEmail->text()); - } - - if (m_pRadioButtonSubscription->isChecked()) - { - //appConfig.setSerialKey(m_pTextEditSerialKey->toPlainText()); - - notifyActivation("serial:" + m_pTextEditSerialKey->toPlainText()); - } - - if (m_pRadioButtonSkip->isChecked()) - { - notifyActivation("skip:unknown"); - } - - appConfig.setEdition(m_Edition); - m_MainWindow.setEdition(m_Edition); - m_MainWindow.updateLocalFingerprint(); - - appConfig.saveSettings(); - settings.sync(); - QWizard::accept(); if (m_StartMain) @@ -238,56 +145,11 @@ void SetupWizard::reject() m_MainWindow.open(); } - // treat cancel as skip - notifyActivation("skip:unknown"); - QWizard::reject(); } -void SetupWizard::notifyActivation(QString identity) -{ - ActivationNotifier* notifier = new ActivationNotifier(); - notifier->setIdentity(identity); - QThread* thread = new QThread; - connect(notifier, SIGNAL(finished()), thread, SLOT(quit())); - connect(notifier, SIGNAL(finished()), notifier, SLOT(deleteLater())); - connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); - - notifier->moveToThread(thread); - thread->start(); - - QMetaObject::invokeMethod(notifier, "notify", Qt::QueuedConnection); -} - void SetupWizard::on_m_pComboLanguage_currentIndexChanged(int index) { QString ietfCode = m_pComboLanguage->itemData(index).toString(); QSynergyApplication::getInstance()->switchTranslator(ietfCode); } - -void SetupWizard::on_m_pRadioButtonSkip_toggled(bool checked) -{ - if (checked) { - m_pLineEditEmail->setEnabled(false); - m_pLineEditPassword->setEnabled(false); - m_pTextEditSerialKey->setEnabled(false); - } -} - -void SetupWizard::on_m_pRadioButtonActivate_toggled(bool checked) -{ - if (checked) { - m_pLineEditEmail->setEnabled(true); - m_pLineEditPassword->setEnabled(true); - m_pTextEditSerialKey->setEnabled(false); - } -} - -void SetupWizard::on_m_pRadioButtonSubscription_toggled(bool checked) -{ - if (checked) { - m_pLineEditEmail->setEnabled(false); - m_pLineEditPassword->setEnabled(false); - m_pTextEditSerialKey->setEnabled(true); - } -} diff --git a/src/gui/src/SetupWizard.h b/src/gui/src/SetupWizard.h index fd6dcd14..a1fde149 100644 --- a/src/gui/src/SetupWizard.h +++ b/src/gui/src/SetupWizard.h @@ -42,7 +42,6 @@ protected: void changeEvent(QEvent* event); void accept(); void reject(); - void notifyActivation(QString identity); private: MainWindow& m_MainWindow; @@ -52,8 +51,5 @@ private: int m_LoginAttemps; private slots: - void on_m_pRadioButtonSubscription_toggled(bool checked); - void on_m_pRadioButtonActivate_toggled(bool checked); - void on_m_pRadioButtonSkip_toggled(bool checked); void on_m_pComboLanguage_currentIndexChanged(int index); }; From 02d75cd370ad4c404c8d801f747c990ef4c0a440 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Fri, 30 Sep 2016 15:52:24 +0100 Subject: [PATCH 041/101] #5603 Ignore exceptions in getOSInformation() --- src/gui/src/QUtility.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/gui/src/QUtility.cpp b/src/gui/src/QUtility.cpp index ca2c52c0..f463f1d2 100644 --- a/src/gui/src/QUtility.cpp +++ b/src/gui/src/QUtility.cpp @@ -114,15 +114,18 @@ QString getOSInformation() QString result; #if defined(Q_OS_LINUX) - QStringList arguments; - arguments.append("/etc/os-release"); - CommandProcess cp("/bin/cat", arguments); - QString output = cp.run(); + result = "Linux"; + try { + QStringList arguments; + arguments.append("/etc/os-release"); + CommandProcess cp("/bin/cat", arguments); + QString output = cp.run(); - QRegExp resultRegex(".*PRETTY_NAME=\"([^\"]+)\".*"); - if (resultRegex.exactMatch(output)) { - QString OSInfo = resultRegex.cap(1); - result = OSInfo; + QRegExp resultRegex(".*PRETTY_NAME=\"([^\"]+)\".*"); + if (resultRegex.exactMatch(output)) { + result = resultRegex.cap(1); + } + } catch (...) { } #endif From bcf2d5de0d97e4f053176ab63ab7dd84d2d413d9 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Fri, 30 Sep 2016 16:04:49 +0100 Subject: [PATCH 042/101] #5629 Trigger activation dialog if previously unseen --- src/gui/src/AppConfig.cpp | 13 +++++++++++++ src/gui/src/AppConfig.h | 4 ++++ src/gui/src/MainWindow.cpp | 6 ++++++ 3 files changed, 23 insertions(+) diff --git a/src/gui/src/AppConfig.cpp b/src/gui/src/AppConfig.cpp index 6347c6cf..60481930 100644 --- a/src/gui/src/AppConfig.cpp +++ b/src/gui/src/AppConfig.cpp @@ -163,6 +163,7 @@ void AppConfig::loadSettings() m_AutoHide = settings().value("autoHide", false).toBool(); m_Serialkey = settings().value("serialKey", "").toString(); m_LastExpiringWarningTime = settings().value("lastExpiringWarningTime", 0).toInt(); + m_ActivationHasRun = settings().value("activationHasRun", false).toBool(); } void AppConfig::saveSettings() @@ -188,6 +189,18 @@ void AppConfig::saveSettings() settings().setValue("autoHide", m_AutoHide); settings().setValue("serialKey", m_Serialkey); settings().setValue("lastExpiringWarningTime", m_LastExpiringWarningTime); + settings().setValue("activationHasRun", m_ActivationHasRun); +} + +bool AppConfig::activationHasRun() const +{ + return m_ActivationHasRun; +} + +AppConfig& AppConfig::activationHasRun(bool value) +{ + m_ActivationHasRun = value; + return *this; } QSettings &AppConfig::settings() { return *m_pSettings; } diff --git a/src/gui/src/AppConfig.h b/src/gui/src/AppConfig.h index df391bfb..a3dd0a11 100644 --- a/src/gui/src/AppConfig.h +++ b/src/gui/src/AppConfig.h @@ -100,6 +100,9 @@ class AppConfig void saveSettings(); + bool activationHasRun() const; + AppConfig& activationHasRun(bool value); + protected: QSettings& settings(); void setScreenName(const QString& s); @@ -136,6 +139,7 @@ class AppConfig bool m_AutoHide; QString m_Serialkey; int m_LastExpiringWarningTime; + bool m_ActivationHasRun; static const char m_SynergysName[]; static const char m_SynergycName[]; diff --git a/src/gui/src/MainWindow.cpp b/src/gui/src/MainWindow.cpp index 15c20d12..f27777a1 100644 --- a/src/gui/src/MainWindow.cpp +++ b/src/gui/src/MainWindow.cpp @@ -139,6 +139,12 @@ MainWindow::MainWindow(QSettings& settings, AppConfig& appConfig) : m_pLabelPadlock->hide(); updateLocalFingerprint(); + + if (!appConfig.activationHasRun() && (appConfig.edition() == Unregistered)) { + ActivationDialog activationDialog (this, appConfig); + activationDialog.exec(); + appConfig.activationHasRun(true); + } } MainWindow::~MainWindow() From 2809530793c80d182d094b6aadaf0ab6e175fe2c Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Fri, 30 Sep 2016 16:23:04 +0100 Subject: [PATCH 043/101] #5629 Remove 'Run Wizard' from file menu --- src/gui/res/MainWindowBase.ui | 8 -------- src/gui/src/MainWindow.cpp | 9 +-------- src/gui/src/MainWindow.h | 1 - 3 files changed, 1 insertion(+), 17 deletions(-) diff --git a/src/gui/res/MainWindowBase.ui b/src/gui/res/MainWindowBase.ui index fa7955cc..5a852c8c 100644 --- a/src/gui/res/MainWindowBase.ui +++ b/src/gui/res/MainWindowBase.ui @@ -481,14 +481,6 @@ - - - Run Wizard - - - - - Activate diff --git a/src/gui/src/MainWindow.cpp b/src/gui/src/MainWindow.cpp index f27777a1..8dca067d 100644 --- a/src/gui/src/MainWindow.cpp +++ b/src/gui/src/MainWindow.cpp @@ -26,7 +26,6 @@ #include "AboutDialog.h" #include "ServerConfigDialog.h" #include "SettingsDialog.h" -#include "SetupWizard.h" #include "ActivationDialog.h" #include "ZeroconfService.h" #include "DataDownloader.h" @@ -269,8 +268,8 @@ void MainWindow::createMenuBar() m_pMenuFile->addAction(m_pActionStartSynergy); m_pMenuFile->addAction(m_pActionStopSynergy); m_pMenuFile->addSeparator(); - m_pMenuFile->addAction(m_pActionWizard); m_pMenuFile->addAction(m_pActivate); + m_pMenuFile->addSeparator(); m_pMenuFile->addAction(m_pActionSave); m_pMenuFile->addSeparator(); m_pMenuFile->addAction(m_pActionQuit); @@ -1138,12 +1137,6 @@ void MainWindow::on_m_pButtonConfigureServer_clicked() showConfigureServer(); } -void MainWindow::on_m_pActionWizard_triggered() -{ - SetupWizard wizard(*this, false); - wizard.exec(); -} - void MainWindow::on_m_pActivate_triggered() { ActivationDialog activationDialog (this, this->appConfig()); diff --git a/src/gui/src/MainWindow.h b/src/gui/src/MainWindow.h index 8788e4a2..e815d53f 100644 --- a/src/gui/src/MainWindow.h +++ b/src/gui/src/MainWindow.h @@ -130,7 +130,6 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase bool on_m_pActionSave_triggered(); void on_m_pActionAbout_triggered(); void on_m_pActionSettings_triggered(); - void on_m_pActionWizard_triggered(); void on_m_pActivate_triggered(); void synergyFinished(int exitCode, QProcess::ExitStatus); void trayActivated(QSystemTrayIcon::ActivationReason reason); From d6b7d8e357bf3e091e89f1a9c830c6dd906a6293 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Fri, 30 Sep 2016 17:01:43 +0100 Subject: [PATCH 044/101] #5627 Enable encryption for Pro users --- src/gui/res/SettingsDialogBase.ui | 7 +++++-- src/gui/src/AppConfig.cpp | 8 +++++--- src/gui/src/AppConfig.h | 4 ++-- src/gui/src/SettingsDialog.cpp | 2 ++ 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/gui/res/SettingsDialogBase.ui b/src/gui/res/SettingsDialogBase.ui index 1cd82801..edfabaf9 100644 --- a/src/gui/res/SettingsDialogBase.ui +++ b/src/gui/res/SettingsDialogBase.ui @@ -7,7 +7,7 @@ 0 0 368 - 380 + 470 @@ -176,8 +176,11 @@ + + false + - Use &SSL encryption (unique certificate) + Use &SSL encryption diff --git a/src/gui/src/AppConfig.cpp b/src/gui/src/AppConfig.cpp index 60481930..1fbd966b 100644 --- a/src/gui/src/AppConfig.cpp +++ b/src/gui/src/AppConfig.cpp @@ -159,7 +159,7 @@ void AppConfig::loadSettings() m_AutoConfigPrompted = settings().value("autoConfigPrompted", false).toBool(); m_Edition = settings().value("edition", Unregistered).toInt(); m_ActivateEmail = settings().value("activateEmail", "").toString(); - m_CryptoEnabled = settings().value("cryptoEnabled", false).toBool(); + m_CryptoEnabled = settings().value("cryptoEnabled", true).toBool(); m_AutoHide = settings().value("autoHide", false).toBool(); m_Serialkey = settings().value("serialKey", "").toString(); m_LastExpiringWarningTime = settings().value("lastExpiringWarningTime", 0).toInt(); @@ -239,7 +239,7 @@ void AppConfig::setAutoConfigPrompted(bool prompted) void AppConfig::setEdition(int e) { m_Edition = e; } -int AppConfig::edition() { return m_Edition; } +int AppConfig::edition() const { return m_Edition; } bool AppConfig::setActivateEmail(QString e) { m_ActivateEmail = e; @@ -279,7 +279,9 @@ ElevateMode AppConfig::elevateMode() void AppConfig::setCryptoEnabled(bool e) { m_CryptoEnabled = e; } -bool AppConfig::getCryptoEnabled() { return m_CryptoEnabled; } +bool AppConfig::getCryptoEnabled() const { + return (edition() == Pro) && m_CryptoEnabled; +} void AppConfig::setAutoHide(bool b) { m_AutoHide = b; } diff --git a/src/gui/src/AppConfig.h b/src/gui/src/AppConfig.h index a3dd0a11..5110bf91 100644 --- a/src/gui/src/AppConfig.h +++ b/src/gui/src/AppConfig.h @@ -75,7 +75,7 @@ class AppConfig bool autoConfigPrompted(); void setAutoConfigPrompted(bool prompted); void setEdition(int e); - int edition(); + int edition() const; bool setActivateEmail(QString e); QString activateEmail(); bool setSerialKey(QString serial, QString& error); @@ -94,7 +94,7 @@ class AppConfig ElevateMode elevateMode(); void setCryptoEnabled(bool e); - bool getCryptoEnabled(); + bool getCryptoEnabled() const; void setAutoHide(bool b); bool getAutoHide(); diff --git a/src/gui/src/SettingsDialog.cpp b/src/gui/src/SettingsDialog.cpp index 8f754490..e6bec0fa 100644 --- a/src/gui/src/SettingsDialog.cpp +++ b/src/gui/src/SettingsDialog.cpp @@ -23,6 +23,7 @@ #include "QSynergyApplication.h" #include "QUtility.h" #include "AppConfig.h" +#include "EditionType.h" #include #include @@ -61,6 +62,7 @@ SettingsDialog::SettingsDialog(QWidget* parent, AppConfig& config) : #endif m_pCheckBoxEnableCrypto->setChecked(m_AppConfig.getCryptoEnabled()); + m_pCheckBoxEnableCrypto->setEnabled(m_AppConfig.edition() == Pro); } void SettingsDialog::accept() From 4924f2faff109d371e5e58de7965d620837c6dc5 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Fri, 30 Sep 2016 17:07:26 +0100 Subject: [PATCH 045/101] #5627 Save settings after creating MainWindow --- src/gui/src/MainWindow.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/gui/src/MainWindow.cpp b/src/gui/src/MainWindow.cpp index 8dca067d..021b4f4b 100644 --- a/src/gui/src/MainWindow.cpp +++ b/src/gui/src/MainWindow.cpp @@ -144,6 +144,8 @@ MainWindow::MainWindow(QSettings& settings, AppConfig& appConfig) : activationDialog.exec(); appConfig.activationHasRun(true); } + + appConfig.saveSettings(); } MainWindow::~MainWindow() From c799041ce8a7e2a0fecfc970f394f87a91dc57d1 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Fri, 30 Sep 2016 17:31:55 +0100 Subject: [PATCH 046/101] #5627 Only generate an SSL certificate when it doesn't exist --- src/gui/src/MainWindow.cpp | 11 ++++- src/gui/src/MainWindow.h | 2 + src/gui/src/SslCertificate.cpp | 75 ++++++++++++++++++---------------- 3 files changed, 51 insertions(+), 37 deletions(-) diff --git a/src/gui/src/MainWindow.cpp b/src/gui/src/MainWindow.cpp index 021b4f4b..6f326be1 100644 --- a/src/gui/src/MainWindow.cpp +++ b/src/gui/src/MainWindow.cpp @@ -34,6 +34,7 @@ #include "EditionType.h" #include "QUtility.h" #include "ProcessorArch.h" +#include "SslCertificate.h" #include #include @@ -97,7 +98,8 @@ MainWindow::MainWindow(QSettings& settings, AppConfig& appConfig) : m_SuppressAutoConfigWarning(false), m_BonjourInstall(NULL), m_SuppressEmptyServerWarning(false), - m_ExpectedRunningState(kStopped) + m_ExpectedRunningState(kStopped), + m_pSslCertificate(NULL) { setupUi(this); @@ -145,6 +147,11 @@ MainWindow::MainWindow(QSettings& settings, AppConfig& appConfig) : appConfig.activationHasRun(true); } + if (appConfig.getCryptoEnabled()) { + m_pSslCertificate = new SslCertificate(this); + m_pSslCertificate->generateCertificate(); + } + appConfig.saveSettings(); } @@ -166,6 +173,8 @@ MainWindow::~MainWindow() if (m_BonjourInstall != NULL) { delete m_BonjourInstall; } + + delete m_pSslCertificate; } void MainWindow::open() diff --git a/src/gui/src/MainWindow.h b/src/gui/src/MainWindow.h index e815d53f..650b05d1 100644 --- a/src/gui/src/MainWindow.h +++ b/src/gui/src/MainWindow.h @@ -57,6 +57,7 @@ class SetupWizard; class ZeroconfService; class DataDownloader; class CommandProcess; +class SslCertificate; class MainWindow : public QMainWindow, public Ui::MainWindowBase { @@ -207,6 +208,7 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase bool m_SuppressEmptyServerWarning; qRuningState m_ExpectedRunningState; QMutex m_StopDesktopMutex; + SslCertificate* m_pSslCertificate; private slots: void on_m_pCheckBoxAutoConfig_toggled(bool checked); diff --git a/src/gui/src/SslCertificate.cpp b/src/gui/src/SslCertificate.cpp index 7a8403c0..a669c5f6 100644 --- a/src/gui/src/SslCertificate.cpp +++ b/src/gui/src/SslCertificate.cpp @@ -90,56 +90,59 @@ bool SslCertificate::runTool(const QStringList& args) void SslCertificate::generateCertificate() { - QStringList arguments; - - // self signed certificate - arguments.append("req"); - arguments.append("-x509"); - arguments.append("-nodes"); - - // valide duration - arguments.append("-days"); - arguments.append(kCertificateLifetime); - - // subject information - arguments.append("-subj"); - - QString subInfo(kCertificateSubjectInfo); - arguments.append(subInfo); - - // private key - arguments.append("-newkey"); - arguments.append("rsa:1024"); - QString sslDirPath = QString("%1%2%3") .arg(m_ProfileDir) .arg(QDir::separator()) .arg(kSslDir); - QDir sslDir(sslDirPath); - if (!sslDir.exists()) { - sslDir.mkpath("."); - } - QString filename = QString("%1%2%3") .arg(sslDirPath) .arg(QDir::separator()) .arg(kCertificateFilename); - // key output filename - arguments.append("-keyout"); - arguments.append(filename); + QFile file(filename); + if (!file.exists()) { + QStringList arguments; - // certificate output filename - arguments.append("-out"); - arguments.append(filename); + // self signed certificate + arguments.append("req"); + arguments.append("-x509"); + arguments.append("-nodes"); - if (!runTool(arguments)) { - return; + // valide duration + arguments.append("-days"); + arguments.append(kCertificateLifetime); + + // subject information + arguments.append("-subj"); + + QString subInfo(kCertificateSubjectInfo); + arguments.append(subInfo); + + // private key + arguments.append("-newkey"); + arguments.append("rsa:1024"); + + QDir sslDir(sslDirPath); + if (!sslDir.exists()) { + sslDir.mkpath("."); + } + + // key output filename + arguments.append("-keyout"); + arguments.append(filename); + + // certificate output filename + arguments.append("-out"); + arguments.append(filename); + + if (!runTool(arguments)) { + return; + } + + emit info(tr("SSL certificate generated.")); } - emit info(tr("SSL certificate generated.")); - generateFingerprint(filename); emit generateFinished(); From d6bcdcbea74da9db6f718e0a6e72e101f364cf57 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Mon, 3 Oct 2016 11:54:45 +0100 Subject: [PATCH 047/101] #5629 Change activation failure to a QDialog --- src/gui/gui.pro | 9 ++- src/gui/res/FailedLoginDialog.ui | 108 ++++++++++++++++++++++++++++++ src/gui/src/ActivationDialog.cpp | 6 +- src/gui/src/FailedLoginDialog.cpp | 15 +++++ src/gui/src/FailedLoginDialog.h | 23 +++++++ src/gui/src/WebClient.cpp | 2 +- 6 files changed, 156 insertions(+), 7 deletions(-) create mode 100644 src/gui/res/FailedLoginDialog.ui create mode 100644 src/gui/src/FailedLoginDialog.cpp create mode 100644 src/gui/src/FailedLoginDialog.h diff --git a/src/gui/gui.pro b/src/gui/gui.pro index ee4ba52b..c0bf4fad 100644 --- a/src/gui/gui.pro +++ b/src/gui/gui.pro @@ -18,7 +18,8 @@ FORMS += res/MainWindowBase.ui \ res/SetupWizardBase.ui \ res/AddClientDialogBase.ui \ res/ActivationDialog.ui \ - res/CancelActivationDialog.ui + res/CancelActivationDialog.ui \ + res/FailedLoginDialog.ui SOURCES += src/main.cpp \ src/MainWindow.cpp \ src/AboutDialog.cpp \ @@ -62,7 +63,8 @@ SOURCES += src/main.cpp \ src/SubscriptionManager.cpp \ src/ActivationNotifier.cpp \ src/ActivationDialog.cpp \ - src/CancelActivationDialog.cpp + src/CancelActivationDialog.cpp \ + src/FailedLoginDialog.cpp HEADERS += src/MainWindow.h \ src/AboutDialog.h \ src/ServerConfig.h \ @@ -109,7 +111,8 @@ HEADERS += src/MainWindow.h \ src/ActivationNotifier.h \ src/ElevateMode.h \ src/ActivationDialog.h \ - src/CancelActivationDialog.h + src/CancelActivationDialog.h \ + src/FailedLoginDialog.h RESOURCES += res/Synergy.qrc RC_FILE = res/win/Synergy.rc macx { diff --git a/src/gui/res/FailedLoginDialog.ui b/src/gui/res/FailedLoginDialog.ui new file mode 100644 index 00000000..d3c6b507 --- /dev/null +++ b/src/gui/res/FailedLoginDialog.ui @@ -0,0 +1,108 @@ + + + FailedLoginDialog + + + + 0 + 0 + 400 + 165 + + + + Activation Error + + + + + 50 + 120 + 341 + 32 + + + + Qt::Horizontal + + + QDialogButtonBox::Close + + + + + + 10 + 90 + 382 + 30 + + + + <html><head/><body><p><a href="https://symless.com/account/reset/?source=gui"><span style=" text-decoration: underline; color:#0000ff;">Forgotten your password?</span></a></p></body></html> + + + true + + + + + + 10 + 10 + 382 + 72 + + + + An error occurred while trying to activate Synergy. The Symless server returned the following error: + +%1 + + + true + + + true + + + label_2 + messageLabel + buttonBox + + + + + buttonBox + accepted() + FailedLoginDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + FailedLoginDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/gui/src/ActivationDialog.cpp b/src/gui/src/ActivationDialog.cpp index 8f1fb8c7..3950d198 100644 --- a/src/gui/src/ActivationDialog.cpp +++ b/src/gui/src/ActivationDialog.cpp @@ -8,6 +8,7 @@ #include "MainWindow.h" #include "QUtility.h" #include "SubscriptionManager.h" +#include "FailedLoginDialog.h" #include #include @@ -116,9 +117,8 @@ void ActivationDialog::accept() return; } else if (!webClient.getEdition (edition, error)) { - message.critical (this, "Activation Error", - tr("An error occurred while trying to activate Synergy. " - "The Symless server returned the following error:\n\n%1").arg(error)); + FailedLoginDialog failedLoginDialog (this, error); + failedLoginDialog.exec(); return; } diff --git a/src/gui/src/FailedLoginDialog.cpp b/src/gui/src/FailedLoginDialog.cpp new file mode 100644 index 00000000..07ec6bdc --- /dev/null +++ b/src/gui/src/FailedLoginDialog.cpp @@ -0,0 +1,15 @@ +#include "FailedLoginDialog.h" +#include "ui_FailedLoginDialog.h" + +FailedLoginDialog::FailedLoginDialog(QWidget *parent, QString message): + QDialog(parent), + ui(new Ui::FailedLoginDialog) +{ + ui->setupUi(this); + ui->messageLabel->setText(ui->messageLabel->text().arg(message)); +} + +FailedLoginDialog::~FailedLoginDialog() +{ + delete ui; +} diff --git a/src/gui/src/FailedLoginDialog.h b/src/gui/src/FailedLoginDialog.h new file mode 100644 index 00000000..2eb67634 --- /dev/null +++ b/src/gui/src/FailedLoginDialog.h @@ -0,0 +1,23 @@ +#ifndef FAILEDLOGINDIALOG_H +#define FAILEDLOGINDIALOG_H + +#include +#include + +namespace Ui { +class FailedLoginDialog; +} + +class FailedLoginDialog : public QDialog +{ + Q_OBJECT + +public: + explicit FailedLoginDialog(QWidget *parent = 0, QString message = ""); + ~FailedLoginDialog(); + +private: + Ui::FailedLoginDialog *ui; +}; + +#endif // FAILEDLOGINDIALOG_H diff --git a/src/gui/src/WebClient.cpp b/src/gui/src/WebClient.cpp index a0a6118a..1d21dc82 100644 --- a/src/gui/src/WebClient.cpp +++ b/src/gui/src/WebClient.cpp @@ -46,7 +46,7 @@ WebClient::getEdition (int& edition, QString& errorOut) { throw std::runtime_error ("Unrecognised server response."); } } else { - errorOut = tr("Login failed. Invalid email or password."); + errorOut = tr("Login failed. Invalid email address or password."); return false; } } else { From 32f143f52b412203406f2624e0db208b65398278 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Mon, 3 Oct 2016 15:16:03 +0100 Subject: [PATCH 048/101] #5627 Update Main Window fingerprint after SSL cert gen --- src/gui/src/MainWindow.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/gui/src/MainWindow.cpp b/src/gui/src/MainWindow.cpp index 6f326be1..971bd880 100644 --- a/src/gui/src/MainWindow.cpp +++ b/src/gui/src/MainWindow.cpp @@ -139,8 +139,6 @@ MainWindow::MainWindow(QSettings& settings, AppConfig& appConfig) : m_pLabelPadlock->hide(); - updateLocalFingerprint(); - if (!appConfig.activationHasRun() && (appConfig.edition() == Unregistered)) { ActivationDialog activationDialog (this, appConfig); activationDialog.exec(); @@ -152,6 +150,7 @@ MainWindow::MainWindow(QSettings& settings, AppConfig& appConfig) : m_pSslCertificate->generateCertificate(); } + updateLocalFingerprint(); appConfig.saveSettings(); } From d1a180f652158dc1e91cd0d9f41f7bdd5cad9d1b Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Mon, 3 Oct 2016 15:26:27 +0100 Subject: [PATCH 049/101] #5627 Automatically generate SSL cert when enabling SSL --- src/gui/src/SettingsDialog.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/gui/src/SettingsDialog.cpp b/src/gui/src/SettingsDialog.cpp index e6bec0fa..813eac36 100644 --- a/src/gui/src/SettingsDialog.cpp +++ b/src/gui/src/SettingsDialog.cpp @@ -24,6 +24,8 @@ #include "QUtility.h" #include "AppConfig.h" #include "EditionType.h" +#include "SslCertificate.h" +#include "MainWindow.h" #include #include @@ -143,4 +145,11 @@ void SettingsDialog::on_m_pComboLanguage_currentIndexChanged(int index) void SettingsDialog::on_m_pCheckBoxEnableCrypto_toggled(bool checked) { m_AppConfig.setCryptoEnabled(checked); + m_AppConfig.saveSettings(); + if (checked) { + SslCertificate sslCertificate; + sslCertificate.generateCertificate(); + MainWindow& mainWindow = dynamic_cast (*this->parent()); + mainWindow.updateLocalFingerprint(); + } } From 912ed9be9c44ab2957f06d6224ff5c858087d7b7 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Mon, 3 Oct 2016 15:27:38 +0100 Subject: [PATCH 050/101] #5629 Ensure settings are saved when AppConfig updates them --- src/gui/src/AppConfig.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gui/src/AppConfig.cpp b/src/gui/src/AppConfig.cpp index 1fbd966b..e6b9b0ed 100644 --- a/src/gui/src/AppConfig.cpp +++ b/src/gui/src/AppConfig.cpp @@ -190,6 +190,7 @@ void AppConfig::saveSettings() settings().setValue("serialKey", m_Serialkey); settings().setValue("lastExpiringWarningTime", m_LastExpiringWarningTime); settings().setValue("activationHasRun", m_ActivationHasRun); + settings().sync(); } bool AppConfig::activationHasRun() const From 176d7e47257d8553f78c0509c8f416631aaef47c Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Mon, 3 Oct 2016 15:36:21 +0100 Subject: [PATCH 051/101] #5617 Don't copy plugins directory on Windows --- src/lib/net/CMakeLists.txt | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/lib/net/CMakeLists.txt b/src/lib/net/CMakeLists.txt index 60a14499..3e64fe5d 100644 --- a/src/lib/net/CMakeLists.txt +++ b/src/lib/net/CMakeLists.txt @@ -35,13 +35,6 @@ endif() add_library(net STATIC ${sources}) if (WIN32) - add_custom_command( - TARGET net - POST_BUILD - COMMAND xcopy /Y /Q - ..\\..\\..\\..\\lib\\${CMAKE_CFG_INTDIR}\\ns.* - ..\\..\\..\\..\\bin\\${CMAKE_CFG_INTDIR}\\plugins\\ - ) add_custom_command( TARGET net POST_BUILD From 15a6a27dc6a31d98671fe1b352a092dd397146bf Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Mon, 3 Oct 2016 17:23:10 +0100 Subject: [PATCH 052/101] #5629 Show activation dialog only after main window --- src/gui/src/ActivationDialog.cpp | 3 ++- src/gui/src/MainWindow.cpp | 15 ++++++++------- src/gui/src/MainWindow.h | 2 ++ src/gui/src/SettingsDialog.cpp | 1 + 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/gui/src/ActivationDialog.cpp b/src/gui/src/ActivationDialog.cpp index 3950d198..a0221fec 100644 --- a/src/gui/src/ActivationDialog.cpp +++ b/src/gui/src/ActivationDialog.cpp @@ -152,6 +152,7 @@ void ActivationDialog::accept() } m_appConfig->setEdition(edition); + m_appConfig->activationHasRun(true); m_appConfig->saveSettings(); message.information (this, "Activated!", @@ -159,7 +160,7 @@ void ActivationDialog::accept() MainWindow& mainWindow = dynamic_cast(*this->parent()); mainWindow.setEdition(edition); mainWindow.updateLocalFingerprint(); - mainWindow.settings().sync(); + mainWindow.saveSettings(); QDialog::accept(); } diff --git a/src/gui/src/MainWindow.cpp b/src/gui/src/MainWindow.cpp index 971bd880..0c64b6b4 100644 --- a/src/gui/src/MainWindow.cpp +++ b/src/gui/src/MainWindow.cpp @@ -139,19 +139,20 @@ MainWindow::MainWindow(QSettings& settings, AppConfig& appConfig) : m_pLabelPadlock->hide(); - if (!appConfig.activationHasRun() && (appConfig.edition() == Unregistered)) { - ActivationDialog activationDialog (this, appConfig); - activationDialog.exec(); - appConfig.activationHasRun(true); - } - if (appConfig.getCryptoEnabled()) { m_pSslCertificate = new SslCertificate(this); m_pSslCertificate->generateCertificate(); } updateLocalFingerprint(); - appConfig.saveSettings(); +} + +void +MainWindow::showEvent(QShowEvent*) { + if (!m_AppConfig.activationHasRun() && (m_AppConfig.edition() == Unregistered)) { + ActivationDialog activationDialog (this, m_AppConfig); + activationDialog.exec(); + } } MainWindow::~MainWindow() diff --git a/src/gui/src/MainWindow.h b/src/gui/src/MainWindow.h index 650b05d1..d66201e3 100644 --- a/src/gui/src/MainWindow.h +++ b/src/gui/src/MainWindow.h @@ -66,6 +66,7 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase friend class QSynergyApplication; friend class SetupWizard; friend class ActivationDialog; + friend class SettingsDialog; public: enum qSynergyState @@ -181,6 +182,7 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase void restartSynergy(); void proofreadInfo(); + void showEvent(QShowEvent *event); private: QSettings& m_Settings; AppConfig& m_AppConfig; diff --git a/src/gui/src/SettingsDialog.cpp b/src/gui/src/SettingsDialog.cpp index 813eac36..14cd1fc7 100644 --- a/src/gui/src/SettingsDialog.cpp +++ b/src/gui/src/SettingsDialog.cpp @@ -151,5 +151,6 @@ void SettingsDialog::on_m_pCheckBoxEnableCrypto_toggled(bool checked) sslCertificate.generateCertificate(); MainWindow& mainWindow = dynamic_cast (*this->parent()); mainWindow.updateLocalFingerprint(); + mainWindow.saveSettings(); } } From 603b12dc59970eb56716e82d4b67063c80004e68 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Tue, 4 Oct 2016 10:45:27 +0100 Subject: [PATCH 053/101] #5629 Trigger main window show event before opening activation dialog --- src/gui/src/MainWindow.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gui/src/MainWindow.cpp b/src/gui/src/MainWindow.cpp index 0c64b6b4..87a79c51 100644 --- a/src/gui/src/MainWindow.cpp +++ b/src/gui/src/MainWindow.cpp @@ -148,7 +148,8 @@ MainWindow::MainWindow(QSettings& settings, AppConfig& appConfig) : } void -MainWindow::showEvent(QShowEvent*) { +MainWindow::showEvent(QShowEvent* event) { + QMainWindow::showEvent (event); if (!m_AppConfig.activationHasRun() && (m_AppConfig.edition() == Unregistered)) { ActivationDialog activationDialog (this, m_AppConfig); activationDialog.exec(); From 16ef224ba8f185a0eb7d8ac28d6cdb2e6e72cae5 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Tue, 4 Oct 2016 11:15:53 +0100 Subject: [PATCH 054/101] #5629 Save activation dialog seen state on reject --- src/gui/src/ActivationDialog.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/gui/src/ActivationDialog.cpp b/src/gui/src/ActivationDialog.cpp index a0221fec..e4beeb49 100644 --- a/src/gui/src/ActivationDialog.cpp +++ b/src/gui/src/ActivationDialog.cpp @@ -68,6 +68,8 @@ void ActivationDialog::reject() CancelActivationDialog cancelActivationDialog(this); if (QDialog::Accepted == cancelActivationDialog.exec()) { notifyActivation("skip:unknown"); + m_appConfig->activationHasRun(true); + m_appConfig->saveSettings(); QDialog::reject(); } } @@ -102,6 +104,9 @@ void ActivationDialog::accept() QString error; int edition = Unregistered; + m_appConfig->activationHasRun(true); + m_appConfig->saveSettings(); + try { if (ui->m_pRadioButtonActivate->isChecked()) { WebClient webClient; @@ -152,7 +157,6 @@ void ActivationDialog::accept() } m_appConfig->setEdition(edition); - m_appConfig->activationHasRun(true); m_appConfig->saveSettings(); message.information (this, "Activated!", From 15f2e27d1883e8cd8da9f9c848574e22c41e743b Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Tue, 4 Oct 2016 11:48:47 +0100 Subject: [PATCH 055/101] #5629 Show the main window behind the activation dialog --- src/gui/src/MainWindow.cpp | 23 +++++++++++++++-------- src/gui/src/MainWindow.h | 8 +++++++- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/src/gui/src/MainWindow.cpp b/src/gui/src/MainWindow.cpp index 87a79c51..f4cab6ef 100644 --- a/src/gui/src/MainWindow.cpp +++ b/src/gui/src/MainWindow.cpp @@ -145,15 +145,8 @@ MainWindow::MainWindow(QSettings& settings, AppConfig& appConfig) : } updateLocalFingerprint(); -} -void -MainWindow::showEvent(QShowEvent* event) { - QMainWindow::showEvent (event); - if (!m_AppConfig.activationHasRun() && (m_AppConfig.edition() == Unregistered)) { - ActivationDialog activationDialog (this, m_AppConfig); - activationDialog.exec(); - } + connect (this, SIGNAL(windowShown()), this, SLOT(on_windowShown()), Qt::QueuedConnection); } MainWindow::~MainWindow() @@ -518,6 +511,12 @@ void MainWindow::proofreadInfo() setSynergyState((qSynergyState)oldState); } +void MainWindow::showEvent(QShowEvent* event) +{ + QMainWindow::showEvent(event); + emit windowShown(); +} + void MainWindow::clearLog() { m_pLogOutput->clear(); @@ -1367,6 +1366,14 @@ void MainWindow::bonjourInstallFinished() m_pCheckBoxAutoConfig->setChecked(true); } +void MainWindow::on_windowShown() +{ + if (!m_AppConfig.activationHasRun() && (m_AppConfig.edition() == Unregistered)) { + ActivationDialog activationDialog (this, m_AppConfig); + activationDialog.exec(); + } +} + QString MainWindow::getProfileRootForArg() { CoreInterface coreInterface; diff --git a/src/gui/src/MainWindow.h b/src/gui/src/MainWindow.h index d66201e3..b71d8a00 100644 --- a/src/gui/src/MainWindow.h +++ b/src/gui/src/MainWindow.h @@ -117,6 +117,7 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase void serverDetected(const QString name); void setEdition(int edition); void updateLocalFingerprint(); + public slots: void appendLogRaw(const QString& text); void appendLogInfo(const QString& text); @@ -182,7 +183,8 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase void restartSynergy(); void proofreadInfo(); - void showEvent(QShowEvent *event); + void showEvent (QShowEvent*); + private: QSettings& m_Settings; AppConfig& m_AppConfig; @@ -217,6 +219,10 @@ private slots: void on_m_pComboServerList_currentIndexChanged(QString ); void on_m_pButtonApply_clicked(); void installBonjour(); + void on_windowShown(); + +signals: + void windowShown(); }; #endif From 783056f7cc0d4ddce71f958de87c0c42d1384af7 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Tue, 4 Oct 2016 13:41:27 +0100 Subject: [PATCH 056/101] #5629 Ensure setEdition signals main UI --- src/gui/src/ActivationDialog.cpp | 5 ----- src/gui/src/AppConfig.cpp | 5 ++++- src/gui/src/AppConfig.h | 8 +++++++- src/gui/src/MainWindow.cpp | 17 ++++++++--------- src/gui/src/MainWindow.h | 2 +- src/gui/src/SettingsDialog.cpp | 1 - src/gui/src/SetupWizard.cpp | 5 +---- src/gui/src/SetupWizard.h | 2 -- 8 files changed, 21 insertions(+), 24 deletions(-) diff --git a/src/gui/src/ActivationDialog.cpp b/src/gui/src/ActivationDialog.cpp index e4beeb49..40251019 100644 --- a/src/gui/src/ActivationDialog.cpp +++ b/src/gui/src/ActivationDialog.cpp @@ -161,10 +161,5 @@ void ActivationDialog::accept() message.information (this, "Activated!", tr("Thanks for activating %1!").arg (getEditionName (edition))); - MainWindow& mainWindow = dynamic_cast(*this->parent()); - mainWindow.setEdition(edition); - mainWindow.updateLocalFingerprint(); - mainWindow.saveSettings(); - QDialog::accept(); } diff --git a/src/gui/src/AppConfig.cpp b/src/gui/src/AppConfig.cpp index e6b9b0ed..a6d081f9 100644 --- a/src/gui/src/AppConfig.cpp +++ b/src/gui/src/AppConfig.cpp @@ -238,7 +238,10 @@ void AppConfig::setAutoConfigPrompted(bool prompted) m_AutoConfigPrompted = prompted; } -void AppConfig::setEdition(int e) { m_Edition = e; } +void AppConfig::setEdition(int e) { + m_Edition = e; + emit editionSet (e); +} int AppConfig::edition() const { return m_Edition; } diff --git a/src/gui/src/AppConfig.h b/src/gui/src/AppConfig.h index 5110bf91..3d15ec6e 100644 --- a/src/gui/src/AppConfig.h +++ b/src/gui/src/AppConfig.h @@ -20,6 +20,7 @@ #define APPCONFIG_H +#include #include #include "ElevateMode.h" @@ -47,8 +48,10 @@ enum ProcessMode { Desktop }; -class AppConfig +class AppConfig: public QObject { + Q_OBJECT + friend class SettingsDialog; friend class MainWindow; friend class SetupWizard; @@ -144,6 +147,9 @@ class AppConfig static const char m_SynergysName[]; static const char m_SynergycName[]; static const char m_SynergyLogDir[]; + + signals: + void editionSet(int); }; #endif diff --git a/src/gui/src/MainWindow.cpp b/src/gui/src/MainWindow.cpp index f4cab6ef..64271c14 100644 --- a/src/gui/src/MainWindow.cpp +++ b/src/gui/src/MainWindow.cpp @@ -138,15 +138,8 @@ MainWindow::MainWindow(QSettings& settings, AppConfig& appConfig) : setEdition(m_AppConfig.edition()); m_pLabelPadlock->hide(); - - if (appConfig.getCryptoEnabled()) { - m_pSslCertificate = new SslCertificate(this); - m_pSslCertificate->generateCertificate(); - } - - updateLocalFingerprint(); - connect (this, SIGNAL(windowShown()), this, SLOT(on_windowShown()), Qt::QueuedConnection); + connect (&m_AppConfig, SIGNAL(editionSet(int)), this, SLOT(setEdition(int)), Qt::QueuedConnection); } MainWindow::~MainWindow() @@ -1034,11 +1027,17 @@ void MainWindow::serverDetected(const QString name) void MainWindow::setEdition(int edition) { setWindowTitle(getEditionName(edition)); + if (m_AppConfig.getCryptoEnabled()) { + m_pSslCertificate = new SslCertificate(this); + m_pSslCertificate->generateCertificate(); + } + updateLocalFingerprint(); + saveSettings(); } void MainWindow::updateLocalFingerprint() { - if (Fingerprint::local().fileExists()) { + if (m_AppConfig.getCryptoEnabled() && Fingerprint::local().fileExists()) { m_pLabelFingerprint->setVisible(true); m_pLabelLocalFingerprint->setVisible(true); m_pLabelLocalFingerprint->setText(Fingerprint::local().readFirst()); diff --git a/src/gui/src/MainWindow.h b/src/gui/src/MainWindow.h index b71d8a00..2f0b2c5b 100644 --- a/src/gui/src/MainWindow.h +++ b/src/gui/src/MainWindow.h @@ -115,10 +115,10 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase void autoAddScreen(const QString name); void updateZeroconfService(); void serverDetected(const QString name); - void setEdition(int edition); void updateLocalFingerprint(); public slots: + void setEdition(int edition); void appendLogRaw(const QString& text); void appendLogInfo(const QString& text); void appendLogDebug(const QString& text); diff --git a/src/gui/src/SettingsDialog.cpp b/src/gui/src/SettingsDialog.cpp index 14cd1fc7..813eac36 100644 --- a/src/gui/src/SettingsDialog.cpp +++ b/src/gui/src/SettingsDialog.cpp @@ -151,6 +151,5 @@ void SettingsDialog::on_m_pCheckBoxEnableCrypto_toggled(bool checked) sslCertificate.generateCertificate(); MainWindow& mainWindow = dynamic_cast (*this->parent()); mainWindow.updateLocalFingerprint(); - mainWindow.saveSettings(); } } diff --git a/src/gui/src/SetupWizard.cpp b/src/gui/src/SetupWizard.cpp index a9dab840..b4e6ab3a 100644 --- a/src/gui/src/SetupWizard.cpp +++ b/src/gui/src/SetupWizard.cpp @@ -28,9 +28,7 @@ SetupWizard::SetupWizard(MainWindow& mainWindow, bool startMain) : m_MainWindow(mainWindow), - m_StartMain(startMain), - m_Edition(Unregistered), - m_LoginAttemps(0) + m_StartMain(startMain) { setupUi(this); @@ -141,7 +139,6 @@ void SetupWizard::reject() if (m_StartMain) { - m_MainWindow.setEdition(m_Edition); m_MainWindow.open(); } diff --git a/src/gui/src/SetupWizard.h b/src/gui/src/SetupWizard.h index a1fde149..009939b2 100644 --- a/src/gui/src/SetupWizard.h +++ b/src/gui/src/SetupWizard.h @@ -47,8 +47,6 @@ private: MainWindow& m_MainWindow; bool m_StartMain; SynergyLocale m_Locale; - int m_Edition; - int m_LoginAttemps; private slots: void on_m_pComboLanguage_currentIndexChanged(int index); From 002bcebbd2010b6ec06275f67725091843022d99 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Tue, 4 Oct 2016 13:47:28 +0100 Subject: [PATCH 057/101] #5629 Fix main window AppConfig naming conventions --- src/gui/src/SettingsDialog.cpp | 10 +++++----- src/gui/src/SettingsDialog.h | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/gui/src/SettingsDialog.cpp b/src/gui/src/SettingsDialog.cpp index 813eac36..9b1d1b0e 100644 --- a/src/gui/src/SettingsDialog.cpp +++ b/src/gui/src/SettingsDialog.cpp @@ -38,7 +38,7 @@ static const char networkSecurity[] = "ns"; SettingsDialog::SettingsDialog(QWidget* parent, AppConfig& config) : QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint), Ui::SettingsDialogBase(), - m_AppConfig(config) + m_appConfig(config) { setupUi(this); @@ -63,8 +63,8 @@ SettingsDialog::SettingsDialog(QWidget* parent, AppConfig& config) : m_pComboElevate->hide(); #endif - m_pCheckBoxEnableCrypto->setChecked(m_AppConfig.getCryptoEnabled()); - m_pCheckBoxEnableCrypto->setEnabled(m_AppConfig.edition() == Pro); + m_pCheckBoxEnableCrypto->setChecked(m_appConfig.getCryptoEnabled()); + m_pCheckBoxEnableCrypto->setEnabled(m_appConfig.edition() == Pro); } void SettingsDialog::accept() @@ -144,8 +144,8 @@ void SettingsDialog::on_m_pComboLanguage_currentIndexChanged(int index) void SettingsDialog::on_m_pCheckBoxEnableCrypto_toggled(bool checked) { - m_AppConfig.setCryptoEnabled(checked); - m_AppConfig.saveSettings(); + m_appConfig.setCryptoEnabled(checked); + m_appConfig.saveSettings(); if (checked) { SslCertificate sslCertificate; sslCertificate.generateCertificate(); diff --git a/src/gui/src/SettingsDialog.h b/src/gui/src/SettingsDialog.h index 656323a6..841ffff8 100644 --- a/src/gui/src/SettingsDialog.h +++ b/src/gui/src/SettingsDialog.h @@ -40,10 +40,10 @@ class SettingsDialog : public QDialog, public Ui::SettingsDialogBase void accept(); void reject(); void changeEvent(QEvent* event); - AppConfig& appConfig() { return m_AppConfig; } + AppConfig& appConfig() { return m_appConfig; } private: - AppConfig& m_AppConfig; + AppConfig& m_appConfig; SynergyLocale m_Locale; CoreInterface m_CoreInterface; From c288918d68d7fd67d99dfefe8b7cde87ccb52948 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Tue, 4 Oct 2016 15:12:27 +0100 Subject: [PATCH 058/101] #5629 Fix height of settings dialog --- src/gui/res/SettingsDialogBase.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/res/SettingsDialogBase.ui b/src/gui/res/SettingsDialogBase.ui index edfabaf9..dca1bdad 100644 --- a/src/gui/res/SettingsDialogBase.ui +++ b/src/gui/res/SettingsDialogBase.ui @@ -7,7 +7,7 @@ 0 0 368 - 470 + 380 From b345eb4067ee9cba62598a5a73e159ce7f8f81b0 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Tue, 4 Oct 2016 15:30:53 +0100 Subject: [PATCH 059/101] v1.8.4-rc1 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fe96198b..a86fee80 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,7 +18,7 @@ set(VERSION_MAJOR 1) set(VERSION_MINOR 8) set(VERSION_REV 4) -set(VERSION_STAGE beta) +set(VERSION_STAGE rc1) set(VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REV}") cmake_minimum_required(VERSION 2.6) From e6a3caaf75d88441072fde03b507929786c11a2d Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Tue, 4 Oct 2016 15:51:07 +0100 Subject: [PATCH 060/101] #5628 Fix net lib linkage on Ubuntu --- src/lib/net/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/net/CMakeLists.txt b/src/lib/net/CMakeLists.txt index 3e64fe5d..10e2cae1 100644 --- a/src/lib/net/CMakeLists.txt +++ b/src/lib/net/CMakeLists.txt @@ -52,5 +52,5 @@ if (WIN32) endif() if (UNIX) - target_link_libraries(net mt io) + target_link_libraries(net mt io ${OPENSSL_LIBS}) endif() From f3d1470e58b5a7f76e388b2bf170a9e5d2dd4729 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Mon, 19 Sep 2016 17:22:41 +0100 Subject: [PATCH 061/101] Brutally replace all reinterpret_casts with static_casts --- .../MSWindowsClientTaskBarReceiver.cpp | 12 ++--- .../MSWindowsPortableTaskBarReceiver.cpp | 16 +++--- .../MSWindowsServerTaskBarReceiver.cpp | 16 +++--- src/gui/src/SynergyLocale.cpp | 2 +- src/lib/arch/unix/ArchMultithreadPosix.cpp | 2 +- src/lib/arch/unix/ArchNetworkBSD.cpp | 12 ++--- src/lib/arch/win32/ArchMiscWindows.cpp | 14 +++--- src/lib/arch/win32/ArchMultithreadWindows.cpp | 4 +- src/lib/arch/win32/ArchNetworkWinsock.cpp | 10 ++-- src/lib/arch/win32/ArchTaskBarWindows.cpp | 22 ++++---- src/lib/arch/win32/ArchTimeWindows.cpp | 2 +- src/lib/base/EventQueue.cpp | 2 +- src/lib/base/Unicode.cpp | 50 +++++++++---------- src/lib/client/Client.cpp | 10 ++-- src/lib/io/StreamBuffer.cpp | 4 +- src/lib/io/StreamFilter.cpp | 2 +- src/lib/mt/Thread.cpp | 2 +- src/lib/net/SecureSocket.cpp | 2 +- src/lib/net/SocketMultiplexer.cpp | 2 +- src/lib/net/TCPListenSocket.cpp | 2 +- src/lib/net/TCPSocket.cpp | 2 +- .../MSWindowsClipboardBitmapConverter.cpp | 2 +- src/lib/platform/MSWindowsDesks.cpp | 10 ++-- src/lib/platform/MSWindowsScreen.cpp | 8 +-- src/lib/platform/MSWindowsScreenSaver.cpp | 4 +- src/lib/platform/OSXClipboardBMPConverter.cpp | 4 +- src/lib/platform/OSXKeyState.cpp | 2 +- src/lib/platform/OSXScreen.cpp | 2 +- src/lib/platform/OSXUchrKeyResource.cpp | 26 +++++----- src/lib/platform/XWindowsClipboard.cpp | 20 ++++---- .../XWindowsClipboardAnyBitmapConverter.cpp | 4 +- .../XWindowsClipboardBMPConverter.cpp | 4 +- src/lib/platform/XWindowsKeyState.cpp | 2 +- src/lib/platform/XWindowsScreen.cpp | 8 +-- src/lib/platform/XWindowsUtil.cpp | 14 +++--- src/lib/server/ClientListener.cpp | 4 +- src/lib/server/InputFilter.cpp | 8 +-- src/lib/server/Server.cpp | 42 ++++++++-------- src/lib/synergy/ClientApp.cpp | 4 +- src/lib/synergy/ClipboardChunk.cpp | 10 ++-- src/lib/synergy/IClipboard.cpp | 2 +- src/lib/synergy/KeyState.cpp | 2 +- src/lib/synergy/ProtocolUtil.cpp | 28 +++++------ src/lib/synergy/ServerApp.cpp | 2 +- src/lib/synergy/StreamChunker.cpp | 2 +- src/test/integtests/net/NetworkTests.cpp | 22 ++++---- 46 files changed, 213 insertions(+), 213 deletions(-) diff --git a/src/cmd/synergyc/MSWindowsClientTaskBarReceiver.cpp b/src/cmd/synergyc/MSWindowsClientTaskBarReceiver.cpp index 039246cc..529a54dc 100644 --- a/src/cmd/synergyc/MSWindowsClientTaskBarReceiver.cpp +++ b/src/cmd/synergyc/MSWindowsClientTaskBarReceiver.cpp @@ -221,7 +221,7 @@ MSWindowsClientTaskBarReceiver::primaryAction() const IArchTaskBarReceiver::Icon MSWindowsClientTaskBarReceiver::getIcon() const { - return reinterpret_cast(m_icon[getStatus()]); + return static_cast(m_icon[getStatus()]); } void @@ -263,7 +263,7 @@ MSWindowsClientTaskBarReceiver::loadIcon(UINT id) IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR); - return reinterpret_cast(icon); + return static_cast(icon); } void @@ -287,8 +287,8 @@ MSWindowsClientTaskBarReceiver::createWindow() MAKEINTRESOURCE(IDD_TASKBAR_STATUS), NULL, (DLGPROC)&MSWindowsClientTaskBarReceiver::staticDlgProc, - reinterpret_cast( - reinterpret_cast(this))); + static_cast( + static_cast(this))); // window should appear on top of everything, including (especially) // the task bar. @@ -337,8 +337,8 @@ MSWindowsClientTaskBarReceiver::staticDlgProc(HWND hwnd, // and put it in the extra window data then forward the call. MSWindowsClientTaskBarReceiver* self = NULL; if (msg == WM_INITDIALOG) { - self = reinterpret_cast( - reinterpret_cast(lParam)); + self = static_cast( + static_cast(lParam)); SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) lParam); } else { diff --git a/src/cmd/synergyp/MSWindowsPortableTaskBarReceiver.cpp b/src/cmd/synergyp/MSWindowsPortableTaskBarReceiver.cpp index 4f35fe4f..b42f28b3 100644 --- a/src/cmd/synergyp/MSWindowsPortableTaskBarReceiver.cpp +++ b/src/cmd/synergyp/MSWindowsPortableTaskBarReceiver.cpp @@ -238,7 +238,7 @@ MSWindowsPortableTaskBarReceiver::primaryAction() const IArchTaskBarReceiver::Icon MSWindowsPortableTaskBarReceiver::getIcon() const { - return reinterpret_cast(m_icon[getStatus()]); + return static_cast(m_icon[getStatus()]); } void @@ -280,7 +280,7 @@ MSWindowsPortableTaskBarReceiver::loadIcon(UINT id) IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR); - return reinterpret_cast(icon); + return static_cast(icon); } void @@ -304,8 +304,8 @@ MSWindowsPortableTaskBarReceiver::createWindow() MAKEINTRESOURCE(IDD_TASKBAR_STATUS), NULL, (DLGPROC)&MSWindowsPortableTaskBarReceiver::staticDlgProc, - reinterpret_cast( - reinterpret_cast(this))); + static_cast( + static_cast(this))); // window should appear on top of everything, including (especially) // the task bar. @@ -354,16 +354,16 @@ MSWindowsPortableTaskBarReceiver::staticDlgProc(HWND hwnd, // and put it in the extra window data then forward the call. MSWindowsPortableTaskBarReceiver* self = NULL; if (msg == WM_INITDIALOG) { - self = reinterpret_cast( - reinterpret_cast(lParam)); + self = static_cast( + static_cast(lParam)); SetWindowLongPtr(hwnd, GWLP_USERDATA, lParam); } else { // get the extra window data and forward the call LONG data = (LONG)GetWindowLongPtr(hwnd, GWLP_USERDATA); if (data != 0) { - self = reinterpret_cast( - reinterpret_cast(data)); + self = static_cast( + static_cast(data)); } } diff --git a/src/cmd/synergys/MSWindowsServerTaskBarReceiver.cpp b/src/cmd/synergys/MSWindowsServerTaskBarReceiver.cpp index f65e2a35..83fc539c 100644 --- a/src/cmd/synergys/MSWindowsServerTaskBarReceiver.cpp +++ b/src/cmd/synergys/MSWindowsServerTaskBarReceiver.cpp @@ -252,7 +252,7 @@ MSWindowsServerTaskBarReceiver::primaryAction() const IArchTaskBarReceiver::Icon MSWindowsServerTaskBarReceiver::getIcon() const { - return reinterpret_cast(m_icon[getStatus()]); + return static_cast(m_icon[getStatus()]); } void @@ -294,7 +294,7 @@ MSWindowsServerTaskBarReceiver::loadIcon(UINT id) IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR); - return reinterpret_cast(icon); + return static_cast(icon); } void @@ -318,8 +318,8 @@ MSWindowsServerTaskBarReceiver::createWindow() MAKEINTRESOURCE(IDD_TASKBAR_STATUS), NULL, (DLGPROC)&MSWindowsServerTaskBarReceiver::staticDlgProc, - reinterpret_cast( - reinterpret_cast(this))); + static_cast( + static_cast(this))); // window should appear on top of everything, including (especially) // the task bar. @@ -368,16 +368,16 @@ MSWindowsServerTaskBarReceiver::staticDlgProc(HWND hwnd, // and put it in the extra window data then forward the call. MSWindowsServerTaskBarReceiver* self = NULL; if (msg == WM_INITDIALOG) { - self = reinterpret_cast( - reinterpret_cast(lParam)); + self = static_cast( + static_cast(lParam)); SetWindowLongPtr(hwnd, GWLP_USERDATA, lParam); } else { // get the extra window data and forward the call LONG data = (LONG)GetWindowLongPtr(hwnd, GWLP_USERDATA); if (data != 0) { - self = reinterpret_cast( - reinterpret_cast(data)); + self = static_cast( + static_cast(data)); } } diff --git a/src/gui/src/SynergyLocale.cpp b/src/gui/src/SynergyLocale.cpp index fa980ed4..13c8d215 100644 --- a/src/gui/src/SynergyLocale.cpp +++ b/src/gui/src/SynergyLocale.cpp @@ -29,7 +29,7 @@ SynergyLocale::SynergyLocale() void SynergyLocale::loadLanguages() { QResource resource(":/res/lang/Languages.xml"); - QByteArray bytes(reinterpret_cast(resource.data()), resource.size()); + QByteArray bytes(static_cast(resource.data()), resource.size()); QXmlStreamReader xml(bytes); while (!xml.atEnd()) diff --git a/src/lib/arch/unix/ArchMultithreadPosix.cpp b/src/lib/arch/unix/ArchMultithreadPosix.cpp index 807894e2..33da29b4 100644 --- a/src/lib/arch/unix/ArchMultithreadPosix.cpp +++ b/src/lib/arch/unix/ArchMultithreadPosix.cpp @@ -697,7 +697,7 @@ void* ArchMultithreadPosix::threadFunc(void* vrep) { // get the thread - ArchThreadImpl* thread = reinterpret_cast(vrep); + ArchThreadImpl* thread = static_cast(vrep); // setup pthreads pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); diff --git a/src/lib/arch/unix/ArchNetworkBSD.cpp b/src/lib/arch/unix/ArchNetworkBSD.cpp index c2d692fc..f324a7f1 100644 --- a/src/lib/arch/unix/ArchNetworkBSD.cpp +++ b/src/lib/arch/unix/ArchNetworkBSD.cpp @@ -646,7 +646,7 @@ ArchNetworkBSD::newAnyAddr(EAddressFamily family) switch (family) { case kINET: { struct sockaddr_in* ipAddr = - reinterpret_cast(&addr->m_addr); + static_cast(&addr->m_addr); ipAddr->sin_family = AF_INET; ipAddr->sin_port = 0; ipAddr->sin_addr.s_addr = INADDR_ANY; @@ -738,7 +738,7 @@ ArchNetworkBSD::addrToName(ArchNetAddress addr) // mutexed name lookup (ugh) ARCH->lockMutex(m_mutex); struct hostent* info = gethostbyaddr( - reinterpret_cast(&addr->m_addr), + static_cast(&addr->m_addr), addr->m_len, addr->m_addr.sa_family); if (info == NULL) { ARCH->unlockMutex(m_mutex); @@ -762,7 +762,7 @@ ArchNetworkBSD::addrToString(ArchNetAddress addr) switch (getAddrFamily(addr)) { case kINET: { struct sockaddr_in* ipAddr = - reinterpret_cast(&addr->m_addr); + static_cast(&addr->m_addr); ARCH->lockMutex(m_mutex); std::string s = inet_ntoa(ipAddr->sin_addr); ARCH->unlockMutex(m_mutex); @@ -797,7 +797,7 @@ ArchNetworkBSD::setAddrPort(ArchNetAddress addr, int port) switch (getAddrFamily(addr)) { case kINET: { struct sockaddr_in* ipAddr = - reinterpret_cast(&addr->m_addr); + static_cast(&addr->m_addr); ipAddr->sin_port = htons(port); break; } @@ -816,7 +816,7 @@ ArchNetworkBSD::getAddrPort(ArchNetAddress addr) switch (getAddrFamily(addr)) { case kINET: { struct sockaddr_in* ipAddr = - reinterpret_cast(&addr->m_addr); + static_cast(&addr->m_addr); return ntohs(ipAddr->sin_port); } @@ -834,7 +834,7 @@ ArchNetworkBSD::isAnyAddr(ArchNetAddress addr) switch (getAddrFamily(addr)) { case kINET: { struct sockaddr_in* ipAddr = - reinterpret_cast(&addr->m_addr); + static_cast(&addr->m_addr); return (ipAddr->sin_addr.s_addr == INADDR_ANY && addr->m_len == (socklen_t)sizeof(struct sockaddr_in)); } diff --git a/src/lib/arch/win32/ArchMiscWindows.cpp b/src/lib/arch/win32/ArchMiscWindows.cpp index d70861d2..53b71286 100644 --- a/src/lib/arch/win32/ArchMiscWindows.cpp +++ b/src/lib/arch/win32/ArchMiscWindows.cpp @@ -234,7 +234,7 @@ ArchMiscWindows::setValue(HKEY key, return; } RegSetValueEx(key, name, 0, REG_SZ, - reinterpret_cast(value.c_str()), + static_cast(value.c_str()), (DWORD)value.size() + 1); } @@ -247,7 +247,7 @@ ArchMiscWindows::setValue(HKEY key, const TCHAR* name, DWORD value) return; } RegSetValueEx(key, name, 0, REG_DWORD, - reinterpret_cast(&value), + static_cast(&value), sizeof(DWORD)); } @@ -262,7 +262,7 @@ ArchMiscWindows::setValueBinary(HKEY key, return; } RegSetValueEx(key, name, 0, REG_BINARY, - reinterpret_cast(value.data()), + static_cast(value.data()), (DWORD)value.size()); } @@ -287,7 +287,7 @@ ArchMiscWindows::readBinaryOrString(HKEY key, const TCHAR* name, DWORD type) // read it result = RegQueryValueEx(key, name, 0, &actualType, - reinterpret_cast(buffer), &size); + static_cast(buffer), &size); if (result != ERROR_SUCCESS || actualType != type) { delete[] buffer; return std::string(); @@ -322,7 +322,7 @@ ArchMiscWindows::readValueInt(HKEY key, const TCHAR* name) DWORD value; DWORD size = sizeof(value); LONG result = RegQueryValueEx(key, name, 0, &type, - reinterpret_cast(&value), &size); + static_cast(&value), &size); if (result != ERROR_SUCCESS || type != REG_DWORD) { return 0; } @@ -374,7 +374,7 @@ ArchMiscWindows::setThreadExecutionState(DWORD busyModes) if (s_stes == NULL) { HINSTANCE kernel = LoadLibrary("kernel32.dll"); if (kernel != NULL) { - s_stes = reinterpret_cast(GetProcAddress(kernel, + s_stes = static_cast(GetProcAddress(kernel, "SetThreadExecutionState")); } if (s_stes == NULL) { @@ -414,7 +414,7 @@ ArchMiscWindows::wakeupDisplay() if (s_stes == NULL) { HINSTANCE kernel = LoadLibrary("kernel32.dll"); if (kernel != NULL) { - s_stes = reinterpret_cast(GetProcAddress(kernel, + s_stes = static_cast(GetProcAddress(kernel, "SetThreadExecutionState")); } if (s_stes == NULL) { diff --git a/src/lib/arch/win32/ArchMultithreadWindows.cpp b/src/lib/arch/win32/ArchMultithreadWindows.cpp index 0768492d..70aafa2d 100644 --- a/src/lib/arch/win32/ArchMultithreadWindows.cpp +++ b/src/lib/arch/win32/ArchMultithreadWindows.cpp @@ -303,7 +303,7 @@ ArchMultithreadWindows::newThread(ThreadFunc func, void* data) // create thread unsigned int id = 0; - thread->m_thread = reinterpret_cast(_beginthreadex(NULL, 0, + thread->m_thread = static_cast(_beginthreadex(NULL, 0, threadFunc, (void*)thread, 0, &id)); thread->m_id = static_cast(id); @@ -661,7 +661,7 @@ unsigned int __stdcall ArchMultithreadWindows::threadFunc(void* vrep) { // get the thread - ArchThreadImpl* thread = reinterpret_cast(vrep); + ArchThreadImpl* thread = static_cast(vrep); // run thread s_instance->doThreadFunc(thread); diff --git a/src/lib/arch/win32/ArchNetworkWinsock.cpp b/src/lib/arch/win32/ArchNetworkWinsock.cpp index 712e1bdc..265924d5 100644 --- a/src/lib/arch/win32/ArchNetworkWinsock.cpp +++ b/src/lib/arch/win32/ArchNetworkWinsock.cpp @@ -754,7 +754,7 @@ ArchNetworkWinsock::addrToName(ArchNetAddress addr) // name lookup struct hostent* info = gethostbyaddr_winsock( - reinterpret_cast(&addr->m_addr), + static_cast(&addr->m_addr), addr->m_len, addr->m_addr.sa_family); if (info == NULL) { throwNameError(getsockerror_winsock()); @@ -772,7 +772,7 @@ ArchNetworkWinsock::addrToString(ArchNetAddress addr) switch (getAddrFamily(addr)) { case kINET: { struct sockaddr_in* ipAddr = - reinterpret_cast(&addr->m_addr); + static_cast(&addr->m_addr); return inet_ntoa_winsock(ipAddr->sin_addr); } @@ -804,7 +804,7 @@ ArchNetworkWinsock::setAddrPort(ArchNetAddress addr, int port) switch (getAddrFamily(addr)) { case kINET: { struct sockaddr_in* ipAddr = - reinterpret_cast(&addr->m_addr); + static_cast(&addr->m_addr); ipAddr->sin_port = htons_winsock(static_cast(port)); break; } @@ -823,7 +823,7 @@ ArchNetworkWinsock::getAddrPort(ArchNetAddress addr) switch (getAddrFamily(addr)) { case kINET: { struct sockaddr_in* ipAddr = - reinterpret_cast(&addr->m_addr); + static_cast(&addr->m_addr); return ntohs_winsock(ipAddr->sin_port); } @@ -841,7 +841,7 @@ ArchNetworkWinsock::isAnyAddr(ArchNetAddress addr) switch (getAddrFamily(addr)) { case kINET: { struct sockaddr_in* ipAddr = - reinterpret_cast(&addr->m_addr); + static_cast(&addr->m_addr); return (addr->m_len == sizeof(struct sockaddr_in) && ipAddr->sin_addr.s_addr == INADDR_ANY); } diff --git a/src/lib/arch/win32/ArchTaskBarWindows.cpp b/src/lib/arch/win32/ArchTaskBarWindows.cpp index e4154ab2..eac283a8 100644 --- a/src/lib/arch/win32/ArchTaskBarWindows.cpp +++ b/src/lib/arch/win32/ArchTaskBarWindows.cpp @@ -245,7 +245,7 @@ ArchTaskBarWindows::modifyIconNoLock( receiver->lock(); // get icon data - HICON icon = reinterpret_cast( + HICON icon = static_cast( const_cast(receiver->getIcon())); // get tool tip @@ -414,17 +414,17 @@ ArchTaskBarWindows::staticWndProc(HWND hwnd, UINT msg, ArchTaskBarWindows* self = NULL; if (msg == WM_NCCREATE) { CREATESTRUCT* createInfo; - createInfo = reinterpret_cast(lParam); - self = reinterpret_cast( + createInfo = static_cast(lParam); + self = static_cast( createInfo->lpCreateParams); - SetWindowLong(hwnd, 0, reinterpret_cast(self)); + SetWindowLong(hwnd, 0, static_cast(self)); } else { // get the extra window data and forward the call LONG data = GetWindowLong(hwnd, 0); if (data != 0) { - self = reinterpret_cast( - reinterpret_cast(data)); + self = static_cast( + static_cast(data)); } } @@ -461,14 +461,14 @@ ArchTaskBarWindows::threadMainLoop() // create window m_hwnd = CreateWindowEx(WS_EX_TOOLWINDOW, - reinterpret_cast(windowClass), + static_cast(windowClass), TEXT("Synergy Task Bar"), WS_POPUP, 0, 0, 1, 1, NULL, NULL, instanceWin32(), - reinterpret_cast(this)); + static_cast(this)); // signal ready ARCH->lockMutex(m_mutex); @@ -478,7 +478,7 @@ ArchTaskBarWindows::threadMainLoop() // handle failure if (m_hwnd == NULL) { - UnregisterClass(reinterpret_cast(windowClass), instanceWin32()); + UnregisterClass(static_cast(windowClass), instanceWin32()); return; } @@ -494,13 +494,13 @@ ArchTaskBarWindows::threadMainLoop() // clean up removeAllIcons(); DestroyWindow(m_hwnd); - UnregisterClass(reinterpret_cast(windowClass), instanceWin32()); + UnregisterClass(static_cast(windowClass), instanceWin32()); } void* ArchTaskBarWindows::threadEntry(void* self) { - reinterpret_cast(self)->threadMainLoop(); + static_cast(self)->threadMainLoop(); return NULL; } diff --git a/src/lib/arch/win32/ArchTimeWindows.cpp b/src/lib/arch/win32/ArchTimeWindows.cpp index ef3f9ef8..cf48c2a2 100644 --- a/src/lib/arch/win32/ArchTimeWindows.cpp +++ b/src/lib/arch/win32/ArchTimeWindows.cpp @@ -65,7 +65,7 @@ ArchTimeWindows::~ArchTimeWindows() { s_freq = 0.0; if (s_mmInstance == NULL) { - FreeLibrary(reinterpret_cast(s_mmInstance)); + FreeLibrary(static_cast(s_mmInstance)); s_tgt = NULL; s_mmInstance = NULL; } diff --git a/src/lib/base/EventQueue.cpp b/src/lib/base/EventQueue.cpp index 60a16317..5f15293f 100644 --- a/src/lib/base/EventQueue.cpp +++ b/src/lib/base/EventQueue.cpp @@ -54,7 +54,7 @@ static void interrupt(Arch::ESignal, void* data) { - EventQueue* events = reinterpret_cast(data); + EventQueue* events = static_cast(data); events->addEvent(Event(Event::kQuit)); } diff --git a/src/lib/base/Unicode.cpp b/src/lib/base/Unicode.cpp index ad7a266d..fd4ad694 100644 --- a/src/lib/base/Unicode.cpp +++ b/src/lib/base/Unicode.cpp @@ -101,7 +101,7 @@ bool Unicode::isUTF8(const String& src) { // convert and test each character - const UInt8* data = reinterpret_cast(src.c_str()); + const UInt8* data = static_cast(src.c_str()); for (UInt32 n = (UInt32)src.size(); n > 0; ) { if (fromUTF8(data, n) == s_invalid) { return false; @@ -122,7 +122,7 @@ Unicode::UTF8ToUCS2(const String& src, bool* errors) dst.reserve(2 * n); // convert each character - const UInt8* data = reinterpret_cast(src.c_str()); + const UInt8* data = static_cast(src.c_str()); while (n > 0) { UInt32 c = fromUTF8(data, n); if (c == s_invalid) { @@ -133,7 +133,7 @@ Unicode::UTF8ToUCS2(const String& src, bool* errors) c = s_replacement; } UInt16 ucs2 = static_cast(c); - dst.append(reinterpret_cast(&ucs2), 2); + dst.append(static_cast(&ucs2), 2); } return dst; @@ -151,13 +151,13 @@ Unicode::UTF8ToUCS4(const String& src, bool* errors) dst.reserve(4 * n); // convert each character - const UInt8* data = reinterpret_cast(src.c_str()); + const UInt8* data = static_cast(src.c_str()); while (n > 0) { UInt32 c = fromUTF8(data, n); if (c == s_invalid) { c = s_replacement; } - dst.append(reinterpret_cast(&c), 4); + dst.append(static_cast(&c), 4); } return dst; @@ -175,7 +175,7 @@ Unicode::UTF8ToUTF16(const String& src, bool* errors) dst.reserve(2 * n); // convert each character - const UInt8* data = reinterpret_cast(src.c_str()); + const UInt8* data = static_cast(src.c_str()); while (n > 0) { UInt32 c = fromUTF8(data, n); if (c == s_invalid) { @@ -187,14 +187,14 @@ Unicode::UTF8ToUTF16(const String& src, bool* errors) } if (c < 0x00010000) { UInt16 ucs2 = static_cast(c); - dst.append(reinterpret_cast(&ucs2), 2); + dst.append(static_cast(&ucs2), 2); } else { c -= 0x00010000; UInt16 utf16h = static_cast((c >> 10) + 0xd800); UInt16 utf16l = static_cast((c & 0x03ff) + 0xdc00); - dst.append(reinterpret_cast(&utf16h), 2); - dst.append(reinterpret_cast(&utf16l), 2); + dst.append(static_cast(&utf16h), 2); + dst.append(static_cast(&utf16l), 2); } } @@ -213,7 +213,7 @@ Unicode::UTF8ToUTF32(const String& src, bool* errors) dst.reserve(4 * n); // convert each character - const UInt8* data = reinterpret_cast(src.c_str()); + const UInt8* data = static_cast(src.c_str()); while (n > 0) { UInt32 c = fromUTF8(data, n); if (c == s_invalid) { @@ -223,7 +223,7 @@ Unicode::UTF8ToUTF32(const String& src, bool* errors) setError(errors); c = s_replacement; } - dst.append(reinterpret_cast(&c), 4); + dst.append(static_cast(&c), 4); } return dst; @@ -260,7 +260,7 @@ Unicode::UCS2ToUTF8(const String& src, bool* errors) // convert UInt32 n = (UInt32)src.size() >> 1; - return doUCS2ToUTF8(reinterpret_cast(src.data()), n, errors); + return doUCS2ToUTF8(static_cast(src.data()), n, errors); } String @@ -271,7 +271,7 @@ Unicode::UCS4ToUTF8(const String& src, bool* errors) // convert UInt32 n = (UInt32)src.size() >> 2; - return doUCS4ToUTF8(reinterpret_cast(src.data()), n, errors); + return doUCS4ToUTF8(static_cast(src.data()), n, errors); } String @@ -282,7 +282,7 @@ Unicode::UTF16ToUTF8(const String& src, bool* errors) // convert UInt32 n = (UInt32)src.size() >> 1; - return doUTF16ToUTF8(reinterpret_cast(src.data()), n, errors); + return doUTF16ToUTF8(static_cast(src.data()), n, errors); } String @@ -293,7 +293,7 @@ Unicode::UTF32ToUTF8(const String& src, bool* errors) // convert UInt32 n = (UInt32)src.size() >> 2; - return doUTF32ToUTF8(reinterpret_cast(src.data()), n, errors); + return doUTF32ToUTF8(static_cast(src.data()), n, errors); } String @@ -361,16 +361,16 @@ Unicode::wideCharToUTF8(const wchar_t* src, UInt32 size, bool* errors) // the String's nul character). switch (ARCH->getWideCharEncoding()) { case IArchString::kUCS2: - return doUCS2ToUTF8(reinterpret_cast(src), size, errors); + return doUCS2ToUTF8(static_cast(src), size, errors); case IArchString::kUCS4: - return doUCS4ToUTF8(reinterpret_cast(src), size, errors); + return doUCS4ToUTF8(static_cast(src), size, errors); case IArchString::kUTF16: - return doUTF16ToUTF8(reinterpret_cast(src), size, errors); + return doUTF16ToUTF8(static_cast(src), size, errors); case IArchString::kUTF32: - return doUTF32ToUTF8(reinterpret_cast(src), size, errors); + return doUTF32ToUTF8(static_cast(src), size, errors); default: assert(0 && "unknown wide character encoding"); @@ -741,25 +741,25 @@ Unicode::toUTF8(String& dst, UInt32 c, bool* errors) // convert to UTF-8 if (c < 0x00000080) { data[0] = static_cast(c); - dst.append(reinterpret_cast(data), 1); + dst.append(static_cast(data), 1); } else if (c < 0x00000800) { data[0] = static_cast(((c >> 6) & 0x0000001f) + 0xc0); data[1] = static_cast((c & 0x0000003f) + 0x80); - dst.append(reinterpret_cast(data), 2); + dst.append(static_cast(data), 2); } else if (c < 0x00010000) { data[0] = static_cast(((c >> 12) & 0x0000000f) + 0xe0); data[1] = static_cast(((c >> 6) & 0x0000003f) + 0x80); data[2] = static_cast((c & 0x0000003f) + 0x80); - dst.append(reinterpret_cast(data), 3); + dst.append(static_cast(data), 3); } else if (c < 0x00200000) { data[0] = static_cast(((c >> 18) & 0x00000007) + 0xf0); data[1] = static_cast(((c >> 12) & 0x0000003f) + 0x80); data[2] = static_cast(((c >> 6) & 0x0000003f) + 0x80); data[3] = static_cast((c & 0x0000003f) + 0x80); - dst.append(reinterpret_cast(data), 4); + dst.append(static_cast(data), 4); } else if (c < 0x04000000) { data[0] = static_cast(((c >> 24) & 0x00000003) + 0xf8); @@ -767,7 +767,7 @@ Unicode::toUTF8(String& dst, UInt32 c, bool* errors) data[2] = static_cast(((c >> 12) & 0x0000003f) + 0x80); data[3] = static_cast(((c >> 6) & 0x0000003f) + 0x80); data[4] = static_cast((c & 0x0000003f) + 0x80); - dst.append(reinterpret_cast(data), 5); + dst.append(static_cast(data), 5); } else if (c < 0x80000000) { data[0] = static_cast(((c >> 30) & 0x00000001) + 0xfc); @@ -776,7 +776,7 @@ Unicode::toUTF8(String& dst, UInt32 c, bool* errors) data[3] = static_cast(((c >> 12) & 0x0000003f) + 0x80); data[4] = static_cast(((c >> 6) & 0x0000003f) + 0x80); data[5] = static_cast((c & 0x0000003f) + 0x80); - dst.append(reinterpret_cast(data), 6); + dst.append(static_cast(data), 6); } else { assert(0 && "character out of range"); diff --git a/src/lib/client/Client.cpp b/src/lib/client/Client.cpp index d984be4c..e0ef9e8b 100644 --- a/src/lib/client/Client.cpp +++ b/src/lib/client/Client.cpp @@ -430,7 +430,7 @@ Client::sendConnectionFailedEvent(const char* msg) void Client::sendFileChunk(const void* data) { - FileChunk* chunk = reinterpret_cast(const_cast(data)); + FileChunk* chunk = static_cast(const_cast(data)); LOG((CLOG_DEBUG1 "send file chunk")); assert(m_server != NULL); @@ -605,7 +605,7 @@ void Client::handleConnectionFailed(const Event& event, void*) { IDataSocket::ConnectionFailedInfo* info = - reinterpret_cast(event.getData()); + static_cast(event.getData()); cleanupTimer(); cleanupConnecting(); @@ -661,7 +661,7 @@ Client::handleClipboardGrabbed(const Event& event, void*) } const IScreen::ClipboardInfo* info = - reinterpret_cast(event.getData()); + static_cast(event.getData()); // grab ownership m_server->onGrabClipboard(info->m_id); @@ -810,14 +810,14 @@ Client::sendFileToServer(const char* filename) m_sendFileThread = new Thread( new TMethodJob( this, &Client::sendFileThread, - reinterpret_cast(const_cast(filename)))); + static_cast(const_cast(filename)))); } void Client::sendFileThread(void* filename) { try { - char* name = reinterpret_cast(filename); + char* name = static_cast(filename); StreamChunker::sendFile(name, m_events, this); } catch (std::runtime_error error) { diff --git a/src/lib/io/StreamBuffer.cpp b/src/lib/io/StreamBuffer.cpp index 050adae1..80903ada 100644 --- a/src/lib/io/StreamBuffer.cpp +++ b/src/lib/io/StreamBuffer.cpp @@ -59,7 +59,7 @@ StreamBuffer::peek(UInt32 n) scan = m_chunks.erase(scan); } - return reinterpret_cast(&(head->begin()[m_headUsed])); + return static_cast(&(head->begin()[m_headUsed])); } void @@ -104,7 +104,7 @@ StreamBuffer::write(const void* vdata, UInt32 n) m_size += n; // cast data to bytes - const UInt8* data = reinterpret_cast(vdata); + const UInt8* data = static_cast(vdata); // point to last chunk if it has space, otherwise append an empty chunk ChunkList::iterator scan = m_chunks.end(); diff --git a/src/lib/io/StreamFilter.cpp b/src/lib/io/StreamFilter.cpp index eb66b973..468aff84 100644 --- a/src/lib/io/StreamFilter.cpp +++ b/src/lib/io/StreamFilter.cpp @@ -83,7 +83,7 @@ StreamFilter::shutdownOutput() void* StreamFilter::getEventTarget() const { - return const_cast(reinterpret_cast(this)); + return const_cast(static_cast(this)); } bool diff --git a/src/lib/mt/Thread.cpp b/src/lib/mt/Thread.cpp index 0c67e8a9..752aace8 100644 --- a/src/lib/mt/Thread.cpp +++ b/src/lib/mt/Thread.cpp @@ -147,7 +147,7 @@ Thread::threadFunc(void* vjob) } // get job - IJob* job = reinterpret_cast(vjob); + IJob* job = static_cast(vjob); // run job void* result = NULL; diff --git a/src/lib/net/SecureSocket.cpp b/src/lib/net/SecureSocket.cpp index 7076c764..cd0068a5 100644 --- a/src/lib/net/SecureSocket.cpp +++ b/src/lib/net/SecureSocket.cpp @@ -683,7 +683,7 @@ SecureSocket::verifyCertFingerprint() } // format fingerprint into hexdecimal format with colon separator - String fingerprint(reinterpret_cast(tempFingerprint), tempFingerprintLen); + String fingerprint(static_cast(tempFingerprint), tempFingerprintLen); formatFingerprint(fingerprint); LOG((CLOG_NOTE "server fingerprint: %s", fingerprint.c_str())); diff --git a/src/lib/net/SocketMultiplexer.cpp b/src/lib/net/SocketMultiplexer.cpp index 9ba352a6..b7f9236f 100644 --- a/src/lib/net/SocketMultiplexer.cpp +++ b/src/lib/net/SocketMultiplexer.cpp @@ -46,7 +46,7 @@ SocketMultiplexer::SocketMultiplexer() : // this pointer just has to be unique and not NULL. it will // never be dereferenced. it's used to identify cursor nodes // in the jobs list. - m_cursorMark = reinterpret_cast(this); + m_cursorMark = static_cast(this); // start thread m_thread = new Thread(new TMethodJob( diff --git a/src/lib/net/TCPListenSocket.cpp b/src/lib/net/TCPListenSocket.cpp index 94760d53..2b20c124 100644 --- a/src/lib/net/TCPListenSocket.cpp +++ b/src/lib/net/TCPListenSocket.cpp @@ -102,7 +102,7 @@ TCPListenSocket::close() void* TCPListenSocket::getEventTarget() const { - return const_cast(reinterpret_cast(this)); + return const_cast(static_cast(this)); } IDataSocket* diff --git a/src/lib/net/TCPSocket.cpp b/src/lib/net/TCPSocket.cpp index ce2cdd09..680e49e5 100644 --- a/src/lib/net/TCPSocket.cpp +++ b/src/lib/net/TCPSocket.cpp @@ -125,7 +125,7 @@ TCPSocket::close() void* TCPSocket::getEventTarget() const { - return const_cast(reinterpret_cast(this)); + return const_cast(static_cast(this)); } UInt32 diff --git a/src/lib/platform/MSWindowsClipboardBitmapConverter.cpp b/src/lib/platform/MSWindowsClipboardBitmapConverter.cpp index c78bd3c4..9b39ca7e 100644 --- a/src/lib/platform/MSWindowsClipboardBitmapConverter.cpp +++ b/src/lib/platform/MSWindowsClipboardBitmapConverter.cpp @@ -78,7 +78,7 @@ MSWindowsClipboardBitmapConverter::toIClipboard(HANDLE data) const UInt32 srcSize = (UInt32)GlobalSize(data); // check image type - const BITMAPINFO* bitmap = reinterpret_cast(src); + const BITMAPINFO* bitmap = static_cast(src); LOG((CLOG_INFO "bitmap: %dx%d %d", bitmap->bmiHeader.biWidth, bitmap->bmiHeader.biHeight, (int)bitmap->bmiHeader.biBitCount)); if (bitmap->bmiHeader.biPlanes == 1 && (bitmap->bmiHeader.biBitCount == 24 || diff --git a/src/lib/platform/MSWindowsDesks.cpp b/src/lib/platform/MSWindowsDesks.cpp index cb1ed9e9..555d2e79 100644 --- a/src/lib/platform/MSWindowsDesks.cpp +++ b/src/lib/platform/MSWindowsDesks.cpp @@ -241,7 +241,7 @@ void MSWindowsDesks::getCursorPos(SInt32& x, SInt32& y) const { POINT pos; - sendMessage(SYNERGY_MSG_CURSOR_POS, reinterpret_cast(&pos), 0); + sendMessage(SYNERGY_MSG_CURSOR_POS, static_cast(&pos), 0); x = pos.x; y = pos.y; } @@ -427,7 +427,7 @@ void MSWindowsDesks::destroyClass(ATOM windowClass) const { if (windowClass != 0) { - UnregisterClass(reinterpret_cast(windowClass), + UnregisterClass(static_cast(windowClass), MSWindowsScreen::getWindowInstance()); } } @@ -437,7 +437,7 @@ MSWindowsDesks::createWindow(ATOM windowClass, const char* name) const { HWND window = CreateWindowEx(WS_EX_TRANSPARENT | WS_EX_TOOLWINDOW, - reinterpret_cast(windowClass), + static_cast(windowClass), name, WS_POPUP, 0, 0, 1, 1, @@ -656,7 +656,7 @@ MSWindowsDesks::deskThread(void* vdesk) MSG msg; // use given desktop for this thread - Desk* desk = reinterpret_cast(vdesk); + Desk* desk = static_cast(vdesk); desk->m_threadID = GetCurrentThreadId(); desk->m_window = NULL; desk->m_foregroundWindow = NULL; @@ -757,7 +757,7 @@ MSWindowsDesks::deskThread(void* vdesk) break; case SYNERGY_MSG_CURSOR_POS: { - POINT* pos = reinterpret_cast(msg.wParam); + POINT* pos = static_cast(msg.wParam); if (!GetCursorPos(pos)) { pos->x = m_xCenter; pos->y = m_yCenter; diff --git a/src/lib/platform/MSWindowsScreen.cpp b/src/lib/platform/MSWindowsScreen.cpp index de0c7c26..68c628cc 100644 --- a/src/lib/platform/MSWindowsScreen.cpp +++ b/src/lib/platform/MSWindowsScreen.cpp @@ -864,7 +864,7 @@ void MSWindowsScreen::destroyClass(ATOM windowClass) const { if (windowClass != 0) { - UnregisterClass(reinterpret_cast(windowClass), s_windowInstance); + UnregisterClass(static_cast(windowClass), s_windowInstance); } } @@ -874,7 +874,7 @@ MSWindowsScreen::createWindow(ATOM windowClass, const char* name) const HWND window = CreateWindowEx(WS_EX_TOPMOST | WS_EX_TRANSPARENT | WS_EX_TOOLWINDOW, - reinterpret_cast(windowClass), + static_cast(windowClass), name, WS_POPUP, 0, 0, 1, 1, @@ -895,7 +895,7 @@ MSWindowsScreen::createDropWindow(ATOM windowClass, const char* name) const WS_EX_TOPMOST | WS_EX_TRANSPARENT | WS_EX_ACCEPTFILES, - reinterpret_cast(m_class), + static_cast(m_class), name, WS_POPUP, 0, 0, m_dropWindowSize, m_dropWindowSize, @@ -941,7 +941,7 @@ MSWindowsScreen::sendClipboardEvent(Event::Type type, ClipboardID id) void MSWindowsScreen::handleSystemEvent(const Event& event, void*) { - MSG* msg = reinterpret_cast(event.getData()); + MSG* msg = static_cast(event.getData()); assert(msg != NULL); if (ArchMiscWindows::processDialog(msg)) { diff --git a/src/lib/platform/MSWindowsScreenSaver.cpp b/src/lib/platform/MSWindowsScreenSaver.cpp index f2ab7334..4289bb01 100644 --- a/src/lib/platform/MSWindowsScreenSaver.cpp +++ b/src/lib/platform/MSWindowsScreenSaver.cpp @@ -162,7 +162,7 @@ MSWindowsScreenSaver::deactivate() if (desktop != NULL) { EnumDesktopWindows(desktop, &MSWindowsScreenSaver::killScreenSaverFunc, - reinterpret_cast(&killed)); + static_cast(&killed)); CloseDesktop(desktop); } @@ -205,7 +205,7 @@ MSWindowsScreenSaver::killScreenSaverFunc(HWND hwnd, LPARAM arg) HINSTANCE instance = (HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE); if (instance != MSWindowsScreen::getWindowInstance()) { PostMessage(hwnd, WM_CLOSE, 0, 0); - *reinterpret_cast(arg) = true; + *static_cast(arg) = true; } } return TRUE; diff --git a/src/lib/platform/OSXClipboardBMPConverter.cpp b/src/lib/platform/OSXClipboardBMPConverter.cpp index faeac291..574b917a 100644 --- a/src/lib/platform/OSXClipboardBMPConverter.cpp +++ b/src/lib/platform/OSXClipboardBMPConverter.cpp @@ -104,7 +104,7 @@ OSXClipboardBMPConverter::fromIClipboard(const String& bmp) const toLE(dst, static_cast(0)); toLE(dst, static_cast(0)); toLE(dst, static_cast(14 + 40)); - return String(reinterpret_cast(header), 14) + bmp; + return String(static_cast(header), 14) + bmp; } String @@ -116,7 +116,7 @@ OSXClipboardBMPConverter::toIClipboard(const String& bmp) const } // check BMP file header - const UInt8* rawBMPHeader = reinterpret_cast(bmp.data()); + const UInt8* rawBMPHeader = static_cast(bmp.data()); if (rawBMPHeader[0] != 'B' || rawBMPHeader[1] != 'M') { return String(); } diff --git a/src/lib/platform/OSXKeyState.cpp b/src/lib/platform/OSXKeyState.cpp index 2071621b..33d81fdf 100644 --- a/src/lib/platform/OSXKeyState.cpp +++ b/src/lib/platform/OSXKeyState.cpp @@ -415,7 +415,7 @@ OSXKeyState::pollPressedKeys(KeyButtonSet& pressedKeys) const { ::KeyMap km; GetKeys(km); - const UInt8* m = reinterpret_cast(km); + const UInt8* m = static_cast(km); for (UInt32 i = 0; i < 16; ++i) { for (UInt32 j = 0; j < 8; ++j) { if ((m[i] & (1u << j)) != 0) { diff --git a/src/lib/platform/OSXScreen.cpp b/src/lib/platform/OSXScreen.cpp index 7ca76138..e81f1621 100644 --- a/src/lib/platform/OSXScreen.cpp +++ b/src/lib/platform/OSXScreen.cpp @@ -986,7 +986,7 @@ OSXScreen::sendClipboardEvent(Event::Type type, ClipboardID id) const void OSXScreen::handleSystemEvent(const Event& event, void*) { - EventRef* carbonEvent = reinterpret_cast(event.getData()); + EventRef* carbonEvent = static_cast(event.getData()); assert(carbonEvent != NULL); UInt32 eventClass = GetEventClass(*carbonEvent); diff --git a/src/lib/platform/OSXUchrKeyResource.cpp b/src/lib/platform/OSXUchrKeyResource.cpp index 7c362d70..b3f785b8 100644 --- a/src/lib/platform/OSXUchrKeyResource.cpp +++ b/src/lib/platform/OSXUchrKeyResource.cpp @@ -31,7 +31,7 @@ OSXUchrKeyResource::OSXUchrKeyResource(const void* resource, m_sri(NULL), m_st(NULL) { - m_resource = reinterpret_cast(resource); + m_resource = static_cast(resource); if (m_resource == NULL) { return; } @@ -56,19 +56,19 @@ OSXUchrKeyResource::OSXUchrKeyResource(const void* resource, } // get tables for keyboard type - const UInt8* base = reinterpret_cast(m_resource); - m_m = reinterpret_cast(base + + const UInt8* base = static_cast(m_resource); + m_m = static_cast(base + th->keyModifiersToTableNumOffset); - m_cti = reinterpret_cast(base + + m_cti = static_cast(base + th->keyToCharTableIndexOffset); - m_sdi = reinterpret_cast(base + + m_sdi = static_cast(base + th->keySequenceDataIndexOffset); if (th->keyStateRecordsIndexOffset != 0) { - m_sri = reinterpret_cast(base + + m_sri = static_cast(base + th->keyStateRecordsIndexOffset); } if (th->keyStateTerminatorsOffset != 0) { - m_st = reinterpret_cast(base + + m_st = static_cast(base + th->keyStateTerminatorsOffset); } @@ -81,7 +81,7 @@ OSXUchrKeyResource::OSXUchrKeyResource(const void* resource, KeyID id = getKey(table, button); if (id == 0x20) { UCKeyOutput c = - reinterpret_cast(base + + static_cast(base + m_cti->keyToCharTableOffsets[table])[button]; if ((c & kUCKeyOutputTestForIndexMask) == kUCKeyOutputStateIndexMask) { @@ -134,8 +134,8 @@ OSXUchrKeyResource::getKey(UInt32 table, UInt32 button) const assert(table < getNumTables()); assert(button < getNumButtons()); - const UInt8* base = reinterpret_cast(m_resource); - const UCKeyOutput* cPtr = reinterpret_cast(base + + const UInt8* base = static_cast(m_resource); + const UCKeyOutput* cPtr = static_cast(base + m_cti->keyToCharTableOffsets[table]); const UCKeyOutput c = cPtr[button]; @@ -211,12 +211,12 @@ bool OSXUchrKeyResource::getKeyRecord( KeySequence& keys, UInt16 index, UInt16& state) const { - const UInt8* base = reinterpret_cast(m_resource); + const UInt8* base = static_cast(m_resource); const UCKeyStateRecord* sr = - reinterpret_cast(base + + static_cast(base + m_sri->keyStateRecordOffsets[index]); const UCKeyStateEntryTerminal* kset = - reinterpret_cast(sr->stateEntryData); + static_cast(sr->stateEntryData); UInt16 nextState = 0; bool found = false; diff --git a/src/lib/platform/XWindowsClipboard.cpp b/src/lib/platform/XWindowsClipboard.cpp index 6aa3a4cb..bba70bec 100644 --- a/src/lib/platform/XWindowsClipboard.cpp +++ b/src/lib/platform/XWindowsClipboard.cpp @@ -516,7 +516,7 @@ XWindowsClipboard::icccmFillCache() } XWindowsUtil::convertAtomProperty(data); - const Atom* targets = reinterpret_cast(data.data()); + const Atom* targets = static_cast(data.data()); const UInt32 numTargets = data.size() / sizeof(Atom); LOG((CLOG_DEBUG " available targets: %s", XWindowsUtil::atomsToString(m_display, targets, numTargets).c_str())); @@ -594,7 +594,7 @@ XWindowsClipboard::icccmGetTime() const String data; if (icccmGetSelection(m_atomTimestamp, &actualTarget, &data) && actualTarget == m_atomInteger) { - Time time = *reinterpret_cast(data.data()); + Time time = *static_cast(data.data()); LOG((CLOG_DEBUG1 "got ICCCM time %d", time)); return time; } @@ -672,7 +672,7 @@ XWindowsClipboard::motifOwnsClipboard() const // check the owner window against the current clipboard owner const MotifClipHeader* header = - reinterpret_cast(data.data()); + static_cast(data.data()); if (data.size() >= sizeof(MotifClipHeader) && header->m_id == kMotifClipHeader) { if (static_cast(header->m_selectionOwner) == owner) { @@ -701,7 +701,7 @@ XWindowsClipboard::motifFillCache() // check that the header is okay const MotifClipHeader* header = - reinterpret_cast(data.data()); + static_cast(data.data()); if (data.size() < sizeof(MotifClipHeader) || header->m_id != kMotifClipHeader || header->m_numItems < 1) { @@ -721,7 +721,7 @@ XWindowsClipboard::motifFillCache() // check that the item is okay const MotifClipItem* item = - reinterpret_cast(data.data()); + static_cast(data.data()); if (data.size() < sizeof(MotifClipItem) || item->m_id != kMotifClipItem || item->m_numFormats - item->m_numDeletedFormats < 1) { @@ -730,8 +730,8 @@ XWindowsClipboard::motifFillCache() // format list is after static item structure elements const SInt32 numFormats = item->m_numFormats - item->m_numDeletedFormats; - const SInt32* formats = reinterpret_cast(item->m_size + - reinterpret_cast(data.data())); + const SInt32* formats = static_cast(item->m_size + + static_cast(data.data())); // get the available formats typedef std::map MotifFormatMap; @@ -749,7 +749,7 @@ XWindowsClipboard::motifFillCache() // check that the format is okay const MotifClipFormat* motifFormat = - reinterpret_cast(data.data()); + static_cast(data.data()); if (data.size() < sizeof(MotifClipFormat) || motifFormat->m_id != kMotifClipFormat || motifFormat->m_length < 0 || @@ -783,7 +783,7 @@ XWindowsClipboard::motifFillCache() // get format const MotifClipFormat* motifFormat = - reinterpret_cast( + static_cast( index2->second.data()); const Atom target = motifFormat->m_type; @@ -855,7 +855,7 @@ XWindowsClipboard::insertMultipleReply(Window requestor, // data is a list of atom pairs: target, property XWindowsUtil::convertAtomProperty(data); - const Atom* targets = reinterpret_cast(data.data()); + const Atom* targets = static_cast(data.data()); const UInt32 numTargets = data.size() / sizeof(Atom); // add replies for each target diff --git a/src/lib/platform/XWindowsClipboardAnyBitmapConverter.cpp b/src/lib/platform/XWindowsClipboardAnyBitmapConverter.cpp index 07f89a3a..94b33593 100644 --- a/src/lib/platform/XWindowsClipboardAnyBitmapConverter.cpp +++ b/src/lib/platform/XWindowsClipboardAnyBitmapConverter.cpp @@ -127,7 +127,7 @@ XWindowsClipboardAnyBitmapConverter::fromIClipboard(const String& bmp) const { // fill BMP info header with native-endian data CBMPInfoHeader infoHeader; - const UInt8* rawBMPInfoHeader = reinterpret_cast(bmp.data()); + const UInt8* rawBMPInfoHeader = static_cast(bmp.data()); infoHeader.biSize = fromLEU32(rawBMPInfoHeader + 0); infoHeader.biWidth = fromLES32(rawBMPInfoHeader + 4); infoHeader.biHeight = fromLES32(rawBMPInfoHeader + 8); @@ -186,6 +186,6 @@ XWindowsClipboardAnyBitmapConverter::toIClipboard(const String& image) const toLE(dst, static_cast(0)); // construct image - return String(reinterpret_cast(infoHeader), + return String(static_cast(infoHeader), sizeof(infoHeader)) + rawBMP; } diff --git a/src/lib/platform/XWindowsClipboardBMPConverter.cpp b/src/lib/platform/XWindowsClipboardBMPConverter.cpp index e1f35ff1..e28e81de 100644 --- a/src/lib/platform/XWindowsClipboardBMPConverter.cpp +++ b/src/lib/platform/XWindowsClipboardBMPConverter.cpp @@ -113,7 +113,7 @@ XWindowsClipboardBMPConverter::fromIClipboard(const String& bmp) const toLE(dst, static_cast(0)); toLE(dst, static_cast(0)); toLE(dst, static_cast(14 + 40)); - return String(reinterpret_cast(header), 14) + bmp; + return String(static_cast(header), 14) + bmp; } String @@ -125,7 +125,7 @@ XWindowsClipboardBMPConverter::toIClipboard(const String& bmp) const } // check BMP file header - const UInt8* rawBMPHeader = reinterpret_cast(bmp.data()); + const UInt8* rawBMPHeader = static_cast(bmp.data()); if (rawBMPHeader[0] != 'B' || rawBMPHeader[1] != 'M') { return String(); } diff --git a/src/lib/platform/XWindowsKeyState.cpp b/src/lib/platform/XWindowsKeyState.cpp index 6f82d4df..f97ef531 100644 --- a/src/lib/platform/XWindowsKeyState.cpp +++ b/src/lib/platform/XWindowsKeyState.cpp @@ -785,7 +785,7 @@ void XWindowsKeyState::remapKeyModifiers(KeyID id, SInt32 group, synergy::KeyMap::KeyItem& item, void* vself) { - XWindowsKeyState* self = reinterpret_cast(vself); + XWindowsKeyState* self = static_cast(vself); item.m_required = self->mapModifiersFromX(XkbBuildCoreState(item.m_required, group)); item.m_sensitive = diff --git a/src/lib/platform/XWindowsScreen.cpp b/src/lib/platform/XWindowsScreen.cpp index b16e2e51..6c3e1357 100644 --- a/src/lib/platform/XWindowsScreen.cpp +++ b/src/lib/platform/XWindowsScreen.cpp @@ -1169,7 +1169,7 @@ XWindowsScreen::getKeyState() const Bool XWindowsScreen::findKeyEvent(Display*, XEvent* xevent, XPointer arg) { - KeyEventFilter* filter = reinterpret_cast(arg); + KeyEventFilter* filter = static_cast(arg); return (xevent->type == filter->m_event && xevent->xkey.window == filter->m_window && xevent->xkey.time == filter->m_time && @@ -1179,7 +1179,7 @@ XWindowsScreen::findKeyEvent(Display*, XEvent* xevent, XPointer arg) void XWindowsScreen::handleSystemEvent(const Event& event, void*) { - XEvent* xevent = reinterpret_cast(event.getData()); + XEvent* xevent = static_cast(event.getData()); assert(xevent != NULL); // update key state @@ -1408,7 +1408,7 @@ XWindowsScreen::handleSystemEvent(const Event& event, void*) default: #if HAVE_XKB_EXTENSION if (m_xkb && xevent->type == m_xkbEventBase) { - XkbEvent* xkbEvent = reinterpret_cast(xevent); + XkbEvent* xkbEvent = static_cast(xevent); switch (xkbEvent->any.xkb_type) { case XkbMapNotify: refreshKeyboard(xevent); @@ -1426,7 +1426,7 @@ XWindowsScreen::handleSystemEvent(const Event& event, void*) if (m_xrandr) { if (xevent->type == m_xrandrEventBase + RRScreenChangeNotify || xevent->type == m_xrandrEventBase + RRNotify - && reinterpret_cast(xevent)->subtype == RRNotify_CrtcChange) { + && static_cast(xevent)->subtype == RRNotify_CrtcChange) { LOG((CLOG_INFO "XRRScreenChangeNotifyEvent or RRNotify_CrtcChange received")); // we're required to call back into XLib so XLib can update its internal state diff --git a/src/lib/platform/XWindowsUtil.cpp b/src/lib/platform/XWindowsUtil.cpp index 6103cced..304bca13 100644 --- a/src/lib/platform/XWindowsUtil.cpp +++ b/src/lib/platform/XWindowsUtil.cpp @@ -1386,7 +1386,7 @@ XWindowsUtil::setWindowProperty(Display* display, Window window, Atom type, SInt32 format) { const UInt32 length = 4 * XMaxRequestSize(display); - const unsigned char* data = reinterpret_cast(vdata); + const unsigned char* data = static_cast(vdata); UInt32 datumSize = static_cast(format / 8); // format 32 on 64bit systems is 8 bytes not 4. if (format == 32) { @@ -1665,35 +1665,35 @@ XWindowsUtil::convertAtomProperty(String& data) // 64-bit numbers we have to ensure the last number is a full 64 bits. if (sizeof(Atom) != 4 && ((data.size() / 4) & 1) != 0) { UInt32 zero = 0; - data.append(reinterpret_cast(&zero), sizeof(zero)); + data.append(static_cast(&zero), sizeof(zero)); } } void XWindowsUtil::appendAtomData(String& data, Atom atom) { - data.append(reinterpret_cast(&atom), sizeof(Atom)); + data.append(static_cast(&atom), sizeof(Atom)); } void XWindowsUtil::replaceAtomData(String& data, UInt32 index, Atom atom) { data.replace(index * sizeof(Atom), sizeof(Atom), - reinterpret_cast(&atom), + static_cast(&atom), sizeof(Atom)); } void XWindowsUtil::appendTimeData(String& data, Time time) { - data.append(reinterpret_cast(&time), sizeof(Time)); + data.append(static_cast(&time), sizeof(Time)); } Bool XWindowsUtil::propertyNotifyPredicate(Display*, XEvent* xevent, XPointer arg) { PropertyNotifyPredicateInfo* filter = - reinterpret_cast(arg); + static_cast(arg); return (xevent->type == PropertyNotify && xevent->xproperty.window == filter->m_window && xevent->xproperty.atom == filter->m_property && @@ -1784,5 +1784,5 @@ void XWindowsUtil::ErrorLock::saveHandler(Display*, XErrorEvent* e, void* flag) { LOG((CLOG_DEBUG1 "flagging X error: %d", e->error_code)); - *reinterpret_cast(flag) = true; + *static_cast(flag) = true; } diff --git a/src/lib/server/ClientListener.cpp b/src/lib/server/ClientListener.cpp index a9777aae..619ba2a0 100644 --- a/src/lib/server/ClientListener.cpp +++ b/src/lib/server/ClientListener.cpp @@ -178,7 +178,7 @@ void ClientListener::handleUnknownClient(const Event&, void* vclient) { ClientProxyUnknown* unknownClient = - reinterpret_cast(vclient); + static_cast(vclient); // we should have the client in our new client list assert(m_newClients.count(unknownClient) == 1); @@ -222,7 +222,7 @@ ClientListener::handleUnknownClient(const Event&, void* vclient) void ClientListener::handleClientDisconnected(const Event&, void* vclient) { - ClientProxy* client = reinterpret_cast(vclient); + ClientProxy* client = static_cast(vclient); // find client in waiting clients queue for (WaitingClients::iterator i = m_waitingClients.begin(), diff --git a/src/lib/server/InputFilter.cpp b/src/lib/server/InputFilter.cpp index f03786a7..0ab2fcaa 100644 --- a/src/lib/server/InputFilter.cpp +++ b/src/lib/server/InputFilter.cpp @@ -121,7 +121,7 @@ InputFilter::KeystrokeCondition::match(const Event& event) // check if it's our hotkey IPrimaryScreen::HotKeyInfo* kinfo = - reinterpret_cast(event.getData()); + static_cast(event.getData()); if (kinfo->m_id != m_id) { return kNoMatch; } @@ -217,7 +217,7 @@ InputFilter::MouseButtonCondition::match(const Event& event) // check if it's the right button and modifiers. ignore modifiers // that cannot be combined with a mouse button. IPlatformScreen::ButtonInfo* minfo = - reinterpret_cast(event.getData()); + static_cast(event.getData()); if (minfo->m_button != m_button || (minfo->m_mask & ~s_ignoreMask) != m_mask) { return kNoMatch; @@ -256,7 +256,7 @@ InputFilter::ScreenConnectedCondition::match(const Event& event) { if (event.getType() == m_events->forServer().connected()) { Server::ScreenConnectedInfo* info = - reinterpret_cast(event.getData()); + static_cast(event.getData()); if (m_screen == info->m_screen || m_screen.empty()) { return kActivate; } @@ -357,7 +357,7 @@ InputFilter::SwitchToScreenAction::perform(const Event& event) String screen = m_screen; if (screen.empty() && event.getType() == m_events->forServer().connected()) { Server::ScreenConnectedInfo* info = - reinterpret_cast(event.getData()); + static_cast(event.getData()); screen = info->m_screen; } diff --git a/src/lib/server/Server.cpp b/src/lib/server/Server.cpp index b0ff56fc..d9394ed5 100644 --- a/src/lib/server/Server.cpp +++ b/src/lib/server/Server.cpp @@ -1187,7 +1187,7 @@ void Server::handleShapeChanged(const Event&, void* vclient) { // ignore events from unknown clients - BaseClientProxy* client = reinterpret_cast(vclient); + BaseClientProxy* client = static_cast(vclient); if (m_clientSet.count(client) == 0) { return; } @@ -1224,12 +1224,12 @@ Server::handleClipboardGrabbed(const Event& event, void* vclient) } // ignore events from unknown clients - BaseClientProxy* grabber = reinterpret_cast(vclient); + BaseClientProxy* grabber = static_cast(vclient); if (m_clientSet.count(grabber) == 0) { return; } const IScreen::ClipboardInfo* info = - reinterpret_cast(event.getData()); + static_cast(event.getData()); // ignore grab if sequence number is old. always allow primary // screen to grab. @@ -1270,12 +1270,12 @@ void Server::handleClipboardChanged(const Event& event, void* vclient) { // ignore events from unknown clients - BaseClientProxy* sender = reinterpret_cast(vclient); + BaseClientProxy* sender = static_cast(vclient); if (m_clientSet.count(sender) == 0) { return; } const IScreen::ClipboardInfo* info = - reinterpret_cast(event.getData()); + static_cast(event.getData()); onClipboardChanged(sender, info->m_id, info->m_sequenceNumber); } @@ -1283,7 +1283,7 @@ void Server::handleKeyDownEvent(const Event& event, void*) { IPlatformScreen::KeyInfo* info = - reinterpret_cast(event.getData()); + static_cast(event.getData()); onKeyDown(info->m_key, info->m_mask, info->m_button, info->m_screens); } @@ -1291,7 +1291,7 @@ void Server::handleKeyUpEvent(const Event& event, void*) { IPlatformScreen::KeyInfo* info = - reinterpret_cast(event.getData()); + static_cast(event.getData()); onKeyUp(info->m_key, info->m_mask, info->m_button, info->m_screens); } @@ -1299,7 +1299,7 @@ void Server::handleKeyRepeatEvent(const Event& event, void*) { IPlatformScreen::KeyInfo* info = - reinterpret_cast(event.getData()); + static_cast(event.getData()); onKeyRepeat(info->m_key, info->m_mask, info->m_count, info->m_button); } @@ -1307,7 +1307,7 @@ void Server::handleButtonDownEvent(const Event& event, void*) { IPlatformScreen::ButtonInfo* info = - reinterpret_cast(event.getData()); + static_cast(event.getData()); onMouseDown(info->m_button); } @@ -1315,7 +1315,7 @@ void Server::handleButtonUpEvent(const Event& event, void*) { IPlatformScreen::ButtonInfo* info = - reinterpret_cast(event.getData()); + static_cast(event.getData()); onMouseUp(info->m_button); } @@ -1323,7 +1323,7 @@ void Server::handleMotionPrimaryEvent(const Event& event, void*) { IPlatformScreen::MotionInfo* info = - reinterpret_cast(event.getData()); + static_cast(event.getData()); onMouseMovePrimary(info->m_x, info->m_y); } @@ -1331,7 +1331,7 @@ void Server::handleMotionSecondaryEvent(const Event& event, void*) { IPlatformScreen::MotionInfo* info = - reinterpret_cast(event.getData()); + static_cast(event.getData()); onMouseMoveSecondary(info->m_x, info->m_y); } @@ -1339,7 +1339,7 @@ void Server::handleWheelEvent(const Event& event, void*) { IPlatformScreen::WheelInfo* info = - reinterpret_cast(event.getData()); + static_cast(event.getData()); onMouseWheel(info->m_xDelta, info->m_yDelta); } @@ -1374,7 +1374,7 @@ Server::handleClientDisconnected(const Event&, void* vclient) { // client has disconnected. it might be an old client or an // active client. we don't care so just handle it both ways. - BaseClientProxy* client = reinterpret_cast(vclient); + BaseClientProxy* client = static_cast(vclient); removeActiveClient(client); removeOldClient(client); @@ -1388,7 +1388,7 @@ void Server::handleClientCloseTimeout(const Event&, void* vclient) { // client took too long to disconnect. just dump it. - BaseClientProxy* client = reinterpret_cast(vclient); + BaseClientProxy* client = static_cast(vclient); LOG((CLOG_NOTE "forced disconnection of client \"%s\"", getName(client).c_str())); removeOldClient(client); PacketStreamFilter* streamFileter = dynamic_cast(client->getStream()); @@ -1401,7 +1401,7 @@ void Server::handleSwitchToScreenEvent(const Event& event, void*) { SwitchToScreenInfo* info = - reinterpret_cast(event.getData()); + static_cast(event.getData()); ClientList::const_iterator index = m_clients.find(info->m_screen); if (index == m_clients.end()) { @@ -1416,7 +1416,7 @@ void Server::handleSwitchInDirectionEvent(const Event& event, void*) { SwitchInDirectionInfo* info = - reinterpret_cast(event.getData()); + static_cast(event.getData()); // jump to screen in chosen direction from center of this screen SInt32 x = m_x, y = m_y; @@ -1817,7 +1817,7 @@ Server::onMouseMovePrimary(SInt32 x, SInt32 y) void Server::sendDragInfoThread(void* arg) { - BaseClientProxy* newScreen = reinterpret_cast(arg); + BaseClientProxy* newScreen = static_cast(arg); m_dragFileList.clear(); String& dragFileList = m_screen->getDraggingFilename(); @@ -2053,7 +2053,7 @@ Server::onMouseWheel(SInt32 xDelta, SInt32 yDelta) void Server::onFileChunkSending(const void* data) { - FileChunk* chunk = reinterpret_cast(const_cast(data)); + FileChunk* chunk = static_cast(const_cast(data)); LOG((CLOG_DEBUG1 "sending file chunk")); assert(m_active != NULL); @@ -2372,14 +2372,14 @@ Server::sendFileToClient(const char* filename) m_sendFileThread = new Thread( new TMethodJob( this, &Server::sendFileThread, - reinterpret_cast(const_cast(filename)))); + static_cast(const_cast(filename)))); } void Server::sendFileThread(void* data) { try { - char* filename = reinterpret_cast(data); + char* filename = static_cast(data); LOG((CLOG_DEBUG "sending file to client, filename=%s", filename)); StreamChunker::sendFile(filename, m_events, this); } diff --git a/src/lib/synergy/ClientApp.cpp b/src/lib/synergy/ClientApp.cpp index 54f9f687..10aba5f3 100644 --- a/src/lib/synergy/ClientApp.cpp +++ b/src/lib/synergy/ClientApp.cpp @@ -268,7 +268,7 @@ void ClientApp::handleClientRestart(const Event&, void* vtimer) { // discard old timer - EventQueueTimer* timer = reinterpret_cast(vtimer); + EventQueueTimer* timer = static_cast(vtimer); m_events->deleteTimer(timer); m_events->removeHandler(Event::kTimer, timer); @@ -301,7 +301,7 @@ void ClientApp::handleClientFailed(const Event& e, void*) { Client::FailInfo* info = - reinterpret_cast(e.getData()); + static_cast(e.getData()); updateStatus(String("Failed to connect to server: ") + info->m_what); if (!args().m_restartable || !info->m_retry) { diff --git a/src/lib/synergy/ClipboardChunk.cpp b/src/lib/synergy/ClipboardChunk.cpp index f7a5673d..781098d9 100644 --- a/src/lib/synergy/ClipboardChunk.cpp +++ b/src/lib/synergy/ClipboardChunk.cpp @@ -41,7 +41,7 @@ ClipboardChunk::start( char* chunk = start->m_chunk; chunk[0] = id; - UInt32* seq = reinterpret_cast(&chunk[1]); + UInt32* seq = static_cast(&chunk[1]); *seq = sequence; chunk[5] = kDataStart; memcpy(&chunk[6], size.c_str(), sizeLength); @@ -61,7 +61,7 @@ ClipboardChunk::data( char* chunkData = chunk->m_chunk; chunkData[0] = id; - UInt32* seq = reinterpret_cast(&chunkData[1]); + UInt32* seq = static_cast(&chunkData[1]); *seq = sequence; chunkData[5] = kDataChunk; memcpy(&chunkData[6], data.c_str(), dataSize); @@ -77,7 +77,7 @@ ClipboardChunk::end(ClipboardID id, UInt32 sequence) char* chunk = end->m_chunk; chunk[0] = id; - UInt32* seq = reinterpret_cast(&chunk[1]); + UInt32* seq = static_cast(&chunk[1]); *seq = sequence; chunk[5] = kDataEnd; chunk[CLIPBOARD_CHUNK_META_SIZE - 1] = '\0'; @@ -127,13 +127,13 @@ ClipboardChunk::assemble(synergy::IStream* stream, void ClipboardChunk::send(synergy::IStream* stream, void* data) { - ClipboardChunk* clipboardData = reinterpret_cast(data); + ClipboardChunk* clipboardData = static_cast(data); LOG((CLOG_DEBUG1 "sending clipboard chunk")); char* chunk = clipboardData->m_chunk; ClipboardID id = chunk[0]; - UInt32* seq = reinterpret_cast(&chunk[1]); + UInt32* seq = static_cast(&chunk[1]); UInt32 sequence = *seq; UInt8 mark = chunk[5]; String dataChunk(&chunk[6], clipboardData->m_dataSize); diff --git a/src/lib/synergy/IClipboard.cpp b/src/lib/synergy/IClipboard.cpp index a8019184..42ca0c85 100644 --- a/src/lib/synergy/IClipboard.cpp +++ b/src/lib/synergy/IClipboard.cpp @@ -151,7 +151,7 @@ IClipboard::copy(IClipboard* dst, const IClipboard* src, Time time) UInt32 IClipboard::readUInt32(const char* buf) { - const unsigned char* ubuf = reinterpret_cast(buf); + const unsigned char* ubuf = static_cast(buf); return (static_cast(ubuf[0]) << 24) | (static_cast(ubuf[1]) << 16) | (static_cast(ubuf[2]) << 8) | diff --git a/src/lib/synergy/KeyState.cpp b/src/lib/synergy/KeyState.cpp index 3808b944..bdb8706c 100644 --- a/src/lib/synergy/KeyState.cpp +++ b/src/lib/synergy/KeyState.cpp @@ -524,7 +524,7 @@ KeyState::addActiveModifierCB(KeyID, SInt32 group, synergy::KeyMap::KeyItem& keyItem, void* vcontext) { AddActiveModifierContext* context = - reinterpret_cast(vcontext); + static_cast(vcontext); if (group == context->m_activeGroup && (keyItem.m_generates & context->m_mask) != 0) { context->m_activeModifiers.insert(std::make_pair( diff --git a/src/lib/synergy/ProtocolUtil.cpp b/src/lib/synergy/ProtocolUtil.cpp index ab361880..ae796fa9 100644 --- a/src/lib/synergy/ProtocolUtil.cpp +++ b/src/lib/synergy/ProtocolUtil.cpp @@ -120,27 +120,27 @@ ProtocolUtil::vreadf(synergy::IStream* stream, const char* fmt, va_list args) switch (len) { case 1: // 1 byte integer - *reinterpret_cast(v) = buffer[0]; - LOG((CLOG_DEBUG2 "readf: read %d byte integer: %d (0x%x)", len, *reinterpret_cast(v), *reinterpret_cast(v))); + *static_cast(v) = buffer[0]; + LOG((CLOG_DEBUG2 "readf: read %d byte integer: %d (0x%x)", len, *static_cast(v), *static_cast(v))); break; case 2: // 2 byte integer - *reinterpret_cast(v) = + *static_cast(v) = static_cast( (static_cast(buffer[0]) << 8) | static_cast(buffer[1])); - LOG((CLOG_DEBUG2 "readf: read %d byte integer: %d (0x%x)", len, *reinterpret_cast(v), *reinterpret_cast(v))); + LOG((CLOG_DEBUG2 "readf: read %d byte integer: %d (0x%x)", len, *static_cast(v), *static_cast(v))); break; case 4: // 4 byte integer - *reinterpret_cast(v) = + *static_cast(v) = (static_cast(buffer[0]) << 24) | (static_cast(buffer[1]) << 16) | (static_cast(buffer[2]) << 8) | static_cast(buffer[3]); - LOG((CLOG_DEBUG2 "readf: read %d byte integer: %d (0x%x)", len, *reinterpret_cast(v), *reinterpret_cast(v))); + LOG((CLOG_DEBUG2 "readf: read %d byte integer: %d (0x%x)", len, *static_cast(v), *static_cast(v))); break; } break; @@ -165,9 +165,9 @@ ProtocolUtil::vreadf(synergy::IStream* stream, const char* fmt, va_list args) // 1 byte integer for (UInt32 i = 0; i < n; ++i) { read(stream, buffer, 1); - reinterpret_cast*>(v)->push_back( + static_cast*>(v)->push_back( buffer[0]); - LOG((CLOG_DEBUG2 "readf: read %d byte integer[%d]: %d (0x%x)", len, i, reinterpret_cast*>(v)->back(), reinterpret_cast*>(v)->back())); + LOG((CLOG_DEBUG2 "readf: read %d byte integer[%d]: %d (0x%x)", len, i, static_cast*>(v)->back(), static_cast*>(v)->back())); } break; @@ -175,11 +175,11 @@ ProtocolUtil::vreadf(synergy::IStream* stream, const char* fmt, va_list args) // 2 byte integer for (UInt32 i = 0; i < n; ++i) { read(stream, buffer, 2); - reinterpret_cast*>(v)->push_back( + static_cast*>(v)->push_back( static_cast( (static_cast(buffer[0]) << 8) | static_cast(buffer[1]))); - LOG((CLOG_DEBUG2 "readf: read %d byte integer[%d]: %d (0x%x)", len, i, reinterpret_cast*>(v)->back(), reinterpret_cast*>(v)->back())); + LOG((CLOG_DEBUG2 "readf: read %d byte integer[%d]: %d (0x%x)", len, i, static_cast*>(v)->back(), static_cast*>(v)->back())); } break; @@ -187,12 +187,12 @@ ProtocolUtil::vreadf(synergy::IStream* stream, const char* fmt, va_list args) // 4 byte integer for (UInt32 i = 0; i < n; ++i) { read(stream, buffer, 4); - reinterpret_cast*>(v)->push_back( + static_cast*>(v)->push_back( (static_cast(buffer[0]) << 24) | (static_cast(buffer[1]) << 16) | (static_cast(buffer[2]) << 8) | static_cast(buffer[3])); - LOG((CLOG_DEBUG2 "readf: read %d byte integer[%d]: %d (0x%x)", len, i, reinterpret_cast*>(v)->back(), reinterpret_cast*>(v)->back())); + LOG((CLOG_DEBUG2 "readf: read %d byte integer[%d]: %d (0x%x)", len, i, static_cast*>(v)->back(), static_cast*>(v)->back())); } break; } @@ -340,7 +340,7 @@ ProtocolUtil::getLength(const char* fmt, va_list args) void ProtocolUtil::writef(void* buffer, const char* fmt, va_list args) { - UInt8* dst = reinterpret_cast(buffer); + UInt8* dst = static_cast(buffer); while (*fmt) { if (*fmt == '%') { @@ -515,7 +515,7 @@ ProtocolUtil::read(synergy::IStream* stream, void* vbuffer, UInt32 count) assert(stream != NULL); assert(vbuffer != NULL); - UInt8* buffer = reinterpret_cast(vbuffer); + UInt8* buffer = static_cast(vbuffer); while (count > 0) { // read more UInt32 n = stream->read(buffer, count); diff --git a/src/lib/synergy/ServerApp.cpp b/src/lib/synergy/ServerApp.cpp index 52e4331f..23884aec 100644 --- a/src/lib/synergy/ServerApp.cpp +++ b/src/lib/synergy/ServerApp.cpp @@ -259,7 +259,7 @@ ServerApp::forceReconnect(const Event&, void*) void ServerApp::handleClientConnected(const Event&, void* vlistener) { - ClientListener* listener = reinterpret_cast(vlistener); + ClientListener* listener = static_cast(vlistener); ClientProxy* client = listener->getNextClient(); if (client != NULL) { m_server->adoptClient(client); diff --git a/src/lib/synergy/StreamChunker.cpp b/src/lib/synergy/StreamChunker.cpp index f53c39bc..2ad64a03 100644 --- a/src/lib/synergy/StreamChunker.cpp +++ b/src/lib/synergy/StreamChunker.cpp @@ -49,7 +49,7 @@ StreamChunker::sendFile( { s_isChunkingFile = true; - std::fstream file(reinterpret_cast(filename), std::ios::in | std::ios::binary); + std::fstream file(static_cast(filename), std::ios::in | std::ios::binary); if (!file.is_open()) { throw runtime_error("failed to open file"); diff --git a/src/test/integtests/net/NetworkTests.cpp b/src/test/integtests/net/NetworkTests.cpp index dd7fb6b4..cc346f31 100644 --- a/src/test/integtests/net/NetworkTests.cpp +++ b/src/test/integtests/net/NetworkTests.cpp @@ -328,7 +328,7 @@ TEST_F(NetworkTests, sendToServer_mockFile) void NetworkTests::sendToClient_mockData_handleClientConnected(const Event&, void* vlistener) { - ClientListener* listener = reinterpret_cast(vlistener); + ClientListener* listener = static_cast(vlistener); Server* server = listener->getServer(); ClientProxy* client = listener->getNextClient(); @@ -336,7 +336,7 @@ NetworkTests::sendToClient_mockData_handleClientConnected(const Event&, void* vl throw runtime_error("client is null"); } - BaseClientProxy* bcp = reinterpret_cast(client); + BaseClientProxy* bcp = static_cast(client); server->adoptClient(bcp); server->setActive(bcp); @@ -346,7 +346,7 @@ NetworkTests::sendToClient_mockData_handleClientConnected(const Event&, void* vl void NetworkTests::sendToClient_mockData_fileRecieveCompleted(const Event& event, void*) { - Client* client = reinterpret_cast(event.getTarget()); + Client* client = static_cast(event.getTarget()); EXPECT_TRUE(client->isReceivedFileSizeValid()); m_events.raiseQuitEvent(); @@ -355,7 +355,7 @@ NetworkTests::sendToClient_mockData_fileRecieveCompleted(const Event& event, voi void NetworkTests::sendToClient_mockFile_handleClientConnected(const Event&, void* vlistener) { - ClientListener* listener = reinterpret_cast(vlistener); + ClientListener* listener = static_cast(vlistener); Server* server = listener->getServer(); ClientProxy* client = listener->getNextClient(); @@ -363,7 +363,7 @@ NetworkTests::sendToClient_mockFile_handleClientConnected(const Event&, void* vl throw runtime_error("client is null"); } - BaseClientProxy* bcp = reinterpret_cast(client); + BaseClientProxy* bcp = static_cast(client); server->adoptClient(bcp); server->setActive(bcp); @@ -373,7 +373,7 @@ NetworkTests::sendToClient_mockFile_handleClientConnected(const Event&, void* vl void NetworkTests::sendToClient_mockFile_fileRecieveCompleted(const Event& event, void*) { - Client* client = reinterpret_cast(event.getTarget()); + Client* client = static_cast(event.getTarget()); EXPECT_TRUE(client->isReceivedFileSizeValid()); m_events.raiseQuitEvent(); @@ -382,14 +382,14 @@ NetworkTests::sendToClient_mockFile_fileRecieveCompleted(const Event& event, voi void NetworkTests::sendToServer_mockData_handleClientConnected(const Event&, void* vclient) { - Client* client = reinterpret_cast(vclient); + Client* client = static_cast(vclient); sendMockData(client); } void NetworkTests::sendToServer_mockData_fileRecieveCompleted(const Event& event, void*) { - Server* server = reinterpret_cast(event.getTarget()); + Server* server = static_cast(event.getTarget()); EXPECT_TRUE(server->isReceivedFileSizeValid()); m_events.raiseQuitEvent(); @@ -398,14 +398,14 @@ NetworkTests::sendToServer_mockData_fileRecieveCompleted(const Event& event, voi void NetworkTests::sendToServer_mockFile_handleClientConnected(const Event&, void* vclient) { - Client* client = reinterpret_cast(vclient); + Client* client = static_cast(vclient); client->sendFileToServer(kMockFilename); } void NetworkTests::sendToServer_mockFile_fileRecieveCompleted(const Event& event, void*) { - Server* server = reinterpret_cast(event.getTarget()); + Server* server = static_cast(event.getTarget()); EXPECT_TRUE(server->isReceivedFileSizeValid()); m_events.raiseQuitEvent(); @@ -491,7 +491,7 @@ createFile(fstream& file, const char* filename, size_t size) throw runtime_error("file not open"); } - file.write(reinterpret_cast(buffer), size); + file.write(static_cast(buffer), size); file.close(); delete[] buffer; From 9ed9bde4e724795caf8c26be4507435cd4c76c7e Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Fri, 9 Sep 2016 13:08:59 +0100 Subject: [PATCH 062/101] Restore use of reinterpret_cast for sockaddr_in --- src/lib/arch/unix/ArchNetworkBSD.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/lib/arch/unix/ArchNetworkBSD.cpp b/src/lib/arch/unix/ArchNetworkBSD.cpp index f324a7f1..cf061bc9 100644 --- a/src/lib/arch/unix/ArchNetworkBSD.cpp +++ b/src/lib/arch/unix/ArchNetworkBSD.cpp @@ -646,7 +646,7 @@ ArchNetworkBSD::newAnyAddr(EAddressFamily family) switch (family) { case kINET: { struct sockaddr_in* ipAddr = - static_cast(&addr->m_addr); + reinterpret_cast(&addr->m_addr); ipAddr->sin_family = AF_INET; ipAddr->sin_port = 0; ipAddr->sin_addr.s_addr = INADDR_ANY; @@ -762,7 +762,7 @@ ArchNetworkBSD::addrToString(ArchNetAddress addr) switch (getAddrFamily(addr)) { case kINET: { struct sockaddr_in* ipAddr = - static_cast(&addr->m_addr); + reinterpret_cast(&addr->m_addr); ARCH->lockMutex(m_mutex); std::string s = inet_ntoa(ipAddr->sin_addr); ARCH->unlockMutex(m_mutex); @@ -797,7 +797,7 @@ ArchNetworkBSD::setAddrPort(ArchNetAddress addr, int port) switch (getAddrFamily(addr)) { case kINET: { struct sockaddr_in* ipAddr = - static_cast(&addr->m_addr); + reinterpret_cast(&addr->m_addr); ipAddr->sin_port = htons(port); break; } @@ -816,7 +816,7 @@ ArchNetworkBSD::getAddrPort(ArchNetAddress addr) switch (getAddrFamily(addr)) { case kINET: { struct sockaddr_in* ipAddr = - static_cast(&addr->m_addr); + reinterpret_cast(&addr->m_addr); return ntohs(ipAddr->sin_port); } @@ -834,7 +834,7 @@ ArchNetworkBSD::isAnyAddr(ArchNetAddress addr) switch (getAddrFamily(addr)) { case kINET: { struct sockaddr_in* ipAddr = - static_cast(&addr->m_addr); + reinterpret_cast(&addr->m_addr); return (ipAddr->sin_addr.s_addr == INADDR_ANY && addr->m_len == (socklen_t)sizeof(struct sockaddr_in)); } From f17461465566566698cd86e00f8c6596e16a1d51 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Fri, 9 Sep 2016 13:14:07 +0100 Subject: [PATCH 063/101] Remove bizarre cast of sockaddr to char* --- src/lib/arch/unix/ArchNetworkBSD.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/lib/arch/unix/ArchNetworkBSD.cpp b/src/lib/arch/unix/ArchNetworkBSD.cpp index cf061bc9..8913313e 100644 --- a/src/lib/arch/unix/ArchNetworkBSD.cpp +++ b/src/lib/arch/unix/ArchNetworkBSD.cpp @@ -737,8 +737,7 @@ ArchNetworkBSD::addrToName(ArchNetAddress addr) // mutexed name lookup (ugh) ARCH->lockMutex(m_mutex); - struct hostent* info = gethostbyaddr( - static_cast(&addr->m_addr), + struct hostent* info = gethostbyaddr(&addr->m_addr, addr->m_len, addr->m_addr.sa_family); if (info == NULL) { ARCH->unlockMutex(m_mutex); From 0371002497026383235f85a076f516b484f612c2 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Fri, 9 Sep 2016 13:22:15 +0100 Subject: [PATCH 064/101] Restore use of reinterpret_cast in unicode routines --- src/lib/base/Unicode.cpp | 50 ++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/src/lib/base/Unicode.cpp b/src/lib/base/Unicode.cpp index fd4ad694..ad7a266d 100644 --- a/src/lib/base/Unicode.cpp +++ b/src/lib/base/Unicode.cpp @@ -101,7 +101,7 @@ bool Unicode::isUTF8(const String& src) { // convert and test each character - const UInt8* data = static_cast(src.c_str()); + const UInt8* data = reinterpret_cast(src.c_str()); for (UInt32 n = (UInt32)src.size(); n > 0; ) { if (fromUTF8(data, n) == s_invalid) { return false; @@ -122,7 +122,7 @@ Unicode::UTF8ToUCS2(const String& src, bool* errors) dst.reserve(2 * n); // convert each character - const UInt8* data = static_cast(src.c_str()); + const UInt8* data = reinterpret_cast(src.c_str()); while (n > 0) { UInt32 c = fromUTF8(data, n); if (c == s_invalid) { @@ -133,7 +133,7 @@ Unicode::UTF8ToUCS2(const String& src, bool* errors) c = s_replacement; } UInt16 ucs2 = static_cast(c); - dst.append(static_cast(&ucs2), 2); + dst.append(reinterpret_cast(&ucs2), 2); } return dst; @@ -151,13 +151,13 @@ Unicode::UTF8ToUCS4(const String& src, bool* errors) dst.reserve(4 * n); // convert each character - const UInt8* data = static_cast(src.c_str()); + const UInt8* data = reinterpret_cast(src.c_str()); while (n > 0) { UInt32 c = fromUTF8(data, n); if (c == s_invalid) { c = s_replacement; } - dst.append(static_cast(&c), 4); + dst.append(reinterpret_cast(&c), 4); } return dst; @@ -175,7 +175,7 @@ Unicode::UTF8ToUTF16(const String& src, bool* errors) dst.reserve(2 * n); // convert each character - const UInt8* data = static_cast(src.c_str()); + const UInt8* data = reinterpret_cast(src.c_str()); while (n > 0) { UInt32 c = fromUTF8(data, n); if (c == s_invalid) { @@ -187,14 +187,14 @@ Unicode::UTF8ToUTF16(const String& src, bool* errors) } if (c < 0x00010000) { UInt16 ucs2 = static_cast(c); - dst.append(static_cast(&ucs2), 2); + dst.append(reinterpret_cast(&ucs2), 2); } else { c -= 0x00010000; UInt16 utf16h = static_cast((c >> 10) + 0xd800); UInt16 utf16l = static_cast((c & 0x03ff) + 0xdc00); - dst.append(static_cast(&utf16h), 2); - dst.append(static_cast(&utf16l), 2); + dst.append(reinterpret_cast(&utf16h), 2); + dst.append(reinterpret_cast(&utf16l), 2); } } @@ -213,7 +213,7 @@ Unicode::UTF8ToUTF32(const String& src, bool* errors) dst.reserve(4 * n); // convert each character - const UInt8* data = static_cast(src.c_str()); + const UInt8* data = reinterpret_cast(src.c_str()); while (n > 0) { UInt32 c = fromUTF8(data, n); if (c == s_invalid) { @@ -223,7 +223,7 @@ Unicode::UTF8ToUTF32(const String& src, bool* errors) setError(errors); c = s_replacement; } - dst.append(static_cast(&c), 4); + dst.append(reinterpret_cast(&c), 4); } return dst; @@ -260,7 +260,7 @@ Unicode::UCS2ToUTF8(const String& src, bool* errors) // convert UInt32 n = (UInt32)src.size() >> 1; - return doUCS2ToUTF8(static_cast(src.data()), n, errors); + return doUCS2ToUTF8(reinterpret_cast(src.data()), n, errors); } String @@ -271,7 +271,7 @@ Unicode::UCS4ToUTF8(const String& src, bool* errors) // convert UInt32 n = (UInt32)src.size() >> 2; - return doUCS4ToUTF8(static_cast(src.data()), n, errors); + return doUCS4ToUTF8(reinterpret_cast(src.data()), n, errors); } String @@ -282,7 +282,7 @@ Unicode::UTF16ToUTF8(const String& src, bool* errors) // convert UInt32 n = (UInt32)src.size() >> 1; - return doUTF16ToUTF8(static_cast(src.data()), n, errors); + return doUTF16ToUTF8(reinterpret_cast(src.data()), n, errors); } String @@ -293,7 +293,7 @@ Unicode::UTF32ToUTF8(const String& src, bool* errors) // convert UInt32 n = (UInt32)src.size() >> 2; - return doUTF32ToUTF8(static_cast(src.data()), n, errors); + return doUTF32ToUTF8(reinterpret_cast(src.data()), n, errors); } String @@ -361,16 +361,16 @@ Unicode::wideCharToUTF8(const wchar_t* src, UInt32 size, bool* errors) // the String's nul character). switch (ARCH->getWideCharEncoding()) { case IArchString::kUCS2: - return doUCS2ToUTF8(static_cast(src), size, errors); + return doUCS2ToUTF8(reinterpret_cast(src), size, errors); case IArchString::kUCS4: - return doUCS4ToUTF8(static_cast(src), size, errors); + return doUCS4ToUTF8(reinterpret_cast(src), size, errors); case IArchString::kUTF16: - return doUTF16ToUTF8(static_cast(src), size, errors); + return doUTF16ToUTF8(reinterpret_cast(src), size, errors); case IArchString::kUTF32: - return doUTF32ToUTF8(static_cast(src), size, errors); + return doUTF32ToUTF8(reinterpret_cast(src), size, errors); default: assert(0 && "unknown wide character encoding"); @@ -741,25 +741,25 @@ Unicode::toUTF8(String& dst, UInt32 c, bool* errors) // convert to UTF-8 if (c < 0x00000080) { data[0] = static_cast(c); - dst.append(static_cast(data), 1); + dst.append(reinterpret_cast(data), 1); } else if (c < 0x00000800) { data[0] = static_cast(((c >> 6) & 0x0000001f) + 0xc0); data[1] = static_cast((c & 0x0000003f) + 0x80); - dst.append(static_cast(data), 2); + dst.append(reinterpret_cast(data), 2); } else if (c < 0x00010000) { data[0] = static_cast(((c >> 12) & 0x0000000f) + 0xe0); data[1] = static_cast(((c >> 6) & 0x0000003f) + 0x80); data[2] = static_cast((c & 0x0000003f) + 0x80); - dst.append(static_cast(data), 3); + dst.append(reinterpret_cast(data), 3); } else if (c < 0x00200000) { data[0] = static_cast(((c >> 18) & 0x00000007) + 0xf0); data[1] = static_cast(((c >> 12) & 0x0000003f) + 0x80); data[2] = static_cast(((c >> 6) & 0x0000003f) + 0x80); data[3] = static_cast((c & 0x0000003f) + 0x80); - dst.append(static_cast(data), 4); + dst.append(reinterpret_cast(data), 4); } else if (c < 0x04000000) { data[0] = static_cast(((c >> 24) & 0x00000003) + 0xf8); @@ -767,7 +767,7 @@ Unicode::toUTF8(String& dst, UInt32 c, bool* errors) data[2] = static_cast(((c >> 12) & 0x0000003f) + 0x80); data[3] = static_cast(((c >> 6) & 0x0000003f) + 0x80); data[4] = static_cast((c & 0x0000003f) + 0x80); - dst.append(static_cast(data), 5); + dst.append(reinterpret_cast(data), 5); } else if (c < 0x80000000) { data[0] = static_cast(((c >> 30) & 0x00000001) + 0xfc); @@ -776,7 +776,7 @@ Unicode::toUTF8(String& dst, UInt32 c, bool* errors) data[3] = static_cast(((c >> 12) & 0x0000003f) + 0x80); data[4] = static_cast(((c >> 6) & 0x0000003f) + 0x80); data[5] = static_cast((c & 0x0000003f) + 0x80); - dst.append(static_cast(data), 6); + dst.append(reinterpret_cast(data), 6); } else { assert(0 && "character out of range"); From 90c3dd6622e25ebe33cfcb3593d2607a50a50b1a Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Fri, 9 Sep 2016 13:38:08 +0100 Subject: [PATCH 065/101] Restore evil-enabling reinterpret_cast in SocketMultiplexer --- src/lib/net/SocketMultiplexer.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lib/net/SocketMultiplexer.cpp b/src/lib/net/SocketMultiplexer.cpp index b7f9236f..bab76b20 100644 --- a/src/lib/net/SocketMultiplexer.cpp +++ b/src/lib/net/SocketMultiplexer.cpp @@ -46,7 +46,8 @@ SocketMultiplexer::SocketMultiplexer() : // this pointer just has to be unique and not NULL. it will // never be dereferenced. it's used to identify cursor nodes // in the jobs list. - m_cursorMark = static_cast(this); + // TODO: Remove this evilness + m_cursorMark = reinterpret_cast(this); // start thread m_thread = new Thread(new TMethodJob( From e81f7ab8c734301e4d3282d5414c0c05aedfb073 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Fri, 9 Sep 2016 13:47:41 +0100 Subject: [PATCH 066/101] Replace unsafe casts with memcpy ops --- src/lib/synergy/ClipboardChunk.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/lib/synergy/ClipboardChunk.cpp b/src/lib/synergy/ClipboardChunk.cpp index 781098d9..25c0e2d8 100644 --- a/src/lib/synergy/ClipboardChunk.cpp +++ b/src/lib/synergy/ClipboardChunk.cpp @@ -21,6 +21,7 @@ #include "synergy/protocol_types.h" #include "io/IStream.h" #include "base/Log.h" +#include size_t ClipboardChunk::s_expectedSize = 0; @@ -41,8 +42,7 @@ ClipboardChunk::start( char* chunk = start->m_chunk; chunk[0] = id; - UInt32* seq = static_cast(&chunk[1]); - *seq = sequence; + std::memcpy (&chunk[1], &sequence, 4); chunk[5] = kDataStart; memcpy(&chunk[6], size.c_str(), sizeLength); chunk[sizeLength + CLIPBOARD_CHUNK_META_SIZE - 1] = '\0'; @@ -61,8 +61,7 @@ ClipboardChunk::data( char* chunkData = chunk->m_chunk; chunkData[0] = id; - UInt32* seq = static_cast(&chunkData[1]); - *seq = sequence; + std::memcpy (&chunkData[1], &sequence, 4); chunkData[5] = kDataChunk; memcpy(&chunkData[6], data.c_str(), dataSize); chunkData[dataSize + CLIPBOARD_CHUNK_META_SIZE - 1] = '\0'; @@ -77,8 +76,7 @@ ClipboardChunk::end(ClipboardID id, UInt32 sequence) char* chunk = end->m_chunk; chunk[0] = id; - UInt32* seq = static_cast(&chunk[1]); - *seq = sequence; + std::memcpy (&chunk[1], &sequence, 4); chunk[5] = kDataEnd; chunk[CLIPBOARD_CHUNK_META_SIZE - 1] = '\0'; @@ -133,8 +131,8 @@ ClipboardChunk::send(synergy::IStream* stream, void* data) char* chunk = clipboardData->m_chunk; ClipboardID id = chunk[0]; - UInt32* seq = static_cast(&chunk[1]); - UInt32 sequence = *seq; + UInt32 sequence; + std::memcpy (&sequence, &chunk[1], 4); UInt8 mark = chunk[5]; String dataChunk(&chunk[6], clipboardData->m_dataSize); From fb5e2bb1715ff181cf5864dceedde29b5ddc8131 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Fri, 9 Sep 2016 15:27:30 +0100 Subject: [PATCH 067/101] Restore safe reinterpret_cast in readUInt32 --- src/lib/synergy/IClipboard.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/synergy/IClipboard.cpp b/src/lib/synergy/IClipboard.cpp index 42ca0c85..a8019184 100644 --- a/src/lib/synergy/IClipboard.cpp +++ b/src/lib/synergy/IClipboard.cpp @@ -151,7 +151,7 @@ IClipboard::copy(IClipboard* dst, const IClipboard* src, Time time) UInt32 IClipboard::readUInt32(const char* buf) { - const unsigned char* ubuf = static_cast(buf); + const unsigned char* ubuf = reinterpret_cast(buf); return (static_cast(ubuf[0]) << 24) | (static_cast(ubuf[1]) << 16) | (static_cast(ubuf[2]) << 8) | From 055370412c0da21b05a4230884e45a10b19105d0 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Fri, 9 Sep 2016 15:35:21 +0100 Subject: [PATCH 068/101] Restore safe reinterpret_cast in clipboard converter --- src/lib/platform/XWindowsClipboardAnyBitmapConverter.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/platform/XWindowsClipboardAnyBitmapConverter.cpp b/src/lib/platform/XWindowsClipboardAnyBitmapConverter.cpp index 94b33593..07f89a3a 100644 --- a/src/lib/platform/XWindowsClipboardAnyBitmapConverter.cpp +++ b/src/lib/platform/XWindowsClipboardAnyBitmapConverter.cpp @@ -127,7 +127,7 @@ XWindowsClipboardAnyBitmapConverter::fromIClipboard(const String& bmp) const { // fill BMP info header with native-endian data CBMPInfoHeader infoHeader; - const UInt8* rawBMPInfoHeader = static_cast(bmp.data()); + const UInt8* rawBMPInfoHeader = reinterpret_cast(bmp.data()); infoHeader.biSize = fromLEU32(rawBMPInfoHeader + 0); infoHeader.biWidth = fromLES32(rawBMPInfoHeader + 4); infoHeader.biHeight = fromLES32(rawBMPInfoHeader + 8); @@ -186,6 +186,6 @@ XWindowsClipboardAnyBitmapConverter::toIClipboard(const String& image) const toLE(dst, static_cast(0)); // construct image - return String(static_cast(infoHeader), + return String(reinterpret_cast(infoHeader), sizeof(infoHeader)) + rawBMP; } From 50807bfcb67417e9e85ae57e23e72e6f24cebb7a Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Fri, 9 Sep 2016 15:48:07 +0100 Subject: [PATCH 069/101] Restore safe reinterpret_casts in XWindowsScreen --- src/lib/platform/XWindowsScreen.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/platform/XWindowsScreen.cpp b/src/lib/platform/XWindowsScreen.cpp index 6c3e1357..ce20109c 100644 --- a/src/lib/platform/XWindowsScreen.cpp +++ b/src/lib/platform/XWindowsScreen.cpp @@ -1169,7 +1169,7 @@ XWindowsScreen::getKeyState() const Bool XWindowsScreen::findKeyEvent(Display*, XEvent* xevent, XPointer arg) { - KeyEventFilter* filter = static_cast(arg); + KeyEventFilter* filter = reinterpret_cast(arg); return (xevent->type == filter->m_event && xevent->xkey.window == filter->m_window && xevent->xkey.time == filter->m_time && @@ -1408,7 +1408,7 @@ XWindowsScreen::handleSystemEvent(const Event& event, void*) default: #if HAVE_XKB_EXTENSION if (m_xkb && xevent->type == m_xkbEventBase) { - XkbEvent* xkbEvent = static_cast(xevent); + XkbEvent* xkbEvent = reinterpret_cast(xevent); switch (xkbEvent->any.xkb_type) { case XkbMapNotify: refreshKeyboard(xevent); From 5272c9dde4e1b5b178e56a469a8f4e38c7d3bd5f Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Fri, 9 Sep 2016 15:51:42 +0100 Subject: [PATCH 070/101] Restore safe reinterpret_casts in XWindowsUtil --- src/lib/platform/XWindowsUtil.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/lib/platform/XWindowsUtil.cpp b/src/lib/platform/XWindowsUtil.cpp index 304bca13..10b35096 100644 --- a/src/lib/platform/XWindowsUtil.cpp +++ b/src/lib/platform/XWindowsUtil.cpp @@ -1665,35 +1665,35 @@ XWindowsUtil::convertAtomProperty(String& data) // 64-bit numbers we have to ensure the last number is a full 64 bits. if (sizeof(Atom) != 4 && ((data.size() / 4) & 1) != 0) { UInt32 zero = 0; - data.append(static_cast(&zero), sizeof(zero)); + data.append(reinterpret_cast(&zero), sizeof(zero)); } } void XWindowsUtil::appendAtomData(String& data, Atom atom) { - data.append(static_cast(&atom), sizeof(Atom)); + data.append(reinterpret_cast(&atom), sizeof(Atom)); } void XWindowsUtil::replaceAtomData(String& data, UInt32 index, Atom atom) { data.replace(index * sizeof(Atom), sizeof(Atom), - static_cast(&atom), + reinterpret_cast(&atom), sizeof(Atom)); } void XWindowsUtil::appendTimeData(String& data, Time time) { - data.append(static_cast(&time), sizeof(Time)); + data.append(reinterpret_cast(&time), sizeof(Time)); } Bool XWindowsUtil::propertyNotifyPredicate(Display*, XEvent* xevent, XPointer arg) { PropertyNotifyPredicateInfo* filter = - static_cast(arg); + reinterpret_cast(arg); return (xevent->type == PropertyNotify && xevent->xproperty.window == filter->m_window && xevent->xproperty.atom == filter->m_property && From 5b8fb69124f281c778a5cbdfa5d11f4f90c6b8b1 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Fri, 9 Sep 2016 16:18:05 +0100 Subject: [PATCH 071/101] Partially de-reinterpret_cast XWindowsClipboard --- src/lib/platform/XWindowsClipboard.cpp | 75 +++++++++++++------------- 1 file changed, 39 insertions(+), 36 deletions(-) diff --git a/src/lib/platform/XWindowsClipboard.cpp b/src/lib/platform/XWindowsClipboard.cpp index bba70bec..f30cc2c9 100644 --- a/src/lib/platform/XWindowsClipboard.cpp +++ b/src/lib/platform/XWindowsClipboard.cpp @@ -31,6 +31,7 @@ #include "common/stdvector.h" #include +#include #include // @@ -516,7 +517,7 @@ XWindowsClipboard::icccmFillCache() } XWindowsUtil::convertAtomProperty(data); - const Atom* targets = static_cast(data.data()); + const Atom* targets = reinterpret_cast(data.data()); // TODO: Safe? const UInt32 numTargets = data.size() / sizeof(Atom); LOG((CLOG_DEBUG " available targets: %s", XWindowsUtil::atomsToString(m_display, targets, numTargets).c_str())); @@ -594,7 +595,7 @@ XWindowsClipboard::icccmGetTime() const String data; if (icccmGetSelection(m_atomTimestamp, &actualTarget, &data) && actualTarget == m_atomInteger) { - Time time = *static_cast(data.data()); + Time time = *reinterpret_cast(data.data()); LOG((CLOG_DEBUG1 "got ICCCM time %d", time)); return time; } @@ -671,11 +672,11 @@ XWindowsClipboard::motifOwnsClipboard() const } // check the owner window against the current clipboard owner - const MotifClipHeader* header = - static_cast(data.data()); - if (data.size() >= sizeof(MotifClipHeader) && - header->m_id == kMotifClipHeader) { - if (static_cast(header->m_selectionOwner) == owner) { + if (data.size() >= sizeof(MotifClipHeader)) { + MotifClipHeader header; + std::memcpy (&header, data.data(), sizeof(header)); + if ((header.m_id == kMotifClipHeader) && + (static_cast(header.m_selectionOwner) == owner)) { return true; } } @@ -699,18 +700,18 @@ XWindowsClipboard::motifFillCache() return; } - // check that the header is okay - const MotifClipHeader* header = - static_cast(data.data()); - if (data.size() < sizeof(MotifClipHeader) || - header->m_id != kMotifClipHeader || - header->m_numItems < 1) { + MotifClipHeader header; + if (data.size() < sizeof(header)) { // check that the header is okay + return; + } + std::memcpy (&header, data.data(), sizeof(header)); + if (header.m_id != kMotifClipHeader || header.m_numItems < 1) { return; } // get the Motif item property from the root window char name[18 + 20]; - sprintf(name, "_MOTIF_CLIP_ITEM_%d", header->m_item); + sprintf(name, "_MOTIF_CLIP_ITEM_%d", header.m_item); Atom atomItem = XInternAtom(m_display, name, False); data = ""; if (!XWindowsUtil::getWindowProperty(m_display, root, @@ -719,18 +720,19 @@ XWindowsClipboard::motifFillCache() return; } - // check that the item is okay - const MotifClipItem* item = - static_cast(data.data()); - if (data.size() < sizeof(MotifClipItem) || - item->m_id != kMotifClipItem || - item->m_numFormats - item->m_numDeletedFormats < 1) { + MotifClipItem item; + if (data.size() < sizeof(item)) { // check that the item is okay + return; + } + std::memcpy (&item, data.data(), sizeof(item)); + if (item.m_id != kMotifClipItem || + item.m_numFormats - item.m_numDeletedFormats < 1) { return; } // format list is after static item structure elements - const SInt32 numFormats = item->m_numFormats - item->m_numDeletedFormats; - const SInt32* formats = static_cast(item->m_size + + const SInt32 numFormats = item.m_numFormats - item.m_numDeletedFormats; + const SInt32* formats = reinterpret_cast(item.m_size + static_cast(data.data())); // get the available formats @@ -748,18 +750,20 @@ XWindowsClipboard::motifFillCache() } // check that the format is okay - const MotifClipFormat* motifFormat = - static_cast(data.data()); - if (data.size() < sizeof(MotifClipFormat) || - motifFormat->m_id != kMotifClipFormat || - motifFormat->m_length < 0 || - motifFormat->m_type == None || - motifFormat->m_deleted != 0) { + MotifClipFormat motifFormat; + if (data.size() < sizeof(motifFormat)) { + continue; + } + std::memcpy (&motifFormat, data.data(), sizeof(motifFormat)); + if (motifFormat.m_id != kMotifClipFormat || + motifFormat.m_length < 0 || + motifFormat.m_type == None || + motifFormat.m_deleted != 0) { continue; } // save it - motifFormats.insert(std::make_pair(motifFormat->m_type, data)); + motifFormats.insert(std::make_pair(motifFormat.m_type, data)); } //const UInt32 numMotifFormats = motifFormats.size(); @@ -782,15 +786,14 @@ XWindowsClipboard::motifFillCache() } // get format - const MotifClipFormat* motifFormat = - static_cast( - index2->second.data()); - const Atom target = motifFormat->m_type; + MotifClipFormat motifFormat; + std::memcpy (&motifFormat, index2->second.data(), sizeof(motifFormat)); + const Atom target = motifFormat.m_type; // get the data (finally) Atom actualTarget; String targetData; - if (!motifGetSelection(motifFormat, &actualTarget, &targetData)) { + if (!motifGetSelection(&motifFormat, &actualTarget, &targetData)) { LOG((CLOG_DEBUG1 " no data for target %s", XWindowsUtil::atomToString(m_display, target).c_str())); continue; } @@ -855,7 +858,7 @@ XWindowsClipboard::insertMultipleReply(Window requestor, // data is a list of atom pairs: target, property XWindowsUtil::convertAtomProperty(data); - const Atom* targets = static_cast(data.data()); + const Atom* targets = reinterpret_cast(data.data()); const UInt32 numTargets = data.size() / sizeof(Atom); // add replies for each target From 16977788d3406cbbef7823f07a81b2cc15d18f96 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Fri, 9 Sep 2016 16:32:30 +0100 Subject: [PATCH 072/101] Restore safe reinterpret_casts in XWindowsClipboardBMPConverter --- src/lib/platform/XWindowsClipboardBMPConverter.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/platform/XWindowsClipboardBMPConverter.cpp b/src/lib/platform/XWindowsClipboardBMPConverter.cpp index e28e81de..e1f35ff1 100644 --- a/src/lib/platform/XWindowsClipboardBMPConverter.cpp +++ b/src/lib/platform/XWindowsClipboardBMPConverter.cpp @@ -113,7 +113,7 @@ XWindowsClipboardBMPConverter::fromIClipboard(const String& bmp) const toLE(dst, static_cast(0)); toLE(dst, static_cast(0)); toLE(dst, static_cast(14 + 40)); - return String(static_cast(header), 14) + bmp; + return String(reinterpret_cast(header), 14) + bmp; } String @@ -125,7 +125,7 @@ XWindowsClipboardBMPConverter::toIClipboard(const String& bmp) const } // check BMP file header - const UInt8* rawBMPHeader = static_cast(bmp.data()); + const UInt8* rawBMPHeader = reinterpret_cast(bmp.data()); if (rawBMPHeader[0] != 'B' || rawBMPHeader[1] != 'M') { return String(); } From a13dc92f2e42b40ba3b23baded1da3426000f6f5 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Fri, 9 Sep 2016 16:36:26 +0100 Subject: [PATCH 073/101] Restore safe reinterpret_casts in SecureSocket --- src/lib/net/SecureSocket.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/net/SecureSocket.cpp b/src/lib/net/SecureSocket.cpp index cd0068a5..7076c764 100644 --- a/src/lib/net/SecureSocket.cpp +++ b/src/lib/net/SecureSocket.cpp @@ -683,7 +683,7 @@ SecureSocket::verifyCertFingerprint() } // format fingerprint into hexdecimal format with colon separator - String fingerprint(static_cast(tempFingerprint), tempFingerprintLen); + String fingerprint(reinterpret_cast(tempFingerprint), tempFingerprintLen); formatFingerprint(fingerprint); LOG((CLOG_NOTE "server fingerprint: %s", fingerprint.c_str())); From 0568271506797f1d2b8b129a32c7001844c47608 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Fri, 9 Sep 2016 16:46:48 +0100 Subject: [PATCH 074/101] Partially remove reinterpret_casts in network tests --- src/test/integtests/net/NetworkTests.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/test/integtests/net/NetworkTests.cpp b/src/test/integtests/net/NetworkTests.cpp index cc346f31..79ef7c99 100644 --- a/src/test/integtests/net/NetworkTests.cpp +++ b/src/test/integtests/net/NetworkTests.cpp @@ -27,6 +27,7 @@ #include "test/global/TestEventQueue.h" #include "server/Server.h" #include "server/ClientListener.h" +#include "server/ClientProxy.h" #include "client/Client.h" #include "synergy/FileChunk.h" #include "synergy/StreamChunker.h" @@ -336,7 +337,7 @@ NetworkTests::sendToClient_mockData_handleClientConnected(const Event&, void* vl throw runtime_error("client is null"); } - BaseClientProxy* bcp = static_cast(client); + BaseClientProxy* bcp = client; server->adoptClient(bcp); server->setActive(bcp); @@ -363,7 +364,7 @@ NetworkTests::sendToClient_mockFile_handleClientConnected(const Event&, void* vl throw runtime_error("client is null"); } - BaseClientProxy* bcp = static_cast(client); + BaseClientProxy* bcp = client; server->adoptClient(bcp); server->setActive(bcp); @@ -491,7 +492,7 @@ createFile(fstream& file, const char* filename, size_t size) throw runtime_error("file not open"); } - file.write(static_cast(buffer), size); + file.write(reinterpret_cast(buffer), size); file.close(); delete[] buffer; From f1cd215f28b01f263189c831a0fbce9ee2578fb2 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Fri, 9 Sep 2016 16:54:06 +0100 Subject: [PATCH 075/101] Restore safe reinterpret_cast in Synergy GUI --- src/gui/src/SynergyLocale.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/src/SynergyLocale.cpp b/src/gui/src/SynergyLocale.cpp index 13c8d215..fa980ed4 100644 --- a/src/gui/src/SynergyLocale.cpp +++ b/src/gui/src/SynergyLocale.cpp @@ -29,7 +29,7 @@ SynergyLocale::SynergyLocale() void SynergyLocale::loadLanguages() { QResource resource(":/res/lang/Languages.xml"); - QByteArray bytes(static_cast(resource.data()), resource.size()); + QByteArray bytes(reinterpret_cast(resource.data()), resource.size()); QXmlStreamReader xml(bytes); while (!xml.atEnd()) From 5a03e37d154560951b86bae76d1753bc8c4820ea Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Mon, 12 Sep 2016 13:32:50 +0100 Subject: [PATCH 076/101] Restore safe reinterpret_casts in misc Windows code --- src/lib/arch/win32/ArchMiscWindows.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/lib/arch/win32/ArchMiscWindows.cpp b/src/lib/arch/win32/ArchMiscWindows.cpp index 53b71286..d70861d2 100644 --- a/src/lib/arch/win32/ArchMiscWindows.cpp +++ b/src/lib/arch/win32/ArchMiscWindows.cpp @@ -234,7 +234,7 @@ ArchMiscWindows::setValue(HKEY key, return; } RegSetValueEx(key, name, 0, REG_SZ, - static_cast(value.c_str()), + reinterpret_cast(value.c_str()), (DWORD)value.size() + 1); } @@ -247,7 +247,7 @@ ArchMiscWindows::setValue(HKEY key, const TCHAR* name, DWORD value) return; } RegSetValueEx(key, name, 0, REG_DWORD, - static_cast(&value), + reinterpret_cast(&value), sizeof(DWORD)); } @@ -262,7 +262,7 @@ ArchMiscWindows::setValueBinary(HKEY key, return; } RegSetValueEx(key, name, 0, REG_BINARY, - static_cast(value.data()), + reinterpret_cast(value.data()), (DWORD)value.size()); } @@ -287,7 +287,7 @@ ArchMiscWindows::readBinaryOrString(HKEY key, const TCHAR* name, DWORD type) // read it result = RegQueryValueEx(key, name, 0, &actualType, - static_cast(buffer), &size); + reinterpret_cast(buffer), &size); if (result != ERROR_SUCCESS || actualType != type) { delete[] buffer; return std::string(); @@ -322,7 +322,7 @@ ArchMiscWindows::readValueInt(HKEY key, const TCHAR* name) DWORD value; DWORD size = sizeof(value); LONG result = RegQueryValueEx(key, name, 0, &type, - static_cast(&value), &size); + reinterpret_cast(&value), &size); if (result != ERROR_SUCCESS || type != REG_DWORD) { return 0; } @@ -374,7 +374,7 @@ ArchMiscWindows::setThreadExecutionState(DWORD busyModes) if (s_stes == NULL) { HINSTANCE kernel = LoadLibrary("kernel32.dll"); if (kernel != NULL) { - s_stes = static_cast(GetProcAddress(kernel, + s_stes = reinterpret_cast(GetProcAddress(kernel, "SetThreadExecutionState")); } if (s_stes == NULL) { @@ -414,7 +414,7 @@ ArchMiscWindows::wakeupDisplay() if (s_stes == NULL) { HINSTANCE kernel = LoadLibrary("kernel32.dll"); if (kernel != NULL) { - s_stes = static_cast(GetProcAddress(kernel, + s_stes = reinterpret_cast(GetProcAddress(kernel, "SetThreadExecutionState")); } if (s_stes == NULL) { From d77b5f1176fb101fb15811521046cc752256f07f Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Mon, 12 Sep 2016 16:03:24 +0100 Subject: [PATCH 077/101] Restore safe reinterpret_casts in Windows TaskBar --- src/lib/arch/win32/ArchNetworkWinsock.cpp | 12 ++++++------ src/lib/arch/win32/ArchTaskBarWindows.cpp | 18 +++++++++--------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/lib/arch/win32/ArchNetworkWinsock.cpp b/src/lib/arch/win32/ArchNetworkWinsock.cpp index 265924d5..c6f0a179 100644 --- a/src/lib/arch/win32/ArchNetworkWinsock.cpp +++ b/src/lib/arch/win32/ArchNetworkWinsock.cpp @@ -754,7 +754,7 @@ ArchNetworkWinsock::addrToName(ArchNetAddress addr) // name lookup struct hostent* info = gethostbyaddr_winsock( - static_cast(&addr->m_addr), + reinterpret_cast(&addr->m_addr), addr->m_len, addr->m_addr.sa_family); if (info == NULL) { throwNameError(getsockerror_winsock()); @@ -772,7 +772,7 @@ ArchNetworkWinsock::addrToString(ArchNetAddress addr) switch (getAddrFamily(addr)) { case kINET: { struct sockaddr_in* ipAddr = - static_cast(&addr->m_addr); + reinterpret_cast(&addr->m_addr); return inet_ntoa_winsock(ipAddr->sin_addr); } @@ -804,8 +804,8 @@ ArchNetworkWinsock::setAddrPort(ArchNetAddress addr, int port) switch (getAddrFamily(addr)) { case kINET: { struct sockaddr_in* ipAddr = - static_cast(&addr->m_addr); - ipAddr->sin_port = htons_winsock(static_cast(port)); + reinterpret_cast(&addr->m_addr); + ipAddr->sin_port = htons_winsock(reinterpret_cast(port)); break; } @@ -823,7 +823,7 @@ ArchNetworkWinsock::getAddrPort(ArchNetAddress addr) switch (getAddrFamily(addr)) { case kINET: { struct sockaddr_in* ipAddr = - static_cast(&addr->m_addr); + reinterpret_cast(&addr->m_addr); return ntohs_winsock(ipAddr->sin_port); } @@ -841,7 +841,7 @@ ArchNetworkWinsock::isAnyAddr(ArchNetAddress addr) switch (getAddrFamily(addr)) { case kINET: { struct sockaddr_in* ipAddr = - static_cast(&addr->m_addr); + reinterpret_cast(&addr->m_addr); return (addr->m_len == sizeof(struct sockaddr_in) && ipAddr->sin_addr.s_addr == INADDR_ANY); } diff --git a/src/lib/arch/win32/ArchTaskBarWindows.cpp b/src/lib/arch/win32/ArchTaskBarWindows.cpp index eac283a8..7de57de2 100644 --- a/src/lib/arch/win32/ArchTaskBarWindows.cpp +++ b/src/lib/arch/win32/ArchTaskBarWindows.cpp @@ -414,17 +414,16 @@ ArchTaskBarWindows::staticWndProc(HWND hwnd, UINT msg, ArchTaskBarWindows* self = NULL; if (msg == WM_NCCREATE) { CREATESTRUCT* createInfo; - createInfo = static_cast(lParam); + createInfo = reinterpret_cast(lParam); self = static_cast( createInfo->lpCreateParams); - SetWindowLong(hwnd, 0, static_cast(self)); + SetWindowLongPtr(hwnd, 0, self); } else { // get the extra window data and forward the call - LONG data = GetWindowLong(hwnd, 0); + LONG_PTR data = GetWindowLongPtr(hwnd, 0); if (data != 0) { - self = static_cast( - static_cast(data)); + self = static_cast(reinterpret_cast(data)); } } @@ -444,6 +443,7 @@ ArchTaskBarWindows::threadMainLoop() m_taskBarRestart = RegisterWindowMessage(TEXT("TaskbarCreated")); // register a window class + LPCTSTR className = TEXT("SynergyTaskBar"); WNDCLASSEX classInfo; classInfo.cbSize = sizeof(classInfo); classInfo.style = CS_NOCLOSE; @@ -455,13 +455,13 @@ ArchTaskBarWindows::threadMainLoop() classInfo.hCursor = NULL; classInfo.hbrBackground = NULL; classInfo.lpszMenuName = NULL; - classInfo.lpszClassName = TEXT("SynergyTaskBar"); + classInfo.lpszClassName = className; classInfo.hIconSm = NULL; ATOM windowClass = RegisterClassEx(&classInfo); // create window m_hwnd = CreateWindowEx(WS_EX_TOOLWINDOW, - static_cast(windowClass), + className, TEXT("Synergy Task Bar"), WS_POPUP, 0, 0, 1, 1, @@ -478,7 +478,7 @@ ArchTaskBarWindows::threadMainLoop() // handle failure if (m_hwnd == NULL) { - UnregisterClass(static_cast(windowClass), instanceWin32()); + UnregisterClass(className, instanceWin32()); return; } @@ -494,7 +494,7 @@ ArchTaskBarWindows::threadMainLoop() // clean up removeAllIcons(); DestroyWindow(m_hwnd); - UnregisterClass(static_cast(windowClass), instanceWin32()); + UnregisterClass(className, instanceWin32()); } void* From 7e386c0bf9f007f74b3c72c7196ee04696223be4 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Mon, 12 Sep 2016 16:10:24 +0100 Subject: [PATCH 078/101] Fix cast of port number in Winsock --- src/lib/arch/win32/ArchNetworkWinsock.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/arch/win32/ArchNetworkWinsock.cpp b/src/lib/arch/win32/ArchNetworkWinsock.cpp index c6f0a179..b1470aa2 100644 --- a/src/lib/arch/win32/ArchNetworkWinsock.cpp +++ b/src/lib/arch/win32/ArchNetworkWinsock.cpp @@ -805,7 +805,7 @@ ArchNetworkWinsock::setAddrPort(ArchNetAddress addr, int port) case kINET: { struct sockaddr_in* ipAddr = reinterpret_cast(&addr->m_addr); - ipAddr->sin_port = htons_winsock(reinterpret_cast(port)); + ipAddr->sin_port = htons_winsock(port); break; } From 702f095efda04a8dd1cb1d4c3fbaa81aa200b025 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Mon, 12 Sep 2016 16:13:35 +0100 Subject: [PATCH 079/101] Fix cast in Windows TaskBar --- src/lib/arch/win32/ArchTaskBarWindows.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/arch/win32/ArchTaskBarWindows.cpp b/src/lib/arch/win32/ArchTaskBarWindows.cpp index 7de57de2..f87a595b 100644 --- a/src/lib/arch/win32/ArchTaskBarWindows.cpp +++ b/src/lib/arch/win32/ArchTaskBarWindows.cpp @@ -417,7 +417,7 @@ ArchTaskBarWindows::staticWndProc(HWND hwnd, UINT msg, createInfo = reinterpret_cast(lParam); self = static_cast( createInfo->lpCreateParams); - SetWindowLongPtr(hwnd, 0, self); + SetWindowLongPtr(hwnd, 0, reinterpret_cast(createInfo->lpCreateParams)); } else { // get the extra window data and forward the call From 2e30dc2c68b2a99a562ca0ec93e1a39bfbcadef2 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Mon, 12 Sep 2016 16:21:33 +0100 Subject: [PATCH 080/101] Restore safe reinterpret_cast of Windows thread handle --- src/lib/arch/win32/ArchMultithreadWindows.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/arch/win32/ArchMultithreadWindows.cpp b/src/lib/arch/win32/ArchMultithreadWindows.cpp index 70aafa2d..3c131780 100644 --- a/src/lib/arch/win32/ArchMultithreadWindows.cpp +++ b/src/lib/arch/win32/ArchMultithreadWindows.cpp @@ -303,7 +303,7 @@ ArchMultithreadWindows::newThread(ThreadFunc func, void* data) // create thread unsigned int id = 0; - thread->m_thread = static_cast(_beginthreadex(NULL, 0, + thread->m_thread = reinterpret_cast(_beginthreadex(NULL, 0, threadFunc, (void*)thread, 0, &id)); thread->m_id = static_cast(id); From f7ad16263468ba9df584831774914ba4902484c2 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Tue, 13 Sep 2016 10:32:13 +0100 Subject: [PATCH 081/101] Fix up casts in MSWindowsClipboardBitmapConverter --- src/lib/platform/MSWindowsClipboardBitmapConverter.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/platform/MSWindowsClipboardBitmapConverter.cpp b/src/lib/platform/MSWindowsClipboardBitmapConverter.cpp index 9b39ca7e..d1676bb0 100644 --- a/src/lib/platform/MSWindowsClipboardBitmapConverter.cpp +++ b/src/lib/platform/MSWindowsClipboardBitmapConverter.cpp @@ -71,7 +71,7 @@ String MSWindowsClipboardBitmapConverter::toIClipboard(HANDLE data) const { // get datator - const char* src = (const char*)GlobalLock(data); + LPVOID src = GlobalLock(data); if (src == NULL) { return String(); } @@ -85,7 +85,7 @@ MSWindowsClipboardBitmapConverter::toIClipboard(HANDLE data) const bitmap->bmiHeader.biBitCount == 32) && bitmap->bmiHeader.biCompression == BI_RGB) { // already in canonical form - String image(src, srcSize); + String image(static_cast(src), srcSize); GlobalUnlock(data); return image; } From 2a5dc62747b69abdaec93005ecf34733d55275be Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Tue, 13 Sep 2016 10:35:53 +0100 Subject: [PATCH 082/101] Restore safe reinterpret_casts in MSWindowsDesks --- src/lib/platform/MSWindowsDesks.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib/platform/MSWindowsDesks.cpp b/src/lib/platform/MSWindowsDesks.cpp index 555d2e79..a5cf4e62 100644 --- a/src/lib/platform/MSWindowsDesks.cpp +++ b/src/lib/platform/MSWindowsDesks.cpp @@ -241,7 +241,7 @@ void MSWindowsDesks::getCursorPos(SInt32& x, SInt32& y) const { POINT pos; - sendMessage(SYNERGY_MSG_CURSOR_POS, static_cast(&pos), 0); + sendMessage(SYNERGY_MSG_CURSOR_POS, reinterpret_cast(&pos), 0); x = pos.x; y = pos.y; } @@ -427,7 +427,7 @@ void MSWindowsDesks::destroyClass(ATOM windowClass) const { if (windowClass != 0) { - UnregisterClass(static_cast(windowClass), + UnregisterClass(reinterpret_cast(windowClass), MSWindowsScreen::getWindowInstance()); } } @@ -437,7 +437,7 @@ MSWindowsDesks::createWindow(ATOM windowClass, const char* name) const { HWND window = CreateWindowEx(WS_EX_TRANSPARENT | WS_EX_TOOLWINDOW, - static_cast(windowClass), + reinterpret_cast(windowClass), name, WS_POPUP, 0, 0, 1, 1, @@ -757,7 +757,7 @@ MSWindowsDesks::deskThread(void* vdesk) break; case SYNERGY_MSG_CURSOR_POS: { - POINT* pos = static_cast(msg.wParam); + POINT* pos = reinterpret_cast(msg.wParam); if (!GetCursorPos(pos)) { pos->x = m_xCenter; pos->y = m_yCenter; From 788f6eab9f9c71adbec0b1b08fa831781a2a6231 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Tue, 13 Sep 2016 10:37:01 +0100 Subject: [PATCH 083/101] Restore safe reinterpret_casts in MSWindowsScreen --- src/lib/platform/MSWindowsScreen.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib/platform/MSWindowsScreen.cpp b/src/lib/platform/MSWindowsScreen.cpp index 68c628cc..1011cb0c 100644 --- a/src/lib/platform/MSWindowsScreen.cpp +++ b/src/lib/platform/MSWindowsScreen.cpp @@ -864,7 +864,7 @@ void MSWindowsScreen::destroyClass(ATOM windowClass) const { if (windowClass != 0) { - UnregisterClass(static_cast(windowClass), s_windowInstance); + UnregisterClass(reinterpret_cast(windowClass), s_windowInstance); } } @@ -874,7 +874,7 @@ MSWindowsScreen::createWindow(ATOM windowClass, const char* name) const HWND window = CreateWindowEx(WS_EX_TOPMOST | WS_EX_TRANSPARENT | WS_EX_TOOLWINDOW, - static_cast(windowClass), + reinterpret_cast(windowClass), name, WS_POPUP, 0, 0, 1, 1, @@ -895,7 +895,7 @@ MSWindowsScreen::createDropWindow(ATOM windowClass, const char* name) const WS_EX_TOPMOST | WS_EX_TRANSPARENT | WS_EX_ACCEPTFILES, - static_cast(m_class), + reinterpret_cast(m_class), name, WS_POPUP, 0, 0, m_dropWindowSize, m_dropWindowSize, From 19b9be45930e62def36926d2a0fe1bee3ee1d3f7 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Tue, 13 Sep 2016 10:39:06 +0100 Subject: [PATCH 084/101] Restore safe reinterpret_casts in MSWindowsScreenSaver --- src/lib/platform/MSWindowsScreenSaver.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/platform/MSWindowsScreenSaver.cpp b/src/lib/platform/MSWindowsScreenSaver.cpp index 4289bb01..f2ab7334 100644 --- a/src/lib/platform/MSWindowsScreenSaver.cpp +++ b/src/lib/platform/MSWindowsScreenSaver.cpp @@ -162,7 +162,7 @@ MSWindowsScreenSaver::deactivate() if (desktop != NULL) { EnumDesktopWindows(desktop, &MSWindowsScreenSaver::killScreenSaverFunc, - static_cast(&killed)); + reinterpret_cast(&killed)); CloseDesktop(desktop); } @@ -205,7 +205,7 @@ MSWindowsScreenSaver::killScreenSaverFunc(HWND hwnd, LPARAM arg) HINSTANCE instance = (HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE); if (instance != MSWindowsScreen::getWindowInstance()) { PostMessage(hwnd, WM_CLOSE, 0, 0); - *static_cast(arg) = true; + *reinterpret_cast(arg) = true; } } return TRUE; From 23cf284a66617bfe551e02355fa9382ddde734f5 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Tue, 13 Sep 2016 10:53:27 +0100 Subject: [PATCH 085/101] Restore safe reinterpret_casts in MSWindowsClientTaskBarReceiver --- src/cmd/synergyc/MSWindowsClientTaskBarReceiver.cpp | 4 ++-- src/cmd/synergyp/MSWindowsPortableTaskBarReceiver.cpp | 8 ++++---- src/cmd/synergys/MSWindowsServerTaskBarReceiver.cpp | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/cmd/synergyc/MSWindowsClientTaskBarReceiver.cpp b/src/cmd/synergyc/MSWindowsClientTaskBarReceiver.cpp index 529a54dc..fc3ed94e 100644 --- a/src/cmd/synergyc/MSWindowsClientTaskBarReceiver.cpp +++ b/src/cmd/synergyc/MSWindowsClientTaskBarReceiver.cpp @@ -287,7 +287,7 @@ MSWindowsClientTaskBarReceiver::createWindow() MAKEINTRESOURCE(IDD_TASKBAR_STATUS), NULL, (DLGPROC)&MSWindowsClientTaskBarReceiver::staticDlgProc, - static_cast( + reinterpret_cast( static_cast(this))); // window should appear on top of everything, including (especially) @@ -338,7 +338,7 @@ MSWindowsClientTaskBarReceiver::staticDlgProc(HWND hwnd, MSWindowsClientTaskBarReceiver* self = NULL; if (msg == WM_INITDIALOG) { self = static_cast( - static_cast(lParam)); + reinterpret_cast(lParam)); SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) lParam); } else { diff --git a/src/cmd/synergyp/MSWindowsPortableTaskBarReceiver.cpp b/src/cmd/synergyp/MSWindowsPortableTaskBarReceiver.cpp index b42f28b3..ae7b0ee4 100644 --- a/src/cmd/synergyp/MSWindowsPortableTaskBarReceiver.cpp +++ b/src/cmd/synergyp/MSWindowsPortableTaskBarReceiver.cpp @@ -304,7 +304,7 @@ MSWindowsPortableTaskBarReceiver::createWindow() MAKEINTRESOURCE(IDD_TASKBAR_STATUS), NULL, (DLGPROC)&MSWindowsPortableTaskBarReceiver::staticDlgProc, - static_cast( + reinterpret_cast( static_cast(this))); // window should appear on top of everything, including (especially) @@ -355,15 +355,15 @@ MSWindowsPortableTaskBarReceiver::staticDlgProc(HWND hwnd, MSWindowsPortableTaskBarReceiver* self = NULL; if (msg == WM_INITDIALOG) { self = static_cast( - static_cast(lParam)); + reinterpret_cast(lParam)); SetWindowLongPtr(hwnd, GWLP_USERDATA, lParam); } else { // get the extra window data and forward the call - LONG data = (LONG)GetWindowLongPtr(hwnd, GWLP_USERDATA); + LONG_PTR data = GetWindowLongPtr(hwnd, GWLP_USERDATA); if (data != 0) { self = static_cast( - static_cast(data)); + reinterpret_cast(data)); } } diff --git a/src/cmd/synergys/MSWindowsServerTaskBarReceiver.cpp b/src/cmd/synergys/MSWindowsServerTaskBarReceiver.cpp index 83fc539c..b2d304a1 100644 --- a/src/cmd/synergys/MSWindowsServerTaskBarReceiver.cpp +++ b/src/cmd/synergys/MSWindowsServerTaskBarReceiver.cpp @@ -318,7 +318,7 @@ MSWindowsServerTaskBarReceiver::createWindow() MAKEINTRESOURCE(IDD_TASKBAR_STATUS), NULL, (DLGPROC)&MSWindowsServerTaskBarReceiver::staticDlgProc, - static_cast( + reinterpret_cast( static_cast(this))); // window should appear on top of everything, including (especially) @@ -369,15 +369,15 @@ MSWindowsServerTaskBarReceiver::staticDlgProc(HWND hwnd, MSWindowsServerTaskBarReceiver* self = NULL; if (msg == WM_INITDIALOG) { self = static_cast( - static_cast(lParam)); + reinterpret_cast(lParam)); SetWindowLongPtr(hwnd, GWLP_USERDATA, lParam); } else { // get the extra window data and forward the call - LONG data = (LONG)GetWindowLongPtr(hwnd, GWLP_USERDATA); + LONG_PTR data = GetWindowLongPtr(hwnd, GWLP_USERDATA); if (data != 0) { self = static_cast( - static_cast(data)); + reinterpret_cast(data)); } } From 8072594008e040b9a49668e8024dcf359bfaa43a Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Tue, 13 Sep 2016 11:14:40 +0100 Subject: [PATCH 086/101] Restore safe reinterpret_casts in OSXClipboardBMPConverter --- src/lib/platform/OSXClipboardBMPConverter.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/platform/OSXClipboardBMPConverter.cpp b/src/lib/platform/OSXClipboardBMPConverter.cpp index 574b917a..faeac291 100644 --- a/src/lib/platform/OSXClipboardBMPConverter.cpp +++ b/src/lib/platform/OSXClipboardBMPConverter.cpp @@ -104,7 +104,7 @@ OSXClipboardBMPConverter::fromIClipboard(const String& bmp) const toLE(dst, static_cast(0)); toLE(dst, static_cast(0)); toLE(dst, static_cast(14 + 40)); - return String(static_cast(header), 14) + bmp; + return String(reinterpret_cast(header), 14) + bmp; } String @@ -116,7 +116,7 @@ OSXClipboardBMPConverter::toIClipboard(const String& bmp) const } // check BMP file header - const UInt8* rawBMPHeader = static_cast(bmp.data()); + const UInt8* rawBMPHeader = reinterpret_cast(bmp.data()); if (rawBMPHeader[0] != 'B' || rawBMPHeader[1] != 'M') { return String(); } From 602fd3f64932685be62471e2688a49757bf7b70a Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Tue, 13 Sep 2016 11:18:59 +0100 Subject: [PATCH 087/101] Restore safe reinterpret_casts in OSXKeyState --- src/lib/platform/OSXKeyState.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/platform/OSXKeyState.cpp b/src/lib/platform/OSXKeyState.cpp index 33d81fdf..2071621b 100644 --- a/src/lib/platform/OSXKeyState.cpp +++ b/src/lib/platform/OSXKeyState.cpp @@ -415,7 +415,7 @@ OSXKeyState::pollPressedKeys(KeyButtonSet& pressedKeys) const { ::KeyMap km; GetKeys(km); - const UInt8* m = static_cast(km); + const UInt8* m = reinterpret_cast(km); for (UInt32 i = 0; i < 16; ++i) { for (UInt32 j = 0; j < 8; ++j) { if ((m[i] & (1u << j)) != 0) { From 26c11ec3c9cfee31749b64cf1a3346cc49a1c649 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Tue, 13 Sep 2016 11:26:34 +0100 Subject: [PATCH 088/101] Restore horrible reinterpret_casts in OSXUchrKeyResource --- src/lib/platform/OSXUchrKeyResource.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/lib/platform/OSXUchrKeyResource.cpp b/src/lib/platform/OSXUchrKeyResource.cpp index b3f785b8..603ba04a 100644 --- a/src/lib/platform/OSXUchrKeyResource.cpp +++ b/src/lib/platform/OSXUchrKeyResource.cpp @@ -56,19 +56,19 @@ OSXUchrKeyResource::OSXUchrKeyResource(const void* resource, } // get tables for keyboard type - const UInt8* base = static_cast(m_resource); - m_m = static_cast(base + + const UInt8* const base = reinterpret_cast(m_resource); + m_m = reinterpret_cast(base + th->keyModifiersToTableNumOffset); - m_cti = static_cast(base + + m_cti = reinterpret_cast(base + th->keyToCharTableIndexOffset); - m_sdi = static_cast(base + + m_sdi = reinterpret_cast(base + th->keySequenceDataIndexOffset); if (th->keyStateRecordsIndexOffset != 0) { - m_sri = static_cast(base + + m_sri = reinterpret_cast(base + th->keyStateRecordsIndexOffset); } if (th->keyStateTerminatorsOffset != 0) { - m_st = static_cast(base + + m_st = reinterpret_cast(base + th->keyStateTerminatorsOffset); } @@ -81,7 +81,7 @@ OSXUchrKeyResource::OSXUchrKeyResource(const void* resource, KeyID id = getKey(table, button); if (id == 0x20) { UCKeyOutput c = - static_cast(base + + reinterpret_cast(base + m_cti->keyToCharTableOffsets[table])[button]; if ((c & kUCKeyOutputTestForIndexMask) == kUCKeyOutputStateIndexMask) { @@ -134,8 +134,8 @@ OSXUchrKeyResource::getKey(UInt32 table, UInt32 button) const assert(table < getNumTables()); assert(button < getNumButtons()); - const UInt8* base = static_cast(m_resource); - const UCKeyOutput* cPtr = static_cast(base + + const UInt8* const base = reinterpret_cast(m_resource); + const UCKeyOutput* cPtr = reinterpret_cast(base + m_cti->keyToCharTableOffsets[table]); const UCKeyOutput c = cPtr[button]; @@ -211,12 +211,12 @@ bool OSXUchrKeyResource::getKeyRecord( KeySequence& keys, UInt16 index, UInt16& state) const { - const UInt8* base = static_cast(m_resource); + const UInt8* const base = reinterpret_cast(m_resource); const UCKeyStateRecord* sr = - static_cast(base + + reinterpret_cast(base + m_sri->keyStateRecordOffsets[index]); const UCKeyStateEntryTerminal* kset = - static_cast(sr->stateEntryData); + reinterpret_cast(sr->stateEntryData); UInt16 nextState = 0; bool found = false; From 5b7392d302a8524a6b9228b46b6f1f2597980118 Mon Sep 17 00:00:00 2001 From: Benedikt Morbach Date: Tue, 28 Oct 2014 16:24:57 +0100 Subject: [PATCH 089/101] #4420 Fix check for XRRNotifyEvent use CheckTypeSize instead of CheckSymbolExists From http://www.cmake.org/cmake/help/v3.0/module/CheckSymbolExists.html : If the symbol is a type or enum value it will not be recognized (consider using CheckTypeSize or CheckCSourceCompiles). --- CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a86fee80..b3e066a8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -205,7 +205,10 @@ if (UNIX) set(CMAKE_INCLUDE_PATH "${CMAKE_INCLUDE_PATH}:/usr/local/include") set(XKBlib "X11/Xlib.h;X11/XKBlib.h") - check_symbol_exists("XRRNotifyEvent" "${XKBlib};X11/extensions/Xrandr.h" HAVE_X11_EXTENSIONS_XRANDR_H) + set(CMAKE_EXTRA_INCLUDE_FILES "${XKBlib};X11/extensions/Xrandr.h") + check_type_size("XRRNotifyEvent" X11_EXTENSIONS_XRANDR_H) + set(HAVE_X11_EXTENSIONS_XRANDR_H "${X11_EXTENSIONS_XRANDR_H}") + set(CMAKE_EXTRA_INCLUDE_FILES) check_include_files("${XKBlib};X11/extensions/dpms.h" HAVE_X11_EXTENSIONS_DPMS_H) check_include_files("X11/extensions/Xinerama.h" HAVE_X11_EXTENSIONS_XINERAMA_H) From dd88e324d721536a1d03a2897e4b3c84675aa632 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Fri, 23 Sep 2016 15:30:22 +0100 Subject: [PATCH 090/101] #4420 Send screen shape change event on Linux (xrandr) --- src/lib/platform/XWindowsScreen.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib/platform/XWindowsScreen.cpp b/src/lib/platform/XWindowsScreen.cpp index b16e2e51..b7b248c9 100644 --- a/src/lib/platform/XWindowsScreen.cpp +++ b/src/lib/platform/XWindowsScreen.cpp @@ -1442,6 +1442,8 @@ XWindowsScreen::handleSystemEvent(const Event& event, void*) XMoveWindow(m_display, m_window, m_x, m_y); XResizeWindow(m_display, m_window, m_w, m_h); } + + sendEvent(m_events->forIScreen().shapeChanged()); } } #endif From 6892664f4a575a57f5e437aef74187b9b3bd8278 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Wed, 5 Oct 2016 15:10:40 +0100 Subject: [PATCH 091/101] Fix cast of XRRNotifyEvent --- src/lib/platform/XWindowsScreen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/platform/XWindowsScreen.cpp b/src/lib/platform/XWindowsScreen.cpp index 6e0ac4f8..c7032470 100644 --- a/src/lib/platform/XWindowsScreen.cpp +++ b/src/lib/platform/XWindowsScreen.cpp @@ -1426,7 +1426,7 @@ XWindowsScreen::handleSystemEvent(const Event& event, void*) if (m_xrandr) { if (xevent->type == m_xrandrEventBase + RRScreenChangeNotify || xevent->type == m_xrandrEventBase + RRNotify - && static_cast(xevent)->subtype == RRNotify_CrtcChange) { + && reinterpret_cast(xevent)->subtype == RRNotify_CrtcChange) { LOG((CLOG_INFO "XRRScreenChangeNotifyEvent or RRNotify_CrtcChange received")); // we're required to call back into XLib so XLib can update its internal state From 833c73f1bdb4ade0b89b9ca93da61db26654a548 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Wed, 5 Oct 2016 20:53:23 +0100 Subject: [PATCH 092/101] #5640 Update icon to the new hotness --- res/synergy.ico | Bin 287934 -> 24277 bytes src/gui/res/icons/256x256/synergy.ico | Bin 287934 -> 24277 bytes src/gui/res/image/about.png | Bin 4941 -> 5701 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/res/synergy.ico b/res/synergy.ico index fc2e41468ec60a88e0da4194f288a18572f3f36f..9e3d57100883a631db42ac5c9ef323228f84b43f 100644 GIT binary patch literal 24277 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 z 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 literal 287934 zcmeFa2XK^Uwk_)W>b!b&ea=1Ou`wA$HqJK20b`pS3?|u_Xbc8S2Ahl!2!SL}4k+iG zQ>(kxYDpcWR?a!+074=_| zJo5iOBL4l4M1=P`(bCjp-cVO(^@E_is!o!M>Uvbw zHln7k-dad~eZ5s=D2s53L5Nlrm*Xc&CFyx`#Egp(Jnu>)YDec2rhZyP5LxkfK&0Br*ano*p=V=^`wS9>ej2hj3uu zKJ4Cm*QPhouGb&fi?s*$V*6QheCBWw=l#9m5)lfI=m_{k-Ic(YC`6|wBSoV^qAD3t zaghj%4nk~PD57Hn5gG1-zyN2syIsKfbNqjf?!jjVckut(hP`_}reF97yXaT;AJ~Hv zCyz?;f}6WD0s?)JkQk55tPJ{sV${{wT8o%K_5-pXxREdS;I?VecsK*8RlnBW9MfFu>R0q%-y>kuQE4ZV0RX~v8U2jBF ze+^o$)}WU^d#$?&*IU!kUmuODb$;lsbwpR~C3H7jL~oNFuGG7szs?8OYeI3WJ_6Ue zqHv=x4uhRZ=xSSc) z8&O-!+@QC2(XZuN%72IKmwv7e+_`mgSbuA?d0Dmrd0ASdCC0(q#RW$W9mJN+oABX= zb@+(3bIR2LZW&7WRpi6Hp%jkoRj}!AN+Jtf%LS&B{FrFg%q9Pf6O zVR83enaAhm^p;>A-?xH(U@v{c#jEv<|65ToP>;r|)o9{#T|H&!YtN&Nr=q(u6kQb_ zXsfu0)`|;gt+GN}^?7tu*rTJ=1wF++xKieix-xgP*Zbp2ODwK7B}?|-UZp`}aXQMf zH87?nBPKKmrx?F{xNa>rZP|={hY#WGrStFz@`1>0Dk>`6YHF+PJG(kI{@m|QexGb- z526m-{`$*DMIG!Kd-V;}`}8z5f}_G=X@3zLKHG;kHm$|t;|H-L#0%TwgRwg+1xIT0 zab}4c|XP*0K(O!2DtqnWS(zr#E zw)$;otJ{Ij+TDE5Av9GVLvy7CT52uPQE!W`CP(x&dttCE5_hht(BGj#XM>vlEfk4S zml5LQ0E^?FW5-7uvG3DeIDh^;LPJB5lB_^kX?aw0Yn!>i8Qr?`g^Vqd@dUprJjIP~ zz8uzj?dqcXhC1YCWg$L19QLf?A3c2%n?Bu+9jA|DhwV8Wj|_xQZ85?bpLv72%ccVoClM`wwKDK-hodAkTm14_#La(bKL$ zcYO%Ds-4hTa|Ug-2hdW#9ZmI{C26Vs7|qq&&|0|z?G^iI_a{(Wd>rKkhf!U03bmz{ zs4KSRbIzzK@j^p+xMcrV+H#m%RM2-6A|Wai7c5TU6nhs34jjPFojY;H;w%FE0}&ga zfReIubaZuZ6qv&Y(Z|cbvmBfJr4DrVU)@;Q*x;6xYeHmV0-W4kag6!!@`JlE=fpw0 zed==@%1nX7Kr5{7bYkCNGuASXU(!>KH+xF)Dr55(uax73s}*>far~s-Voc~R#N;a# znACUotQY6~B%bv{GL=9340C{&=__91XUyX3i~Gv3y{8gquGGMfHNh;_{j0lMP}5tF zcIN(FEotbf4rcsshrTLvT&dZQp1P0FRsW$R-Sz7k7i^?|*n;k=Pta1n6>XKDpuK9l zByH8atzo=Svzs{sB!@7EUR+ZP+`D+Y%cm)OG zl+`)xJ#+wDwzF5}=77t^+3>F~hg(}U&a+2%sG}TPJ1g)W>+JK|3h{bp5oYqNe~$6} zw2lHyWR5<*GhecQVfzz%%P@_v3zjc|q>)X&#yOZbqUdjI3s*j_VaY0?t1ytudqRMoc^#j%l z>eA3wn2L&0J#r0cNKOpLr=NU;O&iwZjJXAzUESFKNQTM8K4f#J`ORBj%J^bAA9$eh zfv>I&PQTL9cBrPX7%53fuyVA=I%0B`9omCE?hZJWmVhI51vt(+{{Eg?Y-lTGY+sId zI*KrhXZ=fk%;RbELY|`CPU|Yd)4Y9#kDuk){vt)#^-JxAn9*7!$uq5m5Hh_b7f&^t z@KReIX7K*Y?Kya@-Gn)vIauG3hl4%EaAiEM>Zw6NTNR4vYie8dXsJs4Y>w;i21d(dUti{A2`=qcZZuF{XuQL+gg2FHUK!~R|%uk-guEU>U zx8-S=v+f;`r$=OWBdmA^AMC2c?v6@qY%jy=-b%dLl82eX)_KlP?JSgRU-$rF|4)g> zlxginnBH1|XWH`dLTf%=YA(QwP5GGKoR6oP@-VF_2U8l1c(&1q=j#o;&BDt~dVaPJ z?>8H*v!G4li3e|Py7#snMbKNug-_PeV$vQDs(HoqOMVMOhtOPj z42_i5LMt?u2eC#Fi>AtWTwi2(i>hlBm#K#RM@-lFivG(cyM(kuCej#J^ zx0suY82=U8^>dvCc)F_qPf?~Z#uvBG@;M>Tx98(Ip64&LnDBga4xVeu#|bU4$RjcEFVtY!@i z%}NwCM5Ch8hjF?!Y7B=_o3#VAx{avKT#IV$YDvWXx{UQ`NZ*8d%|_H2K14(IdNk*5 zLTmmwTK>F_V$2e`c?V;7=Jr3ee_{Jm z8LNvpV0v3Fo^8#=)3keWra#kQz|-}5OsvesyGju6+57z^fIwV@#t;Q5?hdl40RM-9IZKbZ~(`T zTfoCR0Gjk1&KtH7FEA*_0)Mtt#7c(GiJlv+Z%gM9LHMD#H@2?eLEuw z$JoEyeWMBM25KcN&a1TR=R0zl+w+X?W}Hu%(v|z8Ozz5IoS%cKtvbf}Iy}{qfoaWJ zOl?ZX`EA7 z-~BvZw} zP7+(}?&gWKbR#OOo81KG!NZho{08WZrpLn;EoVmMPo)5>) zTAXB^Z5``!OPQ;`)m4bs7~8+l$#eY&`xmx9xzmJ6%z-DiXTz+GXM1xNCN^p@g(7Tz zBC)k*HK`a^m4cCskB9SYf3hMPBg&#Msw4s}wVwm_`Zt^1Jr7T8a>QWS^u0W}370Of}pi2FrBz4-2k}s&& zZ9-%ACN$-3L~}lK1?C4rgb!#h+KQG!_6~~nqNVr=6_f4=@dtUhS)+O_Fb#PKPJz}a+?klTQV`B z@vgm3V%|QbmN|S)A|_SxjHkVevwdVq2u2hKV?w?!rsewJDU&yC-AlTCI?op`n*#7Q zZGTmMIMx?MV@pL6b}=vbyeR{=ZP^Im?~%%WU^eH4Dmxlb%f4eP^O3eD9eaDptkDId zCD#KL85d~N=EzPs2z}HJ+Wr>k!q!6@^Z_ygRzerPR1!nPyU31Oj$FnH`SFYk65dB? z(pr=ze}Hnuhp14mLzQL&YFIm{%c4&(Zl*u@2(2PNU~bTu_o3t$I?J~+9@xeIpMA$N zb15(Ata2y5I2t`o3K+BjaI~RsJ@zRs*`7swd^`#Z3-#UPIlE0h!-rK5<-hwM?*p$~ zxiVYu=qZwuanaEMyJ`D-ZO+3^t3)7c`!>YXd`isTD)#f{uy*$n&->?i_KUoJVw*{l zX>A6^_HQmjq zXCI=S^8;P<4ObXz^wq?nzbX`+B_6ElIik*Zp7lU;+V4^3|NCg;+hB@ZFWG)(=wkW< z#s-1&krBKQdisRisP|A1y9)WSD^M7}3dJdFP?}0#z}i7oI%@}6^aJ{hs5gBe`GDqv z^=Qo9z!-ozL%|L-=I`SDURV$hnQPQNlk^jhX+1kT)N5iB0e{&iLI%{o~yMIPIo?gcCWUY@G^Vx zFS33oYIx7Eem|YhO>Gi&yiC^dGBAa8I8no!$oSrj@%?z(?u4>fOehY=MCR?2^8+wB z#}`wxJ%11n-g;nWjyK*k`C<-VpI;P=MdcBAw>k#z*Ct{cV~5Xq<{zOyIo_B7bNU%8 z#vsnb`9#vz(}*$3XI@gnencG~H@6j_y;+Y={w`gN0lMgSn)!dXV`H zFt5LeTJ>2}B_Bm$%r4}Ie+)z5I%N2*M27FX$O>2reaKQ6!E2z@0MVan>#`_ykmoMyp9a`uIn)BC5_nY%Jqak-YpJR`p;4EtLFA-A| zj4t*nN^^q|>}SK8;Bi=4Ss@}Kf_TA_sE&?~jkj*ylH&lmE_mPSf}+P)Q&VFtX4f2@ zopF>pc*x!s&ZZ2wGoC)tS%r@{D=%{Ww`uRMG-u=0_5!KDH=RAZr&zy#s)haeMgykT zY4KETIwn>#x3A=x&p3TdSpr6v@VqaI#Mt~`j57sde6}~t^q!cccb8lI*{(yB3X{ zCu(OtAkP0T;s84NdvugWGcFHiZ_iJ%|EBEAXfisZS$_#l%nO<{7HCXAfx6U#D2>|z zQ}}uqf>uiQpAoPS>Hc$&89bNqz+7ZU&xa{?Ax!a$k(;mt1@r}?UQnE|3MHAVQL0^}t>g_W)ujcLOjAdt!{dk=VCS*8aip~*F8C~#fo;z!Lo|vB>iRA^+SX~r{4@(lTxik)& zN@B5r{^Ns^NUWw$SXCOv+fb~ljKC+=;n-UhfzRt>VcnR7zy=jk*fUf!UNDtMp}4@0 zu{mdVG*+lqoknHq2~;SKvln;@RoXMCNI!?lbZb;=tWlxlZK@s060K2^Xu+J|F!T|h zKohbS%Aog<;g2YlBW&VE8VQe*w$WP1!}&KyEWYygUC zixu@fEmniyd}($+^g#a1htI!U`}XVU9XAFyR<*Z6la+};cMsT}K7+l1o;X^R3H!c! z;`Yn1vMw8QiO~`D{izLEnA*bpo-&2C_Q{Qztmmh}jJ>z?{4vddSB%Yc!o*DHySATu87~%jVMeJh=H*3Ti76aQv%|2Q zvL+`4tFwc#!sw4B24Bq8UB=rPu6R@9fVa}@u~>5ntJ58@k@3SJ<_#CKgW#hJL_nqo zVw4U@h_!$+;2=`Hwj#xS0~D9nBiZdkBzbLw(*I+qgFa;)@GuG!%~6zi76s9FMc99- z;w0nzeaMdc7@1LPp$T3l*}u|fE`(_42ekeRU<_nV5X3%W$TGfn0df=BKS*I8k$J(8 z9}su~fi0@fS%(G_YX!L<@&0zk0(;SvLmY9@SzHrXfpQ&cOLRz$_ajfzNu0fCj-c3J z{=bx5Vt#< zy|kBGnb)(AC(ipREwp>ix=m@+5QC?}E0scus4L zXDHLO7cf5E3Zv32@muv7NrtH{F(&;yrfY5RdZr!bFoyV$`MhPWJG>1p@X5M_VC7lv z062i?fUStVyc+S&OA+fh7crOKLag0eNV0!hk~HV}FkW7Y?90oM<@bS<`xi!SMR~%f zD2?5T;^^%tj@XX8;4Lutu1A&^eZl4TpmtvZwI^c%;RgcWk#Yk=*ka^FzAM!UixO6& zBkW84i*>pJ9V%H0Lpm zwmUiHG$tgQW4z)tMky^Yobq_uSqx*$J|@c+la2OxImekX!(}Wj^1+tk09+!6Pe`E; z!t&h_r?*3j>J*eQ`=JWjj5Oa5kmR-qNwoJQ=Xp>#%|*hc*+{gR1%>r2BwD_XxJ&bp zV7~xLw`I_JuSTZN2Rz?5pdfUsB>5p9!xXp~I^Xx9@pu=?%X6Ugd>d-tH<2FjHZp_e zLl?48suh}|mi_1lN)@aTs#i+*!s;yc42UhPHEv>!U@K}3#3dVdqh5a)Wm(o}Vx6Ru zJ&uM7?mvk0gQegeb##Q-Pte%hYPQ1$_GJ@6OT1AANB4pkNw=@TL%v4cInjZQW= zRhWSjoT2@Yv$sn*OZNtGG|$y)@icKe(R0Vd=@@e5ewkC7P;OVCCT&IglwM;(0Q$a`to8Z zT<0M9@@y#R2Q;2@k?y&Weq#yr{>%r0mm@EH75fS+Q5?SlWvQzq{IS3p3qMdRasm+x zm^Slv3vYL$A?F0K0?wQ-j6*{SdCdJU;{x}Yc)GbF+n7Z@;|9w+cLvSmGyCB>v+u?A z{$gNodJ}i-#D_=Vy!mN-ZhHYv#&ld}&HO-9KHlSO?R;YMXEhn{d|d{6dKuE0KdwPT zY_1w(Y5U`=l3-RAjR`#O$FrV4hS;2uMsEyfU2hCy`cXXNM`T{YlUiF0)1Jo&#_1!p zR*cuJFrJSmF`l2SxqvBZD@<0L!<57`n3`}_lK-VSg~u{1FiLlh{eknCqPNAf1_!*9 z=Yls1y)m~k81Gd_V?#qC_B5+;qAde<-Pv%xQiyPJh^WXNl;2x`;+_J1RcH2%M&b`z zI3Lhf$}_bv2=$CPD%Iyvlysc^{=LvMH_-WPhS7ulKIhd?y3A!xFq?6~EW|PB-cJkn~^FczpWZlEvN%-fy3J&Fc_5nvqEUY&-r zoDBH7xxt1!3;upyk`L(ZZI^2Sat!b{#Q-<251Lg~SGsA^(_rajhh28(aZ0bi`Mw(L zAlJs679(C{ZGS53dLqsjx&C<8_eL`o9b1=-3H6NkD`PN`b^Xc2>rE*L#H3vI@z}Q? z%Q$~DfpW;cKLyFcUC`0nun117G>!GgJGXMH&1Ih~($j%B! zrqTLChVjb2X!e$X7t=~qZ%^QfcnknTAsrK(ckEx>UxluqwJ< z+H&RutE66Gtx?1S>=~MfDbCx=nt%mo2Yfh3s7A3a8bO{8xODzBB0>XERG8a#o&4(e z;!Kb~#3^*te@iPwFiD4aQdD8@+fzKHdGez1Kv#`jJ<;~g-HXZ_eTD~u$bX0+-IMyt(X zmUf!LJf1zb(TZajqd0|8LTLLV6&4tuW+T-DpQayqmA(JD1>smzDb9B-F7y?^|5gK% zzUhSi+kO;&H>j`s!&g@A_;$xt{9(p*{L$=h)!*NLb9KhIUv_T%_D-|;?ZImMf$qGL zR?Zw&M=bvi=KAk)R&O@3G%qw~u(nU^j?~jrVqC3)Gxv!+^NHCli-cK; zsO|e=f;jV;=bN#1H#W;2qcbjHBbF7!0|1lxy*sqeLgZhh$Z%0gzUhjFoi8ge)Mt_ zFcv5whEU8QS80hE(!PiKtW^>RK~44!RORePRUT)F%l*hpu0UFfFYGT`;~v|24O z&Yf}|Am;)9Z60vv+Q9VsD#rb(3Y@uQgU|ikaW+?jQ#|*#5<54aoEx) zGGzPWR@lDq0TbA}doJT5USrNM$K-<*ob}t%qQc?6Tx8w4ippZ=N_cw=q|LyHZzrV#DpM5pf-TY2!ii1#)aUSaEok;Lqg*evx;@Lw?U~Mqz z;#-paC!L)Q6@7sE!dxWV&-yb_*#F4~Xk3{Sco0MAJs(;A>=A_07cdscja!7Gly^Co z^e*R$mZCa+xl|i0&-xf8S)Zai}iw!ap-T5 zZ-4!<{NH+wyIAj6rl-Ni%N?7Y$vt6G;Q)Da7qX}SYL5v|v$ppv<*6Daar><86K6Yt zc0Z{+hIxJ%CUbUfA~CZQ+0z?OyzB(MBgV15H-_~+5$}&kJBKG}_aoV#8?y1=q#Va% ziWB%v>Pg<7#xN!Gebog_Wsd)r#tm!qe%ND*f_0e^QRMB)y3>Z1@2(&ETmQEE`Tnnd zcin8@X3L?D_FUwfBA`yNMIz&YIImrZb>4(H`;~~gFduQ}XCeLq`v&J`BA&TH0{e-H zmtJT8fIWmuuOiv*HT=mB&deqaUbgX|G#84r+$ zq#|oADs)>=olE|r0z2}T$B>&m386u*xXe8&v2jr-D=${u_~M#e3y|Z0|050}`-S~atiBuXk7Ip*Jm>Sw3W8up z?Cv-t&wZ)JXOFQw^GB!KU}V|_#`l(ZQgs$jh%;Ydjwe%&VHoFVgzZ1BWbB`2!MK3^ zdiDS(vwt^(vBQeOFzl{Pfi-ynB5u?m|NDWGT6}GN4gd8or^DZaF~J|YSKS;ejp}LU zZXeDj=B8M2K5!p<|HKkHE{D=#K2nG&iaY-rbAs0pM_&+c`>Nyv5-+l5X!{BhZC^u* z-7Kg?O@OsQ4SNQ{2W0v!fPr`c!9O5;Kz`yf6pGs55B-5s?HZJjbD%hDFG}?1P|CUJ z%AypQjH#R%bm1OCNA4v~M{`HL)vd4Op5XmF4<5A7{(|%4b&6Nu&cQ(r$6lW6;sdG1f3St8bRCt}^!B7(huh>P?6Lyn1FG>r8gu$A^Ha@r+M@P3y2|NAAxfPLztoLsFj>ATumRq-e4;6LaLRhP9s(z zVjx3A9`J%Q)pxo^gEe+={_xaOKidCL-aj(+v}FI&I8!rQ>xR_@5!hFugd2U2;_F`2 z;2Z0!_~Qe)H~ahB-K(y*7w8-F!eC6WfJ)$tJy#&cVG$C}za!aywB_AcK-hlFg&E8X zW=i&-#M)uID2W{sm?3SzTnRg<4_^*L#CsAaSy>9}g31+=52(zHnpUMocbkj}kbTNspCWq0wbj-3Vev6IPTT)n5ebXt zBJ60*#bR=2&!YXmP|diXbMe#I-y2gNPY#|K&ginnpC3p}j}L2no~-Y?^2~R@Sj~{_ z-#zz-^V}bqdiUHH{k*ZsCnb4;Gc)3~sjLNx8J#s*J~%=wo-eUQVmD9wcVGW%>eXLf zYp`tQjB|n31&XMni1OUbTwpa)h!cuC_YUH$W+V2(OvIdjg|Wch96;0u5`_<7z94*n zg8c%OJMqIlZxMU&4$_0(MMelQgOQveBwnyKX$9&S3)CvtNIWC?s!gacl25GA5zV#n zFzF-V?QD-o?{E|uN^p(*O|lK#-*fdr_wYw3_^M}s;Cx3|f zMchA{asQD04`VDaMtcq~WjkRx`vtqI65-Uvc>mj8wBZjst^p6^ng7?X`Rzyl_;rKj zjSe+2dalsM9D?3!GtwPbBH3mE5-z-rc$?QG`;W1DS&9K-tX`G!f*~J}#2#UaGv^OH z-hk4Jy#n8bQ2Q^2F@!UO#0yr$E=5)RGE^p$i%_{5!v6Ep4shS%ITZ0aRhOwaFB}Qa ziw{4tfW<>VYk&h0tjadPJl=WOi=wH@pF){OHl@hI*4KhjR(H_Bsp zQgIX$Qcl1uiSd6DeE{+MQ&Q~lj>d<${7_itry`a6IQqW4@vG;yZ)|F?)MjvAC(;_h z9$OLOvNVa$tQD zWO>e!a6_6i&#hbMN#sQf@-LPmD@J3}2)1&76jyU%f=P@#cvHuVKJ%Qo*P0CS8hVi+vd~I^74Q8jgVw;{j zz)Q7=>8nE7?*=h|?;fgrw6Cket;7(Hv?vSm1?@lr=K|tw-eN8=3o(|jQaDp|PT&XM zAa;QFIaiQGAECB?0~*ISIae?nX{-mNdCiB`cMr+$shdp>XQ8P4_>^~b)|2WGLyW0e!lRD42OGZ zHcq#2FHdb6o~tCbhqiB48Y9{M1aj!#t@ZhlqsLR?<{70IwojWUp6>~s`H$1~hb5oG z@FdRPr<{`d`$P8sn85V12QX260nd@kXGu-~j#hDJ0QYd}{_6^w@jLSy_`^eW4*l={ z>Ys7FGq&K{x1T-F8Y2gpTij3Cz__Y)K)5GN#N2NK`s{J?G$kqe|7YJotodxjThJ$1a@LqL1Og)@u!1QLuW^3h4XH06dV|6Tr2BAgAcz>DaN>lC z5t4-5Lb>sqkgqsE&X5b7S@1$$mOmmReG$YxEfoS2I4I+R{$6`}kbZukzkfzfLH-Sw zkU+R6#lVR*|6{dAtSDFGIdb$oQ;{I?agOJ?FWElp$D_!%J>1}d;pE~RPCh*`uP^X= zW68fWnzMOB_WvYpej88g&ah&0s zs=kD`bzb;1Hy)Ska*%tqtxdirf4U~O2Ch%9uP)H*l%9z9-;X%X5XL#oK@#)+lrzKw zTg*ZdCDwwq04w5#$vq_efWQnV+7Tll=7@B4!7(MQ_D2d{j=y66 zqmmB8jPd_O`h`iv{Xfr~;a&C)j@4u!s=p4+-+yWTYyOUZ$=`P8M)#_kqIhUy&5;(e zg?s|!2)XnQQZ0!ErtK%5ego0wuOY&cI3e$Nf-=pmU2>b-JhQKrEA zB!!a)Ps9B`v<1yu7*8UG;IOBdX-#0$Z8ZQ$Uv`)|dVp%%09X05=Ik@PT z*vG^0Gku+18;kN{kQQ?iNr4|QreB2AOK&3a0`2|mYls&!16FS#%JNOl56zH7-~^L? zf)m!z2V~F(=(vAC?>7%QA&VrQ;T+BjJf7F948L&6eg2zdlqy4ZH2M$X)8p@oxZ5szyIAsTkrch zy4TfaL^*w~Hs)j2^T-|U@HSFx$t@^yf7*Zax!Hea|6+D%2qP$P!fJAgrMr`7#ETdq zpE=|xpAW$`ZV>YVk(?Jw+Q?ny`%sYOg`(^@M1?pZDK7YK9q{HC4}Cr6=Uk%)^*z^a z-k4rgQLYG%jKDEvC=QgV@iFuMS)A<=wSKX4YpmG6!<>I~wmZfe$-~cj(P;ATjwKhT znCTft-k!&a=bw;791nM4{733B>HPoCRMz?^Bb3K6mam&BtuT{&JhtXUz@ za&wQM?F-H>Vf!PQ%ZvH_-xA9&Y=3;hsk^a1}C6RhhGOFW5@BG;!p$$G!Y z`^V5fOd(JIJ9=;IVZGnK+JvgUPWyZDH#{t#@w+c>3~Q<~!ld#*BKraH?jMk2c!3lH zB(VOMBzgeE1&OmiUY!5DpGY4d`UT0X2d0XC0P%rJ(G&C{F2I-E0o+3<_K)RrR-iay z4KV@xhzYugI`XupL^&fqIza3Z#=wm)9x5E>!=h6IU)-6VTUvs!#CSxhQgNmx6CaY- z<899KPUB8#v3GMU`~2fs>lfVo!uFpacbDMg7jyi=_Q$0%_9s`5;OrT){}Hr%VgJJR zN3iBUo}As!a2{YG_xT;>%vnrFCECBZA)oz!4@9rNo1T2#F59WugfFbHrn8>AG zQxJ^wBrnPSv$MGax%Zl!1N@EG>Ot@!JvXl}$|%f-UrZDtG%D<>(_$%ib3Ioai77ec z=jTpL!QnAZ;^ue8rksj+0Q{|qLu&u1oZ{p9QsIsgCU{Qm!!d>oVGk6=my zu|7$(efou`m@B+YjPUl{Sa??FqNcag`a$@9{?&d*v3IelxKOW4^g?RDVI;V|k67}G zCtrAxIKbzK4SEgHXZ~dW3FH%#gmc6q1{lHx4dH{e-sBJS^ zayFT?{zyp-l6Zm}nma6S-jQ)x|7!a1_xwJCUw&cM)_-M(CeH+)s0c)+tFfK4{qxHc zF+HFBUEG-~_HB>luB={*(JThVeWXJN1O^j~BRp+P~=c{nY-aCbHL0 zUoerm!LzIvzDBI@KF*nhv{j(})}Va$|HAX+N<*DhaR&E}M4ske;tfc0oWtE?#Qj)3 zFWG*S1>*qL1f(3`2m6mFHXw;R$r1#oC^-X?nFk1LU>fnkI`4(ZrVq&RTf!Zr+)qj# zf+Fr>$j=IbG9?r$l?qk0O}KIU*FT5(_t?{e__OWJP3Cc#8rWtf<3NcLa~qVHSrUzB z7^hD&lB-`w&R*`{9HZkLKl}W{d5#a`Y>%*iF}ou${L)+x@x8-{?|p*y{#e2hJVvbF zZ;1DKnzQ{cvgZFvx(gO@4~0563$>k{82Ik@({KL~a?kG<_<)<&yH}NP-=Z?k3yIuG z7~`~-J4MJ3a^WT70AE7n*%{;sm?8B6L_I)=s0E5Tpx_P@wLr0BK;^=|;APeWz3$?J zb%6_r4I)QC)F&uXevbNlZ|Jo?+#wo(((-y-x$?!Yo`>Nc(esA1BZK(cIH9oIL%)_Mad(*AwLHev+~OPwih| z{GVj}|2SiQf$tacJh6Z?`Ezd?ys&~?VaAFAwD$KOy7~Pdhuwi}|G(tgef{ON>5X*- zdP5rblX6Zt*<&;JjK0R5LNizke3>`^_5&%R7cf*06t_|@fZXDe4-mUWI3FPP4W@CY zfYz6L1vn$1^W%I_*cO-)_o0&5Ze6-JqN9D0Z7M-q+ci06`vv~`mt5n2#Ls-we|?70 zlnoa}6fE<|>0h6TH!EWCVr~$o>%A~F^D-uIuE$L4C~mNy+ z-x%WgheY^*$C>vJV-6{N!859Jc$>Mya_;y%%-P`!6zAf|1{GEE#*VANPl&3^S zl06iDyU77IPr~~M4sp@{7d=4<10c?R(GMU_NX!XJy#Ub3t&%B;t&;k zMVJc|gnWpcxKAW3KrVMAC&c+6BP$C{ja~9g@ZWje{txH-&}G7zcyD3< zyJ?@Vl|L0@Qk4z?S7wvs?;_)9vY)A79&v&9 z9oi%E*X&>TfT4b%s0AoEACT(wCi8%|q&z_Q05K3*^pmao&sipXdQf_+Vl8L-GS2AcY*l zsiF?xz};iS1*u)%=1vjj0G`AJvlf^cx)vtRY!>O=$qnugr79k^m36pv{cE%Tn@^IT zf3Ri+JDQr!6FKK?tBsfJ|GnZkJY5usiNxlQ6*WKF|8UyxFz)Jkf_eXAjOBl$w!m+R zD>Rp{sksL$^lphP)PGZclQg57(nC! z!v2M1gnWRk*!{@moK|L9Ad*v}QC3ur8v|d;IG}rU{r;K$@-}z-)N+@Uo`-ZW;_XK(T1jc7b1m5q7 zxT6yH$HX*Syh={M4|BudRh*8B&ITFle-Cx1um8&Ia(=IwDXvHjIz+zE52U>SiJbk3 z5%qtHhyf%l5N{Ld7X(HynKJ`P*5nW1{E*lwCUy&|SO-wk2V@c#BsfI%p{tjZU&H`H5(FMl@&UvF&<6zkYvd;?j*E1(VE#yw@{BwjGBA_9fn1=W9bP_EtH!)y4@vj2fwH>c+n z7r|eb3aerjmJ##wCTnz08OYyHjE@;-dc~Z+8DsdnTwbRoj&8B5L&%uqV|OKq*nY~m z#JeJV!0^Nqob$89E8PDvKRXb+@)D6=hLJ!6^=J+^q#V&O!$30BWzr zPz8O6Jnmx3)m}zcY6uF9I&^jRZv1EIto;ApyZVBd`OPgVlO4}scarOC zA+bQ@0~7H-?foz9Ki-PFM1>FdZ|q;oI)KV^5tM;zk;58q4)?8RDuR)x&qPOiw~PU} zhd%sX>cijiSyu)JX6F=|ezgA;ocEbYevgR;CyXOMhuF_ON@I2souLRgMBe{p>;t?l@c{~MfXH*NN)p4E|E|3Hryb+;6M{2PaD@r3K*1HJq-dNM zayR)BsQuOI{>%fkXm9S2Ioj^=HT+xb_FlcWr~m3AL!J?SSqg~r|2^{W z&LHQ!u>bMI`i&90dW8?*oZkq}`H8)K((XRSgVOFk_V&fz-k*xF{jsbOOyPT9ARp*r z;t1B~M&n|h26c_~GLO`K(3_sVj*X?nZfFwRkQREBIKCB7IL_nFaB=}qgbxrB#~H!9 z!hQhlK7sXr!4LFPp1@Rc1gXduD(qk7u~f2u1F_tBN@wU&16T)4M{|9Pd>!w@b-Y)0 z{c}I3r>}33!K6oEW)f^lR9IaWi#Isy_bl!IDW3mRi1!gPnf2d^?E8y3e`(gA_APik zgp6Y!P|W`RRD|t6&%Xbg+-bYs5Q1Yy?(Q{Zp{21|#*W&N}*me%$FV3a?&m&Lh0?rUE;%qRv zMID#W2P}o^@(QT@)L|%wH(LYhimzBZTDWhZ^-_GIQL^) zs>b`=>oYq)fL#18ct-Ci`2fMyGmU$^rmzP%nQ?%SN!%ABWFq^4k}x)y_!F6yW{H=G z8+(Vj|7Py-JCTzJzg!(!n_A?!@jmFx)q(yQWd#|~B>TXSXbofVM#**)9Ty|sexbB8 zB%ZjSWbO_S_@G3)`I5aSJ1k_pzeo}V?Ox%sl)M1%vi`qZl63Di&;)Lh>|ezH22~KU zIUibI-GE!Szmo0$K3vOtVb?$RGy3}aX6Kj;2-l^+sXQI)IQO%hoG)vL{aK-N!}3fQ zEaP6DWyArzOB}#b#`8j!kmq}`=HidCkX$j6Xf9zPWmeWjyk)S*D((W_Pt2bq_Xs3% z#z4*+?_KTor`NcDU|>dhp$-|T{wScG=8(T5({B@f0C|F4S91r*N+@}&c3aKf0Pj;& zuB)WS;<+^UHFxFm`_OoNz**pR#Q&@%Kj0>0hV4L3;wj>Q-B|++r~Ru?Tiqzn0YBij zFZ4&)zbV&<2)zO>l^NJrpNf^G5m=Y+hYyJVU2XKZE9CoJNzT6&<#vfc89GqTJq(_!2 z5M>#jC{8*EQ`mN7`EQ2SX9KxD*Kr>(XZn5CLrc5P@cIy$v~ltH&%}2FXa6=LH)soT z0ye`G{t2>U_9Bmb&ZYd^yo@NAGSX!G{}tH2u)U71Ya0#OMTpa7AgNr3psIK{@%%qW zzAp=-H_l}H;B1bsbpJGGcZHbiJ#mVB076b?UH+?L#n&w=@Y{)G-y z)!99;(U?<=1Va{5Dh&v&O@dolB&@mDQ}_TO=eg(0lH7koBK(2y3;&&5^&>Z zO%fezKtuQc@>aYyBq`(!Q8NBFaF#HqSP6Yz8g+-W<4q0n`F|hmU&Q|=y#YzdixMRd9D& z0au6R|A)9Z-hJJf?{RTn4L_H)@OAzGo*wJqO@8s9=tGD}xr8Kg0O<5;G|PS5M}Dr2 z{VTuk_TUY(rovLxWvbC@N=9$C7kZTrl8yI9orRFTXiIcQSV+g~R2c+Atxo74pzkT?fc+C4lBAy=-@!lc%L*VE5gZ~NqG0`4hrUjrw9R?$Jik24V zU~q8I>>vGi{@VY))|R$IDzy@R;dTg)wSA*iu>aPKMBLJb;13EL{4VUMWYf33cK!eCy?1n7)wMo)?s$LP-(!sX?(Zga zuw@Jw(-RU12@sRyLPByW38C1y_bOYKWlJt9maS^b>b>{gd+)tVwtDZq_wv1OZAtEw z1TGNR9%FhRowfHl`>Z{`x#pS`gO+tZ0(8nvNLtS9e?oU9~tc6Q3S|AZ6l z1A5@t^Vp~SEDj!i<~r>^xE=>?qWuS+g7n^@r?H>s9XRqVjvjdqM-Dv$Wz`p;a^_{6 zGvwZZeMUS2X%pi5-`LzD=l_0#&+xlipG4oU%F0SqCkJDIHRM#Bqv3nv8`p}!1SbC z|LYs#pMky+rJ}-O_y>B!!dVkn91cNC|4pcbm^>#+aCb2z2<4ldapVShMtWaOrxlQpBiE1s3V_nY%O z_Kl4yUAuM-wW*;J{ucw!FX7*83k0SYE^m}bV1Ci~Q^4pGKpdAzyeCMUC(d7y1B+L- z02X@yM>UN4=%a&isj1%dDI|uYrm-F}{=d0r*g+podRhiNyj);nr$JqP2Tq@V4M$X- zkubkw&uVPny$U<`Dq+XY)e>#ru?jcSwq1`(=ZNzJ?bx*nyY?ty*P$n{PxV;||CjBR z;Ys~JyC5Cia{aGw+=laA$hE%7ai#KxI#kg=*A?r8i2!}T=?K?yvDSZrMWc_1^^b{r zk|AH;jl`HZhv(xmWdmvc3a_=IE?|EI^Pbum4z)oE>&GX@2B73x1vGShI*vKB&oF!W6HFR@DA5dMfS_5*gB6-vd5=26%%zW|^Jh&y zg`f%MkWJWpj0O9>fEzWbt5XT-73V0Bj;x+f>(8nRz={U7WbP%0@bw)gXP zgM+gH%&5C*T>2x_PrrZzhm^2q@1xkci);PPhb1{6t?^v{SLA@ey+q4+7uXlHojSk{ zaSd$&`&3@QY5n(M<*JTQ#{XAVSI|iG_2riQ8Q+gN6urNjS(me&&vr2265y(a1&b}1 zBaXie|FgvY9M^s!E5!LL_@88s*`)0!OZay=3pS@i7h_Xny=)N@8iXSf?4%7)4Qx)0(MV4uI$OZk$AdWr>8NaN<`;dx=Hg%Je!6=)UdzvA?zWE)>}^e9 zX{!ZY^G|V{wtp41rzQOF-cS91FZKA{)aRG+zjfy$cgTSiymf8?k|Y8{{>U}4yZpYSni??ka~oND%bzB7!ET=TY@tp zy-k^?=EqpzQq!USiF^N*F!z1B*SdxV<7_+I%{=XVpKZEM=wNO4n z{O)}ad-gm)U*1F5xtn@D^#DQF@xHv@7kC%6gSvpAE!_Wqwwt=cf#-2d{T&!xIf}qA zN0eR7L;paJjQ<}H{sm7D_B6lWUBtK!+UJM;OfciLpE%xvd9k(|kiH22!vA+W{uw{C zXtkR%fO-ULNx=6sM#3+lBgqv}K4!3YFhf>)CfZwiWnJ>0;H93vzV(I0#rDBrA+WQt zrtM!3b}q-DW4r;U&b=Vv|H$D-v2Wi)k_^~Q9bg6jTX!zm_HUK}EBN2Obx8(%CiVk+ z9%cN`&!KkiJ(yXaL{z*N_x@#uBcp?|-}aw)X5Xi^lORKMDV0zyBc?4gZE&!@pvBnIxa!P556l*@$_r|FhU0N3CS`v52l=U~y=`M`QX=zwtl{8l3@1+wSUK&0 zw$ZO};`DkPQ+W)Bi2wcjAC_dm3jPK5Z^r+1U;py@zaj@VZs&Oi*5KgrS8(S1C$M$Z zK^kL3+BzHLxc`6fS>2Ac@8jRIQ$zPmG*#$!W<+5)#2$-Y$7uuDgM~}f=~3}N&f+!5;r(PL|_<6p>tJ+uRg z^{z1%KW*om*|Mma6M8y2O;Rl!_{)HZ}pij9Vt^dLXz?h#a z8>QHRd8@5hu-=Aw8?OJXC%5Q+6w|(1Sd6j4M2a`cLfv3*bOFAMTdAmR(CrwMeSu%) z846vgp}AvM5^McAxI5sI%{h3o-nWhWZWx&U0UGC@f~xu|992=mp+l>1;J_o24)8_z z7qVc*{=ae*dw&u4cl^xnp=YuO{$bX*R#jv_IyNNhYX5+&{wmM(`*O}yU&m{0rMc*i z@xfvcP4kTRp1VT)iuL~{{LdM@e=Gh)44{bny9xgi_Js^!{TZ;foWTFM=Naw+OfjAA zhr0Lx*cvcb&EAearEFBUv}+7a&&j;?CA=kcrIPY0xO#dq$JYdA%=dHi(}uazHs~7v z7HXQ0L*?Wn68;Y#UVR<^LjT{fi|hM}e{XsHU(o|ra4-1)g)YFjzr8BYLS5%iFta;` z*c4B+w#l{IzAsq)-?)!)%J$~ktJ-zxv6y79r$v`jm@waq1tad|83O==54hITTxaku z-=iKNVuQu{zl{HR;(x}JaX{wG1ro9U*32Pt*ntJsn1ma13O!B&0gNwBaKT85AClcH zSYO5vo_;>aDKAB9-=N$V_)GAAwYph5IxY<+mKL~VsSB3?9XR$ z)l&~%$N#>Ak6`bChndfJ1OGSg|5xJwHqq`U#Q`ubK==o@9c13miC3V-xDQvK3&<&n zMc+V|yifa*=kvdT%Wv~DJDcm2Tk}#d%UXVLKaDBN{mk#<9^fCu{{m~vfwkn|NE;&S z%}V(9Ql}q47Yh+K7)uL44Q-8Prh2$yX^t572C1lTlH*FhfWNx>`(Db-Dam(s^TQ=` z#`@dp!zaR!ak)Ej!Te2V>OYTDXCB1~^@pzGfB&IJCHxEj-}aqLu|2or|FbO*UN_-%jZ(CF|z&Gl89gQ>ol z3u5gqr&F}$6T2d|cLo2q=>N<37rBC8hJR=J6ulWb9%O)7)&-o*Wj)Z$5I9;Jv&P&7 z1O)}*YH@|>o6+{iI)ALKX6JrDvis>6y@<0q z>m=-}oqQN8_!s*B?tKqR_}{TpCQk| zIEsVp;9z_PPG+LNbOf4f>*U&!H}P6?bMyQ8B}K4vvxd6XF*te{AUMj1wSJGn((XOz zU3wYXdQah;<{F$*r~a?{2#(PIcTmLt9e9ZN=i0yLe&+Msihq#7Z{f}z=nRfr9@C&y=RYShl4~4ho-|^+~_WdKn_YPNP)DI$s?~Z@tzhB4yqWR`q@z4Ge68^o8NwL7Q!51)_Xp6BdZ**mcBg%{Gnht$g zb`I<}k|gJtEaShWx&8g}@^alk#`$UJoMcT;*5C{>M@Y0W99(w8(Buy|Z}4-R(|rPG z&aQ^K#;PyHzo`8o^#2w7eivSY?_Y}}YA-_l{D-h`IE#c#KXmlT`F=k(xzX8B zsokE~__}sKq|U0&tCIE&0VulmWM||H1}9{NoD8%@`-h8i0$I+W_JJbKHYD z^6ISnUd9!$9tiiW2xCrgoH3AO0~Cj$Bf%FwMmn%CxBz!&C*6IGy%uNAtis9DkKp);hjCct z(WUkO;Dguo|J(QfLI#NSU*Lb^_Ei$?IQSHfY0&O}aWC9_EKzhdGk;-Sex<&zV$&aUt?+A=6}rhu zDeT8_h57s{aPlxkOqvY>BTmD?>r?swX`eTK7WxM3p{4cME%-ll>=7Jb{O_Iv%>5Cz zznk=bvHpv-e+B=W#oE7PHDmr*FNC#%)pdSL|AH!_D3cpI*x9P_~E==-0gEnuEL!FjR&7x{sr4uHTvd&j`^Z&)y){%=PAALIW;4S*S^ zotX64i*bMU5MXa=gt0e35PbpBtTz(x02D-Fs+9d}eVy5d;v9^OjNrq(*22O<`_|Uh zA5~m{i0`eZ{uLP&2y=6DXlQ7_kUo-_B<4=0>cP?XW0*%IdeCpyt@Pko&|q!-u+VxGGHKZ1Wz17O;5 z$1V6@2sr_SYq2gELOD+!A!@L6eGf*qFVGM0Gz^W_vbWE}-20QL|Ep;{ zjAO?i!~tdI{n7TfYu|m?A+W#eUe@#xdHwfc3;q2!EPh zYV<>Mr)-D)v0}d;P-+~R+&EBEiQ&u$j0c-xmbE1(%(r8XwZ28oFR2#j^_oC`lX8J( zsUJ+UZ`|VL&u9x^+@Se3#sM$}i2dg0U6@nsbpZ2zj0FriPW}HB<|8$+7;DIQ0Bazd z{fCN!fzkx{*_%QCv^p&GFCyGO0Hyf_UM&r+Kj_@E-p>A)DoW~1QxbAuWoe5Or<9?k zdk{g9`bf#qLvY+K#`^u9`~Fv9V*V@)Ez?>cT|4w_E2fQD1v;ocs9>r|X3Cx6@!CaIcX5-C(RQdyReYqEi zMp=3sylkzZapVvTbW zOAQAzgIL4c3`5T9m^R%*9{^+fY4elve;NNT>Hvve0iyo*yf}*fAnXq$`~boZDDr@p zbbx(W@H~V?|6|<$t70*f_>Vl#cpxLpCRQW*R!1!R@V+U~gyrz^d zoRE@=s=9j3zTpw29|G?U4UFB}(%kxfenC!>e~>5iO>~%Zw-=h{_fY58;ks{**z~jT z2-*Z&&o^Q2_;VPWt)o5Qaa_<}15NEUID6)CsHv}oiYjydk22@)2y=Z8vW~}r`>~C6 zzqW5>Kab5zw0#R}0dC>@JAaBT+!K7dllz0i>!7UhJNo=SVU5oV-1nz&YJd2AE&s-^ z_>B9SHZD{oa*cMtgr_DJtPax7Prd#w_+JpUfJI)A6c5B&0PG1i&srd}!gfdu!AKoXsF?o>Ty`v*&{eS z0(r$Hq4h1TyLtu({$*=Xb++}tb+w{KH!U?CZnSxb^ssum1IEd z?}M#7`|mmZ8pc-7z`*2j+WjAcuAUOkX({2%>9yP|JjQ+h8VURR4zboBvA=!)eb~xc zUn}_E{@J70wwboS&G$+8-%7i{*8TJooM3(Li|^u+^&y0_K0{m2HBA{CUlAKW5;@t^ zQLEgQ7maTA@fr6xk7@J$v;ne50I@Fm0IVD(KY*weCSm~?4=DNwEwUcSiVgq=>JH9~ zC-$Tbz>l#&!Hg{mIgRP?bC`*~h`HoTSWLIYT!t%95&>LG#&Ag@f*J3wt9}gXCyqkj z$N-)JzDUc?K~;T&W?M(+TZ6+R{}Q>wBa;L7cK3I^R9D}uTvA$T8XuPgTN?+)?H=LU zy_vCmY6y(HgsdVxq~xj~D0VYk{NAG8|4ZiKJ_TcQB^a8ng8n5X?)}$DF@L8u9*645 z$Dn*viS;@e@5`E>qUNvY`yuN1Z=;=m8~6QNHw&Bpa(xd`?}s_QI}bmN!>2ajg2`^U z2biItJS$(uzKs3bd0=w1>!pdR%>4004=e;SZpWV3HD!%YuJ=OU7cxN53jP;`FHqoL z)B|EYuoWF(fjWSc59o1-xj@SNELF@0Ye@K?j=F%E#HD?}Oqw(1@`5nM9HH@wRJ619 zOr)P1G*7G1ueG0XuxD92zyaYgvB=FYz_scc&7RKg?`?kS}HM7j>1HAN4sFy`#k1s4@hu9DNpxi8@$J7P$deXbYgtvB(os z`LqePJMQwO_xFbFx4(x$z-`Lc)v9Etv>HGA|21f_( zZRu)#zq0l!QZus<5E2S28(W-FKaG96x8bz-895e+h*v>a!e8MN^d{^2 zy$mboXNdi^%=3E;CKhYB?|%sA^;U81U(L86=KCLi42O@cmU8`e9U!i`_DivT%YFWY zzkj8!hp6i%XbXFS?mqGYj-B}f49pHNp4b7`>dOp=M&(+J-zVPrzTL}oQ;F#$ZGltF z4TO^l>wGiDN9q;IwO*0|^b1f1EU-ox7$+e10irkXJpF-l%q3rBJ@5q^y7A}>kaB{& z4okMc`H+)Xh&+wiSndPj&SO4_dO(sH7IK`iP#TP({7_8Q=VGun4<+nB??d1C*^?^R zw`(hoA3F*?`UzcK+>n@*2BBBCwRXPM`yKbF9ULO==|ACmubYyU%C$WZS1c^)qd(1h z9Q%mO{yX+@-_JUKQmzm2ztZDR;9u1G6xiRq>tW{jJcT1C ze+5m}aC7n1Mt)f|`l;i6-}p_wpYPXRWO%6Kwc*-a^rg6Ci1j=t*xy&w2?sGQNWwa6 zfr}b}QjWl7`UXV20PBbf86cg@m;i7eAjtrC+5&uN3!py`p{mpY7!w$;N&IVLAx#ep z8CS5FWs7<0#3%^?s*`|*e9Tm5AuGTEP6q6Eed-WS9NLMKs>--*W(+q^>I2+Y=jIe7 zRaMt(wzhS>)!8%fQvcA{z262ub#?Z>RM}8!SX`CwC2;RaJ>SyGg>lV>*t_d6l=mNj z`pLtvv(-dOiW!Pa%#fY0j=1E{5EAnig2LW}tJh1c?fV?_`_?h%_i@UNwJWd%pV}X!U-jE~-an@An4TKA7kxDv^Q94(jkCa`wRSwI>9sa56&1-CftmF8|DQ$?4}MtJ;00g0RzZ>j0swd(qKFga|4of zuH%0`!x~eWj+n~!#!O)trf3hGtIfe^buM};DF{o0R0UHxIGG0*4dG3NRc|H9`d>U@cq zo-I3Q*I(Y}3;b{1ejnF;uK#=3`)lti>^b^8RL=euhL$@K6m5dqrp)|_xn89o6CcaJ z_3P;sL!ITi{jA^78DNZ2M|I3t9m4dLt(X#f0gG*v2dw=g^$-0B6Z)TE%8)w1-@~5G8=-OR2uuz2;AU?Fe{U~DMn$mRcsgZ4 z0g5ZiQC@XTx2CZ{qp_`ZV;ki{XK&w2y@Nwaq95Y$P@j^Z{((NFzW!b%5tBbOG;~i- zU;ldHZ)k39d%w26LHQc{@0FI88s-<|At{-DiXcDkLmXgiYz9?T4N1@cF+x!{C(8>575^qdVGi)A0o$Rn~3$L&tK}_M}1$s{&XAt{5zQE zw|5P;?SC5kj=h1?7dFDxn>Gj5^&636{1vi1_y^^|H0#0CXXekapU0x_1+L|+5n{fB zwZgdei{7DPeWz_;j{3kf>&OV2y~LcLD~tyc`vp-SP{;s#$_i)32fMRAfG_s}L8`0` za+2{tv;_zmkj&3cqrV}|jB>zcIX;MS!dJtvSQd)uvM5Z~q++I}2!oA9$Vm%^vlVmW z&987zupgg%@GiD}`VmghMxb+En|Lyl_6Obp{#=36_?O&nRyw}3CC#X+r~N`{{!F9*Wls*b9neX!+To? zXSc`M%kL?eSw005vnODD=?PrWTMJG4`cG@DroC_}*6*nDD)#t&P{O~+@e?sUTN%@{ zb1(M+)c<$V|0iCHwO`cp7BxK&9RCGl{NINKd%P!Qc%r4Nl!lyt@Y&1f%kqLeFfrWq zQs1?lq>cnnbaE{bb%GWwcC-FJ*K}Lf{I%K38UTARYf8DmwSS870yDG?2wF6wy}+Eh zf(>JYB^f{+K-38KCjR}@0Oq&~e*ofjSR;TkAccBBx)JeDT_D#I^Vw!tETBG6=7#xF zAIwyQ0`;jtXED%SfsTR%L^_(n{IoKR8B?Qw>L672ZNb6qA47TXHrfpL;xz4tdb*l0 zH@OUZ*41*hw}Y#r1KgY(C7*(imnXcuJsF$h3TGE5I5^tF!p59_I%DYS>);IQaj4Sv za7bl4_uU^;_x_M}wNL1a-;UF#_v5l5eRv^P*fY-!)r~gDuTV!?!44$ny^qNB-y$sW zRRl!*jP?7UhKtvF>ikc^*5N7G*sW)7FMWMio`iw%6U^@uG5%|r2dE^)_zHXfA?o`F z53;`(_x$_z)0QuMeqz0+&2Ja`eC|8&xYX}+`)>C9rLBJ(bNhB5c^PVF8AoJ$3bE|t z-Pk0@`N*>GYs&uKI_25YI7~7(ZQA1u@yxg&;vLrX@e%*xZ&|VRBv_$M$Z<-mRbD0A;}; z+6#^x+=HWs4npO~VW_DbgNE7(oK-)C6USAc#&|>36US*|Q(-@?qf5m2BNeq{w72cW zomxqN2Sr5*s3=LIzVF32zDr0vsQ}nJ+J$i6z8L^zFM;PsT^Z( z58_|+_7Lm7u=R`D{$kDF&-y)w4n2v3jOi8qes>W2JJ`cptlFa{KlmBI1NHNe=t2|m9jqwOe?&oO_v}C_83+DP*5&O2>*V}Pjw_^_=kq5|F zV1a#+M=TL*1+k&NoXpFM|Dm-^5Oy! zAI$ZgeMn8tpM|>eJ{;P%1$#Dqj9s66g3X(#zkm8EKH=+4eEr$xPnk2fk$B&VeMfdm zb-2vz_23_2$C?}-h|O?EOr|s9b6t>8syTrhP3lvU|zrWDrlTtLtp=D=J(Ow ze^g1T?Xj0}eo{?u#`Fp7D<63psw(XLOWJ$j3FiGW-*4ZO)Ja~1ipCo_Z}b^^Ef}Jx zJPG}Sa$dhI`@R|3w>aIWL<5``(mhxwK$H9V6Sv~uk#;>%``d|m1FRtcOWFWL9Rbz~ zpXYJbVl!r~w`10BA7&kuG3`tl;HivRU)mIc85a=2zCrW}&QJzSr0ZfbgS7+mjjrQ= zA>Wp|fGZYry%;axi^alFOq9f6tTYi5%v%^^{NO}wHfEYjG1XR%;ihu*))t}VD&qzV z(@~HThqRbbB!mPZJ|uw05JZH9At)d~szc=O@6Y%gFYX20nUCjzz;GXg#`q#C*&oR{ zLDcCQ zpIG;I?_s~MW9yj*@Cr0ey@F%P&olOy>ptPIKY%elqr~(S@xS22b=-k5ehxf3a&K>=Onu-0 z#+Vy8M15dP=m9pg2ik61BK8b}2YrH+0iYg$P+m(p0LBL)L5sP<7wHpVoM0|(gZXBd zFS5d1DfbwTWAOP}g9CtJMamxOx_4l`1GL-;dnF z<b+0d0G4Q~%$9grwggI`(yhhQETq;FqNJ-pB6+#sWMCchBeH?)@U|d|dM#o{{YQ z=9aYen>|BY-;>bie*c{IGdOkn3HI`0JrA{qaQMW1%Icu$=l=-a-NT+9$EgFHd=;nkSjXE_kFkfb=;-czP3Bn{`~NFE zFfnw`RKqpRzN9GD_90fi+4GM&y%ZxP@bAp`oR-O%n0BU)&prQ??RHF9(nmm&`~sqP zh{Ha~9stS_@i_?KzCy@=7}^8{{*!en11?}LQy+8Lmob%Vipc_VOcq;Wy3`u8#der0 za>7ih3+Bo^F;ni1x$*$aRs>Q$gkqs85_8otn5#*^Y;6Xn8}cwsTft;g6~>$EFx1?D z{)SrgHPMzx|6&8rzgFpq;!-Q-8(cst*Z1VqeMm~(g2d#%BPQX`h>ia}qT^me7}xq0 z-23{!056|s;pzRXwC1~dtcQ!+Gq7`7M_b?e>vsN2CQs0Ru!jEqN1?5?O2Yn0=JlLl zJzpUM4j%t0_4xm!4eux1e^3ulS;u_epVKGsJJtaDAKD1trfu+L_WF2S!vANglnuHs zufqh^FkQ4_FfG=JXq|zQBa_ZcK~)0OiA?`w_+nGT%tZ0M@?} zwF4zNz&!zy7$ZQt05WMC%%yFx(3CZVgiV09h$36s1n4s?aiCqmk>rYnau@0b9+)RB zl>1=eY5?Z1Q5MvQn4)Yf)E80?lwz=@0)0I8v}B^ADI7I5cBs615&5Mm$Sl~5_>A|M zqw_n2C%lgE*q2$O=LLy^BVK@i$TRQ_e3tq9Ps7vqDf;!+v7X*j^y{yOquV;zJ3qy^ zAlmtC)-j%c9c%bLDb@1O)nh#mUFP(&mZ!=o*78}-=NCPEgpL0o{dX#&C+EqR=@0lV zbT9m#Ho`wM7x*38^?!|>2iDQg_ZW5_T94f)U&9%LO|Wo1%^KeR=%Afe#=gAne=9t| z{8rSZ_Jg+XNk8`bu{%Y5pL#rf&I14N)xbo+8P)2H$4pf`V~R5|UspiiLCG!nZ*L64wQJVQE6_$} z{vq}&{yX>n@31D%>j;c`1wr)T`Gr2ixcz4tQ}7)8f}e&@z%#et-&OMKuY;ZQ_c3~AD~Z>Yd&N8MO^Q}Bdeiud_B&deFYaUZh(=& zA92O>J?nV)U1~}!VOboM*VDMSuUmN3$9h&f^P2ZpU z_yA(pmofjITA1@Vfob{yMjQ__uHXQMxE~mEp-q8%0df62Ylkh;N4OLxuxt~ceNgNP zgg&sCL;GMpYY7xl7L=NE&9_*hN*)DWwPp+v?G)EsxEJuDuON(Te**0RX|xLzVzj9m zgLReYXMAB-T>z>pFQd5VIP>#9MndWagvbA!dHT;1^XuUovQEOf(Di-&e?fi!XYk;< z@6L7K#pg*lx-*{7^$A$oGmf9J{Fg1BkZO2bG+fI(9796*{XDqVYyKXF=RbfMW2h~ePc6vCdJ{}c-eb?N*O|ln9P4tovU1jf0apY%L}$q?rGg|Oa7h%sgY z>B|%N_rJt?Af!;f4kea@sNYjZnDag<#RN>cD@)gpQWqF!-rywb2TTVXr;mWO$s>hr zfcis%7WV`?m`=NZ=`4NBj+(vYHug>b1X@}fSm*m0>^kz46w`l5 z{Ws8M?=@%YS6R%H=;?2e_xrLQ@}27;y{%WZ+t@?0HP#B9zFHV}cr^F$(R@FK#}$e;!gPo(#(Ym>&_fL)UMDc>t;WA8Qy4Ee9mqbV zA>2nqP-aAFGdGDj#0eLeLqOX=nm%&~=_|;gji7*WgoQj7Q^piAmQdIVgngileuBzS z`Uql3=@_gjL*KPx^w2KQQRR*5QX`ZW979g_r$|ov1HvO;qFw(v_%L?Q(}(eUZj9xj zFVDf@McCLp3k&bUfs{JcGrvS z+r$37+|wIzKW}0AF)SUoz?MBzM2{~=)=qY?W9?toPO`V%%6Q^Wpri8^ZGgXI%;B@t z`G3Vc{&#SmHGDkT7cjRn8a=(8FUjlPceL)wGUryAGu5j!*ID2-T^xY1s7uuC8P{*W zECa-vA7Meio;Bv;tT7Q|hLH&F1LFDK3MJ5%mrR@rN+f3EsV{_SV?I<1Gr^}Z8E^^{ zekU;Lza$4{Sx;y(N)uDjT9}Gu+(10*3no)0r0LREpo@iE%7lE%gM4Ew=9^%lz=m>w zzCw{xR24-^m9XDco{x^Jv1lrDMOmIMax?Z5`|l$<>NN@b-oCW!F@Dd*{RucYJqZVU z+V$<8hm{rMc&ygqGX42Rrb^H=UJV`A>(D&E3a2$0!+(~&y0o8#rq0iC(eMq%`Tq}` z+&0liK>U*2J@(L7zmGA2`z8Df+`GFTWDdb0*jRmri@NXNF#B`wKk_r~7hb_htv^Da zb=kexQ?;-m90N15txuMH-#^(m)Yts}NNE~|Vm#Rk2475bVGe-vGSQx&YEPNK-XW9|GcnW~!VNJJ%6`Q`I+zVy zqNxyVOmios%qxTiOw4^RK{8seR~I_IBeJ?^;)xWJFt2Sk;%MQl-4lN&lT)3aXY{qG;| z%g+RgMb^NB@I%$+Bq4$NcAyDnU1_`Xq7N^EdI0e+YJVcj0rM%e%cas^M-s2+Q=Eu< zSB|++kM|&nBPn;8@;Js?LCB#lFY1ORaPJUDU4gwt7T8}v;D0)Ta)3I4pt)Eb%yW-0 z8_SsDxXYMhAHu~{>Hz6Mj3W#~Q%N}L3qw#<$hDvG1!)P#5fi?JF@b+%zTYdbW2~;g zzB$)Vm~)7Y z)<$H6Ho`)**yrdR0t3&&Kj!XKJ`T=HW3q-=wTD-uX zprQ`=bh;-dQrs|^#`vA=0P5~R(s4dNn0k8%_wb~WFs|9*OH?Lab05##V3dlnAm#}8 zW4gc_6S*Fkpo|#LcESkbbcfUJFhCumH`NK(ezEm#%QrF zp)U6fMo3S)f(-WYNKLU|?GH=tA+8`i%ow2|h6oEaLP)3~<%1pq0xuvan7w|&j1U-N z0Iz`4FtXSLm2r+B6 z^G_>cnBQl|SfGm-^rSy9i2HKZ6v!~L~W3&XvX@+0(EiB4W?bMmb!fn9b~l z5%d4dP*`BWG1m6VGDk+bDN>V6kq~c!xR@)fPiBD_+Bt!a9HO7yr6tc zw3lF_n=!zhHJI&e!DMR#Mmwr7*jkF#hD(+>+eKRS|mi-Lu zkeq3S*yJmW8&Jo&iyzas{|DCW_#=*={VQ|~_Q1+jn{kIeXzZ%c9hs8#eR)0o0q8xG z%th^};NlsF@kAH&g_zS%XoUV?Q;f%R-=9OfTshb7tBIrpzUDg3a|O+o#4i!CKgah4 z_UEsrV6rAzqVa0tois)nFi|Js{E7F*ObPoljeOmbg}D~S{1$O%gRF;4;YM6?k@zD6b7Lnm+~OnOQM`?SJoeO zV_jc2uKymC1#ZY-p0J=y?rBn!U67XIO8MZ1ES{57;EtqpD|iQuH<@7n!LJ1sLG^%pNYk5JYLP^F`s`I zQ2#IFKA?!i*L8ed&-WYnx~YUzj>VR8%(q^{OlK2DT52)ab`?EsrD$Rt;5F_AO6#If zR2`1oiXdba2O*QV&!e3{P+?vq3bP|5%4eRfpgiW?bF&ULj zaVV>gmgGPoZ4CM45hyN;K}mTm%4mx#FXVVZEbIJ*&>ldYfVBaNi$hV)I)ztRmqbt{ zZ60N15y;4NM=1RscC4AAqyI5f&%6zFop)&4`-HvzcEFc0jrkS6Xzj`k9h;Qnd1Tr5 zDc_O|}$ptcbb&#h7KC(CMZE>inf#=gUat%=@pvVmq@lNvD6-H4&i zdglFCp^I{%wTU`FeGzJyBUr^ep^9rsDCd5ptTG;@6>+TR8+DyZuSTP$JPp@Ml2Ob4 zg>}`m8`Q-x7C!-1&B3f0Vuiri3$SK9^EsoBp{Da!9M}2~Cv`T$$o43FBCepYu+YA? zwpO{nU*6-(xc~9s{+4IGNZy}jF5w{cfo9ehDvY8&;DPZldyG&P%tSM{KRu8=0cii@ zUSN_s{CHOtru*uE-byU?RA7Pjytz(dy`w~;#f~!KTh+Wk*9}K5A(XtghppfVMt8TYi4uyv&+o@1Y^~AL}hoMMFv;S`xj{66=P}C>IPco@gG`*UnhnKx+R+I?S-JRo*oQ$cA~ef z8J$h_XlbbCM^~Yx`5J8km1u6RL>ub{b$8dIx3`{g_qFJx9BF7vMR|1;Yy1ZwCfN>l z?x&$|x*u9bJE3u5Gwbhfhq1*8*n1eVZh#ANOH%t=yBl^5Psr=NjGb>DJ3p8?ohLpf z+TMcbQBR#jbe68v3apbamCC zqoW2btQS&STS%WkDsBF;2#vOYv!@R8eOY7t@_wAXxCQ6*wz9V85m>uvAUM_%d1c{f z=%nv+xK4R&womB?^NeKOMb=%uB_5a`>v(Oh>zd|NT|TDSBYYq|jIzKBLvijH=3Zee z$(uGq#tr6CHz=b`u{w?RzHG{X3Sfx){qb60lDfhq_Y6}!&NcxHtyq|Az~X!(=1H@& z^_ZBh#^?ldg2zhHH(G+m?o3oR#v{8dfVF>}5X6`rH^%N+x}0MD&ZD?!c7(k(4?ySA zAzZOL1AA`+_|blu%-G_R>dgF>?i!8ZNg4C9%#+vpugwFC^o7qbhG3X=ZQB_~P{;fN z#s(mtaYAYS7)_)+V2_evailyLNbx~Wk{5dEOBl!vMjv|%_ZBg4t~3h6j2Rkd>_BIG zHriS;xTYtfygU-wd48;?;fgTkFb77MGRL0#c(-%7Y5t-tQTwZ^*C8NH%ugq{@s`>pH4Bq>-fAhB_U*-Fh@%gXF1LHI8uZ@g0ZtU;l z-n_MhF1=i|l%=9EKMu_qk!VN^M0-LYy5a-TM;b~9#zb-$bA-b&&+*E#M8@>QFs3gU zN%3B+=jjMak|07GreSH;6||CtWyr8o@in3Xw^S?-6kTj8UqnE%0h=uhHlp zYJF>Pj6O{nud+@o^T4;v1H<>w_;)WBsb|kpKbT<8!lA~EQVwFrRc$8u7^0efh05$C zRFEpEH(V9Rto+8h?4;VN^!jTR$+*gX8D)$sE@9k3UQr}_1%@KGnEpQc|E@M>=8HXi zTYtH3&uF#A@J!RjiA8>o{H(v_XDzSOGSA68AoGCC12PZDJRtLc%mXqH$UGqPfXo9j z56CWGa%2vk9!9G?F)bYyh5Sa@C9cybNt^we_ULyP-uPb3B%I( ze}3+Gsx&5kVzkyUSB>lVl6l*V!Din8rh}VbjK7Ql&@BRaB-2UBvz>V8iD3tCp0XL7|?FXjb zxIe|+W?1`6#%~(F8w;#3$I@wc-rvnX?`}Wv=G*`B@jEBr*6Z(_faY87|IR0z`X%Gq zOXL5(bhvW@m)`$3G)ph;e9;_pK$y5?GHfu(B;#`=YQGw?GGrG z*Q`vcc>T|euUym2>u-O6+I(;2p2Tmt+xUj%`xg^%`#9gaKBwXdtlaC$42f~AY<*Sh5daZ5LDS(|@-(Rk`z$5*Bg5aSze`Ft@YH^!Uq7{B%V z?;O8%O7A|t@^}F8fbRVMTgR2|xW60ki0g0sB~BFIf8(87{}SW3e&csNE@tz_-LBl9 zmUtok`zqr%W=mWmexH_ft@uw||9u}Q#{~sG~=BI5CmtFsN>-BdZ|1$Y-V?6ba z&lgYRhWrxaTGzi@yts8-`;PHD<>#%}OUvu^Pvqryk*_!2x^w&%k$vljEq$uEWaTTx z&E8G^Z&86|S zHZFbW(hZ8?>(654dTCs`!KGJPD+9|%>87P`mG0z@>zC9zF~iN$=iheuvf3xUKwFHj zOx2Ckq^me>OCNvdcig<_*QOf<%|_pxbgkctgZ~-@%UEM&Xp6C zZd|zhYU#dL#y8wCzBH{X<63u&FHP{u_#MM56S#E3ozt_TH-G+k>dI&Hc<1!oIze|% z&#e=nbeH?Pc>*@vW&GwJsP!e|cNxC<3E%nj#RWHh;N5=S(i*ii2Y35bd$_;3J&iE1r?}DwB^Ot!1?!R7~v-Aiztek%5 zQT&3tPyW)m%^d%N%kTU^`5k!%K%N1427Zt;u%0X8&q&)z|E5^O|L^{fKVB%u zGJVH$&^xP_)B6y0N^imuL1#XxVLqOZGK(cRUh=p7zZ40Nn_D*y4@N9SX@M`w<@k|Q~3yDfjOAoH7tUTV_()i2% zfxiEDaA-i$+Sa0|t*ucsG&L$ZyLuJf-2;lAo*_j`OPgY#zhBWmHlpaA7`=mT=b2mX zUHq0Wxc|Y<4#jYHm!hq?<(cfv%yaJU?zI;U4ROlY0Q=00aLCyj+5w)h5B7&IkKW$) zu(vUS>80~9Fwlj8k-?(7hkIpiey&bSYx7f0y!XcDrf=o`hbP7q{cWv3Pm7HXG`eIw ze#}@82mM^Iw|7m7!j=k{}lZgY?COD82hmCEe z_+3vqp6@Eg`t~9`-dcq9t%Z2Ey%@orHE3$dMO&Ex8Y?y~QRzM&kD|3&2MrYt$cT1= zrHMYST)8ryo{?+WKQQ`}zP^!flz&DBhZJ3{ZLb7)cvYyHUc%ALSZwSl$EzJhc(NrA z>zZ<~z9Ab=*Jj|c>Qp>=Ego;wCc?Hp7sZtks7_Z$P3qrKo4N`0nOo6Vz~55z2^xyF z^S7NqbA>fB66|4Sq6crUfU?G>?%#BDbbTZI-^Y1xsH*zd%-VYVu%9b7Hy81~3-Cls zCe}8l;Yr@-6W3y}sw@Z(7kS~~Ja;^s?T)uf17UMD0og^q$d6G)M!*M1^LYo^LGPe2 z@;zLQ{}i=ppP?>iBkJ?EqNPL~4W;(*aWjFHmHlv4b?pbEBP0Jjey1lC12a>Kn#!x2 z^(@S0lv5({K}QLmY0APAb!m8_Iu5JLL$M~`6OU%vVQsoKUdeXEpNhP3pdtbno6?ce zR*6Rb-qx}JTuU`UX_N-CeYYXe`G1h?_9tWq`~^jke?tYIO-y5_T?sd37lu{-E?`O`~Tc{2@C{?s)$sTtc?&m78*#ecWvuJ@S98zVueJHLx^|UiVUv<$n#O< zZ#aN>m%k#)?!S@b^xw$ze+NZTf5p|5zvF897PJ&G%OdZOI#D6#EV6B+%%5cuN7amEs#e<1Pcrfk)){vfw zx`;IqT6iGxG@gpNfM2IsU~9hDxK%|&XIze3b83)QcZ|ahgkE|V0T+LZ5W_c-VDAwE-zke@0%wyC{i!ALYp(qapts(ui$07uWut?)I0)#s(F`!+oTFiEh9D zk%4}NpwWQ=#l+Ci{|yKZtT>(+jNdnB;?Zl-c(^POt8$&NI>ihR#azTgk!SEg#7R6D zdJ?O{wD5L@3yf;B8Uy;OtqUgmj`YkOq{{i0rfMRlFR8f$Vqkl5QllPvEwVZRMVqdJuw8ttj=TX|YFH9Z(6>7gNlm9F~z|AoMLclUQyp(%JrgBF+J9%7#Xfn%ubK| z+vrf!?<$IYVj~<5z(?l|`02dN=khW_4S$1Jvp*o!?QP_R5F2sCMz%iux&9RtB&?_Gd$iC8t1|5HXq*xG;~XC3z5g^= z4Ub1?<77$XaPD~j$yUt%dlM!VEekV>{HZ=g>HLVIZ*EpGFg3S){}qapm|Ve{LvQcRiYw-1_kt_- z@o{MklnT7?DChlwc=AkyChiYb$Adw~aeufbw9DfUqyiSD+o4v1>t5JkmmN^$oBsma^npV9_lyP-q!X=S4YPk z_dh`1FDolOsgV|n7r6GUqD+4<=`tRSJWoC+zlW;e!H`qfo$EhSH!<+;0A>~abpQOb z_uto3A_Q=*)N!=im42ui$(BmwXOyAl~Xtq`JO^{D|F%54S~m zdD)SH!I3-fe`MtUM5d>dd{hvOM{}I<5M}y9G3W6>*lF_n3H)b>3SLbxLvnkK{^;y9 z*S1MTANjp~VNOxAIIgJu2l!`lyj?LmT&gAQ0LU7qIF?f(YWx{@jJ!)9~jxGzcv_lIiW{vb8{BuEu6Q~sp3*11gccaMAy^$`zwQ@vjxe<~GI zlYNTukxtHkr($I2X6jH(jP)sMtMbi*%|C*V=8N#<{Rim0O1b(PqAlJ)hR4T9jIu#h zP22X{@4uwHOm9<$FIJ_R<9@E8KjGZ}G(-*e1*(#NPGM7)>tgdj*Xu$b>AwpNOmSa8 zohfIkM^SQD`PoeU`xu^ww_;$hTQPVW4Gs4yy1HB5jP+87pZ3e}BOe87{R+Vs ze~pMsuOY$qZ6t(V#MR2`E4SZ&dUUrv1^Eb=?a>e8*_2J=RMgI_Wlh2`n;Za5Z@Yn-s(e{J> z7hZ?=S;0g64HA}rg(%b4k>Gz4r9}nqx8HwaaZcLXnJ&D4p&Mx8f$-DBt~%}yIf>_^ z_2E{OkucEJr|9hLB6WWbbt$^3x3_UE>7AWX3`{Srzdc-kd-}Q+UDU<9dV9W*dIkpm zEiXN!FxceJ@S+^`J^w2FFZ>2Ulttl}e}{O_V<^eZioX5+lM8dxcI0{CPtW+nDr&3izXH{9Kij7087I#BI}}}Ao#YGN|5u=1>Hx)g zi5c;(`w(XOH$<3yNZ$WDVyr$vyxm452b@81e)hH7??1n=I3qaE8(zsa@Jh0QM}n0^ z?nzb%%=SihNnUhqLxZBKzV0hgO=E+ikNV)?-~iX!9z{Q&Ti;ip!R|gqeqLH;c;H$1 zIqX5O<8FjH?Lmn10ff38Mnw1p6c%Lt|Lt6Pe3jLi{v6vnZO7ucltnO5wWCw2Ok0(X zIyge77PL|kRQ9k0MUYLDRT4r%5(puLC1g(^`$j_c^=9AqeYs0+?!MpLC3k=3{Q^O` zplxTSf6Q-&A1~)_-#PC&-}%mY-{*M_MehFd+gpm|`5{my9)axI5y;8dQg-by#&3k8 zv#z{ZNpXjgFby_N`c|Xw6-t_C6i;ci6mMx%l#dfGB9<|7iJXyBU%ty!ay3(4ncs5$ z(t3FNyopmj|Bh4MWG9#5wC^&6MS7vWsVdFge?eb+v5kCno?8n?@H#lj9Ou@-6|xTY zs4vi7lx~ojOwZ~lF4NN7zMpB>&+S%5LVXYtRy6IujQk%TmoQ4g7GzS25x>RcEcPSS z&P~mZ)qQ?!F}8SlVC%N|*s|3FTef?^(`z0M`@e(M&gN)$|M~o(P~){@a0b2yXTU1B zSPNQ1eR&@)igWw2<1i$bpHPy2a*O#sHpwU~7RuoajEG{XaVf2jx5uCLpUdMjBB6x* zqd1q|-_O)^U&nakORvWHVfW|HVdLhR*sy6fHf)@Q^&4km-KHmS^z=&f4)%WT?!Qbb z-l$Ivf-`6}oc^oeIL-S10URM801;l`ri7ucqdi%vGci(?j*;EATd(!>nU)dK{E#Zt z_w}F07cc_;I3tpbGaAaHRBFXNrkl_*ZLRI`!54R9*S?>@bL%W@^qhnBn`Tizeu@p7 zXCWwT8(}ismG1r<4C<#<#R+Ct@LIV1--DIz18Dr6A!~u~ZO~+$MoCV(OrbH))SGOK z&S1S|Ml1P4_k-rd7>%z~srgR-xdJYup2|VAv=0~j@kI@l6^F)k6m5uFfgz8vd?quvX!d(T{KWyha}t69!GsDf@i> zwf-x$Y`!F?=UB<&lCzUjQwO6Gk0SKaYdC!LNqkE4XUq1PQ~s}AKNIV>(%eZ2&}dEa z*=mF2UjHfn(op=R9cs(8MeKxwy$7dh?Vc3p7CR|?Qk(QR;dL{A{;?mc^FTev|9-0fU-813oISZR;-T9E_&S!^SMSD-( zR~jQ>ygKX|q~2jNKsoQLRP_V5uNZf&R_f)PM-Q1K0n}r?OwAeW_Xfp9@cH0hw#`VdaYi($l}m2CY$1p zx%=<1D4A(<(rcGZ&Dd4EcTH(Q2KyD-6C(D&dC?P=Fp7&JcfghLIUMEQa5e_Q*%krx zX8|Ln&~_JLq%IdVH_JJ;%1RAN~({bqTUNPOW#0J`tyj2c^;t`pMkgk zQ`q;#OnB}5DR%DqIri^=0qZH&2?*Wd7?%vKv05i+Ua)iHYjgMC#ro`KuuU*F33rV# z{fyZewHK4AM_`Sku@Bz~OVke7llQ=te+15IKe$@X!POZK^u_^$slZqr98xY+qH?r# z??FMu>&VVqh}4XqBO&n_ghxMvz;g?5^s6WF+5WlMyYHWH(&yiB(r+m|KY12DA?sZ{ zanBA5<)UU9%Spl|ziEGw|C6*&5dUWrjs8)Wch+o6I0{EjC~P-_VW&LQLNWRz<#Sfb zkL?A=VdtEJv*|QkZRdcVRG5cbA?Qm1hx0ZP)8-?Rd=9&^0DUfaM)=daMoUjt1bbK+88)E;cyV{Vk4e{HEZoPXgZ70(|i><*=rCT^IJs5yoTu5 z6^Kt*kCc=>$jms78#hkT^WaZw=Njxe^a>J^PL0X*+&7gvA)_ID&g%Lf@ZU&ywUy?V zN&L9Evn)za7>2Dfj^=$Ht)r!IbeF;2Ujge-6|BQmunkwj!fSw8*bf=65nbJBXlRZ{ zb7KNpi1%n9eyP4D3AHr|xLFW{)3m=F_ov*jF*RLh6wlL6iYT7t{?GbPxCjV$!i0oz zs)tsX+Vg7+6-lr)<-s;o59?S59KtR*$GYL5I!{ixA)&7rRQ3}xF)DCdLF$N{nR$rw%jCa57+nC+?Z%DtG2Y4 zwW$ZIJ3G1xc}3;%{LI4e{-T;|r8TYjXL`7ee^MF8=4c2ld))H`<-{W7;nrb7IO*3*$k5zwXC$zoz?%+x@;X4xHQL zBDg(H)8j@LPK_gOk1LHbjliApW_4Qg$=)FQf1TE!pYwNgMpODC;wcFeRgozOXEYMt zDCTmXsVpu1Dn2QZb0+P&@vE$4T+GQp29+79(MU;-wO&uW-at8r-@wq&F9pIeMtocM zBqe-OP2Br8^-k=~`lj8leI4O#a=C0?MQQQ5vnkhfn{yJeqN5Z`h3$A<){RRVKIEc$ zhz5K}JM$GNT&Ar=HO7)-Z zzm&L-DWhClW0@qZxp{|AR?6gC{nhw|s0kj!rSRy?#C+1R{E}>WM>;Ny)}oIzA>Ad1 z(2%hKwW;r-<;J_{t5^ko+ZOZ@PoI%|8TIu|U+SoS1>q~x_u!jj&%RbtJj$A$c&~x} z{_RI{Q}J(9|NN0M%xh1@9MVQCC=JF7#9h8z9)iV{=dp+AhN7}iltp`@B5D)aI^yJ3 z(EHz^DeG<0rmV(j<3Z$QkPoe`#|QyL4q*;)j<1!6;j`|Xrpv;X#CnxrTi;042i*1>Cz=b-l@vvJ88QRjL{7l# z$P0M`RdK&Zd%+6y*X$*|LbPLababh~tYdV9QMtFTRjC<+O8xz`isI^}-G!Ljor!r> zmocZn2ajYQz|Zo0aD1SouFaxe&2w5F7;%{ygUv~oY9=MJbe%17^~lTc9q2m1$BZ>!0{0@8HM;e?Tn!v{Yh zp6TVHvnWw=&k&aJAeZz6y_BzZ+jYdl*cgGRn=vSdN#nw0CfT^yBxGcwt`BlAueT%~ zTZHt}i&1*@O|)dc4NguVx;lFIX-W6x-hZ`B{=Kxi%7#~3(=n5@0W*nbe3W>u1*Ct; zlJtd4(i{=N&I~#Y-`c)eFJO$?A;v|VuT;?PnH93qk#h7`$PD-`$|BxCW6oC8RAdfH zCGv;e+ZT()i#{iwb9Q|MW)+?)%~2Q`)4rTfV1sSV@OqVFtdn{ZVFeLco|P z_Oh5%jNNKt`ddr;|}R9E^%e1?dXxZTt<|5t_fZ_|plklrc`QSh{dgPPnHt z>DY@%_g#$qQ1T&V2XXD4!S3xBcelhp$GMD0^G{6iqYtO=!^e%uGSWrb7aA z93j0*w}bH2+xOq78fCOv%8N*Msv*94+H@28@7EPw=}RWQFrCKW#_5+)6tNs_jm1^& z?I*QYH_k6Ri^o}hmbmf9iDSOfQJJYF98pACSa%Z=KB}}@8NRriQ7gx3pCJ5=*3563 zN^fF%+DfC-{9Yr@_$6feEk<7GGBlJW4Y{|U+g8)EttK3v<>#@X^c*&GE~2oz=?Z_C z#|#aP+--yOesGu(v$`A=i`TM793^RAziBKNHPqW2P!O{Xd6zyyVfcC!$8AAfd5YA% z{n6&CMq!2z#*&UhkaP?J%4Y{!t20>~Q%v=`n~=1^a^kZzv^TQ+m5TT^CCi}@<~(Ke zTC3DCZEba7!6EM>@YH`G$o~(7%dJ3uNqnz+`;w080uV2SfcJ@CSPg`3#7If1LTa=9 zR89PoinJB1v9DP^NzP}84RJQ> zx6MX&L3F8m`$}H_m$uL?aQdwzu8DlOuofd}=P@c#zM|F>hom(!N-b%p)r2F;Z}DK$ z?F&fLJT^8)93aIEqPbyVB6A|rg_4KRz9q-RV_ zeCc+^C718JW$2Ib#( zbo6hGzZNNtOWTN`^G{>%fqB@xWi~$iXa->l+f*W%aDhll`LWyhPgo6%k#IeubYP`5 zitsz)863pfB7yjka$lH91Hj3kI5Y8jdue&)iOzw6l|tGxBofIB{R1O!l$BQ>x}KEM z7?IpXIyc6=_j@0bntzI*L?0fYRO?H1=GGckGZ{%2?PUWCgzoO;GGQ0;HK zw1aTn&2U^KTr}x3pz;)9i1Cosr=cwQ3UX6ok)4u^#R_C!wM>$nm{ z7@W@>!aSdZ*A5SC+OYunr7`Jtr{V9+78PS6Jk!1ZcQ8)EqhOz4ENx|%tg#1RO*jZg z%pTYhcf(nD7-*zNXCM|BN{5Zt3EogLN;tnK4D&_AC3@gY2x0Zq?=KH8#EBEHVFz(* znMD_G+8xFpTO8UuSmn32&tk2Fd4sgImi|hATh>{Zy)X=pl1s3coF_X&cw`_P^&zl! zm!P}(9Ihw*3u$r};Zpb#L_~au*!WLr{5QkfcRBLQW8!rt*+01Bjo;Zm%cGH|6js8j z#eKgw)ufEr8#3VNEQM{bnsBXZ*hgvz+v>qM#i&iKNrb<#mV%0kC|pZDh6@pU#a)A( z?GuELsR{dW$2$LP`>dALM0|#kI5DGehK<*<)!bEHX&r1Z*hbo5Aw0?==R!t!T6<3g z;ea_Pp{+m+eWcCXWFJeV@vv-z{BzoUG)%q zJ=HUV>hqv_mrTJEEL@=@@Z|O%7N?j+#-1trzkpLr<@qeeKzM+X^e9@LmeGpFXSCGT zZA>XCOb;l|=?yE%7Zns{NDA{328xSvb871vKkgqKeoUdH^D4y0s`OgQWpACGqG7yi zExl7earbOa+27s$epq2n-)c?{ULC2&vw|jkBIyC2)=hrPHVif&pj_PtH?w28Ev?<2 z>^UvMy1k`zqRQtVP?+ zl^CQvnA_ro%6xxRR#aY68797`q+FQI#ohha(6|^$^U&1R>a(VSwAz&S&u)stEYdqa zTjV!&hGJi5hJjOgNnJ^CZDH6-6kc40>crns-oFNo#m7-wR};aWjksT)X{PuPN#?XL{9WCZ11US~}8{xym& zEY;8nUuAQo#;lbTqbKs@a`g}0>mTKEm#(Ty$K#w3%pm>o z;*ua^zfrkNNAqCVX<|BUIz~+AYvi(F%0+pU4+Cs7Fzo0mBt2mi*v7)e7QI+v2 z#dU)eVB9@_N`|`6JX;k$rBh{dz<6#;sMY0S1Jib5l=89 z-DO9Uy%!_H_a&4>yoHvA!V>rTFLZJW9xn97k0`JIr+i;mpHlRy*2tc*A)OA{0OfWP z8XviAh;n+$>F8XDn$78S#Nn$IPv>3UU`jr+5II3Fp|0rS@ICdnm$tq{8p&UgMte(j zypcP~pUdY87%rDLWjrpQ5z})aQ&Rpy&mXJNAkE2CNjjtNS7)Cd&JOw=3NE~jnw!CN z4B+nZ8EMFC>`gw3o}{DbE{w8_iN#M(*((au(^*f}b`3c?Y*VSg-#Hl|5r~d>~B%L9XidU;`cFKPz8RaD1SBkCWlwYuM z_PCIE63S26a|3F^Z$#s=-}v~ivVFMzAF*cb3|xvi*yUcozOUi1gK{i3zO+T`KyL#l zRbz6{*$>JsNcSTmpJlh}=kbW|Qi`W?3WLeY)HHIg96Y>;a;eAg;rhoYkBdukuV14O zFPeHc3sAnAL{ zXt{TNa8R7>B<|ck-o45ix!+|c?Sb?9E};4}bPZ7$ERRD=X|AiF;Ho1zYa8hamLekd zY2xE&lXh$YKHl?7G`8h`;UpZ)Y@ry<&Hw2*8g>I?<8^GX-Z(p9&pZVOX`NAZ251c> z9Y6`XT77Um^?Bl+e}jvcmLn+m9ry;k>!@zY{F1GEDqbXQ#kbY(Vq;X&FF54`i>>W> z<+j#5m#wz~j$w*TiEkB*R-&2Cxm8!k;Kt2!NX`mq=;zii*Hb)dwyW;MgWp-dk=mGw zKgEn)Ht>pdv?biiYj3xX_l%8>HmYk{a)vpL*$Msprez`-kMb`z_TztN{qF7kZ+q`z zP7oKigyp}8^P0g3n1>k7R}V5AJjhhR_rAt{$Nq->Eqe`1K(Teu%)fJg**NSGvibi@ z;xP6cxRPQVokaS*y7tzs-t`p~ha1X8)tnef9p`FYQ&Y`nV?xD`RdiOB#r@syvyx&M zT0cp0{->AVqXVzR%SDFj$~tfT)l<% z=W&;n86^xstsEijmGV70ht!Z8l$v_{Su_-$YjVGSPkq|(96Aeet*7R&n$~22NW=(8 zJFHL&$tcDo?dniZ?Z!<1*HNCh|DJu2TX1!V8%}4o+pB%0q;+Mr;SzQqW!HB)N1A?=NV zv5UGsw2d?tSa@xso}N-=O;c7?b7#qRxlZr{vqMc|4dY*14ZW`Nz4aaY8w>rGy@s{_1kebYzW@LL diff --git a/src/gui/res/icons/256x256/synergy.ico b/src/gui/res/icons/256x256/synergy.ico index fc2e41468ec60a88e0da4194f288a18572f3f36f..9e3d57100883a631db42ac5c9ef323228f84b43f 100644 GIT binary patch literal 24277 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 z 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 literal 287934 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 diff --git a/src/gui/res/image/about.png b/src/gui/res/image/about.png index 4630bd32a5d36f7588a3d8b4bbf9b8706e80adec..66307bb077761806aace467307b7b7ae93e58a95 100644 GIT binary patch literal 5701 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 literal 4941 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 LNkvXXu0mjfO~zre From 03b8788660af08290f74cc4812ac32f29932010c Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Wed, 5 Oct 2016 21:53:22 +0100 Subject: [PATCH 093/101] #5640 About dialog tweaks --- src/gui/res/AboutDialogBase.ui | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/gui/res/AboutDialogBase.ui b/src/gui/res/AboutDialogBase.ui index ba18e309..52d8330f 100644 --- a/src/gui/res/AboutDialogBase.ui +++ b/src/gui/res/AboutDialogBase.ui @@ -13,7 +13,7 @@ 0 0 450 - 300 + 350 @@ -25,13 +25,13 @@ 450 - 300 + 350 450 - 300 + 350 @@ -51,14 +51,14 @@ <p> -Keyboard and mouse sharing application. Cross platform and open source.<br /><br /> +Keyboard and mouse sharing application. Cross platform, open source, and totally awesome.<br /><br /> Copyright © 2012-2016 Symless Ltd.<br /> -Copyright © 2002-2012 Chris Schoeneman, Nick Bolton, Volker Lanz.<br /><br /> -Synergy is released under the GNU General Public License (GPLv2).<br /><br /> +Copyright © 2002-2012 Chris Schoeneman, Nick Bolton, Volker Lanz.<br /> Synergy is based on CosmoSynergy by Richard Lee and Adam Feder.<br /> The Synergy GUI is based on QSynergy by Volker Lanz.<br /><br /> Visit our website for help and info (symless.com). -</p> +</p> +Synergy is released under the GNU General Public License (GPLv2).<br /><br /> 1 From 176d7c9286e416ede12523d5ad6b2ec596f70920 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Wed, 5 Oct 2016 22:12:00 +0100 Subject: [PATCH 094/101] Update installer graphics --- res/banner.bmp | Bin 85896 -> 114514 bytes res/dialog.bmp | Bin 461816 -> 615402 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/res/banner.bmp b/res/banner.bmp index f5838d857ed2559b208458787c3977aba575d97f..418746c867fee0398e6a7497c19df880bfb1f8ba 100644 GIT binary patch literal 114514 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 diff --git a/res/dialog.bmp b/res/dialog.bmp index 4899e58333408c60b19861b738882e3ba81b43b7..683f4fe5e12d8f1df4a9a8d9332f51cf7ed5332c 100644 GIT binary patch literal 615402 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 O0uX=z1R$^w1pXhybvg(D literal 461816 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 From 742cd70f986cdeb5a4d6df7aa865857782aaf649 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Thu, 6 Oct 2016 11:29:34 +0100 Subject: [PATCH 095/101] #5627 Toggle fingerprint visibility when toggling SSL state --- src/gui/res/MainWindowBase.ui | 2 +- src/gui/src/AppConfig.cpp | 5 ++++- src/gui/src/AppConfig.h | 7 ++++--- src/gui/src/MainWindow.cpp | 13 ++++++++++++- src/gui/src/MainWindow.h | 1 + src/gui/src/VersionChecker.cpp | 6 ++++-- 6 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/gui/res/MainWindowBase.ui b/src/gui/res/MainWindowBase.ui index 5a852c8c..87144cd1 100644 --- a/src/gui/res/MainWindowBase.ui +++ b/src/gui/res/MainWindowBase.ui @@ -128,7 +128,7 @@ - Fingerprint: + SSL Fingerprint: diff --git a/src/gui/src/AppConfig.cpp b/src/gui/src/AppConfig.cpp index a6d081f9..9848e6b4 100644 --- a/src/gui/src/AppConfig.cpp +++ b/src/gui/src/AppConfig.cpp @@ -281,7 +281,10 @@ ElevateMode AppConfig::elevateMode() return m_ElevateMode; } -void AppConfig::setCryptoEnabled(bool e) { m_CryptoEnabled = e; } +void AppConfig::setCryptoEnabled(bool e) { + m_CryptoEnabled = e; + emit sslToggled(e); +} bool AppConfig::getCryptoEnabled() const { return (edition() == Pro) && m_CryptoEnabled; diff --git a/src/gui/src/AppConfig.h b/src/gui/src/AppConfig.h index 3d15ec6e..271ef683 100644 --- a/src/gui/src/AppConfig.h +++ b/src/gui/src/AppConfig.h @@ -98,14 +98,15 @@ class AppConfig: public QObject void setCryptoEnabled(bool e); bool getCryptoEnabled() const; + void setAutoHide(bool b); bool getAutoHide(); - void saveSettings(); - bool activationHasRun() const; AppConfig& activationHasRun(bool value); + void saveSettings(); + protected: QSettings& settings(); void setScreenName(const QString& s); @@ -118,7 +119,6 @@ class AppConfig: public QObject void setLanguage(const QString language); void setStartedBefore(bool b); void setElevateMode(ElevateMode em); - void loadSettings(); private: @@ -150,6 +150,7 @@ class AppConfig: public QObject signals: void editionSet(int); + void sslToggled(bool enabled); }; #endif diff --git a/src/gui/src/MainWindow.cpp b/src/gui/src/MainWindow.cpp index 64271c14..f9903a12 100644 --- a/src/gui/src/MainWindow.cpp +++ b/src/gui/src/MainWindow.cpp @@ -140,6 +140,7 @@ MainWindow::MainWindow(QSettings& settings, AppConfig& appConfig) : m_pLabelPadlock->hide(); connect (this, SIGNAL(windowShown()), this, SLOT(on_windowShown()), Qt::QueuedConnection); connect (&m_AppConfig, SIGNAL(editionSet(int)), this, SLOT(setEdition(int)), Qt::QueuedConnection); + connect (&m_AppConfig, SIGNAL(sslToggled(bool)), this, SLOT(sslToggled(bool)), Qt::QueuedConnection); } MainWindow::~MainWindow() @@ -497,7 +498,7 @@ void MainWindow::restartSynergy() void MainWindow::proofreadInfo() { - setEdition(m_AppConfig.edition()); + setEdition(m_AppConfig.edition()); // Why is this here? int oldState = m_SynergyState; m_SynergyState = synergyDisconnected; @@ -628,6 +629,16 @@ void MainWindow::startSynergy() } } +void +MainWindow::sslToggled (bool enabled) +{ + if (enabled) { + m_pSslCertificate = new SslCertificate(this); + m_pSslCertificate->generateCertificate(); + } + updateLocalFingerprint(); +} + bool MainWindow::clientArgs(QStringList& args, QString& app) { app = appPath(appConfig().synergycName()); diff --git a/src/gui/src/MainWindow.h b/src/gui/src/MainWindow.h index 2f0b2c5b..efd83dcc 100644 --- a/src/gui/src/MainWindow.h +++ b/src/gui/src/MainWindow.h @@ -126,6 +126,7 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase void startSynergy(); protected slots: + void sslToggled(bool enabled); void on_m_pGroupClient_toggled(bool on); void on_m_pGroupServer_toggled(bool on); bool on_m_pButtonBrowseConfigFile_clicked(); diff --git a/src/gui/src/VersionChecker.cpp b/src/gui/src/VersionChecker.cpp index 1f6980fc..4ce27433 100644 --- a/src/gui/src/VersionChecker.cpp +++ b/src/gui/src/VersionChecker.cpp @@ -51,8 +51,10 @@ void VersionChecker::replyFinished(QNetworkReply* reply) if (!newestVersion.isEmpty()) { QString currentVersion = getVersion(); - if (compareVersions(currentVersion, newestVersion) > 0) - emit updateFound(newestVersion); + if (currentVersion != "Unknown") { + if (compareVersions(currentVersion, newestVersion) > 0) + emit updateFound(newestVersion); + } } } From 9837c982cd2ff0ec89b9683eaabd6657868f858a Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Thu, 6 Oct 2016 12:58:57 +0100 Subject: [PATCH 096/101] #5640 About dialog tweaks --- src/gui/res/AboutDialogBase.ui | 87 +++++++++++++++++----------------- 1 file changed, 44 insertions(+), 43 deletions(-) diff --git a/src/gui/res/AboutDialogBase.ui b/src/gui/res/AboutDialogBase.ui index 52d8330f..01df3dd9 100644 --- a/src/gui/res/AboutDialogBase.ui +++ b/src/gui/res/AboutDialogBase.ui @@ -13,25 +13,19 @@ 0 0 450 - 350 + 378 - + 0 0 - - - 450 - 350 - - 450 - 350 + 378 @@ -41,48 +35,20 @@ true - - + + - + 0 0 - - <p> -Keyboard and mouse sharing application. Cross platform, open source, and totally awesome.<br /><br /> -Copyright © 2012-2016 Symless Ltd.<br /> -Copyright © 2002-2012 Chris Schoeneman, Nick Bolton, Volker Lanz.<br /> -Synergy is based on CosmoSynergy by Richard Lee and Adam Feder.<br /> -The Synergy GUI is based on QSynergy by Volker Lanz.<br /><br /> -Visit our website for help and info (symless.com). -</p> -Synergy is released under the GNU General Public License (GPLv2).<br /><br /> - - - 1 - - - - - - - Qt::Vertical - - - QSizePolicy::Preferred - - + - 20 - 100 + 450 + 16777215 - - - - @@ -197,6 +163,41 @@ Synergy is released under the GNU General Public License (GPLv2).<br />< + + + + + 0 + 0 + + + + <html><head/><body><p>Keyboard and mouse sharing application. <br/><br/>Copyright © 2012-2016 Symless Ltd.<br/>Copyright © 2002-2012 Chris Schoeneman, Nick Bolton, Volker Lanz.</p><p>Synergy is based on CosmoSynergy by Richard Lee and Adam Feder.<br/>The Synergy GUI is based on QSynergy by Volker Lanz. </p><p>Synergy is released under the GNU General Public License (GPLv2).</p></body></html> + + + false + + + 1 + + + + + + + Qt::Vertical + + + QSizePolicy::Preferred + + + + 20 + 100 + + + + From 42ba77ae049f2235ea49317d34d9cc330f6e7f40 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Thu, 6 Oct 2016 13:11:07 +0100 Subject: [PATCH 097/101] v1.8.4 rc2 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b3e066a8..731f03fa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,7 +18,7 @@ set(VERSION_MAJOR 1) set(VERSION_MINOR 8) set(VERSION_REV 4) -set(VERSION_STAGE rc1) +set(VERSION_STAGE rc2) set(VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REV}") cmake_minimum_required(VERSION 2.6) From 217eb475dee83d4e736e7da9b553df315598ccb4 Mon Sep 17 00:00:00 2001 From: Andrew Magill Date: Tue, 19 Jan 2016 00:22:08 -0700 Subject: [PATCH 098/101] #5183 Accumulate fractional moves across updates. --- src/lib/platform/MSWindowsScreen.cpp | 32 ++++++++++++++++++++++------ src/lib/platform/MSWindowsScreen.h | 9 +++++++- 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/src/lib/platform/MSWindowsScreen.cpp b/src/lib/platform/MSWindowsScreen.cpp index 1011cb0c..74abfcd7 100644 --- a/src/lib/platform/MSWindowsScreen.cpp +++ b/src/lib/platform/MSWindowsScreen.cpp @@ -105,6 +105,7 @@ MSWindowsScreen::MSWindowsScreen( m_xCenter(0), m_yCenter(0), m_multimon(false), m_xCursor(0), m_yCursor(0), + m_xFractionalMove(0.0f), m_yFractionalMove(0.0f), m_sequenceNumber(0), m_mark(0), m_markReceived(0), @@ -575,6 +576,21 @@ void MSWindowsScreen::saveMousePosition(SInt32 x, SInt32 y) { LOG((CLOG_DEBUG5 "saved mouse position for next delta: %+d,%+d", x,y)); } +void MSWindowsScreen::accumulateFractionalMove(float x, float y, SInt32& intX, SInt32& intY) +{ + // Accumulate together the move into the running total + m_xFractionalMove += x; + m_yFractionalMove += y; + + // Return the integer part + intX = (SInt32)m_xFractionalMove; + intY = (SInt32)m_yFractionalMove; + + // And keep only the fractional part + m_xFractionalMove -= intX; + m_yFractionalMove -= intY; +} + UInt32 MSWindowsScreen::registerHotKey(KeyID key, KeyModifierMask mask) { @@ -1355,16 +1371,18 @@ MSWindowsScreen::onMouseMove(SInt32 mx, SInt32 my) { SInt32 originalMX = mx; SInt32 originalMY = my; + float scaledMX = (float)mx; + float scaledMY = (float)my; if (DpiHelper::s_dpiScaled) { - mx = (SInt32)(mx / DpiHelper::getDpi()); - my = (SInt32)(my / DpiHelper::getDpi()); + scaledMX /= DpiHelper::getDpi(); + scaledMY /= DpiHelper::getDpi(); } // compute motion delta (relative to the last known // mouse position) - SInt32 x = mx - m_xCursor; - SInt32 y = my - m_yCursor; + float x = scaledMX - m_xCursor; + float y = scaledMY - m_yCursor; LOG((CLOG_DEBUG3 "mouse move - motion delta: %+d=(%+d - %+d),%+d=(%+d - %+d)", @@ -1377,7 +1395,7 @@ MSWindowsScreen::onMouseMove(SInt32 mx, SInt32 my) } // save position to compute delta of next motion - saveMousePosition(mx, my); + saveMousePosition((SInt32)scaledMX, (SInt32)scaledMY); if (m_isOnScreen) { @@ -1415,7 +1433,9 @@ MSWindowsScreen::onMouseMove(SInt32 mx, SInt32 my) } else { // send motion - sendEvent(m_events->forIPrimaryScreen().motionOnSecondary(), MotionInfo::alloc(x, y)); + SInt32 ix, iy; + accumulateFractionalMove(x, y, ix, iy); + sendEvent(m_events->forIPrimaryScreen().motionOnSecondary(), MotionInfo::alloc(ix, iy)); } } diff --git a/src/lib/platform/MSWindowsScreen.h b/src/lib/platform/MSWindowsScreen.h index 7e734f85..4d947be7 100644 --- a/src/lib/platform/MSWindowsScreen.h +++ b/src/lib/platform/MSWindowsScreen.h @@ -215,7 +215,11 @@ private: // HACK // save last position of mouse to compute next delta movement void saveMousePosition(SInt32 x, SInt32 y); - + + // accumulates together a series of fractional pixel moves, each time + // taking away and returning just the integer part of the running total. + void accumulateFractionalMove(float x, float y, SInt32& intX, SInt32& intY); + // check if it is a modifier key repeating message bool isModifierRepeat(KeyModifierMask oldState, KeyModifierMask state, WPARAM wParam) const; @@ -266,6 +270,9 @@ private: // last mouse position SInt32 m_xCursor, m_yCursor; + // accumulated fractional pixel moves + float m_xFractionalMove, m_yFractionalMove; + // last clipboard UInt32 m_sequenceNumber; From fcd81530022a81fcf7d8bae626682e7c7a34f041 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Thu, 6 Oct 2016 15:49:44 +0100 Subject: [PATCH 099/101] v1.8.4 rc3 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 731f03fa..fe16ecbd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,7 +18,7 @@ set(VERSION_MAJOR 1) set(VERSION_MINOR 8) set(VERSION_REV 4) -set(VERSION_STAGE rc2) +set(VERSION_STAGE rc3) set(VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REV}") cmake_minimum_required(VERSION 2.6) From 0e209aa903a818e74731ebf93641e4e80f514d28 Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Tue, 11 Oct 2016 10:13:50 +0100 Subject: [PATCH 100/101] Update Changelog --- ChangeLog | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/ChangeLog b/ChangeLog index 270668f5..19d10d50 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +v1.8.4-stable +============= + +Bug #4041 UHD/4K DPI scaling broken on Windows servers +Bug #4420 When XRandR adds a screen, it is inaccessible +Bug #5603 Activation notification depends on existence of /etc/os-release +Bug #5624 Update notification sometimes requests a downgrade +Bug #5329 Current date is shown for build date in the about dialog +Bug #5640 Synergy branding is inconsistent across platforms +Enhancement #5617 Remove redundant plugin infrastructure +Enhancement #5627 Move SSL certificate generation to main window +Enhancement #5628 Move SSL implementation into core binary +Enhancement #5629 Move activation from wizard into new dialog window + v1.8.3-stable ============= Bug #2765 - A letter appears on macOS clients when the spacebar is pressed From a6ff90794fbf9a6d4a0bd7201f1443faabead8fa Mon Sep 17 00:00:00 2001 From: Andrew Nelless Date: Tue, 11 Oct 2016 10:14:18 +0100 Subject: [PATCH 101/101] v1.8.4 stable --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fe16ecbd..fc5a3311 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,7 +18,7 @@ set(VERSION_MAJOR 1) set(VERSION_MINOR 8) set(VERSION_REV 4) -set(VERSION_STAGE rc3) +set(VERSION_STAGE stable) set(VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REV}") cmake_minimum_required(VERSION 2.6)