gcontini
2019-10-19 497745ad31c90545b288e2845049e0ce474bcbe2
Merge branch 'feature/code_review_and_refactor' into develop
34个文件已修改
19个文件已添加
2个文件已删除
2444 ■■■■ 已修改文件
.gitignore 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CONTRIBUTING.md 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
README.md 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
example/CMakeLists.txt 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
example/example.cpp 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/build_properties.h.in 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/CMakeLists.txt 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/LicenseReader.cpp 230 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/LicenseReader.h 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/LicenseReader.hpp 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/api/Licensepp-features.h 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/api/datatypes.h 39 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/api/license++.h 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/base/CMakeLists.txt 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/base/EventRegistry.cpp 152 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/base/EventRegistry.h 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/base/FileUtils.cpp 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/base/FileUtils.hpp 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/base/StringUtils.cpp 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/base/StringUtils.h 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/base/base.h 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/base/base64.c 133 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/base/base64.h 140 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/license++.cpp 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/locate/ApplicationFolder.cpp 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/locate/ApplicationFolder.hpp 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/locate/CMakeLists.txt 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/locate/EnvironmentVarData.cpp 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/locate/EnvironmentVarData.hpp 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/locate/EnvironmentVarLocation.cpp 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/locate/EnvironmentVarLocation.hpp 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/locate/ExternalDefinition.cpp 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/locate/ExternalDefinition.hpp 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/locate/LocatorFactory.cpp 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/locate/LocatorFactory.hpp 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/locate/LocatorStrategy.cpp 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/locate/LocatorStrategy.hpp 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/library/os/os.h 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tools/base_lib/win/CryptoHelperWindows.cpp 补丁 | 查看 | 原始文档 | blame | 历史
src/tools/base_lib/win/CryptoHelperWindows.h 补丁 | 查看 | 原始文档 | blame | 历史
src/tools/license-generator/CMakeLists.txt 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tools/license-generator/license-generator.cpp 111 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tools/license-generator/license-generator.h 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
test/functional/CMakeLists.txt 30 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
test/functional/date_test.cpp 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
test/functional/generate-license.cpp 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
test/functional/generate-license.h 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
test/functional/hijiaking_test.cpp 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
test/functional/standard-license_test.cpp 50 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
test/functional/volid_test.cpp 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
test/library/CMakeLists.txt 54 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
test/library/EventRegistry_test.cpp 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
test/library/LicenseLocator_test.cpp 217 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
test/library/LicenseReader_test.cpp 91 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
test/license-generator/license-generator_test.cpp 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.gitignore
@@ -7,6 +7,9 @@
*.so
*.dylib
#Visual studio files
.vs
# Compiled Static libraries
*.lai
*.la
@@ -22,3 +25,4 @@
.settings
.project
*.out
/Default/
CONTRIBUTING.md
@@ -18,7 +18,8 @@
* **Use a clear and descriptive title** for the issue to identify the problem.
* **Describe the exact steps which reproduce the problem** in as many details as possible. For example, start by explaining how are you using Open License Manager. 
* **Provide specific examples to demonstrate the steps**. Include links to files or GitHub projects, or licenses, which can cause the bug. If you're providing code snippets in the issue, use [Markdown code blocks](https://help.github.com/articles/markdown-basics/#multiple-lines). The best way to report a bug is to **design a test** to demonstrate it.
* **Provide specific examples to demonstrate the steps**. Include links to files or GitHub projects, or licenses, which can cause the bug. If you're providing code snippets in the issue, use [Markdown code blocks](https://help.github.com/articles/markdown-basics/#multiple-lines).
* **Provide a boost unit test to demonstrate the bug**. The best way to report a bug, and to have it fixed **forever** is to design a test to demonstrate it.
* **If you're reporting that Open License Manager crashed**, include a crash dump and the associated message. 
* **Label the issue as bug.**
@@ -79,8 +80,8 @@
##### Don't
 * Don't reformat the code following your personal likes, it introduce a lot of "noise" and makes very hard to merge. 
 * Very large pull requests with few comments, no corresponding issue will probably be rejected.
    * We understand that the project is still in a very alpha stage and a rearrangement is needed, however we would like to discuss it with you before we take project changing decision.
    * We can't break current functionality, user established habits without documenting the change.
 * Very large pull requests with few comments, no corresponding issue explaining what's it about will probably be rejected.
    * We understand that the project is still in a very alpha stage and a rearrangement is needed, however we would like to discuss it with you before we take project changing decision. Please contact the project maintainer at `contini.mailing[AT]gmail.com` if you have time and plan to do a large contribution.
    * Even it it's in alpha stage it's used ( _by some really courageous people!_ ) in production. We can't break current functionality, user established habits without documenting the change.
  
README.md
@@ -2,7 +2,7 @@
[![Build Status](https://travis-ci.org/open-license-manager/open-license-manager.svg?branch=develop)](https://travis-ci.org/open-license-manager/open-license-manager)
[![experimental](http://badges.github.io/stability-badges/dist/experimental.svg)](http://github.com/badges/stability-badges)[![License](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause)
A copy protection, licensing software written in C/C++ for Windows and Linux.
A copy protection, licensing software written in C++ for Windows and Linux (with a simple C api for use in C projects).
It allows to protect the software you develop from unauthorized copies,
limit the usage in time, to a specific set of machines, or prevent the usage in 
example/CMakeLists.txt
@@ -1,4 +1,3 @@
#cmake_minimum_required(VERSION 3.0)
cmake_minimum_required(VERSION 2.8.11)
link_directories (   "${CMAKE_CURRENT_SOURCE_DIR}/../install/lib" )
@@ -10,7 +9,7 @@
SET(CMAKE_FIND_LIBRARY_SUFFIXES .lib )
else(MSVC)
set(CMAKE_FIND_LIBRARY_SUFFIXES .a .so)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s -Wl,--exclude-libs,liblicensepp_static.a")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s -Wl,--exclude-libs,liblicensecc_static.a")
find_package(OpenSSL REQUIRED)
endif(MSVC)
@@ -18,7 +17,7 @@
add_executable(example example.cpp)
target_link_libraries(example licensepp_static os base tools_base)
target_link_libraries(example licensecc_static os base tools_base)
if(NOT MSVC)
target_link_libraries(example crypto pthread dl z)
example/example.cpp
@@ -2,12 +2,10 @@
#include <map>
#include "api/license++.h"
#include "pc-identifiers.h"
#include "ini/SimpleIni.h"
using namespace std;
int main(int argc, char *argv[])
{
int main(int argc, char *argv[]) {
    map<EVENT_TYPE, string> stringByEventType;
    stringByEventType[LICENSE_OK                      ] = "OK ";
    stringByEventType[LICENSE_FILE_NOT_FOUND          ] = "license file not found ";
@@ -19,38 +17,31 @@
    stringByEventType[PRODUCT_EXPIRED                 ] = "license expired ";
    stringByEventType[LICENSE_CORRUPTED               ] = "license signature didn't match with current license ";
    stringByEventType[IDENTIFIERS_MISMATCH            ] = "Calculated identifier and the one provided in license didn't match";
    stringByEventType[LICENSE_FILE_FOUND              ] = "license file not found ";
    stringByEventType[LICENSE_VERIFIED                ] = "license verified ";
    const string licLocation("example.lic");
    
    LicenseInfo licenseInfo;
    LicenseLocation licenseLocation;
    licenseLocation.openFileNearModule = false;
    licenseLocation.licenseFileLocation = licLocation.c_str();
    licenseLocation.environmentVariableName = "";
    EVENT_TYPE result = acquire_license("example", licenseLocation, &licenseInfo);
    PcSignature signature;
    FUNCTION_RETURN generate_ok = generate_user_pc_signature(signature, DEFAULT);
    EVENT_TYPE result = acquire_license("example", nullptr, &licenseInfo);
    if (result == LICENSE_OK && licenseInfo.linked_to_pc) {
        CSimpleIniA ini;
        SI_Error rc = ini.LoadFile(licLocation.c_str());
        string IDinLicense = ini.GetValue("example", "client_signature", "");
        if (IDinLicense == "") {
            cout << "No client signature in license file, generate license with -s <id>";
    if (result == LICENSE_OK) {
        //for this example we want to link the license to the execution hardware.
        if (licenseInfo.linked_to_pc) {
            cout
                    << "No client signature in license file, generate license with -s <id>";
            result = IDENTIFIERS_MISMATCH;
        } else if (IDinLicense != signature) {
            result = IDENTIFIERS_MISMATCH;
        } else {
            cout << "license OK" << endl;
        }
    }
    if (result != LICENSE_OK) {
        cout << "license ERROR :" << endl;
        cout << "    " << stringByEventType[result].c_str() << endl;
        if (result == IDENTIFIERS_MISMATCH) {
            PcSignature signature;
            FUNCTION_RETURN generate_ok = generate_user_pc_signature(signature,
                    DEFAULT);
        cout << "the pc signature is :" << endl;
        cout << "    " << signature << endl;
    }
    else
        cout << "license OK" << endl;
    }
    return result;
}
src/build_properties.h.in
@@ -1,12 +1,24 @@
#ifndef BUILD_PROPERTIES_H_
#define BUILD_PROPERTIES_H_
//License retrieval configuration
#define FIND_LICENSE_NEAR_MODULE 1
#define FIND_LICENSE_WITH_ENV_VAR 1
#define LICENSE_LOCATION_ENV_VAR "LICENSE_LOCATION"
#define LICENSE_DATA_ENV_VAR "LICENSE_DATA"
//Internal data structures limits
#define MAX_LICENSE_LENGTH 256*1024
//Build locations and parameters
#define PROJECT_INT_VERSION @LICENSECC_INT_VERSION@
#define PROJECT_VERSION "@LICENSECC_VERSION@"
#define PROJECT_BINARY_DIR "@CMAKE_BINARY_DIR@"
#define PROJECT_SRC_DIR "@CMAKE_CURRENT_LIST_DIR@"
#define PROJECT_BASE_DIR "@CMAKE_SOURCE_DIR@"
#define PROJECT_TEST_SRC_DIR "@CMAKE_SOURCE_DIR@/test"
#define PROJECT_TEST_TEMP_DIR "Testing/Temporary"
#define PROJECT_TEST_TEMP_DIR "@CMAKE_BINARY_DIR@/Testing/Temporary"
#define BUILD_TYPE "@CMAKE_BUILD_TYPE@"
#endif
src/library/CMakeLists.txt
@@ -1,20 +1,24 @@
add_subdirectory("os")
add_subdirectory("base")
add_subdirectory("ini")
add_subdirectory("locate")
ADD_LIBRARY(licensepp_static STATIC
ADD_LIBRARY(licensecc_static STATIC
    license++.cpp
    LicenseReader.cpp
    pc-identifiers.c
)
target_link_libraries(
     licensepp_static
     licensecc_static
     ini
     locators
     os
     base
)
install(TARGETS licensepp_static ARCHIVE DESTINATION lib)
install(TARGETS licensecc_static ARCHIVE DESTINATION lib)
install(FILES api/datatypes.h api/license++.h DESTINATION include/api)
install(FILES base/base.h DESTINATION include/base)
install(FILES pc-identifiers.h DESTINATION include/)
src/library/LicenseReader.cpp
@@ -10,6 +10,7 @@
#else
# include <unistd.h>
#endif
#include <cstring>
#include <ctime>
#include <vector>
@@ -17,14 +18,17 @@
#include <iterator>
#include <fstream>
#include <sstream>
#include <stdlib.h>
#include <math.h>
#include "pc-identifiers.h"
#include "LicenseReader.h"
#include "build_properties.h"
#include "public-key.h"
#include "LicenseReader.hpp"
#include "base/StringUtils.h"
#include "base/logger.h"
#include "public-key.h"
#include <build_properties.h>
#include "locate/LocatorFactory.hpp"
namespace license {
@@ -48,35 +52,42 @@
        extra_data(extra_data) {
}
EventRegistry FullLicenseInfo::validate(int sw_version) {
    EventRegistry er;
bool FullLicenseInfo::validate(int sw_version,
        EventRegistry &eventRegistryOut) {
    os_initialize();
    const FUNCTION_RETURN sigVer = verifySignature(printForSign().c_str(),
            license_signature.c_str());
    const bool sigVerified = sigVer == FUNC_RET_OK;
    if (sigVerified) {
        er.addEvent(LICENSE_VERIFIED, SVRT_INFO);
    bool is_valid = (sigVer == FUNC_RET_OK);
    if (is_valid) {
        eventRegistryOut.addEvent(SIGNATURE_VERIFIED, source);
    } else {
        er.addEvent(LICENSE_CORRUPTED, SVRT_ERROR);
        eventRegistryOut.addEvent(LICENSE_CORRUPTED, source);
    }
    if (has_expiry) {
        cout<<source<<endl;
        const time_t now = time(nullptr);
        if (expires_on() < now) {
            er.addEvent(PRODUCT_EXPIRED, SVRT_ERROR, "");
/*
            eventRegistryOut.addEvent(PRODUCT_EXPIRED, source.c_str(),
                    string("Expired on: " + this->to_date).c_str());*/
            eventRegistryOut.addEvent(PRODUCT_EXPIRED, source.c_str(),nullptr);
            is_valid = false;
        }
        if (valid_from() > now) {
            er.addEvent(PRODUCT_EXPIRED, SVRT_ERROR);
            /*eventRegistryOut.addEvent(PRODUCT_EXPIRED, source.c_str(),
                    string("Valid from " + this->from_date).c_str());*/
            eventRegistryOut.addEvent(PRODUCT_EXPIRED, source.c_str(),nullptr);
            is_valid = false;
        }
    }
    if (has_client_sig) {
        PcSignature str_code;
        strncpy(str_code, client_signature.c_str(), sizeof(str_code)-1);
        const EVENT_TYPE event = validate_pc_signature(str_code);
        if (event != LICENSE_OK) {
            er.addEvent(event, SVRT_ERROR);
        eventRegistryOut.addEvent(event, source);
        is_valid = is_valid && (event == LICENSE_OK);
        }
    }
    return er;
    return is_valid;
}
void FullLicenseInfo::toLicenseInfo(LicenseInfo* license) const {
@@ -91,45 +102,54 @@
            license->days_left = 999999;
        } else {
            strncpy(license->expiry_date, to_date.c_str(), 11);
            const double secs = difftime(
                seconds_from_epoch(to_date.c_str()),
            const double secs = difftime(seconds_from_epoch(to_date.c_str()),
                time(nullptr));
            license->days_left = round(secs / (60 * 60 * 24));
        }
    }
}
LicenseReader::LicenseReader(const LicenseLocation& licenseLocation) :
        licenseLocation(licenseLocation) {
LicenseReader::LicenseReader(const LicenseLocation* licenseLocation) :
        licenseLocation(licenseLocation) {
}
EventRegistry LicenseReader::readLicenses(const string &product,
        vector<FullLicenseInfo>& licenseInfoOut) {
    vector<string> diskFiles;
    EventRegistry result = getLicenseDiskFiles(diskFiles);
    if (!result.isGood()) {
        return result;
    vector<unique_ptr<locate::LocatorStrategy>> locator_strategies;
    FUNCTION_RETURN ret = locate::LocatorFactory::get_active_strategies(
            locator_strategies, licenseLocation);
    EventRegistry eventRegistry;
    if (ret != FUNC_RET_OK) {
        eventRegistry.addEvent(LICENSE_FILE_NOT_FOUND);
        eventRegistry.turnWarningsIntoErrors();
        return eventRegistry;
    }
    bool loadAtLeastOneFile = false;
    bool atLeastOneProductLicensed = false;
    bool atLeastOneLicenseComplete = false;
    CSimpleIniA ini;
    for (auto it = diskFiles.begin(); it != diskFiles.end(); it++) {
        ini.Reset();
        const SI_Error rc = ini.LoadFile((*it).c_str());
        if (rc < 0) {
            result.addEvent(FILE_FORMAT_NOT_RECOGNIZED, SVRT_WARN, *it);
    for (unique_ptr<locate::LocatorStrategy> &locator : locator_strategies) {
        vector<string> licenseLocations = locator->license_locations(
                eventRegistry);
        if (licenseLocations.size() == 0) {
            continue;
        } else {
            loadAtLeastOneFile = true;
        }
        CSimpleIniA ini;
        for (auto it = licenseLocations.begin(); it != licenseLocations.end();
                it++) {
            ini.Reset();
            string license = locator->retrieve_license_content((*it).c_str());
            const SI_Error rc = ini.LoadData(license.c_str(), license.size());
            if (rc < 0) {
                eventRegistry.addEvent(FILE_FORMAT_NOT_RECOGNIZED,     *it);
                continue;
        }
        const char* productNamePtr = product.c_str();
        const int sectionSize = ini.GetSectionSize(productNamePtr);
        if (sectionSize <= 0) {
            result.addEvent(PRODUCT_NOT_LICENSED, SVRT_WARN, *it);
                eventRegistry.addEvent(PRODUCT_NOT_LICENSED, *it);
            continue;
        } else {
            atLeastOneProductLicensed = true;
                eventRegistry.addEvent(PRODUCT_FOUND,     *it);
        }
        /*
         *  sw_version_from = (optional int)
@@ -160,156 +180,28 @@
                    "from_sw_version",
                    FullLicenseInfo::UNUSED_SOFTWARE_VERSION);
            const int to_sw_version = ini.GetLongValue(productNamePtr,
                    "to_sw_version", FullLicenseInfo::UNUSED_SOFTWARE_VERSION);
                        "to_sw_version",
                        FullLicenseInfo::UNUSED_SOFTWARE_VERSION);
            string extra_data = trim_copy(
                    ini.GetValue(productNamePtr, "extra_data", ""));
            FullLicenseInfo licInfo(*it, product, license_signature,
                    (int) license_version, from_date, to_date, client_signature,
                    from_sw_version, to_sw_version, extra_data);
                        (int) license_version, from_date, to_date,
                        client_signature, from_sw_version, to_sw_version,
                        extra_data);
            licenseInfoOut.push_back(licInfo);
            atLeastOneLicenseComplete = true;
        } else {
            result.addEvent(LICENSE_MALFORMED, SVRT_WARN, *it);
                eventRegistry.addEvent(LICENSE_MALFORMED, *it);
        }
    }
    if (!loadAtLeastOneFile) {
        result.turnEventIntoError(FILE_FORMAT_NOT_RECOGNIZED);
    }
    if (!atLeastOneProductLicensed) {
        result.turnEventIntoError(PRODUCT_NOT_LICENSED);
    }
    if (!atLeastOneLicenseComplete) {
        result.turnEventIntoError(LICENSE_MALFORMED);
    }
    return result;
}
bool LicenseReader::findLicenseWithExplicitLocation(vector<string>& diskFiles,
        EventRegistry& eventRegistry) {
//bool hasFileLocation = false;
    bool licenseFoundWithExplicitLocation = false;
    if (licenseLocation.licenseFileLocation != nullptr
            && licenseLocation.licenseFileLocation[0] != '\0') {
        //hasFileLocation = true;
        const string varName(licenseLocation.licenseFileLocation);
        const vector<string> declared_positions = splitLicensePositions(varName);
        vector<string> existing_pos = filterExistingFiles(declared_positions);
        if (existing_pos.size() > 0) {
            if (existing_pos.size() > 0) {
                licenseFoundWithExplicitLocation = true;
                for (auto it = existing_pos.begin(); it != existing_pos.end();
                        ++it) {
                    diskFiles.push_back(*it);
                    eventRegistry.addEvent(LICENSE_FILE_FOUND, SVRT_INFO, *it);
                }
            }
        } else {
            eventRegistry.addEvent(LICENSE_FILE_NOT_FOUND, SVRT_WARN, varName);
        }
    }
    return licenseFoundWithExplicitLocation;
}
bool LicenseReader::findFileWithEnvironmentVariable(vector<string>& diskFiles,
        EventRegistry& eventRegistry) {
    bool licenseFileFoundWithEnvVariable = false;
    if (licenseLocation.environmentVariableName != nullptr
            && licenseLocation.environmentVariableName[0] != '\0') {
        const string varName(licenseLocation.environmentVariableName);
        if (varName.length() > 0) {
            //var name is passed in by the calling application.
            char* env_var_value = getenv(varName.c_str());
            if (env_var_value != nullptr && env_var_value[0] != '\0') {
                const vector<string> declared_positions = splitLicensePositions(
                        string(env_var_value));
                vector<string> existing_pos = filterExistingFiles(
                        declared_positions);
                if (existing_pos.size() > 0) {
                    licenseFileFoundWithEnvVariable = true;
                    for (auto it = existing_pos.begin();
                            it != existing_pos.end(); ++it) {
                        diskFiles.push_back(*it);
                        eventRegistry.addEvent(LICENSE_FILE_FOUND, SVRT_INFO,
                                *it);
                    }
                } else {
                    eventRegistry.addEvent(LICENSE_FILE_NOT_FOUND, SVRT_WARN,
                            env_var_value);
                }
            } else {
                eventRegistry.addEvent(ENVIRONMENT_VARIABLE_NOT_DEFINED,
                        SVRT_WARN);
            }
        } else {
            eventRegistry.addEvent(ENVIRONMENT_VARIABLE_NOT_DEFINED, SVRT_WARN);
        }
    }
    return licenseFileFoundWithEnvVariable;
}
EventRegistry LicenseReader::getLicenseDiskFiles(vector<string>& diskFiles) {
    EventRegistry eventRegistry;
    const bool licenseFoundWithExplicitLocation = findLicenseWithExplicitLocation(
            diskFiles, eventRegistry);
    bool foundNearModule = false;
    if (licenseLocation.openFileNearModule) {
        char fname[MAX_PATH] = { 0 };
        const FUNCTION_RETURN fret = getModuleName(fname);
        if (fret == FUNC_RET_OK) {
            const string temptativeLicense = string(fname) + ".lic";
            ifstream f(temptativeLicense.c_str());
            if (f.good()) {
                foundNearModule = true;
                diskFiles.push_back(temptativeLicense);
                eventRegistry.addEvent(LICENSE_FILE_FOUND, SVRT_INFO,
                        temptativeLicense);
            } else {
                eventRegistry.addEvent(LICENSE_FILE_NOT_FOUND, SVRT_WARN,
                        temptativeLicense);
            }
            f.close();
        } else {
            LOG_WARN("Error determining module name.");
        }
    }
    const bool licenseFileFoundWithEnvVariable = findFileWithEnvironmentVariable(
            diskFiles, eventRegistry);
    if (!foundNearModule && !licenseFoundWithExplicitLocation
            && !licenseFileFoundWithEnvVariable) {
        eventRegistry.turnEventIntoError(ENVIRONMENT_VARIABLE_NOT_DEFINED);
        eventRegistry.turnEventIntoError(LICENSE_FILE_NOT_FOUND);
        eventRegistry.turnWarningsIntoErrors();
    }
    return eventRegistry;
}
vector<string> LicenseReader::filterExistingFiles(
        vector<string> licensePositions) {
    vector<string> existingFiles;
    for (auto it = licensePositions.begin(); it != licensePositions.end();
            it++) {
        ifstream f(it->c_str());
        if (f.good()) {
            existingFiles.push_back(*it);
        }
        f.close();
    }
    return existingFiles;
}
vector<string> LicenseReader::splitLicensePositions(string licensePositions) {
    std::stringstream streamToSplit(licensePositions);
    std::string segment;
    std::vector<string> seglist;
    while (std::getline(streamToSplit, segment, ';')) {
        seglist.push_back(segment);
    }
    return seglist;
}
LicenseReader::~LicenseReader() {
}
string FullLicenseInfo::printForSign() const {
src/library/LicenseReader.h
File was deleted
src/library/LicenseReader.hpp
New file
@@ -0,0 +1,84 @@
/*
 * LicenseReader.h
 *
 *  Created on: Mar 30, 2014
 *
 */
#ifndef LICENSEREADER_H_
#define LICENSEREADER_H_
#include <string>
#include <ctime>
#define SI_SUPPORT_IOSTREAMS
#include "api/datatypes.h"
#include "base/EventRegistry.h"
#include "os/os.h"
#include "ini/SimpleIni.h"
namespace license {
class FullLicenseInfo {
public:
    std::string source;
    std::string product;
    std::string license_signature;
    int license_version;
    std::string from_date;
    std::string to_date;
    bool has_expiry;
    unsigned int from_sw_version;
    unsigned int to_sw_version;
    bool has_versions;
    std::string client_signature;
    bool has_client_sig;
    std::string extra_data;
    static const char* UNUSED_TIME;
    static const unsigned int UNUSED_SOFTWARE_VERSION = 0;
    FullLicenseInfo(const std::string& source, const std::string& product,
            const std::string& license_signature, int licenseVersion,
            std::string from_date = UNUSED_TIME,
            std::string to_date = UNUSED_TIME, //
            const std::string& client_signature = "", //
            unsigned int from_sw_version = UNUSED_SOFTWARE_VERSION,
            unsigned int to_sw_version = UNUSED_SOFTWARE_VERSION,
            const std::string& extra_data = "");
    std::string printForSign() const;
    void printAsIni(std::ostream & a_ostream) const;
    void toLicenseInfo(LicenseInfo* license) const;
    bool validate(int sw_version, EventRegistry& eventRegistryOut);
    time_t expires_on() const;
    time_t valid_from() const;
};
/**
 * This class it is responsible to read the licenses from the disk
 * (in future from network) examining all the possible LicenseLocation
 * positions.
 *
 * Each section of the ini file represents a product.
 * <pre>
 * [product]
 *  sw_version_from = (optional int)
 *  sw_version_to = (optional int)
 *  from_date = YYYY-MM-DD (optional)
 *  to_date  = YYYY-MM-DD (optional)
 *  client_signature = XXXXXXXX (optional std::string 16)
 *  license_signature = XXXXXXXXXX (mandatory, 1024)
 *  application_data = xxxxxxxxx (optional std::string 16)
 *    license_version = 100 (mandatory int)
 *  </pre>
 */
class LicenseReader {
private:
    const LicenseLocation* licenseLocation;
public:
    LicenseReader(const LicenseLocation* licenseLocation);
    EventRegistry readLicenses(const std::string &product,
            std::vector<FullLicenseInfo>& licenseInfoOut);
    virtual ~LicenseReader();
};
}
#endif /* LICENSEREADER_H_ */
src/library/api/Licensepp-features.h
File was deleted
src/library/api/datatypes.h
@@ -13,14 +13,18 @@
#ifdef __unix__
#define DllExport
#ifndef MAX_PATH
    #define MAX_PATH 1024
#endif
#else
#include <windows.h>
#define DllExport  __declspec( dllexport )
#endif
#define ENVIRONMENT_VAR_NAME_MAX 64
#define PC_IDENTIFIER_SIZE 18
#define PROPRIETARY_DATA_SIZE 16
#define AUDIT_EVENT_NUM 5
#define LICENESE_INT_VERSION 110
#define LICENSEPP_VERSION "1.1.0"
@@ -37,8 +41,10 @@
    LICENSE_CORRUPTED = 8,//License signature didn't match with current license
    IDENTIFIERS_MISMATCH = 9, //Calculated identifier and the one provided in license didn't match
    LICENSE_FILE_FOUND = 100,
    LICENSE_VERIFIED = 101
    LICENSE_SPECIFIED = 100,    //license location was specified
    LICENSE_FOUND = 101,         //License file has been found or license data has been located
    PRODUCT_FOUND = 102,        //License has been loaded and the declared product has been found
    SIGNATURE_VERIFIED = 103
} EVENT_TYPE;
@@ -53,23 +59,40 @@
typedef struct {
    SEVERITY severity;
    EVENT_TYPE event_type;
    char param1[256];
    /**
     * License file name or location where the license is stored.
     */
    char license_reference[MAX_PATH];
    char param2[256];
} AuditEvent;
/**
 * This structure contains informations on the raw license data. Software authors
 * can specify the location of the license file or its full content.
 *
 * Can be NULL, in this case OpenLicenseManager will try to figure out the
 * license file location on its own.
 */
typedef struct {
    /**
     * A list of absolute path separated by ';' containing the eventual location
     * of the license files. Can be NULL.
     */
    const char *licenseFileLocation;
    const char *environmentVariableName;
    bool openFileNearModule;
    /**
     * The application can provide the full license content through this string.
     * It can be both in encoded form (base64) or in plain. It's optional.
     */
    const char *licenseData;
} LicenseLocation;
typedef struct {
    /**
     * Detailed reason of success/failure. Reasons for a failure can be
     * multiple (for instance, license expired and signature not verified).
     * Only the last 5 are reported.
     * Only the last AUDIT_EVENT_NUM are reported.
     */
    AuditEvent status[5];
    AuditEvent status[AUDIT_EVENT_NUM];
    /**
     * Eventual expiration date of the software,
     * can be '\0' if the software don't expire
src/library/api/license++.h
@@ -3,22 +3,9 @@
/*
 * This include file is the public api di License++
 * You should include this file if your software don't plan to use
 * the part of the library dealing with features.
 * Otherwise licensepp-features.h should be included.
 */
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __unix__
#define DllExport
#ifndef MAX_PATH
    #define MAX_PATH 1024
#endif
#else
#include <windows.h>
#define DllExport  __declspec( dllexport )
#endif
#include "datatypes.h"
@@ -35,30 +22,37 @@
 */
void identify_pc(IDENTIFICATION_STRATEGY pc_id_method,
        char chbuffer[PC_IDENTIFIER_SIZE + 1]);
/*
 * The optional parameter License contains the information the program that uses the library
 * should display:
/**
 * This method is used to request the use of one license for a product.
 * In case of local license it's used to check if the product is licensed.
 * [In case of network licenses this will decrease the count of the available
 *  licenses]
 *
 * @return true if successful. False if there are errors.
 * @param licenseLocation[in] licenseLocation, either the name of the file
 * @return LICENSE_OK(0) if successful. Other values if there are errors.
 * @param productName[in]
 *             a vendor defined string containing the name of the product we want to request.
 * @param licenseLocation[in] otpional, can be NULL.
 *                     licenseLocation, either the name of the file
 *                                 or the name of the environment variable should be !='\0'
 * @param license[out] optional, can be NULL.
 * @param license[out] optional, can be NULL, if set it will return extra informations about the license.
 */
EVENT_TYPE acquire_license(const char * productName,
        LicenseLocation licenseLocation, LicenseInfo* license);
        const LicenseLocation* licenseLocation, LicenseInfo* license);
/**
 * Do nothing for now, useful for network licenses.
 * Should be called from time to time to confirm we're still using the
 * slicense.
 * license.
 */
EVENT_TYPE confirm_license(char * productName,
        LicenseLocation licenseLocation);
EVENT_TYPE confirm_license(char * featureName,
        LicenseLocation* licenseLocation);
/**
 * Do nothing for now, useful for network licenses.
 */
EVENT_TYPE release_license(char * productName,
EVENT_TYPE release_license(char * featureName,
        LicenseLocation licenseLocation);
#ifdef __cplusplus
src/library/base/CMakeLists.txt
@@ -1,7 +1,9 @@
ADD_LIBRARY(base STATIC
    EventRegistry.cpp
    StringUtils.cpp
    FileUtils.cpp
    logger.c
    base64.c
)
add_dependencies( base public_key )
src/library/base/EventRegistry.cpp
@@ -5,15 +5,24 @@
 *      
 */
#include "EventRegistry.h"
#include <cstddef>
#include <string.h>
#include <algorithm>
#include <map>
#include <iostream>
using namespace std;
#include "EventRegistry.h"
#define LIC_ID_NOT_DEFINED "UNDEF"
namespace license {
using namespace std;
const map<EVENT_TYPE, int> PROGRESS_BY_EVENT_TYPE = { { LICENSE_SPECIFIED, 0 },
        { LICENSE_FOUND, 1 }, { PRODUCT_FOUND, 2 }, { SIGNATURE_VERIFIED, 3 }, {
                LICENSE_OK, 4 } };
EventRegistry::EventRegistry() {
    current_validation_step = -1;
}
EventRegistry& operator<<(EventRegistry& eventRegistry,
@@ -28,26 +37,20 @@
    return eventRegistry1;
}
ostream& operator<<(std::ostream &out, const EventRegistry &er) {
    out << string("EventReg[step:") << er.current_validation_step
            << ",events:{";
    for (auto &it : er.logs) {
        out << "[ev:" << it.event_type << ",sev:" << it.severity << "ref:"
                << it.license_reference << "]";
    }
    out << "]";
    return out;
}
void EventRegistry::append(const EventRegistry& eventRegistry) {
    logs.insert(logs.end(), eventRegistry.logs.begin(),
            eventRegistry.logs.end());
}
void EventRegistry::turnLastEventIntoError() {
    if (logs.size() > 0) {
        logs.back().severity = SVRT_ERROR;
    }
}
bool EventRegistry::turnEventIntoError(EVENT_TYPE event) {
    bool eventFound = false;
    for (auto it = logs.begin(); it != logs.end(); ++it) {
        if (it->event_type == event) {
            it->severity = SVRT_ERROR;
            eventFound = true;
        }
    }
    return eventFound;
}
AuditEvent const * EventRegistry::getLastFailure() const {
@@ -55,6 +58,17 @@
    if (logs.size() == 0) {
        return result;
    }
    //try to find a failure between the licenses who progressed the most
    if (mostAdvancedLogIdx_by_LicenseId.size() > 0) {
        for (auto const &mostAdvLogIter : mostAdvancedLogIdx_by_LicenseId) {
            const AuditEvent &currentLog = logs[mostAdvLogIter.second];
            if (currentLog.severity == SVRT_ERROR) {
                result = &(currentLog);
                break;
            }
        }
    }
    if (result == nullptr) {
    auto it = logs.end();
    do {
        --it;
@@ -63,45 +77,76 @@
            break;
        }
    } while (it != logs.begin());
    }
    return result;
}
bool EventRegistry::isGood() const {
    bool isGood = true;
void EventRegistry::addEvent(EVENT_TYPE event,
        const std::string &licenseLocationId) {
    addEvent(event, licenseLocationId.c_str(), nullptr);
}
void EventRegistry::addEvent(EVENT_TYPE event, const char *licenseLocationId,
        const char *info) {
    AuditEvent audit;
    auto eventIterator = PROGRESS_BY_EVENT_TYPE.find(event);
    bool successEvent = (eventIterator != PROGRESS_BY_EVENT_TYPE.end());
    audit.severity = successEvent ? SVRT_INFO : SVRT_WARN;
    audit.event_type = event;
    if (licenseLocationId == nullptr) {
        strcpy(audit.license_reference, LIC_ID_NOT_DEFINED);
    } else {
        strncpy(audit.license_reference, licenseLocationId, MAX_PATH);
    }
    if (info == nullptr) {
        audit.param2[0] = '\0';
    } else {
        strncpy(audit.param2, info, 255);
    }
    logs.push_back(audit);
//udpate the status of the log
    if (successEvent) {
        int step = eventIterator->second;
        if (step > current_validation_step) {
            mostAdvancedLogIdx_by_LicenseId.clear();
            current_validation_step = step;
        }
        if (step == current_validation_step) {
            mostAdvancedLogIdx_by_LicenseId[audit.license_reference] =
                    logs.size() - 1;
        }
    } else if (mostAdvancedLogIdx_by_LicenseId.find(audit.license_reference)
            != mostAdvancedLogIdx_by_LicenseId.end()) {
        mostAdvancedLogIdx_by_LicenseId[audit.license_reference] = logs.size()
                - 1;
    }
}
bool EventRegistry::turnWarningsIntoErrors() {
    bool eventFound = false;
    if (mostAdvancedLogIdx_by_LicenseId.size() > 0) {
        for (auto const &mostAdvLogIter : mostAdvancedLogIdx_by_LicenseId) {
            AuditEvent &currentLog = logs[mostAdvLogIter.second];
            if (currentLog.severity == SVRT_WARN
                    || currentLog.severity == SVRT_ERROR) {
                currentLog.severity = SVRT_ERROR;
                eventFound = true;
            }
        }
    }
    if (!eventFound) {
    for (auto it = logs.begin(); it != logs.end(); ++it) {
        if (it->severity == SVRT_ERROR) {
            isGood = false;
            break;
            if (it->severity == SVRT_WARN) {
                it->severity = SVRT_ERROR;
                eventFound = true;
        }
    }
    return isGood;
    }
    return eventFound;
}
void EventRegistry::addError(EVENT_TYPE event) {
    this->addEvent(event, SVRT_ERROR);
}
void EventRegistry::addEvent(EVENT_TYPE event, SEVERITY severity) {
    AuditEvent audit;
    audit.severity = severity;
    audit.event_type = event;
    audit.param1[0] = '\0';
    audit.param2[0] = '\0';
    logs.push_back(audit);
}
void EventRegistry::addEvent(EVENT_TYPE event, SEVERITY severity,
        const string& eventParameter) {
    AuditEvent audit;
    audit.severity = severity;
    audit.event_type = event;
    strncpy(audit.param1, eventParameter.c_str(), 255);
    audit.param2[0] = '\0';
    logs.push_back(audit);
}
bool EventRegistry::turnErrosIntoWarnings() {
bool EventRegistry::turnErrorsIntoWarnings() {
    bool eventFound = false;
    for (auto it = logs.begin(); it != logs.end(); ++it) {
        if (it->severity == SVRT_ERROR) {
@@ -114,7 +159,12 @@
void EventRegistry::exportLastEvents(AuditEvent* auditEvents, int nlogs) {
    const int sizeToCopy = min(nlogs, (int) logs.size());
    std::copy(logs.begin(), logs.begin() + sizeToCopy, auditEvents);
    std::copy(logs.end() - sizeToCopy, logs.end(), auditEvents);
}
bool EventRegistry::isGood() const {
    return getLastFailure() == nullptr;
}
}
src/library/base/EventRegistry.h
@@ -10,43 +10,51 @@
#include "../api/datatypes.h"
#include <vector>
#include <map>
#include <set>
#include <string>
namespace license {
using namespace std;
/*
AuditEvent error_event_builder(EVENT_TYPE event);
AuditEvent audit_event_builder(EVENT_TYPE event, SEVERITY severity);
AuditEvent audit_event_builder(EVENT_TYPE event, SEVERITY severity,
        const string& eventParameter);*/
/**
 * Tracks the events relative to a license and provide explanation regarding
 * failures to verify licenses.
 */
class EventRegistry {
private:
    friend EventRegistry& operator<<(EventRegistry&, AuditEvent&);
    friend EventRegistry& operator<<(EventRegistry&, EventRegistry&);
    //TODO change into map
    vector<AuditEvent> logs;
    //Forbid copy
    //EventRegistry(const EventRegistry& that) = delete;
    friend std::ostream & operator << (std::ostream &out, const EventRegistry &er);
    std::vector<AuditEvent> logs;
    /**
     * For every license keep track of the events who progressed most
     * in the validation process
     */
    std::map<std::string,int> mostAdvancedLogIdx_by_LicenseId;
    int current_validation_step;
public:
    EventRegistry();
    //operator <<
    void append(const EventRegistry& eventRegistry);
    void turnLastEventIntoError();
    bool turnEventIntoError(EVENT_TYPE event);
    bool turnErrosIntoWarnings();
    /**
     * Turn the event warning for the license with the most advanced status
     * into an error.
     */
    bool turnWarningsIntoErrors();
    bool turnErrorsIntoWarnings();
    bool isGood() const;
    /**
     * Return the last failure (event with warn or error status)
     * for the license with the most advanced status.
     * @return NULL if no failures are found.
     */
    AuditEvent const * getLastFailure() const;
    bool isGood() const;
    void addError(EVENT_TYPE event);
    void addEvent(EVENT_TYPE event, SEVERITY severity);
    void addEvent(EVENT_TYPE event, SEVERITY severity,
            const string& eventParameter);
    void addEvent(EVENT_TYPE event, const std::string &licenseLocationId);
    void addEvent(EVENT_TYPE event, const char *licenseLocationId = nullptr,
            const char *info = nullptr);
    void exportLastEvents(AuditEvent* auditEvents,int nlogs);
};
}
#endif /* EVENTREGISTRY_H_ */
src/library/base/FileUtils.cpp
New file
@@ -0,0 +1,69 @@
/*
 * FileUtils.cpp
 *
 *  Created on: Oct 8, 2019
 *      Author: devel
 */
#include <fstream>
#include <string>
#include <cerrno>
#include <iostream>
#include <algorithm>
#include "FileUtils.hpp"
namespace license {
using namespace std;
vector<string> filter_existing_files(const vector<string> &fileList,
        EventRegistry& registry,const char* extraData) {
    vector<string> existingFiles;
    for (auto it = fileList.begin(); it != fileList.end(); it++) {
        registry.addEvent(LICENSE_SPECIFIED,it->c_str(), extraData);
        ifstream f(it->c_str());
        if (f.good()) {
            existingFiles.push_back(*it);
            registry.addEvent(LICENSE_FOUND,it->c_str(),extraData);
        } else {
            registry.addEvent(LICENSE_FILE_NOT_FOUND,it->c_str(), extraData);
        }
        f.close();
    }
    return existingFiles;
}
string get_file_contents(const char *filename, size_t max_size) {
    ifstream in(filename, std::ios::binary);
    if (in) {
        string contents;
        size_t index = in.seekg(0, ios::end).tellg();
        size_t limited_size = min(index, max_size);
        contents.resize(limited_size);
        in.seekg(0, ios::beg);
        in.read(&contents[0], limited_size);
        return contents;
    }
    throw(errno);
}
string remove_extension(const string& path) {
    if (path == "." || path == "..") {
        return path;
    }
    size_t dotpos = path.find_last_of(".");
    //no dot
    if (dotpos == string::npos) {
        return path;
    }
    //find the last path separator
    size_t pathsep_pos = path.find_last_of("\\/");
    if (pathsep_pos == string::npos) {
        return (dotpos == 0 ? path : path.substr(0, dotpos));
    } else if(pathsep_pos >= dotpos +1) {
        return path;
    }
    return path.substr(0, dotpos);
}
}
src/library/base/FileUtils.hpp
New file
@@ -0,0 +1,22 @@
/*
 * FileUtils.h
 *
 *  Created on: Apr 8, 2019
 *
 */
#ifndef FILEUTILS_H_
#define FILEUTILS_H_
#include <string>
#include <vector>
#include "EventRegistry.h"
namespace license {
std::vector<std::string> filter_existing_files(const std::vector<std::string>& fileList,EventRegistry& registry, const char* extraData);
std::string get_file_contents(const char *filename,size_t max_size);
std::string remove_extension(const std::string& path);
} /* namespace license */
#endif
src/library/base/StringUtils.cpp
@@ -6,12 +6,14 @@
 */
#include <cctype> //toupper
#include "StringUtils.h"
#include <iostream>
#include <string>
#include <sstream>
#include <cstring>
#include <algorithm>
#include <stdexcept>
#include <regex>
#include "StringUtils.h"
#ifdef _WIN32
#include <time.h> //mktime under windows
@@ -47,9 +49,11 @@
            throw invalid_argument("Date not recognized");
        }
    } else if (strlen(timeString) == 10) {
        const int nfield = sscanf(timeString, "%4d-%2d-%2d", &year, &month, &day);
        const int nfield = sscanf(timeString, "%4d-%2d-%2d", &year, &month,
                &day);
        if (nfield != 3) {
            const int nfield = sscanf(timeString, "%4d/%2d/%2d", &year, &month, &day);
            const int nfield = sscanf(timeString, "%4d/%2d/%2d", &year, &month,
                    &day);
            if (nfield != 3) {
                throw invalid_argument("Date not recognized");
            }
@@ -68,4 +72,31 @@
    tm.tm_wday = -1;
    return mktime(&tm);
}
const vector<string> split_string(const string &licensePositions,
        char splitchar) {
    std::stringstream streamToSplit(licensePositions);
    std::string segment;
    std::vector<string> seglist;
    while (std::getline(streamToSplit, segment, splitchar)) {
        seglist.push_back(segment);
    }
    return seglist;
}
const static regex iniSection("\\[.*?\\]");
const static regex b64(
        "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$");
FILE_FORMAT identify_format(const string &license) {
    FILE_FORMAT result = UNKNOWN;
    if (regex_match(license, b64)) {
        result = BASE64;
    } else if (regex_search(license, iniSection)) {
        result = INI;
    }
    return result;
}
} /* namespace license */
src/library/base/StringUtils.h
@@ -7,7 +7,10 @@
#ifndef STRINGUTILS_H_
#define STRINGUTILS_H_
#include <bits/types/time_t.h>
#include <string>
#include <vector>
namespace license {
using namespace std;
@@ -23,6 +26,20 @@
string toupper_copy(const string& lowercase);
time_t seconds_from_epoch(const char* s);
} /* namespace license */
/**
 * Split a string on a given character
 */
const vector<string> split_string(const string& stringToBeSplit, const char splitchar);
typedef enum {
    INI, BASE64, UNKNOWN
} FILE_FORMAT;
FILE_FORMAT identify_format(const string& license);
}
/* namespace license */
#endif /* STRINGUTILS_H_ */
src/library/base/base.h
@@ -1,7 +1,6 @@
#ifndef BASE_H_
#define BASE_H_
#ifdef __cplusplus
extern "C" {
#endif
@@ -29,11 +28,6 @@
#endif
/* #define _DEBUG */
#define cmax(a,b) \
   ({ __typeof__ (a) _a = (a); \
       __typeof__ (b) _b = (b); \
     _a > _b ? _a : _b; })
#define cmin(a,b) \
   ({ __typeof__ (a) _a = (a); \
src/library/base/base64.c
New file
@@ -0,0 +1,133 @@
#include <stdio.h>
#include <stdlib.h>
const static char* b64 =
        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
// maps A=>0,B=>1..
const static unsigned char unb64[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //10
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //20
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //30
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //40
        0, 0, 0, 62, 0, 0, 0, 63, 52, 53, //50
        54, 55, 56, 57, 58, 59, 60, 61, 0, 0, //60
        0, 0, 0, 0, 0, 0, 1, 2, 3, 4, //70
        5, 6, 7, 8, 9, 10, 11, 12, 13, 14, //80
        15, 16, 17, 18, 19, 20, 21, 22, 23, 24, //90
        25, 0, 0, 0, 0, 0, 0, 26, 27, 28, //100
        29, 30, 31, 32, 33, 34, 35, 36, 37, 38, //110
        39, 40, 41, 42, 43, 44, 45, 46, 47, 48, //120
        49, 50, 51, 0, 0, 0, 0, 0, 0, 0, //130
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //140
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //150
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //160
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //170
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //180
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //190
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //200
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //210
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //220
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //230
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //240
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //250
        0, 0, 0, 0, 0, 0, }; // This array has 255 elements
//review api
char* base64(const void* binaryData, int len, int *flen) {
    const unsigned char* bin = (const unsigned char*) binaryData;
    char* res;
    int rc = 0; // result counter
    int byteNo; // I need this after the loop
    int modulusLen = len % 3;
    int pad = ((modulusLen & 1) << 1) + ((modulusLen & 2) >> 1); // 2 gives 1 and 1 gives 2, but 0 gives 0.
    *flen = 4 * (len + pad) / 3;
    res = (char*) malloc(*flen + 1); // and one for the null
    if (!res) {
        puts("ERROR: base64 could not allocate enough memory.");
        puts("I must stop because I could not get enough");
        return 0;
    }
    for (byteNo = 0; byteNo <= len - 3; byteNo += 3) {
        unsigned char BYTE0 = bin[byteNo];
        unsigned char BYTE1 = bin[byteNo + 1];
        unsigned char BYTE2 = bin[byteNo + 2];
        res[rc++] = b64[BYTE0 >> 2];
        res[rc++] = b64[((0x3 & BYTE0) << 4) + (BYTE1 >> 4)];
        res[rc++] = b64[((0x0f & BYTE1) << 2) + (BYTE2 >> 6)];
        res[rc++] = b64[0x3f & BYTE2];
    }
    if (pad == 2) {
        res[rc++] = b64[bin[byteNo] >> 2];
        res[rc++] = b64[(0x3 & bin[byteNo]) << 4];
        res[rc++] = '=';
        res[rc++] = '=';
    } else if (pad == 1) {
        res[rc++] = b64[bin[byteNo] >> 2];
        res[rc++] = b64[((0x3 & bin[byteNo]) << 4) + (bin[byteNo + 1] >> 4)];
        res[rc++] = b64[(0x0f & bin[byteNo + 1]) << 2];
        res[rc++] = '=';
    }
    res[rc] = 0; // NULL TERMINATOR! ;)
    return res;
}
unsigned char* unbase64(const char* ascii, int len, int *flen) {
    const unsigned char *safeAsciiPtr = (const unsigned char*) ascii;
    unsigned char *bin;
    int cb = 0;
    int charNo;
    int pad = 0;
    if (len < 2) { // 2 accesses below would be OOB.
        // catch empty string, return NULL as result.
        puts(
                "ERROR: You passed an invalid base64 string (too short). You get NULL back.");
        *flen = 0;
        return 0;
    }
    if (safeAsciiPtr[len - 1] == '=')
        ++pad;
    if (safeAsciiPtr[len - 2] == '=')
        ++pad;
    *flen = 3 * len / 4 - pad;
    bin = (unsigned char*) malloc(*flen);
    if (!bin) {
        puts("ERROR: unbase64 could not allocate enough memory.");
        puts("I must stop because I could not get enough");
        return 0;
    }
    for (charNo = 0; charNo <= len - 4 - pad; charNo += 4) {
        int A = unb64[safeAsciiPtr[charNo]];
        int B = unb64[safeAsciiPtr[charNo + 1]];
        int C = unb64[safeAsciiPtr[charNo + 2]];
        int D = unb64[safeAsciiPtr[charNo + 3]];
        bin[cb++] = (A << 2) | (B >> 4);
        bin[cb++] = (B << 4) | (C >> 2);
        bin[cb++] = (C << 6) | (D);
    }
    if (pad == 1) {
        int A = unb64[safeAsciiPtr[charNo]];
        int B = unb64[safeAsciiPtr[charNo + 1]];
        int C = unb64[safeAsciiPtr[charNo + 2]];
        bin[cb++] = (A << 2) | (B >> 4);
        bin[cb++] = (B << 4) | (C >> 2);
    } else if (pad == 2) {
        int A = unb64[safeAsciiPtr[charNo]];
        int B = unb64[safeAsciiPtr[charNo + 1]];
        bin[cb++] = (A << 2) | (B >> 4);
    }
    return bin;
}
src/library/base/base64.h
@@ -31,140 +31,14 @@
#ifndef BASE64_H
#define BASE64_H
#include <stdio.h>
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif
const static char* b64 =
        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
unsigned char* unbase64(const char* ascii, int len, int *flen);
char* base64(const void* binaryData, int len, int *flen);
// maps A=>0,B=>1..
const static unsigned char unb64[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //10
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //20
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //30
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //40
        0, 0, 0, 62, 0, 0, 0, 63, 52, 53, //50
        54, 55, 56, 57, 58, 59, 60, 61, 0, 0, //60
        0, 0, 0, 0, 0, 0, 1, 2, 3, 4, //70
        5, 6, 7, 8, 9, 10, 11, 12, 13, 14, //80
        15, 16, 17, 18, 19, 20, 21, 22, 23, 24, //90
        25, 0, 0, 0, 0, 0, 0, 26, 27, 28, //100
        29, 30, 31, 32, 33, 34, 35, 36, 37, 38, //110
        39, 40, 41, 42, 43, 44, 45, 46, 47, 48, //120
        49, 50, 51, 0, 0, 0, 0, 0, 0, 0, //130
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //140
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //150
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //160
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //170
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //180
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //190
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //200
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //210
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //220
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //230
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //240
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //250
        0, 0, 0, 0, 0, 0, }; // This array has 255 elements
// Converts binary data of length=len to base64 characters.
// Length of the resultant string is stored in flen
// (you must pass pointer flen).
char* base64(const void* binaryData, int len, int *flen) {
    const unsigned char* bin = (const unsigned char*) binaryData;
    char* res;
    int rc = 0; // result counter
    int byteNo; // I need this after the loop
    int modulusLen = len % 3;
    int pad = ((modulusLen & 1) << 1) + ((modulusLen & 2) >> 1); // 2 gives 1 and 1 gives 2, but 0 gives 0.
    *flen = 4 * (len + pad) / 3;
    res = (char*) malloc(*flen + 1); // and one for the null
    if (!res) {
        puts("ERROR: base64 could not allocate enough memory.");
        puts("I must stop because I could not get enough");
        return 0;
#ifdef __cplusplus
    }
    for (byteNo = 0; byteNo <= len - 3; byteNo += 3) {
        unsigned char BYTE0 = bin[byteNo];
        unsigned char BYTE1 = bin[byteNo + 1];
        unsigned char BYTE2 = bin[byteNo + 2];
        res[rc++] = b64[BYTE0 >> 2];
        res[rc++] = b64[((0x3 & BYTE0) << 4) + (BYTE1 >> 4)];
        res[rc++] = b64[((0x0f & BYTE1) << 2) + (BYTE2 >> 6)];
        res[rc++] = b64[0x3f & BYTE2];
    }
    if (pad == 2) {
        res[rc++] = b64[bin[byteNo] >> 2];
        res[rc++] = b64[(0x3 & bin[byteNo]) << 4];
        res[rc++] = '=';
        res[rc++] = '=';
    } else if (pad == 1) {
        res[rc++] = b64[bin[byteNo] >> 2];
        res[rc++] = b64[((0x3 & bin[byteNo]) << 4) + (bin[byteNo + 1] >> 4)];
        res[rc++] = b64[(0x0f & bin[byteNo + 1]) << 2];
        res[rc++] = '=';
    }
    res[rc] = 0; // NULL TERMINATOR! ;)
    return res;
}
unsigned char* unbase64(const char* ascii, int len, int *flen) {
    const unsigned char *safeAsciiPtr = (const unsigned char*) ascii;
    unsigned char *bin;
    int cb = 0;
    int charNo;
    int pad = 0;
    if (len < 2) { // 2 accesses below would be OOB.
        // catch empty string, return NULL as result.
        puts(
                "ERROR: You passed an invalid base64 string (too short). You get NULL back.");
        *flen = 0;
        return 0;
    }
    if (safeAsciiPtr[len - 1] == '=')
        ++pad;
    if (safeAsciiPtr[len - 2] == '=')
        ++pad;
    *flen = 3 * len / 4 - pad;
    bin = (unsigned char*) malloc(*flen);
    if (!bin) {
        puts("ERROR: unbase64 could not allocate enough memory.");
        puts("I must stop because I could not get enough");
        return 0;
    }
    for (charNo = 0; charNo <= len - 4 - pad; charNo += 4) {
        int A = unb64[safeAsciiPtr[charNo]];
        int B = unb64[safeAsciiPtr[charNo + 1]];
        int C = unb64[safeAsciiPtr[charNo + 2]];
        int D = unb64[safeAsciiPtr[charNo + 3]];
        bin[cb++] = (A << 2) | (B >> 4);
        bin[cb++] = (B << 4) | (C >> 2);
        bin[cb++] = (C << 6) | (D);
    }
    if (pad == 1) {
        int A = unb64[safeAsciiPtr[charNo]];
        int B = unb64[safeAsciiPtr[charNo + 1]];
        int C = unb64[safeAsciiPtr[charNo + 2]];
        bin[cb++] = (A << 2) | (B >> 4);
        bin[cb++] = (B << 4) | (C >> 2);
    } else if (pad == 2) {
        int A = unb64[safeAsciiPtr[charNo]];
        int B = unb64[safeAsciiPtr[charNo + 1]];
        bin[cb++] = (A << 2) | (B >> 4);
    }
    return bin;
}
#endif
#endif
src/library/license++.cpp
@@ -9,8 +9,11 @@
#include <stdio.h>
#include <stdlib.h>
#include <cstring>
#include <iostream>
#include "api/license++.h"
#include "LicenseReader.h"
#include "LicenseReader.hpp"
using namespace std;
void print_error(char out_buffer[256], LicenseInfo* licenseInfo) {
@@ -39,7 +42,7 @@
}
EVENT_TYPE acquire_license(const char * product,
        LicenseLocation licenseLocation, LicenseInfo* license) {
        const LicenseLocation* licenseLocation, LicenseInfo* licenseInfoOut) {
    license::LicenseReader lr = license::LicenseReader(licenseLocation);
    vector<license::FullLicenseInfo> licenses;
    license::EventRegistry er = lr.readLicenses(string(product), licenses);
@@ -48,28 +51,32 @@
        vector<license::FullLicenseInfo> licenses_with_errors;
        vector<license::FullLicenseInfo> licenses_ok;
        for (auto it = licenses.begin(); it != licenses.end(); it++) {
            license::EventRegistry validation_er = it->validate(0);
            if (validation_er.isGood()) {
            bool valid = it->validate(0,er);
            if (valid) {
                licenses_ok.push_back(*it);
            } else {
                licenses_with_errors.push_back(*it);
            }
            er.append(validation_er);
        }
        if (licenses_ok.size() > 0) {
            er.turnErrosIntoWarnings();
            er.turnErrorsIntoWarnings();
            result = LICENSE_OK;
            mergeLicenses(licenses_ok, license);
            mergeLicenses(licenses_ok, licenseInfoOut);
        } else {
            er.turnWarningsIntoErrors();
            result = er.getLastFailure()->event_type;
            mergeLicenses(licenses_with_errors, license);
            mergeLicenses(licenses_with_errors, licenseInfoOut);
        }
    } else {
        er.turnWarningsIntoErrors();
        result = er.getLastFailure()->event_type;
    }
    if (license != nullptr) {
        er.exportLastEvents(license->status, 5);
#ifdef _DEBUG
    cout << er <<endl;
#endif
    if (licenseInfoOut != nullptr) {
        er.exportLastEvents(licenseInfoOut->status, AUDIT_EVENT_NUM);
    }
    return result;
}
src/library/locate/ApplicationFolder.cpp
New file
@@ -0,0 +1,56 @@
/*
 * ApplicationFolder.cpp
 *
 *  Created on: Oct 12, 2019
 *      Author: Gabriele Contini
 */
#include <fstream>
#include <sstream>
#include <string>
#include <build_properties.h>
#include "../base/logger.h"
#include "../api/datatypes.h"
#include "../base/base.h"
#include "../base/EventRegistry.h"
#include "../base/FileUtils.hpp"
#include "../os/os.h"
#include "ApplicationFolder.hpp"
#include <iostream>
namespace license {
namespace locate {
using namespace std;
ApplicationFolder::ApplicationFolder() :
        LocatorStrategy("ApplicationFolder") {
}
ApplicationFolder::~ApplicationFolder() {
}
const vector<string> ApplicationFolder::license_locations(
        EventRegistry &eventRegistry) {
    vector<string> diskFiles;
    char fname[MAX_PATH] = { 0 };
    const FUNCTION_RETURN fret = getModuleName(fname);
    if (fret == FUNC_RET_OK) {
        const string module_name = remove_extension(fname);
        const string temptativeLicense = string(module_name) + ".lic";
        ifstream f(temptativeLicense.c_str());
        if (f.good()) {
            diskFiles.push_back(temptativeLicense);
            eventRegistry.addEvent(LICENSE_FOUND, temptativeLicense.c_str());
        } else {
            eventRegistry.addEvent(LICENSE_FILE_NOT_FOUND, temptativeLicense.c_str());
        }
        f.close();
    } else {
        LOG_WARN("Error determining module name.");
    }
    return diskFiles;
}
}
} /* namespace license */
src/library/locate/ApplicationFolder.hpp
New file
@@ -0,0 +1,28 @@
/*
 * ApplicationFolder.h
 *
 *  Created on: Oct 6, 2019
 *      Author: devel
 */
#ifndef SRC_LIBRARY_RETRIEVERS_APPLICATIONFOLDER_H_
#define SRC_LIBRARY_RETRIEVERS_APPLICATIONFOLDER_H_
#include <string>
#include "LocatorStrategy.hpp"
namespace license {
namespace locate {
class ApplicationFolder: public LocatorStrategy {
public:
    ApplicationFolder();
    virtual const std::vector<std::string> license_locations(EventRegistry& eventRegistry);
    virtual ~ApplicationFolder();
};
}
} /* namespace license */
#endif /* SRC_LIBRARY_RETRIEVERS_APPLICATIONFOLDER_H_ */
src/library/locate/CMakeLists.txt
New file
@@ -0,0 +1,18 @@
ADD_LIBRARY(locators STATIC
    ApplicationFolder.cpp
    EnvironmentVarLocation.cpp
    EnvironmentVarData.cpp
    ExternalDefinition.cpp
    LocatorStrategy.cpp
    LocatorFactory.cpp
)
add_dependencies( locators os base )
target_link_libraries(
     locators
     os
     base
)
src/library/locate/EnvironmentVarData.cpp
New file
@@ -0,0 +1,67 @@
/*
 * EnvironmentVarData.cpp
 *
 *  Created on: Oct 12, 2019
 *     Author: Gabriele Contini
 */
#include "EnvironmentVarData.hpp"
#include <build_properties.h>
#include <cstdlib>
#include <regex>
#include <string>
#include <vector>
#include "../api/datatypes.h"
#include "../base/base64.h"
#include "../base/EventRegistry.h"
#include "../base/StringUtils.h"
namespace license {
namespace locate {
using namespace std;
EnvironmentVarData::EnvironmentVarData() :
        LocatorStrategy("EnvironmentVarData") {
}
EnvironmentVarData::~EnvironmentVarData() {
}
const vector<string> EnvironmentVarData::license_locations(
        EventRegistry &eventRegistry) {
    vector<string> diskFiles;
    char *env_var_value = getenv(LICENSE_DATA_ENV_VAR);
    if (env_var_value != nullptr && env_var_value[0] != '\0') {
        eventRegistry.addEvent(LICENSE_SPECIFIED, LICENSE_LOCATION_ENV_VAR);
        FILE_FORMAT licenseFormat = identify_format(env_var_value);
        if (licenseFormat == UNKNOWN) {
            eventRegistry.addEvent(LICENSE_MALFORMED, LICENSE_LOCATION_ENV_VAR);
        } else {
            diskFiles.push_back(LICENSE_LOCATION_ENV_VAR);
            isBase64 = (licenseFormat == BASE64);
        }
    } else {
        eventRegistry.addEvent(ENVIRONMENT_VARIABLE_NOT_DEFINED,
        LICENSE_LOCATION_ENV_VAR);
    }
    return diskFiles;
}
const std::string EnvironmentVarData::retrieve_license_content(
        const std::string &licenseLocation) const {
    string tmpVal = getenv(LICENSE_LOCATION_ENV_VAR);
    if (isBase64) {
        int flen = 0;
        unsigned char *raw = unbase64(tmpVal.c_str(), tmpVal.length(), &flen);
        string str = string(reinterpret_cast<char*>(raw));
        free(raw);
        return str;
    }
    return tmpVal;
}
}
}
src/library/locate/EnvironmentVarData.hpp
New file
@@ -0,0 +1,29 @@
/*
 * EnvironmentVarLocation.h
 *
 *  Created on: Oct 6, 2019
 *      Author: devel
 */
#ifndef SRC_LIBRARY_LOCATE_ENVIRONMENTVARDATA_H_
#define SRC_LIBRARY_LOCATE_ENVIRONMENTVARDATA_H_
#include "LocatorStrategy.hpp"
namespace license {
namespace locate {
class EnvironmentVarData: public LocatorStrategy {
private:
    bool isBase64 = false;
public:
    EnvironmentVarData();
    virtual const std::vector<std::string> license_locations(EventRegistry& eventRegistr);
    virtual const std::string retrieve_license_content(const std::string &licenseLocation) const;
    virtual ~EnvironmentVarData();
};
}
}
#endif
src/library/locate/EnvironmentVarLocation.cpp
New file
@@ -0,0 +1,46 @@
/*
 * EnvironmentVarLocation.cpp
 *
 *  Created on: Oct 12, 2019
 *      Author: Gabriele Contini
 */
#include <build_properties.h>
#include "../base/FileUtils.hpp"
#include "../base/StringUtils.h"
#include "EnvironmentVarLocation.hpp"
namespace license {
namespace locate {
using namespace std;
EnvironmentVarLocation::EnvironmentVarLocation() :
        LocatorStrategy("EnvironmentVarLocation") {
}
EnvironmentVarLocation::~EnvironmentVarLocation() {
}
const vector<string> EnvironmentVarLocation::license_locations(
        EventRegistry &eventRegistry) {
    vector<string> licenseFileFoundWithEnvVariable;
    const string varName(LICENSE_LOCATION_ENV_VAR);
    if (varName.length() > 0) {
        //var name is defined in header files.
        char *env_var_value = getenv(LICENSE_LOCATION_ENV_VAR);
        if (env_var_value != nullptr && env_var_value[0] != '\0') {
            const vector<string> declared_positions = license::split_string(
                    string(env_var_value), ';');
            licenseFileFoundWithEnvVariable = license::filter_existing_files(
                    declared_positions, eventRegistry, LICENSE_LOCATION_ENV_VAR);
        } else {
            eventRegistry.addEvent(ENVIRONMENT_VARIABLE_NOT_DEFINED);
        }
    }
    return licenseFileFoundWithEnvVariable;
}
}
}
src/library/locate/EnvironmentVarLocation.hpp
New file
@@ -0,0 +1,27 @@
/*
 * EnvironmentVarLocation.h
 *
 *  Created on: Oct 6, 2019
 *      Author: devel
 */
#ifndef SRC_LIBRARY_LOCATE_ENVIRONMENTVARLOCATION_H_
#define SRC_LIBRARY_LOCATE_ENVIRONMENTVARLOCATION_H_
#include "LocatorStrategy.hpp"
namespace license {
namespace locate {
class EnvironmentVarLocation: public LocatorStrategy {
public:
    EnvironmentVarLocation();
    virtual const std::vector<std::string> license_locations(EventRegistry& eventRegistry);
    virtual ~EnvironmentVarLocation();
};
}
}
#endif /* SRC_LIBRARY_LOCATE_ENVIRONMENTVARLOCATION_H_ */
src/library/locate/ExternalDefinition.cpp
New file
@@ -0,0 +1,76 @@
/*
 * ExplicitDefinition.cpp
 *
 *  Created on: Oct 12, 2019
 *      Author: Gabriele Contini
 */
#include <stdlib.h>
#include <cstring>
#include <string>
#include <vector>
#include "../api/datatypes.h"
#include "../base/base64.h"
#include "../base/EventRegistry.h"
#include "../base/FileUtils.hpp"
#include "../base/StringUtils.h"
#include "ExternalDefinition.hpp"
namespace license {
namespace locate {
using namespace std;
ExternalDefinition::ExternalDefinition(const LicenseLocation *location) :
        LocatorStrategy("ExternalDefinition"), m_location(location) {
}
ExternalDefinition::~ExternalDefinition() {
}
const std::vector<std::string> ExternalDefinition::license_locations(
        EventRegistry &eventRegistry) {
    vector<string> existing_pos;
    if (m_location->licenseData != nullptr
            && m_location->licenseData[0] != '\0') {
        eventRegistry.addEvent(LICENSE_SPECIFIED, get_strategy_name());
        FILE_FORMAT licenseFormat = identify_format(m_location->licenseData);
        if (licenseFormat == UNKNOWN) {
            eventRegistry.addEvent(LICENSE_MALFORMED, get_strategy_name());
        } else {
            existing_pos.push_back(get_strategy_name());
            licenseDataIsBase64 = (licenseFormat == BASE64);
        }
    }
    if (m_location->licenseFileLocation != nullptr
            && strlen(m_location->licenseFileLocation) > 0) {
        const vector<string> declared_positions = license::split_string(
                m_location->licenseFileLocation, ';');
        existing_pos = license::filter_existing_files(declared_positions,
                eventRegistry, get_strategy_name().c_str());
    }
    return existing_pos;
}
const std::string ExternalDefinition::retrieve_license_content(
        const std::string &licenseLocation) const {
    if (licenseLocation == get_strategy_name()) {
        if (licenseDataIsBase64) {
            int flen = 0;
            unsigned char *raw = unbase64(m_location->licenseData,
                    strlen(m_location->licenseData), &flen);
            string str = string(reinterpret_cast<char*>(raw));
            free(raw);
            return str;
        } else {
            return m_location->licenseData;
        }
    } else {
        return LocatorStrategy::retrieve_license_content(licenseLocation);
    }
}
} /* namespace locate */
} /* namespace license */
src/library/locate/ExternalDefinition.hpp
New file
@@ -0,0 +1,30 @@
/*
 * ExplicitDefinition.hpp
 *
 *  Created on: Oct 12, 2019
 *      Author: devel
 */
#ifndef SRC_LIBRARY_LOCATE_EXTERNALDEFINITION_HPP_
#define SRC_LIBRARY_LOCATE_EXTERNALDEFINITION_HPP_
#include "LocatorStrategy.hpp"
namespace license {
namespace locate {
class ExternalDefinition: public LocatorStrategy {
private:
    const LicenseLocation* m_location;
    bool licenseDataIsBase64 = false;
public:
    ExternalDefinition(const LicenseLocation* location);
    virtual const std::vector<std::string> license_locations(EventRegistry& eventRegistry);
    virtual const std::string retrieve_license_content(const std::string &licenseLocation) const;
    virtual ~ExternalDefinition();
};
} /* namespace locate */
} /* namespace license */
#endif /* SRC_LIBRARY_LOCATE_EXTERNALDEFINITION_HPP_ */
src/library/locate/LocatorFactory.cpp
New file
@@ -0,0 +1,46 @@
/*
 * LocatorFactory.cpp
 *
 *  Created on: Oct 13, 2019
 *      Author: Gabriele Contini
 */
#include "build_properties.h"
#include "LocatorStrategy.hpp"
#include "LocatorFactory.hpp"
#include "ApplicationFolder.hpp"
#include "EnvironmentVarData.hpp"
#include "EnvironmentVarLocation.hpp"
#include "ExternalDefinition.hpp"
namespace license {
namespace locate {
FUNCTION_RETURN LocatorFactory::get_active_strategies(
        std::vector<std::unique_ptr<LocatorStrategy>> &strategies,
        const LicenseLocation *locationHint) {
#if(FIND_LICENSE_NEAR_MODULE)
    strategies.push_back(
            std::unique_ptr<LocatorStrategy>(
                    (LocatorStrategy*) new ApplicationFolder()));
#endif
#if(FIND_LICENSE_WITH_ENV_VAR)
    strategies.push_back(
            std::unique_ptr<LocatorStrategy>(
                    (LocatorStrategy*) new EnvironmentVarLocation()));
    strategies.push_back(
            std::unique_ptr<LocatorStrategy>(
                    (LocatorStrategy*) new EnvironmentVarData()));
#endif
    if (locationHint != nullptr) {
        strategies.push_back(
                std::unique_ptr<LocatorStrategy>(
                        (LocatorStrategy*) new ExternalDefinition(locationHint)));
    }
    return strategies.size() > 0 ? FUNC_RET_OK : FUNC_RET_NOT_AVAIL;
}
}
}
src/library/locate/LocatorFactory.hpp
New file
@@ -0,0 +1,32 @@
#ifndef RETRIEVE_FACTORY_H_
#define RETRIEVE_FACTORY_H_
#include <cstddef>
#include <string>
#include <vector>
#include "../base/base.h"
#include "../api/datatypes.h"
#include "LocatorStrategy.hpp"
namespace license {
namespace locate {
class LocatorFactory {
private:
    inline LocatorFactory() {
    }
    inline ~LocatorFactory() {
    }
public:
    static FUNCTION_RETURN get_active_strategies(
            std::vector<std::unique_ptr<LocatorStrategy>> &strategiesOut,
            const LicenseLocation *locationHint);
};
}
}
#endif
src/library/locate/LocatorStrategy.cpp
New file
@@ -0,0 +1,23 @@
/*
 * EnvironmentVarLocation.cpp
 *
 *  Created on: Oct 12, 2019
 *      Author: Gabriele Contini
 */
#include <build_properties.h>
#include "../base/FileUtils.hpp"
#include "LocatorStrategy.hpp"
namespace license {
namespace locate {
using namespace std;
const string LocatorStrategy::retrieve_license_content(
        const string &licenseLocation) const {
    return get_file_contents(licenseLocation.c_str(), MAX_LICENSE_LENGTH);
}
}
}
src/library/locate/LocatorStrategy.hpp
New file
@@ -0,0 +1,60 @@
#ifndef RETRIEVER_H_
#define RETRIEVER_H_
#include <memory>
#include <cstddef>
#include <string>
#include <vector>
#include "../base/EventRegistry.h"
namespace license {
namespace locate {
/**
 * This class provides a common interface to find and retrieve
 * licenses from different sources and positions.
 *
 * Usage:
 * <ol>
 * <li> call licenseLocations to get a list of available locations (the returned format is defined by the class, it's usually the file name)</li>
 * <li> iterate over the returned vector and call retrieveLicense to get the content of the license</li>
 * </ol>
 */
class LocatorStrategy {
protected:
    const std::string m_strategy_name;
    inline LocatorStrategy(const std::string &strategyName) :
            m_strategy_name(strategyName) {
    }
public:
    virtual const std::string get_strategy_name() const {
        return m_strategy_name;
    }
    /**
     * Try to find licenses
     * @param eventRegistry
     * @return
     * A list of identifiers for call retrieve_license_content.
     */
    virtual const std::vector<std::string> license_locations(
            EventRegistry &eventRegistry) = 0;
    /**
     * Default implementation is to retrieve the license from file.
     * Subclasses may override it.
     * @param licenseLocationId
     *     String that identifies the license. It is usually the file name
     *     but can be whatever is understood by the class
     * @return
     *     a string containing the license data in INI format.
     */
    virtual const std::string retrieve_license_content(
            const std::string &licenseLocationId) const;
    inline virtual ~LocatorStrategy() {
    }
};
}
}
#endif
src/library/os/os.h
@@ -78,6 +78,14 @@
void os_initialize();
FUNCTION_RETURN verifySignature(const char* stringToVerify, const char* signatureB64);
#ifdef _WIN32
#define SETENV(VAR,VAL) _putenv_s(VAR, VAL);
#define    UNSETENV(P) _putenv_s(P, "");
#else
#define SETENV(VAR,VAL) setenv(VAR, VAL, 1);
#define    UNSETENV(P)    unsetenv(P);
#endif
#ifdef __cplusplus
}
src/tools/base_lib/win/CryptoHelperWindows.cpp
src/tools/base_lib/win/CryptoHelperWindows.h
src/tools/license-generator/CMakeLists.txt
@@ -10,7 +10,8 @@
target_link_libraries(
     license_generator_lib
     tools_base
     licensepp_static
     base
     licensecc_static
     $<$<CONFIG:Debug>:${Boost_PROGRAM_OPTIONS_LIBRARY_DEBUG}>
     $<$<NOT:$<CONFIG:Debug>>:${Boost_PROGRAM_OPTIONS_LIBRARY_RELEASE}>     
     $<$<CONFIG:Debug>:${Boost_SYSTEM_LIBRARY_DEBUG}>
src/tools/license-generator/license-generator.cpp
@@ -1,24 +1,32 @@
#include <build_properties.h>
#include <private-key.h>
#include "license-generator.h"
#include "../base_lib/CryptoHelper.h"
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <cerrno>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <string.h>
#include <iostream>
#include <string.h>
#include <boost/date_time.hpp>
#include <iterator>
#include <map>
#include <memory>
#include <regex>
#include <sstream>
#include <stdexcept>
#include <string>
#include <vector>
#include <boost/program_options.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/unordered_map.hpp>
#include <boost/assign.hpp>
#include <fstream>
#include <regex>
#include <boost/filesystem.hpp>
namespace fs = boost::filesystem;
namespace bt = boost::posix_time;
#include <private-key.h>
#include <build_properties.h>
#include "../../library/base/base64.h"
#include "../base_lib/CryptoHelper.h"
//namespace fs = boost::filesystem;
//namespace bt = boost::posix_time;
namespace po = boost::program_options;
using namespace std;
@@ -40,36 +48,34 @@
po::options_description LicenseGenerator::configureProgramOptions() {
    po::options_description common("General options");
    common.add_options()
        ("help,h", "print help message and exit.")
        ("verbose,v", "print more information.")
    common.add_options()("help,h", "print help message and exit.") //
    ("verbose,v", "print more information.")//
        ("output,o", po::value<string>(), "Output file name. If not specified the "
            "license will be printed in standard output")
        ;
            "license will be printed to standard output");
    po::options_description licenseGeneration("License Generation");
    licenseGeneration.add_options()
        ("private_key,p", po::value<string>(),
    licenseGeneration.add_options()("private_key,p", po::value<string>(),
            "Specify an alternate file for the primary key to be used. "
                    "If not specified the internal primary key will be used.")
        ("begin_date,b", po::value<string>(),
                    "If not specified the internal primary key will be used.")(
            "begin_date,b", po::value<string>(),
            "Specify the start of the validity for this license. "
                    " Format YYYYMMDD. If not specified defaults to today")
        ("expire_date,e", po::value<string>(),
                    " Format YYYYMMDD. If not specified defaults to today")(
            "expire_date,e", po::value<string>(),
            "Specify the expire date for this license. "
                    " Format YYYYMMDD. If not specified the license won't expire")
        ("client_signature,s", po::value<string>(),
                    " Format YYYYMMDD. If not specified the license won't expire")(
            "client_signature,s", po::value<string>(),
            "The signature of the pc that requires the license. "
                    "It should be in the format XXXX-XXXX-XXXX-XXXX."
                    " If not specified the license "
                    "won't be linked to a specific pc.")
        ("start_version,t", po::value<unsigned int>()->default_value(0
                    "won't be linked to a specific pc.")("start_version,t",
            po::value<unsigned int>()->default_value(0
            /*FullLicenseInfo.UNUSED_SOFTWARE_VERSION*/, "All Versions"),
            "Specify the first version of the software this license apply to.")
        ("end_version,n", po::value<unsigned int>()->default_value(0
            "Specify the first version of the software this license apply to.")(
            "end_version,n", po::value<unsigned int>()->default_value(0
            /*FullLicenseInfo.UNUSED_SOFTWARE_VERSION*/, "All Versions"),
            "Specify the last version of the software this license apply to.")
        ("extra_data,x", po::value<string>(), "Specify extra data to be included into the license")
        ;
            "Specify the last version of the software this license apply to.")(
            "extra_data,x", po::value<string>(),
            "Specify extra data to be included into the license");
    po::options_description visibleOptions;
    visibleOptions.add(common).add(licenseGeneration);
    return visibleOptions;
@@ -108,7 +114,8 @@
    if (vm.count("client_signature")) {
        client_signature = vm["client_signature"].as<string>();
        cout << "cli sig:" << client_signature;
        regex e("[A-Za-z0-9\\+/]{4}-[A-Za-z0-9\\+/]{4}-[A-Za-z0-9\\+/]{4}-[A-Za-z0-9\\+/]{4}");
        regex e(
                "[A-Za-z0-9\\+/]{4}-[A-Za-z0-9\\+/]{4}-[A-Za-z0-9\\+/]{4}-[A-Za-z0-9\\+/]{4}");
        cout << "\nregex:";
        if (!regex_match(client_signature, e)) {
            cerr << endl << "Client signature not recognized: "
@@ -150,10 +157,24 @@
    const size_t len = sizeof(pkey);
    for (auto it = licenseInfo.begin(); it != licenseInfo.end(); ++it) {
        const string license = it->printForSign();
        const string signature = helper->signString((const void *)pkey,len,license);
        const string signature = helper->signString((const void*) pkey, len,
                license);
        it->license_signature = signature;
        it->printAsIni(outputFile);
    }
}
void LicenseGenerator::generateB64Licenses(const po::variables_map &vm,
        ostream &outputFile) {
    std::ostringstream tempStream;
    generateAndOutputLicenses(vm, tempStream);
    std::string str = tempStream.str();
    const char *chr = str.c_str();
    int finalLenght;
    char *encoded = base64(chr, str.length(), &finalLenght);
    outputFile.write(encoded, finalLenght);
    free(encoded);
}
int LicenseGenerator::generateLicense(int argc, const char **argv) {
@@ -183,13 +204,21 @@
        fstream ofstream(fname, std::ios::out | std::ios::app);
        if (!ofstream.is_open()) {
            cerr << "can't open file [" << fname << "] for output." << endl
                    << " error: " << strerror( errno);
                    << " error: " << strerror(errno) << endl;
            exit(3);
        }
        if (vm.count("base64")) {
            generateB64Licenses(vm, ofstream);
        } else {
        generateAndOutputLicenses(vm, ofstream);
        }
        ofstream.close();
    } else {
        if (vm.count("base64")) {
            generateB64Licenses(vm, cout);
        } else {
        generateAndOutputLicenses(vm, cout);
        }
    }
    return 0;
}
@@ -203,7 +232,8 @@
    unsigned int year, month, day;
    bool found = false;
    for (size_t i = 0; i < formats_n && !found; ++i) {
        const int chread = sscanf(sDate.c_str(),formats[i].c_str(),&year,&month,&day);
        const int chread = sscanf(sDate.c_str(), formats[i].c_str(), &year,
                &month, &day);
        if(chread==3) {
            found = true;
            break;
@@ -212,7 +242,8 @@
    if(!found)
        throw invalid_argument("Date string did not match a known format");
    ostringstream oss;
    oss << year << "-" << setfill('0') << std::setw(2) << month << "-" << setfill('0') << std::setw(2) << day;
    oss << year << "-" << setfill('0') << std::setw(2) << month << "-"
            << setfill('0') << std::setw(2) << day;
    return oss.str();
}
}
src/tools/license-generator/license-generator.h
@@ -9,7 +9,7 @@
#define LICENSE_GENERATOR_H_
#include <boost/program_options.hpp>
#include "../../library/LicenseReader.h"
#include "../../library/LicenseReader.hpp"
namespace license {
@@ -21,12 +21,15 @@
class LicenseGenerator {
private:
    LicenseGenerator();
    static void printHelp(const char* prog_name, const po::options_description& options);
    static po::options_description configureProgramOptions();
    static vector<FullLicenseInfo> parseLicenseInfo(const po::variables_map& vm);
    static std::vector<FullLicenseInfo> parseLicenseInfo(const po::variables_map& vm);
    static void generateAndOutputLicenses(const po::variables_map& vm,
            ostream& outputFile);
    static string normalize_date(const std::string& s);
            std::ostream& outputFile);
    static void generateB64Licenses(const po::variables_map& vm,
            std::ostream& outputFile);
    static std::string normalize_date(const std::string& s);
public:
    /**
     * Available options:
test/functional/CMakeLists.txt
@@ -8,37 +8,37 @@
)
add_executable(
 standard_license_test
 test_standard_license
 standard-license_test.cpp
)
target_link_libraries(
 standard_license_test
 licensepp_static
 test_standard_license
 licensecc_static
 license_generator_snippet
 ${Boost_LIBRARIES}
)
add_executable(
 date_test
 test_date
 date_test.cpp
)
target_link_libraries(
 date_test
 licensepp_static
 test_date
 licensecc_static
 license_generator_snippet
 ${Boost_LIBRARIES}
)
add_executable(
 volid_test
 test_volid
 volid_test.cpp
)
target_link_libraries(
 volid_test
 licensepp_static
 test_volid
 licensecc_static
 license_generator_snippet
 ${Boost_LIBRARIES}
)
@@ -46,13 +46,13 @@
IF( ( CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") AND CMAKE_CROSSCOMPILING)
#binfmt_misc doesn't work in my system :(
    ADD_TEST(NAME standard_license_test COMMAND wine ${CMAKE_CURRENT_BINARY_DIR}/standard_license_test WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
    ADD_TEST(NAME date_test COMMAND wine ${CMAKE_CURRENT_BINARY_DIR}/date_test WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
    ADD_TEST(NAME volid_test COMMAND wine ${CMAKE_CURRENT_BINARY_DIR}/volid_test WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
    ADD_TEST(NAME test_standard_license COMMAND wine ${CMAKE_CURRENT_BINARY_DIR}/test_standard_license WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
    ADD_TEST(NAME test_date COMMAND wine ${CMAKE_CURRENT_BINARY_DIR}/test_date WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
    ADD_TEST(NAME test_volid COMMAND wine ${CMAKE_CURRENT_BINARY_DIR}/test_volid WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
ELSE()
    ADD_TEST(NAME standard_license_test COMMAND standard_license_test WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
    ADD_TEST(NAME date_test COMMAND date_test WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
    ADD_TEST(NAME volid_test COMMAND volid_test WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
    ADD_TEST(NAME test_standard_license COMMAND test_standard_license WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
    ADD_TEST(NAME test_date COMMAND test_date WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
    ADD_TEST(NAME test_volid COMMAND test_volid WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
ENDIF()
test/functional/date_test.cpp
@@ -1,17 +1,19 @@
#define BOOST_TEST_MODULE date_test
//#define BOOST_TEST_MAIN
//#define BOOST_TEST_DYN_LINK
#include <boost/test/unit_test.hpp>
#include <boost/filesystem.hpp>
#include <build_properties.h>
#include "../../src/tools/license-generator/license-generator.h"
#include "../../src/library/api/license++.h"
#include <build_properties.h>
#include <boost/filesystem.hpp>
#include "../../src/library/ini/SimpleIni.h"
#include "generate-license.h"
namespace fs = boost::filesystem;
using namespace license;
using namespace std;
namespace test {
BOOST_AUTO_TEST_CASE( license_not_expired ) {
    const string licLocation(PROJECT_TEST_TEMP_DIR "/not_expired.lic");
@@ -22,10 +24,10 @@
    /* */
    LicenseInfo license;
    LicenseLocation licenseLocation;
    licenseLocation.openFileNearModule = false;
    licenseLocation.licenseFileLocation = licLocation.c_str();
    licenseLocation.environmentVariableName = "";
    const EVENT_TYPE result = acquire_license("TEST", licenseLocation, &license);
    licenseLocation.licenseData = "";
    const EVENT_TYPE result = acquire_license("TEST", &licenseLocation,
            &license);
    BOOST_CHECK_EQUAL(result, LICENSE_OK);
    BOOST_CHECK_EQUAL(license.has_expiry, true);
    BOOST_CHECK_EQUAL(license.linked_to_pc, false);
@@ -33,6 +35,7 @@
BOOST_AUTO_TEST_CASE( license_expired ) {
    const string licLocation(PROJECT_TEST_TEMP_DIR "/expired.lic");
    remove(licLocation.c_str());
    vector<string> extraArgs;
    extraArgs.push_back("-e");
    extraArgs.push_back("2013-10-10");
@@ -40,11 +43,14 @@
    /* */
    LicenseInfo license;
    LicenseLocation licenseLocation;
    licenseLocation.openFileNearModule = false;
    licenseLocation.licenseFileLocation = licLocation.c_str();
    licenseLocation.environmentVariableName = "";
    const EVENT_TYPE result = acquire_license("TEST", licenseLocation, &license);
    licenseLocation.licenseData = nullptr;
    BOOST_TEST_MESSAGE("before acquire license");
    const EVENT_TYPE result = acquire_license("TEST", &licenseLocation,
            &license);
    BOOST_CHECK_EQUAL(result, PRODUCT_EXPIRED);
    BOOST_CHECK_EQUAL(license.has_expiry, true);
    BOOST_CHECK_EQUAL(license.linked_to_pc, false);
}
}
test/functional/generate-license.cpp
@@ -17,6 +17,7 @@
using namespace std;
void generate_license(const string& fname, const vector<string>& other_args) {
    remove(fname.c_str());
    const int argc = 4+other_args.size();
    const char** argv = new const char*[argc + 1];
    unsigned int i=0;
test/functional/generate-license.h
@@ -1,5 +1,3 @@
#include<string>
#include<vector>
test/functional/hijiaking_test.cpp
@@ -2,8 +2,8 @@
//#define BOOST_TEST_MAIN
//#define BOOST_TEST_DYN_LINK
#include <boost/test/unit_test.hpp>
#include "../../../src/license-generator/license-generator.h"
#include "../../../src/library/api/license++.h"
#include "../../src/tools/license-generator/license-generator.h"
#include "../../src/library/api/license++.h"
#include <build_properties.h>
#include <boost/filesystem.hpp>
#include "../../src/library/ini/SimpleIni.h"
@@ -23,7 +23,7 @@
    LicenseLocation licenseLocation;
    licenseLocation.openFileNearModule=false;
    licenseLocation.licenseFileLocation = licLocation.c_str();
    licenseLocation.environmentVariableName = "";
    licenseLocation.licenseData = "";
    EVENT_TYPE result = acquire_license("TEST",
            licenseLocation, & license);
    BOOST_CHECK_EQUAL(result, LICENSE_OK);
test/functional/standard-license_test.cpp
@@ -1,6 +1,5 @@
#define BOOST_TEST_MODULE standard_license_test
//#define BOOST_TEST_MAIN
//#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE test_standard_license
#include <boost/test/unit_test.hpp>
#include "../../src/tools/license-generator/license-generator.h"
#include "../../src/library/api/license++.h"
@@ -8,11 +7,12 @@
#include <boost/filesystem.hpp>
#include "../../src/library/ini/SimpleIni.h"
#include "generate-license.h"
#include "../../src/library/base/FileUtils.hpp"
namespace test {
namespace fs = boost::filesystem;
using namespace license;
using namespace std;
BOOST_AUTO_TEST_CASE( standard_lic_file ) {
    const string licLocation(PROJECT_TEST_TEMP_DIR "/standard_license.lic");
@@ -21,14 +21,48 @@
    /* */
    LicenseInfo license;
    LicenseLocation licenseLocation;
    licenseLocation.openFileNearModule=false;
    licenseLocation.licenseFileLocation = licLocation.c_str();
    licenseLocation.environmentVariableName = "";
    const EVENT_TYPE result = acquire_license("TEST",
            licenseLocation, & license);
    licenseLocation.licenseData = nullptr;
    const EVENT_TYPE result = acquire_license("TEST", &licenseLocation,
            &license);
    BOOST_CHECK_EQUAL(result, LICENSE_OK);
    BOOST_CHECK_EQUAL(license.has_expiry, false);
    BOOST_CHECK_EQUAL(license.linked_to_pc, false);
}
/**
 * Pass the license data to the application.
 */
BOOST_AUTO_TEST_CASE( b64_environment_variable ) {
    const string licLocation(PROJECT_TEST_TEMP_DIR "/standard_env_license.lic");
    const vector<string> extraArgs;
    generate_license(licLocation, extraArgs);
    const string licensestr(license::get_file_contents(licLocation.c_str(), MAX_LICENSE_LENGTH));
    /* */
    LicenseInfo license;
    LicenseLocation licenseLocation;
    licenseLocation.licenseFileLocation = nullptr;
    licenseLocation.licenseData = licensestr.c_str();
    const EVENT_TYPE result = acquire_license("TEST", &licenseLocation,
            &license);
    BOOST_CHECK_EQUAL(result, LICENSE_OK);
    BOOST_CHECK_EQUAL(license.has_expiry, false);
    BOOST_CHECK_EQUAL(license.linked_to_pc, false);
}
BOOST_AUTO_TEST_CASE( pc_identifier ) {
    const string licLocation(PROJECT_TEST_TEMP_DIR "/pc_identifier.lic");
    const vector<string> extraArgs = { "-s", "Jaaa-aaaa-MG9F-ZhB1" };
    generate_license(licLocation, extraArgs);
    LicenseInfo license;
    LicenseLocation licenseLocation;
    licenseLocation.licenseFileLocation = licLocation.c_str();
    licenseLocation.licenseData = "";
    const EVENT_TYPE result = acquire_license("TEST", &licenseLocation,
            &license);
    BOOST_CHECK_EQUAL(result, IDENTIFIERS_MISMATCH);
    BOOST_CHECK_EQUAL(license.has_expiry, false);
    BOOST_CHECK_EQUAL(license.linked_to_pc, true);
}
}
test/functional/volid_test.cpp
@@ -1,6 +1,5 @@
#define BOOST_TEST_MODULE standard_license_test
//#define BOOST_TEST_MAIN
//#undef BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE test_volid
#include <boost/test/unit_test.hpp>
#include <fstream>
#include <stdio.h>
@@ -36,10 +35,9 @@
    LicenseInfo license;
    LicenseLocation licenseLocation;
    licenseLocation.openFileNearModule = false;
    licenseLocation.licenseFileLocation = licLocation.c_str();
    licenseLocation.environmentVariableName = "";
    const EVENT_TYPE result = acquire_license("TEST", licenseLocation, &license);
    licenseLocation.licenseData = "";
    const EVENT_TYPE result = acquire_license("TEST", &licenseLocation, &license);
    BOOST_CHECK_EQUAL(result, LICENSE_OK);
    BOOST_CHECK_EQUAL(license.has_expiry, false);
    BOOST_CHECK_EQUAL(license.linked_to_pc, true);
test/library/CMakeLists.txt
@@ -1,34 +1,72 @@
add_executable(
 license_reader_test
 test_license_reader
 LicenseReader_test.cpp
)
target_link_libraries(
 license_reader_test
 licensepp_static
 test_license_reader
 licensecc_static
 ${Boost_LIBRARIES}
)
IF( ( CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") AND CMAKE_CROSSCOMPILING)
#binfmt_misc doesn't work in my system :(
    ADD_TEST(NAME license_reader_test COMMAND wine ${CMAKE_CURRENT_BINARY_DIR}/license_reader_test)
    ADD_TEST(NAME test_license_reader COMMAND wine ${CMAKE_CURRENT_BINARY_DIR}/test_license_reader)
ELSE()
    ADD_TEST(NAME license_reader_test COMMAND license_reader_test)
    ADD_TEST(NAME test_license_reader COMMAND test_license_reader)
ENDIF()
IF(WIN32)
#test windows
ELSE(WIN32)
    add_executable(
         os_linux_test
         test_os_linux
         Os_Linux_test.cpp
    )
    target_link_libraries(
         os_linux_test
         test_os_linux
         os
         ${Boost_LIBRARIES}
    )
    ADD_TEST(NAME os_linux_test COMMAND os_linux_test)
    ADD_TEST(NAME test_os_linux COMMAND test_os_linux)
ENDIF(WIN32)
### LicenseLocator tests
add_executable(
 test_license_locator
 LicenseLocator_test.cpp
)
target_link_libraries(
 test_license_locator
 locators
 ${Boost_LIBRARIES}
)
IF( ( CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") AND CMAKE_CROSSCOMPILING)
#binfmt_misc doesn't work in my system :(
    ADD_TEST(NAME test_license_locator COMMAND wine ${CMAKE_CURRENT_BINARY_DIR}/test_license_locator)
ELSE()
    ADD_TEST(NAME test_license_locator COMMAND test_license_locator)
ENDIF()
### LicenseLocator tests
add_executable(
 test_event_registry
 EventRegistry_test.cpp
)
target_link_libraries(
 test_event_registry
 base
 ${Boost_LIBRARIES}
)
IF( ( CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") AND CMAKE_CROSSCOMPILING)
    ADD_TEST(NAME test_event_registry COMMAND wine ${CMAKE_CURRENT_BINARY_DIR}/test_event_registry)
ELSE()
    ADD_TEST(NAME test_event_registry COMMAND test_event_registry)
ENDIF()
test/library/EventRegistry_test.cpp
New file
@@ -0,0 +1,41 @@
#define BOOST_TEST_MODULE "test_event_registry"
#include <iostream>
#include <iterator>
#include <fstream>
#include <string>
#include <vector>
#include <boost/filesystem.hpp>
#include <boost/optional.hpp>
#include <boost/test/unit_test.hpp>
#include <stdlib.h>
#include <cstdio>
#include <build_properties.h>
#include "../../src/library/base/EventRegistry.h"
namespace test {
using namespace std;
using namespace license;
/**
 * The error reported is for the license that advanced most in the validation process
 *
 */
BOOST_AUTO_TEST_CASE( test_most_advanced_license_error ) {
    EventRegistry er;
    er.addEvent(LICENSE_SPECIFIED, "lic2");
    er.addEvent(LICENSE_FOUND, "lic1");
    er.addEvent(LICENSE_CORRUPTED, "lic1");
    er.turnWarningsIntoErrors();
    const AuditEvent *event = er.getLastFailure();
    BOOST_CHECK_MESSAGE(event != nullptr, "An error is detected");
    BOOST_CHECK_MESSAGE(string("lic1") == event->license_reference, "Error is for lic1");
    BOOST_CHECK_MESSAGE(LICENSE_CORRUPTED == event->event_type, "Error is for LICENSE_CORRUPTED");
}
}  //namespace test
test/library/LicenseLocator_test.cpp
New file
@@ -0,0 +1,217 @@
#define BOOST_TEST_MODULE "test_license_locator"
#include <iostream>
#include <iterator>
#include <fstream>
#include <string>
#include <vector>
#include <boost/filesystem.hpp>
#include <boost/optional.hpp>
#include <boost/test/unit_test.hpp>
#include <stdlib.h>
#include <cstdio>
#include <build_properties.h>
#include "../../src/library/os/os.h"
#include "../../src/library/base/EventRegistry.h"
#include "../../src/library/locate/ApplicationFolder.hpp"
#include "../../src/library/locate/EnvironmentVarLocation.hpp"
#include "../../src/library/locate/ExternalDefinition.hpp"
#define MOCK_LICENSE PROJECT_TEST_SRC_DIR "/library/test_reader.ini"
namespace test {
using namespace license::locate;
using namespace std;
using namespace boost::filesystem;
static boost::optional<path> find_file(const path& dir_path, const path& file_name) {
    const recursive_directory_iterator end;
    const auto it = find_if(recursive_directory_iterator(dir_path), end,
        [&file_name](const directory_entry& e) {
            return e.path().filename() == file_name;
        });
    return it == end ? boost::optional<path>() : it->path();
}
/*****************************************************************************
 * Application Folder tests
 *****************************************************************************/
BOOST_AUTO_TEST_CASE( read_license_near_module ) {
    const string testExeFolder = PROJECT_BINARY_DIR "/test/library";
    bool exeFileFound = false;
    string referenceExeFileName;
    string referenceLicenseFileName;
    //Verify we're pointing the correct executable, in windows isn't clear where it's built
#ifdef _WIN32
    boost::optional<path> exeLocation(find_file(path(testExeFolder), path(BOOST_TEST_MODULE ".exe")));
    exeFileFound = exeLocation.has_value();
    if (exeFileFound) {
        referenceExeFileName = exeLocation.get().string();
        referenceLicenseFileName = referenceExeFileName.replace(referenceExeFileName.find(BOOST_TEST_MODULE ".exe"),
            string(BOOST_TEST_MODULE ".exe").size(), BOOST_TEST_MODULE ".lic");
    }
#else
    referenceExeFileName = testExeFolder + "/" + BOOST_TEST_MODULE;
    std::ifstream f(referenceExeFileName.c_str());
    exeFileFound = f.good();
    referenceLicenseFileName = testExeFolder + "/" + BOOST_TEST_MODULE ".lic";
#endif
    BOOST_WARN_MESSAGE(!exeFileFound, "File [" + referenceExeFileName + "] NOT found");
    if (exeFileFound) {
        //copy test license near module
        std::ifstream src(MOCK_LICENSE, std::ios::binary);
        std::ofstream dst(referenceLicenseFileName, std::ios::binary);
        dst << src.rdbuf();
        dst.close();
        license::EventRegistry registry;
        ApplicationFolder applicationFolder;
        vector<string> licenseInfos = applicationFolder.license_locations(registry);
        BOOST_CHECK(registry.isGood());
        BOOST_REQUIRE_EQUAL(1, licenseInfos.size());
        string currentLocation = licenseInfos[0];
        BOOST_CHECK_MESSAGE(equivalent(path(referenceLicenseFileName),path(currentLocation)),
            "file " +currentLocation + "found at expected location");
        string licenseRealContent = applicationFolder.retrieve_license_content(
            currentLocation);
        src.seekg(0, ios::beg);
        std::string referenceContent((std::istreambuf_iterator<char>(src)),
            std::istreambuf_iterator<char>());
        BOOST_CHECK_MESSAGE(referenceContent.compare(licenseRealContent) == 0,
            "File content is same");
        remove(referenceLicenseFileName.c_str());
    }
}
/*****************************************************************************
 * External_Definition tests
 *****************************************************************************/
BOOST_AUTO_TEST_CASE( external_definition ) {
    //an application can define multiple license locations separated by ';'
    const char *applicationDefinedString =
    MOCK_LICENSE ";/this/one/doesnt/exist";
    //read test license
    std::ifstream src(MOCK_LICENSE, std::ios::binary);
    std::string referenceContent((std::istreambuf_iterator<char>(src)),
            std::istreambuf_iterator<char>());
    license::EventRegistry registry;
    const LicenseLocation licLocation({applicationDefinedString,nullptr});
    ExternalDefinition externalDefinition(&licLocation);
    vector<string> licenseInfos = externalDefinition.license_locations(registry);
    BOOST_CHECK(registry.isGood());
    BOOST_CHECK_EQUAL(1, licenseInfos.size());
    string currentLocation = licenseInfos[0];
    BOOST_CHECK_MESSAGE(string(MOCK_LICENSE).compare(currentLocation) == 0,
            "file found at expected location");
    string licenseRealContent = externalDefinition.retrieve_license_content(
            currentLocation);
    BOOST_CHECK_MESSAGE(referenceContent.compare(licenseRealContent) == 0,
            "File content is same");
}
/**
 * The license file doesn't exist. Check that the locator reports the right error
 */
BOOST_AUTO_TEST_CASE( external_definition_not_found ) {
    const char *applicationDefinedString = PROJECT_TEST_SRC_DIR "/this/file/doesnt/exist";
    license::EventRegistry registry;
    const LicenseLocation licLocation({applicationDefinedString,nullptr});
    ExternalDefinition externalDefinition(&licLocation);
    vector<string> licenseInfos = externalDefinition.license_locations(registry);
    BOOST_CHECK_MESSAGE(registry.isGood(),
            "No fatal error for now, only warnings");
    registry.turnWarningsIntoErrors();
    BOOST_REQUIRE_MESSAGE(!registry.isGood(), "Error detected");
    BOOST_CHECK_EQUAL(0, licenseInfos.size());
    BOOST_CHECK_MESSAGE(
            registry.getLastFailure()->event_type == LICENSE_FILE_NOT_FOUND,
            "Error detected");
}
/*****************************************************************************
 * EnvironmentVarLocation tests
 *****************************************************************************/
BOOST_AUTO_TEST_CASE( environment_var_location ) {
    //an application can define multiple license locations separated by ';'
    const char *environment_variable_value =
    MOCK_LICENSE ";/this/one/doesnt/exist";
#ifdef _WIN32
    _putenv_s(LICENSE_LOCATION_ENV_VAR, environment_variable_value);
#else
    setenv(LICENSE_LOCATION_ENV_VAR, environment_variable_value, 1);
#endif
    //read test license
    std::ifstream src(MOCK_LICENSE, std::ios::binary);
    std::string referenceContent((std::istreambuf_iterator<char>(src)),
            std::istreambuf_iterator<char>());
    license::EventRegistry registry;
    EnvironmentVarLocation envVarLocationStrategy;
    vector<string> licenseInfos = envVarLocationStrategy.license_locations(
            registry);
    BOOST_CHECK(registry.isGood());
    BOOST_CHECK_EQUAL(1, licenseInfos.size());
    string currentLocation = licenseInfos[0];
    BOOST_CHECK_MESSAGE(string(MOCK_LICENSE).compare(currentLocation) == 0,
            "file found at expected location");
    string licenseRealContent = envVarLocationStrategy.retrieve_license_content(
            currentLocation);
    BOOST_CHECK_MESSAGE(referenceContent.compare(licenseRealContent) == 0,
            "File content is same");
    UNSETENV(LICENSE_LOCATION_ENV_VAR);
}
/**
 * The license file doesn't exist. Check that the locator reports the right error
 */
BOOST_AUTO_TEST_CASE( environment_var_location_not_found ) {
    const char *environment_variable_value =
    PROJECT_TEST_SRC_DIR "/this/file/doesnt/exist";
    SETENV(LICENSE_LOCATION_ENV_VAR, environment_variable_value);
    license::EventRegistry registry;
    EnvironmentVarLocation envVarLocationStrategy;
    vector<string> licenseInfos = envVarLocationStrategy.license_locations(
            registry);
    BOOST_CHECK_MESSAGE(registry.isGood(),
            "No fatal error for now, only warnings");
    registry.turnWarningsIntoErrors();
    BOOST_REQUIRE_MESSAGE(!registry.isGood(), "Error detected");
    BOOST_CHECK_EQUAL(0, licenseInfos.size());
    BOOST_CHECK_MESSAGE(
            registry.getLastFailure()->event_type == LICENSE_FILE_NOT_FOUND,
            "Error detected");
    UNSETENV(LICENSE_LOCATION_ENV_VAR);
}
/**
 * The license file doesn't exist. Check that the locator reports the right error
 */
BOOST_AUTO_TEST_CASE( environment_var_location_not_defined ) {
    UNSETENV(LICENSE_LOCATION_ENV_VAR);
    license::EventRegistry registry;
    EnvironmentVarLocation environmentVarLocation;
    vector<string> licenseInfos = environmentVarLocation.license_locations(
            registry);
    BOOST_CHECK_MESSAGE(registry.isGood(),
            "No fatal error for now, only warnings");
    registry.turnWarningsIntoErrors();
    BOOST_REQUIRE_MESSAGE(!registry.isGood(), "Error detected");
    BOOST_CHECK_EQUAL(0, licenseInfos.size());
    BOOST_CHECK_MESSAGE(
            registry.getLastFailure()->event_type
                    == ENVIRONMENT_VARIABLE_NOT_DEFINED, "Error detected");
}
}  //namespace test
test/library/LicenseReader_test.cpp
@@ -1,18 +1,32 @@
#define BOOST_TEST_MODULE license_reader_test
//#define BOOST_TEST_MAIN
//#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE "test_license_reader"
#include <boost/assert.hpp>
#include <boost/test/tools/old/interface.hpp>
#include <boost/test/unit_test_suite.hpp>
#include <iostream>
#include <vector>
#include "../../src/library/api/datatypes.h"
#include "../../src/library/base/EventRegistry.h"
#include "../../src/library/os/os.h"
#include <boost/test/unit_test.hpp>
#include "../../src/library/LicenseReader.h"
#include <build_properties.h>
#include <stdlib.h>
using namespace license;
#include <build_properties.h>
#include "../../src/library/LicenseReader.hpp"
namespace test {
using namespace license;
using namespace std;
/**
 * Read license at fixed location
 */
BOOST_AUTO_TEST_CASE( read_single_file ) {
    const char * licLocation =
    PROJECT_TEST_SRC_DIR "/library/test_reader.ini";
    const LicenseLocation location = { licLocation, nullptr, false };
    LicenseReader licenseReader(location);
    const char *licLocation = PROJECT_TEST_SRC_DIR "/library/test_reader.ini";
    const LicenseLocation location = { licLocation, nullptr };
    LicenseReader licenseReader(&location);
    vector<FullLicenseInfo> licenseInfos;
    const EventRegistry registry = licenseReader.readLicenses("PrODUCT",
            licenseInfos);
@@ -20,11 +34,14 @@
    BOOST_CHECK_EQUAL(1, licenseInfos.size());
}
/**
 * Test the error return if the product code is not found in the license
 */
BOOST_AUTO_TEST_CASE( product_not_licensed ) {
    const char * licLocation =
    PROJECT_TEST_SRC_DIR "/library/test_reader.ini";
    const LicenseLocation location = { licLocation, nullptr, false };
    LicenseReader licenseReader(location);
    const LicenseLocation location = { licLocation, nullptr };
    LicenseReader licenseReader(&location);
    vector<FullLicenseInfo> licenseInfos;
    const EventRegistry registry = licenseReader.readLicenses("PRODUCT-NOT",
            licenseInfos);
@@ -35,11 +52,14 @@
            registry.getLastFailure()->event_type);
}
/**
 * Test the error code if the license file is specified but doesn't exists
 */
BOOST_AUTO_TEST_CASE( file_not_found ) {
    const char * licLocation = PROJECT_TEST_SRC_DIR "/library/not_found.ini";
    //const char * envName = "MYVAR";
    const LicenseLocation location = { licLocation, nullptr, false };
    LicenseReader licenseReader(location);
    const LicenseLocation location = { licLocation, nullptr };
    LicenseReader licenseReader(&location);
    vector<FullLicenseInfo> licenseInfos;
    const EventRegistry registry = licenseReader.readLicenses("PRODUCT",
            licenseInfos);
@@ -50,10 +70,13 @@
            registry.getLastFailure()->event_type);
}
/**
 * Test the error code if the license default environment variable isn't specified
 */
BOOST_AUTO_TEST_CASE( env_var_not_defined ) {
    const char * envName = "MYVAR";
    const LicenseLocation location = {nullptr, envName, false };
    LicenseReader licenseReader(location);
    UNSETENV(LICENSE_LOCATION_ENV_VAR);
    const LicenseLocation location = { nullptr, nullptr };
    LicenseReader licenseReader(&location);
    vector<FullLicenseInfo> licenseInfos;
    const EventRegistry registry = licenseReader.readLicenses("PRODUCT",
            licenseInfos);
@@ -64,16 +87,26 @@
            registry.getLastFailure()->event_type);
}
BOOST_AUTO_TEST_CASE( read_env_var ) {
    char str[MAX_PATH];
    strcpy(str,"LIC_VAR=" PROJECT_TEST_SRC_DIR "/library/test_reader.ini");
    putenv(str);
    const LicenseLocation location = {nullptr, "LIC_VAR", false };
    LicenseReader licenseReader(location);
    vector<FullLicenseInfo> licenseInfos;
    const EventRegistry registry = licenseReader.readLicenses("PrODUCT",
            licenseInfos);
    BOOST_CHECK(registry.isGood());
    BOOST_CHECK_EQUAL(1, licenseInfos.size());
}
/**
 * Test the error code if the license default environment variable is
 * specified but points to a non existent file.
 */
BOOST_AUTO_TEST_CASE( env_var_point_to_wrong_file ) {
    const char *environment_variable_value =
    PROJECT_TEST_SRC_DIR "/this/file/doesnt/exist";
    SETENV(LICENSE_LOCATION_ENV_VAR, environment_variable_value)
    const LicenseLocation location = { nullptr, nullptr };
    LicenseReader licenseReader(&location);
    vector<FullLicenseInfo> licenseInfos;
    const EventRegistry registry = licenseReader.readLicenses("PRODUCT",
            licenseInfos);
    cout << registry << endl;
    BOOST_CHECK(!registry.isGood());
    BOOST_CHECK_EQUAL(0, licenseInfos.size());
    BOOST_ASSERT(registry.getLastFailure()!=NULL);
    BOOST_CHECK_EQUAL(LICENSE_FILE_NOT_FOUND,
            registry.getLastFailure()->event_type);
    UNSETENV(LICENSE_LOCATION_ENV_VAR);
}
} /* namespace test*/
test/license-generator/license-generator_test.cpp
@@ -2,9 +2,10 @@
//#define BOOST_TEST_MAIN
//#define BOOST_TEST_DYN_LINK
#include <boost/test/unit_test.hpp>
#include "../../src/tools/license-generator/license-generator.h"
#include <build_properties.h>
#include <boost/filesystem.hpp>
#include <build_properties.h>
#include "../../src/tools/license-generator/license-generator.h"
#include "../../src/library/ini/SimpleIni.h"
namespace fs = boost::filesystem;