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 ### ### Operating Systems ###
Client: Applesoft Windy OS 10
Server: microOS Tiara 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 ;) **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 config.h
.DS_Store
*.pyc *.pyc
*.o
*~ *~
\.*.swp \.*.swp
*build-gui-Desktop_Qt*
/bin /bin
/lib /lib
/build /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 v1.8.4-stable
============= =============
Bug #5183 - Slowly moving the cursor has no effect on high DPI clients
Bug #4041 UHD/4K DPI scaling broken on Windows servers Bug #4041 - UHD/4K DPI scaling broken on Windows servers
Bug #4420 When XRandR adds a screen, it is inaccessible Bug #4420 - When XRandR adds a screen, it is inaccessible
Bug #5603 Activation notification depends on existence of /etc/os-release Bug #5603 - Activation notification depends on existence of /etc/os-release
Bug #5624 Update notification sometimes requests a downgrade Bug #5624 - Update notification sometimes requests a downgrade
Bug #5329 Current date is shown for build date in the about dialog 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 #5617 Remove redundant plugin infrastructure Enhancement #5627 - Move SSL certificate generation to main window
Enhancement #5627 Move SSL certificate generation to main window Enhancement #5628 - Move SSL implementation into core binary
Enhancement #5628 Move SSL implementation into core binary Enhancement #5629 - Move activation from wizard into new dialog window
Enhancement #5629 Move activation from wizard into new dialog window
v1.8.3-stable v1.8.3-stable
============= =============

View File

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 281 KiB

View File

@ -35,7 +35,7 @@ else()
endif() endif()
target_link_libraries(synergyd 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) if (WIN32)
ADD_CUSTOM_COMMAND( ADD_CUSTOM_COMMAND(

View File

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

View File

@ -13,19 +13,25 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>450</width> <width>450</width>
<height>378</height> <height>300</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="minimumSize">
<size>
<width>450</width>
<height>300</height>
</size>
</property>
<property name="maximumSize"> <property name="maximumSize">
<size> <size>
<width>450</width> <width>450</width>
<height>378</height> <height>300</height>
</size> </size>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -35,20 +41,48 @@
<bool>true</bool> <bool>true</bool>
</property> </property>
<layout class="QGridLayout"> <layout class="QGridLayout">
<item row="0" column="1"> <item row="2" column="1" colspan="2">
<widget class="QLabel" name="label_2"> <widget class="QLabel" name="label_3">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </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> <size>
<width>450</width> <width>20</width>
<height>16777215</height> <height>100</height>
</size> </size>
</property> </property>
</spacer>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_2">
<property name="text"> <property name="text">
<string/> <string/>
</property> </property>
@ -163,41 +197,6 @@
</item> </item>
</layout> </layout>
</item> </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> </layout>
</widget> </widget>
<resources> <resources>

View File

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>440</width> <width>410</width>
<height>314</height> <height>211</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -15,7 +15,7 @@
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<item> <item>
<widget class="QRadioButton" name="m_pRadioButtonActivate"> <widget class="QLabel" name="label">
<property name="font"> <property name="font">
<font> <font>
<weight>75</weight> <weight>75</weight>
@ -23,83 +23,14 @@
</font> </font>
</property> </property>
<property name="text"> <property name="text">
<string>&amp;Account login</string> <string>Serial key</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>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QLabel" name="label_5"> <widget class="QLabel" name="label_5">
<property name="text"> <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>
<property name="openExternalLinks"> <property name="openExternalLinks">
<bool>true</bool> <bool>true</bool>
@ -109,7 +40,10 @@
<item> <item>
<widget class="QTextEdit" name="m_pTextEditSerialKey"> <widget class="QTextEdit" name="m_pTextEditSerialKey">
<property name="enabled"> <property name="enabled">
<bool>false</bool> <bool>true</bool>
</property>
<property name="tabChangesFocus">
<bool>true</bool>
</property> </property>
<property name="html"> <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; <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> </property>
</widget> </widget>
</item> </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> <item>
<widget class="QDialogButtonBox" name="buttonBox"> <widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation"> <property name="orientation">
@ -135,7 +120,12 @@ p, li { white-space: pre-wrap; }
</item> </item>
</layout> </layout>
</widget> </widget>
<resources/> <tabstops>
<tabstop>m_pTextEditSerialKey</tabstop>
</tabstops>
<resources>
<include location="Synergy.qrc"/>
</resources>
<connections> <connections>
<connection> <connection>
<sender>buttonBox</sender> <sender>buttonBox</sender>

View File

@ -19,7 +19,7 @@
<property name="text"> <property name="text">
<string>Are you sure? <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>
<property name="wordWrap"> <property name="wordWrap">
<bool>true</bool> <bool>true</bool>

View File

@ -27,6 +27,57 @@
</property> </property>
<widget class="QWidget" name="centralwidget"> <widget class="QWidget" name="centralwidget">
<layout class="QVBoxLayout" name="verticalLayout_2"> <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> <item>
<widget class="QWidget" name="m_pWidgetUpdate" native="true"> <widget class="QWidget" name="m_pWidgetUpdate" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_2"> <layout class="QHBoxLayout" name="horizontalLayout_2">
@ -40,7 +91,7 @@
<number>0</number> <number>0</number>
</property> </property>
<property name="bottomMargin"> <property name="bottomMargin">
<number>7</number> <number>8</number>
</property> </property>
<item> <item>
<widget class="QLabel" name="m_pIconUpdate"> <widget class="QLabel" name="m_pIconUpdate">

View File

@ -17,7 +17,7 @@
<item> <item>
<widget class="QTabWidget" name="m_pTabWidget"> <widget class="QTabWidget" name="m_pTabWidget">
<property name="currentIndex"> <property name="currentIndex">
<number>2</number> <number>0</number>
</property> </property>
<widget class="QWidget" name="m_pTabScreens"> <widget class="QWidget" name="m_pTabScreens">
<attribute name="title"> <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,39 +7,40 @@
#include "ActivationNotifier.h" #include "ActivationNotifier.h"
#include "MainWindow.h" #include "MainWindow.h"
#include "QUtility.h" #include "QUtility.h"
#include "SubscriptionManager.h" #include "LicenseManager.h"
#include "FailedLoginDialog.h" #include "FailedLoginDialog.h"
#include <QMessageBox> #include <QMessageBox>
#include <QThread> #include <QThread>
#include <iostream> #include <iostream>
ActivationDialog::ActivationDialog(QWidget* parent, AppConfig& appConfig) : ActivationDialog::ActivationDialog(QWidget* parent, AppConfig& appConfig,
LicenseManager& licenseManager) :
QDialog(parent), QDialog(parent),
ui(new Ui::ActivationDialog), ui(new Ui::ActivationDialog),
m_appConfig (&appConfig) m_appConfig(&appConfig),
m_LicenseManager (&licenseManager)
{ {
ui->setupUi(this); ui->setupUi(this);
refreshSerialKey();
time_t currentTime = ::time(0);
if (!m_LicenseManager->serialKey().isExpired(currentTime)) {
ui->m_trialWidget->hide();
}
}
ui->m_pLineEditEmail->setText(appConfig.activateEmail()); void ActivationDialog::refreshSerialKey()
ui->m_pTextEditSerialKey->setText(appConfig.serialKey()); {
ui->m_pTextEditSerialKey->setText(m_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->setFocus();
ui->m_pTextEditSerialKey->moveCursor(QTextCursor::End); ui->m_pTextEditSerialKey->moveCursor(QTextCursor::End);
} else { ui->m_trialLabel->setText(tr("<html><head/><body><p>Your trial has "
if (ui->m_pLineEditEmail->text().isEmpty()) { "expired. <a href=\"https://symless.com/"
ui->m_pLineEditEmail->setFocus(); "synergy/trial/thanks?id=%1\"><span "
} else { "style=\"text-decoration: underline; "
ui->m_pLineEditPassword->setFocus(); "color:#0000ff;\">Buy now!</span></a>"
} "</p></body></html>")
} .arg (m_appConfig->serialKey()));
} }
ActivationDialog::~ActivationDialog() ActivationDialog::~ActivationDialog()
@ -47,119 +48,75 @@ ActivationDialog::~ActivationDialog()
delete ui; 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() void ActivationDialog::reject()
{ {
if (m_LicenseManager->activeEdition() == kUnregistered) {
CancelActivationDialog cancelActivationDialog(this); CancelActivationDialog cancelActivationDialog(this);
if (QDialog::Accepted == cancelActivationDialog.exec()) { if (QDialog::Accepted == cancelActivationDialog.exec()) {
notifyActivation("skip:unknown"); m_LicenseManager->skipActivation();
m_appConfig->activationHasRun(true); m_appConfig->activationHasRun(true);
m_appConfig->saveSettings(); 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();
} else { } else {
ui->m_pLineEditPassword->setFocus(); return;
} }
} }
QDialog::reject();
} }
void ActivationDialog::accept() void ActivationDialog::accept()
{ {
QMessageBox message; QMessageBox message;
QString error;
int edition = Unregistered;
m_appConfig->activationHasRun(true); m_appConfig->activationHasRun(true);
m_appConfig->saveSettings(); m_appConfig->saveSettings();
std::pair<bool, QString> result;
try { try {
if (ui->m_pRadioButtonActivate->isChecked()) { QString serialKey = ui->m_pTextEditSerialKey->toPlainText().trimmed();
WebClient webClient; result = m_LicenseManager->setSerialKey(serialKey);
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());
}
} }
catch (std::exception& e) { catch (std::exception& e) {
message.critical (this, "Unknown Error", message.critical(this, "Unknown Error",
tr("An error occurred while trying to activate Synergy. " tr("An error occurred while trying to activate Synergy. "
"Please contact the helpdesk, and provide the " "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; return;
} }
m_appConfig->setEdition(edition); if (!result.first) {
m_appConfig->saveSettings(); 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(); QDialog::accept();
} }

View File

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

View File

@ -29,6 +29,15 @@ void ActivationNotifier::setIdentity(QString identity)
m_Identity = 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() void ActivationNotifier::notify()
{ {
CoreInterface coreInterface; CoreInterface coreInterface;
@ -39,3 +48,13 @@ void ActivationNotifier::notify()
// catch all exceptions and fails silently // catch all exceptions and fails silently
} }
} }
void ActivationNotifier::notifyUpdate()
{
try {
CoreInterface coreInterface;
coreInterface.notifyUpdate(m_fromVersion, m_toVersion,
m_serialKey);
} catch (...) {
}
}

View File

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

View File

@ -157,11 +157,12 @@ void AppConfig::loadSettings()
} }
m_ElevateMode = static_cast<ElevateMode>(elevateMode.toInt()); m_ElevateMode = static_cast<ElevateMode>(elevateMode.toInt());
m_AutoConfigPrompted = settings().value("autoConfigPrompted", false).toBool(); 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_ActivateEmail = settings().value("activateEmail", "").toString();
m_CryptoEnabled = settings().value("cryptoEnabled", true).toBool(); m_CryptoEnabled = settings().value("cryptoEnabled", true).toBool();
m_AutoHide = settings().value("autoHide", false).toBool(); m_AutoHide = settings().value("autoHide", false).toBool();
m_Serialkey = settings().value("serialKey", "").toString(); m_Serialkey = settings().value("serialKey", "").toString();
m_lastVersion = settings().value("lastVersion", "Unknown").toString();
m_LastExpiringWarningTime = settings().value("lastExpiringWarningTime", 0).toInt(); m_LastExpiringWarningTime = settings().value("lastExpiringWarningTime", 0).toInt();
m_ActivationHasRun = settings().value("activationHasRun", false).toBool(); m_ActivationHasRun = settings().value("activationHasRun", false).toBool();
} }
@ -184,10 +185,10 @@ void AppConfig::saveSettings()
settings().setValue("elevateModeEnum", static_cast<int>(m_ElevateMode)); settings().setValue("elevateModeEnum", static_cast<int>(m_ElevateMode));
settings().setValue("autoConfigPrompted", m_AutoConfigPrompted); settings().setValue("autoConfigPrompted", m_AutoConfigPrompted);
settings().setValue("edition", m_Edition); settings().setValue("edition", m_Edition);
settings().setValue("activateEmail", m_ActivateEmail);
settings().setValue("cryptoEnabled", m_CryptoEnabled); settings().setValue("cryptoEnabled", m_CryptoEnabled);
settings().setValue("autoHide", m_AutoHide); settings().setValue("autoHide", m_AutoHide);
settings().setValue("serialKey", m_Serialkey); settings().setValue("serialKey", m_Serialkey);
settings().setValue("lastVersion", m_lastVersion);
settings().setValue("lastExpiringWarningTime", m_LastExpiringWarningTime); settings().setValue("lastExpiringWarningTime", m_LastExpiringWarningTime);
settings().setValue("activationHasRun", m_ActivationHasRun); settings().setValue("activationHasRun", m_ActivationHasRun);
settings().sync(); settings().sync();
@ -204,6 +205,15 @@ AppConfig& AppConfig::activationHasRun(bool value)
return *this; return *this;
} }
QString AppConfig::lastVersion() const
{
return m_lastVersion;
}
void AppConfig::setLastVersion(QString version) {
m_lastVersion = version;
}
QSettings &AppConfig::settings() { return *m_pSettings; } QSettings &AppConfig::settings() { return *m_pSettings; }
void AppConfig::setScreenName(const QString &s) { m_ScreenName = s; } void AppConfig::setScreenName(const QString &s) { m_ScreenName = s; }
@ -238,27 +248,16 @@ void AppConfig::setAutoConfigPrompted(bool prompted)
m_AutoConfigPrompted = prompted; m_AutoConfigPrompted = prompted;
} }
void AppConfig::setEdition(int e) { void AppConfig::setEdition(Edition e) {
m_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) { QString AppConfig::setSerialKey(QString serial) {
m_ActivateEmail = e; using std::swap;
return true; swap (serial, m_Serialkey);
} return serial;
QString AppConfig::activateEmail() { return m_ActivateEmail; }
bool AppConfig::setSerialKey(QString serial, QString& errorOut) {
if (serial.isEmpty()) {
errorOut = "Your serial key cannot be blank.";
return false;
}
m_Serialkey = serial;
return true;
} }
void AppConfig::clearSerialKey() void AppConfig::clearSerialKey()
@ -287,7 +286,7 @@ void AppConfig::setCryptoEnabled(bool e) {
} }
bool AppConfig::getCryptoEnabled() const { bool AppConfig::getCryptoEnabled() const {
return (edition() == Pro) && m_CryptoEnabled; return (edition() == kPro) && m_CryptoEnabled;
} }
void AppConfig::setAutoHide(bool b) { m_AutoHide = b; } void AppConfig::setAutoHide(bool b) { m_AutoHide = b; }

View File

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

View File

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

View File

@ -24,13 +24,13 @@ class CoreInterface
public: public:
CoreInterface(); CoreInterface();
QString getPluginDir();
QString getProfileDir(); QString getProfileDir();
QString getInstalledDir(); QString getInstalledDir();
QString getArch(); QString getArch();
QString getSubscriptionFilename(); QString getSerialKeyFilePath();
QString activateSerial(const QString& serial);
QString checkSubscription();
QString notifyActivation(const QString& identity); QString notifyActivation(const QString& identity);
QString notifyUpdate (QString const& fromVersion,
QString const& toVersion,
QString const& serialKey);
QString run(const QStringList& args, const QString& input = ""); 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 "ZeroconfService.h"
#include "DataDownloader.h" #include "DataDownloader.h"
#include "CommandProcess.h" #include "CommandProcess.h"
#include "SubscriptionManager.h" #include "LicenseManager.h"
#include "EditionType.h" #include "EditionType.h"
#include "QUtility.h" #include "QUtility.h"
#include "ProcessorArch.h" #include "ProcessorArch.h"
@ -76,12 +76,14 @@ static const char* synergyIconFiles[] =
":/res/icons/16x16/synergy-transfering.png" ":/res/icons/16x16/synergy-transfering.png"
}; };
MainWindow::MainWindow(QSettings& settings, AppConfig& appConfig) : MainWindow::MainWindow(QSettings& settings, AppConfig& appConfig,
LicenseManager& licenseManager) :
m_Settings(settings), m_Settings(settings),
m_AppConfig(appConfig), m_AppConfig(&appConfig),
m_LicenseManager(&licenseManager),
m_pSynergy(NULL), m_pSynergy(NULL),
m_SynergyState(synergyDisconnected), 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_pTempConfigFile(NULL),
m_pTrayIcon(NULL), m_pTrayIcon(NULL),
m_pTrayIconMenu(NULL), m_pTrayIconMenu(NULL),
@ -99,7 +101,8 @@ MainWindow::MainWindow(QSettings& settings, AppConfig& appConfig) :
m_BonjourInstall(NULL), m_BonjourInstall(NULL),
m_SuppressEmptyServerWarning(false), m_SuppressEmptyServerWarning(false),
m_ExpectedRunningState(kStopped), m_ExpectedRunningState(kStopped),
m_pSslCertificate(NULL) m_pSslCertificate(NULL),
m_ActivationDialogRunning(false)
{ {
setupUi(this); setupUi(this);
@ -134,13 +137,34 @@ MainWindow::MainWindow(QSettings& settings, AppConfig& appConfig) :
m_SuppressAutoConfigWarning = false; m_SuppressAutoConfigWarning = false;
m_pComboServerList->hide(); m_pComboServerList->hide();
setEdition(m_AppConfig.edition());
m_pLabelPadlock->hide(); m_pLabelPadlock->hide();
connect (this, SIGNAL(windowShown()), this, SLOT(on_windowShown()), Qt::QueuedConnection); m_trialWidget->hide();
connect (&m_AppConfig, SIGNAL(editionSet(int)), this, SLOT(setEdition(int)), Qt::QueuedConnection);
connect (&m_AppConfig, SIGNAL(sslToggled(bool)), this, SLOT(sslToggled(bool)), Qt::QueuedConnection); 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() MainWindow::~MainWindow()
@ -397,15 +421,17 @@ void MainWindow::appendLogRaw(const QString& text)
foreach(QString line, text.split(QRegExp("\r|\n|\r\n"))) { foreach(QString line, text.split(QRegExp("\r|\n|\r\n"))) {
if (!line.isEmpty()) { if (!line.isEmpty()) {
m_pLogOutput->append(line); 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); checkConnected(line);
checkFingerprint(line); checkFingerprint(line);
checkLicense(line);
} }
void MainWindow::checkConnected(const QString& 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) void MainWindow::checkFingerprint(const QString& line)
{ {
QRegExp fingerprintRegex(".*server fingerprint: ([A-F0-9:]+)"); QRegExp fingerprintRegex(".*server fingerprint: ([A-F0-9:]+)");
@ -498,7 +532,7 @@ void MainWindow::restartSynergy()
void MainWindow::proofreadInfo() void MainWindow::proofreadInfo()
{ {
setEdition(m_AppConfig.edition()); // Why is this here? setEdition(m_AppConfig->edition()); // Why is this here?
int oldState = m_SynergyState; int oldState = m_SynergyState;
m_SynergyState = synergyDisconnected; m_SynergyState = synergyDisconnected;
@ -518,6 +552,14 @@ void MainWindow::clearLog()
void MainWindow::startSynergy() 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 desktopMode = appConfig().processMode() == Desktop;
bool serviceMode = appConfig().processMode() == Service; bool serviceMode = appConfig().processMode() == Service;
@ -566,7 +608,7 @@ void MainWindow::startSynergy()
#endif #endif
if (m_AppConfig.getCryptoEnabled()) { if (m_AppConfig->getCryptoEnabled()) {
args << "--enable-crypto"; args << "--enable-crypto";
} }
@ -734,19 +776,6 @@ QString MainWindow::appPath(const QString& name)
bool MainWindow::serverArgs(QStringList& args, QString& app) 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()); app = appPath(appConfig().synergysName());
if (!QFile::exists(app)) if (!QFile::exists(app))
@ -775,6 +804,10 @@ bool MainWindow::serverArgs(QStringList& args, QString& app)
#endif #endif
args << "-c" << configFilename << "--address" << address(); args << "-c" << configFilename << "--address" << address();
if (!appConfig().serialKey().isEmpty()) {
args << "--serial-key" << appConfig().serialKey();
}
#if defined(Q_OS_WIN) #if defined(Q_OS_WIN)
// pass in physical resolution and primary screen center // pass in physical resolution and primary screen center
// TODO: get this information in the core binary even when // TODO: get this information in the core binary even when
@ -895,7 +928,7 @@ void MainWindow::setSynergyState(qSynergyState state)
switch (state) switch (state)
{ {
case synergyConnected: { case synergyConnected: {
if (m_AppConfig.getCryptoEnabled()) { if (m_AppConfig->getCryptoEnabled()) {
m_pLabelPadlock->show(); m_pLabelPadlock->show();
} }
else { else {
@ -1010,13 +1043,13 @@ void MainWindow::updateZeroconfService()
QMutexLocker locker(&m_UpdateZeroconfMutex); QMutexLocker locker(&m_UpdateZeroconfMutex);
if (isBonjourRunning()) { if (isBonjourRunning()) {
if (!m_AppConfig.wizardShouldRun()) { if (!m_AppConfig->wizardShouldRun()) {
if (m_pZeroconfService) { if (m_pZeroconfService) {
delete m_pZeroconfService; delete m_pZeroconfService;
m_pZeroconfService = NULL; m_pZeroconfService = NULL;
} }
if (m_AppConfig.autoConfig() || synergyType() == synergyServer) { if (m_AppConfig->autoConfig() || synergyType() == synergyServer) {
m_pZeroconfService = new ZeroconfService(this); 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)); setWindowTitle(m_LicenseManager->getEditionName (edition));
if (m_AppConfig.getCryptoEnabled()) { if (m_AppConfig->getCryptoEnabled()) {
m_pSslCertificate = new SslCertificate(this); m_pSslCertificate = new SslCertificate(this);
m_pSslCertificate->generateCertificate(); m_pSslCertificate->generateCertificate();
} }
@ -1046,9 +1079,60 @@ void MainWindow::setEdition(int edition)
saveSettings(); 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() void MainWindow::updateLocalFingerprint()
{ {
if (m_AppConfig.getCryptoEnabled() && Fingerprint::local().fileExists()) { if (m_AppConfig->getCryptoEnabled() && Fingerprint::local().fileExists()) {
m_pLabelFingerprint->setVisible(true); m_pLabelFingerprint->setVisible(true);
m_pLabelLocalFingerprint->setVisible(true); m_pLabelLocalFingerprint->setVisible(true);
m_pLabelLocalFingerprint->setText(Fingerprint::local().readFirst()); 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) void MainWindow::on_m_pGroupClient_toggled(bool on)
{ {
m_pGroupServer->setChecked(!on); m_pGroupServer->setChecked(!on);
@ -1123,6 +1213,14 @@ void MainWindow::on_m_pActionSettings_triggered()
void MainWindow::autoAddScreen(const QString name) void MainWindow::autoAddScreen(const QString name)
{ {
if (!m_ServerConfig.ignoreAutoConfigClient()) { 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); int r = m_ServerConfig.autoAddScreen(name);
if (r != kAutoAddScreenOk) { if (r != kAutoAddScreenOk) {
switch (r) { switch (r) {
@ -1160,8 +1258,7 @@ void MainWindow::on_m_pButtonConfigureServer_clicked()
void MainWindow::on_m_pActivate_triggered() void MainWindow::on_m_pActivate_triggered()
{ {
ActivationDialog activationDialog (this, this->appConfig()); raiseActivationDialog();
activationDialog.exec();
} }
void MainWindow::on_m_pButtonApply_clicked() void MainWindow::on_m_pButtonApply_clicked()
@ -1325,16 +1422,16 @@ void MainWindow::promptAutoConfig()
QMessageBox::Yes | QMessageBox::No); QMessageBox::Yes | QMessageBox::No);
if (r == QMessageBox::Yes) { if (r == QMessageBox::Yes) {
m_AppConfig.setAutoConfig(true); m_AppConfig->setAutoConfig(true);
downloadBonjour(); downloadBonjour();
} }
else { else {
m_AppConfig.setAutoConfig(false); m_AppConfig->setAutoConfig(false);
m_pCheckBoxAutoConfig->setChecked(false); m_pCheckBoxAutoConfig->setChecked(false);
} }
} }
m_AppConfig.setAutoConfigPrompted(true); m_AppConfig->setAutoConfigPrompted(true);
} }
void MainWindow::on_m_pComboServerList_currentIndexChanged(QString ) void MainWindow::on_m_pComboServerList_currentIndexChanged(QString )
@ -1380,11 +1477,37 @@ void MainWindow::bonjourInstallFinished()
m_pCheckBoxAutoConfig->setChecked(true); 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() void MainWindow::on_windowShown()
{ {
if (!m_AppConfig.activationHasRun() && (m_AppConfig.edition() == Unregistered)) { time_t currentTime = ::time(0);
ActivationDialog activationDialog (this, m_AppConfig); if (!m_AppConfig->activationHasRun()
activationDialog.exec(); && ((m_AppConfig->edition() == kUnregistered) ||
(m_LicenseManager->serialKey().isExpired(currentTime)))) {
raiseActivationDialog();
} }
} }

View File

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

View File

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

View File

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

View File

@ -19,7 +19,7 @@
#include "MainWindow.h" #include "MainWindow.h"
#include "WebClient.h" #include "WebClient.h"
#include "ActivationNotifier.h" #include "ActivationNotifier.h"
#include "SubscriptionManager.h" #include "LicenseManager.h"
#include "EditionType.h" #include "EditionType.h"
#include "QSynergyApplication.h" #include "QSynergyApplication.h"
#include "QUtility.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

@ -20,6 +20,7 @@
#define TRAY_RETRY_WAIT 2000 #define TRAY_RETRY_WAIT 2000
#include "QSynergyApplication.h" #include "QSynergyApplication.h"
#include "LicenseManager.h"
#include "MainWindow.h" #include "MainWindow.h"
#include "AppConfig.h" #include "AppConfig.h"
#include "SetupWizard.h" #include "SetupWizard.h"
@ -82,11 +83,13 @@ int main(int argc, char* argv[])
#endif #endif
QSettings settings; QSettings settings;
AppConfig appConfig(&settings); AppConfig appConfig (&settings);
qRegisterMetaType<Edition>("Edition");
LicenseManager licenseManager (&appConfig);
app.switchTranslator(appConfig.language()); app.switchTranslator(appConfig.language());
MainWindow mainWindow(settings, appConfig); MainWindow mainWindow(settings, appConfig, licenseManager);
SetupWizard setupWizard(mainWindow, true); SetupWizard setupWizard(mainWindow, true);
if (appConfig.wizardShouldRun()) if (appConfig.wizardShouldRun())

View File

@ -25,7 +25,7 @@ add_subdirectory(net)
add_subdirectory(platform) add_subdirectory(platform)
add_subdirectory(server) add_subdirectory(server)
add_subdirectory(synergy) add_subdirectory(synergy)
add_subdirectory(shared)
if (WIN32) if (WIN32)
add_subdirectory(synwinhk) 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); char* resultCStr = curl_easy_escape(m_curl, url.c_str(), 0);
if (resultCStr == NULL) { if (resultCStr == NULL) {
curl_free(resultCStr);
throw XArch("CURL escape failed."); throw XArch("CURL escape failed.");
} }

View File

@ -42,13 +42,6 @@ public:
virtual IDataSocket* virtual IDataSocket*
accept() = 0; 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 // ISocket overrides

View File

@ -93,14 +93,3 @@ SecureListenSocket::accept()
throw ex; 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 // IListenSocket overrides
virtual IDataSocket* virtual IDataSocket*
accept(); accept();
void deleteSocket(void*);
private: private:
typedef std::set<IDataSocket*> SecureSocketSet; typedef std::set<IDataSocket*> SecureSocketSet;

View File

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

View File

@ -19,7 +19,7 @@ if (WIN32)
file(GLOB sources "MSWindows*.cpp") file(GLOB sources "MSWindows*.cpp")
elseif (APPLE) elseif (APPLE)
file(GLOB headers "OSX*.h" "IOSX*.h") 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) elseif (UNIX)
file(GLOB headers "XWindows*.h") file(GLOB headers "XWindows*.h")
file(GLOB sources "XWindows*.cpp") file(GLOB sources "XWindows*.cpp")

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -45,11 +45,13 @@
#include "base/Log.h" #include "base/Log.h"
#include "base/TMethodEventJob.h" #include "base/TMethodEventJob.h"
#include "common/stdexcept.h" #include "common/stdexcept.h"
#include "shared/SerialKey.h"
#include <cstring> #include <cstring>
#include <cstdlib> #include <cstdlib>
#include <sstream> #include <sstream>
#include <fstream> #include <fstream>
#include <ctime>
// //
// Server // Server
@ -60,7 +62,7 @@ Server::Server(
PrimaryClient* primaryClient, PrimaryClient* primaryClient,
synergy::Screen* screen, synergy::Screen* screen,
IEventQueue* events, IEventQueue* events,
bool enableDragDrop) : ServerArgs const& args) :
m_mock(false), m_mock(false),
m_primaryClient(primaryClient), m_primaryClient(primaryClient),
m_active(primaryClient), m_active(primaryClient),
@ -91,10 +93,10 @@ Server::Server(
m_sendFileThread(NULL), m_sendFileThread(NULL),
m_writeToDropDirThread(NULL), m_writeToDropDirThread(NULL),
m_ignoreFileTransfer(false), m_ignoreFileTransfer(false),
m_enableDragDrop(enableDragDrop),
m_enableClipboard(true), m_enableClipboard(true),
m_sendDragInfoThread(NULL), m_sendDragInfoThread(NULL),
m_waitDragInfoThread(true) m_waitDragInfoThread(true),
m_args(args)
{ {
// must have a primary client and it must have a canonical name // must have a primary client and it must have a canonical name
assert(m_primaryClient != NULL); assert(m_primaryClient != NULL);
@ -184,7 +186,7 @@ Server::Server(
new TMethodEventJob<Server>(this, new TMethodEventJob<Server>(this,
&Server::handleFakeInputEndEvent)); &Server::handleFakeInputEndEvent));
if (m_enableDragDrop) { if (m_args.m_enableDragDrop) {
m_events->adoptHandler(m_events->forFile().fileChunkSending(), m_events->adoptHandler(m_events->forFile().fileChunkSending(),
this, this,
new TMethodEventJob<Server>(this, new TMethodEventJob<Server>(this,
@ -451,6 +453,13 @@ Server::switchScreen(BaseClientProxy* dst,
SInt32 x, SInt32 y, bool forScreensaver) SInt32 x, SInt32 y, bool forScreensaver)
{ {
assert(dst != NULL); 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 #ifndef NDEBUG
{ {
SInt32 dx, dy, dw, dh; SInt32 dx, dy, dw, dh;
@ -1378,10 +1387,7 @@ Server::handleClientDisconnected(const Event&, void* vclient)
removeActiveClient(client); removeActiveClient(client);
removeOldClient(client); removeOldClient(client);
PacketStreamFilter* streamFileter = dynamic_cast<PacketStreamFilter*>(client->getStream());
TCPSocket* socket = dynamic_cast<TCPSocket*>(streamFileter->getStream());
delete client; delete client;
m_clientListener->deleteSocket(socket);
} }
void void
@ -1391,10 +1397,8 @@ Server::handleClientCloseTimeout(const Event&, void* vclient)
BaseClientProxy* client = static_cast<BaseClientProxy*>(vclient); BaseClientProxy* client = static_cast<BaseClientProxy*>(vclient);
LOG((CLOG_NOTE "forced disconnection of client \"%s\"", getName(client).c_str())); LOG((CLOG_NOTE "forced disconnection of client \"%s\"", getName(client).c_str()));
removeOldClient(client); removeOldClient(client);
PacketStreamFilter* streamFileter = dynamic_cast<PacketStreamFilter*>(client->getStream());
TCPSocket* socket = dynamic_cast<TCPSocket*>(streamFileter->getStream());
delete client; delete client;
m_clientListener->deleteSocket(socket);
} }
void void
@ -1706,7 +1710,7 @@ Server::onMouseUp(ButtonID id)
return; return;
} }
if (m_enableDragDrop) { if (m_args.m_enableDragDrop) {
if (!m_screen->isOnScreen()) { if (!m_screen->isOnScreen()) {
String& file = m_screen->getDraggingFilename(); String& file = m_screen->getDraggingFilename();
if (!file.empty()) { if (!file.empty()) {
@ -1791,7 +1795,7 @@ Server::onMouseMovePrimary(SInt32 x, SInt32 y)
// should we switch or not? // should we switch or not?
if (isSwitchOkay(newScreen, dir, x, y, xc, yc)) { if (isSwitchOkay(newScreen, dir, x, y, xc, yc)) {
if (m_enableDragDrop if (m_args.m_enableDragDrop
&& m_screen->isDraggingStarted() && m_screen->isDraggingStarted()
&& m_active != newScreen && m_active != newScreen
&& m_waitDragInfoThread) { && m_waitDragInfoThread) {
@ -2393,7 +2397,7 @@ Server::sendFileThread(void* data)
void void
Server::dragInfoReceived(UInt32 fileNum, String content) Server::dragInfoReceived(UInt32 fileNum, String content)
{ {
if (!m_enableDragDrop) { if (!m_args.m_enableDragDrop) {
LOG((CLOG_DEBUG "drag drop not enabled, ignoring drag info.")); LOG((CLOG_DEBUG "drag drop not enabled, ignoring drag info."));
return; return;
} }

View File

@ -25,6 +25,7 @@
#include "synergy/mouse_types.h" #include "synergy/mouse_types.h"
#include "synergy/INode.h" #include "synergy/INode.h"
#include "synergy/DragInformation.h" #include "synergy/DragInformation.h"
#include "synergy/ServerArgs.h"
#include "base/Event.h" #include "base/Event.h"
#include "base/Stopwatch.h" #include "base/Stopwatch.h"
#include "base/EventTypes.h" #include "base/EventTypes.h"
@ -106,7 +107,7 @@ public:
ownership of \p primaryClient. ownership of \p primaryClient.
*/ */
Server(Config& config, PrimaryClient* primaryClient, Server(Config& config, PrimaryClient* primaryClient,
synergy::Screen* screen, IEventQueue* events, bool enableDragDrop); synergy::Screen* screen, IEventQueue* events, ServerArgs const& args);
~Server(); ~Server();
#ifdef TEST_ENV #ifdef TEST_ENV
@ -472,11 +473,11 @@ private:
Thread* m_writeToDropDirThread; Thread* m_writeToDropDirThread;
String m_dragFileExt; String m_dragFileExt;
bool m_ignoreFileTransfer; bool m_ignoreFileTransfer;
bool m_enableDragDrop;
bool m_enableClipboard; bool m_enableClipboard;
Thread* m_sendDragInfoThread; Thread* m_sendDragInfoThread;
bool m_waitDragInfoThread; bool m_waitDragInfoThread;
ClientListener* m_clientListener; 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! */ /* Do not reorder these! */
enum EditionType { enum Edition {
Basic, kBasic,
Pro, kPro,
Trial, Trial_DO_NOT_USE_OR_THERE_WILL_BE_PAIN,
Unregistered kUnregistered
}; };
#endif // EDITIONTYPE_H #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

@ -74,6 +74,9 @@ ArgParser::parseServerArgs(ServerArgs& args, int argc, const char* const* argv)
else if (isArg(i, argc, argv, "", "--prm-hc", 1)) { else if (isArg(i, argc, argv, "", "--prm-hc", 1)) {
DpiHelper::s_primaryHeightCenter = synergy::string::stringToSizeType(argv[++i]); DpiHelper::s_primaryHeightCenter = synergy::string::stringToSizeType(argv[++i]);
} }
else if (isArg(i, argc, argv, "", "--serial-key", 1)) {
args.m_serial = SerialKey(argv[++i]);
}
else { else {
LOG((CLOG_PRINT "%s: unrecognized option `%s'" BYE, args.m_pname, argv[i], args.m_pname)); LOG((CLOG_PRINT "%s: unrecognized option `%s'" BYE, args.m_pname, argv[i], args.m_pname));
return false; return false;
@ -193,18 +196,10 @@ ArgParser::parseToolArgs(ToolArgs& args, int argc, const char* const* argv)
args.m_loginAuthenticate = true; args.m_loginAuthenticate = true;
return 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)) { else if (isArg(i, argc, argv, NULL, "--get-installed-dir", 0)) {
args.m_getInstalledDir = true; args.m_getInstalledDir = true;
return 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)) { else if (isArg(i, argc, argv, NULL, "--get-profile-dir", 0)) {
args.m_getProfileDir = true; args.m_getProfileDir = true;
return true; return true;
@ -213,26 +208,14 @@ ArgParser::parseToolArgs(ToolArgs& args, int argc, const char* const* argv)
args.m_getArch = true; args.m_getArch = true;
return 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)) { else if (isArg(i, argc, argv, NULL, "--notify-activation", 0)) {
args.m_notifyActivation = true; args.m_notifyActivation = true;
return true; return true;
} }
else if (isArg(i, argc, argv, NULL, "--notify-update", 0)) {
args.m_notifyUpdate = true;
return true;
}
else { else {
return false; return false;
} }

View File

@ -647,7 +647,7 @@ ServerApp::openClientListener(const NetworkAddress& address)
Server* Server*
ServerApp::openServer(Config& config, PrimaryClient* primaryClient) 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 { try {
m_events->adoptHandler( m_events->adoptHandler(
m_events->forServer().disconnected(), server, m_events->forServer().disconnected(), server,

View File

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

View File

@ -18,6 +18,7 @@
#pragma once #pragma once
#include "synergy/ArgsBase.h" #include "synergy/ArgsBase.h"
#include "shared/SerialKey.h"
class NetworkAddress; class NetworkAddress;
class Config; class Config;
@ -28,5 +29,6 @@ public:
public: public:
String m_configFile; String m_configFile;
SerialKey m_serial;
Config* m_config; 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

@ -18,7 +18,6 @@
#include "synergy/ToolApp.h" #include "synergy/ToolApp.h"
#include "synergy/ArgParser.h" #include "synergy/ArgParser.h"
#include "synergy/SubscriptionManager.h"
#include "arch/Arch.h" #include "arch/Arch.h"
#include "base/Log.h" #include "base/Log.h"
#include "base/String.h" #include "base/String.h"
@ -72,50 +71,17 @@ ToolApp::run(int argc, char** argv)
else if (m_args.m_loginAuthenticate) { else if (m_args.m_loginAuthenticate) {
loginAuth(); loginAuth();
} }
else if (m_args.m_getPluginList) {
getPluginList();
}
else if (m_args.m_getInstalledDir) { else if (m_args.m_getInstalledDir) {
std::cout << ARCH->getInstalledDirectory() << std::endl; std::cout << ARCH->getInstalledDirectory() << std::endl;
} }
else if (m_args.m_getPluginDir) {
std::cout << ARCH->getPluginDirectory() << std::endl;
}
else if (m_args.m_getProfileDir) { else if (m_args.m_getProfileDir) {
std::cout << ARCH->getProfileDirectory() << std::endl; std::cout << ARCH->getProfileDirectory() << std::endl;
} }
else if (m_args.m_getArch) { else if (m_args.m_getArch) {
std::cout << ARCH->getPlatformName() << std::endl; std::cout << ARCH->getPlatformName() << std::endl;
} }
else if (!m_args.m_subscriptionSerial.empty()) { else if (m_args.m_notifyUpdate) {
try { notifyUpdate();
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_notifyActivation) { else if (m_args.m_notifyActivation) {
notifyActivation(); notifyActivation();
@ -172,8 +138,26 @@ ToolApp::loginAuth()
} }
void 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

View File

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

View File

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

View File

@ -26,13 +26,9 @@ public:
public: public:
bool m_printActiveDesktopName; bool m_printActiveDesktopName;
bool m_loginAuthenticate; bool m_loginAuthenticate;
bool m_getPluginList;
bool m_getPluginDir;
bool m_getInstalledDir; bool m_getInstalledDir;
bool m_getProfileDir; bool m_getProfileDir;
bool m_getArch; bool m_getArch;
bool m_getSubscriptionFilename;
bool m_checkSubscription;
bool m_notifyActivation; 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, isScreen(_)).WillByDefault(Return(true));
ON_CALL(serverConfig, getInputFilter()).WillByDefault(Return(&serverInputFilter)); 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; server.m_mock = true;
listener.setServer(&server); listener.setServer(&server);
@ -142,10 +144,10 @@ TEST_F(NetworkTests, sendToClient_mockData)
ON_CALL(clientScreen, getCursorPos(_, _)).WillByDefault(Invoke(getCursorPos)); ON_CALL(clientScreen, getCursorPos(_, _)).WillByDefault(Invoke(getCursorPos));
ClientArgs args; ClientArgs clientArgs;
args.m_enableDragDrop = true; clientArgs.m_enableDragDrop = true;
args.m_enableCrypto = false; clientArgs.m_enableCrypto = false;
Client client(&m_events, "stub", serverAddress, clientSocketFactory, &clientScreen, args); Client client(&m_events, "stub", serverAddress, clientSocketFactory, &clientScreen, clientArgs);
m_events.adoptHandler( m_events.adoptHandler(
m_events.forFile().fileRecieveCompleted(), &client, m_events.forFile().fileRecieveCompleted(), &client,
@ -185,7 +187,9 @@ TEST_F(NetworkTests, sendToClient_mockFile)
ON_CALL(serverConfig, isScreen(_)).WillByDefault(Return(true)); ON_CALL(serverConfig, isScreen(_)).WillByDefault(Return(true));
ON_CALL(serverConfig, getInputFilter()).WillByDefault(Return(&serverInputFilter)); 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; server.m_mock = true;
listener.setServer(&server); listener.setServer(&server);
@ -198,10 +202,10 @@ TEST_F(NetworkTests, sendToClient_mockFile)
ON_CALL(clientScreen, getCursorPos(_, _)).WillByDefault(Invoke(getCursorPos)); ON_CALL(clientScreen, getCursorPos(_, _)).WillByDefault(Invoke(getCursorPos));
ClientArgs args; ClientArgs clientArgs;
args.m_enableDragDrop = true; clientArgs.m_enableDragDrop = true;
args.m_enableCrypto = false; clientArgs.m_enableCrypto = false;
Client client(&m_events, "stub", serverAddress, clientSocketFactory, &clientScreen, args); Client client(&m_events, "stub", serverAddress, clientSocketFactory, &clientScreen, clientArgs);
m_events.adoptHandler( m_events.adoptHandler(
m_events.forFile().fileRecieveCompleted(), &client, m_events.forFile().fileRecieveCompleted(), &client,
@ -235,7 +239,9 @@ TEST_F(NetworkTests, sendToServer_mockData)
ON_CALL(serverConfig, isScreen(_)).WillByDefault(Return(true)); ON_CALL(serverConfig, isScreen(_)).WillByDefault(Return(true));
ON_CALL(serverConfig, getInputFilter()).WillByDefault(Return(&serverInputFilter)); 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; server.m_mock = true;
listener.setServer(&server); listener.setServer(&server);
@ -247,10 +253,10 @@ TEST_F(NetworkTests, sendToServer_mockData)
ON_CALL(clientScreen, getShape(_, _, _, _)).WillByDefault(Invoke(getScreenShape)); ON_CALL(clientScreen, getShape(_, _, _, _)).WillByDefault(Invoke(getScreenShape));
ON_CALL(clientScreen, getCursorPos(_, _)).WillByDefault(Invoke(getCursorPos)); ON_CALL(clientScreen, getCursorPos(_, _)).WillByDefault(Invoke(getCursorPos));
ClientArgs args; ClientArgs clientArgs;
args.m_enableDragDrop = true; clientArgs.m_enableDragDrop = true;
args.m_enableCrypto = false; clientArgs.m_enableCrypto = false;
Client client(&m_events, "stub", serverAddress, clientSocketFactory, &clientScreen, args); Client client(&m_events, "stub", serverAddress, clientSocketFactory, &clientScreen, clientArgs);
m_events.adoptHandler( m_events.adoptHandler(
m_events.forClientListener().connected(), &listener, m_events.forClientListener().connected(), &listener,
@ -290,7 +296,9 @@ TEST_F(NetworkTests, sendToServer_mockFile)
ON_CALL(serverConfig, isScreen(_)).WillByDefault(Return(true)); ON_CALL(serverConfig, isScreen(_)).WillByDefault(Return(true));
ON_CALL(serverConfig, getInputFilter()).WillByDefault(Return(&serverInputFilter)); 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; server.m_mock = true;
listener.setServer(&server); listener.setServer(&server);
@ -302,10 +310,10 @@ TEST_F(NetworkTests, sendToServer_mockFile)
ON_CALL(clientScreen, getShape(_, _, _, _)).WillByDefault(Invoke(getScreenShape)); ON_CALL(clientScreen, getShape(_, _, _, _)).WillByDefault(Invoke(getScreenShape));
ON_CALL(clientScreen, getCursorPos(_, _)).WillByDefault(Invoke(getCursorPos)); ON_CALL(clientScreen, getCursorPos(_, _)).WillByDefault(Invoke(getCursorPos));
ClientArgs args; ClientArgs clientArgs;
args.m_enableDragDrop = true; clientArgs.m_enableDragDrop = true;
args.m_enableCrypto = false; clientArgs.m_enableCrypto = false;
Client client(&m_events, "stub", serverAddress, clientSocketFactory, &clientScreen, args); Client client(&m_events, "stub", serverAddress, clientSocketFactory, &clientScreen, clientArgs);
m_events.adoptHandler( m_events.adoptHandler(
m_events.forClientListener().connected(), &listener, m_events.forClientListener().connected(), &listener,

View File

@ -68,4 +68,4 @@ endif()
add_executable(unittests ${sources}) add_executable(unittests ${sources})
target_link_libraries(unittests 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,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);
}