diff --git a/CMakeLists.txt b/CMakeLists.txt
index 38dff936..f2863384 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -349,6 +349,7 @@ set_property(
TARGET ${LIB_CXX_PROJECT_NAME}
PROPERTY INCLUDE_DIRECTORIES
"${LIB_CXX_INCLUDE_PATHS}"
+ "${LIB_LICENSE_INCLUDE_PATHS}"
"${LIB_UTILITY_INCLUDE_PATHS}"
"${LIB_INCLUDE_PATHS}"
)
diff --git a/bin/app/user/ApplicationSettings_template.xml b/bin/app/user/ApplicationSettings_template.xml
index 7ad86d6a..5c3498b7 100644
--- a/bin/app/user/ApplicationSettings_template.xml
+++ b/bin/app/user/ApplicationSettings_template.xml
@@ -82,7 +82,6 @@
-
diff --git a/bin/test/data/GeneratorTestSuite/private-v2.pem b/bin/test/data/LicenseGeneratorTestSuite/private-v2.pem
similarity index 100%
rename from bin/test/data/GeneratorTestSuite/private-v2.pem
rename to bin/test/data/LicenseGeneratorTestSuite/private-v2.pem
diff --git a/src/app/main.cpp b/src/app/main.cpp
index 3f16a1eb..e91be77f 100644
--- a/src/app/main.cpp
+++ b/src/app/main.cpp
@@ -15,7 +15,6 @@
#include "QtCoreApplication.h"
#include "utilityQt.h"
#include "QtViewFactory.h"
-#include "QtEulaWindow.h"
#include "ApplicationSettings.h"
#include "CommandLineParser.h"
#include "ConsoleLogger.h"
@@ -258,7 +257,7 @@ int main(int argc, char *argv[])
// check if already agreed to EULA
ApplicationSettings* appSettings = ApplicationSettings::getInstance().get();
- if (appSettings->getAcceptedEulaVersion() < QtEulaWindow::EULA_VERSION)
+ if (appSettings->getAcceptedEulaVersion() < Application::EULA_VERSION)
{
if (!commandLineParser.acceptedEULA())
{
@@ -282,7 +281,7 @@ int main(int argc, char *argv[])
}
std::cout << "\nSourcetrail End User License Agreement accepted.\n" << std::endl;
- appSettings->setAcceptedEulaVersion(QtEulaWindow::EULA_VERSION);
+ appSettings->setAcceptedEulaVersion(Application::EULA_VERSION);
appSettings->save();
}
diff --git a/src/lib/Application.cpp b/src/lib/Application.cpp
index e889e597..342f523f 100644
--- a/src/lib/Application.cpp
+++ b/src/lib/Application.cpp
@@ -1,36 +1,36 @@
#include "Application.h"
-#include "IDECommunicationController.h"
-#include "NetworkFactory.h"
-#include "DialogView.h"
-#include "GraphViewStyle.h"
-#include "MainView.h"
-#include "ViewFactory.h"
-#include "StorageCache.h"
-#include "LicenseChecker.h"
#include "ApplicationSettings.h"
-#include "ProjectSettings.h"
+#include "AppPath.h"
#include "ColorScheme.h"
+#include "DialogView.h"
#include "FileSystem.h"
-#include "SharedMemoryGarbageCollector.h"
+#include "GraphViewStyle.h"
+#include "IDECommunicationController.h"
+#include "LicenseChecker.h"
#include "logging.h"
#include "LogManager.h"
+#include "MainView.h"
#include "MessageFilterErrorCountUpdate.h"
#include "MessageFilterFocusInOut.h"
#include "MessageFilterSearchAutocomplete.h"
#include "MessageQueue.h"
-#include "MessageForceEnterLicense.h"
#include "MessageQuitApplication.h"
#include "MessageStatus.h"
+#include "NetworkFactory.h"
+#include "ProjectSettings.h"
+#include "SharedMemoryGarbageCollector.h"
+#include "StorageCache.h"
#include "TabId.h"
#include "TaskManager.h"
#include "TaskScheduler.h"
#include "tracing.h"
+#include "UpdateChecker.h"
#include "UserPaths.h"
#include "utilityString.h"
#include "utilityUuid.h"
#include "Version.h"
-#include "UpdateChecker.h"
+#include "ViewFactory.h"
std::shared_ptr Application::s_instance;
std::string Application::s_uuid;
@@ -38,7 +38,17 @@ std::string Application::s_uuid;
void Application::createInstance(
const Version& version, ViewFactory* viewFactory, NetworkFactory* networkFactory
){
+ bool hasGui = (viewFactory != nullptr);
+
Version::setApplicationVersion(version);
+ LicenseChecker::loadPublicKey();
+ LicenseChecker::setEncodeKey(AppPath::getAppPath().str());
+
+ if (hasGui)
+ {
+ GraphViewStyle::setImpl(viewFactory->createGraphStyleImpl());
+ }
+
loadSettings();
SharedMemoryGarbageCollector* collector = SharedMemoryGarbageCollector::createInstance();
@@ -51,7 +61,6 @@ void Application::createInstance(
TaskManager::createScheduler(TabId::background());
MessageQueue::getInstance();
- bool hasGui = (viewFactory != nullptr);
s_instance = std::shared_ptr(new Application(hasGui));
s_instance->m_storageCache = std::make_shared();
@@ -60,9 +69,6 @@ void Application::createInstance(
{
s_instance->m_mainView = viewFactory->createMainView(s_instance->m_storageCache.get());
s_instance->m_mainView->setup();
- s_instance->updateTitle();
-
- GraphViewStyle::setImpl(viewFactory->createGraphStyleImpl());
}
if (networkFactory != nullptr)
@@ -121,7 +127,6 @@ void Application::loadStyle(const FilePath& colorSchemePath)
Application::Application(bool withGUI)
: m_hasGUI(withGUI)
- , m_licenseType(MessageEnteredLicense::LICENSE_NONE)
, m_lastLicenseCheck(TimeStamp::now())
{
}
@@ -207,21 +212,6 @@ void Application::handleMessage(MessageActivateWindow* message)
}
}
-void Application::handleMessage(MessageEnteredLicense* message)
-{
- MessageStatus(L"Found valid license key, unlocked application.").dispatch();
-
- m_licenseType = message->type;
-
- updateTitle();
- loadSettings();
-
- if (m_hasGUI)
- {
- m_mainView->refreshViews();
- }
-}
-
void Application::handleMessage(MessageIndexingFinished* message)
{
logStorageStats();
@@ -241,11 +231,7 @@ void Application::handleMessage(MessageLoadProject* message)
TRACE("app load project");
FilePath projectSettingsFilePath(message->projectSettingsFilePath);
- if (m_hasGUI)
- {
- bool showStartWindow = projectSettingsFilePath.empty();
- m_mainView->loadWindow(showStartWindow);
- }
+ loadWindow(projectSettingsFilePath.empty());
if (projectSettingsFilePath.empty())
{
@@ -332,6 +318,8 @@ void Application::handleMessage(MessageRefreshUI* message)
if (m_hasGUI)
{
+ updateTitle();
+
if (message->loadStyle)
{
loadStyle(ApplicationSettings::getInstance()->getColorSchemePath());
@@ -366,9 +354,9 @@ void Application::handleMessage(MessageWindowFocus* message)
m_lastLicenseCheck = TimeStamp::now();
LicenseChecker::LicenseState state = LicenseChecker::checkCurrentLicense();
- if (state != LicenseChecker::LICENSE_VALID && state != LicenseChecker::LICENSE_MOVED)
+ if (state != LicenseChecker::LicenseState::VALID)
{
- MessageForceEnterLicense(state).dispatch();
+ m_mainView->forceEnterLicense(LicenseChecker::getLicenseErrorForState(state));
}
}
}
@@ -417,6 +405,54 @@ void Application::startMessagingAndScheduling()
queue->startMessageLoopThreaded();
}
+void Application::loadWindow(bool showStartWindow)
+{
+ if (!m_hasGUI)
+ {
+ return;
+ }
+
+ if (!m_loadedWindow)
+ {
+ ApplicationSettings* appSettings = ApplicationSettings::getInstance().get();
+ LicenseChecker::LicenseState state = LicenseChecker::LicenseState::VALID;
+ std::string licenseError;
+
+ if (!appSettings->getNonCommercialUse())
+ {
+ state = LicenseChecker::setCurrentLicenseStringEncoded(appSettings->getLicenseString());
+ licenseError = LicenseChecker::getLicenseErrorForState(state);
+
+ if (state == LicenseChecker::LicenseState::VALID)
+ {
+ MessageStatus(L"Found valid license key, unlocked application.").dispatch();
+ }
+ else if (state == LicenseChecker::LicenseState::EMPTY)
+ {
+ licenseError = "";
+ }
+ else if (state == LicenseChecker::LicenseState::MALFORMED)
+ {
+ licenseError = "Plese re-enter your license key.";
+ appSettings->setLicenseString("");
+ appSettings->save();
+ }
+ }
+
+ updateTitle();
+
+ bool showEula = (appSettings->getAcceptedEulaVersion() < EULA_VERSION);
+ bool enterLicense = (state != LicenseChecker::LicenseState::VALID);
+
+ m_mainView->loadWindow(showStartWindow, showEula, enterLicense, licenseError);
+ m_loadedWindow = true;
+ }
+ else if (!showStartWindow)
+ {
+ m_mainView->hideStartScreen();
+ }
+}
+
void Application::refreshProject(RefreshMode refreshMode)
{
if (m_project && checkSharedMemory())
@@ -487,16 +523,15 @@ void Application::updateTitle()
{
std::wstring title = L"Sourcetrail";
- switch (m_licenseType)
+ switch (LicenseChecker::getCurrentLicenseType())
{
- case MessageEnteredLicense::LICENSE_TEST:
+ case LicenseType::TEST:
title += L" [test]";
break;
- case MessageEnteredLicense::LICENSE_NONE:
- case MessageEnteredLicense::LICENSE_NON_COMMERCIAL:
+ case LicenseType::NON_COMMERCIAL:
title += L" [non-commercial]";
break;
- case MessageEnteredLicense::LICENSE_COMMERCIAL:
+ case LicenseType::COMMERCIAL:
break;
}
@@ -519,7 +554,8 @@ bool Application::checkSharedMemory()
std::wstring error = utility::decodeFromUtf8(SharedMemory::checkSharedMemory(getUUID()));
if (error.size())
{
- MessageStatus(L"Error on accessing shared memory. Indexing not possible. Please restart computer or run as admin: " + error, true).dispatch();
+ MessageStatus(L"Error on accessing shared memory. Indexing not possible. "
+ "Please restart computer or run as admin: " + error, true).dispatch();
handleDialog(
L"There was an error accessing shared memory on your computer: " + error + L"\n\n"
"Project indexing is not possible. Please restart your computer or try running Sourcetrail as admin. If the "
diff --git a/src/lib/Application.h b/src/lib/Application.h
index 9130695f..39a8a3a7 100644
--- a/src/lib/Application.h
+++ b/src/lib/Application.h
@@ -7,7 +7,6 @@
#include "MessageListener.h"
#include "MessageIndexingFinished.h"
#include "MessageActivateWindow.h"
-#include "MessageEnteredLicense.h"
#include "MessageLoadProject.h"
#include "MessageRefresh.h"
#include "MessageRefreshUI.h"
@@ -27,7 +26,6 @@ class ViewFactory;
class Application
: public MessageListener
- , public MessageListener
, public MessageListener
, public MessageListener
, public MessageListener
@@ -36,6 +34,8 @@ class Application
, public MessageListener
{
public:
+ static const int EULA_VERSION = 5;
+
static void createInstance(const Version& version, ViewFactory* viewFactory, NetworkFactory* networkFactory);
static std::shared_ptr getInstance();
static void destroyInstance();
@@ -68,7 +68,6 @@ private:
Application(bool withGUI = true);
void handleMessage(MessageActivateWindow* message) override;
- void handleMessage(MessageEnteredLicense* message) override;
void handleMessage(MessageIndexingFinished* message) override;
void handleMessage(MessageLoadProject* message) override;
void handleMessage(MessageRefresh* message) override;
@@ -79,6 +78,8 @@ private:
FilePath migrateProjectSettings(const FilePath& projectSettingsFilePath) const;
void startMessagingAndScheduling();
+ void loadWindow(bool showStartWindow);
+
void refreshProject(RefreshMode refreshMode);
void updateRecentProjects(const FilePath& projectSettingsFilePath);
@@ -89,6 +90,8 @@ private:
bool checkSharedMemory();
const bool m_hasGUI;
+ bool m_loadedWindow = false;
+
std::shared_ptr m_project;
std::shared_ptr m_storageCache;
@@ -97,7 +100,6 @@ private:
std::shared_ptr m_ideCommunicationController;
std::shared_ptr m_updateChecker;
- MessageEnteredLicense::LicenseType m_licenseType;
TimeStamp m_lastLicenseCheck;
};
diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt
index 228fa371..0f9a7fe6 100644
--- a/src/lib/CMakeLists.txt
+++ b/src/lib/CMakeLists.txt
@@ -495,12 +495,10 @@ add_files(
utility/messaging/type/MessageClearStatusView.h
utility/messaging/type/MessageCodeReference.h
utility/messaging/type/MessageDeactivateEdge.h
- utility/messaging/type/MessageEnteredLicense.h
utility/messaging/type/MessageFind.h
utility/messaging/type/MessageFlushUpdates.h
utility/messaging/type/MessageFocusIn.h
utility/messaging/type/MessageFocusOut.h
- utility/messaging/type/MessageForceEnterLicense.h
utility/messaging/type/MessageGraphNodeBundleSplit.h
utility/messaging/type/MessageGraphNodeExpand.h
utility/messaging/type/MessageGraphNodeHide.h
@@ -655,7 +653,5 @@ add_files(
LanguagePackage.h
LanguagePackageManager.cpp
LanguagePackageManager.h
- LicenseChecker.cpp
- LicenseChecker.h
UpdateChecker.h
)
diff --git a/src/lib/LicenseChecker.cpp b/src/lib/LicenseChecker.cpp
deleted file mode 100644
index 83bfab21..00000000
--- a/src/lib/LicenseChecker.cpp
+++ /dev/null
@@ -1,189 +0,0 @@
-#include "LicenseChecker.h"
-
-#include "ApplicationSettings.h"
-#include "AppPath.h"
-#include "License.h"
-#include "logging.h"
-#include "utilityApp.h"
-
-std::string LicenseChecker::getCurrentLicenseString()
-{
- License license;
- bool isLoaded = license.loadFromEncodedString(
- ApplicationSettings::getInstance()->getLicenseString(), AppPath::getAppPath().str());
-
- if (isLoaded)
- {
- return license.getLicenseString();
- }
-
- return "";
-}
-
-void LicenseChecker::saveCurrentLicenseString(const std::string& licenseString)
-{
- License license;
- bool isLoaded = license.loadFromString(licenseString);
- if (!isLoaded)
- {
- return;
- }
-
- utility::saveLicense(&license);
-}
-
-bool LicenseChecker::isCurrentLicenseValid()
-{
- return checkCurrentLicense() == LICENSE_VALID;
-}
-
-LicenseChecker::LicenseState LicenseChecker::checkCurrentLicense()
-{
- ApplicationSettings* appSettings = ApplicationSettings::getInstance().get();
- if (appSettings == nullptr)
- {
- LOG_ERROR_STREAM(<< "Unable to retrieve app settings");
- return LICENSE_EMPTY;
- }
-
- const FilePath appPath = AppPath::getAppPath();
-
- if (appPath.empty())
- {
- LOG_ERROR_STREAM(<< "Failed to retrieve app path");
- return LICENSE_EMPTY;
- }
-
- std::string licenseString = appSettings->getLicenseString();
- if (licenseString.size() == 0)
- {
- LOG_ERROR_STREAM(<< "No license key available.");
- return LICENSE_EMPTY;
- }
-
- if (!License::checkLocation(appPath.getAbsolute().str(), appSettings->getLicenseCheck()))
- {
- LOG_ERROR_STREAM(<< "Application was moved, reenter license key.");
- return LICENSE_MOVED;
- }
-
- License license;
- bool isLoaded = license.loadFromEncodedString(licenseString, appPath.str());
- if (!isLoaded)
- {
- LOG_ERROR_STREAM(<< "License is invalid or application was moved.");
- return LICENSE_MOVED;
- }
-
- return checkLicense(license);
-}
-
-LicenseChecker::LicenseState LicenseChecker::checkLicenseString(const std::string& licenseString)
-{
- if (licenseString.size() == 0)
- {
- return LICENSE_EMPTY;
- }
-
- License license;
- bool isLoaded = license.loadFromString(licenseString);
- if (!isLoaded)
- {
- return LICENSE_MALFORMED;
- }
-
- license.print();
-
- return checkLicense(license);
-}
-
-MessageEnteredLicense::LicenseType LicenseChecker::getCurrentLicenseType()
-{
- License license;
- bool isLoaded = license.loadFromEncodedString(
- ApplicationSettings::getInstance()->getLicenseString(), AppPath::getAppPath().str());
-
- if (!isLoaded)
- {
- return MessageEnteredLicense::LICENSE_NONE;
- }
-
- LicenseState state = checkLicense(license);
- if (state != LICENSE_VALID)
- {
- return MessageEnteredLicense::LICENSE_NONE;
- }
- else if (license.isTestLicense())
- {
- return MessageEnteredLicense::LICENSE_TEST;
- }
- else if (license.isNonCommercialLicenseType())
- {
- return MessageEnteredLicense::LICENSE_NON_COMMERCIAL;
- }
-
- return MessageEnteredLicense::LICENSE_COMMERCIAL;
-}
-
-MessageEnteredLicense::LicenseType LicenseChecker::getLicenseType(const std::string& licenseString)
-{
- if (licenseString.size() == 0)
- {
- return MessageEnteredLicense::LICENSE_NONE;
- }
-
- License license;
- bool isLoaded = license.loadFromString(licenseString);
- if (!isLoaded)
- {
- return MessageEnteredLicense::LICENSE_NONE;
- }
-
- LicenseState state = checkLicense(license);
- if (state != LICENSE_VALID)
- {
- return MessageEnteredLicense::LICENSE_NONE;
- }
- else if (license.isTestLicense())
- {
- return MessageEnteredLicense::LICENSE_TEST;
- }
- else if (license.isNonCommercialLicenseType())
- {
- return MessageEnteredLicense::LICENSE_NON_COMMERCIAL;
- }
-
- return MessageEnteredLicense::LICENSE_COMMERCIAL;
-}
-
-std::string LicenseChecker::getCurrentLicenseTypeString()
-{
- // WARNING: Don't change these string. The server API relies on them.
- switch (getCurrentLicenseType())
- {
- case MessageEnteredLicense::LICENSE_NONE:
- case MessageEnteredLicense::LICENSE_NON_COMMERCIAL:
- return "private";
- case MessageEnteredLicense::LICENSE_TEST:
- return "test";
- case MessageEnteredLicense::LICENSE_COMMERCIAL:
- return "commercial";
- }
-
- return "private";
-}
-
-LicenseChecker::LicenseState LicenseChecker::checkLicense(License& license)
-{
- if (license.isExpired())
- {
- return LICENSE_EXPIRED;
- }
-
- if (license.isValid())
- {
- return LICENSE_VALID;
- }
-
- return LICENSE_INVALID;
-}
diff --git a/src/lib/LicenseChecker.h b/src/lib/LicenseChecker.h
deleted file mode 100644
index 90b944ca..00000000
--- a/src/lib/LicenseChecker.h
+++ /dev/null
@@ -1,37 +0,0 @@
-#ifndef LICENSE_CHECKER_H
-#define LICENSE_CHECKER_H
-
-#include "MessageEnteredLicense.h"
-
-class License;
-
-class LicenseChecker
-{
-public:
- enum LicenseState
- {
- LICENSE_EMPTY,
- LICENSE_MOVED,
- LICENSE_MALFORMED,
- LICENSE_INVALID,
- LICENSE_EXPIRED,
- LICENSE_VALID
- };
-
- static std::string getCurrentLicenseString();
- static void saveCurrentLicenseString(const std::string& licenseString);
-
- static bool isCurrentLicenseValid();
- static LicenseState checkCurrentLicense();
- static LicenseState checkLicenseString(const std::string& licenseString);
-
- static MessageEnteredLicense::LicenseType getCurrentLicenseType();
- static MessageEnteredLicense::LicenseType getLicenseType(const std::string& licenseString);
-
- static std::string getCurrentLicenseTypeString();
-
-private:
- static LicenseState checkLicense(License& license);
-};
-
-#endif // LICENSE_CHECKER_H
diff --git a/src/lib/component/view/MainView.h b/src/lib/component/view/MainView.h
index f7efd39f..d8ea6a96 100644
--- a/src/lib/component/view/MainView.h
+++ b/src/lib/component/view/MainView.h
@@ -32,11 +32,12 @@ public:
virtual void refreshView() = 0;
- virtual void loadWindow(bool showStartWindow) = 0;
+ virtual void loadWindow(bool showStartWindow, bool showEULA, bool enterLicense, std::string licenseError) = 0;
virtual void hideStartScreen() = 0;
virtual void setTitle(const std::wstring& title) = 0;
virtual void activateWindow() = 0;
+ virtual void forceEnterLicense(std::string licenseError) = 0;
virtual void updateRecentProjectMenu() = 0;
diff --git a/src/lib/settings/ApplicationSettings.cpp b/src/lib/settings/ApplicationSettings.cpp
index 5ce763c3..d9f0a67b 100644
--- a/src/lib/settings/ApplicationSettings.cpp
+++ b/src/lib/settings/ApplicationSettings.cpp
@@ -53,20 +53,6 @@ bool ApplicationSettings::load(const FilePath& filePath, bool readOnly)
"network/coati_port",
"network/sourcetrail_port"
));
- migrator.addMigration(3, std::make_shared(
- [](const SettingsMigration* migration, Settings* settings)
- {
- License license;
- bool isLoaded = license.loadFromEncodedString(
- migration->getValueFromSettings(settings, "user/license/license", ""), AppPath::getAppPath().str());
- if (isLoaded && license.isValid() && license.isNonCommercialLicenseType())
- {
- migration->removeValuesInSettings(settings, "user/license/license");
- migration->removeValuesInSettings(settings, "user/license/check");
- migration->setValueInSettings(settings, "user/license/non_commercial_use", true);
- }
- }
- ));
migrator.addMigration(4, std::make_shared(
[](const SettingsMigration* migration, Settings* settings)
{
@@ -680,16 +666,6 @@ void ApplicationSettings::setLicenseString(const std::string& licenseString)
setValue("user/license/license", licenseString);
}
-std::string ApplicationSettings::getLicenseCheck() const
-{
- return getValue("user/license/check", "");
-}
-
-void ApplicationSettings::setLicenseCheck(const std::string& hash)
-{
- setValue("user/license/check", hash);
-}
-
bool ApplicationSettings::getNonCommercialUse() const
{
return getValue("user/license/non_commercial_use", false);
diff --git a/src/lib/settings/ApplicationSettings.h b/src/lib/settings/ApplicationSettings.h
index b7283f3c..73032288 100644
--- a/src/lib/settings/ApplicationSettings.h
+++ b/src/lib/settings/ApplicationSettings.h
@@ -191,9 +191,6 @@ public:
std::string getLicenseString() const;
void setLicenseString(const std::string& licenseString);
- std::string getLicenseCheck() const;
- void setLicenseCheck(const std::string& hash);
-
bool getNonCommercialUse() const;
void setNonCommercialUse(bool nonCommercialUse);
diff --git a/src/lib/utility/messaging/type/MessageEnteredLicense.h b/src/lib/utility/messaging/type/MessageEnteredLicense.h
deleted file mode 100644
index e2cd408f..00000000
--- a/src/lib/utility/messaging/type/MessageEnteredLicense.h
+++ /dev/null
@@ -1,32 +0,0 @@
-#ifndef MESSAGE_ENTERED_LICENSE_H
-#define MESSAGE_ENTERED_LICENSE_H
-
-#include "Message.h"
-
-class MessageEnteredLicense
- : public Message
-{
-public:
- enum LicenseType
- {
- LICENSE_NONE,
- LICENSE_TEST,
- LICENSE_NON_COMMERCIAL,
- LICENSE_COMMERCIAL
- };
-
- MessageEnteredLicense(LicenseType type)
- : type(type)
- {
- setSendAsTask(false);
- }
-
- static const std::string getStaticType()
- {
- return "MessageEnteredLicense";
- }
-
- const LicenseType type;
-};
-
-#endif // MESSAGE_ENTERED_LICENSE_H
diff --git a/src/lib/utility/messaging/type/MessageForceEnterLicense.h b/src/lib/utility/messaging/type/MessageForceEnterLicense.h
deleted file mode 100644
index e21375b8..00000000
--- a/src/lib/utility/messaging/type/MessageForceEnterLicense.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#ifndef MESSAGE_FORCE_ENTER_LICENSE_H
-#define MESSAGE_FORCE_ENTER_LICENSE_H
-
-#include "LicenseChecker.h"
-#include "Message.h"
-
-class MessageForceEnterLicense
- : public Message
-{
-public:
- MessageForceEnterLicense(LicenseChecker::LicenseState state)
- : state(state)
- {
- setSendAsTask(false);
- }
-
- static const std::string getStaticType()
- {
- return "MessageForceEnterLicense";
- }
-
- const LicenseChecker::LicenseState state;
-};
-
-#endif // MESSAGE_FORCE_ENTER_LICENSE_H
diff --git a/src/lib_gui/qt/view/QtMainView.cpp b/src/lib_gui/qt/view/QtMainView.cpp
index a6d8d7c0..11dda326 100644
--- a/src/lib_gui/qt/view/QtMainView.cpp
+++ b/src/lib_gui/qt/view/QtMainView.cpp
@@ -98,12 +98,12 @@ void QtMainView::saveLayout()
m_window->saveLayout();
}
-void QtMainView::loadWindow(bool showStartWindow)
+void QtMainView::loadWindow(bool showStartWindow, bool showEULA, bool enterLicense, std::string licenseError)
{
m_onQtThread(
[=]()
{
- m_window->loadWindow(showStartWindow);
+ m_window->loadWindow(showStartWindow, showEULA, enterLicense, licenseError);
}
);
}
@@ -163,6 +163,16 @@ void QtMainView::activateWindow()
);
}
+void QtMainView::forceEnterLicense(std::string licenseError)
+{
+ m_onQtThread(
+ [=]()
+ {
+ m_window->forceEnterLicense(licenseError);
+ }
+ );
+}
+
void QtMainView::updateRecentProjectMenu()
{
m_onQtThread(
@@ -208,18 +218,6 @@ void QtMainView::clearBookmarksMenu()
updateBookmarksMenu({});
}
-void QtMainView::handleMessage(MessageForceEnterLicense* message)
-{
- LicenseChecker::LicenseState state = message->state;
-
- m_onQtThread(
- [=]()
- {
- m_window->forceEnterLicense(state);
- }
- );
-}
-
void QtMainView::handleMessage(MessageProjectEdit* message)
{
m_onQtThread(
diff --git a/src/lib_gui/qt/view/QtMainView.h b/src/lib_gui/qt/view/QtMainView.h
index a42ce52b..c7a9b534 100644
--- a/src/lib_gui/qt/view/QtMainView.h
+++ b/src/lib_gui/qt/view/QtMainView.h
@@ -10,7 +10,6 @@
#include "QtThreadedFunctor.h"
#include "MessageListener.h"
-#include "MessageForceEnterLicense.h"
#include "MessageProjectEdit.h"
#include "MessageProjectNew.h"
@@ -19,7 +18,6 @@ class View;
class QtMainView
: public MainView
- , public MessageListener
, public MessageListener
, public MessageListener
{
@@ -50,13 +48,14 @@ public:
void loadLayout() override;
void saveLayout() override;
- void loadWindow(bool showStartWindow) override;
+ void loadWindow(bool showStartWindow, bool showEULA, bool enterLicense, std::string licenseError) override;
void refreshView() override;
void hideStartScreen() override;
void setTitle(const std::wstring& title) override;
void activateWindow() override;
+ void forceEnterLicense(std::string licenseError) override;
void updateRecentProjectMenu() override;
@@ -67,7 +66,6 @@ public:
void clearBookmarksMenu() override;
private:
- void handleMessage(MessageForceEnterLicense* message) override;
void handleMessage(MessageProjectEdit* message) override;
void handleMessage(MessageProjectNew* message) override;
diff --git a/src/lib_gui/qt/window/QtEulaWindow.h b/src/lib_gui/qt/window/QtEulaWindow.h
index 84acdab5..32d8f689 100644
--- a/src/lib_gui/qt/window/QtEulaWindow.h
+++ b/src/lib_gui/qt/window/QtEulaWindow.h
@@ -7,9 +7,8 @@ class QtEulaWindow
: public QtWindow
{
Q_OBJECT
-public:
- static const int EULA_VERSION = 5;
+public:
QtEulaWindow(QWidget* parent, bool forceAccept);
QSize sizeHint() const override;
diff --git a/src/lib_gui/qt/window/QtLicenseWindow.cpp b/src/lib_gui/qt/window/QtLicenseWindow.cpp
index a7404dc5..ef23993d 100644
--- a/src/lib_gui/qt/window/QtLicenseWindow.cpp
+++ b/src/lib_gui/qt/window/QtLicenseWindow.cpp
@@ -85,9 +85,11 @@ void QtLicenseWindow::populateWindow(QWidget* widget)
m_licenseText->setPlaceholderText(
"-----BEGIN LICENSE-----\n"
"Product: Sourcetrail\n"
- "Licensed to:\n"
+ "License holder:\n"
"License type:\n"
- "Valid up to version:\n"
+ "Licensed number of users:\n"
+ "Licensed product version:\n"
+ "Licensed usage period:\n"
"-\n"
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n"
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n"
@@ -152,45 +154,22 @@ void QtLicenseWindow::handleNext()
if (m_commercialUse->isChecked())
{
std::string licenseString = m_licenseText->toPlainText().toStdString();
-
LicenseChecker::LicenseState state = LicenseChecker::checkLicenseString(licenseString);
- std::string errorString;
+ std::string errorString = LicenseChecker::getLicenseErrorForState(state);
- switch (state)
+ if (state == LicenseChecker::LicenseState::VALID)
{
- case LicenseChecker::LICENSE_EMPTY:
- errorString = "No license key was entered.";
- break;
- case LicenseChecker::LICENSE_MOVED:
- case LicenseChecker::LICENSE_MALFORMED:
- errorString = "The entered license key is malformed.";
- break;
- case LicenseChecker::LICENSE_INVALID:
- errorString = "The entered license key is invalid.";
- break;
- case LicenseChecker::LICENSE_EXPIRED:
- errorString = "The entered license key is expired.";
- break;
- case LicenseChecker::LICENSE_VALID:
- {
- if (LicenseChecker::getLicenseType(licenseString) == MessageEnteredLicense::LICENSE_NON_COMMERCIAL)
- {
- errorString =
- "The entered license key does not permit commercial use. You no longer need a license "
- "key for non-commercial use. Please choose the non-commercial option below.";
- break;
- }
+ ApplicationSettings* appSettings = ApplicationSettings::getInstance().get();
- LicenseChecker::saveCurrentLicenseString(licenseString);
- m_errorLabel->setText(" ");
+ LicenseChecker::setCurrentLicenseString(licenseString);
- ApplicationSettings::getInstance()->setNonCommercialUse(false);
- ApplicationSettings::getInstance()->save();
+ appSettings->setLicenseString(LicenseChecker::getCurrentLicenseStringEncoded());
+ appSettings->setNonCommercialUse(false);
+ appSettings->save();
- emit finished();
- return;
- }
+ emit finished();
+ return;
}
m_errorLabel->setText(errorString.c_str());
diff --git a/src/lib_gui/qt/window/QtMainWindow.cpp b/src/lib_gui/qt/window/QtMainWindow.cpp
index 0d02ada9..e6493135 100644
--- a/src/lib_gui/qt/window/QtMainWindow.cpp
+++ b/src/lib_gui/qt/window/QtMainWindow.cpp
@@ -29,6 +29,7 @@
#include "QtStartScreen.h"
#include "ApplicationSettings.h"
#include "FileSystem.h"
+#include "LicenseChecker.h"
#include "logging.h"
#include "MessageErrorsHelpMessage.h"
#include "MessageHistoryRedo.h"
@@ -39,7 +40,6 @@
#include "MessageBookmarkBrowse.h"
#include "MessageBookmarkCreate.h"
#include "MessageCodeReference.h"
-#include "MessageEnteredLicense.h"
#include "MessageFind.h"
#include "MessageIndexingShowDialog.h"
#include "MessageLoadProject.h"
@@ -116,8 +116,7 @@ bool MouseReleaseFilter::eventFilter(QObject* obj, QEvent* event)
QtMainWindow::QtMainWindow()
- : m_loaded(false)
- , m_historyMenu(nullptr)
+ : m_historyMenu(nullptr)
, m_bookmarksMenu(nullptr)
, m_showDockWidgetTitleBars(true)
, m_windowStack(this)
@@ -324,46 +323,20 @@ void QtMainWindow::loadDockWidgetLayout()
}
}
-void QtMainWindow::loadWindow(bool showStartWindow)
+void QtMainWindow::loadWindow(bool showStartWindow, bool showEULA, bool enterLicense, const std::string& licenseError)
{
- if (m_loaded)
- {
- if (!showStartWindow)
- {
- hideStartScreen();
- }
- return;
- }
-
- m_loaded = true;
-
- LicenseChecker::LicenseState state = LicenseChecker::checkCurrentLicense();
- bool licenseValid = (state == LicenseChecker::LICENSE_VALID);
-
- if (licenseValid)
- {
- MessageEnteredLicense(LicenseChecker::getCurrentLicenseType()).dispatch();
- }
-
- ApplicationSettings* appSettings = ApplicationSettings::getInstance().get();
-
- if (state == LicenseChecker::LICENSE_MOVED)
- {
- appSettings->setLicenseString("");
- }
-
if (showStartWindow)
{
showStartScreen();
}
- if (state != LicenseChecker::LICENSE_VALID && !appSettings->getNonCommercialUse())
+ if (enterLicense)
{
- forceEnterLicense(state);
+ forceEnterLicense(licenseError);
}
#ifndef Q_OS_WIN
- if (appSettings->getAcceptedEulaVersion() < QtEulaWindow::EULA_VERSION)
+ if (showEULA)
{
showEula(true);
}
@@ -387,7 +360,7 @@ void QtMainWindow::saveLayout()
settings.setValue("DOCK_LOCATIONS", this->saveState());
}
-void QtMainWindow::forceEnterLicense(LicenseChecker::LicenseState state)
+void QtMainWindow::forceEnterLicense(const std::string& licenseError)
{
QtLicenseWindow* window = dynamic_cast(m_windowStack.getTopWindow());
if (window)
@@ -404,14 +377,9 @@ void QtMainWindow::forceEnterLicense(LicenseChecker::LicenseState state)
return;
}
- if (state == LicenseChecker::LICENSE_EXPIRED)
+ if (licenseError.size())
{
- window->setErrorMessage("The license key is expired.");
- }
- else if (state != LicenseChecker::LICENSE_VALID && state != LicenseChecker::LICENSE_EMPTY)
- {
- window->clear();
- window->setErrorMessage("Please re-enter your license key.");
+ window->setErrorMessage(QString::fromStdString(licenseError));
}
window->updateCloseButton("Quit");
@@ -620,7 +588,7 @@ void QtMainWindow::showEula(bool forceAccept)
void QtMainWindow::acceptedEula()
{
- ApplicationSettings::getInstance()->setAcceptedEulaVersion(QtEulaWindow::EULA_VERSION);
+ ApplicationSettings::getInstance()->setAcceptedEulaVersion(Application::EULA_VERSION);
ApplicationSettings::getInstance()->save();
setEnabled(true);
@@ -654,7 +622,7 @@ void QtMainWindow::enteredLicense()
m_windowStack.clearWindows();
- MessageEnteredLicense(LicenseChecker::getCurrentLicenseType()).dispatch();
+ MessageRefreshUI().dispatch();
setEnabled(true);
diff --git a/src/lib_gui/qt/window/QtMainWindow.h b/src/lib_gui/qt/window/QtMainWindow.h
index fe08dfa2..feb230ff 100644
--- a/src/lib_gui/qt/window/QtMainWindow.h
+++ b/src/lib_gui/qt/window/QtMainWindow.h
@@ -8,11 +8,11 @@
#include
#include "SearchMatch.h"
-#include "LicenseChecker.h"
#include "QtWindowsTaskbarButton.h"
#include "QtWindowStack.h"
class Bookmark;
+class MessageBase;
class QDockWidget;
class View;
@@ -73,9 +73,9 @@ public:
void saveLayout();
void loadDockWidgetLayout();
- void loadWindow(bool showStartWindow);
+ void loadWindow(bool showStartWindow, bool showEULA, bool enterLicense, const std::string& licenseError);
- void forceEnterLicense(LicenseChecker::LicenseState state);
+ void forceEnterLicense(const std::string& licenseError);
void updateHistoryMenu(std::shared_ptr message);
void clearHistoryMenu();
@@ -190,8 +190,6 @@ private:
std::vector m_dockWidgets;
- bool m_loaded;
-
QMenu* m_viewMenu;
QAction* m_viewSeparator;
diff --git a/src/lib_gui/qt/window/QtStartScreen.cpp b/src/lib_gui/qt/window/QtStartScreen.cpp
index 14bea92a..2f69b907 100644
--- a/src/lib_gui/qt/window/QtStartScreen.cpp
+++ b/src/lib_gui/qt/window/QtStartScreen.cpp
@@ -8,11 +8,9 @@
#include
#include "ApplicationSettings.h"
-#include "AppPath.h"
-#include "License.h"
+#include "LicenseChecker.h"
#include "MessageLoadProject.h"
#include "ProjectSettings.h"
-#include "PublicKey.h"
#include "QtUpdateCheckerWidget.h"
#include "QtNewsWidget.h"
#include "ResourcePaths.h"
@@ -146,9 +144,6 @@ void QtStartScreen::updateButtons()
void QtStartScreen::setupStartScreen()
{
- License license;
- license.loadFromEncodedString(ApplicationSettings::getInstance()->getLicenseString(), AppPath::getAppPath().str());
-
setStyleSheet(utility::getStyleSheet(ResourcePaths::getGuiPath().concatenate(L"startscreen/startscreen.css")).c_str());
addLogo();
@@ -170,15 +165,15 @@ void QtStartScreen::setupStartScreen()
col->addSpacing(15);
- if (license.isValid())
+ if (LicenseChecker::checkCurrentLicense() == LicenseChecker::LicenseState::VALID)
{
- std::string licenseString = license.getLicenseInfo();
+ std::string licenseInfo = LicenseChecker::getCurrentLicense()->getLicenseInfo();
QLabel* licenseHeader = new QLabel("Licensed to:");
licenseHeader->setObjectName("boldLabel");
col->addWidget(licenseHeader);
col->addSpacing(2);
- QLabel* licenseLabel = new QLabel(licenseString.c_str());
+ QLabel* licenseLabel = new QLabel(licenseInfo.c_str());
licenseLabel->setObjectName("textLabel");
col->addWidget(licenseLabel);
}
diff --git a/src/lib_gui/utility/utilityApp.cpp b/src/lib_gui/utility/utilityApp.cpp
index 8712335a..d13d5898 100644
--- a/src/lib_gui/utility/utilityApp.cpp
+++ b/src/lib_gui/utility/utilityApp.cpp
@@ -224,32 +224,3 @@ std::string utility::getOsTypeString()
}
return "unknown";
}
-
-bool utility::saveLicense(const License* license)
-{
- if (license == nullptr)
- {
- return false;
- }
-
- if (license->isValid())
- {
- ApplicationSettings* appSettings = ApplicationSettings::getInstance().get();
- if (appSettings == nullptr)
- {
- LOG_ERROR_STREAM(<< "Unable to retrieve app settings");
- return false;
- }
-
- const FilePath appLocation = AppPath::getAppPath();
- appSettings->setLicenseString(license->getLicenseEncodedString(appLocation.str()));
- appSettings->setLicenseCheck(license->hashLocation(appLocation.getAbsolute().str()));
- appSettings->save();
- return true;
- }
- else
- {
- LOG_ERROR( "The entered license key is invalid.");
- return false;
- }
-}
diff --git a/src/lib_gui/utility/utilityApp.h b/src/lib_gui/utility/utilityApp.h
index 816510df..fd0b2f1f 100644
--- a/src/lib_gui/utility/utilityApp.h
+++ b/src/lib_gui/utility/utilityApp.h
@@ -28,8 +28,6 @@ namespace utility
OsType getOsType();
std::string getOsTypeString();
-
- bool saveLicense(const License* license);
}
#endif // UTILITY_APP_H
diff --git a/src/lib_license/CMakeLists.txt b/src/lib_license/CMakeLists.txt
index 1e678239..d6f989ae 100644
--- a/src/lib_license/CMakeLists.txt
+++ b/src/lib_license/CMakeLists.txt
@@ -6,4 +6,7 @@ add_files(
License.cpp
License.h
+ LicenseChecker.cpp
+ LicenseChecker.h
+ LicenseType.h
)
diff --git a/src/lib_license/License.cpp b/src/lib_license/License.cpp
index 8de2eda7..a943e238 100644
--- a/src/lib_license/License.cpp
+++ b/src/lib_license/License.cpp
@@ -1,28 +1,18 @@
#include "License.h"
#include
-#include
#include
#include
#include
#include
-#include
-//#include
#include
#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
+// #include
#include
-#include
+#include
#include "Version.h"
-#include "PublicKey.h"
namespace
{
@@ -41,96 +31,7 @@ std::string toLowerCase(const std::string& in)
return out;
}
-}
-
-License::License()
- : m_rng(std::make_shared())
- , m_user("")
- , m_type("Private License")
- , m_numberOfUsers(0)
- , m_createdWithSeats(false)
- , m_expire("")
-{
- loadPublicKey();
-}
-
-License::~License()
-{
-}
-
-void License::createHeader(
- const std::string& user,
- const std::string& type,
- const std::string& expiration,
- bool expiresAtDate,
- size_t numberOfUsers
-)
-{
- if (user.empty() || type.empty() || expiration.empty())
- {
- return;
- }
- m_user = user;
- m_expire = expiration;
- m_expiresAtDate = expiresAtDate;
- m_type = type;
- m_numberOfUsers = numberOfUsers;
-}
-
-std::string License::getMessage(bool withNewlines) const
-{
- const std::string separator = (withNewlines ? "\n" : "");
- std::string message = "";
-
- if ( m_user.empty() || m_type.empty() || m_expire.empty() || m_hashLine.empty())
- {
- return "";
- }
-
- message += LicenseConstants::PRODUCT_STRING + separator;
- message += LicenseConstants::LICENSED_TO_STRING + m_user + separator;
- message += LicenseConstants::LICENSE_TYPE_STRING + m_type;
-
- if (m_numberOfUsers == 0)
- {
- message += (m_createdWithSeats ? " (unlimited seats)" : " (unlimited users)");
- }
- else if (m_numberOfUsers == 1)
- {
- message += (m_createdWithSeats ? " (1 Seat)" : " (1 user)");
- }
- else if (m_numberOfUsers > 1)
- {
- message += " (" + std::to_string(m_numberOfUsers) + (m_createdWithSeats ? " Seats)" : " users)");
- }
-
- message += separator;
- message += getExpireLine() + separator;
- message += LicenseConstants::SEPARATOR_STRING + separator;
- message += m_hashLine;
-
- return message;
-}
-
-std::string License::getLine(std::istream& stream)
-{
- std::string line;
- if(getline(stream, line, '\n'))
- {
- return trim(line);
- }
- return "";
-}
-
-void License::setHashLine(const std::string &hash)
-{
- if (!hash.empty())
- {
- m_hashLine = hash;
- }
-}
-
-std::string License::removeCaption(const std::string& line, const std::string& caption) const
+std::string removeCaption(const std::string& line, const std::string& caption)
{
if (line.substr(0, caption.length()) == caption)
{
@@ -139,50 +40,20 @@ std::string License::removeCaption(const std::string& line, const std::string& c
return "";
}
-bool License::extractData(const std::string& data, LICENSE_LINE line)
-{
- switch ( line )
- {
- case USER_LINE:
- m_user = removeCaption(data, LicenseConstants::LICENSED_TO_STRING);
- return !m_user.empty();
- case EXPIRE_LINE:
- m_expire = removeCaption(data, LicenseConstants::VALID_UP_TO_STRING);
- m_expiresAtDate = false;
- if (m_expire.empty())
- {
- m_expire = removeCaption(data, LicenseConstants::VALID_UNTIL_STRING);
- m_expiresAtDate = true;
- }
- return !m_expire.empty();
- case TYPE_LINE:
- setTypeAndNumberOfUsers(removeCaption(data, LicenseConstants::LICENSE_TYPE_STRING));
- return !m_type.empty();
- default:
- return false;
- }
}
-bool License::isTestLicense() const
+License::License()
+ : m_rng(std::make_unique())
{
- return m_type == LicenseConstants::TEST_LICENSE_STRING;
}
-bool License::isNonCommercialLicenseType() const
+License::~License()
{
- for ( const std::string& nonCommercialLicenseType : NON_COMMERCIAL_LICENSE_TYPES)
- {
- if (m_type == nonCommercialLicenseType)
- {
- return true;
- }
- }
- return false;
}
-size_t License::getNumberOfUsers() const
+std::string License::getUser() const
{
- return m_numberOfUsers;
+ return m_user;
}
std::string License::getType() const
@@ -190,18 +61,9 @@ std::string License::getType() const
return m_type;
}
-std::string License::getExpireLine() const
+size_t License::getNumberOfUsers() const
{
- return (m_expiresAtDate ?
- LicenseConstants::VALID_UNTIL_STRING :
- LicenseConstants::VALID_UP_TO_STRING) + m_expire;
-}
-
-std::string License::getExpireLineUI() const
-{
- return toLowerCase(m_expiresAtDate ?
- LicenseConstants::VALID_UNTIL_STRING :
- LicenseConstants::VALID_UP_TO_STRING) + m_expire;
+ return m_numberOfUsers;
}
std::string License::getLicenseInfo() const
@@ -211,11 +73,7 @@ std::string License::getLicenseInfo() const
info += m_type + "\n";
// get info depending on license type
- if (isNonCommercialLicenseType())
- {
- info += "not registered for commercial development\n";
- }
- else if (m_numberOfUsers == 0)
+ if (m_numberOfUsers == 0)
{
info += "unlimited users\n";
}
@@ -228,21 +86,135 @@ std::string License::getLicenseInfo() const
info += "1 user\n";
}
- info += getExpireLineUI();
+ if (m_expirationVersion != LicenseConstants::VALID_UNLIMITED)
+ {
+ info += "valid up to version " + m_expirationVersion;
+ }
+ else if (m_expirationDate != LicenseConstants::VALID_UNLIMITED)
+ {
+ info += "valid until " + m_expirationDate;
+ }
+ else
+ {
+ info += "valid perpetually";
+ }
return info;
}
-std::string License::getUser() const
+std::string License::getMessage(bool withNewlines) const
{
- return m_user;
+ if (m_user.empty() || m_type.empty() || m_expirationVersion.empty() || m_expirationDate.empty() || m_hashLine.empty())
+ {
+ return "";
+ }
+
+ const std::string separator = (withNewlines ? "\n" : "");
+ std::string message = LicenseConstants::PRODUCT + separator;
+
+ if (m_isOldFormat)
+ {
+ message += LicenseConstants::LICENSED_TO_OLD + m_user + separator;
+ message += LicenseConstants::LICENSE_TYPE + m_type;
+
+ if (m_numberOfUsers == 0)
+ {
+ message += (m_createdWithSeats ? " (unlimited seats)" : " (unlimited users)");
+ }
+ else if (m_numberOfUsers == 1)
+ {
+ message += (m_createdWithSeats ? " (1 Seat)" : " (1 user)");
+ }
+ else if (m_numberOfUsers > 1)
+ {
+ message += " (" + std::to_string(m_numberOfUsers) + (m_createdWithSeats ? " Seats)" : " users)");
+ }
+ message += separator;
+
+ if (m_expirationVersion != LicenseConstants::VALID_UNLIMITED)
+ {
+ message += LicenseConstants::VALID_UP_TO_OLD + m_expirationVersion + separator;
+ }
+ else if (m_expirationDate != LicenseConstants::VALID_UNLIMITED)
+ {
+ message += LicenseConstants::VALID_UNTIL_OLD + m_expirationDate + separator;
+ }
+ }
+ else
+ {
+ std::string s;
+ message += LicenseConstants::LICENSE_HOLDER + m_user + separator;
+ message += LicenseConstants::LICENSE_TYPE + m_type + separator;
+
+ if (m_numberOfUsers > 0)
+ {
+ message += LicenseConstants::LICENSED_USERS + std::to_string(m_numberOfUsers) + separator;
+ }
+ else
+ {
+ message += s + LicenseConstants::LICENSED_USERS + LicenseConstants::VALID_UNLIMITED + separator;
+ }
+
+ if (m_expirationVersion != LicenseConstants::VALID_UNLIMITED)
+ {
+ message += s + LicenseConstants::LICENSED_VERSION + LicenseConstants::VALID_UP_TO + m_expirationVersion + separator;
+ }
+ else
+ {
+ message += s + LicenseConstants::LICENSED_VERSION + LicenseConstants::VALID_UNLIMITED + separator;
+ }
+
+ if (m_expirationDate != LicenseConstants::VALID_UNLIMITED)
+ {
+ message += s + LicenseConstants::LICENSED_PERIOD + LicenseConstants::VALID_UNTIL + m_expirationDate + separator;
+ }
+ else
+ {
+ message += s + LicenseConstants::LICENSED_PERIOD + LicenseConstants::VALID_UNLIMITED + separator;
+ }
+ }
+
+ message += LicenseConstants::SEPARATOR + separator;
+ message += m_hashLine;
+
+ return message;
+}
+
+void License::setMessage(
+ const std::string& user,
+ const std::string& type,
+ size_t numberOfUsers,
+ const std::string& expirationVersion,
+ const std::string& expirationDate
+){
+ if (user.empty() || type.empty() || (numberOfUsers == 0 && expirationVersion.empty() && expirationDate.empty()))
+ {
+ return;
+ }
+
+ m_user = user;
+ m_type = type;
+ m_numberOfUsers = numberOfUsers;
+ m_expirationVersion = expirationVersion.size() ? expirationVersion : LicenseConstants::VALID_UNLIMITED;
+ m_expirationDate = expirationDate.size() ? expirationDate : LicenseConstants::VALID_UNLIMITED;
+ m_hashLine = generateHash(user + type);
+}
+
+const std::string& License::getSignature() const
+{
+ return m_signature;
+}
+
+void License::setSignature(const std::string& signature)
+{
+ m_signature = signature;
}
int License::getTimeLeft() const
{
const std::string dateText = "YYYY-MMM-DD";
- std::string dateString = m_expire;
+ std::string dateString = m_expirationDate;
if (dateString.length() != dateText.length())
{
return -2;
@@ -269,100 +241,6 @@ bool License::loadFromString(const std::string& licenseText)
return load(license);
}
-bool License::load(std::istream& stream)
-{
- std::string line;
- std::array lines;
-
- line = getLine(stream);
- if (line == LicenseConstants::BEGIN_LICENSE_STRING)
- {
- line = getLine(stream);
- }
-
- // sourcetrail line
- if (line != LicenseConstants::PRODUCT_STRING)
- {
- return false;
- }
-
- // user line
- if (!extractData(getLine(stream), USER_LINE))
- {
- return false;
- }
-
- if (!extractData(getLine(stream), TYPE_LINE))
- {
- return false;
- }
-
- // expire line
- if (!extractData(getLine(stream), EXPIRE_LINE))
- {
- return false;
- }
-
- // separator line
- getline(stream, line, '\n');
- if (trim(line) != LicenseConstants::SEPARATOR_STRING)
- {
- return false;
- }
-
- // hash line
- m_hashLine = getLine(stream);
-
- // signature
- m_signature = "";
- while (getline(stream, line, '\n'))
- {
- std::string l = trim(line);
- if (l == LicenseConstants::END_LICENSE_STRING)
- {
- break;
- }
- if (l.size())
- {
- m_signature += l;
- }
- }
- if (m_signature.length() != 344)
- {
- return false;
- }
-
- return true;
-}
-
-void License::setTypeAndNumberOfUsers(const std::string& line)
-{
- size_t pos = line.find("(");
-
- if (pos != line.npos)
- {
- m_type = line.substr(0, pos - 1);
- try
- {
- m_numberOfUsers = std::stoi(line.substr(pos+1));
- }
- catch (std::invalid_argument e)
- {
- m_numberOfUsers = 0;
- }
-
- if (toLowerCase(line).find("seat") != line.npos)
- {
- m_createdWithSeats = true;
- }
- }
- else
- {
- m_type = line;
- m_numberOfUsers = 0;
- }
-}
-
bool License::loadFromFile(const std::string& filename)
{
std::ifstream sigfile(filename);
@@ -374,293 +252,324 @@ void License::print()
std::cout << getLicenseString();
}
-bool License::isValid() const
+bool License::isEmpty() const
{
- if (!m_publicKey)
+ if (m_user.empty() && m_type.empty() &&
+ m_expirationVersion.empty() && m_expirationDate.empty() &&
+ m_hashLine.empty() && m_signature.empty())
{
- std::cout << "No public key loaded" << std::endl;
- return false;
- }
- try
- {
- if (m_signature.empty())
- {
- std::cout << "Could not read signature" << std::endl;
- return false;
- }
-
- Botan::secure_vector signature = Botan::base64_decode(m_signature);
-
- if (m_publicKey == NULL)
- {
- std::cout << "Public key is NULL" << std::endl;
- return false;
- }
-
- if (isExpired())
- {
- return false;
- }
-
- Botan::PK_Verifier verifier(*m_publicKey.get(), "EMSA4(SHA-256)");
-
- Botan::DataSource_Memory in(getMessage());
- Botan::byte buffer[4096] = {0};
- while(size_t got = in.read(buffer, sizeof(buffer)))
- {
- verifier.update(buffer, got); // what does 'got' stand for?
- }
-
- const bool ok = verifier.check_signature(signature);
- if (!ok)
- {
- std::cout << "License check failed" << std::endl;
- return false;
- }
- return ok;
- }
- catch(...) // invalid character, or something else... why not check what the exception is?
- {
- std::cout << "Invalid character in Licensekey" << std::endl;
- }
- return false;
-}
-
-bool License::isExpired() const
-{
- if (m_expiresAtDate)
- {
- return (getTimeLeft() == -1);
- }
- else
- {
- Version version = Version::fromString(m_expire);
- return Version::getApplicationVersion().toShortVersion() > version;
- }
-}
-
-std::string License::getPublicKeyFilename() const
-{
- if (m_publicKeyFilename.empty())
- {
- return "public-sourcetrail" + KEY_FILEENDING;
- }
- return m_publicKeyFilename;
-}
-
-bool License::loadPublicKeyFromFile(const std::string& filename)
-{
- if (!filename.empty())
- {
- m_publicKeyFilename = filename;
- }
-
- if (boost::filesystem::exists(getPublicKeyFilename()))
- {
- Botan::RSA_PublicKey* rsaPublicKey =
- dynamic_cast(Botan::X509::load_key(getPublicKeyFilename()));
-
- if (!rsaPublicKey)
- {
- std::cout << "The loaded key is not a RSA key" << std::endl;
- return false;
- }
-
- m_publicKey = std::shared_ptr(rsaPublicKey);
return true;
}
return false;
}
-bool License::loadPublicKey()
+bool License::isComplete() const
{
- Botan::DataSource_Memory in(PUBLIC_KEY);
- Botan::RSA_PublicKey *rsaPublicKey = dynamic_cast(Botan::X509::load_key(in));
-
- if (!rsaPublicKey)
+ if (m_user.empty() || m_type.empty() ||
+ m_expirationVersion.empty() || m_expirationDate.empty() ||
+ m_hashLine.empty() || m_signature.empty())
{
- std::cout << "The loaded key is not a RSA key" << std::endl;
return false;
}
- m_publicKey = std::shared_ptr(rsaPublicKey);
return true;
}
-bool License::loadPublicKeyFromString(const std::string& publicKey)
+bool License::isExpired() const
{
- if (publicKey.empty())
+ if (m_expirationVersion != LicenseConstants::VALID_UNLIMITED)
+ {
+ Version version = Version::fromString(m_expirationVersion);
+ return Version::getApplicationVersion().toShortVersion() > version;
+ }
+ else if (m_expirationDate != LicenseConstants::VALID_UNLIMITED)
+ {
+ return (getTimeLeft() == -1);
+ }
+ else if (m_expirationVersion == LicenseConstants::VALID_UNLIMITED &&
+ m_expirationDate == LicenseConstants::VALID_UNLIMITED)
{
- std::cout << "Public key is empty" << std::endl;
return false;
}
- Botan::DataSource_Memory in(publicKey);
- Botan::RSA_PublicKey *rsaPublicKey = dynamic_cast(Botan::X509::load_key(in));
-
- if (!rsaPublicKey)
- {
- std::cout << "The loaded key is not a RSA key" << std::endl;
- return false;
- }
-
- m_publicKey = std::shared_ptr(rsaPublicKey);
return true;
}
+bool License::isTestLicense() const
+{
+ return m_type == LicenseConstants::TEST_LICENSE;
+}
+
std::string License::getLicenseString() const
{
+ if (m_user.empty() || m_type.empty() || m_expirationVersion.empty() || m_expirationDate.empty())
+ {
+ return "";
+ }
+
+ std::string signatureLines;
+ std::stringstream ss;
+ const int lineLength = 55;
+ for (size_t i = 0; i < m_signature.size(); i++)
+ {
+ if (i % lineLength == 0 && i != 0)
+ {
+ signatureLines += ss.str() + "\n";
+ ss.str("");
+ }
+ ss << m_signature[i];
+ }
+ signatureLines += ss.str();
+
std::string license = "";
- license += LicenseConstants::BEGIN_LICENSE_STRING;
+ license += LicenseConstants::BEGIN_LICENSE;
license += "\n";
license += getMessage(true) + "\n";
- license += getSignature() + "\n";
- license += LicenseConstants::END_LICENSE_STRING;
+ license += signatureLines + "\n";
+ license += LicenseConstants::END_LICENSE;
license += "\n";
return license;
}
-std::string License::hashLocation(const std::string& location) const
+std::string License::generateHash(const std::string& str) const
{
- if (m_rng == NULL || location.size() <= 0)
+ if (m_rng == NULL || str.size() <= 0)
{
return "";
}
- return Botan::generate_passhash9(location, *(m_rng.get()));
+ return Botan::generate_passhash9(str, *(m_rng.get()));
}
-bool License::checkLocation(const std::string& location, const std::string& hash)
+bool License::checkHash(const std::string& str, const std::string& hash)
{
- if (location.empty() || hash.empty())
+ if (str.empty() || hash.empty())
{
return true;
}
- return Botan::check_passhash9(location, hash);
+ return Botan::check_passhash9(str, hash);
}
-std::string License::getLicenseEncodedString(const std::string& applicationLocation) const
+bool License::load(std::istream& stream)
{
- if (applicationLocation.empty())
+ std::string line;
+ std::vector lines;
+
+ while (getline(stream, line, '\n'))
{
- std::cout << "No application location was given" << std::endl;
- return "";
+ line = trim(line);
+
+ if ((!lines.size() && line == LicenseConstants::BEGIN_LICENSE) || line == LicenseConstants::END_LICENSE)
+ {
+ continue;
+ }
+
+ if (line.size())
+ {
+ lines.push_back(line);
+ }
}
- Botan::AutoSeeded_RNG rng;
- std::vector fileContents;
- std::stringstream input(getLicenseString());
-
- //prepare the license string to work with the botan cryptobox
- while(input.good())
+ if (lines.size() == 15)
{
- Botan::byte filebuffer[4096] = { 0 };
- input.read((char*)filebuffer, sizeof(filebuffer));
- size_t got = input.gcount(); // what does got stand for?
-
- fileContents.insert(fileContents.end(), filebuffer, filebuffer + got);
+ m_isOldFormat = false;
+ return loadFromLines(lines);
}
-
- if(fileContents.size() <= 0)
+ else if (lines.size() == 13)
{
- std::cout << "Failed to read license string" << std::endl;
- return "";
- }
-
- std::string result =
- Botan::CryptoBox::encrypt(&fileContents[0], fileContents.size(), getEncodeKey(applicationLocation), rng);
-
- //remove Botan Cryptobox begin and end
- //should not be in the application settings
- const int leMagicNumberA = 40;
- const int leMagicNumberB = 78;
-
- if (result.length() < leMagicNumberA + leMagicNumberB)
- {
- std::cout << "Invalid result" << std::endl;
- return "";
- }
-
- result = result.substr(leMagicNumberA, result.length() - leMagicNumberB);
-
- return result;
-}
-
-bool License::loadFromEncodedString(const std::string& encodedLicense, const std::string& applicationLocation)
-{
- if (encodedLicense.empty())
- {
- std::cout << "No license string given" << std::endl;
- return false;
- }
-
- if (applicationLocation.empty())
- {
- std::cout << "No application location given" << std::endl;
- return false;
- }
-
- try
- {
- //add cryptobox begin and end to loaded string
- std::string crypbobxInput = "-----BEGIN BOTAN CRYPTOBOX MESSAGE-----\n";
- crypbobxInput += encodedLicense;
- crypbobxInput += "-----END BOTAN CRYPTOBOX MESSAGE-----";
-
- //decrypt license
- return loadFromString(Botan::CryptoBox::decrypt(crypbobxInput, getEncodeKey(applicationLocation)));
- }
- catch(...)
- {
- //loaded string from application settings is invalid
- return false;
+ m_isOldFormat = true;
+ return loadFromLinesOld(lines);
}
return false;
}
-std::string License::getHashedLicense() const
+bool License::loadFromLines(const std::vector& lines)
{
- return getEncodeKey("fakeKey");
-}
-
-std::string License::getEncodeKey(const std::string applicationLocation) const
-{
- if (applicationLocation.empty())
+ if (lines.size() != 15)
{
- std::cout << "No application location given" << std::endl;
- return "";
+ return false;
}
- Botan::PBKDF *pbkdf = Botan::get_pbkdf("PBKDF2(SHA-256)");
- Botan::secure_vector salt = Botan::base64_decode("34zA54n60v4CxjY5n20k3J40c976n690", 32);
- Botan::AutoSeeded_RNG rng;
- return pbkdf->derive_key(32, applicationLocation, &salt[0], salt.size(), 10000).as_string();
-}
-
-std::string License::getSignature() const
-{
- std::string sig;
- std::stringstream ss;
- const int lineLength = 55;
- for (size_t i = 0; i < m_signature.size(); i++)
+ // sourcetrail line
+ if (lines[0] != LicenseConstants::PRODUCT)
{
- if(i % lineLength == 0 && i != 0)
+ return false;
+ }
+
+ // user line
+ m_user = removeCaption(lines[1], LicenseConstants::LICENSE_HOLDER);
+ if (m_user.empty())
+ {
+ return false;
+ }
+
+ // type line
+ m_type = removeCaption(lines[2], LicenseConstants::LICENSE_TYPE);
+ if (m_type.empty())
+ {
+ return false;
+ }
+
+ // number of users
+ std::string users = removeCaption(lines[3], LicenseConstants::LICENSED_USERS);
+ if (users != LicenseConstants::VALID_UNLIMITED)
+ {
+ try
{
- sig += ss.str() + "\n";
- ss.str("");
+ m_numberOfUsers = std::stoi(users);
}
- ss << m_signature[i];
+ catch (std::invalid_argument e)
+ {
+ m_numberOfUsers = 0;
+ return false;
+ }
+ }
+ else
+ {
+ m_numberOfUsers = 0;
}
- sig += ss.str();
- return sig;
+ // expiration version
+ m_expirationVersion = removeCaption(lines[4], LicenseConstants::LICENSED_VERSION);
+ if (m_expirationVersion != LicenseConstants::VALID_UNLIMITED)
+ {
+ m_expirationVersion = removeCaption(m_expirationVersion, LicenseConstants::VALID_UP_TO);
+ if (!Version::fromString(m_expirationVersion).isValid())
+ {
+ return false;
+ }
+ }
+
+ // expiration date
+ m_expirationDate = removeCaption(lines[5], LicenseConstants::LICENSED_PERIOD);
+ if (m_expirationDate != LicenseConstants::VALID_UNLIMITED)
+ {
+ m_expirationDate = removeCaption(m_expirationDate, LicenseConstants::VALID_UNTIL);
+
+ if (m_expirationDate.size() != 11 || m_expirationDate[4] != '-' || m_expirationDate[8] != '-')
+ {
+ return false;
+ }
+ }
+
+ // separator line
+ if (lines[6] != LicenseConstants::SEPARATOR)
+ {
+ return false;
+ }
+
+ // hash line
+ m_hashLine = lines[7];
+ if (m_hashLine.length() != 55)
+ {
+ return false;
+ }
+
+ // signature
+ m_signature = lines[8] + lines[9] + lines[10] + lines[11] + lines[12] + lines[13] + lines[14];
+ if (m_signature.length() != 344)
+ {
+ return false;
+ }
+
+ return true;
}
-void License::setSignature(const std::string& signature)
+bool License::loadFromLinesOld(const std::vector& lines)
{
- m_signature = signature;
+ if (lines.size() != 13)
+ {
+ return false;
+ }
+
+ // sourcetrail line
+ if (lines[0] != LicenseConstants::PRODUCT)
+ {
+ return false;
+ }
+
+ // user line
+ m_user = removeCaption(lines[1], LicenseConstants::LICENSED_TO_OLD);
+ if (m_user.empty())
+ {
+ return false;
+ }
+
+ // type line
+ {
+ std::string line = removeCaption(lines[2], LicenseConstants::LICENSE_TYPE);
+ size_t pos = line.find("(");
+
+ if (pos != line.npos)
+ {
+ m_type = line.substr(0, pos - 1);
+ try
+ {
+ m_numberOfUsers = std::stoi(line.substr(pos+1));
+ }
+ catch (std::invalid_argument e)
+ {
+ m_numberOfUsers = 0;
+ }
+
+ if (toLowerCase(line).find("seat") != line.npos)
+ {
+ m_createdWithSeats = true;
+ }
+ }
+ else
+ {
+ m_type = line;
+ m_numberOfUsers = 0;
+ }
+
+ if (m_type.empty())
+ {
+ return false;
+ }
+ }
+
+ // expire line
+ m_expirationVersion = removeCaption(lines[3], LicenseConstants::VALID_UP_TO_OLD);
+ m_expirationDate = removeCaption(lines[3], LicenseConstants::VALID_UNTIL_OLD);
+ if (m_expirationVersion.empty() && m_expirationDate.empty())
+ {
+ return false;
+ }
+
+ if (m_expirationVersion.empty())
+ {
+ m_expirationVersion = LicenseConstants::VALID_UNLIMITED;
+ }
+
+ if (m_expirationDate.empty())
+ {
+ m_expirationDate = LicenseConstants::VALID_UNLIMITED;
+ }
+
+ // separator line
+ if (lines[4] != LicenseConstants::SEPARATOR)
+ {
+ return false;
+ }
+
+ // hash line
+ m_hashLine = lines[5];
+ if (m_hashLine.length() != 55)
+ {
+ return false;
+ }
+
+ // signature
+ m_signature = lines[6] + lines[7] + lines[8] + lines[9] + lines[10] + lines[11] + lines[12];
+ if (m_signature.length() != 344)
+ {
+ return false;
+ }
+
+ return true;
}
diff --git a/src/lib_license/License.h b/src/lib_license/License.h
index 78703da9..61c94eab 100644
--- a/src/lib_license/License.h
+++ b/src/lib_license/License.h
@@ -4,130 +4,101 @@
#include
#include
#include
-#include
namespace Botan
{
- class RSA_PublicKey;
- class RSA_PrivateKey;
class AutoSeeded_RNG;
}
-namespace LicenseConstants {
- const char BEGIN_LICENSE_STRING[] = "-----BEGIN LICENSE-----";
- const char END_LICENSE_STRING[] = "-----END LICENSE-----";
- const char TEST_LICENSE_STRING[] = "Test License";
- const char PRODUCT_STRING[] = "Product: Sourcetrail";
- const char LICENSED_TO_STRING[] = "Licensed to: ";
- const char LICENSE_TYPE_STRING[] = "License type: ";
- const char VALID_UNTIL_STRING[] = "Valid until: ";
- const char VALID_UP_TO_STRING[] = "Valid up to version: ";
- const char SEPARATOR_STRING[] = "-";
- const int MINOR_VERSIONS_PER_YEAR = 4;
+namespace LicenseConstants
+{
+ const char BEGIN_LICENSE[] = "-----BEGIN LICENSE-----";
+ const char END_LICENSE[] = "-----END LICENSE-----";
+
+ const char TEST_LICENSE[] = "Test License";
+
+ const char PRODUCT[] = "Product: Sourcetrail";
+
+ const char LICENSE_HOLDER[] = "License holder: ";
+ const char LICENSE_TYPE[] = "License type: ";
+ const char LICENSED_USERS[] = "Licensed number of users: ";
+ const char LICENSED_VERSION[] = "Licensed product version: ";
+ const char LICENSED_PERIOD[] = "Licensed usage period: ";
+
+ const char VALID_UNTIL[] = "until ";
+ const char VALID_UP_TO[] = "up to ";
+ const char VALID_UNLIMITED[] = "unlimited";
+
+ const char LICENSED_TO_OLD[] = "Licensed to: ";
+ const char VALID_UNTIL_OLD[] = "Valid for: ";
+ const char VALID_UP_TO_OLD[] = "Valid up to version: ";
+
+ const char SEPARATOR[] = "-";
}
class License
{
public:
- enum LICENSE_LINE
- {
- BEGIN_LICENSE_LINE = 0,
- SOURCETRAIL_LINE = 1,
- USER_LINE = 2,
- TYPE_LINE = 3,
- EXPIRE_LINE = 4,
- SEPARATOR_LINE=5,
- HASH_LINE = 6,
- FIRST_SIGNATURE_LINE = 7,
- LAST_SIGNATURE_LINE = 13,
- END_LICENSE_LINE = 14,
- LICENSE_LINES = 15
- };
-
License();
~License();
- std::string getMessage(bool withNewlines = false) const;
- std::string getSignature() const;
- std::string getVersionLineWithoutPrefix() const;
- std::string getLine(std::istream& stream);
- std::string getLineWithoutDescription(LICENSE_LINE line) const;
-
- void setLine(const LICENSE_LINE line, const std::string& value);
- void setHashLine(const std::string& hash);
- void setTypeAndNumberOfUsers(const std::string& line);
-
- std::string getLicenseInfo() const;
- std::string getPublicKeyFilename() const;
- std::string getVersion() const;
std::string getType() const;
std::string getUser() const;
size_t getNumberOfUsers() const;
+ std::string getLicenseInfo() const;
- void createHeader(
+ std::string getMessage(bool withNewlines) const;
+ void setMessage(
const std::string& user,
const std::string& type,
- const std::string& expiration,
- bool expiresAtDate,
- size_t numberOfUsers = 0
+ size_t numberOfUsers,
+ const std::string& expirationVersion,
+ const std::string& expirationDate
);
- std::string getExpireLine() const;
- std::string getExpireLineUI() const;
- /// if Test License return >=0 or -1 if expired
- /// for non Test License -2
- int getTimeLeft() const;
+ const std::string& getSignature() const;
+ void setSignature(const std::string& signature);
std::string getLicenseString() const;
- std::string getLicenseEncodedString(const std::string& applicationLocation) const;
- std::string getHashedLicense() const;
void writeToFile(const std::string& filename);
- bool load(std::istream& stream);
+
bool loadFromString(const std::string& licenseText);
bool loadFromFile(const std::string& filename);
- bool loadFromEncodedString(const std::string& encodedLicense, const std::string& applicationLocation);
- bool loadPublicKey();
-
- bool loadPublicKeyFromFile(const std::string&);
- bool loadPublicKeyFromString(const std::string&);
-
- void setSignature(const std::string&);
-
- bool isValid() const;
+ bool isEmpty() const;
+ bool isComplete() const;
bool isExpired() const;
bool isTestLicense() const;
- bool isNonCommercialLicenseType() const;
+
+ // if Test License return >=0 or -1 if expired
+ // for non Test License -2
+ int getTimeLeft() const;
void print();
- std::string hashLocation(const std::string&) const;
- static bool checkLocation(const std::string&, const std::string&);
+ std::string generateHash(const std::string& str) const;
+ static bool checkHash(const std::string& str, const std::string& hash);
private:
- std::string getEncodeKey(const std::string applicationLocation) const;
- bool extractData(const std::string& data, LICENSE_LINE line);
- std::string removeCaption(const std::string& line, const std::string& caption) const;
+ bool load(std::istream& stream);
+ bool loadFromLines(const std::vector& lines);
+ bool loadFromLinesOld(const std::vector& lines);
- std::string m_publicKeyFilename;
- std::shared_ptr m_publicKey;
+ std::unique_ptr m_rng;
- std::shared_ptr m_rng;
- // message
std::string m_user;
std::string m_type;
- size_t m_numberOfUsers;
- bool m_createdWithSeats;
- std::string m_expire;
- bool m_expiresAtDate;
- std::string m_hashLine;
+ size_t m_numberOfUsers = 0;
+ bool m_createdWithSeats = false;
+ std::string m_expirationVersion;
+ std::string m_expirationDate;
+
+ std::string m_hashLine;
std::string m_signature;
- const std::string KEY_FILEENDING = ".pem";
-
- const std::vector NON_COMMERCIAL_LICENSE_TYPES = { { "Private/Academic Single User License" } };
+ bool m_isOldFormat = false;
};
#endif // SOURCETRAIL_LICENSE_H
diff --git a/src/lib_license/LicenseChecker.cpp b/src/lib_license/LicenseChecker.cpp
new file mode 100644
index 00000000..e50fde1d
--- /dev/null
+++ b/src/lib_license/LicenseChecker.cpp
@@ -0,0 +1,336 @@
+#include "LicenseChecker.h"
+
+#include
+#include
+
+#include
+// #include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "License.h"
+#include "PublicKey.h"
+
+std::string LicenseChecker::s_encodeKey;
+std::unique_ptr LicenseChecker::s_publicKey;
+std::unique_ptr LicenseChecker::s_currentLicense;
+
+void LicenseChecker::setEncodeKey(const std::string& key)
+{
+ if (key.empty())
+ {
+ return;
+ }
+
+ Botan::PBKDF *pbkdf = Botan::get_pbkdf("PBKDF2(SHA-256)");
+ Botan::secure_vector salt = Botan::base64_decode("34zA54n60v4CxjY5n20k3J40c976n690", 32);
+ s_encodeKey = pbkdf->derive_key(32, key, &salt[0], salt.size(), 10000).as_string();
+}
+
+bool LicenseChecker::loadPublicKeyFromFile(std::string fileName)
+{
+ if (!boost::filesystem::exists(fileName))
+ {
+ std::cout << "Public key file does not exist: " << fileName << std::endl;
+ return false;
+ }
+
+ return createPublicKey(dynamic_cast(Botan::X509::load_key(fileName)));
+}
+
+bool LicenseChecker::loadPublicKeyFromString(const std::string& publicKey)
+{
+ if (publicKey.empty())
+ {
+ std::cout << "Public key is empty" << std::endl;
+ return false;
+ }
+
+ Botan::DataSource_Memory in(publicKey);
+ return createPublicKey(dynamic_cast(Botan::X509::load_key(in)));
+}
+
+bool LicenseChecker::loadPublicKey()
+{
+ return loadPublicKeyFromString(PUBLIC_KEY);
+}
+
+const License* LicenseChecker::getCurrentLicense()
+{
+ return s_currentLicense.get();
+}
+
+std::string LicenseChecker::getCurrentLicenseString()
+{
+ if (s_currentLicense)
+ {
+ return s_currentLicense->getLicenseString();
+ }
+ return "";
+}
+
+std::string LicenseChecker::getCurrentLicenseStringEncoded()
+{
+ if (!s_currentLicense)
+ {
+ std::cout << "No current license" << std::endl;
+ return "";
+ }
+
+ if (s_encodeKey.empty())
+ {
+ std::cout << "No encode key" << std::endl;
+ return "";
+ }
+
+ Botan::AutoSeeded_RNG rng;
+ std::vector fileContents;
+ std::stringstream input(s_currentLicense->getLicenseString());
+
+ // prepare the license string to work with the botan cryptobox
+ while (input.good())
+ {
+ Botan::byte filebuffer[4096] = { 0 };
+ input.read((char*)filebuffer, sizeof(filebuffer));
+ size_t got = input.gcount();
+
+ fileContents.insert(fileContents.end(), filebuffer, filebuffer + got);
+ }
+
+ if (fileContents.size() <= 0)
+ {
+ std::cout << "Failed to read license string" << std::endl;
+ return "";
+ }
+
+ std::string result = Botan::CryptoBox::encrypt(&fileContents[0], fileContents.size(), s_encodeKey, rng);
+
+ // remove Botan Cryptobox begin and end
+ // should not be in the application settings
+ const int cryptoboxBeginLength = 40;
+ const int cryptoboxEndLength = 38;
+
+ if (result.length() < cryptoboxBeginLength + cryptoboxEndLength)
+ {
+ std::cout << "Invalid result" << std::endl;
+ return "";
+ }
+
+ result = result.substr(cryptoboxBeginLength, result.length() - (cryptoboxBeginLength + cryptoboxEndLength));
+
+ return result;
+}
+
+LicenseChecker::LicenseState LicenseChecker::setCurrentLicenseString(const std::string& licenseStr)
+{
+ s_currentLicense = nullptr;
+
+ if (licenseStr.empty())
+ {
+ return LicenseState::EMPTY;
+ }
+
+ s_currentLicense = std::make_unique();
+ if (!s_currentLicense->loadFromString(licenseStr))
+ {
+ s_currentLicense = nullptr;
+ return LicenseState::MALFORMED;
+ }
+
+ return checkCurrentLicense();
+}
+
+LicenseChecker::LicenseState LicenseChecker::setCurrentLicenseStringEncoded(const std::string& licenseStr)
+{
+ s_currentLicense = nullptr;
+
+ if (licenseStr.empty())
+ {
+ return LicenseState::EMPTY;
+ }
+
+ if (s_encodeKey.empty())
+ {
+ std::cout << "No key available" << std::endl;
+ return LicenseState::EMPTY;
+ }
+
+ s_currentLicense = std::make_unique();
+
+ try
+ {
+ // add cryptobox begin and end to loaded string
+ std::string cryptoboxInput = "-----BEGIN BOTAN CRYPTOBOX MESSAGE-----\n";
+ cryptoboxInput += licenseStr;
+ cryptoboxInput += "-----END BOTAN CRYPTOBOX MESSAGE-----";
+
+ // decrypt license
+ if (!s_currentLicense->loadFromString(Botan::CryptoBox::decrypt(cryptoboxInput, s_encodeKey)))
+ {
+ s_currentLicense = nullptr;
+ return LicenseState::MALFORMED;
+ }
+ }
+ catch (...)
+ {
+ s_currentLicense = nullptr;
+ return LicenseState::MALFORMED;
+ }
+
+ return checkCurrentLicense();
+}
+
+LicenseChecker::LicenseState LicenseChecker::checkLicense(const License& license)
+{
+ if (license.isEmpty())
+ {
+ return LicenseState::EMPTY;
+ }
+
+ if (!license.isComplete())
+ {
+ return LicenseState::INCOMPLETE;
+ }
+
+ std::string message = license.getMessage(false);
+ std::string signature = license.getSignature();
+ if (message.empty() || signature.empty())
+ {
+ return LicenseState::INCOMPLETE;
+ }
+
+ if (!s_publicKey)
+ {
+ std::cout << "No public key loaded" << std::endl;
+ return LicenseState::INCOMPLETE;
+ }
+
+ try
+ {
+ Botan::PK_Verifier verifier(*s_publicKey.get(), "EMSA4(SHA-256)");
+ Botan::DataSource_Memory in(message);
+ Botan::byte buffer[4096] = { 0 };
+
+ while (size_t got = in.read(buffer, sizeof(buffer)))
+ {
+ verifier.update(buffer, got);
+ }
+
+ Botan::secure_vector sig = Botan::base64_decode(signature);
+ if (!verifier.check_signature(sig))
+ {
+ return LicenseState::INVALID;
+ }
+ }
+ catch (...)
+ {
+ std::cout << "Invalid character in Licensekey" << std::endl;
+ return LicenseState::MALFORMED;
+ }
+
+ if (license.isExpired())
+ {
+ return LicenseState::EXPIRED;
+ }
+
+ return LicenseState::VALID;
+}
+
+LicenseChecker::LicenseState LicenseChecker::checkLicenseString(const std::string& licenseString)
+{
+ if (licenseString.size() == 0)
+ {
+ return LicenseState::EMPTY;
+ }
+
+ License license;
+ bool isLoaded = license.loadFromString(licenseString);
+ if (!isLoaded)
+ {
+ return LicenseState::MALFORMED;
+ }
+
+ return checkLicense(license);
+}
+
+LicenseChecker::LicenseState LicenseChecker::checkCurrentLicense()
+{
+ if (!s_currentLicense)
+ {
+ return LicenseState::EMPTY;
+ }
+
+ return checkLicense(*s_currentLicense.get());
+}
+
+LicenseType LicenseChecker::getCurrentLicenseType()
+{
+ if (!s_currentLicense)
+ {
+ return LicenseType::NON_COMMERCIAL;
+ }
+
+ LicenseState state = checkLicense(*s_currentLicense.get());
+ if (state != LicenseState::VALID)
+ {
+ return LicenseType::NON_COMMERCIAL;
+ }
+ else if (s_currentLicense->isTestLicense())
+ {
+ return LicenseType::TEST;
+ }
+
+ return LicenseType::COMMERCIAL;
+}
+
+std::string LicenseChecker::getCurrentLicenseTypeString()
+{
+ // WARNING: Don't change these strings. The analytics API on the server relies on them.
+ switch (getCurrentLicenseType())
+ {
+ case LicenseType::NON_COMMERCIAL:
+ return "private";
+ case LicenseType::TEST:
+ return "test";
+ case LicenseType::COMMERCIAL:
+ return "commercial";
+ }
+
+ return "private";
+}
+
+std::string LicenseChecker::getLicenseErrorForState(LicenseState state)
+{
+ switch (state)
+ {
+ case LicenseState::EMPTY:
+ return "No license key was entered.";
+ case LicenseState::INCOMPLETE:
+ return "The license key is incomplete.";
+ case LicenseState::MALFORMED:
+ return "The license key is malformed.";
+ case LicenseState::INVALID:
+ return "The license key is invalid.";
+ case LicenseState::EXPIRED:
+ return "The license key is expired.";
+ case LicenseState::VALID:
+ return "";
+ }
+}
+
+bool LicenseChecker::createPublicKey(Botan::RSA_PublicKey *rsaPublicKey)
+{
+ if (!rsaPublicKey)
+ {
+ std::cout << "The loaded key is not a RSA key" << std::endl;
+ return false;
+ }
+
+ s_publicKey = std::unique_ptr(rsaPublicKey);
+ return true;
+}
diff --git a/src/lib_license/LicenseChecker.h b/src/lib_license/LicenseChecker.h
new file mode 100644
index 00000000..c68fda8a
--- /dev/null
+++ b/src/lib_license/LicenseChecker.h
@@ -0,0 +1,60 @@
+#ifndef LICENSE_CHECKER_H
+#define LICENSE_CHECKER_H
+
+#include
+#include
+
+#include "License.h"
+#include "LicenseType.h"
+
+namespace Botan
+{
+ class RSA_PublicKey;
+ class AutoSeeded_RNG;
+}
+
+class LicenseChecker
+{
+public:
+ enum class LicenseState
+ {
+ EMPTY,
+ INCOMPLETE,
+ MALFORMED,
+ INVALID,
+ EXPIRED,
+ VALID
+ };
+
+ static void setEncodeKey(const std::string& key);
+
+ static bool loadPublicKeyFromFile(std::string fileName);
+ static bool loadPublicKeyFromString(const std::string& publicKey);
+ static bool loadPublicKey();
+
+ static const License* getCurrentLicense();
+
+ static std::string getCurrentLicenseString();
+ static std::string getCurrentLicenseStringEncoded();
+
+ static LicenseState setCurrentLicenseString(const std::string& licenseStr);
+ static LicenseState setCurrentLicenseStringEncoded(const std::string& licenseStr);
+
+ static LicenseState checkLicense(const License& license);
+ static LicenseState checkLicenseString(const std::string& licenseString);
+ static LicenseState checkCurrentLicense();
+
+ static LicenseType getCurrentLicenseType();
+ static std::string getCurrentLicenseTypeString();
+
+ static std::string getLicenseErrorForState(LicenseState state);
+
+private:
+ static bool createPublicKey(Botan::RSA_PublicKey *rsaPublicKey);
+
+ static std::string s_encodeKey;
+ static std::unique_ptr s_publicKey;
+ static std::unique_ptr s_currentLicense;
+};
+
+#endif // LICENSE_CHECKER_H
diff --git a/src/lib_license/LicenseType.h b/src/lib_license/LicenseType.h
new file mode 100644
index 00000000..97dd015a
--- /dev/null
+++ b/src/lib_license/LicenseType.h
@@ -0,0 +1,11 @@
+#ifndef LICENSE_TYPE_H
+#define LICENSE_TYPE_H
+
+enum class LicenseType
+{
+ TEST,
+ NON_COMMERCIAL,
+ COMMERCIAL
+};
+
+#endif // LICENSE_TYPE_H
diff --git a/src/license_generator/CMakeLists.txt b/src/license_generator/CMakeLists.txt
index 4164af63..16ee6b06 100644
--- a/src/license_generator/CMakeLists.txt
+++ b/src/license_generator/CMakeLists.txt
@@ -1,8 +1,8 @@
add_files(
LICENSE_GENERATOR
- Generator.cpp
- Generator.h
+ LicenseGenerator.cpp
+ LicenseGenerator.h
)
# split for tests
diff --git a/src/license_generator/Generator.cpp b/src/license_generator/Generator.cpp
deleted file mode 100644
index 1c61b893..00000000
--- a/src/license_generator/Generator.cpp
+++ /dev/null
@@ -1,291 +0,0 @@
-#include "Generator.h"
-
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "License.h"
-#include "Version.h"
-#include "PrivateKey.h"
-#include "PublicKey.h"
-
-const char PRIVATE_KEY_PASSWORD[] = "BA#jk5vbklAiKL9K3k$";
-const char PRIVATE_KEY_FILE[] = "private-sourcetrail.pem";
-const char PUBLIC_KEY_FILE[] = "public-sourcetrail.pem";
-
-Generator::Generator()
-{
- loadPrivateKeyFromString(PRIVATE_KEY);
-}
-
-Generator::~Generator()
-{
-}
-
-void Generator::generateKeys()
-{
- m_privateKey = std::make_unique(m_rng, 2048);
-}
-
-std::string Generator::getPrivateKeyFilename()
-{
- if(m_privateKeyFile.empty())
- {
- return PRIVATE_KEY_FILE;
- }
- return m_privateKeyFile;
-}
-
-std::string Generator::getPublicKeyFilename()
-{
- if(m_publicKeyFile.empty())
- {
- return PUBLIC_KEY_FILE;
- }
- return m_publicKeyFile;
-}
-
-std::string Generator::encodeLicenseByVersion(
- const std::string& user,
- const std::string& licenseType,
- size_t numberOfUsers,
- const std::string& version
-){
- m_license = nullptr;
-
- if (user.size() <= 0)
- {
- std::cout << "No user given" << std::endl;
- return "";
- }
-
- if (licenseType.size() <= 0)
- {
- std::cout << "No license type given" << std::endl;
- return "";
- }
-
- if (version.empty())
- {
- std::cout << "No version given" << std::endl;
- return "";
- }
-
- Version tempVersion = Version::fromString(version);
- if (tempVersion.isValid())
- {
- createLicense(user, licenseType, tempVersion.toShortString(), false, numberOfUsers);
- }
-
- return m_license->getLicenseString();
-}
-
-std::string Generator::encodeLicenseByQuarters(
- const std::string& user,
- const std::string& licenseType,
- size_t numberOfUsers,
- size_t quarters
-){
- return encodeLicenseByVersion(user, licenseType, numberOfUsers, getExpireVersion(quarters));
-}
-
-std::string Generator::encodeLicenseByDays(
- const std::string& user,
- const std::string& licenseType,
- size_t numberOfUsers,
- size_t days
-){
- boost::gregorian::date today = boost::gregorian::day_clock::local_day();
- boost::gregorian::days daysToTry(days);
- boost::gregorian::date expireDate = today + daysToTry;
-
- createLicense(user, licenseType, boost::gregorian::to_simple_string(expireDate), true, numberOfUsers);
-
- return m_license->getLicenseString();
-}
-
-void Generator::printLicenseAndWriteItToFile()
-{
- if (m_license)
- {
- m_license->print();
- m_license->writeToFile("license.txt");
- }
- else
- {
- std::cout << "nothing to print" << std::endl;
- }
-}
-
-bool Generator::verifyLicense(const std::string& filename)
-{
- License license;
- license.loadFromFile(filename);
-// license.loadPublicKeyFromString(PUBLIC_KEY);
- return license.isValid();
-}
-
-void Generator::setCustomPrivateKeyFile(const std::string& file)
-{
- if(!file.empty())
- {
- m_privateKeyFile = file;
- }
-}
-
-void Generator::setCustomPublicKeyFile(const std::string& file)
-{
- if(!file.empty())
- {
- m_publicKeyFile = file;
- }
-}
-
-std::string Generator::getPublicKeyPEMFileAsString()
-{
- return Botan::X509::PEM_encode(*m_privateKey);
-}
-
-std::string Generator::getPrivateKeyPEMFileAsString()
-{
- if (m_privateKey == NULL)
- {
- std::cout << "m_privateKey is NULL" << std::endl;
- return "";
- }
-
- return Botan::PKCS8::PEM_encode(*m_privateKey, m_rng, PRIVATE_KEY_PASSWORD);
-}
-
-void Generator::writeKeysToFiles()
-{
- std::string publicKeyFilename = getPublicKeyFilename();
- if (publicKeyFilename.size() <= 0)
- {
- std::cout << "Failed to retrieve file name for public key" << std::endl;
- return;
- }
-
- std::string privateKeyFilename = getPrivateKeyFilename();
- if (privateKeyFilename.size() <= 0)
- {
- std::cout << "Failed to retrieve file name for private key" << std::endl;
- return;
- }
-
- std::cout << "public key filename: " << publicKeyFilename << std::endl;
- std::ofstream pub(publicKeyFilename);
- pub << getPublicKeyPEMFileAsString();
- std::cout << "public key created" << std::endl;
-
- std::cout << "private key filename: " << privateKeyFilename << std::endl;
- std::ofstream priv(privateKeyFilename);
- priv << getPrivateKeyPEMFileAsString();
- std::cout << "private key created" << std::endl;
-}
-
-bool Generator::loadPrivateKeyFromFile()
-{
- if (boost::filesystem::exists(getPrivateKeyFilename()) == false)
- {
- return false;
- }
-
- Botan::Private_Key* privateKey = Botan::PKCS8::load_key(getPrivateKeyFilename(), m_rng, PRIVATE_KEY_PASSWORD);
- Botan::RSA_PrivateKey *rsaKey = dynamic_cast(privateKey);
-
- if (!rsaKey)
- {
- std::cout << "The key is not a RSA key" << std::endl;
- return false;
- }
-
- m_privateKey = std::unique_ptr(rsaKey);
-
- return (m_privateKey != NULL);
-}
-
-bool Generator::loadPrivateKeyFromString(const std::string& key)
-{
- if (key.size() <= 0)
- {
- std::cout << "No key string given" << std::endl;
- return false;
- }
-
- Botan::DataSource_Memory in(key);
- Botan::Private_Key* privateKey= Botan::PKCS8::load_key(in, m_rng, PRIVATE_KEY_PASSWORD);
- Botan::RSA_PrivateKey *rsaKey = dynamic_cast(privateKey);
-
- if (!rsaKey)
- {
- std::cout << "The key is not a RSA key" << std::endl;
- return false;
- }
-
- m_privateKey = std::unique_ptr(rsaKey);
-
- return (m_privateKey != NULL);
-}
-
-Botan::RSA_PrivateKey *Generator::getPrivateKey() const
-{
- return m_privateKey.get();
-}
-
-void Generator::createLicense(
- const std::string& user,
- const std::string& type,
- const std::string& expiration,
- bool expiresAtDate,
- size_t numberOfUsers
-){
- m_license = std::make_unique();
-
- m_license->createHeader(
- user, type.size() ? type : LicenseConstants::TEST_LICENSE_STRING, expiration, expiresAtDate, numberOfUsers);
-
- Botan::AutoSeeded_RNG rng;
- std::string pass9 = Botan::generate_passhash9(m_license->getExpireLine(), m_rng);
- m_license->setHashLine(pass9);
-
- //encode message
- const std::string emsa = "EMSA4(SHA-256)";
- Botan::PK_Signer signer(*(m_privateKey.get()), rng, emsa);
- Botan::DataSource_Memory in(m_license->getMessage());
- Botan::byte buffer[4096] = {0};
-
- while (size_t got = in.read(buffer, sizeof(buffer)))
- {
- signer.update(buffer, got);
- }
-
- const std::string signature = Botan::base64_encode(signer.signature(rng));
- m_license->setSignature(signature);
-}
-
-int Generator::mapMonthToVersion(int month)
-{
- return (month-1)/3+1;
-}
-
-std::string Generator::getExpireVersion(int quarters)
-{
- boost::gregorian::date today = boost::gregorian::day_clock::local_day();
- int monthNumber = today.month().as_number();
- Version version(today.year(), mapMonthToVersion(monthNumber));
- version += quarters;
- return version.toShortString();
-}
diff --git a/src/license_generator/Generator.h b/src/license_generator/Generator.h
deleted file mode 100644
index 906fce35..00000000
--- a/src/license_generator/Generator.h
+++ /dev/null
@@ -1,78 +0,0 @@
-#ifndef KEYGEN_H
-#define KEYGEN_H
-
-#include
-#include
-
-#include
-
-namespace Botan
-{
- class RSA_PrivateKey;
-}
-class License;
-
-class Generator
-{
-public:
- Generator();
- ~Generator();
-
- std::string encodeLicenseByVersion(
- const std::string& user,
- const std::string& licenseType,
- size_t numberOfUsers,
- const std::string& version
- );
- std::string encodeLicenseByQuarters(
- const std::string& user,
- const std::string& licenseType,
- size_t numberOfUsers,
- size_t quarters
- );
- std::string encodeLicenseByDays(
- const std::string& user,
- const std::string& licenseType,
- size_t numberOfUsers,
- size_t days
- );
-
- void printLicenseAndWriteItToFile();
- bool verifyLicense(const std::string& filename = "license.txt");
- void generateKeys();
- void writeKeysToFiles();
- void setCustomPrivateKeyFile(const std::string& file);
- void setCustomPublicKeyFile(const std::string& file);
-
- std::string getPublicKeyPEMFileAsString();
- std::string getPrivateKeyPEMFileAsString();
- bool loadPrivateKeyFromFile();
- bool loadPrivateKeyFromString(const std::string& key);
-
- Botan::RSA_PrivateKey* getPrivateKey() const;
- void createLicense(
- const std::string& user,
- const std::string& type,
- const std::string& expiration,
- bool expiresAtDate,
- size_t numberOfUsers
- );
-
- std::string getExpireVersion(int quarters);
- void setVersionLine(int year, int minorVersion);
-private:
- int mapMonthToVersion(int month);
- std::string getPrivateKeyFilename();
- std::string getPublicKeyFilename();
-
- //Botan
- Botan::AutoSeeded_RNG m_rng;
-
- std::string m_privateKeyFile;
- std::string m_publicKeyFile;
- std::unique_ptr m_license;
- std::unique_ptr m_privateKey;
-
-};
-
-#endif // KEYGEN_H
diff --git a/src/license_generator/LicenseGenerator.cpp b/src/license_generator/LicenseGenerator.cpp
new file mode 100644
index 00000000..6cf72433
--- /dev/null
+++ b/src/license_generator/LicenseGenerator.cpp
@@ -0,0 +1,243 @@
+#include "LicenseGenerator.h"
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "Version.h"
+
+const char PRIVATE_KEY_PASSWORD[] = "BA#jk5vbklAiKL9K3k$";
+
+LicenseGenerator::LicenseGenerator()
+{
+}
+
+LicenseGenerator::~LicenseGenerator()
+{
+}
+
+void LicenseGenerator::generatePrivateKey()
+{
+ m_privateKey = std::make_unique(m_rng, 2048);
+}
+
+std::unique_ptr LicenseGenerator::createLicenseByVersion(
+ const std::string& user,
+ const std::string& licenseType,
+ size_t numberOfUsers,
+ const std::string& version
+){
+ if (version.empty())
+ {
+ std::cout << "No version given" << std::endl;
+ return nullptr;
+ }
+
+ Version tempVersion = Version::fromString(version);
+ if (tempVersion.isValid())
+ {
+ return createLicense(user, licenseType, numberOfUsers, tempVersion.toShortString(), LicenseConstants::VALID_UNLIMITED);
+ }
+
+ return nullptr;
+}
+
+std::unique_ptr LicenseGenerator::createLicenseByQuarters(
+ const std::string& user,
+ const std::string& type,
+ size_t numberOfUsers,
+ size_t quarters
+){
+ boost::gregorian::date today = boost::gregorian::day_clock::local_day();
+ int quarter = (today.month().as_number() - 1) / 3 + 1;
+ Version version(today.year(), quarter);
+ version += quarters;
+
+ return createLicenseByVersion(user, type, numberOfUsers, version.toShortString());
+}
+
+std::unique_ptr LicenseGenerator::createLicenseByDays(
+ const std::string& user,
+ const std::string& type,
+ size_t numberOfUsers,
+ size_t days
+){
+ boost::gregorian::date today = boost::gregorian::day_clock::local_day();
+ boost::gregorian::days daysToTry(days);
+ boost::gregorian::date expireDate = today + daysToTry;
+
+ return createLicense(
+ user,
+ (type.size() ? type : LicenseConstants::TEST_LICENSE), numberOfUsers,
+ LicenseConstants::VALID_UNLIMITED,
+ boost::gregorian::to_simple_string(expireDate)
+ );
+}
+
+std::unique_ptr LicenseGenerator::createLicenseLifelong(
+ const std::string& user,
+ const std::string& type,
+ size_t numberOfUsers
+){
+ if (numberOfUsers == 0)
+ {
+ std::cout << "No user count given" << std::endl;
+ return nullptr;
+ }
+
+ return createLicense(user, type, numberOfUsers, LicenseConstants::VALID_UNLIMITED, LicenseConstants::VALID_UNLIMITED);
+}
+
+std::string LicenseGenerator::getPublicKeyPEMFileAsString()
+{
+ if (!m_privateKey)
+ {
+ std::cout << "No private key loaded" << std::endl;
+ return "";
+ }
+
+ return Botan::X509::PEM_encode(*m_privateKey);
+}
+
+std::string LicenseGenerator::getPrivateKeyPEMFileAsString()
+{
+ if (!m_privateKey)
+ {
+ std::cout << "No private key loaded" << std::endl;
+ return "";
+ }
+
+ return Botan::PKCS8::PEM_encode(*m_privateKey, m_rng, PRIVATE_KEY_PASSWORD);
+}
+
+void LicenseGenerator::writeKeysToFiles(const std::string& publicKeyFilename, const std::string& privateKeyFilename)
+{
+ if (publicKeyFilename.size() <= 0)
+ {
+ std::cout << "Public key file path is empty" << std::endl;
+ return;
+ }
+
+ if (privateKeyFilename.size() <= 0)
+ {
+ std::cout << "Private key file path is empty" << std::endl;
+ return;
+ }
+
+ std::cout << "public key filename: " << publicKeyFilename << std::endl;
+ std::ofstream pub(publicKeyFilename);
+ pub << getPublicKeyPEMFileAsString();
+ pub.close();
+ std::cout << "public key created" << std::endl;
+
+ std::cout << "private key filename: " << privateKeyFilename << std::endl;
+ std::ofstream priv(privateKeyFilename);
+ priv << getPrivateKeyPEMFileAsString();
+ priv.close();
+ std::cout << "private key created" << std::endl;
+}
+
+bool LicenseGenerator::loadPrivateKeyFromFile(const std::string& file)
+{
+ if (!boost::filesystem::exists(file))
+ {
+ std::cout << "Private key not found: " << file << std::endl;
+ return false;
+ }
+
+ return createPrivateKey(dynamic_cast(Botan::PKCS8::load_key(file, m_rng, PRIVATE_KEY_PASSWORD)));
+}
+
+bool LicenseGenerator::loadPrivateKeyFromString(const std::string& key)
+{
+ if (key.empty())
+ {
+ std::cout << "No key string given" << std::endl;
+ return false;
+ }
+
+ Botan::DataSource_Memory in(key);
+ return createPrivateKey(dynamic_cast(Botan::PKCS8::load_key(in, m_rng, PRIVATE_KEY_PASSWORD)));
+}
+
+Botan::RSA_PrivateKey* LicenseGenerator::getPrivateKey() const
+{
+ return m_privateKey.get();
+}
+
+bool LicenseGenerator::createPrivateKey(Botan::RSA_PrivateKey* rsaPrivateKey)
+{
+ if (!rsaPrivateKey)
+ {
+ std::cout << "The key is not a RSA key" << std::endl;
+ return false;
+ }
+
+ m_privateKey = std::unique_ptr(rsaPrivateKey);
+ return true;
+}
+
+std::unique_ptr LicenseGenerator::createLicense(
+ const std::string& user,
+ const std::string& type,
+ size_t numberOfUsers,
+ const std::string& expirationVersion,
+ const std::string& expirationDate
+){
+ if (user.empty())
+ {
+ std::cout << "No user given" << std::endl;
+ return nullptr;
+ }
+
+ if (type.empty())
+ {
+ std::cout << "No license type given" << std::endl;
+ return nullptr;
+ }
+
+ if (expirationVersion.empty())
+ {
+ std::cout << "No expiration version given" << std::endl;
+ return nullptr;
+ }
+
+ if (expirationDate.empty())
+ {
+ std::cout << "No expiration date given" << std::endl;
+ return nullptr;
+ }
+
+ std::unique_ptr license = std::make_unique();
+ license->setMessage(user, type, numberOfUsers, expirationVersion, expirationDate);
+
+ Botan::AutoSeeded_RNG rng;
+
+ // encode message
+ const std::string emsa = "EMSA4(SHA-256)";
+ Botan::PK_Signer signer(*(m_privateKey.get()), rng, emsa);
+ Botan::DataSource_Memory in(license->getMessage(false));
+
+ Botan::byte buffer[4096] = {0};
+ while (size_t got = in.read(buffer, sizeof(buffer)))
+ {
+ signer.update(buffer, got);
+ }
+
+ const std::string signature = Botan::base64_encode(signer.signature(rng));
+ license->setSignature(signature);
+
+ return license;
+}
diff --git a/src/license_generator/LicenseGenerator.h b/src/license_generator/LicenseGenerator.h
new file mode 100644
index 00000000..eded7f48
--- /dev/null
+++ b/src/license_generator/LicenseGenerator.h
@@ -0,0 +1,78 @@
+#ifndef LICENSE_GENERATOR_H
+#define LICENSE_GENERATOR_H
+
+#include
+#include
+
+#include
+
+#include "License.h"
+
+namespace Botan
+{
+ class RSA_PrivateKey;
+}
+
+class License;
+
+class LicenseGenerator
+{
+public:
+ LicenseGenerator();
+ ~LicenseGenerator();
+
+ void generatePrivateKey();
+ bool loadPrivateKeyFromFile(const std::string& file);
+ bool loadPrivateKeyFromString(const std::string& key);
+
+ Botan::RSA_PrivateKey* getPrivateKey() const;
+
+ std::string getPublicKeyPEMFileAsString();
+ std::string getPrivateKeyPEMFileAsString();
+
+ void writeKeysToFiles(const std::string& publicKeyFilename, const std::string& privateKeyFilename);
+
+ std::unique_ptr createLicenseByVersion(
+ const std::string& user,
+ const std::string& type,
+ size_t numberOfUsers,
+ const std::string& version
+ );
+
+ std::unique_ptr createLicenseByQuarters(
+ const std::string& user,
+ const std::string& type,
+ size_t numberOfUsers,
+ size_t quarters
+ );
+
+ std::unique_ptr createLicenseByDays(
+ const std::string& user,
+ const std::string& type,
+ size_t numberOfUsers,
+ size_t days
+ );
+
+ std::unique_ptr createLicenseLifelong(
+ const std::string& user,
+ const std::string& type,
+ size_t numberOfUsers
+ );
+
+private:
+ bool createPrivateKey(Botan::RSA_PrivateKey* rsaPrivateKey);
+
+ std::unique_ptr createLicense(
+ const std::string& user,
+ const std::string& type,
+ size_t numberOfUsers,
+ const std::string& expirationVersion,
+ const std::string& expirationDate
+ );
+
+ //Botan
+ Botan::AutoSeeded_RNG m_rng;
+ std::unique_ptr m_privateKey;
+};
+
+#endif // KEYGEN_H
diff --git a/src/license_generator/main.cpp b/src/license_generator/main.cpp
index af6b1cb1..1a30b629 100644
--- a/src/license_generator/main.cpp
+++ b/src/license_generator/main.cpp
@@ -5,7 +5,8 @@
#include
-#include "Generator.h"
+#include "LicenseChecker.h"
+#include "LicenseGenerator.h"
#include "PrivateKey.h"
#include "PublicKey.h"
@@ -17,9 +18,9 @@ bool process_command_line(int argc, char** argv)
{
std::string user;
std::string version;
- std::string privateKeyFile;
- std::string publicKeyFile;
- std::string licenseFile = "";
+ std::string privateKeyFile = "private-sourcetrail.pem";
+ std::string publicKeyFile = "public-sourcetrail.pem";
+ std::string licenseFile = "license.txt";
std::string type = "";
int quarters = 4;
int days = 0;
@@ -31,32 +32,28 @@ bool process_command_line(int argc, char** argv)
("generate,g", po::value(&user), "Generate a License, USERNAME as value")
("check,c", "Validate a License");
- po::options_description keygen_description("Options Keygeneration");
+ po::options_description keygen_description("Options License Generation");
keygen_description.add_options()
("version,v", po::value(&version), "Versionnumber (in format 20xx.x) until Sourcetrail valid")
("quarters,q", po::value(&quarters), "Number of quarters Sourcetrail is valid from now")
("users,u", po::value(&numberOfUsers), "Number of users")
("licenseType,t", po::value(&type), "License Type of ")
- ("expiration,e", po::value(&days), "Valid for days");
+ ("expiration,e", po::value(&days), "Valid for days")
+ ("lifelong,l", "Valid perpetually");
- po::options_description hidden_description("Hidden Options");
- hidden_description.add_options()
+ po::options_description advanced_description("Advanced Options");
+ advanced_description.add_options()
("public-file", po::value(&publicKeyFile), "Custom public key file")
("private-file", po::value(&privateKeyFile), "Custom private key file")
- ("license-file", po::value(&licenseFile), "Custom license")
- ("hidden", "Print this help message");
+ ("license-file", po::value(&licenseFile), "Custom license (default: license.txt)");
+
po::options_description desc("Sourcetrail Generator");
desc.add_options()
("help,h", "Print this help message");
- desc.add(modes_description).add(keygen_description);
-
- po::options_description allDescriptions("Sourcetrail Generator");
- allDescriptions.add_options();
- allDescriptions.add(modes_description).add(keygen_description).add(hidden_description);
+ desc.add(modes_description).add(keygen_description).add(advanced_description);
po::variables_map vm;
-
po::store(po::parse_command_line(argc,argv,desc), vm);
po::notify(vm);
@@ -64,7 +61,7 @@ bool process_command_line(int argc, char** argv)
if (vm.count("help"))
{
std::cout << desc << std::endl;
- return 1;
+ return true;
}
// no mode chosen -> display help
@@ -73,42 +70,21 @@ bool process_command_line(int argc, char** argv)
std::cout << "*****************************\nNo mode chosen, display help: "
<< "\n*****************************\n\n" << desc << std::endl;
- return 1;
+ return false;
}
-
- if (vm.count("hidden"))
- {
- std::cout << allDescriptions << std::endl;
- return 1;
- }
-
- Generator keygen;
-
- // make sure there are no negative amount of users
- if (vm.count("users"))
- {
- if (numberOfUsers < 0)
- {
- std::cout << "Invalid amount of users. (Must be > 0)" << std::endl;
- return false;
- }
- }
+ LicenseGenerator keygen;
if (vm.count("key"))
{
- keygen.generateKeys();
- keygen.writeKeysToFiles();
- }
-
- if (vm.count("public-file"))
- {
- keygen.setCustomPublicKeyFile(publicKeyFile);
+ keygen.generatePrivateKey();
+ keygen.writeKeysToFiles(publicKeyFile, privateKeyFile);
+ return true;
}
if (vm.count("private-file"))
{
- keygen.setCustomPrivateKeyFile(privateKeyFile);
+ keygen.loadPrivateKeyFromFile(privateKeyFile);
}
else
{
@@ -117,30 +93,71 @@ bool process_command_line(int argc, char** argv)
if (vm.count("generate"))
{
- if (days > 0)
+ // make sure there is no negative amount of users
+ if (vm.count("users"))
{
- keygen.encodeLicenseByDays(user, type, numberOfUsers, days);
+ if (numberOfUsers < 0)
+ {
+ std::cout << "Invalid amount of users. (Must be > 0)" << std::endl;
+ return false;
+ }
+ }
+
+ std::unique_ptr license;
+
+ if (vm.count("lifelong"))
+ {
+ license = keygen.createLicenseLifelong(user, type, numberOfUsers);
+ }
+ else if (vm.count("expiration"))
+ {
+ license = keygen.createLicenseByDays(user, type, numberOfUsers, days);
}
else if (!version.empty())
{
- keygen.encodeLicenseByVersion(user, type, numberOfUsers, version);
+ license = keygen.createLicenseByVersion(user, type, numberOfUsers, version);
}
else
{
- keygen.encodeLicenseByQuarters(user, type, numberOfUsers, quarters);
+ license = keygen.createLicenseByQuarters(user, type, numberOfUsers, quarters);
+ }
+
+ if (license)
+ {
+ license->print();
+ license->writeToFile(licenseFile);
}
- keygen.printLicenseAndWriteItToFile();
}
if (vm.count("check"))
{
- if (keygen.verifyLicense())
+ if (vm.count("public-file"))
+ {
+ LicenseChecker::loadPublicKeyFromFile(publicKeyFile);
+ }
+ else
+ {
+ LicenseChecker::loadPublicKey();
+ }
+
+ License license;
+ LicenseChecker::LicenseState state = LicenseChecker::LicenseState::EMPTY;
+ if (license.loadFromFile(licenseFile))
+ {
+ state = LicenseChecker::checkLicense(license);
+ }
+ else
+ {
+ state = LicenseChecker::LicenseState::MALFORMED;
+ }
+
+ if (state == LicenseChecker::LicenseState::VALID)
{
std::cout << "License valid" << std::endl;
}
else
{
- std::cout << "License not valid" << std::endl;
+ std::cout << LicenseChecker::getLicenseErrorForState(state) << std::endl;
}
}
}
@@ -153,7 +170,8 @@ bool process_command_line(int argc, char** argv)
return true;
}
-int main(int argc, char *argv[]) {
+int main(int argc, char *argv[])
+{
process_command_line(argc, argv);
return 0;
diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt
index 70edba8c..518f3b7c 100644
--- a/src/test/CMakeLists.txt
+++ b/src/test/CMakeLists.txt
@@ -18,8 +18,9 @@ add_files(
FilePathFilterTestSuite.h
FilePathTestSuite.h
FileSystemTestSuite.h
- GeneratorTestSuite.h
GraphTestSuite.h
+ LicenseCheckerTestSuite.h
+ LicenseGeneratorTestSuite.h
LogManagerTestSuite.h
LowMemoryStringMapTestSuite.h
MatrixBaseTestSuite.h
diff --git a/src/test/LicenseCheckerTestSuite.h b/src/test/LicenseCheckerTestSuite.h
new file mode 100644
index 00000000..efdb5fa8
--- /dev/null
+++ b/src/test/LicenseCheckerTestSuite.h
@@ -0,0 +1,634 @@
+#include
+
+#include "License.h"
+#include "LicenseChecker.h"
+#include "Version.h"
+
+class LicenseCheckerTestSuite : public CxxTest::TestSuite
+{
+public:
+
+ void test_check_empty_license()
+ {
+ LicenseChecker::loadPublicKey();
+ LicenseChecker::LicenseState state = LicenseChecker::checkLicenseString("");
+ TS_ASSERT_EQUALS(state, LicenseChecker::LicenseState::EMPTY);
+ }
+
+ void test_check_malformed_license()
+ {
+ LicenseChecker::loadPublicKey();
+ LicenseChecker::LicenseState state = LicenseChecker::checkLicenseString(
+R"(-----BEGIN LICENSE-----
+Product: Sourcetrail
+License holder: Jane Doe
+License type: Commercial License
+Licensed number of users: 3
+Licensed usage period: until 2021-Dec-10
+-
+$9$AQAKpvMMWlY7aWaMQY/AScwUo/nhqFdj+skS46v+7QHoj7X6qS+W
+IErtt71WhVoqM8eki8IS+BDuO+TyLCAKhpNYQhvgykgfAx16T3ypD4A
+4/DKGZbm/ZzZ3J5KD30Ko7pZfsgCnBMZu+VHSkoxtntDCzmhNySF4yo
+fiDVhR9NYeWjgd0jtj1+dpBfjmQeXLgf4DqtYvgW446pUfEIIur174y
+ffYziDA9VhIpgx2ZEYfFFXWNY+0esAkN389UxZ5UgQcs0LHTdEBphYO
+oZJKdZdPbF+zSPwUeRej9SkCOpionrJ9lvVMo3p2pro0boeM4/bAs/p
+MyEDaYFJdoazS3T8CXB0oPdEoyvYR6kOBZCw9YeW1Ud0azN8BeMx68c
+gwitGhNQeI9A==
+-----END LICENSE-----)"
+ );
+
+ TS_ASSERT_EQUALS(state, LicenseChecker::LicenseState::MALFORMED);
+ }
+
+ void test_check_invalid_license()
+ {
+ LicenseChecker::loadPublicKey();
+ LicenseChecker::LicenseState state = LicenseChecker::checkLicenseString(
+R"(-----BEGIN LICENSE-----
+Product: Sourcetrail
+License holder: Jane Doe
+License type: Commercial License
+Licensed number of users: 3
+Licensed product version: unlimited
+Licensed usage period: until 2021-Dec-10
+-
+$9$AQAKpvMMWlY7aWaMQY/AScwUo/nhqFdj+skS46v+7QHoj7X6qS+W
+IErtt71WhVoqM8eki8IS+BDuO+TyLCAKhpNYQhvgykgfAx16T3ypD4A
+4/DKGZbm/ZzZ3J5KD30Ko7pZfsgCnBMZu+VHSkoxtntDCzmhNySF4yo
+fiDVhR9NYeWjgd0jtj1+dpBfjmQeXLgf4DqtYvgW446pUfEIIur174y
+ffYziDA9VhIpgx2ZEYfFFXWNY+0esAkN389UxZ5UgQcs0LHTdEBphYO
+oZJKdZdPbF+zSPwUeRej9SkCOpionrJ9lvVMo3p2pro0boeM4/bAs/p
+MyEDaYFJdoazS3T8CXB0oPdEoyvYR6kOBZCw9YeW1Ud0azN8BeMx68C
+gwitGhNQeI9A==
+-----END LICENSE-----)"
+ );
+
+ TS_ASSERT_EQUALS(state, LicenseChecker::LicenseState::INVALID);
+ }
+
+ void test_check_license_without_start_end()
+ {
+ LicenseChecker::loadPublicKey();
+ LicenseChecker::LicenseState state = LicenseChecker::checkLicenseString(
+R"(
+Product: Sourcetrail
+License holder: Jane Doe
+License type: Commercial License
+Licensed number of users: 3
+Licensed product version: unlimited
+Licensed usage period: until 2021-Dec-10
+-
+$9$AQAKpvMMWlY7aWaMQY/AScwUo/nhqFdj+skS46v+7QHoj7X6qS+W
+IErtt71WhVoqM8eki8IS+BDuO+TyLCAKhpNYQhvgykgfAx16T3ypD4A
+4/DKGZbm/ZzZ3J5KD30Ko7pZfsgCnBMZu+VHSkoxtntDCzmhNySF4yo
+fiDVhR9NYeWjgd0jtj1+dpBfjmQeXLgf4DqtYvgW446pUfEIIur174y
+ffYziDA9VhIpgx2ZEYfFFXWNY+0esAkN389UxZ5UgQcs0LHTdEBphYO
+oZJKdZdPbF+zSPwUeRej9SkCOpionrJ9lvVMo3p2pro0boeM4/bAs/p
+MyEDaYFJdoazS3T8CXB0oPdEoyvYR6kOBZCw9YeW1Ud0azN8BeMx68c
+gwitGhNQeI9A==
+)"
+ );
+
+ TS_ASSERT_EQUALS(state, LicenseChecker::LicenseState::VALID);
+ }
+
+ void test_license_encoding()
+ {
+ LicenseChecker::loadPublicKey();
+ LicenseChecker::setCurrentLicenseString(
+R"(-----BEGIN LICENSE-----
+Product: Sourcetrail
+License holder: Jane Doe
+License type: Commercial License
+Licensed number of users: 3
+Licensed product version: unlimited
+Licensed usage period: until 2021-Dec-10
+-
+$9$AQAKpvMMWlY7aWaMQY/AScwUo/nhqFdj+skS46v+7QHoj7X6qS+W
+IErtt71WhVoqM8eki8IS+BDuO+TyLCAKhpNYQhvgykgfAx16T3ypD4A
+4/DKGZbm/ZzZ3J5KD30Ko7pZfsgCnBMZu+VHSkoxtntDCzmhNySF4yo
+fiDVhR9NYeWjgd0jtj1+dpBfjmQeXLgf4DqtYvgW446pUfEIIur174y
+ffYziDA9VhIpgx2ZEYfFFXWNY+0esAkN389UxZ5UgQcs0LHTdEBphYO
+oZJKdZdPbF+zSPwUeRej9SkCOpionrJ9lvVMo3p2pro0boeM4/bAs/p
+MyEDaYFJdoazS3T8CXB0oPdEoyvYR6kOBZCw9YeW1Ud0azN8BeMx68c
+gwitGhNQeI9A==
+-----END LICENSE-----)"
+ );
+
+ LicenseChecker::LicenseState state = LicenseChecker::checkCurrentLicense();
+ TS_ASSERT_EQUALS(state, LicenseChecker::LicenseState::VALID);
+
+ LicenseChecker::setEncodeKey("test_key");
+ std::string encodedLicenseString = LicenseChecker::getCurrentLicenseStringEncoded();
+
+ LicenseChecker::setEncodeKey("test_key_new");
+ state = LicenseChecker::setCurrentLicenseStringEncoded(encodedLicenseString);
+
+ TS_ASSERT_EQUALS(state, LicenseChecker::LicenseState::MALFORMED);
+
+ LicenseChecker::setEncodeKey("test_key");
+ state = LicenseChecker::setCurrentLicenseStringEncoded(encodedLicenseString);
+
+ TS_ASSERT_EQUALS(state, LicenseChecker::LicenseState::VALID);
+ }
+
+ void test_check_version_license()
+ {
+ License license;
+ bool ok = license.loadFromString(
+R"(-----BEGIN LICENSE-----
+Product: Sourcetrail
+License holder: Jane Doe
+License type: Commercial License
+Licensed number of users: 1
+Licensed product version: up to 2020.2
+Licensed usage period: unlimited
+-
+$9$AQAKrGHpbkd9I+FVXZ8YtKK7rJePuPqJcWwaLoNYze14fRNiIBQV
+QcelksnNcsztdUVCSp1MPkEbuWHkhR74m5qJ3wECnMekfVmP3GhbvwL
+cqAEyrpR4PrZCRM2oxEgcRVk6QrPM9pHYPaPHe8sV74odOGQtHUrEW6
+N8ZNL0NMLzSxurD/hXdDLdgxya9UptYIJ6c2Bbu33xJ87Ofs07pptc0
+4VzBXJYG5iKIbmQAnrU6KOBL5iIZ11/sM8VbkTw+nSySI4yr3/f8BWe
+7PhDAmhvDTX9aMMfpaXXeL3PyC/023FwyAqimB1vzoo28Pm1p1tN9mF
+l7Ci+UazTnVY34DLVoXYUaDVlt8t8VYq05Z7f6sfcGtqpthuevGatM0
+e6G8hqqTc+CQ==
+-----END LICENSE-----)"
+ );
+
+ Version version = Version::getApplicationVersion();
+ Version::setApplicationVersion(Version(2020, 2, 11, "asdfasdf"));
+
+ TS_ASSERT(ok);
+ TS_ASSERT_EQUALS(license.getUser(), "Jane Doe");
+ TS_ASSERT_EQUALS(license.getType(), "Commercial License");
+ TS_ASSERT_EQUALS(license.getNumberOfUsers(), 1);
+ TS_ASSERT_EQUALS(license.getTimeLeft(), -2);
+ TS_ASSERT(license.isComplete());
+ TS_ASSERT(!license.isEmpty());
+ TS_ASSERT(!license.isExpired());
+ TS_ASSERT(!license.isTestLicense());
+
+ LicenseChecker::loadPublicKey();
+ TS_ASSERT_EQUALS(LicenseChecker::checkLicense(license), LicenseChecker::LicenseState::VALID);
+
+ Version::setApplicationVersion(version);
+ }
+
+ void test_check_version_license_expired()
+ {
+ License license;
+ bool ok = license.loadFromString(
+R"(-----BEGIN LICENSE-----
+Product: Sourcetrail
+License holder: Jane Doe
+License type: Commercial License
+Licensed number of users: 1
+Licensed product version: up to 2018.2
+Licensed usage period: unlimited
+-
+$9$AQAKshj0tavIV6xR/dL9nXxaxib80g8Kxho0CGpvdypb4xujP5nw
+mIQi3TiVrBTCszJLONCdnhyzotj1R370JPHWa/FFbGqABhexI5PGdIb
+3Pa1EqQP9otCJZvDhQTxkm2Ev3zFEgDsA8njBQjr09Blcbt6F9F5zpJ
+Ld75PRPLgvVmrxJfwOOg0tYQ/WrKzmm68gcF7XUHS1N7QDSrxjkqihu
+xvHd6PoQSmX8pbNpYbkNF6N1T7rR5B8o7BnCc1PEw13J6k8CsomyQ4Q
+qg2qAz0IOXk+r7ZagNvR9XedqcytIu6e0u48ujpEUv+1TSj7VBrOq1a
+5La45aDoFn2XgdX/mlJh4RPeTEtg6u06PHf4pHFWiOXyKcvvAWuy7GT
+YeDldWiy3iwA==
+-----END LICENSE-----)"
+ );
+
+ Version version = Version::getApplicationVersion();
+ Version::setApplicationVersion(Version(2018, 3, 11, "asdfasdf"));
+
+ TS_ASSERT(ok);
+ TS_ASSERT_EQUALS(license.getUser(), "Jane Doe");
+ TS_ASSERT_EQUALS(license.getType(), "Commercial License");
+ TS_ASSERT_EQUALS(license.getNumberOfUsers(), 1);
+ TS_ASSERT_EQUALS(license.getTimeLeft(), -2);
+ TS_ASSERT(license.isComplete());
+ TS_ASSERT(!license.isEmpty());
+ TS_ASSERT(license.isExpired());
+ TS_ASSERT(!license.isTestLicense());
+
+ LicenseChecker::loadPublicKey();
+ TS_ASSERT_EQUALS(LicenseChecker::checkLicense(license), LicenseChecker::LicenseState::EXPIRED);
+
+ Version::setApplicationVersion(version);
+ }
+
+ void test_check_period_license()
+ {
+ License license;
+ bool ok = license.loadFromString(
+R"(-----BEGIN LICENSE-----
+Product: Sourcetrail
+License holder: Jane Doe
+License type: Commercial License
+Licensed number of users: 3
+Licensed product version: unlimited
+Licensed usage period: until 2021-Dec-10
+-
+$9$AQAKpvMMWlY7aWaMQY/AScwUo/nhqFdj+skS46v+7QHoj7X6qS+W
+IErtt71WhVoqM8eki8IS+BDuO+TyLCAKhpNYQhvgykgfAx16T3ypD4A
+4/DKGZbm/ZzZ3J5KD30Ko7pZfsgCnBMZu+VHSkoxtntDCzmhNySF4yo
+fiDVhR9NYeWjgd0jtj1+dpBfjmQeXLgf4DqtYvgW446pUfEIIur174y
+ffYziDA9VhIpgx2ZEYfFFXWNY+0esAkN389UxZ5UgQcs0LHTdEBphYO
+oZJKdZdPbF+zSPwUeRej9SkCOpionrJ9lvVMo3p2pro0boeM4/bAs/p
+MyEDaYFJdoazS3T8CXB0oPdEoyvYR6kOBZCw9YeW1Ud0azN8BeMx68c
+gwitGhNQeI9A==
+-----END LICENSE-----)"
+ );
+
+ TS_ASSERT(ok);
+ TS_ASSERT_EQUALS(license.getUser(), "Jane Doe");
+ TS_ASSERT_EQUALS(license.getType(), "Commercial License");
+ TS_ASSERT_EQUALS(license.getNumberOfUsers(), 3);
+ TS_ASSERT(license.getTimeLeft() >= 0);
+ TS_ASSERT(license.isComplete());
+ TS_ASSERT(!license.isEmpty());
+ TS_ASSERT(!license.isExpired());
+ TS_ASSERT(!license.isTestLicense());
+
+ LicenseChecker::loadPublicKey();
+ TS_ASSERT_EQUALS(LicenseChecker::checkLicense(license), LicenseChecker::LicenseState::VALID);
+ }
+
+ void test_check_period_license_expired()
+ {
+ License license;
+ bool ok = license.loadFromString(
+R"(-----BEGIN LICENSE-----
+Product: Sourcetrail
+License holder: Jane Doe
+License type: Commercial License
+Licensed number of users: 3
+Licensed product version: unlimited
+Licensed usage period: until 2018-Dec-06
+-
+$9$AQAKkgTBy1koMv8CusfbUVWyMQtbTc67dSMTv+96bnVWSQdc/Bti
+O8300TO2SWEVuyMo/BQkmXTnEFWLtwnAPqtAJXLR4oDTqlHUNs8Ur5q
+iL6dMVsiyp41EHrzuof1/u+pgX03kCyIgD6TAn42En3+2pgo1zhDxnx
+vaBxQTUcUW8+kJyNdSlJ6E2DgwGX2uXmf8MF8nsJtwHhOe/3qyV6fm0
+PtXmWwjesNX7qGA8L+pcZKsB6AdC4dEJ71iFr8u/O1i8ab0v5xorJM3
+zJ40jE0kcucpag5sW43ch0eX6PntXSwXuFfaQ7gTUH6qYTvxqIFUZGW
+r0TrPuhiyxHS80ki5QApv9AShXlt3LRM41SJSCuv71Z30kGIVV6Itoo
++rtjllrh9TBA==
+-----END LICENSE-----)"
+ );
+
+ TS_ASSERT(ok);
+ TS_ASSERT_EQUALS(license.getUser(), "Jane Doe");
+ TS_ASSERT_EQUALS(license.getType(), "Commercial License");
+ TS_ASSERT_EQUALS(license.getNumberOfUsers(), 3);
+ TS_ASSERT_EQUALS(license.getTimeLeft(), -1);
+ TS_ASSERT(license.isComplete());
+ TS_ASSERT(!license.isEmpty());
+ TS_ASSERT(license.isExpired());
+ TS_ASSERT(!license.isTestLicense());
+
+ LicenseChecker::loadPublicKey();
+ TS_ASSERT_EQUALS(LicenseChecker::checkLicense(license), LicenseChecker::LicenseState::EXPIRED);
+ }
+
+ void test_check_site_license()
+ {
+ License license;
+ bool ok = license.loadFromString(
+R"(-----BEGIN LICENSE-----
+Product: Sourcetrail
+License holder: Jane Doe
+License type: Commercial License
+Licensed number of users: unlimited
+Licensed product version: unlimited
+Licensed usage period: until 2021-Dec-10
+-
+$9$AQAKM0lWahp0xKiqVObgsjtpg9LNh+knuPSDbbv/6LuJqbZYA2F2
+ibdICkHLfDTIiUjqXdmLbNWbavWwcrtOnzw7zxExIyCcJPXrQxUjmRU
+kvVe+mPlN+4Re1jFBmCY18X13fb9JSShOjWGEnpCR/o6Fq1EKoOoYg1
+NyWoVDy+Jv/Tr0Zr1/xFyhQJMw3dr0LiCrmYG0+J9P4lndI7MI4QG3z
+0e625imrkJVDJsRUk3V9YXu8XxJTpSfc8tZjolzxCpaAKNzzCQeghdh
+hwAEZEqUd3+ULN6lY36laCzRSMOts6506wMMhv4wzT65h8RRrrgJJjw
+lnOALOwf+YcHvMpHWBBL18utvvxn1dWUdywBXPfmJnncglP7Cg+/B6q
+gPxec/V8S5mA==
+-----END LICENSE-----)"
+ );
+
+ TS_ASSERT(ok);
+ TS_ASSERT_EQUALS(license.getUser(), "Jane Doe");
+ TS_ASSERT_EQUALS(license.getType(), "Commercial License");
+ TS_ASSERT_EQUALS(license.getNumberOfUsers(), 0);
+ TS_ASSERT(license.getTimeLeft() >= 0);
+ TS_ASSERT(license.isComplete());
+ TS_ASSERT(!license.isEmpty());
+ TS_ASSERT(!license.isExpired());
+ TS_ASSERT(!license.isTestLicense());
+
+ LicenseChecker::loadPublicKey();
+ TS_ASSERT_EQUALS(LicenseChecker::checkLicense(license), LicenseChecker::LicenseState::VALID);
+ }
+
+ void test_check_site_license_expired()
+ {
+ License license;
+ bool ok = license.loadFromString(
+R"(-----BEGIN LICENSE-----
+Product: Sourcetrail
+License holder: Jane Doe
+License type: Commercial License
+Licensed number of users: unlimited
+Licensed product version: unlimited
+Licensed usage period: until 2018-Dec-08
+-
+$9$AQAKi2K2OESpqYwzOE6EPg5ltiYYNV3FYzGT9O/mf8fp8+ovGL5T
+aJjHkXuWYsZ71yG4SH7DKrtSKc3nSHT6eBKpxkGeQ/50KMIqbFHUNWm
+qsv7mzFeKeoA7e9Hf2X/RfWqBmHTV8eIhaE4qqMKF5DY+fG9Y1qlHEs
+oeKJCM6BaxYiPZjG4sMKG2K/6AkT4TbNaHjrBktlE1l4ad8mW1xBXn5
+p6ph0waObobOioNZINvLuRrIModAnfjCFVdKtL+HzM8Kg/2Tx7ZPCQV
+4Tvj6Jm61OiXAdgZcIoL1DYsZWqIb3HFIJQw7Q+IGsKFgh64oNwh/WP
+LZi4XroeDeOJnhX5+sfr0WZoV2BKCsNCsvKNHTtEG9ZGtKSgp8ktgBt
+XCElsg55RjkQ==
+-----END LICENSE-----)"
+ );
+
+ TS_ASSERT(ok);
+ TS_ASSERT_EQUALS(license.getUser(), "Jane Doe");
+ TS_ASSERT_EQUALS(license.getType(), "Commercial License");
+ TS_ASSERT_EQUALS(license.getNumberOfUsers(), 0);
+ TS_ASSERT_EQUALS(license.getTimeLeft(), -1);
+ TS_ASSERT(license.isComplete());
+ TS_ASSERT(!license.isEmpty());
+ TS_ASSERT(license.isExpired());
+ TS_ASSERT(!license.isTestLicense());
+
+ LicenseChecker::loadPublicKey();
+ TS_ASSERT_EQUALS(LicenseChecker::checkLicense(license), LicenseChecker::LicenseState::EXPIRED);
+ }
+
+ void test_check_test_license()
+ {
+ License license;
+ bool ok = license.loadFromString(
+R"(-----BEGIN LICENSE-----
+Product: Sourcetrail
+License holder: Jane Doe
+License type: Test License
+Licensed number of users: unlimited
+Licensed product version: unlimited
+Licensed usage period: until 2021-Dec-10
+-
+$9$AQAKrvzvSMvN038BfcgVNT8rN6/X4pFbYKpU0gMSeH62+Vsd55MC
+E6rIwc+vMlHlLzHZsn6+YpSsPX2Hs31JUpkRTAb2X2ln0SZU2mZUL/V
+SD4trO/jCUoTaC7FbaXD6F1A8DWuJos706g/MaNWyXc0tUnd3N6HSnZ
+UEX0HHQXaKatZh5imexO5NncQtdhObU9PFo0UhXTxQ9wFxrKFzgyIIl
+EQqQq4ExHzMz41wDD/476lf43W8O6tfbSRaO2aSlALy/3IqnrZBjllm
+girrswPR5tAq8JCL8hxenkajWK7plnlg4tUuvpvnj/fif/2Km5v7Xls
++MDZZ7EC7hRX2UUHmIWAnCaiv25k/NHfu1GBQ19mS8mWYnRmxXOccAO
+qCavX9fMG6pQ==
+-----END LICENSE-----)"
+ );
+
+ TS_ASSERT(ok);
+ TS_ASSERT_EQUALS(license.getUser(), "Jane Doe");
+ TS_ASSERT_EQUALS(license.getType(), "Test License");
+ TS_ASSERT_EQUALS(license.getNumberOfUsers(), 0);
+ TS_ASSERT(license.getTimeLeft() >= 0);
+ TS_ASSERT(license.isComplete());
+ TS_ASSERT(!license.isEmpty());
+ TS_ASSERT(!license.isExpired());
+ TS_ASSERT(license.isTestLicense());
+
+ LicenseChecker::loadPublicKey();
+ TS_ASSERT_EQUALS(LicenseChecker::checkLicense(license), LicenseChecker::LicenseState::VALID);
+ }
+
+ void test_check_test_license_expired()
+ {
+ License license;
+ bool ok = license.loadFromString(
+R"(-----BEGIN LICENSE-----
+Product: Sourcetrail
+License holder: Jane Doe
+License type: Test License
+Licensed number of users: unlimited
+Licensed product version: unlimited
+Licensed usage period: until 2018-Dec-06
+-
+$9$AQAKML9uOsAwGbhR/GdF+idZBjBwcvYuNvym5yLvTweDEOs70IHy
+NQBPgvq3TOUPtmKc3DE1lHLB7Fe2/8VNwcg1hkncle9fKh44WGuNIRX
+dFPJ40Hl+be8ekrjyKwz1x9fb85mkzheiDQUEC8QOHUUdJJoETgp3Il
+dcLDe/UL7Sq3/GpPDH+SaThMM5y+3tluf7yO/4qqRuzbV68YW/DTHEL
+47/LvlW1iAypllpeJD7igpCzUEiRYa2m2pSmpOiS0FoXaZ0jhr0LNXm
+C6/zLqHZ4xRnUmhDlmTf1mfybi86xOiPeZFfvSVnv5HPtf5Nsk2wGkW
+pwim1/hpoCxGJ4hiN9a3cbgnjtqG7yTbfMIiBAxM4JcHt2Dzhs3+r6d
+gabQRg1nODDw==
+-----END LICENSE-----)"
+ );
+
+ TS_ASSERT(ok);
+ TS_ASSERT_EQUALS(license.getUser(), "Jane Doe");
+ TS_ASSERT_EQUALS(license.getType(), "Test License");
+ TS_ASSERT_EQUALS(license.getNumberOfUsers(), 0);
+ TS_ASSERT_EQUALS(license.getTimeLeft(), -1);
+ TS_ASSERT(license.isComplete());
+ TS_ASSERT(!license.isEmpty());
+ TS_ASSERT(license.isExpired());
+ TS_ASSERT(license.isTestLicense());
+
+ LicenseChecker::loadPublicKey();
+ TS_ASSERT_EQUALS(LicenseChecker::checkLicense(license), LicenseChecker::LicenseState::EXPIRED);
+ }
+
+ void test_check_lifelong_license()
+ {
+ License license;
+ bool ok = license.loadFromString(
+R"(-----BEGIN LICENSE-----
+Product: Sourcetrail
+License holder: Jane Doe
+License type: Commercial License
+Licensed number of users: 2
+Licensed product version: unlimited
+Licensed usage period: unlimited
+-
+$9$AQAKIZaofFkJU73SLfokexujrBlm792b2tF+oQksC40P+Z8vUtgT
+hesYyYrRxFXK2OALm7zLkdeJYNwC60+oJx0wA19D6PLQo09d5Tf3hHx
+0pkdV0J+2NwidLoJX6ZHWB2KQxg1Vg0yvczZs4uzNLLd6JRdBubN3XF
+0hO9m/sYLMRzeh5sn7WJjV2M/BR1bGmgmY0itW0UXw+hYGZaViiDo1f
+7erXFcZq5TJwhYM447TjoWa+KDjPd/hCohO8SKKtJ33qWWuTfJNPL5q
+7iqyQemOnBOtW+nXHmg/89F+YXoyGeICxinnFs1kmqMey94s/08OUcB
+GSlQ649gX2BuuACmHR/JW/0SY4ik/DgkesVHuRWXD8VTq8cOBMCKjOe
+YHCqvUCFHVMA==
+-----END LICENSE-----)"
+ );
+
+ TS_ASSERT(ok);
+ TS_ASSERT_EQUALS(license.getUser(), "Jane Doe");
+ TS_ASSERT_EQUALS(license.getType(), "Commercial License");
+ TS_ASSERT_EQUALS(license.getNumberOfUsers(), 2);
+ TS_ASSERT_EQUALS(license.getTimeLeft(), -2);
+ TS_ASSERT(license.isComplete());
+ TS_ASSERT(!license.isEmpty());
+ TS_ASSERT(!license.isExpired());
+ TS_ASSERT(!license.isTestLicense());
+
+ LicenseChecker::loadPublicKey();
+ TS_ASSERT_EQUALS(LicenseChecker::checkLicense(license), LicenseChecker::LicenseState::VALID);
+ }
+
+ void test_check_long_name()
+ {
+ License license;
+ bool ok = license.loadFromString(
+R"(-----BEGIN LICENSE-----
+Product: Sourcetrail
+License holder: Janestanasolinaria Doestopolstiminikovasotanibanastovic
+License type: Commercial License
+Licensed number of users: 2
+Licensed product version: up to 2023.4
+Licensed usage period: unlimited
+-
+$9$AQAKD2gin+JhXldRL5AkVpoTgNHibszdfWpKSgm+p5zC5wCYiGWd
+Vtd8nzkj4Gys3liNW5K1Yu/bfgcoOwjBOh6ZpNXCs9MQaNtfHTNeNXA
+6vKwBCyrKruO1Ez1y+63pYN+erVtrxIpy6bTxuSIuD115j++V7sDE6f
+oMCTYVAtMoPBxkIDrMB/dRDVu+ZPffAtPl9qA/1Okl697UpFLIC5kOP
+YoJmSgwXC0k0lOvF7OyzR95oKUjQifdWgnEH5kpPJ3DqcKsAvSh0bQj
+Rmk10RSZo1OmjgYEssKlD04BZMWsgKEeNHVAkovY6mxR4160wOuELxP
+Y8odKqEzRcdV/ZWysqZEGPpdeBIqeBd4ZVgN6kEDZqpGktGZL0LThEB
+Muf9wa0CwXuw==
+-----END LICENSE-----)"
+ );
+
+ TS_ASSERT(ok);
+ TS_ASSERT_EQUALS(license.getUser(), "Janestanasolinaria Doestopolstiminikovasotanibanastovic");
+ TS_ASSERT_EQUALS(license.getType(), "Commercial License");
+ TS_ASSERT_EQUALS(license.getNumberOfUsers(), 2);
+ TS_ASSERT_EQUALS(license.getTimeLeft(), -2);
+ TS_ASSERT(license.isComplete());
+ TS_ASSERT(!license.isEmpty());
+ TS_ASSERT(!license.isExpired());
+ TS_ASSERT(!license.isTestLicense());
+
+ LicenseChecker::loadPublicKey();
+ TS_ASSERT_EQUALS(LicenseChecker::checkLicense(license), LicenseChecker::LicenseState::VALID);
+ }
+
+ void test_check_old_format_license()
+ {
+ License license;
+ bool ok = license.loadFromString(
+R"(-----BEGIN LICENSE-----
+Product: Sourcetrail
+Licensed to: Jane Doe
+License type: Commercial License (5 users)
+Valid up to version: 2020.2
+-
+$9$AQAKDowaE3jU5qows5JQrqt6iEfM+BKO0uCgN8lYCIAy/qUzfDsI
+S8pZMKD9fBNP0QHK1RNAaiwD8qszcnksDHcURUelnCBk2fpAd4YdR2a
+IU6CBwkPWAT92K7KE5OfWV2h2odlSTirPb99WqWYnEngibVeBA4cGZD
+k+fSpsPz3Dwg66dNUKajf+snii5wE9qa/2XYhV3gLm3Utls2jhpom31
+9Ri0uP/5b8Zx8ZWtlT5BDoS8LvVBsOtBe788DSmmF+7hA8xLel+VRvt
+mNzs/MWbKg+m0JrIdwaqhDlx+Fpc+rlhb0uWTJxKO2ruRkLcXkZ4ZbS
+fnOHl2FZZgsRjnT0AbI9hHNf3clXuJsu85ymGa9ZESBvKRmYWvjpdcs
+0yeCOCcxABmw==
+-----END LICENSE-----)"
+ );
+
+ Version version = Version::getApplicationVersion();
+ Version::setApplicationVersion(Version(2019, 1, 11, "asdfasdf"));
+
+ TS_ASSERT(ok);
+ TS_ASSERT_EQUALS(license.getUser(), "Jane Doe");
+ TS_ASSERT_EQUALS(license.getType(), "Commercial License");
+ TS_ASSERT_EQUALS(license.getNumberOfUsers(), 5);
+ TS_ASSERT_EQUALS(license.getTimeLeft(), -2);
+ TS_ASSERT(license.isComplete());
+ TS_ASSERT(!license.isEmpty());
+ TS_ASSERT(!license.isExpired());
+ TS_ASSERT(!license.isTestLicense());
+
+ LicenseChecker::loadPublicKey();
+ TS_ASSERT_EQUALS(LicenseChecker::checkLicense(license), LicenseChecker::LicenseState::VALID);
+
+ Version::setApplicationVersion(version);
+ }
+
+ void test_check_old_format_license_expired()
+ {
+ License license;
+ bool ok = license.loadFromString(
+R"(-----BEGIN LICENSE-----
+Product: Sourcetrail
+Licensed to: Jane Doe
+License type: Commercial License (3 users)
+Valid up to version: 2018.1
+-
+$9$AQAK2j5OkBlxfT/3y0XTbMUu/tRchYJxfD1dHgSFXJMXeFPN9h1N
+RVewaFTRWub12WkRSq4rHaEt6MKZCtO3ntj8bGJxuvH4ggridXBoJjP
+nkHGPMlUvrdbhs/O7uaWvVXf+n7YrZPxeBBdHiXEUI2AaNbig5FzCeS
+Gt31yDkLjSkNwdR4zJGoAB2zWfhxFLIzBXv6z+rToBy71hzMbRHnUX2
+B8zkBAt12QVCZszbV1XJ8LqOhxkGKdo6RsieBc5s2HJB16IFf0gcxkL
+2FRzN6wMlTqs4K4pk8+kxwzB+Ywm+griLgzZo1jbg0JUm4Ou9nppaht
+m4mgTH3FBGtob6Spi7H8hGNGgrT1gRmnHLyomwPfKXKuO/snvK3CZCB
+yBAHSwjidKqg==
+-----END LICENSE-----)"
+ );
+
+ Version version = Version::getApplicationVersion();
+ Version::setApplicationVersion(Version(2019, 1, 11, "asdfasdf"));
+
+ TS_ASSERT(ok);
+ TS_ASSERT_EQUALS(license.getUser(), "Jane Doe");
+ TS_ASSERT_EQUALS(license.getType(), "Commercial License");
+ TS_ASSERT_EQUALS(license.getNumberOfUsers(), 3);
+ TS_ASSERT_EQUALS(license.getTimeLeft(), -2);
+ TS_ASSERT(license.isComplete());
+ TS_ASSERT(!license.isEmpty());
+ TS_ASSERT(license.isExpired());
+ TS_ASSERT(!license.isTestLicense());
+
+ LicenseChecker::loadPublicKey();
+ TS_ASSERT_EQUALS(LicenseChecker::checkLicense(license), LicenseChecker::LicenseState::EXPIRED);
+
+ Version::setApplicationVersion(version);
+ }
+
+ void test_check_one_hundred_year_testimonial_license()
+ {
+ License license;
+ bool ok = license.loadFromString(
+R"(-----BEGIN LICENSE-----
+Product: Sourcetrail
+Licensed to: Jane Doe
+License type: Commercial License (1 Seat)
+Valid up to version: 2117.2
+-
+$9$AQAKhOnW2QeCuuNbHLpUN7CT7DE/FRuOvEOEcHDNOn7yGs0CUIMS
+Ox9zCpz0xH/XsNmL6NTyS3P4DOm9snvaJZM90ttr3nxy4Dv3IRWVXvg
+OsvwbkYYC+N2WUKJ+ahk8zU7Uz179tdX2FLbce6/xcOi8Utv3thWWWs
+EbV62Ja3DS7Qt9Oq7ui+9PrpvPmsc81yK5g993vOsZkPuOuoE8KNX1m
+Dhl9UxaBZfmfQVtiAWx1vP8zCJ4nnANgfAAKPBXfYyuvf8/+GDC7CLo
+9e5e0swhcMt0z0DfKdwR59sQPZnXSZyouW5GzTUi2E8nw5IStxi3/GX
+z3TR0g8ERzP07KrzdYklfYv+cxtlev/H869p0USn5kPBwW8+ZFX+5Id
+8CVzujNAz//w==
+-----END LICENSE-----)"
+ );
+
+ Version version = Version::getApplicationVersion();
+ Version::setApplicationVersion(Version(2019, 1, 11, "asdfasdf"));
+
+ TS_ASSERT(ok);
+ TS_ASSERT_EQUALS(license.getUser(), "Jane Doe");
+ TS_ASSERT_EQUALS(license.getType(), "Commercial License");
+ TS_ASSERT_EQUALS(license.getNumberOfUsers(), 1);
+ TS_ASSERT_EQUALS(license.getTimeLeft(), -2);
+ TS_ASSERT(license.isComplete());
+ TS_ASSERT(!license.isEmpty());
+ TS_ASSERT(!license.isExpired());
+ TS_ASSERT(!license.isTestLicense());
+
+ LicenseChecker::loadPublicKey();
+ TS_ASSERT_EQUALS(LicenseChecker::checkLicense(license), LicenseChecker::LicenseState::VALID);
+
+ Version::setApplicationVersion(version);
+ }
+};
diff --git a/src/test/GeneratorTestSuite.h b/src/test/LicenseGeneratorTestSuite.h
similarity index 51%
rename from src/test/GeneratorTestSuite.h
rename to src/test/LicenseGeneratorTestSuite.h
index dbb6f9e0..c5a98c74 100644
--- a/src/test/GeneratorTestSuite.h
+++ b/src/test/LicenseGeneratorTestSuite.h
@@ -1,16 +1,17 @@
#include
#include "License.h"
-#include "Generator.h"
+#include "LicenseChecker.h"
+#include "LicenseGenerator.h"
-class GeneratorTestSuite : public CxxTest::TestSuite
+class LicenseGeneratorTestSuite : public CxxTest::TestSuite
{
public:
void test_create_Keys_with_Version_and_check()
{
- Generator generator;
- generator.generateKeys();
+ LicenseGenerator generator;
+ generator.generatePrivateKey();
std::string privateKey = generator.getPrivateKeyPEMFileAsString();
std::string publicKey = generator.getPublicKeyPEMFileAsString();
@@ -24,16 +25,15 @@ public:
void test_load_private_Key_from_file()
{
- Generator generator;
- generator.setCustomPrivateKeyFile("./data/GeneratorTestSuite/private-v2.pem");
- bool ok = generator.loadPrivateKeyFromFile();
+ LicenseGenerator generator;
+ bool ok = generator.loadPrivateKeyFromFile("./data/LicenseGeneratorTestSuite/private-v2.pem");
TS_ASSERT(ok);
}
void test_load_private_key_from_string()
{
- Generator generator;
+ LicenseGenerator generator;
bool ok = generator.loadPrivateKeyFromString(m_privateKey);
TS_ASSERT(ok);
@@ -41,71 +41,83 @@ public:
void test_create_volume_license_and_validate()
{
- Generator generator;
- generator.generateKeys();
- generator.loadPrivateKeyFromString(generator.getPrivateKeyPEMFileAsString());
+ LicenseGenerator generator;
+ generator.generatePrivateKey();
- License license;
- license.loadFromString(generator.encodeLicenseByQuarters("TestUser", "VolumeLicense", 20, 4));
+ std::unique_ptr license = generator.createLicenseByQuarters("TestUser", "VolumeLicense", 20, 4);
- TS_ASSERT_EQUALS(license.getNumberOfUsers(), 20);
+ TS_ASSERT(license.get());
+ TS_ASSERT_EQUALS(license->getUser(), "TestUser");
+ TS_ASSERT_EQUALS(license->getType(), "VolumeLicense");
+ TS_ASSERT_EQUALS(license->getNumberOfUsers(), 20);
+ TS_ASSERT_EQUALS(license->isEmpty(), false);
+ TS_ASSERT_EQUALS(license->isComplete(), true);
+ TS_ASSERT_EQUALS(license->isExpired(), false);
+ TS_ASSERT_EQUALS(license->isTestLicense(), false);
+ TS_ASSERT_EQUALS(license->getTimeLeft(), -2);
+
+ TS_ASSERT(LicenseChecker::loadPublicKeyFromString(generator.getPublicKeyPEMFileAsString()));
+ TS_ASSERT_EQUALS(LicenseChecker::checkLicense(*license.get()), LicenseChecker::LicenseState::VALID);
}
void test_create_test_license_and_validate()
{
- Generator generator;
- generator.generateKeys();
- generator.loadPrivateKeyFromString(generator.getPrivateKeyPEMFileAsString());
+ LicenseGenerator generator;
+ generator.generatePrivateKey();
- License license;
- license.loadPublicKeyFromString(generator.getPublicKeyPEMFileAsString());
- license.loadFromString(generator.encodeLicenseByDays("User", "", 0, 10));
+ std::unique_ptr license = generator.createLicenseByDays("User", "", 0, 10);
- TS_ASSERT(license.isValid());
- TS_ASSERT_EQUALS(license.getTimeLeft(), 10);
+ TS_ASSERT(license.get());
+ TS_ASSERT_EQUALS(license->getUser(), "User");
+ TS_ASSERT_EQUALS(license->getType(), "Test License");
+ TS_ASSERT_EQUALS(license->getNumberOfUsers(), 0);
+ TS_ASSERT_EQUALS(license->isEmpty(), false);
+ TS_ASSERT_EQUALS(license->isComplete(), true);
+ TS_ASSERT_EQUALS(license->isExpired(), false);
+ TS_ASSERT_EQUALS(license->isTestLicense(), true);
+ TS_ASSERT_EQUALS(license->getTimeLeft(), 10);
- license.loadPublicKeyFromString(generator.getPublicKeyPEMFileAsString());
- license.loadFromString(generator.encodeLicenseByDays("User", "", 0, -10));
+ TS_ASSERT(LicenseChecker::loadPublicKeyFromString(generator.getPublicKeyPEMFileAsString()));
+ TS_ASSERT_EQUALS(LicenseChecker::checkLicense(*license.get()), LicenseChecker::LicenseState::VALID);
- TS_ASSERT(!license.isValid());
- // -1 and not -10 since it means it is expired
- TS_ASSERT_EQUALS(license.getTimeLeft(), -1);
+ license = generator.createLicenseByDays("User", "", 0, -10);
+
+ TS_ASSERT(license.get());
+ TS_ASSERT_EQUALS(license->getUser(), "User");
+ TS_ASSERT_EQUALS(license->getType(), "Test License");
+ TS_ASSERT_EQUALS(license->getNumberOfUsers(), 0);
+ TS_ASSERT_EQUALS(license->isEmpty(), false);
+ TS_ASSERT_EQUALS(license->isComplete(), true);
+ TS_ASSERT_EQUALS(license->isExpired(), true);
+ TS_ASSERT_EQUALS(license->isTestLicense(), true);
+ TS_ASSERT_EQUALS(license->getTimeLeft(), -1);
+ TS_ASSERT_EQUALS(LicenseChecker::checkLicense(*license.get()), LicenseChecker::LicenseState::EXPIRED);
}
void test_create_licenses_and_check_the_license_info()
{
- Generator generator;
- generator.generateKeys();
+ LicenseGenerator generator;
+ generator.generatePrivateKey();
- License license;
+ std::unique_ptr license = generator.createLicenseByVersion("TestUser", "Private License", 1, "2017.4");
+ std::string testInfo = "TestUser\nPrivate License\n1 user\nvalid up to version 2017.4";
+ TS_ASSERT(license.get());
+ TS_ASSERT_EQUALS(license->getLicenseInfo(), testInfo);
- license.loadFromString(generator.encodeLicenseByVersion("TestUser", "Private License", 1, "2017.4"));
- std::string testInfo = "TestUser\nPrivate License\n1 user\nvalid up to version: 2017.4";
- TS_ASSERT_EQUALS(license.getLicenseInfo(), testInfo);
+ license = generator.createLicenseByVersion("TestUser", "Volume License", 20, "2017.3");
+ testInfo = "TestUser\nVolume License\n20 users\nvalid up to version 2017.3";
+ TS_ASSERT(license.get());
+ TS_ASSERT_EQUALS(license->getLicenseInfo(), testInfo);
- license.loadFromString(generator.encodeLicenseByVersion("TestUser", "Volume License", 20, "2017.3"));
- testInfo = "TestUser\nVolume License\n20 users\nvalid up to version: 2017.3";
- TS_ASSERT_EQUALS(license.getLicenseInfo(), testInfo);
+ license = generator.createLicenseByVersion("TestUser", "Volume License", 0, "2018.3");
+ testInfo = "TestUser\nVolume License\nunlimited users\nvalid up to version 2018.3";
+ TS_ASSERT(license.get());
+ TS_ASSERT_EQUALS(license->getLicenseInfo(), testInfo);
- license.loadFromString(generator.encodeLicenseByVersion("TestUser", "Private/Academic Single User License", 0, "2018.1"));
- testInfo = "TestUser\nPrivate/Academic Single User License\nnot registered for commercial development\nvalid up to version: 2018.1";
- TS_ASSERT_EQUALS(license.getLicenseInfo(), testInfo);
- }
-
- void test_create_license_and_validate()
- {
- Generator generator;
- generator.generateKeys();
-
- generator.loadPrivateKeyFromString(generator.getPrivateKeyPEMFileAsString());
- License license;
- license.loadFromString(generator.encodeLicenseByVersion("TestUser", "Private License", 20, "2017.3"));
- license.loadPublicKeyFromString(generator.getPublicKeyPEMFileAsString());
-
- TS_ASSERT_EQUALS(license.getUser(), "TestUser");
- TS_ASSERT_EQUALS(license.getType(), "Private License");
- TS_ASSERT_EQUALS(license.getNumberOfUsers(), 20);
- TS_ASSERT(license.isValid());
+ license = generator.createLicenseLifelong("TestUser", "Volume License", 1);
+ testInfo = "TestUser\nVolume License\n1 user\nvalid perpetually";
+ TS_ASSERT(license.get());
+ TS_ASSERT_EQUALS(license->getLicenseInfo(), testInfo);
}
private: