logic: versioning
This commit is contained in:
+2
-1
@@ -50,10 +50,11 @@ Linux64_licenseGenerator:
|
||||
script:
|
||||
- ./script/setup.sh
|
||||
- ./script/buildonly.sh r keygen
|
||||
- mv build/Release/license_generator/Sourcetrail_license_generator .
|
||||
artifacts:
|
||||
name: "$CI_JOB_NAME"
|
||||
paths:
|
||||
- build/Release/license_generator/*_license_generator
|
||||
- Sourcetrail_license_generator
|
||||
expire_in: 3 days
|
||||
|
||||
Linux32:
|
||||
|
||||
+13
-6
@@ -106,7 +106,7 @@ elseif(UNIX AND APPLE)
|
||||
set(Boost_NO_SYSTEM_PATHS ON)
|
||||
else()
|
||||
STRING(REGEX REPLACE "\\\\" "/" BOOST_LIBRARYDIR ${BOOST_LIBRARYDIR})
|
||||
|
||||
|
||||
if(${WINXXBITS} STREQUAL "Win32")
|
||||
set(BOOST_ROOT "${BOOST_LIBRARYDIR}/win32")
|
||||
else()
|
||||
@@ -402,11 +402,10 @@ configure_file(
|
||||
)
|
||||
|
||||
# configure public key for the sourcetrail version
|
||||
include(cmake/publicKey.cmake)
|
||||
include(cmake/public_key.cmake)
|
||||
|
||||
set(CMAKE_AUTOMOC OFF)
|
||||
|
||||
|
||||
# Indexer App ------------------------------------------------------------------
|
||||
|
||||
if (UNIX)
|
||||
@@ -583,6 +582,9 @@ endif ()
|
||||
|
||||
add_subdirectory(src/license_generator)
|
||||
|
||||
# configure private key for the sourcetrail version
|
||||
include(cmake/private_key.cmake)
|
||||
|
||||
if (UNIX)
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/license_generator/")
|
||||
else ()
|
||||
@@ -592,7 +594,7 @@ else ()
|
||||
endforeach( OUTPUTCONFIG CMAKE_CONFIGURATION_TYPES )
|
||||
endif ()
|
||||
|
||||
add_executable(${LICENSE_GENERATOR_PROJECT_NAME} ${LICENSE_GENERATOR_FILES})
|
||||
add_executable(${LICENSE_GENERATOR_PROJECT_NAME} ${LICENSE_GENERATOR_FILES} ${LICENSE_GENERATOR_MAIN})
|
||||
|
||||
create_source_groups(${LICENSE_GENERATOR_FILES})
|
||||
|
||||
@@ -600,6 +602,8 @@ set_property(
|
||||
TARGET ${LICENSE_GENERATOR_PROJECT_NAME}
|
||||
PROPERTY INCLUDE_DIRECTORIES
|
||||
"${CMAKE_SOURCE_DIR}/src/lib_license"
|
||||
"${CMAKE_BINARY_DIR}/src/license_generator"
|
||||
"${CMAKE_BINARY_DIR}/src/lib_license"
|
||||
)
|
||||
|
||||
target_include_directories(${LICENSE_GENERATOR_PROJECT_NAME} SYSTEM
|
||||
@@ -632,7 +636,7 @@ set(TESTGEN_FILE ${CMAKE_CURRENT_BINARY_DIR}/test_main.cpp)
|
||||
find_package(PythonInterp REQUIRED)
|
||||
|
||||
|
||||
add_executable (${TEST_PROJECT_NAME} ${TESTGEN_FILE} ${TEST_FILES} )
|
||||
add_executable (${TEST_PROJECT_NAME} ${TESTGEN_FILE} ${TEST_FILES} ${LICENSE_GENERATOR_FILES})
|
||||
|
||||
create_source_groups(${TEST_FILES})
|
||||
|
||||
@@ -650,6 +654,9 @@ if (CXXTEST_FOUND)
|
||||
"${CMAKE_SOURCE_DIR}/src/lib_java"
|
||||
"${CMAKE_SOURCE_DIR}/src/external"
|
||||
"${CMAKE_SOURCE_DIR}/src/lib_license"
|
||||
"${CMAKE_BINARY_DIR}/src/lib_license"
|
||||
"${CMAKE_SOURCE_DIR}/src/license_generator"
|
||||
"${CMAKE_BINARY_DIR}/src/license_generator"
|
||||
"${Boost_INCLUDE_DIRS}"
|
||||
)
|
||||
endif (CXXTEST_FOUND)
|
||||
@@ -719,6 +726,6 @@ if (UNIX)
|
||||
)
|
||||
|
||||
# Linux package
|
||||
include(cmake/LinuxPackage.cmake)
|
||||
include(cmake/linux_package.cmake)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
#ifndef PRIVATE_KEY_H
|
||||
#define PRIVATE_KEY_H
|
||||
|
||||
// This File(PrivateKey.h) is generated with CMake
|
||||
|
||||
#include <string>
|
||||
|
||||
const std::string PRIVATE_KEY = "@KEY@";
|
||||
|
||||
#endif // PRIVATE_KEY_H
|
||||
@@ -5,6 +5,6 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
static const std::string PublicKey = "@KEY@";
|
||||
const std::string PUBLIC_KEY = "@KEY@";
|
||||
|
||||
#endif // PUBLIC_KEY_H
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
# searching for private key file of the Sourcetrail version in setup/RSA_keys
|
||||
# if found the file will be put into a const string into the PrivateKey.h file
|
||||
|
||||
string(REGEX REPLACE "^([0-9]+)\\..*" "\\1" VERSION_MAJOR "${GIT_VERSION_NUMBER}")
|
||||
message(STATUS "Get Public Key for Sourcetrail version: ${VERSION_MAJOR}")
|
||||
|
||||
message(STATUS "${CMAKE_SOURCE_DIR}/setup/RSA_keys/private-sourcetrail.pem")
|
||||
|
||||
set(privateKeyFile "${CMAKE_SOURCE_DIR}/setup/RSA_keys/private-sourcetrail.pem")
|
||||
|
||||
if(EXISTS ${privateKeyFile})
|
||||
file(READ ${privateKeyFile} KEY)
|
||||
STRING(REGEX REPLACE "\"" "\\\\\"" KEY "${KEY}")
|
||||
STRING(REGEX REPLACE "\n" "\\\\n\"\n\t\"" KEY "${KEY}")
|
||||
else()
|
||||
message(FATAL_ERROR "private keyfile for Sourcetrail not found")
|
||||
endif()
|
||||
|
||||
configure_file(
|
||||
${CMAKE_SOURCE_DIR}/cmake/PrivateKey.h.in
|
||||
${CMAKE_BINARY_DIR}/src/license_generator/PrivateKey.h
|
||||
)
|
||||
@@ -1,27 +1,23 @@
|
||||
# searching for public key file of the Sourcetrail version in setup/RSA_keys
|
||||
# if found the file will be put into a const string into the PubicKeh.h file
|
||||
# if found the file will be put into a const string into the PubicKey.h file
|
||||
|
||||
string(REGEX REPLACE "^([0-9]+)\\..*" "\\1" VERSION_MAJOR "${GIT_VERSION_NUMBER}")
|
||||
message(STATUS "Get Public Key for Sourcetrail version: ${VERSION_MAJOR}")
|
||||
|
||||
# message(STATUS "${CMAKE_SOURCE_DIR}/setup/RSA_keys/public-${VERSION_MAJOR}.pem")
|
||||
message(STATUS "${CMAKE_SOURCE_DIR}/setup/RSA_keys/public-0.pem") # explain in Readme.md how to get this to work first
|
||||
message(STATUS "${CMAKE_SOURCE_DIR}/setup/RSA_keys/public-sourcetrail.pem")
|
||||
|
||||
# set(pubKeyFile "${CMAKE_SOURCE_DIR}/setup/RSA_keys/public-${VERSION_MAJOR}.pem")
|
||||
set(pubKeyFile "${CMAKE_SOURCE_DIR}/setup/RSA_keys/public-0.pem") # explain in Readme.md how to get this to work first
|
||||
|
||||
# message(STATUS "file: ${pubKeyFile}")
|
||||
set(pubKeyFile "${CMAKE_SOURCE_DIR}/setup/RSA_keys/public-sourcetrail.pem")
|
||||
|
||||
if(EXISTS ${pubKeyFile})
|
||||
file(READ ${pubKeyFile} KEY)
|
||||
STRING(REGEX REPLACE "\"" "\\\\\"" KEY "${KEY}")
|
||||
STRING(REGEX REPLACE "\n" "\\\\n\"\n\t\"" KEY "${KEY}")
|
||||
# message(STATUS "key: ${KEY}")
|
||||
else()
|
||||
message(WARNING "public keyfile for this version of Sourcetrail not found")
|
||||
message(FATAL_ERROR "public keyfile for Sourcetrail not found")
|
||||
#message(WARNING "public keyfile for Sourcetrail not found")
|
||||
endif()
|
||||
|
||||
configure_file(
|
||||
${CMAKE_SOURCE_DIR}/cmake/PublicKey.h.in
|
||||
${CMAKE_BINARY_DIR}/src/lib_license/PublicKey.h
|
||||
)
|
||||
)
|
||||
+10
-3
@@ -24,7 +24,7 @@ if(EXISTS "${CMAKE_SOURCE_DIR}/.git")
|
||||
)
|
||||
|
||||
execute_process(
|
||||
COMMAND ${GIT_EXECUTABLE} describe --long --match "[0-9]*" --abbrev=7 HEAD
|
||||
COMMAND ${GIT_EXECUTABLE} describe --long --match "[0-9]*" HEAD
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE GIT_VERSION_NUMBER
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
@@ -37,10 +37,17 @@ else(EXISTS "${CMAKE_SOURCE_DIR}/.git")
|
||||
|
||||
endif(EXISTS "${CMAKE_SOURCE_DIR}/.git")
|
||||
|
||||
string(REGEX REPLACE "^([0-9]+)\\..*" "\\1" VERSION_YEAR "${GIT_VERSION_NUMBER}")
|
||||
string(REGEX REPLACE "^[0-9]+\\.([0-9]+).*" "\\1" VERSION_MINOR "${GIT_VERSION_NUMBER}")
|
||||
string(REGEX REPLACE "^[0-9]+\\.[0-9]+-([0-9]+).*" "\\1" VERSION_COMMIT "${GIT_VERSION_NUMBER}")
|
||||
|
||||
message(STATUS "Git current branch: ${GIT_BRANCH}")
|
||||
message(STATUS "Git commit hash: ${GIT_COMMIT_HASH}")
|
||||
message(STATUS "Git commit time: ${GIT_COMMIT_TIME}")
|
||||
message(STATUS "Git version number: " ${GIT_VERSION_NUMBER} )
|
||||
message(STATUS "Git commit hash: ${GIT_COMMIT_HASH}")
|
||||
message(STATUS "Version year: ${VERSION_YEAR}")
|
||||
message(STATUS "Version minor: ${VERSION_MINOR}")
|
||||
message(STATUS "Version commit: ${VERSION_COMMIT}")
|
||||
message(STATUS "Git commit time: ${GIT_COMMIT_TIME}")
|
||||
|
||||
configure_file(
|
||||
${CMAKE_SOURCE_DIR}/cmake/version.h.in
|
||||
|
||||
@@ -5,5 +5,8 @@
|
||||
#define GIT_VERSION_NUMBER "@GIT_VERSION_NUMBER@"
|
||||
#define GIT_COMMIT_HASH "@GIT_COMMIT_HASH@"
|
||||
#define GIT_COMMIT_TIME "@GIT_COMMIT_TIME@"
|
||||
#define VERSION_YEAR @VERSION_YEAR@
|
||||
#define VERSION_MINOR @VERSION_MINOR@
|
||||
#define VERSION_COMMIT @VERSION_COMMIT@
|
||||
|
||||
#endif // SOURCETRAIL_VERSION_H
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
-----BEGIN ENCRYPTED PRIVATE KEY-----
|
||||
MIIFNTBfBgkqhkiG9w0BBQ0wUjAxBgkqhkiG9w0BBQwwJAQMaL23TLlJPBcUKzOV
|
||||
AgMDNFACASAwDAYIKoZIhvcNAgkFADAdBglghkgBZQMEASoEEGE6+JCRFOJ3gax9
|
||||
foofctUEggTQe8MrLN9r4JI+HyQbB1LgERCohoWW0DKhFaK56nnlWtG5mPJksGeF
|
||||
F5jw2qwTgiHkDXR8swCqLpJbHQII0cAJ0XYrso7opAwdtSrUQTZ1v6PUdR50pgND
|
||||
+UzbdRbcp/TLfPfpgYGU4484S0WoHWeP9AbeSs1s8244U36MZTfkQck18psH/c0+
|
||||
lnxJHsUurLuclEhlql5bTaIkslEc6bhiWWBH9hvY+o1wRDpoOtAmgn25UsFb7FSJ
|
||||
PIjDBSJZe9tJPfuuQ8ltvtzz/eo03UJU0BNBalK5dibOoACCi9EGObFn8812DSOb
|
||||
0ZqBafsNCRwavkdOMVJ9GwMfhTJROhz9d9/CTxeFjVzpE0d+UJ1zbGXQDUYswsvG
|
||||
pA2udPvWVi8Sd8at1Mob47UXRkf5PLRXFNmcEwTE4Ui9maYGhA/KnhSPQq9cn2CF
|
||||
HRBgOwRJFR7f4E7BVgAUs6WCrsCL/RhTjnR3dwKAgO/QehVFMd3T9kJwijbk30un
|
||||
ksjMcjWtuDsDveBuldxRMlXbN5Ia3C9vNvWN4S7SIlJ7eUb9SQDcRmcj54tu5K41
|
||||
y8mrqgl9UtX7BxwgKUGP7O9vkQLTkBExNaI5xFLKRYgF0Xzz6xfAb2BawBD2LWZF
|
||||
RpXPAoOexPN7fyUSPYnMZMzboPxyD30SE8uXXf4s00ZpBlnxNhzBnpUVTxohRJUV
|
||||
Y4keHadJr6rmxZ/lfWEUIvTeKdVJdmfrExbGAnyEWUxUtZ/N5e1ufgPGy7V8ZuR3
|
||||
7ghotzx6HJYTajFD8VRbmJ1tIT5C/O2wEqg/yka8b7cQ8xoul8CPyQJ/hVSy9RXV
|
||||
1q4Epc/oQ0dkuLb1oCRbgdJncOR02JnWniRrq8sn+yv8qgoxqtjAL4ng3nry4MWT
|
||||
oo17kjXCEq/mAKHdXLX/dGIA4nGAyQC8xumpMKIiOUHXUJkiAfAjZXkocNu0UXxS
|
||||
VW9aK9MOJjT1g2cYlo9Az1MJtfeOlsEx6oxRpVE8OyfUPa4tUzPMpE8zG6xiFpEw
|
||||
v7cdAj8M9g+iMA5E6UkcA9gGw95wnkvif0AZUWWWXVQxNBelHB43yfvZ7hzANo2S
|
||||
MOPbwDJOwrHFX//dFZJeaYT8voNpnznFlbNcg2LqD6N5l+pQzpDnA+MQ/XgBoL7c
|
||||
4TRsUtIyvXEMFYV/3O9hIEr6GwvjbzOQdEIZfvWbGYV6KnmOnCD+rq10AlBbjmAC
|
||||
8C2TS0R5nPUH/SWPSp2m6+GmO1xj/reAkvQvPgWyzDoOTfuLOm0B21esn5txvN/C
|
||||
wAnTq0RvpnUi/gDnoX4H2lkks2YoU+1v1TKVLG0x+YbV0VH9g0EngGF4PsAV7/qN
|
||||
yf8uBwJKPXPz43SF1GJNN6RcQftYAVbb0TqNMljGNh2fgY3N3echMIAOxHgis98f
|
||||
/QBjYWA7GEc8WkI+EHVAdqMb4l7zI36tsPAg7sUiF2EXZVN9P9aTwkmc71NNUnt5
|
||||
x563kqnv0MFCOAZpq6zq+j7BVxUr6wJDO1Tzot4HfhKbiDeMPvkHUFQJep3UaVLk
|
||||
fAYFD1I1fRZOufUBLcL01KD5RY9QbNI0ouUkQhpTZlDJsA8hSvOlQJyF54hJSkt3
|
||||
BDAkUNz0dqt4kag4GKXN89GOv5fEEMZSkedRBYY5VmwrI+4i6yuXHx0=
|
||||
-----END ENCRYPTED PRIVATE KEY-----
|
||||
@@ -0,0 +1,9 @@
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArAldN+gG7p94WgnKH2Wq
|
||||
XOOqYUcyGUB7GQY66DINxGoZVR9wkawxqGHEOvBaG7Zc469m/0Ox8sCNIt8oGywe
|
||||
le0XdyGnVwJdq02lDp4lLYur3jq15BsApsQCqcOG9zkBX0v9sQhKVxVY5+m0B4v4
|
||||
9i2kHB81k6A2yWvSduoswrBbCsUfAqRmcXwCwT1O6LKN6XRzuzKXXq440fOhZiGX
|
||||
1MkkVTkVMDB/J3uSl63ZkeQIqKTA6mH6qiX0x+xF8VAEwMf/ZvxWtP3S1Ryxbszb
|
||||
MrK/qJfc8Bzp+gJtM36ZgXFMNXL0DshdnI0qXh1+7P6UKekSUEvlbAi/UPnGGYwq
|
||||
8wIDAQAB
|
||||
-----END PUBLIC KEY-----
|
||||
+12
-10
@@ -1,13 +1,15 @@
|
||||
-----BEGIN LICENSE-----
|
||||
builder
|
||||
builder license
|
||||
Coati 0
|
||||
$9$AQAKIJ1UwEq5cZQujDjiHaO9R7B/KN9a6JVxppbOcZ4VSvEFRlSn
|
||||
hBa0BMnyCdcL95VDSSC13m+BC/GTxweqaR2lBrF6NzVlIDeCjhBGv80
|
||||
L5SBw8yaNRx9LOZAnwGWw2IG7lclSuraqECIqVE3o2ooFC4xSg9KC6F
|
||||
4Xqq2Fw8rtPCJ3HwkLZzhMhQg208cdLlyOPXL/dPa1AqZiIar4cnF/0
|
||||
sJDjxpk5C8CvpD4dq0JOs6Xs6KF8Uc7Gwp0UfnwQ0nlOl8TL63ukb8T
|
||||
/70Rmzm5cnwM4iz+BdzfCVnhBgyLwCzJe+/5dF4KlVJxiW/f0GinsmU
|
||||
byuZAQUqcCuVSxZXHBthmsLCN9ZWeAsR+Xvv9WRCs018nuk67BnZ5Aq
|
||||
sdDRu0Q4GBEg==
|
||||
Sourcetrail
|
||||
BuildingLicense
|
||||
Valid until 2020.1
|
||||
-
|
||||
$9$AQAKttB/yiIxt1mfkCY8m/k2g8SgiiC23v2BnavARxJf6g1py6lJ
|
||||
oYqmp8TK/6ThpE1eNESel+MxBZ5mExT1zp3265FSpUlhI2fsxbxjWvz
|
||||
KJsVSGXgv95A/q2K/dQRjtfGuInsujs+FdqyWh18YAF5NRm/PsKQtvj
|
||||
J7d6sKNi23LWEBm4WRhYVYweu0T+GAzyMhOQdx9RvEZnjEYKTUZoy2E
|
||||
fm+El5WO4kx0Q2SHt+yVz9+SBJCWymGu9eb5R6YIZV/aIdhTd+jqhOR
|
||||
N94H0BKZ7L+4kmhPlarR98caQWrrCla9z9tv5B80LyhpgFiTEfHTsag
|
||||
3CLI0S9Ez0iqi/d9uGQ0y7UbVZr2CFvnLJ4W8FLRuIqyF7esfgSx7IZ
|
||||
GFsQa/6uNHVA==
|
||||
-----END LICENSE-----
|
||||
|
||||
+9
-1
@@ -132,7 +132,15 @@ int main(int argc, char *argv[])
|
||||
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling, true);
|
||||
}
|
||||
|
||||
Version version = Version::fromString(GIT_VERSION_NUMBER);
|
||||
Version version(
|
||||
// TODO: replace hard coded version
|
||||
// VERSION_YEAR,
|
||||
// VERSION_MINOR,
|
||||
2017,
|
||||
2,
|
||||
VERSION_COMMIT,
|
||||
GIT_COMMIT_HASH
|
||||
);
|
||||
QApplication::setApplicationVersion(version.toDisplayString().c_str());
|
||||
|
||||
MessageStatus("Starting Sourcetrail " + version.toDisplayString()).dispatch();
|
||||
|
||||
@@ -492,8 +492,6 @@ add_files(
|
||||
utility/utilityUuid.h
|
||||
utility/utilityXml.cpp
|
||||
utility/utilityXml.h
|
||||
utility/Version.cpp
|
||||
utility/Version.h
|
||||
|
||||
Application.cpp
|
||||
Application.h
|
||||
|
||||
@@ -166,7 +166,7 @@ void LicenseChecker::handleMessage(MessageEnteredLicense* message)
|
||||
|
||||
LicenseChecker::LicenseState LicenseChecker::checkLicense(License& license) const
|
||||
{
|
||||
license.loadPublicKeyFromString(PublicKey);
|
||||
license.loadPublicKeyFromString(PUBLIC_KEY);
|
||||
|
||||
if (license.isExpired())
|
||||
{
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
#include "utility/Version.h"
|
||||
|
||||
#include "utility/utilityString.h"
|
||||
#include "utility/logging/logging.h"
|
||||
|
||||
Version Version::s_version;
|
||||
|
||||
Version Version::fromString(const std::string& versionString)
|
||||
{
|
||||
Version version;
|
||||
std::vector<std::string> components = utility::splitToVector(versionString, '-');
|
||||
|
||||
if (components.size() != 3)
|
||||
{
|
||||
LOG_ERROR("Version string is invalid: " + versionString);
|
||||
return version;
|
||||
}
|
||||
|
||||
std::vector<std::string> numbers = utility::splitToVector(components[0], '.');
|
||||
if (numbers.size() > 0)
|
||||
{
|
||||
version.m_majorNumber = std::stoi(numbers[0]);
|
||||
}
|
||||
if (numbers.size() > 1)
|
||||
{
|
||||
version.m_minorNumber = std::stoi(numbers[1]);
|
||||
}
|
||||
if (numbers.size() > 2)
|
||||
{
|
||||
version.m_refreshNumber = std::stoi(numbers[2]);
|
||||
}
|
||||
|
||||
version.m_commitNumber = std::stoi(components[1]);
|
||||
version.m_commitHash = components[2];
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
void Version::setApplicationVersion(const Version& version)
|
||||
{
|
||||
s_version = version;
|
||||
}
|
||||
|
||||
const Version& Version::getApplicationVersion()
|
||||
{
|
||||
return s_version;
|
||||
}
|
||||
|
||||
Version::Version()
|
||||
: m_majorNumber(0)
|
||||
, m_minorNumber(0)
|
||||
, m_refreshNumber(-1)
|
||||
, m_commitNumber(0)
|
||||
{
|
||||
}
|
||||
|
||||
bool Version::isEmpty() const
|
||||
{
|
||||
return m_majorNumber == 0 && m_minorNumber == 0 && m_refreshNumber == -1 && m_commitNumber == 0;
|
||||
}
|
||||
|
||||
std::string Version::toString() const
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << m_majorNumber << '.' << m_minorNumber;
|
||||
if (m_refreshNumber != -1)
|
||||
{
|
||||
ss << '.' << m_refreshNumber;
|
||||
}
|
||||
ss << '-' << m_commitNumber << '-' << m_commitHash;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string Version::toDisplayString() const
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << m_majorNumber << '.' << m_minorNumber;
|
||||
if (m_refreshNumber != -1)
|
||||
{
|
||||
ss << '.' << m_refreshNumber;
|
||||
}
|
||||
ss << '.' << m_commitNumber;
|
||||
return ss.str();
|
||||
}
|
||||
@@ -110,7 +110,7 @@ void CommandLineParser::processLicense(const bool isLoaded)
|
||||
{
|
||||
std::cout << "Could not load License" << std::endl;
|
||||
}
|
||||
m_license.loadPublicKeyFromString(PublicKey);
|
||||
m_license.loadPublicKeyFromString(PUBLIC_KEY);
|
||||
if (!m_license.isValid())
|
||||
{
|
||||
std::cout << "License is not valid" << std::endl;
|
||||
|
||||
@@ -9,6 +9,6 @@ namespace utility
|
||||
boost::uuids::uuid getUuid();
|
||||
std::string uuidToString(const boost::uuids::uuid& uuid);
|
||||
std::string getUuidString();
|
||||
};
|
||||
}
|
||||
|
||||
#endif // UTILITY_UUID_H
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
add_files(
|
||||
LIB_LICENSE_FILES
|
||||
|
||||
Generator.cpp
|
||||
Generator.h
|
||||
utility/Version.cpp
|
||||
utility/Version.h
|
||||
|
||||
License.cpp
|
||||
License.h
|
||||
)
|
||||
|
||||
+95
-232
@@ -10,6 +10,7 @@
|
||||
|
||||
//#include "botan_all.h"
|
||||
#include "boost/date_time.hpp"
|
||||
#include "boost/date_time/gregorian/gregorian.hpp"
|
||||
#include "boost/filesystem.hpp"
|
||||
#include "botan/rsa.h"
|
||||
#include "botan/cryptobox.h"
|
||||
@@ -20,6 +21,8 @@
|
||||
#include "botan/auto_rng.h"
|
||||
#include "botan/pbkdf.h"
|
||||
|
||||
#include "utility/Version.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
std::string trimWhiteSpaces(const std::string &str)
|
||||
@@ -30,42 +33,31 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
License::License()
|
||||
: m_rng(std::make_shared<Botan::AutoSeeded_RNG>())
|
||||
{
|
||||
m_lines[BEGIN_LICENSE_LINE] = BEGIN_LICENSE;
|
||||
m_lines[SOURCETRAIL_LINE] = "Sourcetrail";
|
||||
m_lines[END_LICENSE_LINE] = END_LICENSE;
|
||||
}
|
||||
|
||||
License::~License()
|
||||
{
|
||||
}
|
||||
|
||||
std::string License::getHashLine() const
|
||||
{
|
||||
if (m_lines.size() >= 5)
|
||||
{
|
||||
return m_lines[4];
|
||||
}
|
||||
else
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
std::string License::getMessage() const
|
||||
{
|
||||
std::string message = "";
|
||||
|
||||
if (m_lines.size() >= 5)
|
||||
{
|
||||
for (int i = 1; i < 5; ++i)
|
||||
{
|
||||
message += m_lines[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
message = "";
|
||||
}
|
||||
for (int i = OWNER_LINE; i < FIRST_SIGNATURE_LINE; ++i)
|
||||
{
|
||||
message += m_lines[i];
|
||||
if (m_lines[i].empty())
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
@@ -74,9 +66,9 @@ std::string License::getSignature() const
|
||||
{
|
||||
std::string signatue = "";
|
||||
|
||||
if (m_lines.size() >= 12)
|
||||
if (!m_lines[LAST_SIGNATURE_LINE].empty())
|
||||
{
|
||||
for (int i = 5; i < 12; ++i)
|
||||
for (int i = FIRST_SIGNATURE_LINE; i <= LAST_SIGNATURE_LINE; ++i)
|
||||
{
|
||||
signatue += m_lines[i];
|
||||
}
|
||||
@@ -89,92 +81,58 @@ std::string License::getSignature() const
|
||||
return signatue;
|
||||
}
|
||||
|
||||
std::string License::getVersionLine() const
|
||||
std::string License::getLine(LICENSE_LINE line) const
|
||||
{
|
||||
if (m_lines.size() >= 3)
|
||||
{
|
||||
return m_lines[3];
|
||||
}
|
||||
else
|
||||
{
|
||||
return "";
|
||||
}
|
||||
return m_lines[line];
|
||||
}
|
||||
|
||||
std::string License::getOwnerLine() const
|
||||
void License::setLine(const LICENSE_LINE line, const std::string& value)
|
||||
{
|
||||
if (m_lines.size() >= 1)
|
||||
{
|
||||
return m_lines[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
return "";
|
||||
}
|
||||
// only allow to set message lines
|
||||
if (line < FIRST_SIGNATURE_LINE)
|
||||
{
|
||||
m_lines[line] = value;
|
||||
}
|
||||
}
|
||||
|
||||
std::string License::getLicenseTypeLine() const
|
||||
std::string License::getVersionLineWithoutPrefix() const
|
||||
{
|
||||
if (m_lines.size() >= 2)
|
||||
{
|
||||
return m_lines[2];
|
||||
}
|
||||
else
|
||||
{
|
||||
return "";
|
||||
}
|
||||
return getLine(VERSION_LINE).substr(LicenseConstants::UNTIL_PREFIX.length());
|
||||
}
|
||||
|
||||
unsigned int License::getSeats() const
|
||||
{
|
||||
std::string licenseTypeLine = getLicenseTypeLine();
|
||||
std::size_t found = licenseTypeLine.find(":");
|
||||
if (found != std::string::npos)
|
||||
std::string line = getLine(SEATS_LINE);
|
||||
if (!line.empty())
|
||||
{
|
||||
// +2 (": ")
|
||||
std::stringstream seatsStream(licenseTypeLine.substr(found+2));
|
||||
int seats;
|
||||
seatsStream>>seats;
|
||||
return seats;
|
||||
try
|
||||
{
|
||||
return std::stoi(line);
|
||||
}
|
||||
catch (std::invalid_argument e)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
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";
|
||||
std::string info = getLine(OWNER_LINE) + "\n";
|
||||
|
||||
const std::string typeString = getLicenseType();
|
||||
info += getLicenseType() + "\n";
|
||||
const std::string typeString = getLine(TYPE_LINE);
|
||||
info += typeString + "\n";
|
||||
info += getLine(VERSION_LINE) + "\n";
|
||||
|
||||
// get info depending on license type
|
||||
if (typeString == "Private/Academic Single User License")
|
||||
if (isNonCommercialLicenseType(typeString))
|
||||
{
|
||||
info += "not registered for commercial development";
|
||||
}
|
||||
else if (typeString == "Test License")
|
||||
else if (typeString == LicenseConstants::TEST_LICENSE_STRING)
|
||||
{
|
||||
const std::string t = "Test License - ";
|
||||
info += getLicenseTypeLine().substr(t.length()) + "\nunlimited Seats";
|
||||
info += "unlimited Seats";
|
||||
}
|
||||
else if (getSeats() > 1)
|
||||
{
|
||||
@@ -191,7 +149,9 @@ std::string License::getLicenseInfo() const
|
||||
bool License::isNonCommercialLicenseType(const std::string type) const
|
||||
{
|
||||
for ( const std::string nonCommercialLicenseType : NON_COMMERCIAL_LICENSE_TYPES)
|
||||
{ if (type == nonCommercialLicenseType) {
|
||||
{
|
||||
if (type == nonCommercialLicenseType)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -200,72 +160,21 @@ bool License::isNonCommercialLicenseType(const std::string type) const
|
||||
|
||||
int License::getTimeLeft() const
|
||||
{
|
||||
const std::string testText = "Test License - valid till ";
|
||||
const std::string dateText = "YYYY-MMM-DD";
|
||||
|
||||
std::string licenceType = getLicenseTypeLine();
|
||||
|
||||
if (licenceType.length() != (testText.length() + dateText.length()))
|
||||
{
|
||||
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(), dateText.length());
|
||||
|
||||
boost::gregorian::date expireDate(
|
||||
boost::gregorian::from_simple_string(dateString));
|
||||
|
||||
boost::gregorian::date today = boost::gregorian::day_clock::local_day();
|
||||
boost::gregorian::days daysLeft = expireDate - today;
|
||||
|
||||
return (daysLeft.days() < 0 ? -1 : daysLeft.days());
|
||||
}
|
||||
else
|
||||
{
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
|
||||
void License::create(
|
||||
const std::string& user, const std::string& version,
|
||||
Botan::RSA_PrivateKey* privateKey, const std::string& type, const unsigned int seats)
|
||||
{
|
||||
m_version = version;
|
||||
if (seats > 0)
|
||||
std::string dateString = getVersionLineWithoutPrefix();
|
||||
if (dateString.length() != dateText.length())
|
||||
{
|
||||
createMessage(user, version, type + ": " + std::to_string(seats) + " seats");
|
||||
}
|
||||
else
|
||||
{
|
||||
createMessage(user, version, type);
|
||||
return -2;
|
||||
}
|
||||
|
||||
//encode message
|
||||
Botan::PK_Signer signer(*privateKey, *(m_rng.get()), "EMSA4(SHA-256)");
|
||||
Botan::DataSource_Memory in(getMessage());
|
||||
Botan::byte buffer[4096] = {0};
|
||||
boost::gregorian::date expireDate(
|
||||
boost::gregorian::from_simple_string(dateString));
|
||||
|
||||
while (size_t got = in.read(buffer, sizeof(buffer)))
|
||||
{
|
||||
signer.update(buffer, got); // the hell does 'got' stand for?
|
||||
}
|
||||
boost::gregorian::date today = boost::gregorian::day_clock::local_day();
|
||||
boost::gregorian::days daysLeft = expireDate - today;
|
||||
|
||||
std::string signature = Botan::base64_encode(signer.signature(*(m_rng.get())));
|
||||
addSignature(signature);
|
||||
}
|
||||
|
||||
void License::createMessage(const std::string& user, const std::string& version, const std::string& type)
|
||||
{
|
||||
m_lines.clear();
|
||||
m_lines.push_back(BEGIN_LICENSE);
|
||||
m_lines.push_back(user);
|
||||
m_lines.push_back(type);
|
||||
std::string versionstring = "Sourcetrail " + getVersion();
|
||||
m_lines.push_back(versionstring);
|
||||
std::string pass9 = Botan::generate_passhash9(versionstring, *(m_rng.get()));
|
||||
m_lines.push_back(pass9);
|
||||
return (daysLeft.days() < 0 ? -1 : daysLeft.days());
|
||||
}
|
||||
|
||||
void License::writeToFile(const std::string& filename)
|
||||
@@ -279,23 +188,27 @@ void License::writeToFile(const std::string& filename)
|
||||
|
||||
bool License::loadFromString(const std::string& licenseText)
|
||||
{
|
||||
m_lines.clear();
|
||||
std::istringstream license(licenseText);
|
||||
return load(license);
|
||||
}
|
||||
|
||||
bool License::load(std::istream& stream)
|
||||
{
|
||||
m_lines.clear();
|
||||
int currentLine = 1;
|
||||
std::string line;
|
||||
|
||||
while (getline(stream, line, '\n'))
|
||||
while (getline(stream, line, '\n') && currentLine < END_LICENSE_LINE)
|
||||
{
|
||||
std::string l = trimWhiteSpaces(line);
|
||||
if (l.size())
|
||||
std::string l = trimWhiteSpaces(line);
|
||||
if (l == BEGIN_LICENSE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (l.size())
|
||||
{
|
||||
m_lines.push_back(l);
|
||||
m_lines[currentLine] = l;
|
||||
}
|
||||
currentLine++;
|
||||
}
|
||||
|
||||
if (m_lines.size() <= 0)
|
||||
@@ -304,29 +217,11 @@ bool License::load(std::istream& stream)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_lines.front() != BEGIN_LICENSE)
|
||||
{
|
||||
std::cout << "No License Header" << std::endl;
|
||||
m_lines.insert(m_lines.begin(), BEGIN_LICENSE);
|
||||
}
|
||||
|
||||
if (m_lines.back() != END_LICENSE)
|
||||
{
|
||||
std::cout << "No License Footer" << std::endl;
|
||||
m_lines.push_back(END_LICENSE);
|
||||
}
|
||||
|
||||
if (m_lines.size() != 13)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool License::loadFromFile(const std::string& filename)
|
||||
{
|
||||
m_lines.clear();
|
||||
std::ifstream sigfile(filename);
|
||||
return load(sigfile);
|
||||
}
|
||||
@@ -336,34 +231,6 @@ void License::print()
|
||||
std::cout << getLicenseString();
|
||||
}
|
||||
|
||||
void License::addSignature(const std::string& signature)
|
||||
{
|
||||
if(m_lines.size() > 5)
|
||||
{
|
||||
std::cout << "signature already there" << std::endl;
|
||||
return;
|
||||
}
|
||||
if (signature.size() <= 0)
|
||||
{
|
||||
std::cout << "signature is empty." << std::endl;
|
||||
return;
|
||||
}
|
||||
std::stringstream ss;
|
||||
|
||||
const int lineLength = 55;
|
||||
for (size_t i = 0; i < signature.size(); i++)
|
||||
{
|
||||
if(i % lineLength == 0 && i != 0)
|
||||
{
|
||||
m_lines.push_back(ss.str());
|
||||
ss.str("");
|
||||
}
|
||||
ss << signature[i];
|
||||
}
|
||||
|
||||
m_lines.push_back(ss.str());
|
||||
m_lines.push_back(END_LICENSE); // why is this done here? the function name indicates only adding of signature
|
||||
}
|
||||
|
||||
bool License::isValid() const
|
||||
{
|
||||
@@ -372,15 +239,8 @@ bool License::isValid() const
|
||||
std::cout << "No public key loaded" << std::endl;
|
||||
return false;
|
||||
}
|
||||
try // lol, now we try to handle errors?
|
||||
try
|
||||
{
|
||||
// remove "Coati " in version 1
|
||||
if(!(Botan::check_passhash9("Coati "+ getVersion(), getHashLine())
|
||||
|| Botan::check_passhash9("Sourcetrail " + getVersion(), getHashLine())))
|
||||
{
|
||||
std::cout << "Wrong license version" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string signatureString = getSignature();
|
||||
if (signatureString.size() <= 0)
|
||||
@@ -422,42 +282,27 @@ bool License::isValid() const
|
||||
|
||||
bool License::isExpired() const
|
||||
{
|
||||
return (getTimeLeft()==-1);
|
||||
std::string expire = getVersionLineWithoutPrefix();
|
||||
if ( getLine(TYPE_LINE) == LicenseConstants::TEST_LICENSE_STRING)
|
||||
{
|
||||
return (getTimeLeft()==-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
Version version = Version::fromShortString(expire);
|
||||
return Version::getApplicationVersion() > version;
|
||||
}
|
||||
}
|
||||
|
||||
std::string License::getPublicKeyFilename() const
|
||||
{
|
||||
if(m_publicKeyFilename.empty())
|
||||
{
|
||||
return "public-" + getVersion() + KEY_FILEENDING;
|
||||
return "public-sourcetrail" + KEY_FILEENDING;
|
||||
}
|
||||
return m_publicKeyFilename;
|
||||
}
|
||||
|
||||
std::string License::getVersion() const
|
||||
{
|
||||
if(m_version.empty())
|
||||
{
|
||||
|
||||
std::string line = getVersionLine();
|
||||
|
||||
//TODO: remove "Coati " in version 1
|
||||
const std::array<std::string, 2> appNames = {{ "Coati ", "Sourcetrail " }};
|
||||
|
||||
for ( std::string appName : appNames)
|
||||
{
|
||||
if (line.substr(0,appName.length()) == appName)
|
||||
{
|
||||
return line.substr(appName.length());
|
||||
}
|
||||
}
|
||||
|
||||
return "x";
|
||||
}
|
||||
return m_version;
|
||||
}
|
||||
|
||||
|
||||
bool License::loadPublicKeyFromFile(const std::string& filename)
|
||||
{
|
||||
if (!filename.empty())
|
||||
@@ -638,3 +483,21 @@ std::string License::getEncodeKey(const std::string applicationLocation) const
|
||||
Botan::AutoSeeded_RNG rng;
|
||||
return pbkdf->derive_key(32, applicationLocation, &salt[0], salt.size(), 10000).as_string();
|
||||
}
|
||||
|
||||
void License::setSignature(const std::string& signature)
|
||||
{
|
||||
std::stringstream ss;
|
||||
int line = FIRST_SIGNATURE_LINE;
|
||||
const int lineLength = 55;
|
||||
for (size_t i = 0; i < signature.size(); i++)
|
||||
{
|
||||
if(i % lineLength == 0 && i != 0)
|
||||
{
|
||||
m_lines[line++] = ss.str();
|
||||
ss.str("");
|
||||
}
|
||||
ss << signature[i];
|
||||
}
|
||||
|
||||
m_lines[line] = ss.str();
|
||||
}
|
||||
|
||||
+32
-14
@@ -4,6 +4,7 @@
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
|
||||
namespace Botan
|
||||
{
|
||||
@@ -12,19 +13,39 @@ namespace Botan
|
||||
class AutoSeeded_RNG;
|
||||
}
|
||||
|
||||
namespace LicenseConstants {
|
||||
const std::string UNTIL_PREFIX = "Valid until ";
|
||||
const std::string TEST_LICENSE_STRING = "Test License";
|
||||
const int MINOR_VERSIONS_PER_YEAR = 4;
|
||||
}
|
||||
|
||||
class License
|
||||
{
|
||||
public:
|
||||
enum LICENSE_LINE
|
||||
{
|
||||
BEGIN_LICENSE_LINE = 0,
|
||||
OWNER_LINE = 1,
|
||||
SOURCETRAIL_LINE = 2,
|
||||
TYPE_LINE = 3,
|
||||
VERSION_LINE = 4,
|
||||
SEATS_LINE=5,
|
||||
HASH_LINE = 6,
|
||||
FIRST_SIGNATURE_LINE = 7,
|
||||
LAST_SIGNATURE_LINE = 13,
|
||||
END_LICENSE_LINE = 14,
|
||||
LICENSE_LINES = 15
|
||||
};
|
||||
|
||||
License();
|
||||
~License();
|
||||
|
||||
std::string getHashLine() const;
|
||||
std::string getMessage() const;
|
||||
std::string getSignature() const;
|
||||
std::string getVersionLine() const;
|
||||
std::string getOwnerLine() const;
|
||||
std::string getLicenseTypeLine() const;
|
||||
std::string getLicenseType() const;
|
||||
std::string getVersionLineWithoutPrefix() const;
|
||||
std::string getLine(LICENSE_LINE line) const;
|
||||
|
||||
void setLine(const LICENSE_LINE line, const std::string& value);
|
||||
|
||||
std::string getLicenseInfo() const;
|
||||
std::string getPublicKeyFilename() const;
|
||||
@@ -35,12 +56,6 @@ public:
|
||||
/// for non Test License -2
|
||||
int getTimeLeft() const;
|
||||
|
||||
void create(
|
||||
const std::string& user, const std::string& version,
|
||||
Botan::RSA_PrivateKey* privateKey, const std::string& type="Private License",
|
||||
const unsigned int seats = 0
|
||||
);
|
||||
|
||||
std::string getLicenseString() const;
|
||||
std::string getLicenseEncodedString(const std::string& applicationLocation) const;
|
||||
std::string getHashedLicense() const;
|
||||
@@ -55,6 +70,7 @@ public:
|
||||
|
||||
bool loadPublicKeyFromString(const std::string&);
|
||||
void setVersion(const std::string&);
|
||||
void setSignature(const std::string&);
|
||||
|
||||
bool isValid() const;
|
||||
bool isExpired() const;
|
||||
@@ -66,7 +82,8 @@ public:
|
||||
|
||||
private:
|
||||
void createMessage(const std::string& user, const std::string& version, const std::string& type = 0);
|
||||
void addSignature(const std::string&);
|
||||
void pushTodaysVersion();
|
||||
void pushVersionLine(int year, int minorVersion);
|
||||
std::string getEncodeKey(const std::string applicationLocation) const;
|
||||
|
||||
bool isNonCommercialLicenseType(const std::string type) const;
|
||||
@@ -74,8 +91,9 @@ private:
|
||||
std::string m_version;
|
||||
std::string m_publicKeyFilename;
|
||||
std::shared_ptr<Botan::RSA_PublicKey> m_publicKey;
|
||||
std::vector<std::string> m_lines;
|
||||
std::shared_ptr<Botan::AutoSeeded_RNG> m_rng; // range?
|
||||
// std::vector<std::string> m_lines;
|
||||
std::array<std::string, LICENSE_LINES> m_lines;
|
||||
std::shared_ptr<Botan::AutoSeeded_RNG> m_rng;
|
||||
|
||||
const std::string KEY_FILEENDING = ".pem";
|
||||
const std::string BEGIN_LICENSE = "-----BEGIN LICENSE-----";
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
#include "utility/Version.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
// since there are 4 version per year it is on digit
|
||||
const int MINOR_VERSION_SHIFT = 10;
|
||||
|
||||
Version Version::s_version;
|
||||
|
||||
#include <iostream>
|
||||
Version Version::fromShortString(const std::string& versionString)
|
||||
{
|
||||
Version version;
|
||||
if (versionString.length() != 6 || versionString[4] != '.')
|
||||
{
|
||||
return version;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
version.m_year = std::stoi(versionString.substr(0,4));
|
||||
version.m_minorNumber = std::stoi(versionString.substr(5));
|
||||
}
|
||||
catch (std::invalid_argument e)
|
||||
{
|
||||
return Version();
|
||||
}
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
bool Version::operator<(const Version& other) const
|
||||
{
|
||||
return (m_year * MINOR_VERSION_SHIFT + m_minorNumber) < (other.m_year * MINOR_VERSION_SHIFT + other.m_minorNumber);
|
||||
}
|
||||
|
||||
bool Version::operator>(const Version& other) const
|
||||
{
|
||||
return (m_year * MINOR_VERSION_SHIFT + m_minorNumber) > (other.m_year * MINOR_VERSION_SHIFT + other.m_minorNumber);
|
||||
}
|
||||
|
||||
Version& Version::operator +=(const int& number)
|
||||
{
|
||||
int minor = this->m_minorNumber - 1 + number;
|
||||
this->m_year += minor/4;
|
||||
this->m_minorNumber = (minor%4) + 1;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool Version::isValid()
|
||||
{
|
||||
if (m_minorNumber < 5 && m_minorNumber > 0
|
||||
&& m_year > 2016)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Version::setApplicationVersion(const Version& version)
|
||||
{
|
||||
s_version = version;
|
||||
}
|
||||
|
||||
const Version& Version::getApplicationVersion()
|
||||
{
|
||||
return s_version;
|
||||
}
|
||||
|
||||
Version::Version(int year, int minor, int commit, const std::string& hash)
|
||||
: m_year(year)
|
||||
, m_minorNumber(minor)
|
||||
, m_commitNumber(commit)
|
||||
, m_commitHash(hash)
|
||||
{
|
||||
}
|
||||
|
||||
bool Version::isEmpty() const
|
||||
{
|
||||
return m_year == 0 && m_minorNumber == 0 && m_commitNumber == 0;
|
||||
}
|
||||
|
||||
std::string Version::toShortString() const
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << m_year << '.' << m_minorNumber;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string Version::toString() const
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << m_year << '.' << m_minorNumber;
|
||||
ss << '-' << m_commitNumber << '-' << m_commitHash;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string Version::toDisplayString() const
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << m_year << '.' << m_minorNumber;
|
||||
ss << '.' << m_commitNumber;
|
||||
return ss.str();
|
||||
}
|
||||
@@ -3,27 +3,33 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
|
||||
class Version
|
||||
{
|
||||
public:
|
||||
static Version fromString(const std::string& versionString);
|
||||
static Version fromShortString(const std::string& versionString);
|
||||
|
||||
static void setApplicationVersion(const Version& version);
|
||||
static const Version& getApplicationVersion();
|
||||
|
||||
Version();
|
||||
Version(int year = 0, int minor = 0, int commit = 0, const std::string& hash = "");
|
||||
|
||||
bool isEmpty() const;
|
||||
|
||||
std::string toString() const;
|
||||
std::string toShortString() const;
|
||||
std::string toDisplayString() const;
|
||||
|
||||
bool operator<(const Version& other) const;
|
||||
bool operator>(const Version& other) const;
|
||||
Version& operator+=(const int& number);
|
||||
bool isValid();
|
||||
private:
|
||||
static Version s_version;
|
||||
|
||||
int m_majorNumber;
|
||||
int m_year;
|
||||
int m_minorNumber;
|
||||
int m_refreshNumber; // deprecated since switch to storage_version, left for downward compatibility
|
||||
int m_commitNumber;
|
||||
|
||||
std::string m_commitHash;
|
||||
@@ -1,5 +1,13 @@
|
||||
add_files(
|
||||
LICENSE_GENERATOR_FILES
|
||||
|
||||
Generator.cpp
|
||||
Generator.h
|
||||
)
|
||||
|
||||
# split for tests
|
||||
add_files(
|
||||
LICENSE_GENERATOR_MAIN
|
||||
|
||||
main.cpp
|
||||
)
|
||||
|
||||
@@ -9,12 +9,25 @@
|
||||
#include "botan/pk_keys.h"
|
||||
#include "botan/pkcs8.h"
|
||||
#include "botan/rsa.h"
|
||||
#include "botan/pbkdf.h"
|
||||
#include "botan/pubkey.h"
|
||||
#include "botan/passhash9.h"
|
||||
#include "botan/base64.h"
|
||||
#include "botan/auto_rng.h"
|
||||
|
||||
#include "License.h"
|
||||
#include "utility/Version.h"
|
||||
#include "PrivateKey.h"
|
||||
#include "PublicKey.h"
|
||||
|
||||
Generator::Generator(const std::string& version)
|
||||
: m_version(version)
|
||||
const std::string KEY_FILEENDING = ".pem";
|
||||
const std::string 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()
|
||||
@@ -23,14 +36,14 @@ Generator::~Generator()
|
||||
|
||||
void Generator::generateKeys()
|
||||
{
|
||||
m_privateKey = std::make_shared<Botan::RSA_PrivateKey>(m_rng, 2048);
|
||||
m_privateKey = std::unique_ptr<Botan::RSA_PrivateKey>(new Botan::RSA_PrivateKey(m_rng, 2048));
|
||||
}
|
||||
|
||||
std::string Generator::getPrivateKeyFilename()
|
||||
{
|
||||
if(m_privateKeyFile.empty())
|
||||
{
|
||||
return "private-" + m_version + KEY_FILEENDING;
|
||||
return PRIVATE_KEY_FILE;
|
||||
}
|
||||
return m_privateKeyFile;
|
||||
}
|
||||
@@ -39,31 +52,30 @@ std::string Generator::getPublicKeyFilename()
|
||||
{
|
||||
if(m_publicKeyFile.empty())
|
||||
{
|
||||
return "public-" + m_version + KEY_FILEENDING;
|
||||
return PUBLIC_KEY_FILE;
|
||||
}
|
||||
return m_publicKeyFile;
|
||||
}
|
||||
|
||||
void Generator::setVersion(const std::string& version)
|
||||
{
|
||||
if(!version.empty())
|
||||
{
|
||||
m_version = version;
|
||||
}
|
||||
}
|
||||
|
||||
std::string Generator::encodeLicense(const std::string& user, const int days)
|
||||
{
|
||||
boost::gregorian::date today = boost::gregorian::day_clock::local_day();
|
||||
boost::gregorian::days daysToTry(days);
|
||||
boost::gregorian::date expireDate = today + daysToTry;
|
||||
|
||||
std::string testLicenseTypeString = "Test License - valid till " + boost::gregorian::to_simple_string(expireDate);
|
||||
return encodeLicense(user, testLicenseTypeString);
|
||||
createLicense(user, LicenseConstants::TEST_LICENSE_STRING, boost::gregorian::to_simple_string(expireDate), 0);
|
||||
|
||||
return m_license->getLicenseString();
|
||||
}
|
||||
|
||||
std::string Generator::encodeLicense(const std::string& user, const std::string& licenseType, const int seats)
|
||||
std::string Generator::encodeLicense(
|
||||
const std::string& user,
|
||||
const std::string& licenseType,
|
||||
const int seats,
|
||||
const std::string& version
|
||||
)
|
||||
{
|
||||
m_license = nullptr;
|
||||
if (user.size() <= 0)
|
||||
{
|
||||
std::cout << "No user given" << std::endl;
|
||||
@@ -76,23 +88,21 @@ std::string Generator::encodeLicense(const std::string& user, const std::string&
|
||||
return "";
|
||||
}
|
||||
|
||||
//load private key
|
||||
if (!m_privateKey)
|
||||
if (!version.empty())
|
||||
{
|
||||
std::cout << "No private key. Trying to load from file." << std::endl;
|
||||
loadPrivateKeyFromFile();
|
||||
Version tempVersion = Version::fromShortString(version);
|
||||
if (tempVersion.isValid())
|
||||
{
|
||||
createLicense(user, licenseType, tempVersion.toShortString(), seats);
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_privateKey)
|
||||
if (!m_license)
|
||||
{
|
||||
std::cout << "No private key. Load from file or string." << std::endl;
|
||||
return "";
|
||||
createLicense(user, licenseType, getExpireVersion(), seats);
|
||||
}
|
||||
|
||||
|
||||
m_license = std::make_shared<License>();
|
||||
m_license->create(user, m_version, m_privateKey.get(), licenseType, seats);
|
||||
|
||||
return m_license->getLicenseString();
|
||||
}
|
||||
|
||||
@@ -113,8 +123,7 @@ bool Generator::verifyLicense(const std::string& filename)
|
||||
{
|
||||
License license;
|
||||
license.loadFromFile(filename);
|
||||
license.setVersion(m_version);
|
||||
license.loadPublicKeyFromFile(getPublicKeyFilename());
|
||||
license.loadPublicKeyFromString(PUBLIC_KEY);
|
||||
return license.isValid();
|
||||
}
|
||||
|
||||
@@ -194,7 +203,7 @@ bool Generator::loadPrivateKeyFromFile()
|
||||
return false;
|
||||
}
|
||||
|
||||
m_privateKey = std::shared_ptr<Botan::RSA_PrivateKey>(rsaKey);
|
||||
m_privateKey = std::unique_ptr<Botan::RSA_PrivateKey>(rsaKey);
|
||||
|
||||
return (m_privateKey != NULL);
|
||||
}
|
||||
@@ -217,7 +226,7 @@ bool Generator::loadPrivateKeyFromString(const std::string& key)
|
||||
return false;
|
||||
}
|
||||
|
||||
m_privateKey = std::shared_ptr<Botan::RSA_PrivateKey>(rsaKey);
|
||||
m_privateKey = std::unique_ptr<Botan::RSA_PrivateKey>(rsaKey);
|
||||
|
||||
return (m_privateKey != NULL);
|
||||
}
|
||||
@@ -227,3 +236,60 @@ 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,
|
||||
const unsigned int seats
|
||||
)
|
||||
{
|
||||
m_license = std::unique_ptr<License>(new License());
|
||||
|
||||
m_license->setLine(License::OWNER_LINE, user);
|
||||
m_license->setLine(License::TYPE_LINE, type);
|
||||
m_license->setLine(License::VERSION_LINE, LicenseConstants::UNTIL_PREFIX + expiration);
|
||||
if (seats > 1)
|
||||
{
|
||||
m_license->setLine(License::SEATS_LINE, std::to_string(seats) + " Seats");
|
||||
}
|
||||
else if (seats == 1)
|
||||
{
|
||||
m_license->setLine(License::SEATS_LINE, "1 Seat");
|
||||
}
|
||||
else
|
||||
{
|
||||
m_license->setLine(License::SEATS_LINE, "-");
|
||||
}
|
||||
Botan::AutoSeeded_RNG rng;
|
||||
std::string pass9 = Botan::generate_passhash9(m_license->getLine(License::VERSION_LINE), m_rng);
|
||||
m_license->setLine(License::HASH_LINE, 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 versions)
|
||||
{
|
||||
boost::gregorian::date today = boost::gregorian::day_clock::local_day();
|
||||
int monthNumber = today.month().as_number();
|
||||
Version version(today.year(), mapMonthToVersion(monthNumber));
|
||||
version += versions;
|
||||
return version.toShortString();
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
#define KEYGEN_H
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
//#include "botan_all.h"
|
||||
#include "botan/auto_rng.h"
|
||||
|
||||
namespace Botan
|
||||
@@ -15,16 +15,23 @@ class License;
|
||||
class Generator
|
||||
{
|
||||
public:
|
||||
Generator(const std::string& version = "x");
|
||||
Generator();
|
||||
~Generator();
|
||||
|
||||
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);
|
||||
std::string encodeLicense(
|
||||
const std::string& user,
|
||||
const std::string& licenseType,
|
||||
const int seats = 0,
|
||||
const std::string& version = ""
|
||||
);
|
||||
std::string encodeLicense(
|
||||
const std::string& user,
|
||||
const int days
|
||||
);
|
||||
void printLicenseAndWriteItToFile();
|
||||
bool verifyLicense(const std::string& filename = "license.txt");
|
||||
void generateKeys();
|
||||
void writeKeysToFiles();
|
||||
void setVersion(const std::string& version);
|
||||
void setCustomPrivateKeyFile(const std::string& file);
|
||||
void setCustomPublicKeyFile(const std::string& file);
|
||||
|
||||
@@ -33,25 +40,29 @@ public:
|
||||
bool loadPrivateKeyFromFile();
|
||||
bool loadPrivateKeyFromString(const std::string& key);
|
||||
|
||||
// void PrintLicense(); // not implemented, is this deprecated or something?
|
||||
|
||||
Botan::RSA_PrivateKey* getPrivateKey() const;
|
||||
void createLicense(
|
||||
const std::string& user,
|
||||
const std::string& type,
|
||||
const std::string& expiration,
|
||||
const unsigned int seates
|
||||
);
|
||||
|
||||
std::string getExpireVersion(int versions = 4);
|
||||
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_version;
|
||||
std::string m_privateKeyFile;
|
||||
std::string m_publicKeyFile;
|
||||
std::shared_ptr<License> m_license;
|
||||
std::shared_ptr<Botan::RSA_PrivateKey> m_privateKey;
|
||||
std::unique_ptr<License> m_license;
|
||||
std::unique_ptr<Botan::RSA_PrivateKey> m_privateKey;
|
||||
|
||||
const std::string PRIVATE_KEY_PASSWORD = "BA#jk5vbklAiKL9K3k$";
|
||||
const std::string KEY_FILEENDING = ".pem";
|
||||
};
|
||||
|
||||
#endif // KEYGEN_H
|
||||
@@ -6,6 +6,8 @@
|
||||
#include "boost/program_options.hpp"
|
||||
|
||||
#include "Generator.h"
|
||||
#include "PrivateKey.h"
|
||||
#include "PublicKey.h"
|
||||
|
||||
namespace po = boost::program_options;
|
||||
|
||||
@@ -28,12 +30,9 @@ bool process_command_line(int argc, char** argv)
|
||||
("generate,g", po::value<std::string>(&user), "Generate a License, USERNAME as value")
|
||||
("check,c", "Validate a License");
|
||||
|
||||
po::options_description required("Required Options");
|
||||
required.add_options()
|
||||
("version,v", po::value<std::string>(&version), "Versionnumber of Sourcetrail");
|
||||
|
||||
po::options_description keygen_description("Options Keygeneration");
|
||||
keygen_description.add_options()
|
||||
("version,v", po::value<std::string>(&version), "Versionnumber (in format 20xx.x) until Sourcetrail valid")
|
||||
("seats,s", po::value<int>(&seats), "Generate a License, USERNAME as value")
|
||||
("licenseType,t", po::value<std::string>(&type), "License Type of ")
|
||||
("testLicense,e", po::value<int>(&days), "Generates a test license for <value> days");
|
||||
@@ -48,11 +47,11 @@ bool process_command_line(int argc, char** argv)
|
||||
po::options_description desc("Sourcetrail Generator");
|
||||
desc.add_options()
|
||||
("help,h", "Print this help message");
|
||||
desc.add(modes_description).add(required).add(keygen_description);
|
||||
desc.add(modes_description).add(keygen_description);
|
||||
|
||||
po::options_description allDescriptions("Sourcetrail Generator");
|
||||
allDescriptions.add_options();
|
||||
allDescriptions.add(modes_description).add(required).add(keygen_description).add(hidden_description);
|
||||
allDescriptions.add(modes_description).add(keygen_description).add(hidden_description);
|
||||
|
||||
po::variables_map vm;
|
||||
|
||||
@@ -82,15 +81,7 @@ bool process_command_line(int argc, char** argv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
// we need a version for all modes
|
||||
// if no version is given there is nothing to do
|
||||
if (!vm.count("version"))
|
||||
{
|
||||
std::cout << "No version specified" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
Generator keygen(version);
|
||||
Generator keygen;
|
||||
|
||||
// make sure there are no negative amount of seats
|
||||
if (vm.count("seats"))
|
||||
@@ -117,17 +108,21 @@ bool process_command_line(int argc, char** argv)
|
||||
{
|
||||
keygen.setCustomPrivateKeyFile(privateKeyFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
keygen.loadPrivateKeyFromString(PRIVATE_KEY);
|
||||
}
|
||||
|
||||
if(vm.count("generate"))
|
||||
{
|
||||
if(vm.count("testLicense"))
|
||||
{
|
||||
keygen.encodeLicense(user,days);
|
||||
keygen.encodeLicense(user,days);
|
||||
keygen.printLicenseAndWriteItToFile();
|
||||
}
|
||||
else
|
||||
{
|
||||
keygen.encodeLicense(user,type,seats);
|
||||
keygen.encodeLicense(user,type,seats,version);
|
||||
keygen.printLicenseAndWriteItToFile();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ public:
|
||||
|
||||
void test_create_Keys_with_Version_and_check()
|
||||
{
|
||||
Generator generator("v0");
|
||||
Generator generator;
|
||||
generator.generateKeys();
|
||||
|
||||
std::string privateKey = generator.getPrivateKeyPEMFileAsString();
|
||||
@@ -21,7 +21,7 @@ public:
|
||||
|
||||
void test_load_private_Key_from_file()
|
||||
{
|
||||
Generator generator("v2");
|
||||
Generator generator;
|
||||
generator.setCustomPrivateKeyFile("./data/GeneratorTestSuite/private-v2.pem");
|
||||
bool ok = generator.loadPrivateKeyFromFile();
|
||||
|
||||
@@ -30,7 +30,7 @@ public:
|
||||
|
||||
void test_load_private_key_from_string()
|
||||
{
|
||||
Generator generator("v0");
|
||||
Generator generator;
|
||||
bool ok = generator.loadPrivateKeyFromString(m_privateKey);
|
||||
|
||||
TS_ASSERT(ok);
|
||||
@@ -38,12 +38,14 @@ public:
|
||||
|
||||
void test_create_volume_license_and_validate()
|
||||
{
|
||||
Generator generator("v2");
|
||||
Generator generator;
|
||||
generator.generateKeys();
|
||||
generator.loadPrivateKeyFromString(generator.getPrivateKeyPEMFileAsString());
|
||||
|
||||
License license;
|
||||
license.create("TestUser", "v2", generator.getPrivateKey(), "Volume License", 20);
|
||||
License license;
|
||||
license.loadFromString(generator.encodeLicense("TestUser", "VolumeLicense", 20));
|
||||
|
||||
// license.create(generator.getPrivateKey(), "TestUser", "v2", "Volume License", 20);
|
||||
license.loadPublicKeyFromString(generator.getPublicKeyPEMFileAsString());
|
||||
|
||||
TS_ASSERT_EQUALS(license.getSeats(), 20);
|
||||
@@ -51,7 +53,7 @@ public:
|
||||
|
||||
void test_create_test_license_and_validate()
|
||||
{
|
||||
Generator generator("v2");
|
||||
Generator generator;
|
||||
generator.generateKeys();
|
||||
generator.loadPrivateKeyFromString(generator.getPrivateKeyPEMFileAsString());
|
||||
|
||||
@@ -61,7 +63,7 @@ public:
|
||||
|
||||
TS_ASSERT(license.isValid());
|
||||
TS_ASSERT_EQUALS(license.getTimeLeft(), 10);
|
||||
TS_ASSERT_EQUALS(license.getVersion(), "v2");
|
||||
// TS_ASSERT_EQUALS(license.getVersion(), "v2");
|
||||
|
||||
license.loadPublicKeyFromString(generator.getPublicKeyPEMFileAsString());
|
||||
license.loadFromString(generator.encodeLicense("User", -10));
|
||||
@@ -73,39 +75,39 @@ public:
|
||||
|
||||
void test_create_licenses_and_check_the_license_info()
|
||||
{
|
||||
Generator generator("v2");
|
||||
Generator generator;
|
||||
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";
|
||||
license.loadFromString(generator.encodeLicense("TestUser", "Private License", 1, "2017.4"));
|
||||
// license.create(generator.getPrivateKey(), "TestUser", "v2");
|
||||
std::string testInfo = "TestUser\nPrivate License\nValid until 2017.4\n1 Seat";
|
||||
TS_ASSERT_EQUALS(license.getLicenseInfo(), testInfo);
|
||||
|
||||
license.create("TestUser", "v2", generator.getPrivateKey(), "Volume License", 20);
|
||||
testInfo = "TestUser\nVolume License\n20 Seats";
|
||||
// license.create(generator.getPrivateKey(), "TestUser", "v2", "Volume License", 20);
|
||||
license.loadFromString(generator.encodeLicense("TestUser", "Volume License", 20, "2017.3"));
|
||||
testInfo = "TestUser\nVolume License\nValid until 2017.3\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";
|
||||
// license.create(generator.getPrivateKey(), "TestUser", "v2", "Private/Academic Single User License", 20);
|
||||
license.loadFromString(generator.encodeLicense("TestUser", "Private/Academic Single User License", 0, "2018.1"));
|
||||
testInfo = "TestUser\nPrivate/Academic Single User License\nValid until 2018.1\nnot registered for commercial development";
|
||||
TS_ASSERT_EQUALS(license.getLicenseInfo(), testInfo);
|
||||
}
|
||||
|
||||
void test_create_license_and_validate()
|
||||
{
|
||||
Generator generator("v2");
|
||||
Generator generator;
|
||||
generator.generateKeys();
|
||||
|
||||
generator.loadPrivateKeyFromString(generator.getPrivateKeyPEMFileAsString());
|
||||
License license;
|
||||
license.create("TestUser", "v2", generator.getPrivateKey());
|
||||
license.loadFromString(generator.encodeLicense("TestUser", "Private License", 20, "2017.3"));
|
||||
license.loadPublicKeyFromString(generator.getPublicKeyPEMFileAsString());
|
||||
|
||||
TS_ASSERT_EQUALS(license.getOwnerLine(), "TestUser");
|
||||
TS_ASSERT_EQUALS(license.getLicenseTypeLine(), "Private License");
|
||||
TS_ASSERT_EQUALS(license.getVersion(), "v2");
|
||||
TS_ASSERT_EQUALS(license.getLine(License::OWNER_LINE), "TestUser");
|
||||
TS_ASSERT_EQUALS(license.getLine(License::TYPE_LINE), "Private License");
|
||||
TS_ASSERT(license.isValid());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user