diff --git a/src/gui/gui.pro b/src/gui/gui.pro index 0576f266..91352f3a 100644 --- a/src/gui/gui.pro +++ b/src/gui/gui.pro @@ -50,7 +50,8 @@ SOURCES += src/main.cpp \ src/ZeroconfService.cpp \ src/DataDownloader.cpp \ src/AddClientDialog.cpp \ - src/CommandProcess.cpp + src/CommandProcess.cpp \ + src/WebClient.cpp HEADERS += src/MainWindow.h \ src/AboutDialog.h \ src/ServerConfig.h \ @@ -86,7 +87,9 @@ HEADERS += src/MainWindow.h \ src/ZeroconfService.h \ src/DataDownloader.h \ src/AddClientDialog.h \ - src/CommandProcess.h + src/CommandProcess.h \ + src/WebClient.h \ + src/EditionType.h RESOURCES += res/Synergy.qrc RC_FILE = res/win/Synergy.rc macx { diff --git a/src/gui/res/SetupWizardBase.ui b/src/gui/res/SetupWizardBase.ui index 8c089886..d14f11b0 100644 --- a/src/gui/res/SetupWizardBase.ui +++ b/src/gui/res/SetupWizardBase.ui @@ -120,6 +120,137 @@ + + + Activate + + + + + + I have purchased and would like to activate... + + + true + + + + + + + QFormLayout::AllNonFixedFieldsGrow + + + 20 + + + 10 + + + + + Email: + + + + + + + + 0 + 0 + + + + + 200 + 0 + + + + QLineEdit::Normal + + + + + + + Passward: + + + + + + + + 0 + 0 + + + + + 200 + 0 + + + + QLineEdit::Password + + + + + + + <a href="https://synergy-project.org/account/reset/">Forget password</a> + + + true + + + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 10 + + + + + + + + I would like to skip activation + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 20 + 500 + + + + + + diff --git a/src/gui/src/AppConfig.cpp b/src/gui/src/AppConfig.cpp index 2054e0a3..a3014cf2 100644 --- a/src/gui/src/AppConfig.cpp +++ b/src/gui/src/AppConfig.cpp @@ -17,6 +17,7 @@ */ #include "AppConfig.h" +#include "EditionType.h" #include "QUtility.h" #include @@ -127,6 +128,9 @@ void AppConfig::loadSettings() m_AutoConfig = settings().value("autoConfig", true).toBool(); m_ElevateMode = settings().value("elevateMode", false).toBool(); m_AutoConfigPrompted = settings().value("autoConfigPrompted", false).toBool(); + m_Edition = settings().value("edition", Unknown).toInt(); + m_ActivateEmail = settings().value("activateEmail", "").toString(); + m_UserToken = settings().value("userToken", "").toString(); } void AppConfig::saveSettings() @@ -145,6 +149,9 @@ void AppConfig::saveSettings() settings().setValue("autoConfig", m_AutoConfig); settings().setValue("elevateMode", m_ElevateMode); settings().setValue("autoConfigPrompted", m_AutoConfigPrompted); + settings().setValue("edition", m_Edition); + settings().setValue("activateEmail", m_ActivateEmail); + settings().setValue("userToken", m_UserToken); } void AppConfig::setCryptoPass(const QString &s) diff --git a/src/gui/src/AppConfig.h b/src/gui/src/AppConfig.h index e53bd438..5a079ce4 100644 --- a/src/gui/src/AppConfig.h +++ b/src/gui/src/AppConfig.h @@ -32,7 +32,7 @@ // 2: added language page // 3: added premium page and removed // -const int kWizardVersion = 3; +const int kWizardVersion = 4; class QSettings; class SettingsDialog; @@ -72,6 +72,12 @@ class AppConfig void setAutoConfig(bool autoConfig); bool autoConfigPrompted() { return m_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 setUserToken(QString t) { m_UserToken = t; } + QString userToken() { return m_UserToken; } QString synergysName() const { return m_SynergysName; } QString synergycName() const { return m_SynergycName; } @@ -118,6 +124,9 @@ class AppConfig bool m_AutoConfig; bool m_ElevateMode; bool m_AutoConfigPrompted; + int m_Edition; + QString m_ActivateEmail; + QString m_UserToken; static const char m_SynergysName[]; static const char m_SynergycName[]; diff --git a/src/gui/src/EditionType.h b/src/gui/src/EditionType.h new file mode 100644 index 00000000..341f8b1b --- /dev/null +++ b/src/gui/src/EditionType.h @@ -0,0 +1,27 @@ +/* + * synergy -- mouse and keyboard sharing utility + * Copyright (C) 2015 Synergy Si 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 COPYING 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 EDITIONTYPE_H +#define EDITIONTYPE_H + +enum qEditionType { + Basic, + Pro, + Unknown +}; + +#endif // EDITIONTYPE_H diff --git a/src/gui/src/MainWindow.cpp b/src/gui/src/MainWindow.cpp index 9d3aebf9..e826222b 100644 --- a/src/gui/src/MainWindow.cpp +++ b/src/gui/src/MainWindow.cpp @@ -28,6 +28,8 @@ #include "ZeroconfService.h" #include "DataDownloader.h" #include "CommandProcess.h" +#include "EditionType.h" +#include "QUtility.h" #include #include @@ -812,10 +814,21 @@ void MainWindow::changeEvent(QEvent* event) switch (event->type()) { case QEvent::LanguageChange: + { retranslateUi(this); retranslateMenuBar(); - break; + QString mac = getFirstMacAddress(); + QString hashSrc = m_AppConfig.activateEmail() + mac; + QString hashResult = hash(hashSrc); + if (hashResult == m_AppConfig.userToken()) { + setEdition(m_AppConfig.edition()); + } + else { + setEdition(Unknown); + } + break; + } default: QMainWindow::changeEvent(event); } @@ -872,6 +885,22 @@ int MainWindow::checkWinArch() return unknown; } +void MainWindow::setEdition(int type) +{ + QString title; + if (type == Basic) { + title = "Synergy Basic"; + } + else if (type == Pro) { + title = "Synergy Pro"; + } + else { + title = "Synergy (UNREGISTERED)"; + } + + setWindowTitle(title); +} + void MainWindow::on_m_pGroupClient_toggled(bool on) { m_pGroupServer->setChecked(!on); diff --git a/src/gui/src/MainWindow.h b/src/gui/src/MainWindow.h index bbc96c37..0af1bf4f 100644 --- a/src/gui/src/MainWindow.h +++ b/src/gui/src/MainWindow.h @@ -112,6 +112,7 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase void updateZeroconfService(); void serverDetected(const QString name); int checkWinArch(); + void setEdition(int type); public slots: void appendLogRaw(const QString& text); diff --git a/src/gui/src/SetupWizard.cpp b/src/gui/src/SetupWizard.cpp index 5a8fbeaa..e3d241f2 100644 --- a/src/gui/src/SetupWizard.cpp +++ b/src/gui/src/SetupWizard.cpp @@ -17,6 +17,8 @@ #include "SetupWizard.h" #include "MainWindow.h" +#include "WebClient.h" +#include "EditionType.h" #include "QSynergyApplication.h" #include "QUtility.h" @@ -24,7 +26,8 @@ SetupWizard::SetupWizard(MainWindow& mainWindow, bool startMain) : m_MainWindow(mainWindow), - m_StartMain(startMain) + m_StartMain(startMain), + m_Edition(Unknown) { setupUi(this); @@ -51,6 +54,9 @@ 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()); } @@ -64,7 +70,36 @@ bool SetupWizard::validateCurrentPage() message.setWindowTitle(tr("Setup Synergy")); message.setIcon(QMessageBox::Information); - if (currentPage() == m_pNodePage) + 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) { + return false; + } + else { + return true; + } + } + } + else { + return true; + } + } + else if (currentPage() == m_pNodePage) { bool result = m_pClientRadioButton->isChecked() || m_pServerRadioButton->isChecked(); @@ -121,6 +156,16 @@ void SetupWizard::accept() settings.setValue("groupServerChecked", false); } + if (m_pRadioButtonActivate->isChecked()) { + appConfig.setActivateEmail(m_pLineEditEmail->text()); + QString mac = getFirstMacAddress(); + QString hashSrc = m_pLineEditEmail->text() + mac; + QString hashResult = hash(hashSrc); + appConfig.setUserToken(hashResult); + appConfig.setEdition(m_Edition); + } + m_MainWindow.setEdition(m_Edition); + settings.sync(); QWizard::accept(); @@ -138,6 +183,7 @@ void SetupWizard::reject() if (m_StartMain) { + m_MainWindow.setEdition(m_Edition); m_MainWindow.open(); } @@ -149,3 +195,19 @@ 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); + } +} + +void SetupWizard::on_m_pRadioButtonActivate_toggled(bool checked) +{ + if (checked) { + m_pLineEditEmail->setEnabled(true); + m_pLineEditPassword->setEnabled(true); + } +} diff --git a/src/gui/src/SetupWizard.h b/src/gui/src/SetupWizard.h index cba210ae..16a2630a 100644 --- a/src/gui/src/SetupWizard.h +++ b/src/gui/src/SetupWizard.h @@ -43,7 +43,10 @@ private: MainWindow& m_MainWindow; bool m_StartMain; SynergyLocale m_Locale; + int m_Edition; private slots: + void on_m_pRadioButtonActivate_toggled(bool checked); + void on_m_pRadioButtonSkip_toggled(bool checked); void on_m_pComboLanguage_currentIndexChanged(int index); }; diff --git a/src/gui/src/WebClient.cpp b/src/gui/src/WebClient.cpp new file mode 100644 index 00000000..75170532 --- /dev/null +++ b/src/gui/src/WebClient.cpp @@ -0,0 +1,130 @@ +/* + * synergy -- mouse and keyboard sharing utility + * Copyright (C) 2015 Synergy Si, Std. + * + * 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 COPYING 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 "WebClient.h" + +#include "EditionType.h" +#include "QUtility.h" + +#include +#include +#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("Sorry, an error occured while trying to sign in. " + "Please contact the help desk, and provide the " + "following details.\n\n%1").arg(e.what())); + return edition; + } + + QRegExp resultRegex(".*\"result\".*:.*(true|false).*"); + 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 edition; + } + else if (boolString == "false") { + message.critical( + w, "Error", + tr("Login failed, invalid email or password.")); + + return edition; + } + } + 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; + } + } + + 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) +{ + QString program(QCoreApplication::applicationDirPath() + "/syntool"); + QStringList args("--login-auth"); + + QProcess process; + process.setReadChannel(QProcess::StandardOutput); + process.start(program, args); + bool success = process.waitForStarted(); + + QString out, error; + if (success) + { + // hash password in case it contains interesting chars. + QString credentials(email + ":" + hash(password) + "\n"); + process.write(credentials.toStdString().c_str()); + + if (process.waitForFinished()) { + out = process.readAllStandardOutput(); + error = process.readAllStandardError(); + } + } + + out = out.trimmed(); + error = error.trimmed(); + + if (out.isEmpty() || + !error.isEmpty() || + !success || + process.exitCode() != 0) + { + throw std::runtime_error( + QString("Code: %1\nError: %2") + .arg(process.exitCode()) + .arg(error.isEmpty() ? "Unknown" : error) + .toStdString()); + } + + return out; +} diff --git a/src/gui/src/WebClient.h b/src/gui/src/WebClient.h new file mode 100644 index 00000000..8c319962 --- /dev/null +++ b/src/gui/src/WebClient.h @@ -0,0 +1,41 @@ +/* + * synergy -- mouse and keyboard sharing utility + * Copyright (C) 2015 Synergy Si, Std. + * + * 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 COPYING 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 WEBCLIENT_H +#define WEBCLIENT_H + +#include +#include + +class QMessageBox; +class QWidget; + +class WebClient : public QObject +{ + Q_OBJECT + +public: + int getEdition(const QString& email, + const QString& password, + QMessageBox& message, + QWidget* w); + +private: + QString request(const QString& email, const QString& password); +}; + +#endif // WEBCLIENT_H diff --git a/src/lib/synergy/ArgParser.cpp b/src/lib/synergy/ArgParser.cpp index 8ab17435..3793551e 100644 --- a/src/lib/synergy/ArgParser.cpp +++ b/src/lib/synergy/ArgParser.cpp @@ -165,6 +165,10 @@ ArgParser::parseToolArgs(ToolArgs& args, int argc, const char* const* argv) args.m_printActiveDesktopName = true; return true; } + else if (isArg(i, argc, argv, NULL, "--login-auth", 0)) { + args.m_loginAuthenticate = true; + return true; + } else { return false; } diff --git a/src/lib/synergy/ToolApp.cpp b/src/lib/synergy/ToolApp.cpp index 32a3a4e9..fda799ce 100644 --- a/src/lib/synergy/ToolApp.cpp +++ b/src/lib/synergy/ToolApp.cpp @@ -29,6 +29,8 @@ #include "platform/MSWindowsSession.h" #endif +#define PREMIUM_AUTH_URL "https://synergy-project.org/premium/json/auth/" + enum { kErrorOk, kErrorArgs, @@ -65,6 +67,9 @@ ToolApp::run(int argc, char** argv) } #endif } + else if (m_args.m_loginAuthenticate) { + loginAuth(); + } else { throw XSynergy("Nothing to do"); } @@ -85,3 +90,21 @@ void ToolApp::help() { } + +void +ToolApp::loginAuth() +{ + 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 << PREMIUM_AUTH_URL; + ss << "?email=" << ARCH->internet().urlEncode(email); + ss << "&password=" << password; + + std::cout << ARCH->internet().get(ss.str()) << std::endl; +} diff --git a/src/lib/synergy/ToolApp.h b/src/lib/synergy/ToolApp.h index a61f2aa0..5c66fcb4 100644 --- a/src/lib/synergy/ToolApp.h +++ b/src/lib/synergy/ToolApp.h @@ -26,6 +26,10 @@ class ToolApp : public MinimalApp public: UInt32 run(int argc, char** argv); void help(); + +private: + void loginAuth(); + private: ToolArgs m_args; }; diff --git a/src/lib/synergy/ToolArgs.h b/src/lib/synergy/ToolArgs.h index a4d542a1..9d5a0b57 100644 --- a/src/lib/synergy/ToolArgs.h +++ b/src/lib/synergy/ToolArgs.h @@ -25,4 +25,5 @@ public: public: bool m_printActiveDesktopName; + bool m_loginAuthenticate; };