Merge changes from v1.8.5

This commit is contained in:
Andrew Nelless 2016-10-31 16:14:39 +00:00
commit 96efe5fb73
68 changed files with 1437 additions and 1209 deletions

View File

@ -1,8 +1,7 @@
### Operating Systems ###
Client: Applesoft Windy OS 10
Server: microOS Tiara
Client: Applesoft Windy OS 10
**READ ME, DELETE ME**: On Windows, hold the Windows key and press 'r', type 'winver' and hit return to get your OS version. On Mac, hit the Apple menu (top left of the screen) and check 'About this Mac'. Linux users... you know what you're using ;)

3
.gitignore vendored
View File

@ -1,7 +1,10 @@
config.h
.DS_Store
*.pyc
*.o
*~
\.*.swp
*build-gui-Desktop_Qt*
/bin
/lib
/build

View File

@ -1,16 +1,22 @@
v1.8.5-stable
=============
Bug #5680 - Server crashes when disconnecting SSL clients
Bug #5626 - Build fails using Xcode 8 and macOS SDK 10.12
Feature #5657 - Trial version support
Feature #5707 - User upgrade statistics
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
Bug #5183 - Slowly moving the cursor has no effect on high DPI clients
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
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
=============

View File

@ -435,14 +435,16 @@ class InternalCommands:
if generator.cmakeName.find('Unix Makefiles') != -1:
cmake_args += ' -DCMAKE_BUILD_TYPE=' + target.capitalize()
elif sys.platform == "darwin":
if sys.platform == "darwin":
macSdkMatch = re.match("(\d+)\.(\d+)", self.macSdk)
if not macSdkMatch:
raise Exception("unknown osx version: " + self.macSdk)
sdkDir = self.getMacSdkDir()
cmake_args += " -DCMAKE_OSX_SYSROOT=" + sdkDir
cmake_args += " -DCMAKE_OSX_DEPLOYMENT_TARGET=" + self.macSdk
if generator.cmakeName.find('Unix Makefiles') == -1:
sdkDir = self.getMacSdkDir()
cmake_args += " -DCMAKE_OSX_SYSROOT=" + sdkDir
cmake_args += " -DCMAKE_OSX_DEPLOYMENT_TARGET=" + self.macSdk
cmake_args += " -DOSX_TARGET_MAJOR=" + macSdkMatch.group(1)
cmake_args += " -DOSX_TARGET_MINOR=" + macSdkMatch.group(2)
@ -558,6 +560,7 @@ class InternalCommands:
if os.path.exists(sdkPath):
return sdkPath
# return os.popen('xcodebuild -version -sdk macosx' + self.macSdk + ' Path').read().strip()
return "/Developer/SDKs/" + sdkDirName + ".sdk"
# http://tinyurl.com/cs2rxxb

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 281 KiB

View File

@ -1,11 +1,11 @@
# 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
@ -35,7 +35,7 @@ else()
endif()
target_link_libraries(synergyd
arch base common io ipc mt net platform synergy ${libs} ${OPENSSL_LIBS})
arch base common io ipc mt net platform synergy shared ${libs} ${OPENSSL_LIBS})
if (WIN32)
ADD_CUSTOM_COMMAND(

View File

@ -7,7 +7,8 @@ DEFINES += VERSION_REVISION=\\\"$$QMAKE_VERSION_REVISION\\\"
DEPENDPATH += . \
res
INCLUDEPATH += . \
src
src \
../lib/shared/
FORMS += res/MainWindowBase.ui \
res/AboutDialogBase.ui \
res/ServerConfigDialogBase.ui \
@ -60,11 +61,12 @@ SOURCES += src/main.cpp \
src/Fingerprint.cpp \
src/SslCertificate.cpp \
src/WebClient.cpp \
src/SubscriptionManager.cpp \
src/ActivationNotifier.cpp \
src/ActivationDialog.cpp \
src/CancelActivationDialog.cpp \
src/FailedLoginDialog.cpp
src/FailedLoginDialog.cpp \
../lib/shared/SerialKey.cpp \
src/LicenseManager.cpp
HEADERS += src/MainWindow.h \
src/AboutDialog.h \
src/ServerConfig.h \
@ -101,18 +103,19 @@ HEADERS += src/MainWindow.h \
src/DataDownloader.h \
src/AddClientDialog.h \
src/CommandProcess.h \
src/EditionType.h \
src/ProcessorArch.h \
src/CoreInterface.h \
src/Fingerprint.h \
src/SslCertificate.h \
src/WebClient.h \
src/SubscriptionManager.h \
src/ActivationNotifier.h \
src/ElevateMode.h \
src/ActivationDialog.h \
src/CancelActivationDialog.h \
src/FailedLoginDialog.h
src/FailedLoginDialog.h \
../lib/shared/EditionType.h \
../lib/shared/SerialKey.h \
src/LicenseManager.h
RESOURCES += res/Synergy.qrc
RC_FILE = res/win/Synergy.rc
macx {

View File

@ -13,19 +13,25 @@
<x>0</x>
<y>0</y>
<width>450</width>
<height>378</height>
<height>300</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>450</width>
<height>300</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>450</width>
<height>378</height>
<height>300</height>
</size>
</property>
<property name="windowTitle">
@ -35,20 +41,48 @@
<bool>true</bool>
</property>
<layout class="QGridLayout">
<item row="0" column="1">
<widget class="QLabel" name="label_2">
<item row="2" column="1" colspan="2">
<widget class="QLabel" name="label_3">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<property name="text">
<string>&lt;p&gt;
Keyboard and mouse sharing application. Cross platform and open source.&lt;br /&gt;&lt;br /&gt;
Copyright © 2012-2016 Symless Ltd.&lt;br /&gt;
Copyright © 2002-2012 Chris Schoeneman, Nick Bolton, Volker Lanz.&lt;br /&gt;&lt;br /&gt;
Synergy is released under the GNU General Public License (GPLv2).&lt;br /&gt;&lt;br /&gt;
Synergy is based on CosmoSynergy by Richard Lee and Adam Feder.&lt;br /&gt;
The Synergy GUI is based on QSynergy by Volker Lanz.&lt;br /&gt;&lt;br /&gt;
Visit our website for help and info (symless.com).
&lt;/p&gt;</string>
</property>
<property name="margin">
<number>1</number>
</property>
</widget>
</item>
<item row="3" column="1" colspan="2">
<spacer>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Preferred</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>450</width>
<height>16777215</height>
<width>20</width>
<height>100</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_2">
<property name="text">
<string/>
</property>
@ -163,41 +197,6 @@
</item>
</layout>
</item>
<item row="2" column="1" colspan="2">
<widget class="QLabel" name="label_3">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Keyboard and mouse sharing application. &lt;br/&gt;&lt;br/&gt;Copyright © 2012-2016 Symless Ltd.&lt;br/&gt;Copyright © 2002-2012 Chris Schoeneman, Nick Bolton, Volker Lanz.&lt;/p&gt;&lt;p&gt;Synergy is based on CosmoSynergy by Richard Lee and Adam Feder.&lt;br/&gt;The Synergy GUI is based on QSynergy by Volker Lanz. &lt;/p&gt;&lt;p&gt;Synergy is released under the GNU General Public License (GPLv2).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>false</bool>
</property>
<property name="margin">
<number>1</number>
</property>
</widget>
</item>
<item row="3" column="1" colspan="2">
<spacer>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Preferred</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>100</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources>

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>440</width>
<height>314</height>
<width>410</width>
<height>211</height>
</rect>
</property>
<property name="windowTitle">
@ -15,7 +15,7 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QRadioButton" name="m_pRadioButtonActivate">
<widget class="QLabel" name="label">
<property name="font">
<font>
<weight>75</weight>
@ -23,83 +23,14 @@
</font>
</property>
<property name="text">
<string>&amp;Account login</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QFormLayout" name="formLayout_2">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<property name="horizontalSpacing">
<number>20</number>
</property>
<property name="verticalSpacing">
<number>10</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="m_pLabelEmail">
<property name="text">
<string>Email:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="m_pLineEditEmail">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="echoMode">
<enum>QLineEdit::Normal</enum>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Password:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="m_pLineEditPassword">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QRadioButton" name="m_pRadioButtonSubscription">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>&amp;Serial key</string>
<string>Serial key</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_5">
<property name="text">
<string>Found on your &lt;a href=&quot;https://symless.com/account/?source=gui&quot;&gt;account&lt;/a&gt; page.</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;This can be found on your &lt;a href=&quot;https://symless.com/account/?source=gui&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;account&lt;/span&gt;&lt;/a&gt; page.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="openExternalLinks">
<bool>true</bool>
@ -109,7 +40,10 @@
<item>
<widget class="QTextEdit" name="m_pTextEditSerialKey">
<property name="enabled">
<bool>false</bool>
<bool>true</bool>
</property>
<property name="tabChangesFocus">
<bool>true</bool>
</property>
<property name="html">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
@ -123,6 +57,57 @@ p, li { white-space: pre-wrap; }
</property>
</widget>
</item>
<item>
<widget class="QWidget" name="m_trialWidget" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_5">
<property name="leftMargin">
<number>2</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>8</number>
</property>
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="Synergy.qrc">:/res/icons/16x16/money.png</pixmap>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="m_trialLabel">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Your trial has expired. &lt;a href=&quot;http://symless.com/pricing?src=gui&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;Buy now!&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
@ -135,7 +120,12 @@ p, li { white-space: pre-wrap; }
</item>
</layout>
</widget>
<resources/>
<tabstops>
<tabstop>m_pTextEditSerialKey</tabstop>
</tabstops>
<resources>
<include location="Synergy.qrc"/>
</resources>
<connections>
<connection>
<sender>buttonBox</sender>

View File

@ -19,7 +19,7 @@
<property name="text">
<string>Are you sure?
If you don't activate Synergy you'll be missing out on some great features</string>
If you don't activate Synergy you'll be missing out on some great features.</string>
</property>
<property name="wordWrap">
<bool>true</bool>

View File

@ -27,6 +27,57 @@
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QWidget" name="m_trialWidget" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_5">
<property name="leftMargin">
<number>2</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>8</number>
</property>
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="Synergy.qrc">:/res/icons/16x16/warning.png</pixmap>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="m_trialLabel">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;%1&lt;/span&gt; days of your Synergy Pro trial remain. &lt;a href=&quot;http://symless.com/pricing?src=gui&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;Buy now!&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="m_pWidgetUpdate" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_2">
@ -40,7 +91,7 @@
<number>0</number>
</property>
<property name="bottomMargin">
<number>7</number>
<number>8</number>
</property>
<item>
<widget class="QLabel" name="m_pIconUpdate">

View File

@ -17,7 +17,7 @@
<item>
<widget class="QTabWidget" name="m_pTabWidget">
<property name="currentIndex">
<number>2</number>
<number>0</number>
</property>
<widget class="QWidget" name="m_pTabScreens">
<attribute name="title">

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

@ -7,159 +7,116 @@
#include "ActivationNotifier.h"
#include "MainWindow.h"
#include "QUtility.h"
#include "SubscriptionManager.h"
#include "LicenseManager.h"
#include "FailedLoginDialog.h"
#include <QMessageBox>
#include <QThread>
#include <iostream>
ActivationDialog::ActivationDialog(QWidget* parent, AppConfig& appConfig) :
ActivationDialog::ActivationDialog(QWidget* parent, AppConfig& appConfig,
LicenseManager& licenseManager) :
QDialog(parent),
ui(new Ui::ActivationDialog),
m_appConfig (&appConfig)
m_appConfig(&appConfig),
m_LicenseManager (&licenseManager)
{
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();
}
refreshSerialKey();
time_t currentTime = ::time(0);
if (!m_LicenseManager->serialKey().isExpired(currentTime)) {
ui->m_trialWidget->hide();
}
}
void ActivationDialog::refreshSerialKey()
{
ui->m_pTextEditSerialKey->setText(m_appConfig->serialKey());
ui->m_pTextEditSerialKey->setFocus();
ui->m_pTextEditSerialKey->moveCursor(QTextCursor::End);
ui->m_trialLabel->setText(tr("<html><head/><body><p>Your trial has "
"expired. <a href=\"https://symless.com/"
"synergy/trial/thanks?id=%1\"><span "
"style=\"text-decoration: underline; "
"color:#0000ff;\">Buy now!</span></a>"
"</p></body></html>")
.arg (m_appConfig->serialKey()));
}
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");
m_appConfig->activationHasRun(true);
m_appConfig->saveSettings();
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();
if (m_LicenseManager->activeEdition() == kUnregistered) {
CancelActivationDialog cancelActivationDialog(this);
if (QDialog::Accepted == cancelActivationDialog.exec()) {
m_LicenseManager->skipActivation();
m_appConfig->activationHasRun(true);
m_appConfig->saveSettings();
} else {
ui->m_pLineEditPassword->setFocus();
return;
}
}
QDialog::reject();
}
void ActivationDialog::accept()
{
QMessageBox message;
QString error;
int edition = Unregistered;
m_appConfig->activationHasRun(true);
m_appConfig->saveSettings();
std::pair<bool, QString> result;
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)) {
FailedLoginDialog failedLoginDialog (this, error);
failedLoginDialog.exec();
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());
}
QString serialKey = ui->m_pTextEditSerialKey->toPlainText().trimmed();
result = m_LicenseManager->setSerialKey(serialKey);
}
catch (std::exception& e) {
message.critical (this, "Unknown Error",
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()));
"following information:\n\n%1").arg(e.what()));
refreshSerialKey();
return;
}
m_appConfig->setEdition(edition);
m_appConfig->saveSettings();
if (!result.first) {
message.critical(this, "Activation failed",
tr("%1").arg(result.second));
refreshSerialKey();
return;
}
m_LicenseManager->notifyActivation("serial:" + m_appConfig->serialKey());
Edition edition = m_LicenseManager->activeEdition();
time_t daysLeft = m_LicenseManager->serialKey().daysLeft(::time(0));
if (edition != kUnregistered) {
QString thanksMessage = tr("Thanks for trying %1! %5\n\n%2 day%3 of "
"your trial remain%4").
arg (m_LicenseManager->getEditionName(edition)).
arg (daysLeft).
arg ((daysLeft == 1) ? "" : "s").
arg ((daysLeft == 1) ? "s" : "");
if (edition == kPro) {
thanksMessage = thanksMessage.arg("If you're using SSL, "
"remember to activate all of your devices.");
} else {
thanksMessage = thanksMessage.arg("");
}
if (m_LicenseManager->serialKey().isTrial()) {
message.information(this, "Thanks!", thanksMessage);
}
else {
message.information(this, "Activated!",
tr("Thanks for activating %1!").arg
(m_LicenseManager->getEditionName(edition)));
}
}
message.information (this, "Activated!",
tr("Thanks for activating %1!").arg (getEditionName (edition)));
QDialog::accept();
}

View File

@ -2,6 +2,7 @@
#define ACTIVATIONDIALOG_H
#include <QDialog>
#include <LicenseManager.h>
namespace Ui {
class ActivationDialog;
@ -12,9 +13,10 @@ class AppConfig;
class ActivationDialog : public QDialog
{
Q_OBJECT
public:
explicit ActivationDialog(QWidget *parent, AppConfig& appConfig);
ActivationDialog(QWidget *parent, AppConfig& appConfig,
LicenseManager& licenseManager);
~ActivationDialog();
public slots:
@ -22,15 +24,12 @@ public slots:
void accept();
protected:
void notifyActivation (QString identity);
void refreshSerialKey();
private:
Ui::ActivationDialog *ui;
AppConfig* m_appConfig;
private slots:
void on_m_pRadioButtonSubscription_toggled(bool checked);
void on_m_pRadioButtonActivate_toggled(bool checked);
LicenseManager* m_LicenseManager;
};
#endif // ACTIVATIONDIALOG_H

View File

@ -20,7 +20,7 @@
#include "CoreInterface.h"
ActivationNotifier::ActivationNotifier(QObject *parent) :
QObject(parent)
QObject(parent)
{
}
@ -29,6 +29,15 @@ void ActivationNotifier::setIdentity(QString identity)
m_Identity = identity;
}
void ActivationNotifier::setUpdateInfo(QString const& fromVersion,
QString const& toVersion,
QString const& serialKey)
{
m_fromVersion = fromVersion;
m_toVersion = toVersion;
m_serialKey = serialKey;
}
void ActivationNotifier::notify()
{
CoreInterface coreInterface;
@ -39,3 +48,13 @@ void ActivationNotifier::notify()
// catch all exceptions and fails silently
}
}
void ActivationNotifier::notifyUpdate()
{
try {
CoreInterface coreInterface;
coreInterface.notifyUpdate(m_fromVersion, m_toVersion,
m_serialKey);
} catch (...) {
}
}

View File

@ -24,18 +24,24 @@ class ActivationNotifier : public QObject
{
Q_OBJECT
public:
explicit ActivationNotifier(QObject *parent = 0);
explicit ActivationNotifier(QObject *parent = 0);
void setIdentity(QString identity);
void setUpdateInfo(QString const& fromVersion,
QString const& toVersion, QString const& serialKey);
public slots:
void notify();
void notifyUpdate();
signals:
void finished();
private:
QString m_Identity;
QString m_fromVersion;
QString m_toVersion;
QString m_serialKey;
};
#endif // ACTIVATIONNOTIFIER_H

View File

@ -2,11 +2,11 @@
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2012-2016 Symless Ltd.
* Copyright (C) 2008 Volker Lanz (vl@fidra.de)
*
*
* 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
@ -153,15 +153,16 @@ void AppConfig::loadSettings()
QVariant elevateMode = settings().value("elevateModeEnum");
if (!elevateMode.isValid()) {
elevateMode = settings().value ("elevateMode",
QVariant(static_cast<int>(defaultElevateMode)));
QVariant(static_cast<int>(defaultElevateMode)));
}
m_ElevateMode = static_cast<ElevateMode>(elevateMode.toInt());
m_AutoConfigPrompted = settings().value("autoConfigPrompted", false).toBool();
m_Edition = settings().value("edition", Unregistered).toInt();
m_Edition = static_cast<Edition>(settings().value("edition", kUnregistered).toInt());
m_ActivateEmail = settings().value("activateEmail", "").toString();
m_CryptoEnabled = settings().value("cryptoEnabled", true).toBool();
m_AutoHide = settings().value("autoHide", false).toBool();
m_Serialkey = settings().value("serialKey", "").toString();
m_lastVersion = settings().value("lastVersion", "Unknown").toString();
m_LastExpiringWarningTime = settings().value("lastExpiringWarningTime", 0).toInt();
m_ActivationHasRun = settings().value("activationHasRun", false).toBool();
}
@ -178,16 +179,16 @@ void AppConfig::saveSettings()
settings().setValue("language", m_Language);
settings().setValue("startedBefore", m_StartedBefore);
settings().setValue("autoConfig", m_AutoConfig);
// Refer to enum ElevateMode declaration for insight in to why this
// flag is mapped this way
// Refer to enum ElevateMode declaration for insight in to why this
// flag is mapped this way
settings().setValue("elevateMode", m_ElevateMode == ElevateAlways);
settings().setValue("elevateModeEnum", static_cast<int>(m_ElevateMode));
settings().setValue("autoConfigPrompted", m_AutoConfigPrompted);
settings().setValue("edition", m_Edition);
settings().setValue("activateEmail", m_ActivateEmail);
settings().setValue("cryptoEnabled", m_CryptoEnabled);
settings().setValue("autoHide", m_AutoHide);
settings().setValue("serialKey", m_Serialkey);
settings().setValue("lastVersion", m_lastVersion);
settings().setValue("lastExpiringWarningTime", m_LastExpiringWarningTime);
settings().setValue("activationHasRun", m_ActivationHasRun);
settings().sync();
@ -204,6 +205,15 @@ AppConfig& AppConfig::activationHasRun(bool value)
return *this;
}
QString AppConfig::lastVersion() const
{
return m_lastVersion;
}
void AppConfig::setLastVersion(QString version) {
m_lastVersion = version;
}
QSettings &AppConfig::settings() { return *m_pSettings; }
void AppConfig::setScreenName(const QString &s) { m_ScreenName = s; }
@ -238,27 +248,16 @@ void AppConfig::setAutoConfigPrompted(bool prompted)
m_AutoConfigPrompted = prompted;
}
void AppConfig::setEdition(int e) {
void AppConfig::setEdition(Edition e) {
m_Edition = e;
emit editionSet (e);
}
int AppConfig::edition() const { return m_Edition; }
Edition AppConfig::edition() const { 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;
QString AppConfig::setSerialKey(QString serial) {
using std::swap;
swap (serial, m_Serialkey);
return serial;
}
void AppConfig::clearSerialKey()
@ -286,8 +285,8 @@ void AppConfig::setCryptoEnabled(bool e) {
emit sslToggled(e);
}
bool AppConfig::getCryptoEnabled() const {
return (edition() == Pro) && m_CryptoEnabled;
bool AppConfig::getCryptoEnabled() const {
return (edition() == kPro) && m_CryptoEnabled;
}
void AppConfig::setAutoHide(bool b) { m_AutoHide = b; }

View File

@ -2,11 +2,11 @@
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2012-2016 Symless Ltd.
* Copyright (C) 2008 Volker Lanz (vl@fidra.de)
*
*
* 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
@ -23,6 +23,7 @@
#include <QObject>
#include <QString>
#include "ElevateMode.h"
#include <EditionType.h>
// this should be incremented each time a new page is added. this is
// saved to settings when the user finishes running the wizard. if
@ -78,11 +79,9 @@ class AppConfig: public QObject
void setAutoConfig(bool autoConfig);
bool autoConfigPrompted();
void setAutoConfigPrompted(bool prompted);
void setEdition(int e);
int edition() const;
bool setActivateEmail(QString e);
QString activateEmail();
bool setSerialKey(QString serial, QString& error);
void setEdition(Edition);
Edition edition() const;
QString setSerialKey(QString serial);
void clearSerialKey();
QString serialKey();
int lastExpiringWarningTime() const;
@ -106,9 +105,12 @@ class AppConfig: public QObject
bool activationHasRun() const;
AppConfig& activationHasRun(bool value);
void saveSettings();
QString lastVersion() const;
protected:
void saveSettings();
void setLastVersion(QString version);
protected:
QSettings& settings();
void setScreenName(const QString& s);
void setPort(int i);
@ -137,11 +139,12 @@ class AppConfig: public QObject
bool m_AutoConfig;
ElevateMode m_ElevateMode;
bool m_AutoConfigPrompted;
int m_Edition;
Edition m_Edition;
QString m_ActivateEmail;
bool m_CryptoEnabled;
bool m_AutoHide;
QString m_Serialkey;
QString m_lastVersion;
int m_LastExpiringWarningTime;
bool m_ActivationHasRun;
@ -150,7 +153,6 @@ class AppConfig: public QObject
static const char m_SynergyLogDir[];
signals:
void editionSet(int);
void sslToggled(bool enabled);
};

View File

@ -22,20 +22,22 @@
#include <QCoreApplication>
#include <QProcess>
#include <QtGlobal>
#include <QDir>
#include <stdexcept>
static const char kCoreBinary[] = "syntool";
#ifdef Q_WS_WIN
static const char kSerialKeyFilename[] = "Synergy.subkey";
#else
static const char kSerialKeyFilename[] = ".synergy.subkey";
#endif
CoreInterface::CoreInterface()
{
}
QString CoreInterface::getPluginDir()
{
QStringList args("--get-plugin-dir");
return run(args);
}
QString CoreInterface::getProfileDir()
{
QStringList args("--get-profile-dir");
@ -54,24 +56,19 @@ QString CoreInterface::getArch()
return run(args);
}
QString CoreInterface::getSubscriptionFilename()
QString CoreInterface::getSerialKeyFilePath()
{
QStringList args("--get-subscription-filename");
return run(args);
QString filename = getProfileDir() + QDir::separator() + kSerialKeyFilename;
return filename;
}
QString CoreInterface::activateSerial(const QString& serial)
{
QStringList args("--subscription-serial");
args << serial;
return run(args);
}
QString CoreInterface::checkSubscription()
{
QStringList args("--check-subscription");
return run(args);
QString CoreInterface::notifyUpdate (QString const& fromVersion,
QString const& toVersion,
QString const& serialKey) {
QStringList args("--notify-update");
QString input(fromVersion + ":" + toVersion + ":" + serialKey);
input.append("\n");
return run(args, input);
}
QString CoreInterface::notifyActivation(const QString& identity)

View File

@ -24,13 +24,13 @@ class CoreInterface
public:
CoreInterface();
QString getPluginDir();
QString getProfileDir();
QString getInstalledDir();
QString getArch();
QString getSubscriptionFilename();
QString activateSerial(const QString& serial);
QString checkSubscription();
QString getSerialKeyFilePath();
QString notifyActivation(const QString& identity);
QString notifyUpdate (QString const& fromVersion,
QString const& toVersion,
QString const& serialKey);
QString run(const QStringList& args, const QString& input = "");
};

View File

@ -0,0 +1,163 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2015 Synergy Seamless Inc.
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "LicenseManager.h"
#include "EditionType.h"
#include "AppConfig.h"
#include <ctime>
#include <stdexcept>
#include <utility>
#include <QThread>
LicenseManager::LicenseManager(AppConfig* appConfig) :
m_AppConfig(appConfig),
m_serialKey(appConfig->edition()) {
}
std::pair<bool, QString>
LicenseManager::setSerialKey(QString serialKeyString, bool acceptExpired)
{
std::pair<bool, QString> ret (true, "");
time_t currentTime = ::time(0);
SerialKey serialKey (serialKeyString.toStdString());
if (!acceptExpired && serialKey.isExpired(currentTime)) {
ret.first = false;
ret.second = "Serial key expired";
return ret;
}
if (serialKey != m_serialKey) {
using std::swap;
swap (serialKey, m_serialKey);
m_AppConfig->setSerialKey(serialKeyString);
emit serialKeyChanged(m_serialKey);
if (serialKey.isTrial()) {
emit endTrial(false);
}
if (m_serialKey.edition() != serialKey.edition()) {
m_AppConfig->setEdition(m_serialKey.edition());
emit editionChanged(m_serialKey.edition());
}
if (m_serialKey.isTrial()) {
if (m_serialKey.isExpired(currentTime)) {
emit endTrial(true);
} else {
emit beginTrial(m_serialKey.isExpiring(currentTime));
}
}
m_AppConfig->saveSettings();
}
return ret;
}
void
LicenseManager::notifyUpdate(QString fromVersion, QString toVersion) {
if ((fromVersion == "Unknown")
&& (m_serialKey == SerialKey(kUnregistered))) {
return;
}
ActivationNotifier* notifier = new ActivationNotifier();
notifier->setUpdateInfo (fromVersion, toVersion,
QString::fromStdString(m_serialKey.toString()));
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, "notifyUpdate",
Qt::QueuedConnection);
}
Edition
LicenseManager::activeEdition() const
{
return m_serialKey.edition();
}
QString
LicenseManager::activeEditionName() const
{
return getEditionName(activeEdition(), m_serialKey.isTrial());
}
SerialKey
LicenseManager::serialKey() const
{
return m_serialKey;
}
void LicenseManager::refresh()
{
if (!m_AppConfig->serialKey().isEmpty()) {
setSerialKey(m_AppConfig->serialKey(), true);
}
if (m_serialKey.isExpired(::time(0))) {
emit endTrial(true);
}
}
void LicenseManager::skipActivation()
{
notifyActivation ("skip:unknown");
}
QString
LicenseManager::getEditionName(Edition const edition, bool trial)
{
std::string name ("Synergy");
switch (edition) {
case kUnregistered:
name += " (UNREGISTERED)";
return QString::fromUtf8 (name.c_str(), name.size());
case kBasic:
name += " Basic";
break;
default:
name += " Pro";
}
if (trial) {
name += " (Trial)";
}
return QString::fromUtf8 (name.c_str(), name.size());
}
void LicenseManager::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);
}

View File

@ -0,0 +1,52 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2015 Synergy Seamless Inc.
*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <QObject>
#include <SerialKey.h>
#include <ActivationNotifier.h>
#include <utility>
class AppConfig;
class LicenseManager: public QObject
{
Q_OBJECT
public:
LicenseManager(AppConfig* appConfig);
std::pair<bool, QString> setSerialKey(QString serialKey, bool acceptExpired = false);
void refresh();
Edition activeEdition() const;
QString activeEditionName() const;
SerialKey serialKey() const;
void skipActivation();
void notifyUpdate(QString fromVersion, QString toVersion);
static QString getEditionName(Edition edition, bool trial = false);
void notifyActivation(QString identity);
private:
AppConfig* m_AppConfig;
SerialKey m_serialKey;
signals:
void serialKeyChanged (SerialKey) const;
void editionChanged (Edition) const;
void beginTrial (bool expiring) const;
void endTrial (bool expired) const;
};

View File

@ -30,7 +30,7 @@
#include "ZeroconfService.h"
#include "DataDownloader.h"
#include "CommandProcess.h"
#include "SubscriptionManager.h"
#include "LicenseManager.h"
#include "EditionType.h"
#include "QUtility.h"
#include "ProcessorArch.h"
@ -76,12 +76,14 @@ static const char* synergyIconFiles[] =
":/res/icons/16x16/synergy-transfering.png"
};
MainWindow::MainWindow(QSettings& settings, AppConfig& appConfig) :
MainWindow::MainWindow(QSettings& settings, AppConfig& appConfig,
LicenseManager& licenseManager) :
m_Settings(settings),
m_AppConfig(appConfig),
m_AppConfig(&appConfig),
m_LicenseManager(&licenseManager),
m_pSynergy(NULL),
m_SynergyState(synergyDisconnected),
m_ServerConfig(&m_Settings, 5, 3, m_AppConfig.screenName(), this),
m_ServerConfig(&m_Settings, 5, 3, m_AppConfig->screenName(), this),
m_pTempConfigFile(NULL),
m_pTrayIcon(NULL),
m_pTrayIconMenu(NULL),
@ -99,7 +101,8 @@ MainWindow::MainWindow(QSettings& settings, AppConfig& appConfig) :
m_BonjourInstall(NULL),
m_SuppressEmptyServerWarning(false),
m_ExpectedRunningState(kStopped),
m_pSslCertificate(NULL)
m_pSslCertificate(NULL),
m_ActivationDialogRunning(false)
{
setupUi(this);
@ -134,13 +137,34 @@ MainWindow::MainWindow(QSettings& settings, AppConfig& appConfig) :
m_SuppressAutoConfigWarning = false;
m_pComboServerList->hide();
setEdition(m_AppConfig.edition());
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);
m_trialWidget->hide();
connect (this, SIGNAL(windowShown()),
this, SLOT(on_windowShown()), Qt::QueuedConnection);
connect (m_LicenseManager, SIGNAL(editionChanged(Edition)),
this, SLOT(setEdition(Edition)), Qt::QueuedConnection);
connect (m_LicenseManager, SIGNAL(beginTrial(bool)),
this, SLOT(beginTrial(bool)), Qt::QueuedConnection);
connect (m_LicenseManager, SIGNAL(endTrial(bool)),
this, SLOT(endTrial(bool)), Qt::QueuedConnection);
connect (m_AppConfig, SIGNAL(sslToggled(bool)),
this, SLOT(sslToggled(bool)), Qt::QueuedConnection);
setWindowTitle (m_LicenseManager->activeEditionName());
m_LicenseManager->refresh();
QString lastVersion = m_AppConfig->lastVersion();
QString currentVersion = m_VersionChecker.getVersion();
if (lastVersion != currentVersion) {
m_AppConfig->setLastVersion (currentVersion);
m_AppConfig->saveSettings();
m_LicenseManager->notifyUpdate (lastVersion, currentVersion);
}
}
MainWindow::~MainWindow()
@ -397,15 +421,17 @@ void MainWindow::appendLogRaw(const QString& text)
foreach(QString line, text.split(QRegExp("\r|\n|\r\n"))) {
if (!line.isEmpty()) {
m_pLogOutput->append(line);
updateStateFromLogLine(line);
updateFromLogLine(line);
}
}
}
void MainWindow::updateStateFromLogLine(const QString &line)
void MainWindow::updateFromLogLine(const QString &line)
{
// TODO: this code makes Andrew cry
checkConnected(line);
checkFingerprint(line);
checkLicense(line);
}
void MainWindow::checkConnected(const QString& line)
@ -430,6 +456,14 @@ void MainWindow::checkConnected(const QString& line)
}
}
void MainWindow::checkLicense(const QString &line)
{
if (line.contains("trial has expired")) {
licenseManager().refresh();
raiseActivationDialog();
}
}
void MainWindow::checkFingerprint(const QString& line)
{
QRegExp fingerprintRegex(".*server fingerprint: ([A-F0-9:]+)");
@ -498,7 +532,7 @@ void MainWindow::restartSynergy()
void MainWindow::proofreadInfo()
{
setEdition(m_AppConfig.edition()); // Why is this here?
setEdition(m_AppConfig->edition()); // Why is this here?
int oldState = m_SynergyState;
m_SynergyState = synergyDisconnected;
@ -518,6 +552,14 @@ void MainWindow::clearLog()
void MainWindow::startSynergy()
{
SerialKey serialKey = m_LicenseManager->serialKey();
time_t currentTime = ::time(0);
if (serialKey.isExpired(currentTime)) {
if (QDialog::Rejected == raiseActivationDialog()) {
return;
}
}
bool desktopMode = appConfig().processMode() == Desktop;
bool serviceMode = appConfig().processMode() == Service;
@ -566,7 +608,7 @@ void MainWindow::startSynergy()
#endif
if (m_AppConfig.getCryptoEnabled()) {
if (m_AppConfig->getCryptoEnabled()) {
args << "--enable-crypto";
}
@ -734,19 +776,6 @@ QString MainWindow::appPath(const QString& name)
bool MainWindow::serverArgs(QStringList& args, QString& app)
{
int edition;
SubscriptionManager subscriptionManager(this, appConfig(), edition);
if (subscriptionManager.fileExists())
{
if (!subscriptionManager.checkSubscription()) {
return false;
}
else {
setEdition(edition);
}
}
app = appPath(appConfig().synergysName());
if (!QFile::exists(app))
@ -775,6 +804,10 @@ bool MainWindow::serverArgs(QStringList& args, QString& app)
#endif
args << "-c" << configFilename << "--address" << address();
if (!appConfig().serialKey().isEmpty()) {
args << "--serial-key" << appConfig().serialKey();
}
#if defined(Q_OS_WIN)
// pass in physical resolution and primary screen center
// TODO: get this information in the core binary even when
@ -895,7 +928,7 @@ void MainWindow::setSynergyState(qSynergyState state)
switch (state)
{
case synergyConnected: {
if (m_AppConfig.getCryptoEnabled()) {
if (m_AppConfig->getCryptoEnabled()) {
m_pLabelPadlock->show();
}
else {
@ -1010,13 +1043,13 @@ void MainWindow::updateZeroconfService()
QMutexLocker locker(&m_UpdateZeroconfMutex);
if (isBonjourRunning()) {
if (!m_AppConfig.wizardShouldRun()) {
if (!m_AppConfig->wizardShouldRun()) {
if (m_pZeroconfService) {
delete m_pZeroconfService;
m_pZeroconfService = NULL;
}
if (m_AppConfig.autoConfig() || synergyType() == synergyServer) {
if (m_AppConfig->autoConfig() || synergyType() == synergyServer) {
m_pZeroconfService = new ZeroconfService(this);
}
}
@ -1035,10 +1068,10 @@ void MainWindow::serverDetected(const QString name)
}
}
void MainWindow::setEdition(int edition)
void MainWindow::setEdition(Edition edition)
{
setWindowTitle(getEditionName(edition));
if (m_AppConfig.getCryptoEnabled()) {
setWindowTitle(m_LicenseManager->getEditionName (edition));
if (m_AppConfig->getCryptoEnabled()) {
m_pSslCertificate = new SslCertificate(this);
m_pSslCertificate->generateCertificate();
}
@ -1046,9 +1079,60 @@ void MainWindow::setEdition(int edition)
saveSettings();
}
void MainWindow::beginTrial(bool isExpiring)
{
//Hack
//if (isExpiring) {
time_t daysLeft = m_LicenseManager->serialKey().daysLeft(::time(0));
QString expiringNotice ("<html><head/><body><p><span style=\""
"font-weight:600;\">%1</span> day%3 of "
"your %2 trial remain%5. <a href="
"\"https://symless.com/synergy/trial/thanks?id=%4\">"
"<span style=\"text-decoration: underline;"
" color:#0000ff;\">Buy now!</span></a>"
"</p></body></html>");
expiringNotice = expiringNotice
.arg (daysLeft)
.arg (LicenseManager::getEditionName
(m_LicenseManager->activeEdition()))
.arg ((daysLeft == 1) ? "" : "s")
.arg (QString::fromStdString
(m_LicenseManager->serialKey().toString()))
.arg ((daysLeft == 1) ? "s" : "");
this->m_trialLabel->setText(expiringNotice);
this->m_trialWidget->show();
//}
setWindowTitle (m_LicenseManager->activeEditionName());
}
void MainWindow::endTrial(bool isExpired)
{
if (isExpired) {
QString expiredNotice (
"<html><head/><body><p>Your %1 trial has expired. <a href="
"\"https://symless.com/synergy/trial/thanks?id=%2\">"
"<span style=\"text-decoration: underline;color:#0000ff;\">"
"Buy now!</span></a></p></body></html>"
);
expiredNotice = expiredNotice
.arg(LicenseManager::getEditionName
(m_LicenseManager->activeEdition()))
.arg(QString::fromStdString
(m_LicenseManager->serialKey().toString()));
this->m_trialLabel->setText(expiredNotice);
this->m_trialWidget->show();
stopSynergy();
m_AppConfig->activationHasRun(false);
} else {
this->m_trialWidget->hide();
}
setWindowTitle (m_LicenseManager->activeEditionName());
}
void MainWindow::updateLocalFingerprint()
{
if (m_AppConfig.getCryptoEnabled() && Fingerprint::local().fileExists()) {
if (m_AppConfig->getCryptoEnabled() && Fingerprint::local().fileExists()) {
m_pLabelFingerprint->setVisible(true);
m_pLabelLocalFingerprint->setVisible(true);
m_pLabelLocalFingerprint->setText(Fingerprint::local().readFirst());
@ -1059,6 +1143,12 @@ void MainWindow::updateLocalFingerprint()
}
}
LicenseManager&
MainWindow::licenseManager() const
{
return *m_LicenseManager;
}
void MainWindow::on_m_pGroupClient_toggled(bool on)
{
m_pGroupServer->setChecked(!on);
@ -1123,6 +1213,14 @@ void MainWindow::on_m_pActionSettings_triggered()
void MainWindow::autoAddScreen(const QString name)
{
if (!m_ServerConfig.ignoreAutoConfigClient()) {
if (m_ActivationDialogRunning) {
// TODO: refactor this code
// add this screen to the pending list and check this list until
// users finish activation dialog
m_PendingClientNames.append(name);
return;
}
int r = m_ServerConfig.autoAddScreen(name);
if (r != kAutoAddScreenOk) {
switch (r) {
@ -1160,8 +1258,7 @@ void MainWindow::on_m_pButtonConfigureServer_clicked()
void MainWindow::on_m_pActivate_triggered()
{
ActivationDialog activationDialog (this, this->appConfig());
activationDialog.exec();
raiseActivationDialog();
}
void MainWindow::on_m_pButtonApply_clicked()
@ -1325,16 +1422,16 @@ void MainWindow::promptAutoConfig()
QMessageBox::Yes | QMessageBox::No);
if (r == QMessageBox::Yes) {
m_AppConfig.setAutoConfig(true);
m_AppConfig->setAutoConfig(true);
downloadBonjour();
}
else {
m_AppConfig.setAutoConfig(false);
m_AppConfig->setAutoConfig(false);
m_pCheckBoxAutoConfig->setChecked(false);
}
}
m_AppConfig.setAutoConfigPrompted(true);
m_AppConfig->setAutoConfigPrompted(true);
}
void MainWindow::on_m_pComboServerList_currentIndexChanged(QString )
@ -1380,11 +1477,37 @@ void MainWindow::bonjourInstallFinished()
m_pCheckBoxAutoConfig->setChecked(true);
}
int MainWindow::raiseActivationDialog()
{
if (m_ActivationDialogRunning) {
return QDialog::Rejected;
}
ActivationDialog activationDialog (this, appConfig(), licenseManager());
m_ActivationDialogRunning = true;
connect (&activationDialog, SIGNAL(finished(int)),
this, SLOT(on_activationDialogFinish()), Qt::QueuedConnection);
int result = activationDialog.exec();
m_ActivationDialogRunning = false;
if (!m_PendingClientNames.empty()) {
foreach (const QString& name, m_PendingClientNames) {
autoAddScreen(name);
}
m_PendingClientNames.clear();
}
if (result == QDialog::Accepted) {
restartSynergy();
}
return result;
}
void MainWindow::on_windowShown()
{
if (!m_AppConfig.activationHasRun() && (m_AppConfig.edition() == Unregistered)) {
ActivationDialog activationDialog (this, m_AppConfig);
activationDialog.exec();
time_t currentTime = ::time(0);
if (!m_AppConfig->activationHasRun()
&& ((m_AppConfig->edition() == kUnregistered) ||
(m_LicenseManager->serialKey().isExpired(currentTime)))) {
raiseActivationDialog();
}
}

View File

@ -58,6 +58,7 @@ class ZeroconfService;
class DataDownloader;
class CommandProcess;
class SslCertificate;
class LicenseManager;
class MainWindow : public QMainWindow, public Ui::MainWindowBase
{
@ -67,7 +68,7 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase
friend class SetupWizard;
friend class ActivationDialog;
friend class SettingsDialog;
public:
enum qSynergyState
{
@ -94,7 +95,8 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase
};
public:
MainWindow(QSettings& settings, AppConfig& appConfig);
MainWindow(QSettings& settings, AppConfig& appConfig,
LicenseManager& licenseManager);
~MainWindow();
public:
@ -116,9 +118,14 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase
void updateZeroconfService();
void serverDetected(const QString name);
void updateLocalFingerprint();
LicenseManager& licenseManager() const;
public slots:
void setEdition(int edition);
int raiseActivationDialog();
public slots:
void setEdition(Edition edition);
void beginTrial(bool isExpiring);
void endTrial(bool isExpired);
void appendLogRaw(const QString& text);
void appendLogInfo(const QString& text);
void appendLogDebug(const QString& text);
@ -145,7 +152,7 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase
protected:
QSettings& settings() { return m_Settings; }
AppConfig& appConfig() { return m_AppConfig; }
AppConfig& appConfig() { return *m_AppConfig; }
QProcess* synergyProcess() { return m_pSynergy; }
void setSynergyProcess(QProcess* p) { m_pSynergy = p; }
void initConnections();
@ -162,7 +169,7 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase
void setStatus(const QString& status);
void sendIpcMessage(qIpcMessageType type, const char* buffer, bool showErrors);
void onModeChanged(bool startDesktop, bool applyService);
void updateStateFromLogLine(const QString& line);
void updateFromLogLine(const QString& line);
QString getIPAddresses();
void stopService();
void stopDesktop();
@ -178,6 +185,7 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase
void promptAutoConfig();
QString getProfileRootForArg();
void checkConnected(const QString& line);
void checkLicense(const QString& line);
void checkFingerprint(const QString& line);
bool autoHide();
QString getTimeStamp();
@ -188,7 +196,8 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase
private:
QSettings& m_Settings;
AppConfig& m_AppConfig;
AppConfig* m_AppConfig;
LicenseManager* m_LicenseManager;
QProcess* m_pSynergy;
int m_SynergyState;
ServerConfig m_ServerConfig;
@ -214,6 +223,8 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase
qRuningState m_ExpectedRunningState;
QMutex m_StopDesktopMutex;
SslCertificate* m_pSslCertificate;
bool m_ActivationDialogRunning;
QStringList m_PendingClientNames;
private slots:
void on_m_pCheckBoxAutoConfig_toggled(bool checked);

View File

@ -42,22 +42,6 @@ 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();

View File

@ -29,4 +29,3 @@ QString hash(const QString& string);
QString getFirstMacAddress();
qProcessorArch getProcessorArch();
QString getOSInformation();
QString getEditionName (int edition);

View File

@ -64,7 +64,7 @@ SettingsDialog::SettingsDialog(QWidget* parent, AppConfig& config) :
#endif
m_pCheckBoxEnableCrypto->setChecked(m_appConfig.getCryptoEnabled());
m_pCheckBoxEnableCrypto->setEnabled(m_appConfig.edition() == Pro);
m_pCheckBoxEnableCrypto->setEnabled(m_appConfig.edition() == kPro);
}
void SettingsDialog::accept()

View File

@ -19,7 +19,7 @@
#include "MainWindow.h"
#include "WebClient.h"
#include "ActivationNotifier.h"
#include "SubscriptionManager.h"
#include "LicenseManager.h"
#include "EditionType.h"
#include "QSynergyApplication.h"
#include "QUtility.h"

View File

@ -1,167 +0,0 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2015 Synergy Seamless Inc.
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "SubscriptionManager.h"
#include "CoreInterface.h"
#include "EditionType.h"
#include "AppConfig.h"
#include <QMessageBox>
#include <QDir>
#include <QFile>
#include <QDateTime>
#include <QDate>
static const char purchaseURL[] = "https://symless.com/account/";
SubscriptionManager::SubscriptionManager(QWidget* parent, AppConfig& appConfig, int& edition) :
m_pParent(parent),
m_AppConfig(appConfig),
m_Edition(edition)
{
}
bool SubscriptionManager::activateSerial(const QString& serial)
{
m_Edition = Unregistered;
persistDirectory();
CoreInterface coreInterface;
QString output;
try
{
output = coreInterface.activateSerial(serial);
}
catch (std::exception& e)
{
m_ErrorMessage = e.what();
checkError(m_ErrorMessage);
return false;
}
checkOutput(output);
return true;
}
bool SubscriptionManager::checkSubscription()
{
m_Edition = Unregistered;
persistDirectory();
CoreInterface coreInterface;
QString output;
try
{
output = coreInterface.checkSubscription();
}
catch (std::exception& e)
{
m_ErrorMessage = e.what();
checkError(m_ErrorMessage);
return false;
}
checkOutput(output);
return true;
}
bool SubscriptionManager::fileExists()
{
CoreInterface coreInterface;
QString subscriptionFilename = coreInterface.getSubscriptionFilename();
return QFile::exists(subscriptionFilename);
}
void SubscriptionManager::checkError(QString& error)
{
if (error.contains("trial has expired")) {
QMessageBox::warning(m_pParent, tr("Subscription warning"),
tr("Your trial has expired. Click <a href='%1'>here</a> to purchase").arg(purchaseURL));
}
else {
QMessageBox::warning(m_pParent, tr("Subscription error"),
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));
}
}
void SubscriptionManager::checkOutput(QString& output)
{
getEditionType(output);
checkExpiring(output);
}
void SubscriptionManager::getEditionType(QString& output)
{
if (output.contains("pro subscription valid")) {
m_Edition = Pro;
}
else if (output.contains("basic subscription valid")) {
m_Edition = Basic;
}
else if (output.contains("trial subscription valid")) {
m_Edition = Trial;
}
}
void SubscriptionManager::checkExpiring(QString& output)
{
if (output.contains("trial will end in") && shouldWarnExpiring()) {
QRegExp dayLeftRegex(".*trial will end in ([0-9]+) day.*");
if (dayLeftRegex.exactMatch(output)) {
QString dayLeft = dayLeftRegex.cap(1);
QMessageBox::warning(m_pParent, tr("Subscription warning"),
tr("Your trial will end in %1 %2. Click <a href='%3'>here</a> to purchase")
.arg(dayLeft)
.arg(dayLeft == "1" ? "day" : "days")
.arg(purchaseURL));
}
}
}
bool SubscriptionManager::shouldWarnExpiring()
{
// warn users about expiring subscription once a day
int lastExpiringWarningTime = m_AppConfig.lastExpiringWarningTime();
QDateTime currentDateTime = QDateTime::currentDateTime();
int currentTime = currentDateTime.toTime_t();
const int secondPerDay = 60 * 60 * 24;
bool result = false;
if ((currentTime - lastExpiringWarningTime) > secondPerDay) {
result = true;
m_AppConfig.setLastExpiringWarningTime(currentTime);
}
return result;
}
void SubscriptionManager::persistDirectory()
{
CoreInterface coreInterface;
QString profileDir = coreInterface.getProfileDir();
QDir dir(profileDir);
if (!dir.exists()) {
dir.mkpath(".");
}
}

View File

@ -1,47 +0,0 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2015 Synergy Seamless Inc.
*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <QWidget>
class AppConfig;
class SubscriptionManager : public QWidget
{
public:
SubscriptionManager(QWidget* parent, AppConfig& appConfig, int& edition);
bool activateSerial(const QString& serial);
bool checkSubscription();
bool fileExists();
QString getLastError(){ return m_ErrorMessage; }
private:
void checkError(QString& error);
void checkOutput(QString& output);
void getEditionType(QString& output);
void checkExpiring(QString& output);
bool shouldWarnExpiring();
void persistDirectory();
private:
QString m_ErrorMessage;
QWidget* m_pParent;
AppConfig& m_AppConfig;
int& m_Edition;
};

View File

@ -2,11 +2,11 @@
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2012-2016 Symless Ltd.
* Copyright (C) 2008 Volker Lanz (vl@fidra.de)
*
*
* 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
@ -20,6 +20,7 @@
#define TRAY_RETRY_WAIT 2000
#include "QSynergyApplication.h"
#include "LicenseManager.h"
#include "MainWindow.h"
#include "AppConfig.h"
#include "SetupWizard.h"
@ -65,7 +66,7 @@ int main(int argc, char* argv[])
"Please drag Synergy to the Applications folder, and open it from there.");
return 1;
}
if (!checkMacAssistiveDevices())
{
return 1;
@ -82,11 +83,13 @@ int main(int argc, char* argv[])
#endif
QSettings settings;
AppConfig appConfig(&settings);
AppConfig appConfig (&settings);
qRegisterMetaType<Edition>("Edition");
LicenseManager licenseManager (&appConfig);
app.switchTranslator(appConfig.language());
MainWindow mainWindow(settings, appConfig);
MainWindow mainWindow(settings, appConfig, licenseManager);
SetupWizard setupWizard(mainWindow, true);
if (appConfig.wizardShouldRun())

View File

@ -25,7 +25,7 @@ add_subdirectory(net)
add_subdirectory(platform)
add_subdirectory(server)
add_subdirectory(synergy)
add_subdirectory(shared)
if (WIN32)
add_subdirectory(synwinhk)

View File

@ -116,7 +116,6 @@ CurlFacade::urlEncode(const String& url)
char* resultCStr = curl_easy_escape(m_curl, url.c_str(), 0);
if (resultCStr == NULL) {
curl_free(resultCStr);
throw XArch("CURL escape failed.");
}

View File

@ -41,14 +41,7 @@ public:
*/
virtual IDataSocket*
accept() = 0;
//! Delete connection socket
/*!
This is used when the socket was created but not adopted by a client
proxy.
*/
virtual void deleteSocket(void*) = 0;
//@}
// ISocket overrides

View File

@ -93,14 +93,3 @@ SecureListenSocket::accept()
throw ex;
}
}
void
SecureListenSocket::deleteSocket(void* socket)
{
SecureSocketSet::iterator it;
it = m_secureSocketSet.find((IDataSocket*)socket);
if (it != m_secureSocketSet.end()) {
delete *it;
m_secureSocketSet.erase(it);
}
}

View File

@ -33,7 +33,6 @@ public:
// IListenSocket overrides
virtual IDataSocket*
accept();
void deleteSocket(void*);
private:
typedef std::set<IDataSocket*> SecureSocketSet;

View File

@ -43,7 +43,6 @@ public:
// IListenSocket overrides
virtual IDataSocket*
accept();
virtual void deleteSocket(void*) { }
protected:
void setListeningJob();

View File

@ -19,7 +19,7 @@ if (WIN32)
file(GLOB sources "MSWindows*.cpp")
elseif (APPLE)
file(GLOB headers "OSX*.h" "IOSX*.h")
file(GLOB sources "OSX*.cpp" "IOSX*.cpp" "OSX*.m")
file(GLOB sources "OSX*.cpp" "IOSX*.cpp" "OSX*.m" "OSX*.mm")
elseif (UNIX)
file(GLOB headers "XWindows*.h")
file(GLOB sources "XWindows*.cpp")

View File

@ -122,7 +122,7 @@ OSXClipboard::add(EFormat format, const String & data)
PasteboardPutItemFlavor(
m_pboard,
(PasteboardItemID) 0,
nullptr,
flavorType,
dataRef,
kPasteboardFlavorNoFlags);

View File

@ -344,4 +344,6 @@ private:
Mutex* m_carbonLoopMutex;
CondVar<bool>* m_carbonLoopReady;
#endif
class OSXScreenImpl* m_impl;
};

View File

@ -101,7 +101,8 @@ OSXScreen::OSXScreen(IEventQueue* events, bool isPrimary, bool autoShowHideCurso
m_lastSingleClickYCursor(0),
m_autoShowHideCursor(autoShowHideCursor),
m_events(events),
m_getDropTargetThread(NULL)
m_getDropTargetThread(NULL),
m_impl(NULL)
{
try {
m_displayID = CGMainDisplayID();
@ -515,9 +516,7 @@ OSXScreen::fakeMouseButton(ButtonID id, bool press)
// we define our own defaults.
const double maxDiff = sqrt(2) + 0.0001;
NXEventHandle handle = NXOpenEventStatus();
double clickTime = NXClickTime(handle);
double clickTime = [NSEvent doubleClickInterval];
// As long as the click is within the time window and distance window
// increase clickState (double click, triple click, etc)

View File

@ -35,6 +35,8 @@ endif()
add_library(server STATIC ${sources})
target_link_libraries(server shared)
if (UNIX)
target_link_libraries(server synergy)
endif()

View File

@ -106,12 +106,6 @@ ClientListener::setServer(Server* server)
m_server = server;
}
void
ClientListener::deleteSocket(void* socket)
{
m_listen->deleteSocket(socket);
}
ClientProxy*
ClientListener::getNextClient()
{
@ -213,10 +207,6 @@ ClientListener::handleUnknownClient(const Event&, void* vclient)
}
delete unknownClient;
if (m_useSecureNetwork && !handshakeOk) {
deleteSocket(socket);
}
}
void

View File

@ -48,8 +48,6 @@ public:
//@}
void deleteSocket(void* socket);
//! @name accessors
//@{

View File

@ -2,11 +2,11 @@
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2012-2016 Symless Ltd.
* Copyright (C) 2002 Chris Schoeneman
*
*
* 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
@ -45,11 +45,13 @@
#include "base/Log.h"
#include "base/TMethodEventJob.h"
#include "common/stdexcept.h"
#include "shared/SerialKey.h"
#include <cstring>
#include <cstdlib>
#include <sstream>
#include <fstream>
#include <ctime>
//
// Server
@ -60,7 +62,7 @@ Server::Server(
PrimaryClient* primaryClient,
synergy::Screen* screen,
IEventQueue* events,
bool enableDragDrop) :
ServerArgs const& args) :
m_mock(false),
m_primaryClient(primaryClient),
m_active(primaryClient),
@ -91,10 +93,10 @@ Server::Server(
m_sendFileThread(NULL),
m_writeToDropDirThread(NULL),
m_ignoreFileTransfer(false),
m_enableDragDrop(enableDragDrop),
m_enableClipboard(true),
m_sendDragInfoThread(NULL),
m_waitDragInfoThread(true)
m_waitDragInfoThread(true),
m_args(args)
{
// must have a primary client and it must have a canonical name
assert(m_primaryClient != NULL);
@ -184,7 +186,7 @@ Server::Server(
new TMethodEventJob<Server>(this,
&Server::handleFakeInputEndEvent));
if (m_enableDragDrop) {
if (m_args.m_enableDragDrop) {
m_events->adoptHandler(m_events->forFile().fileChunkSending(),
this,
new TMethodEventJob<Server>(this,
@ -451,6 +453,13 @@ Server::switchScreen(BaseClientProxy* dst,
SInt32 x, SInt32 y, bool forScreensaver)
{
assert(dst != NULL);
// if trial is expired, exit the process
if (m_args.m_serial.isExpired(std::time(0))) {
LOG((CLOG_ERR "trial has expired, aborting server"));
exit(kExitSuccess);
}
#ifndef NDEBUG
{
SInt32 dx, dy, dw, dh;
@ -534,7 +543,7 @@ Server::jumpToScreen(BaseClientProxy* newScreen)
// get the last cursor position on the target screen
SInt32 x, y;
newScreen->getJumpCursorPos(x, y);
switchScreen(newScreen, x, y, false);
}
@ -884,14 +893,14 @@ Server::isSwitchOkay(BaseClientProxy* newScreen,
if (!preventSwitch && (
(this->m_switchNeedsShift && ((mods & KeyModifierShift) != KeyModifierShift)) ||
(this->m_switchNeedsControl && ((mods & KeyModifierControl) != KeyModifierControl)) ||
(this->m_switchNeedsControl && ((mods & KeyModifierControl) != KeyModifierControl)) ||
(this->m_switchNeedsAlt && ((mods & KeyModifierAlt) != KeyModifierAlt))
)) {
LOG((CLOG_DEBUG1 "need modifiers to switch"));
preventSwitch = true;
stopSwitch();
}
}
return !preventSwitch;
}
@ -1171,7 +1180,7 @@ Server::processOptions()
}
else if (id == kOptionClipboardSharing) {
m_enableClipboard = (value != 0);
if (m_enableClipboard == false) {
LOG((CLOG_NOTE "clipboard sharing is disabled"));
}
@ -1378,10 +1387,7 @@ Server::handleClientDisconnected(const Event&, void* vclient)
removeActiveClient(client);
removeOldClient(client);
PacketStreamFilter* streamFileter = dynamic_cast<PacketStreamFilter*>(client->getStream());
TCPSocket* socket = dynamic_cast<TCPSocket*>(streamFileter->getStream());
delete client;
m_clientListener->deleteSocket(socket);
}
void
@ -1391,16 +1397,14 @@ Server::handleClientCloseTimeout(const Event&, void* vclient)
BaseClientProxy* client = static_cast<BaseClientProxy*>(vclient);
LOG((CLOG_NOTE "forced disconnection of client \"%s\"", getName(client).c_str()));
removeOldClient(client);
PacketStreamFilter* streamFileter = dynamic_cast<PacketStreamFilter*>(client->getStream());
TCPSocket* socket = dynamic_cast<TCPSocket*>(streamFileter->getStream());
delete client;
m_clientListener->deleteSocket(socket);
}
void
Server::handleSwitchToScreenEvent(const Event& event, void*)
{
SwitchToScreenInfo* info =
SwitchToScreenInfo* info =
static_cast<SwitchToScreenInfo*>(event.getData());
ClientList::const_iterator index = m_clients.find(info->m_screen);
@ -1415,7 +1419,7 @@ Server::handleSwitchToScreenEvent(const Event& event, void*)
void
Server::handleSwitchInDirectionEvent(const Event& event, void*)
{
SwitchInDirectionInfo* info =
SwitchInDirectionInfo* info =
static_cast<SwitchInDirectionInfo*>(event.getData());
// jump to screen in chosen direction from center of this screen
@ -1705,8 +1709,8 @@ Server::onMouseUp(ButtonID id)
m_ignoreFileTransfer = false;
return;
}
if (m_enableDragDrop) {
if (m_args.m_enableDragDrop) {
if (!m_screen->isOnScreen()) {
String& file = m_screen->getDraggingFilename();
if (!file.empty()) {
@ -1791,7 +1795,7 @@ Server::onMouseMovePrimary(SInt32 x, SInt32 y)
// should we switch or not?
if (isSwitchOkay(newScreen, dir, x, y, xc, yc)) {
if (m_enableDragDrop
if (m_args.m_enableDragDrop
&& m_screen->isDraggingStarted()
&& m_active != newScreen
&& m_waitDragInfoThread) {
@ -1810,7 +1814,7 @@ Server::onMouseMovePrimary(SInt32 x, SInt32 y)
m_waitDragInfoThread = true;
return true;
}
return false;
}
@ -1826,7 +1830,7 @@ Server::sendDragInfoThread(void* arg)
di.setFilename(dragFileList);
m_dragFileList.push_back(di);
}
#if defined(__APPLE__)
// on mac it seems that after faking a LMB up, system would signal back
// to synergy a mouse up event, which doesn't happen on windows. as a
@ -1849,7 +1853,7 @@ Server::sendDragInfo(BaseClientProxy* newScreen)
{
String infoString;
UInt32 fileCount = DragInformation::setupDragInfo(m_dragFileList, infoString);
if (fileCount > 0) {
char* info = NULL;
size_t size = infoString.size();
@ -2059,7 +2063,7 @@ Server::onFileChunkSending(const void* data)
assert(m_active != NULL);
// relay
m_active->fileChunkSending(chunk->m_chunk[0], &chunk->m_chunk[1], chunk->m_dataSize);
m_active->fileChunkSending(chunk->m_chunk[0], &chunk->m_chunk[1], chunk->m_dataSize);
}
void
@ -2368,7 +2372,7 @@ Server::sendFileToClient(const char* filename)
if (m_sendFileThread != NULL) {
StreamChunker::interruptFile();
}
m_sendFileThread = new Thread(
new TMethodJob<Server>(
this, &Server::sendFileThread,
@ -2393,7 +2397,7 @@ Server::sendFileThread(void* data)
void
Server::dragInfoReceived(UInt32 fileNum, String content)
{
if (!m_enableDragDrop) {
if (!m_args.m_enableDragDrop) {
LOG((CLOG_DEBUG "drag drop not enabled, ignoring drag info."));
return;
}

View File

@ -25,6 +25,7 @@
#include "synergy/mouse_types.h"
#include "synergy/INode.h"
#include "synergy/DragInformation.h"
#include "synergy/ServerArgs.h"
#include "base/Event.h"
#include "base/Stopwatch.h"
#include "base/EventTypes.h"
@ -106,7 +107,7 @@ public:
ownership of \p primaryClient.
*/
Server(Config& config, PrimaryClient* primaryClient,
synergy::Screen* screen, IEventQueue* events, bool enableDragDrop);
synergy::Screen* screen, IEventQueue* events, ServerArgs const& args);
~Server();
#ifdef TEST_ENV
@ -472,11 +473,11 @@ private:
Thread* m_writeToDropDirThread;
String m_dragFileExt;
bool m_ignoreFileTransfer;
bool m_enableDragDrop;
bool m_enableClipboard;
Thread* m_sendDragInfoThread;
bool m_waitDragInfoThread;
ClientListener* m_clientListener;
ServerArgs m_args;
};

View File

@ -0,0 +1,32 @@
# synergy -- mouse and keyboard sharing utility
# Copyright (C) 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 <http://www.gnu.org/licenses/>.
file(GLOB headers "*.h")
file(GLOB sources "*.cpp")
if (SYNERGY_ADD_HEADERS)
list(APPEND sources ${headers})
endif()
add_library(shared STATIC ${sources})
include_directories(
../
../../../ext
../../../ext/gtest-1.6.0/include
)
target_link_libraries(shared arch base)

View File

@ -20,11 +20,11 @@
/* Do not reorder these! */
enum EditionType {
Basic,
Pro,
Trial,
Unregistered
enum Edition {
kBasic,
kPro,
Trial_DO_NOT_USE_OR_THERE_WILL_BE_PAIN,
kUnregistered
};
#endif // EDITIONTYPE_H

View File

@ -0,0 +1,264 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 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 <http://www.gnu.org/licenses/>.
*/
#include "SerialKey.h"
#include <fstream>
#include <iostream>
#include <algorithm>
#include <vector>
#include <climits>
#include <sstream>
#include <iomanip>
#include <stdexcept>
using namespace std;
SerialKey::SerialKey(Edition edition):
m_userLimit(1),
m_warnTime(ULLONG_MAX),
m_expireTime(ULLONG_MAX),
m_edition(edition),
m_trial(false)
{
}
SerialKey::SerialKey(std::string serial) :
m_userLimit(1),
m_warnTime(0),
m_expireTime(0),
m_edition(kBasic),
m_trial(true)
{
string plainText = decode(serial);
bool valid = false;
if (!plainText.empty()) {
valid = parse(plainText);
}
if (!valid) {
throw std::runtime_error ("Invalid serial key");
}
}
bool
SerialKey::isExpiring(time_t currentTime) const
{
bool result = false;
if (m_trial) {
if (m_warnTime <= currentTime && currentTime < m_expireTime) {
result = true;
}
}
return result;
}
bool
SerialKey::isExpired(time_t currentTime) const
{
bool result = false;
if (m_trial) {
if (m_expireTime <= currentTime) {
result = true;
}
}
return result;
}
bool
SerialKey::isTrial() const
{
return m_trial;
}
Edition
SerialKey::edition() const
{
return m_edition;
}
std::string
SerialKey::editionString() const
{
switch (edition()) {
case kBasic:
return "basic";
case kPro:
return "pro";
default: {
std::ostringstream oss;
oss << static_cast<int>(edition());
return oss.str();
}
}
}
static std::string
hexEncode (std::string const& str) {
std::ostringstream oss;
for (size_t i = 0; i < str.size(); ++i) {
int c = str[i];
oss << std::setfill('0') << std::hex << std::setw(2)
<< std::uppercase;
oss << c;
}
return oss.str();
}
std::string
SerialKey::toString() const
{
std::ostringstream oss;
oss << "{";
if (isTrial()) {
oss << "v2;trial;";
} else {
oss << "v1;";
}
oss << editionString() << ";";
oss << m_name << ";";
oss << m_userLimit << ";";
oss << m_email << ";";
oss << m_company << ";";
oss << (isTrial() ? m_warnTime : 0) << ";";
oss << (isTrial() ? m_expireTime : 0);
oss << "}";
return hexEncode(oss.str());
}
time_t
SerialKey::daysLeft(time_t currentTime) const
{
unsigned long long timeLeft = 0;
unsigned long long const day = 60 * 60 * 24;
if (currentTime < m_expireTime) {
timeLeft = m_expireTime - currentTime;
}
unsigned long long daysLeft = 0;
daysLeft = timeLeft % day != 0 ? 1 : 0;
return timeLeft / day + daysLeft;
}
std::string
SerialKey::email() const
{
return m_email;
}
std::string
SerialKey::decode(const std::string& serial)
{
static const char* const lut = "0123456789ABCDEF";
string output;
size_t len = serial.length();
if (len & 1) {
return output;
}
output.reserve(len / 2);
for (size_t i = 0; i < len; i += 2) {
char a = serial[i];
char b = serial[i + 1];
const char* p = std::lower_bound(lut, lut + 16, a);
const char* q = std::lower_bound(lut, lut + 16, b);
if (*q != b || *p != a) {
return output;
}
output.push_back(static_cast<char>(((p - lut) << 4) | (q - lut)));
}
return output;
}
bool
SerialKey::parse(std::string plainSerial)
{
string parityStart = plainSerial.substr(0, 1);
string parityEnd = plainSerial.substr(plainSerial.length() - 1, 1);
bool valid = false;
// check for parity chars { and }, record parity result, then remove them.
if (parityStart == "{" && parityEnd == "}") {
plainSerial = plainSerial.substr(1, plainSerial.length() - 2);
// tokenize serialised subscription.
vector<string> parts;
std::string::size_type pos = 0;
bool look = true;
while (look) {
std::string::size_type start = pos;
pos = plainSerial.find(";", pos);
if (pos == string::npos) {
pos = plainSerial.length();
look = false;
}
parts.push_back(plainSerial.substr(start, pos - start));
pos += 1;
}
if ((parts.size() == 8)
&& (parts.at(0).find("v1") != string::npos)) {
// e.g.: {v1;basic;Bob;1;email;company name;1398297600;1398384000}
m_edition = parseEdition(parts.at(1));
m_name = parts.at(2);
m_trial = false;
sscanf(parts.at(3).c_str(), "%d", &m_userLimit);
m_email = parts.at(4);
m_company = parts.at(5);
sscanf(parts.at(6).c_str(), "%lld", &m_warnTime);
sscanf(parts.at(7).c_str(), "%lld", &m_expireTime);
valid = true;
}
else if ((parts.size() == 9)
&& (parts.at(0).find("v2") != string::npos)) {
// e.g.: {v2;trial;basic;Bob;1;email;company name;1398297600;1398384000}
m_trial = parts.at(1) == "trial" ? true : false;
m_edition = parseEdition(parts.at(2));
m_name = parts.at(3);
sscanf(parts.at(4).c_str(), "%d", &m_userLimit);
m_email = parts.at(5);
m_company = parts.at(6);
sscanf(parts.at(7).c_str(), "%lld", &m_warnTime);
sscanf(parts.at(8).c_str(), "%lld", &m_expireTime);
valid = true;
}
}
return valid;
}
Edition
SerialKey::parseEdition(std::string const& editionStr)
{
Edition e = kBasic;
if (editionStr == "pro") {
e = kPro;
}
return e;
}

View File

@ -0,0 +1,84 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <string>
#include <ctime>
#include "EditionType.h"
#ifdef TEST_ENV
#include "gtest/gtest_prod.h"
#endif
class SerialKey {
friend bool operator== (SerialKey const&, SerialKey const&);
public:
explicit SerialKey(Edition edition = kUnregistered);
explicit SerialKey(std::string serial);
bool isExpiring(time_t currentTime) const;
bool isExpired(time_t currentTime) const;
bool isTrial() const;
time_t daysLeft(time_t currentTime) const;
std::string email() const;
Edition edition() const;
std::string toString() const;
static std::string decode(const std::string& serial);
static Edition parseEdition(const std::string& editionStr);
private:
bool parse(std::string plainSerial);
std::string editionString() const;
#ifdef TEST_ENV
private:
FRIEND_TEST(SerialKeyTests, parse_noParty_invalid);
FRIEND_TEST(SerialKeyTests, parse_invalidPartsLenghth_invalid);
FRIEND_TEST(SerialKeyTests, parse_validV1Serial_valid);
FRIEND_TEST(SerialKeyTests, parse_validV2Serial_valid);
#endif
private:
std::string m_name;
std::string m_email;
std::string m_company;
unsigned m_userLimit;
unsigned long long m_warnTime;
unsigned long long m_expireTime;
Edition m_edition;
bool m_trial;
};
inline bool
operator== (SerialKey const& lhs, SerialKey const& rhs) {
return (lhs.m_name == rhs.m_name) &&
(lhs.m_email == rhs.m_email) &&
(lhs.m_company == rhs.m_company) &&
(lhs.m_userLimit == rhs.m_userLimit) &&
(lhs.m_warnTime == rhs.m_warnTime) &&
(lhs.m_expireTime == rhs.m_expireTime) &&
(lhs.m_edition == rhs.m_edition) &&
(lhs.m_trial == rhs.m_trial);
}
inline bool
operator!= (SerialKey const& lhs, SerialKey const& rhs) {
return !(lhs == rhs);
}

View File

@ -1,11 +1,11 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2014-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
@ -74,6 +74,9 @@ ArgParser::parseServerArgs(ServerArgs& args, int argc, const char* const* argv)
else if (isArg(i, argc, argv, "", "--prm-hc", 1)) {
DpiHelper::s_primaryHeightCenter = synergy::string::stringToSizeType(argv[++i]);
}
else if (isArg(i, argc, argv, "", "--serial-key", 1)) {
args.m_serial = SerialKey(argv[++i]);
}
else {
LOG((CLOG_PRINT "%s: unrecognized option `%s'" BYE, args.m_pname, argv[i], args.m_pname));
return false;
@ -111,7 +114,7 @@ ArgParser::parseClientArgs(ClientArgs& args, int argc, const char* const* argv)
// ignore -- included for backwards compatibility
}
else if (isArg(i, argc, argv, NULL, "--yscroll", 1)) {
// define scroll
// define scroll
args.m_yscroll = atoi(argv[++i]);
}
else {
@ -193,18 +196,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;
@ -213,26 +208,14 @@ ArgParser::parseToolArgs(ToolArgs& args, int argc, const char* const* argv)
args.m_getArch = true;
return true;
}
else if (isArg(i, argc, argv, NULL, "--subscription-serial", 1)) {
args.m_subscriptionSerial = argv[++i];
if (args.m_subscriptionSerial.empty()) {
LOG((CLOG_CRIT "subscription error: serial was not provided"));
return false;
}
return true;
}
else if (isArg(i, argc, argv, NULL, "--get-subscription-filename", 0)) {
args.m_getSubscriptionFilename = true;
return true;
}
else if (isArg(i, argc, argv, NULL, "--check-subscription", 0)) {
args.m_checkSubscription = true;
return true;
}
else if (isArg(i, argc, argv, NULL, "--notify-activation", 0)) {
args.m_notifyActivation = true;
return true;
}
else if (isArg(i, argc, argv, NULL, "--notify-update", 0)) {
args.m_notifyUpdate = true;
return true;
}
else {
return false;
}
@ -296,10 +279,10 @@ ArgParser::parseGenericArgs(int argc, const char* const* argv, int& i)
argsBase().m_enableIpc = true;
}
else if (isArg(i, argc, argv, NULL, "--server")) {
// HACK: stop error happening when using portable (synergyp)
// HACK: stop error happening when using portable (synergyp)
}
else if (isArg(i, argc, argv, NULL, "--client")) {
// HACK: stop error happening when using portable (synergyp)
// HACK: stop error happening when using portable (synergyp)
}
else if (isArg(i, argc, argv, NULL, "--enable-drag-drop")) {
bool useDragDrop = true;
@ -398,7 +381,7 @@ ArgParser::splitCommandString(String& command, std::vector<String>& argv)
else if (space > rightDoubleQuote){
searchDoubleQuotes(command, leftDoubleQuote, rightDoubleQuote, rightDoubleQuote + 1);
}
if (!ignoreThisSpace) {
String subString = command.substr(startPos, space - startPos);
@ -464,7 +447,7 @@ ArgParser::getArgv(std::vector<String>& argsArray)
// them to the inner array. So caller only need to use
// delete[] to delete the outer array
const char** argv = new const char*[argc];
for (size_t i = 0; i < argc; i++) {
argv[i] = argsArray[i].c_str();
}
@ -496,7 +479,7 @@ ArgParser::assembleCommand(std::vector<String>& argsArray, String ignoreArg, in
if (!result.empty()) {
// remove the tail space
result = result.substr(0, result.size() - 1);
result = result.substr(0, result.size() - 1);
}
return result;
@ -513,13 +496,13 @@ bool
ArgParser::checkUnexpectedArgs()
{
#if SYSAPI_WIN32
// suggest that user installs as a windows service. when launched as
// suggest that user installs as a windows service. when launched as
// service, process should automatically detect that it should run in
// daemon mode.
if (argsBase().m_daemon) {
LOG((CLOG_ERR
LOG((CLOG_ERR
"the --daemon argument is not supported on windows. "
"instead, install %s as a service (--service install)",
"instead, install %s as a service (--service install)",
argsBase().m_pname));
return true;
}

View File

@ -647,7 +647,7 @@ ServerApp::openClientListener(const NetworkAddress& address)
Server*
ServerApp::openServer(Config& config, PrimaryClient* primaryClient)
{
Server* server = new Server(config, primaryClient, m_serverScreen, m_events, args().m_enableDragDrop);
Server* server = new Server(config, primaryClient, m_serverScreen, m_events, args());
try {
m_events->adoptHandler(
m_events->forServer().disconnected(), server,

View File

@ -19,6 +19,7 @@
ServerArgs::ServerArgs() :
m_configFile(),
m_serial(),
m_config(NULL)
{
}

View File

@ -1,11 +1,11 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2014-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
@ -18,6 +18,7 @@
#pragma once
#include "synergy/ArgsBase.h"
#include "shared/SerialKey.h"
class NetworkAddress;
class Config;
@ -28,5 +29,6 @@ public:
public:
String m_configFile;
SerialKey m_serial;
Config* m_config;
};

View File

@ -1,30 +0,0 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2015 Synergy Seamless Inc.
*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "base/String.h"
struct SubscriptionKey {
String m_name;
String m_type;
String m_email;
String m_company;
int m_userLimit;
int m_warnTime;
int m_expireTime;
};

View File

@ -1,199 +0,0 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2015 Synergy Seamless Inc.
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "synergy/SubscriptionManager.h"
#include "synergy/XSynergy.h"
#include "arch/Arch.h"
#include "base/Log.h"
#include "base/String.h"
#include "common/Version.h"
#include <fstream>
#include <iostream>
#include <algorithm>
#include <vector>
#include <ctime>
//#include <stdexcept>
#if SYSAPI_WIN32
const char* kFile = "Synergy.subkey";
#else
const char* kFile = ".synergy.subkey";
#endif
//
// SubscriptionManager
//
SubscriptionManager::SubscriptionManager() :
m_key()
{
}
void
SubscriptionManager::checkFile(const String& filename_)
{
String filename = filename_;
if (filename.empty()) {
filename = getFilename();
}
std::ifstream stream(filename.c_str());
if (!stream.is_open()) {
throw XSubscription(synergy::string::sprintf(
"Could not open, path=%s", filename.c_str()));
}
String serial;
stream >> serial;
String plainText = decode(serial);
parsePlainSerial(plainText, m_key);
LOG((CLOG_DEBUG "subscription is valid"));
}
void
SubscriptionManager::activate(const String& serial)
{
String plainText = decode(serial);
parsePlainSerial(plainText, m_key);
String filename = getFilename();
std::ofstream stream(filename.c_str());
if (!stream.is_open()) {
throw XSubscription(synergy::string::sprintf(
"Could not open, file=%s", filename.c_str()));
}
stream << serial << std::endl;
LOG((CLOG_DEBUG "subscription file created, path=%s", filename.c_str()));
}
String
SubscriptionManager::decode(const String& input)
{
static const char* const lut = "0123456789ABCDEF";
size_t len = input.length();
if (len & 1) {
throw XSubscription("Invalid serial, wrong length.");
}
String output;
output.reserve(len / 2);
for (size_t i = 0; i < len; i += 2) {
char a = input[i];
char b = input[i + 1];
const char* p = std::lower_bound(lut, lut + 16, a);
const char* q = std::lower_bound(lut, lut + 16, b);
if (*q != b || *p != a) {
throw XSubscription("Invalid serial, unrecognized digit.");
}
output.push_back(static_cast<char>(((p - lut) << 4) | (q - lut)));
}
return output;
}
void
SubscriptionManager::parsePlainSerial(const String& plainText, SubscriptionKey& key)
{
String serial;
String parityStart = plainText.substr(0, 1);
String parityEnd = plainText.substr(plainText.length() - 1, 1);
// check for parity chars { and }, record parity result, then remove them.
if (parityStart == "{" && parityEnd == "}") {
serial = plainText.substr(1, plainText.length() - 2);
// tokenize serialised subscription.
std::vector<String> parts;
std::string::size_type pos = 0;
bool look = true;
while (look) {
std::string::size_type start = pos;
pos = serial.find(";", pos);
if (pos == String::npos) {
pos = plainText.length();
look = false;
}
parts.push_back(serial.substr(start, pos - start));
pos += 1;
}
// e.g.: {v1;trial;Bob;1;email;company name;1398297600;1398384000}
if ((parts.size() == 8)
&& (parts.at(0).find("v1") != String::npos)) {
key.m_type = parts.at(1);
key.m_name = parts.at(2);
sscanf(parts.at(3).c_str(), "%d", &key.m_userLimit);
key.m_email = parts.at(4);
key.m_company = parts.at(5);
sscanf(parts.at(6).c_str(), "%d", &key.m_warnTime);
sscanf(parts.at(7).c_str(), "%d", &key.m_expireTime);
// only limit to trial version
if (key.m_type == "trial") {
if (time(0) > key.m_expireTime) {
throw XSubscription("trial has expired");
}
else if (time(0) > key.m_warnTime) {
int secLeft = key.m_expireTime - static_cast<int>(time(0));
const int spd = 60 * 60 * 24;
int dayLeft = secLeft / spd + 1;
LOG((CLOG_NOTE "trial will end in %d %s",
dayLeft,
dayLeft == 1 ? "day" : "days"));
}
}
const char* userText = (key.m_userLimit == 1) ? "user" : "users";
LOG((CLOG_INFO "%s subscription valid is for %d %s, registered to %s",
key.m_type.c_str(),
key.m_userLimit,
userText,
key.m_name.c_str()));
return;
}
}
throw XSubscription(synergy::string::sprintf("Serial is invalid."));
}
String
SubscriptionManager::getFilename()
{
String path = ARCH->getProfileDirectory();
path = ARCH->concatPath(path, kFile);
if (path.empty()) {
throw XSubscription("Could not get filename.");
}
return path;
}
void
SubscriptionManager::printFilename()
{
std::cout << getFilename() << std::endl;
}

View File

@ -1,55 +0,0 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2015 Synergy Seamless Inc.
*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "SubscriptionKey.h"
#include "common/common.h"
#include "gtest/gtest_prod.h"
class SubscriptionManager {
public:
SubscriptionManager();
//! Check the subscription activation file
void checkFile(const String& filename);
//! Create a subscription activation file based on a serial
void activate(const String& serial);
//! Use standard output to return subscription filename to gui
void printFilename();
private:
FRIEND_TEST(SubscriptionTests, decode_invalidLength_throwException);
FRIEND_TEST(SubscriptionTests, decode_invalidSerial_outputPlainText);
FRIEND_TEST(SubscriptionTests, decode_unrecognizedDigit_throwException);
FRIEND_TEST(SubscriptionTests, parsePlainSerial_noParity_throwException);
FRIEND_TEST(SubscriptionTests, parsePlainSerial_invalidSerial_throwException);
FRIEND_TEST(SubscriptionTests, parsePlainSerial_validSerial_validSubscriptionKey);
FRIEND_TEST(SubscriptionTests, parsePlainSerial_expiredTrialSerial_throwException);
FRIEND_TEST(SubscriptionTests, parsePlainSerial_expiredBasicSerial_validSubscriptionKey);
FRIEND_TEST(SubscriptionTests, parsePlainSerial_validSerialWithoutCompany_validSubscriptionKey);
private:
String decode(const String& input);
void parsePlainSerial(const String& plainText, SubscriptionKey& key);
String getFilename();
SubscriptionKey m_key;
};

View File

@ -1,11 +1,11 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2014-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
@ -18,7 +18,6 @@
#include "synergy/ToolApp.h"
#include "synergy/ArgParser.h"
#include "synergy/SubscriptionManager.h"
#include "arch/Arch.h"
#include "base/Log.h"
#include "base/String.h"
@ -72,50 +71,17 @@ ToolApp::run(int argc, char** argv)
else if (m_args.m_loginAuthenticate) {
loginAuth();
}
else if (m_args.m_getPluginList) {
getPluginList();
}
else if (m_args.m_getInstalledDir) {
std::cout << ARCH->getInstalledDirectory() << std::endl;
}
else if (m_args.m_getPluginDir) {
std::cout << ARCH->getPluginDirectory() << std::endl;
}
else if (m_args.m_getProfileDir) {
std::cout << ARCH->getProfileDirectory() << std::endl;
}
else if (m_args.m_getArch) {
std::cout << ARCH->getPlatformName() << std::endl;
}
else if (!m_args.m_subscriptionSerial.empty()) {
try {
SubscriptionManager subscriptionManager;
subscriptionManager.activate(m_args.m_subscriptionSerial);
}
catch (XSubscription& e) {
LOG((CLOG_CRIT "subscription error: %s", e.what()));
return kExitSubscription;
}
}
else if (m_args.m_getSubscriptionFilename) {
try {
SubscriptionManager subscriptionManager;
subscriptionManager.printFilename();
}
catch (XSubscription& e) {
LOG((CLOG_CRIT "subscription error: %s", e.what()));
return kExitSubscription;
}
}
else if (m_args.m_checkSubscription) {
try {
SubscriptionManager subscriptionManager;
subscriptionManager.checkFile("");
}
catch (XSubscription& e) {
LOG((CLOG_CRIT "subscription error: %s", e.what()));
return kExitSubscription;
}
else if (m_args.m_notifyUpdate) {
notifyUpdate();
}
else if (m_args.m_notifyActivation) {
notifyActivation();
@ -172,11 +138,29 @@ ToolApp::loginAuth()
}
void
ToolApp::getPluginList()
ToolApp::notifyUpdate()
{
String data;
std::cin >> data;
std::vector<String> parts = synergy::string::splitString(data, ':');
size_t count = parts.size();
if (count == 3) {
std::stringstream ss;
ss << JSON_URL << "notify/update";
ss << "?from=" << parts[0];
ss << "&to=" << parts[1];
ss << "&serial=" << parts[2];
std::cout << ARCH->internet().get(ss.str()) << std::endl;
}
else {
throw XSynergy("Invalid update data.");
}
}
void
void
ToolApp::notifyActivation()
{
String info;

View File

@ -29,8 +29,8 @@ public:
private:
void loginAuth();
void getPluginList();
void notifyActivation();
void notifyUpdate();
private:
ToolArgs m_args;

View File

@ -20,14 +20,10 @@
ToolArgs::ToolArgs() :
m_printActiveDesktopName(false),
m_loginAuthenticate(false),
m_getPluginList(false),
m_getPluginDir(false),
m_getInstalledDir(false),
m_getProfileDir(false),
m_getArch(false),
m_getSubscriptionFilename(false),
m_checkSubscription(false),
m_notifyActivation(false),
m_subscriptionSerial()
m_notifyUpdate(false)
{
}

View File

@ -26,13 +26,9 @@ public:
public:
bool m_printActiveDesktopName;
bool m_loginAuthenticate;
bool m_getPluginList;
bool m_getPluginDir;
bool m_getInstalledDir;
bool m_getProfileDir;
bool m_getArch;
bool m_getSubscriptionFilename;
bool m_checkSubscription;
bool m_notifyActivation;
String m_subscriptionSerial;
bool m_notifyUpdate;
};

View File

@ -129,7 +129,9 @@ TEST_F(NetworkTests, sendToClient_mockData)
ON_CALL(serverConfig, isScreen(_)).WillByDefault(Return(true));
ON_CALL(serverConfig, getInputFilter()).WillByDefault(Return(&serverInputFilter));
Server server(serverConfig, &primaryClient, &serverScreen, &m_events, true);
ServerArgs serverArgs;
serverArgs.m_enableDragDrop = true;
Server server(serverConfig, &primaryClient, &serverScreen, &m_events, serverArgs);
server.m_mock = true;
listener.setServer(&server);
@ -142,10 +144,10 @@ TEST_F(NetworkTests, sendToClient_mockData)
ON_CALL(clientScreen, getCursorPos(_, _)).WillByDefault(Invoke(getCursorPos));
ClientArgs args;
args.m_enableDragDrop = true;
args.m_enableCrypto = false;
Client client(&m_events, "stub", serverAddress, clientSocketFactory, &clientScreen, args);
ClientArgs clientArgs;
clientArgs.m_enableDragDrop = true;
clientArgs.m_enableCrypto = false;
Client client(&m_events, "stub", serverAddress, clientSocketFactory, &clientScreen, clientArgs);
m_events.adoptHandler(
m_events.forFile().fileRecieveCompleted(), &client,
@ -185,7 +187,9 @@ TEST_F(NetworkTests, sendToClient_mockFile)
ON_CALL(serverConfig, isScreen(_)).WillByDefault(Return(true));
ON_CALL(serverConfig, getInputFilter()).WillByDefault(Return(&serverInputFilter));
Server server(serverConfig, &primaryClient, &serverScreen, &m_events, true);
ServerArgs serverArgs;
serverArgs.m_enableDragDrop = true;
Server server(serverConfig, &primaryClient, &serverScreen, &m_events, serverArgs);
server.m_mock = true;
listener.setServer(&server);
@ -198,10 +202,10 @@ TEST_F(NetworkTests, sendToClient_mockFile)
ON_CALL(clientScreen, getCursorPos(_, _)).WillByDefault(Invoke(getCursorPos));
ClientArgs args;
args.m_enableDragDrop = true;
args.m_enableCrypto = false;
Client client(&m_events, "stub", serverAddress, clientSocketFactory, &clientScreen, args);
ClientArgs clientArgs;
clientArgs.m_enableDragDrop = true;
clientArgs.m_enableCrypto = false;
Client client(&m_events, "stub", serverAddress, clientSocketFactory, &clientScreen, clientArgs);
m_events.adoptHandler(
m_events.forFile().fileRecieveCompleted(), &client,
@ -235,7 +239,9 @@ TEST_F(NetworkTests, sendToServer_mockData)
ON_CALL(serverConfig, isScreen(_)).WillByDefault(Return(true));
ON_CALL(serverConfig, getInputFilter()).WillByDefault(Return(&serverInputFilter));
Server server(serverConfig, &primaryClient, &serverScreen, &m_events, true);
ServerArgs serverArgs;
serverArgs.m_enableDragDrop = true;
Server server(serverConfig, &primaryClient, &serverScreen, &m_events, serverArgs);
server.m_mock = true;
listener.setServer(&server);
@ -247,10 +253,10 @@ TEST_F(NetworkTests, sendToServer_mockData)
ON_CALL(clientScreen, getShape(_, _, _, _)).WillByDefault(Invoke(getScreenShape));
ON_CALL(clientScreen, getCursorPos(_, _)).WillByDefault(Invoke(getCursorPos));
ClientArgs args;
args.m_enableDragDrop = true;
args.m_enableCrypto = false;
Client client(&m_events, "stub", serverAddress, clientSocketFactory, &clientScreen, args);
ClientArgs clientArgs;
clientArgs.m_enableDragDrop = true;
clientArgs.m_enableCrypto = false;
Client client(&m_events, "stub", serverAddress, clientSocketFactory, &clientScreen, clientArgs);
m_events.adoptHandler(
m_events.forClientListener().connected(), &listener,
@ -290,7 +296,9 @@ TEST_F(NetworkTests, sendToServer_mockFile)
ON_CALL(serverConfig, isScreen(_)).WillByDefault(Return(true));
ON_CALL(serverConfig, getInputFilter()).WillByDefault(Return(&serverInputFilter));
Server server(serverConfig, &primaryClient, &serverScreen, &m_events, true);
ServerArgs serverArgs;
serverArgs.m_enableDragDrop = true;
Server server(serverConfig, &primaryClient, &serverScreen, &m_events, serverArgs);
server.m_mock = true;
listener.setServer(&server);
@ -302,10 +310,10 @@ TEST_F(NetworkTests, sendToServer_mockFile)
ON_CALL(clientScreen, getShape(_, _, _, _)).WillByDefault(Invoke(getScreenShape));
ON_CALL(clientScreen, getCursorPos(_, _)).WillByDefault(Invoke(getCursorPos));
ClientArgs args;
args.m_enableDragDrop = true;
args.m_enableCrypto = false;
Client client(&m_events, "stub", serverAddress, clientSocketFactory, &clientScreen, args);
ClientArgs clientArgs;
clientArgs.m_enableDragDrop = true;
clientArgs.m_enableCrypto = false;
Client client(&m_events, "stub", serverAddress, clientSocketFactory, &clientScreen, clientArgs);
m_events.adoptHandler(
m_events.forClientListener().connected(), &listener,

View File

@ -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} ${OPENSSL_LIBS})
arch base client server common io net platform server synergy mt ipc gtest gmock shared ${libs} ${OPENSSL_LIBS})

View File

@ -0,0 +1,147 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2016 Symless Inc.
*
* 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 <http://www.gnu.org/licenses/>.
*/
#define TEST_ENV
#include "shared/SerialKey.h"
#include "test/global/gtest.h"
TEST(SerialKeyTests, decode_empty_returnEmptyString)
{
std::string plainText = SerialKey::decode("");
EXPECT_EQ(0, plainText.size());
}
TEST(SerialKeyTests, decode_invalidDigit_returnEmptyString)
{
std::string plainText = SerialKey::decode("MOCKZ");
EXPECT_EQ(0, plainText.size());
}
TEST(SerialKeyTests, decode_validSerial_returnPlainText)
{
std::string plainText = SerialKey::decode("53796E6572677920726F636B7321");
EXPECT_EQ("Synergy rocks!", plainText);
}
TEST(SerialKeyTests, parse_noParty_invalid)
{
SerialKey serial;
bool r = serial.parse("MOCK");
EXPECT_FALSE(r);
}
TEST(SerialKeyTests, parse_invalidPartsLenghth_invalid)
{
SerialKey serial;
bool r = serial.parse("{Synergy;Rocks}");
EXPECT_FALSE(r);
}
TEST(SerialKeyTests, parse_validV1Serial_valid)
{
SerialKey serial;
bool r = serial.parse("{v1;basic;Bob;1;email;company name;0;86400}");
EXPECT_EQ(true, r);
EXPECT_EQ(kBasic, serial.edition());
EXPECT_FALSE(serial.isExpired(0));
EXPECT_EQ(true, serial.daysLeft(0));
EXPECT_FALSE(serial.isExpiring(1));
}
TEST(SerialKeyTests, parse_validV2Serial_valid)
{
SerialKey serial;
bool r = serial.parse("{v2;trial;pro;Bob;1;email;company name;0;86400}");
EXPECT_EQ(true, r);
EXPECT_EQ(kPro, serial.edition());
EXPECT_FALSE(serial.isExpired(0));
EXPECT_EQ(true, serial.daysLeft(0));
EXPECT_EQ(true, serial.isExpiring(1));
EXPECT_EQ(true, serial.isTrial());
}
TEST(SerialKeyTests, isExpiring_validV2TrialBasicSerial_returnFalse)
{
// {v2;trial;basic;Bob;1;email;company name;1;86400}
SerialKey serial("7B76323B747269616C3B62617369633B426F623B313B656D61696C3B636F6D70616E79206E616D653B313B38363430307D");
EXPECT_EQ(true, serial.isTrial());
EXPECT_FALSE(serial.isExpiring(0));
EXPECT_EQ(kBasic, serial.edition());
}
TEST(SerialKeyTests, isExpiring_expiringV2TrialBasicSerial_returnTrue)
{
// {v2;trial;basic;Bob;1;email;company name;0;86400}
SerialKey serial("7B76323B747269616C3B62617369633B426F623B313B656D61696C3B636F6D70616E79206E616D653B303B38363430307D");
EXPECT_EQ(true, serial.isTrial());
EXPECT_EQ(true, serial.isExpiring(1));
}
TEST(SerialKeyTests, isExpiring_expiredV2TrialBasicSerial_returnFalse)
{
// {v2;trial;basic;Bob;1;email;company name;0;86400}
SerialKey serial("7B76323B747269616C3B62617369633B426F623B313B656D61696C3B636F6D70616E79206E616D653B303B38363430307D");
EXPECT_EQ(true, serial.isTrial());
EXPECT_FALSE(serial.isExpiring(86401));
}
TEST(SerialKeyTests, isExpired_validV2TrialBasicSerial_returnFalse)
{
// {v2;trial;basic;Bob;1;email;company name;0;86400}
SerialKey serial("7B76323B747269616C3B62617369633B426F623B313B656D61696C3B636F6D70616E79206E616D653B303B38363430307D");
EXPECT_EQ(true, serial.isTrial());
EXPECT_FALSE(serial.isExpired(0));
}
TEST(SerialKeyTests, isExpired_expiringV2TrialBasicSerial_returnFalse)
{
// {v2;trial;basic;Bob;1;email;company name;0;86400}
SerialKey serial("7B76323B747269616C3B62617369633B426F623B313B656D61696C3B636F6D70616E79206E616D653B303B38363430307D");
EXPECT_EQ(true, serial.isTrial());
EXPECT_FALSE(serial.isExpired(1));
}
TEST(SerialKeyTests, isExpired_expiredV2TrialBasicSerial_returnTrue)
{
// {v2;trial;basic;Bob;1;email;company name;0;86400}
SerialKey serial("7B76323B747269616C3B62617369633B426F623B313B656D61696C3B636F6D70616E79206E616D653B303B38363430307D");
EXPECT_EQ(true, serial.isTrial());
EXPECT_EQ(true, serial.isExpired(86401));
}
TEST(SerialKeyTests, daysLeft_validExactlyOneDayV2TrialBasicSerial_returnOne)
{
// {v2;trial;basic;Bob;1;email;company name;0;86400}
SerialKey serial("7B76323B747269616C3B62617369633B426F623B313B656D61696C3B636F6D70616E79206E616D653B303B38363430307D");
EXPECT_EQ(1, serial.daysLeft(0));
}
TEST(SerialKeyTests, daysLeft_validWithinOneDayV2TrialBasicSerial_returnOne)
{
// {v2;trial;basic;Bob;1;email;company name;0;86400}
SerialKey serial("7B76323B747269616C3B62617369633B426F623B313B656D61696C3B636F6D70616E79206E616D653B303B38363430307D");
EXPECT_EQ(1, serial.daysLeft(1));
}
TEST(SerialKeyTests, daysLeft_expiredV2TrialBasicSerial_returnZero)
{
// {v2;trial;basic;Bob;1;email;company name;0;86400}
SerialKey serial("7B76323B747269616C3B62617369633B426F623B313B656D61696C3B636F6D70616E79206E616D653B303B38363430307D");
EXPECT_EQ(0, serial.daysLeft(86401));
}

View File

@ -1,11 +1,11 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2014-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

View File

@ -1,114 +0,0 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2015 Synergy Seamless Inc.
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "synergy/SubscriptionManager.h"
#include "synergy/XSynergy.h"
#include "test/global/gtest.h"
TEST(SubscriptionTests, decode_invalidLength_throwException)
{
SubscriptionManager subscriptionManager;
String serial("ABC");
EXPECT_THROW(subscriptionManager.decode(serial), XSubscription);
}
TEST(SubscriptionTests, decode_unrecognizedDigit_throwException)
{
SubscriptionManager subscriptionManager;
String serial("MOCK");
EXPECT_THROW(subscriptionManager.decode(serial), XSubscription);
}
TEST(SubscriptionTests, parsePlainSerial_noParity_throwException)
{
SubscriptionManager subscriptionManager;
String painText("MOCK");
SubscriptionKey key;
EXPECT_THROW(subscriptionManager.parsePlainSerial(painText, key), XSubscription);
}
TEST(SubscriptionTests, parsePlainSerial_invalidSerial_throwException)
{
SubscriptionManager subscriptionManager;
String painText("{MOCK}");
SubscriptionKey key;
EXPECT_THROW(subscriptionManager.parsePlainSerial(painText, key), XSubscription);
}
TEST(SubscriptionTests, parsePlainSerial_validSerial_validSubscriptionKey)
{
// valid until 2 March 2049
SubscriptionManager subscriptionManager;
String painText("{v1;trial;Bob;1;a@a.a;mock company;2147483647;2147483647}");
SubscriptionKey key;
subscriptionManager.parsePlainSerial(painText, key);
EXPECT_EQ("trial", key.m_type);
EXPECT_EQ("Bob", key.m_name);
EXPECT_EQ(1, key.m_userLimit);
EXPECT_EQ("a@a.a", key.m_email);
EXPECT_EQ("mock company", key.m_company);
EXPECT_EQ(2147483647, key.m_warnTime);
EXPECT_EQ(2147483647, key.m_expireTime);
}
TEST(SubscriptionTests, parsePlainSerial_validSerialWithoutCompany_validSubscriptionKey)
{
// valid until 2 March 2049
SubscriptionManager subscriptionManager;
String painText("{v1;trial;Bob;1;a@a.a;;2147483647;2147483647}");
SubscriptionKey key;
subscriptionManager.parsePlainSerial(painText, key);
EXPECT_EQ("trial", key.m_type);
EXPECT_EQ("Bob", key.m_name);
EXPECT_EQ(1, key.m_userLimit);
EXPECT_EQ("a@a.a", key.m_email);
EXPECT_EQ("", key.m_company);
EXPECT_EQ(2147483647, key.m_warnTime);
EXPECT_EQ(2147483647, key.m_expireTime);
}
TEST(SubscriptionTests, parsePlainSerial_expiredTrialSerial_throwException)
{
SubscriptionManager subscriptionManager;
String painText("{v1;trial;Bob;1;1398297600;1398384000}");
SubscriptionKey key;
EXPECT_THROW(subscriptionManager.parsePlainSerial(painText, key), XSubscription);
}
TEST(SubscriptionTests, parsePlainSerial_expiredBasicSerial_validSubscriptionKey)
{
SubscriptionManager subscriptionManager;
String painText("{v1;basic;Bob;1;a@a.a;mock company;1398297600;1398384000}");
SubscriptionKey key;
subscriptionManager.parsePlainSerial(painText, key);
EXPECT_EQ("basic", key.m_type);
EXPECT_EQ("Bob", key.m_name);
EXPECT_EQ(1, key.m_userLimit);
EXPECT_EQ("a@a.a", key.m_email);
EXPECT_EQ("mock company", key.m_company);
EXPECT_EQ(1398297600, key.m_warnTime);
EXPECT_EQ(1398384000, key.m_expireTime);
}