diff --git a/CMakeLists.txt b/CMakeLists.txt index c924f634..ed298116 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -599,17 +599,13 @@ if (WIN32) elseif (UNIX) add_custom_command( - OUTPUT ${TESTGEN_FILE} + TARGET ${TEST_PROJECT_NAME} PRE_BUILD - COMMAND rm -f ${TESTGEN_FILE} + #COMMAND rm -f ${TESTGEN_FILE} COMMAND cd ${PROJECT_SOURCE_DIR} && ${PYTHON_EXECUTABLE} ${CXXTEST_PYTHON_TESTGEN_EXECUTABLE} --runner=ParenPrinter -o ${TESTGEN_FILE} ${TEST_FILES} COMMENT "Generating unittest code with cxxtestgen" ) - add_custom_target(gen DEPENDS ${TESTGEN_FILE}) - - add_dependencies(${TEST_PROJECT_NAME} gen) - endif () # Visual Leak Detector --------------------------------------------------------- diff --git a/bin/app/data/gui/startscreen/startscreen.css b/bin/app/data/gui/startscreen/startscreen.css index c491cf92..8ebe47be 100644 --- a/bin/app/data/gui/startscreen/startscreen.css +++ b/bin/app/data/gui/startscreen/startscreen.css @@ -47,6 +47,17 @@ font-size: 12px; } +#licenseHeaderLabel { + color: black; + font-size: 12px; + font-weight: bold; +} + +#licenseLabel { + color: black; + font-size: 12px; +} + #welcomeLabel { color: black; font-size: 12px; diff --git a/cmake/CLANGConfig.cmake b/cmake/CLANGConfig.cmake index b947908d..9c5def8a 100644 --- a/cmake/CLANGConfig.cmake +++ b/cmake/CLANGConfig.cmake @@ -21,6 +21,7 @@ if (UNIX AND NOT APPLE) LLVMCONFIG llvm-config PATHS "${CLANG_BUILD_PATH}/bin" + HINTS "${CLANG_BUILD_PATH}/bin" ) execute_process( COMMAND ${LLVMCONFIG} --cxxflags diff --git a/src/lib/component/controller/IDECommunicationController.cpp b/src/lib/component/controller/IDECommunicationController.cpp index 357e1883..4a38c688 100644 --- a/src/lib/component/controller/IDECommunicationController.cpp +++ b/src/lib/component/controller/IDECommunicationController.cpp @@ -173,19 +173,14 @@ void IDECommunicationController::handlePing(const NetworkProtocolHelper::PingMes if (message.valid) { MessagePingReceived msg; - msg.ideId = message.ideId; + msg.ideName = message.ideId; - std::string ideName = "unknown"; - - if (msg.ideId == "vs") + if (msg.ideName.empty()) { - ideName = "Visual Studio"; + msg.ideName = "unknown"; } - // TODO: add the other ides - msg.ideName = ideName; - - std::string statusMessage = ideName + " instance detected via plugin port"; + std::string statusMessage = msg.ideName + " instance detected via plugin port"; MessageStatus(statusMessage, false, false).dispatch(); msg.dispatch(); diff --git a/src/lib_gui/qt/window/QtStartScreen.cpp b/src/lib_gui/qt/window/QtStartScreen.cpp index 480f9b8c..579abbd0 100644 --- a/src/lib_gui/qt/window/QtStartScreen.cpp +++ b/src/lib_gui/qt/window/QtStartScreen.cpp @@ -16,6 +16,8 @@ #include "qt/utility/utilityQt.h" #include "utility/logging/logging.h" #include "utility/Version.h" +#include "License.h" +#include "utility/AppPath.h" QtRecentProjectButton::QtRecentProjectButton(QWidget* parent) : QPushButton(parent) @@ -95,7 +97,7 @@ QSize QtStartScreen::sizeHint() const void QtStartScreen::updateButtons() { std::vector recentProjects = ApplicationSettings::getInstance()->getRecentProjects(); - size_t i = 0; +size_t i = 0; for (QtRecentProjectButton* button : m_recentProjectsButtons) { button->disconnect(); @@ -207,6 +209,22 @@ void QtStartScreen::setupStartScreen(bool unlocked) updateLabel->setObjectName("updateLabel"); col->addWidget(updateLabel); + col->addSpacing(20); + + License license; + license.loadFromEncodedString( + ApplicationSettings::getInstance()->getLicenseString(), AppPath::getAppPath()); + + std::string licenseString = license.getLicenseInfo(); + + QLabel* licenseHeader = new QLabel("Licensed to:"); + licenseHeader->setObjectName("licenseHeaderLabel"); + col->addWidget(licenseHeader); + col->addSpacing(2); + QLabel* licenseLabel = new QLabel(licenseString.c_str()); + licenseLabel->setObjectName("licenseLabel"); + col->addWidget(licenseLabel); + col->addStretch(); QPushButton* newProjectButton = new QPushButton("New Project", this); diff --git a/src/lib_license/Generator.cpp b/src/lib_license/Generator.cpp index d8cdb5b1..8e960ec6 100644 --- a/src/lib_license/Generator.cpp +++ b/src/lib_license/Generator.cpp @@ -59,7 +59,7 @@ std::string Generator::encodeLicense(const std::string& user, const int days) boost::gregorian::date expireDate = today + daysToTry; std::string testLicenseTypeString = "Test License - valid till " + boost::gregorian::to_simple_string(expireDate); - return encodeLicense(user, testLicenseTypeString); + return encodeLicense(user, testLicenseTypeString); } std::string Generator::encodeLicense(const std::string& user, const std::string& licenseType, const int seats) @@ -67,35 +67,46 @@ std::string Generator::encodeLicense(const std::string& user, const std::string& if (user.size() <= 0) { std::cout << "No user given" << std::endl; - return ""; + return ""; } if (licenseType.size() <= 0) { std::cout << "No licence type given" << std::endl; - return ""; + return ""; } - License license; - //load private key - std::string filename = getPrivateKeyFilename(); - - std::shared_ptr privateKey( - Botan::PKCS8::load_key(filename, m_rng, PRIVATE_KEY_PASSWORD)); - - Botan::RSA_PrivateKey *rsaKey = dynamic_cast(privateKey.get()); - - if (!rsaKey) - { - std::cout << "The key is not a RSA key" << std::endl; + if (!m_privateKey) + { + std::cout << "No private key. Trying to load from file." << std::endl; + loadPrivateKeyFromFile(); } - license.create(user, m_version, rsaKey, licenseType, seats); - license.writeToFile("license.txt"); - license.print(); + if (!m_privateKey) + { + std::cout << "No private key. Load from file or string." << std::endl; + return ""; + } - return license.getLicenseString(); + + m_license = std::make_shared(); + m_license->create(user, m_version, m_privateKey.get(), licenseType, seats); + + 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) diff --git a/src/lib_license/Generator.h b/src/lib_license/Generator.h index 5c0b9fb6..25c78394 100644 --- a/src/lib_license/Generator.h +++ b/src/lib_license/Generator.h @@ -10,6 +10,7 @@ namespace Botan { class RSA_PrivateKey; } +class License; class Generator { @@ -17,8 +18,9 @@ public: Generator(const std::string& version = "x"); ~Generator(); - std::string encodeLicense(const std::string& message, const std::string& licenseType, const int seats = 0); - std::string encodeLicense(const std::string& message, const int days); + std::string encodeLicense(const std::string& user, const std::string& licenseType, const int seats = 0); + std::string encodeLicense(const std::string& user, const int days); + void printLicenseAndWriteItToFile(); bool verifyLicense(const std::string& filename = "license.txt"); void generateKeys(); void writeKeysToFiles(); @@ -45,7 +47,7 @@ private: std::string m_version; std::string m_privateKeyFile; std::string m_publicKeyFile; - std::string m_license; + std::shared_ptr m_license; std::shared_ptr m_privateKey; const std::string PRIVATE_KEY_PASSWORD = "BA#jk5vbklAiKL9K3k$"; diff --git a/src/lib_license/License.cpp b/src/lib_license/License.cpp index 9b7e2174..46cc824c 100644 --- a/src/lib_license/License.cpp +++ b/src/lib_license/License.cpp @@ -139,21 +139,69 @@ unsigned int License::getSeats() const return 0; } +std::string License::getLicenseType() const +{ + std::string licenseTypeLine = getLicenseTypeLine(); + std::size_t found = licenseTypeLine.find(":"); + if (found != licenseTypeLine.npos) + { + return licenseTypeLine.substr(0,found); + } + + const std::string testLicenseString = "Test License"; + found = licenseTypeLine.find(testLicenseString); + if (found != licenseTypeLine.npos) + { + return "Test License"; + } + + return licenseTypeLine; +} + +std::string License::getLicenseInfo() const +{ + std::string info = getOwnerLine() + "\n"; + + const std::string typeString = getLicenseType(); + info += getLicenseType() + "\n"; + + // get info depending on license type + if (typeString == "Private/Academic Single User License") + { + info += "not registered for commercial development"; + } + else if (typeString == "Test License") + { + const std::string t = "Test License - "; + info += getLicenseTypeLine().substr(t.length()) + "\nunlimited Seats"; + } + else if (getSeats() > 1) + { + info += std::to_string(getSeats()) + " Seats"; + } + else + { + info += "1 Seat"; + } + + return info; +} + int License::getTimeLeft() const { const std::string testText = "Test License - valid till "; - const int leMagicNumber = 11; + const std::string dateText = "YYYY-MMM-DD"; std::string licenceType = getLicenseTypeLine(); - if (licenceType.size() <= (testText.length() + leMagicNumber)) + if (licenceType.length() != (testText.length() + dateText.length())) { - return -2; // well, since it's unclear what type of licence...?? + return -2; // well, since it's unclear what type of licence...?? } if(licenceType.substr(0, testText.length()) == testText) { - std::string dateString = licenceType.substr(testText.length(), leMagicNumber); + std::string dateString = licenceType.substr(testText.length(), dateText.length()); boost::gregorian::date expireDate( boost::gregorian::from_simple_string(dateString)); @@ -291,10 +339,10 @@ void License::addSignature(const std::string& signature) } std::stringstream ss; - const int leMagicNumber = 55; // what does this number mean? signature length? + const int lineLength = 55; for (size_t i = 0; i < signature.size(); i++) { - if(i % leMagicNumber == 0 && i != 0) + if(i % lineLength == 0 && i != 0) { m_lines.push_back(ss.str()); ss.str(""); diff --git a/src/lib_license/License.h b/src/lib_license/License.h index 4076adba..916bf1e6 100644 --- a/src/lib_license/License.h +++ b/src/lib_license/License.h @@ -24,7 +24,9 @@ public: std::string getVersionLine() const; std::string getOwnerLine() const; std::string getLicenseTypeLine() const; + std::string getLicenseType() const; + std::string getLicenseInfo() const; std::string getPublicKeyFilename() const; std::string getVersion() const; unsigned int getSeats() const; diff --git a/src/license_generator/main.cpp b/src/license_generator/main.cpp index 4637bda0..d48660d4 100644 --- a/src/license_generator/main.cpp +++ b/src/license_generator/main.cpp @@ -35,7 +35,6 @@ bool process_command_line(int argc, char** argv) po::options_description keygen_description("Options Keygeneration"); keygen_description.add_options() ("seats,s", po::value(&seats), "Generate a License, USERNAME as value") - ("version,v", po::value(&version), "Versionnumber of Coati") ("licenseType,t", po::value(&type), "License Type of ") ("testLicense,e", po::value(&days), "Generates a test license for days"); @@ -61,12 +60,22 @@ bool process_command_line(int argc, char** argv) po::notify(vm); // display help if no argument or the help argument is given - if (vm.count("help") || vm.size() == 0) + if (vm.count("help")) { std::cout << desc << std::endl; return 1; } + // no mode chosen -> display help + if ( vm.size() == 0 || !(vm.count("hidden") || vm.count("key") || vm.count("check") || vm.count("generate"))) + { + std::cout << "*****************************\nNo mode chosen, display help: " + << "\n*****************************\n\n" << desc << std::endl; + + return 1; + } + + if (vm.count("hidden")) { std::cout << allDescriptions << std::endl; @@ -114,10 +123,12 @@ bool process_command_line(int argc, char** argv) if(vm.count("testLicense")) { keygen.encodeLicense(user,days); + keygen.printLicenseAndWriteItToFile(); } else { keygen.encodeLicense(user,type,seats); + keygen.printLicenseAndWriteItToFile(); } } diff --git a/src/test/GeneratorTestSuite.h b/src/test/GeneratorTestSuite.h index 3db1704b..8d1b5558 100644 --- a/src/test/GeneratorTestSuite.h +++ b/src/test/GeneratorTestSuite.h @@ -51,6 +51,49 @@ public: TS_ASSERT_EQUALS(license.getSeats(), 20); } + void test_create_test_license_and_validate() + { + Generator generator("v2"); + generator.generateKeys(); + generator.loadPrivateKeyFromString(generator.getPrivateKeyPEMFileAsString()); + + License license; + license.loadPublicKeyFromString(generator.getPublicKeyPEMFileAsString()); + license.loadFromString(generator.encodeLicense("User", 10)); + + TS_ASSERT(license.isValid()); + TS_ASSERT_EQUALS(license.getTimeLeft(), 10); + + license.loadPublicKeyFromString(generator.getPublicKeyPEMFileAsString()); + license.loadFromString(generator.encodeLicense("User", -10)); + + TS_ASSERT(!license.isValid()); + // -1 and not -10 since it means it is expired + TS_ASSERT_EQUALS(license.getTimeLeft(), -1); + } + + void test_create_licenses_and_check_the_license_info() + { + Generator generator("v2"); + generator.generateKeys(); + + generator.loadPrivateKeyFromString(generator.getPrivateKeyPEMFileAsString()); + License license; + license.loadPublicKeyFromString(generator.getPublicKeyPEMFileAsString()); + + license.create("TestUser", "v2", generator.getPrivateKey()); + std::string testInfo = "TestUser\nPrivate License\n1 Seat"; + TS_ASSERT_EQUALS(license.getLicenseInfo(), testInfo); + + license.create("TestUser", "v2", generator.getPrivateKey(), "Volume License", 20); + testInfo = "TestUser\nVolume License\n20 Seats"; + TS_ASSERT_EQUALS(license.getLicenseInfo(), testInfo); + + license.create("TestUser", "v2", generator.getPrivateKey(), "Private/Academic Single User License", 20); + testInfo = "TestUser\nPrivate/Academic Single User License\nnot registered for commercial development"; + TS_ASSERT_EQUALS(license.getLicenseInfo(), testInfo); + } + void test_create_license_and_validate() { Generator generator("v2");