From 497745ad31c90545b288e2845049e0ce474bcbe2 Mon Sep 17 00:00:00 2001
From: gcontini <1121667+gcontini@users.noreply.github.com>
Date: 周六, 19 10月 2019 10:10:45 +0800
Subject: [PATCH] Merge branch 'feature/code_review_and_refactor' into develop

---
 src/library/locate/EnvironmentVarData.hpp         |   29 
 src/library/api/datatypes.h                       |   49 
 src/library/locate/ExternalDefinition.hpp         |   30 
 src/library/os/os.h                               |   10 
 src/library/locate/EnvironmentVarLocation.hpp     |   27 
 src/library/locate/LocatorStrategy.cpp            |   23 
 test/functional/generate-license.h                |    4 
 test/functional/CMakeLists.txt                    |   30 
 test/functional/hijiaking_test.cpp                |    6 
 src/library/locate/LocatorFactory.hpp             |   32 
 src/tools/license-generator/license-generator.h   |   13 
 src/library/locate/ApplicationFolder.cpp          |   56 
 test/library/LicenseLocator_test.cpp              |  217 +++
 CONTRIBUTING.md                                   |    9 
 test/functional/volid_test.cpp                    |   10 
 README.md                                         |    2 
 src/tools/license-generator/CMakeLists.txt        |    3 
 src/library/LicenseReader.cpp                     |  334 +---
 src/library/locate/CMakeLists.txt                 |   18 
 src/library/base/FileUtils.hpp                    |   22 
 src/library/locate/ExternalDefinition.cpp         |   76 +
 .gitignore                                        |    6 
 src/library/base/base64.h                         |  140 --
 src/library/api/license++.h                       |   44 
 src/tools/license-generator/license-generator.cpp |  141 +
 test/functional/generate-license.cpp              |    3 
 src/library/locate/EnvironmentVarData.cpp         |   67 +
 src/library/base/base64.c                         |  133 ++
 src/library/locate/LocatorStrategy.hpp            |   60 +
 src/library/base/CMakeLists.txt                   |    2 
 test/library/CMakeLists.txt                       |   54 
 src/library/base/EventRegistry.h                  |   56 
 src/library/base/base.h                           |    6 
 src/library/locate/ApplicationFolder.hpp          |   28 
 src/library/locate/LocatorFactory.cpp             |   46 
 test/functional/standard-license_test.cpp         |   50 
 test/license-generator/license-generator_test.cpp |    5 
 test/library/EventRegistry_test.cpp               |   41 
 src/library/base/StringUtils.cpp                  |   49 
 src/library/CMakeLists.txt                        |   10 
 src/library/base/FileUtils.cpp                    |   69 +
 test/functional/date_test.cpp                     |   26 
 src/library/base/EventRegistry.cpp                |  190 ++-
 test/library/LicenseReader_test.cpp               |   95 +
 example/example.cpp                               |   77 
 src/library/license++.cpp                         |   29 
 /dev/null                                         |   13 
 src/library/locate/EnvironmentVarLocation.cpp     |   46 
 src/library/LicenseReader.hpp                     |   84 +
 src/library/base/StringUtils.h                    |   21 
 src/tools/base_lib/win/CryptoHelperWindows.h      |   92 
 src/build_properties.h.in                         |   14 
 example/CMakeLists.txt                            |    5 
 src/tools/base_lib/win/CryptoHelperWindows.cpp    |  788 ++++++------
 54 files changed, 2,318 insertions(+), 1,172 deletions(-)

diff --git a/.gitignore b/.gitignore
index 6cd6db1..7165b6c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,6 +7,9 @@
 *.so
 *.dylib
 
+#Visual studio files
+.vs
+
 # Compiled Static libraries
 *.lai
 *.la
@@ -21,4 +24,5 @@
 .cproject
 .settings
 .project
-*.out
\ No newline at end of file
+*.out
+/Default/
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 9cd24af..32db051 100644
--- a/CONTRIBUTING.md
+++ b/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.
 
   
\ No newline at end of file
diff --git a/README.md b/README.md
index 3b096d7..72838b4 100644
--- a/README.md
+++ b/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 
diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt
index cbd53b6..87016f4 100644
--- a/example/CMakeLists.txt
+++ b/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)
diff --git a/example/example.cpp b/example/example.cpp
index 45370dd..2379d6a 100644
--- a/example/example.cpp
+++ b/example/example.cpp
@@ -2,55 +2,46 @@
 #include <map>
 #include "api/license++.h"
 #include "pc-identifiers.h"
-#include "ini/SimpleIni.h"
 
 using namespace std;
 
-int main(int argc, char *argv[])
-{
-    map<EVENT_TYPE, string> stringByEventType;
-    stringByEventType[LICENSE_OK                      ] = "OK ";
-    stringByEventType[LICENSE_FILE_NOT_FOUND          ] = "license file not found ";
-    stringByEventType[LICENSE_SERVER_NOT_FOUND        ] = "license server can't be contacted ";
-    stringByEventType[ENVIRONMENT_VARIABLE_NOT_DEFINED] = "environment variable not defined ";
-    stringByEventType[FILE_FORMAT_NOT_RECOGNIZED      ] = "license file has invalid format (not .ini file) ";
-    stringByEventType[LICENSE_MALFORMED               ] = "some mandatory field are missing, or data can't be fully read. ";
-    stringByEventType[PRODUCT_NOT_LICENSED            ] = "this product was not licensed ";
-    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);
+int main(int argc, char *argv[]) {
+	map<EVENT_TYPE, string> stringByEventType;
+	stringByEventType[LICENSE_OK] = "OK ";
+	stringByEventType[LICENSE_FILE_NOT_FOUND] = "license file not found ";
+	stringByEventType[LICENSE_SERVER_NOT_FOUND] = "license server can't be contacted ";
+	stringByEventType[ENVIRONMENT_VARIABLE_NOT_DEFINED] = "environment variable not defined ";
+	stringByEventType[FILE_FORMAT_NOT_RECOGNIZED] = "license file has invalid format (not .ini file) ";
+	stringByEventType[LICENSE_MALFORMED] = "some mandatory field are missing, or data can't be fully read. ";
+	stringByEventType[PRODUCT_NOT_LICENSED] = "this product was not licensed ";
+	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";
 
-	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>";
+	LicenseInfo licenseInfo;
+	EVENT_TYPE result = acquire_license("example", nullptr, &licenseInfo);
+
+	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;
 		}
 	}
 
-    if (result != LICENSE_OK) {
-        cout << "license ERROR :" << endl;
-        cout << "    " << stringByEventType[result].c_str() << endl;
-        cout << "the pc signature is :" << endl;
-        cout << "    " << signature << endl;
-    }
-    else
-        cout << "license OK" << endl;
+	return result;
 }
diff --git a/src/build_properties.h.in b/src/build_properties.h.in
index 240ff99..a15ef5e 100644
--- a/src/build_properties.h.in
+++ b/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
diff --git a/src/library/CMakeLists.txt b/src/library/CMakeLists.txt
index d1f0813..0589736 100644
--- a/src/library/CMakeLists.txt
+++ b/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/)
diff --git a/src/library/LicenseReader.cpp b/src/library/LicenseReader.cpp
index 9927426..84de09d 100644
--- a/src/library/LicenseReader.cpp
+++ b/src/library/LicenseReader.cpp
@@ -2,7 +2,7 @@
  * LicenseReader.cpp
  *
  *  Created on: Mar 30, 2014
- *      
+ *
  */
 
 #ifdef _WIN32
@@ -10,6 +10,7 @@
 #else
 # include <unistd.h>
 #endif
+
 #include <cstring>
 #include <ctime>
 #include <vector>
@@ -17,24 +18,27 @@
 #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 {
 
 const char *FullLicenseInfo::UNUSED_TIME = "0000-00-00";
 
-FullLicenseInfo::FullLicenseInfo(const string& source, const string& product,
-		const string& license_signature, int licenseVersion, string from_date,
-		string to_date, const string& client_signature,
+FullLicenseInfo::FullLicenseInfo(const string &source, const string &product,
+		const string &license_signature, int licenseVersion, string from_date,
+		string to_date, const string &client_signature,
 		unsigned int from_sw_version, unsigned int to_sw_version,
-		const string& extra_data) :
+		const string &extra_data) :
 		source(source), product(product), //
 		license_signature(license_signature), license_version(licenseVersion), //
 		from_date(from_date), to_date(to_date), //
@@ -48,38 +52,45 @@
 		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);
+		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 {
+void FullLicenseInfo::toLicenseInfo(LicenseInfo *license) const {
 	if (license != nullptr) {
 		strncpy(license->proprietary_data, extra_data.c_str(),
 		PROPRIETARY_DATA_SIZE);
@@ -91,225 +102,106 @@
 			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()),
-				time(nullptr));
+			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<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;
 		}
-		const char* productNamePtr = product.c_str();
-		const int sectionSize = ini.GetSectionSize(productNamePtr);
-		if (sectionSize <= 0) {
-			result.addEvent(PRODUCT_NOT_LICENSED, SVRT_WARN, *it);
-			continue;
-		} else {
-			atLeastOneProductLicensed = 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) {
+				eventRegistry.addEvent(PRODUCT_NOT_LICENSED, *it);
+				continue;
+			} else {
+				eventRegistry.addEvent(PRODUCT_FOUND, 	*it);
+			}
+			/*
+			 *  sw_version_from = (optional int)
+			 *  sw_version_to = (optional int)
+			 *  from_date = YYYY-MM-DD (optional)
+			 *  to_date  = YYYY-MM-DD (optional)
+			 *  client_signature = XXXX-XXXX-XXXX-XXXX (optional string 16)
+			 *  license_signature = XXXXXXXXXX (mandatory, 1024)
+			 *  application_data = xxxxxxxxx (optional string 16)
+			 */
+			const char *license_signature = ini.GetValue(productNamePtr,
+					"license_signature", nullptr);
+			long license_version = ini.GetLongValue(productNamePtr,
+					"license_version", -1);
+			if (license_signature != nullptr && license_version > 0) {
+				const string from_date = trim_copy(
+						ini.GetValue(productNamePtr, "from_date",
+								FullLicenseInfo::UNUSED_TIME));
+				const string to_date = trim_copy(
+						ini.GetValue(productNamePtr, "to_date",
+								FullLicenseInfo::UNUSED_TIME));
+				string client_signature = trim_copy(
+						ini.GetValue(productNamePtr, "client_signature", ""));
+				/*client_signature.erase(
+				 std::remove(client_signature.begin(), client_signature.end(), '-'),
+				 client_signature.end());*/
+				const int from_sw_version = ini.GetLongValue(productNamePtr,
+						"from_sw_version",
+						FullLicenseInfo::UNUSED_SOFTWARE_VERSION);
+				const int to_sw_version = ini.GetLongValue(productNamePtr,
+						"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);
+				licenseInfoOut.push_back(licInfo);
+				atLeastOneLicenseComplete = true;
+			} else {
+				eventRegistry.addEvent(LICENSE_MALFORMED, *it);
+			}
 		}
-		/*
-		 *  sw_version_from = (optional int)
-		 *  sw_version_to = (optional int)
-		 *  from_date = YYYY-MM-DD (optional)
-		 *  to_date  = YYYY-MM-DD (optional)
-		 *  client_signature = XXXX-XXXX-XXXX-XXXX (optional string 16)
-		 *  license_signature = XXXXXXXXXX (mandatory, 1024)
-		 *  application_data = xxxxxxxxx (optional string 16)
-		 */
-		const char * license_signature = ini.GetValue(productNamePtr,
-				"license_signature", nullptr);
-		long license_version = ini.GetLongValue(productNamePtr,
-				"license_version", -1);
-		if (license_signature != nullptr && license_version > 0) {
-			const string from_date = trim_copy(
-					ini.GetValue(productNamePtr, "from_date",
-							FullLicenseInfo::UNUSED_TIME));
-			const string to_date = trim_copy(
-					ini.GetValue(productNamePtr, "to_date",
-							FullLicenseInfo::UNUSED_TIME));
-			string client_signature = trim_copy(
-					ini.GetValue(productNamePtr, "client_signature", ""));
-			/*client_signature.erase(
-			 std::remove(client_signature.begin(), client_signature.end(), '-'),
-			 client_signature.end());*/
-			const int from_sw_version = ini.GetLongValue(productNamePtr,
-					"from_sw_version",
-					FullLicenseInfo::UNUSED_SOFTWARE_VERSION);
-			const int to_sw_version = ini.GetLongValue(productNamePtr,
-					"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);
-			licenseInfoOut.push_back(licInfo);
-			atLeastOneLicenseComplete = true;
-		} else {
-			result.addEvent(LICENSE_MALFORMED, SVRT_WARN, *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 {
@@ -336,7 +228,7 @@
 
 }
 
-void FullLicenseInfo::printAsIni(ostream & a_ostream) const {
+void FullLicenseInfo::printAsIni(ostream &a_ostream) const {
 	CSimpleIniA ini;
 	string result;
 	const string product = toupper_copy(trim_copy(this->product));
diff --git a/src/library/LicenseReader.h b/src/library/LicenseReader.h
deleted file mode 100644
index 0d70f2f..0000000
--- a/src/library/LicenseReader.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * LicenseReader.h
- *
- *  Created on: Mar 30, 2014
- *      
- */
-
-#ifndef LICENSEREADER_H_
-#define LICENSEREADER_H_
-
-#include "api/datatypes.h"
-#include "base/EventRegistry.h"
-#include "os/os.h"
-#define SI_SUPPORT_IOSTREAMS
-#include "ini/SimpleIni.h"
-#include <string>
-#include <ctime>
-namespace license {
-
-using namespace std;
-
-class FullLicenseInfo {
-public:
-	string source;
-	string product;
-	string license_signature;
-	int license_version;
-	string from_date;
-	string to_date;
-	bool has_expiry;
-	unsigned int from_sw_version;
-	unsigned int to_sw_version;
-	bool has_versions;
-	string client_signature;
-	bool has_client_sig;
-	string extra_data;
-
-	static const char* UNUSED_TIME;
-	static const unsigned int UNUSED_SOFTWARE_VERSION = 0;
-
-	FullLicenseInfo(const string& source, const string& product,
-			const string& license_signature, int licenseVersion,
-			string from_date = UNUSED_TIME,
-			string to_date = UNUSED_TIME, //
-			const string& client_signature = "", //
-			unsigned int from_sw_version = UNUSED_SOFTWARE_VERSION,
-			unsigned int to_sw_version = UNUSED_SOFTWARE_VERSION,
-			const string& extra_data = "");
-	string printForSign() const;
-	void printAsIni(ostream & a_ostream) const;
-	void toLicenseInfo(LicenseInfo* license) const;
-	EventRegistry validate(int sw_version);
-	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 string 16)
- *  license_signature = XXXXXXXXXX (mandatory, 1024)
- *  application_data = xxxxxxxxx (optional string 16)
- *	license_version = 100 (mandatory int)
- *  </pre>
- */
-class LicenseReader {
-private:
-	const LicenseLocation licenseLocation;
-	EventRegistry getLicenseDiskFiles(vector<string>& diskFiles);
-	vector<string> filterExistingFiles(vector<string> licensePositions);
-	vector<string> splitLicensePositions(string licensePositions);
-	bool findLicenseWithExplicitLocation(vector<string>& diskFiles,
-			EventRegistry& eventRegistry);
-	bool findFileWithEnvironmentVariable(vector<string>& diskFiles,
-			EventRegistry& eventRegistry);
-
-public:
-	LicenseReader(const LicenseLocation& licenseLocation);
-	EventRegistry readLicenses(const string &product,
-			vector<FullLicenseInfo>& licenseInfoOut);
-	virtual ~LicenseReader();
-};
-}
-#endif /* LICENSEREADER_H_ */
diff --git a/src/library/LicenseReader.hpp b/src/library/LicenseReader.hpp
new file mode 100644
index 0000000..661bd05
--- /dev/null
+++ b/src/library/LicenseReader.hpp
@@ -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_ */
diff --git a/src/library/api/Licensepp-features.h b/src/library/api/Licensepp-features.h
deleted file mode 100644
index 88e41ab..0000000
--- a/src/library/api/Licensepp-features.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef LICENSEPP_FEATURES_H_
-#define LICENSEPP_FEATURES_H_
-
-#include "license++.h"
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-enum FEATURE_NAMES {
-  FEATURE1,
-}
-
-#endif
diff --git a/src/library/api/datatypes.h b/src/library/api/datatypes.h
index ed30576..439f477 100644
--- a/src/library/api/datatypes.h
+++ b/src/library/api/datatypes.h
@@ -13,32 +13,38 @@
 
 #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"
 
 typedef enum {
-	LICENSE_OK = 0, 						//OK
+	LICENSE_OK = 0, 					//OK
 	LICENSE_FILE_NOT_FOUND = 1, 		//license file not found
 	LICENSE_SERVER_NOT_FOUND = 2, 		//license server can't be contacted
 	ENVIRONMENT_VARIABLE_NOT_DEFINED = 3, //environment variable not defined
-	FILE_FORMAT_NOT_RECOGNIZED = 4,	//license file has invalid format (not .ini file)
-	LICENSE_MALFORMED = 5, //some mandatory field are missing, or data can't be fully read.
+	FILE_FORMAT_NOT_RECOGNIZED = 4,		 //license file has invalid format (not .ini file)
+	LICENSE_MALFORMED = 5,			//some mandatory field are missing, or data can't be fully read.
 	PRODUCT_NOT_LICENSED = 6,		//this product was not licensed
 	PRODUCT_EXPIRED = 7,
-	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_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
diff --git a/src/library/api/license++.h b/src/library/api/license++.h
index faece34..ef1fbb6 100644
--- a/src/library/api/license++.h
+++ b/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
diff --git a/src/library/base/CMakeLists.txt b/src/library/base/CMakeLists.txt
index 6dc0c98..0a61fdf 100644
--- a/src/library/base/CMakeLists.txt
+++ b/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 )
diff --git a/src/library/base/EventRegistry.cpp b/src/library/base/EventRegistry.cpp
index cd3c58f..ec9d4c1 100644
--- a/src/library/base/EventRegistry.cpp
+++ b/src/library/base/EventRegistry.cpp
@@ -2,106 +2,151 @@
  * EventRegistry.cpp
  *
  *  Created on: Mar 30, 2014
- *      
+ *
  */
 
-#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,
-		AuditEvent& securityEvent) {
+EventRegistry& operator<<(EventRegistry &eventRegistry,
+		AuditEvent &securityEvent) {
 	eventRegistry.logs.push_back(securityEvent);
 	return eventRegistry;
 }
 
-EventRegistry& operator<<(EventRegistry& eventRegistry1,
-		EventRegistry& otherRegistry) {
+EventRegistry& operator<<(EventRegistry &eventRegistry1,
+		EventRegistry &otherRegistry) {
 	eventRegistry1.append(otherRegistry);
 	return eventRegistry1;
 }
 
-void EventRegistry::append(const EventRegistry& eventRegistry) {
+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;
+AuditEvent const* EventRegistry::getLastFailure() const {
+	const AuditEvent *result = nullptr;
+	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;
+			if (it->severity == SVRT_ERROR) {
+				result = &(*it);
+				break;
+			}
+		} while (it != logs.begin());
+	}
+	return result;
+}
+
+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::turnEventIntoError(EVENT_TYPE event) {
+bool EventRegistry::turnWarningsIntoErrors() {
 	bool eventFound = false;
-	for (auto it = logs.begin(); it != logs.end(); ++it) {
-		if (it->event_type == event) {
-			it->severity = SVRT_ERROR;
-			eventFound = true;
+	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_WARN) {
+				it->severity = SVRT_ERROR;
+				eventFound = true;
+			}
 		}
 	}
 	return eventFound;
 }
 
-AuditEvent const * EventRegistry::getLastFailure() const {
-	const AuditEvent* result = nullptr;
-	if (logs.size() == 0) {
-		return result;
-	}
-	auto it = logs.end();
-	do {
-		--it;
-		if (it->severity == SVRT_ERROR) {
-			result = &(*it);
-			break;
-		}
-	} while (it != logs.begin());
-	return result;
-
-}
-
-bool EventRegistry::isGood() const {
-	bool isGood = true;
-	for (auto it = logs.begin(); it != logs.end(); ++it) {
-		if (it->severity == SVRT_ERROR) {
-			isGood = false;
-			break;
-		}
-	}
-	return isGood;
-}
-
-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) {
@@ -112,9 +157,14 @@
 	return eventFound;
 }
 
-void EventRegistry::exportLastEvents(AuditEvent* auditEvents, int nlogs) {
+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;
+}
+
 }
 
diff --git a/src/library/base/EventRegistry.h b/src/library/base/EventRegistry.h
index d86ea77..f5fec62 100644
--- a/src/library/base/EventRegistry.h
+++ b/src/library/base/EventRegistry.h
@@ -2,7 +2,7 @@
  * EventRegistry.h
  *
  *  Created on: Mar 30, 2014
- *      
+ *
  */
 
 #ifndef 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();
+	void append(const EventRegistry &eventRegistry);
 	/**
+	 * 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 exportLastEvents(AuditEvent* auditEvents,int nlogs);
-
+	AuditEvent const* getLastFailure() const;
+	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_ */
diff --git a/src/library/base/FileUtils.cpp b/src/library/base/FileUtils.cpp
new file mode 100644
index 0000000..f8fcc20
--- /dev/null
+++ b/src/library/base/FileUtils.cpp
@@ -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);
+}
+
+}
diff --git a/src/library/base/FileUtils.hpp b/src/library/base/FileUtils.hpp
new file mode 100644
index 0000000..e6f9e9e
--- /dev/null
+++ b/src/library/base/FileUtils.hpp
@@ -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
diff --git a/src/library/base/StringUtils.cpp b/src/library/base/StringUtils.cpp
index a635b47..cf9da96 100644
--- a/src/library/base/StringUtils.cpp
+++ b/src/library/base/StringUtils.cpp
@@ -2,16 +2,18 @@
  * StringUtils.cpp
  *
  *  Created on: Apr 8, 2014
- *      
+ *
  */
 
 #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
@@ -20,7 +22,7 @@
 namespace license {
 using namespace std;
 
-string trim_copy(const string& string_to_trim) {
+string trim_copy(const string &string_to_trim) {
 	std::string::const_iterator it = string_to_trim.begin();
 	while (it != string_to_trim.end() && isspace(*it))
 		it++;
@@ -32,13 +34,13 @@
 	return std::string(it, rit.base());
 }
 
-string toupper_copy(const string& lowercase) {
+string toupper_copy(const string &lowercase) {
 	string cp(lowercase);
-	std::transform(cp.begin(), cp.end(), cp.begin(), (int (*)(int))toupper);
+	std::transform(cp.begin(), cp.end(), cp.begin(), (int (*)(int)) toupper);
 	return cp;
 }
 
-time_t seconds_from_epoch(const char* timeString) {
+time_t seconds_from_epoch(const char *timeString) {
 	int year, month, day;
 	tm tm;
 	if (strlen(timeString) == 8) {
@@ -47,14 +49,16 @@
 			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");
 			}
 		}
-	} else{
+	} else {
 		throw invalid_argument("Date not recognized");
 	}
 	tm.tm_isdst = -1;
@@ -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 */
diff --git a/src/library/base/StringUtils.h b/src/library/base/StringUtils.h
index bbb9ce3..dee0526 100644
--- a/src/library/base/StringUtils.h
+++ b/src/library/base/StringUtils.h
@@ -2,12 +2,15 @@
  * StringUtils.h
  *
  *  Created on: Apr 8, 2014
- *      
+ *
  */
 
 #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_ */
diff --git a/src/library/base/base.h b/src/library/base/base.h
index 6ad0bc6..898688f 100644
--- a/src/library/base/base.h
+++ b/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); \
diff --git a/src/library/base/base64.c b/src/library/base/base64.c
new file mode 100644
index 0000000..4d17d33
--- /dev/null
+++ b/src/library/base/base64.c
@@ -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;
+}
diff --git a/src/library/base/base64.h b/src/library/base/base64.h
index 27f49cd..9a353df 100644
--- a/src/library/base/base64.h
+++ b/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;
-	}
-
-	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;
+#ifdef __cplusplus
 }
-
-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
diff --git a/src/library/license++.cpp b/src/library/license++.cpp
index f9cc7c7..b702d51 100644
--- a/src/library/license++.cpp
+++ b/src/library/license++.cpp
@@ -1,6 +1,6 @@
 //============================================================================
 // Name        : license-manager-cpp.cpp
-// Author      : 
+// Author      :
 // Version     :
 // Copyright   : BSD
 //============================================================================
@@ -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;
 }
diff --git a/src/library/locate/ApplicationFolder.cpp b/src/library/locate/ApplicationFolder.cpp
new file mode 100644
index 0000000..b1fb0e3
--- /dev/null
+++ b/src/library/locate/ApplicationFolder.cpp
@@ -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 */
diff --git a/src/library/locate/ApplicationFolder.hpp b/src/library/locate/ApplicationFolder.hpp
new file mode 100644
index 0000000..649d8da
--- /dev/null
+++ b/src/library/locate/ApplicationFolder.hpp
@@ -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_ */
diff --git a/src/library/locate/CMakeLists.txt b/src/library/locate/CMakeLists.txt
new file mode 100644
index 0000000..4314fbd
--- /dev/null
+++ b/src/library/locate/CMakeLists.txt
@@ -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
+)
+
diff --git a/src/library/locate/EnvironmentVarData.cpp b/src/library/locate/EnvironmentVarData.cpp
new file mode 100644
index 0000000..616b948
--- /dev/null
+++ b/src/library/locate/EnvironmentVarData.cpp
@@ -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;
+}
+
+}
+}
diff --git a/src/library/locate/EnvironmentVarData.hpp b/src/library/locate/EnvironmentVarData.hpp
new file mode 100644
index 0000000..5698975
--- /dev/null
+++ b/src/library/locate/EnvironmentVarData.hpp
@@ -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
diff --git a/src/library/locate/EnvironmentVarLocation.cpp b/src/library/locate/EnvironmentVarLocation.cpp
new file mode 100644
index 0000000..a904b9a
--- /dev/null
+++ b/src/library/locate/EnvironmentVarLocation.cpp
@@ -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;
+}
+
+}
+}
diff --git a/src/library/locate/EnvironmentVarLocation.hpp b/src/library/locate/EnvironmentVarLocation.hpp
new file mode 100644
index 0000000..b2f9b6a
--- /dev/null
+++ b/src/library/locate/EnvironmentVarLocation.hpp
@@ -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_ */
diff --git a/src/library/locate/ExternalDefinition.cpp b/src/library/locate/ExternalDefinition.cpp
new file mode 100644
index 0000000..ec0428f
--- /dev/null
+++ b/src/library/locate/ExternalDefinition.cpp
@@ -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 */
diff --git a/src/library/locate/ExternalDefinition.hpp b/src/library/locate/ExternalDefinition.hpp
new file mode 100644
index 0000000..c70775a
--- /dev/null
+++ b/src/library/locate/ExternalDefinition.hpp
@@ -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_ */
diff --git a/src/library/locate/LocatorFactory.cpp b/src/library/locate/LocatorFactory.cpp
new file mode 100644
index 0000000..1b45752
--- /dev/null
+++ b/src/library/locate/LocatorFactory.cpp
@@ -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;
+
+}
+
+}
+}
diff --git a/src/library/locate/LocatorFactory.hpp b/src/library/locate/LocatorFactory.hpp
new file mode 100644
index 0000000..6f1cd30
--- /dev/null
+++ b/src/library/locate/LocatorFactory.hpp
@@ -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
diff --git a/src/library/locate/LocatorStrategy.cpp b/src/library/locate/LocatorStrategy.cpp
new file mode 100644
index 0000000..e1319b2
--- /dev/null
+++ b/src/library/locate/LocatorStrategy.cpp
@@ -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);
+}
+
+}
+}
diff --git a/src/library/locate/LocatorStrategy.hpp b/src/library/locate/LocatorStrategy.hpp
new file mode 100644
index 0000000..278c6a3
--- /dev/null
+++ b/src/library/locate/LocatorStrategy.hpp
@@ -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
diff --git a/src/library/os/os.h b/src/library/os/os.h
index 7eea3eb..1371786 100644
--- a/src/library/os/os.h
+++ b/src/library/os/os.h
@@ -2,7 +2,7 @@
  * os-dependent.hpp
  *
  *  Created on: Mar 29, 2014
- *      
+ *
  */
 
 #ifndef OS_DEPENDENT_HPP_
@@ -79,6 +79,14 @@
 
 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
 }
 #endif
diff --git a/src/tools/base_lib/win/CryptoHelperWindows.cpp b/src/tools/base_lib/win/CryptoHelperWindows.cpp
index 99e0b12..ff40457 100644
--- a/src/tools/base_lib/win/CryptoHelperWindows.cpp
+++ b/src/tools/base_lib/win/CryptoHelperWindows.cpp
@@ -1,394 +1,394 @@
-/*
- * CryptoHelperWindows.cpp
- *
- *  Created on: Sep 14, 2014
- *
- */
-
-#include <sstream> 
-#include <vector>
-#include <string>
-#include "CryptoHelperWindows.h"
-// The RSA public-key key exchange algorithm
-#define ENCRYPT_ALGORITHM         CALG_RSA_SIGN
-// The high order WORD 0x0200 (decimal 512)
-// determines the key length in bits.
-#define KEYLENGTH                 0x02000000
-#pragma comment(lib, "crypt32.lib")
-
-namespace license {
-
-CryptoHelperWindows::CryptoHelperWindows() {
-	m_hCryptProv = NULL;
-	m_hCryptKey = NULL;
-	if (!CryptAcquireContext(&m_hCryptProv, "license_sign", NULL , PROV_RSA_FULL, 0)) {
-		// If the key container cannot be opened, try creating a new
-		// container by specifying a container name and setting the
-		// CRYPT_NEWKEYSET flag.
-		DWORD lastError = GetLastError();
-		printf("Error in CryptAcquireContext (1) 0x%08x \n", lastError);
-		if (NTE_BAD_KEYSET == lastError) {
-			if (!CryptAcquireContext(&m_hCryptProv, "license_sign", NULL , PROV_RSA_FULL, CRYPT_NEWKEYSET)) {
-				printf("Warn in CryptAcquireContext: acquiring new user keyset failed 0x%08x, trying less secure mackine keyset \n", GetLastError());
-				//maybe access to protected storage disabled. Try with machine keys (less secure)
-				if (!CryptAcquireContext(&m_hCryptProv, "license_sign", NULL, PROV_RSA_FULL, CRYPT_MACHINE_KEYSET)) {
-					printf("Error in CryptAcquireContext (2) 0x%08x \n", GetLastError());
-					if (!CryptAcquireContext(&m_hCryptProv, "license_sign", NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET|CRYPT_MACHINE_KEYSET)) {
-						printf("Error in CryptAcquireContext (3): acquiring new keyset(machine) failed 0x%08x \n", GetLastError());
-						throw logic_error("");
-					}
-				}
-			}
-		} else {
-			printf(" Error in CryptAcquireContext (4) 0x%08x \n", lastError);
-			throw logic_error("");
-		}
-	}
-
-}
-
-/**
- This method calls the CryptGenKey function to get a handle to an
-
- exportable key-pair. The key-pair is  generated with the RSA public-key
- key exchange algorithm using Microsoft Enhanced Cryptographic Provider.
- */
-void CryptoHelperWindows::generateKeyPair() {
-	HRESULT hr = S_OK;
-	DWORD dwErrCode;
-	// If the handle to key container is NULL, fail.
-	if (m_hCryptProv == NULL)
-		throw logic_error("Cryptocontext not correctly initialized");
-	// Release a previously acquired handle to key-pair.
-	if (m_hCryptKey)
-		m_hCryptKey = NULL;
-	// Call the CryptGenKey method to get a handle
-	// to a new exportable key-pair.
-	if (!CryptGenKey(m_hCryptProv, ENCRYPT_ALGORITHM,
-	KEYLENGTH | CRYPT_EXPORTABLE, &m_hCryptKey)) {
-		dwErrCode = GetLastError();
-		throw logic_error(
-				string("Error generating keys ")
-						+ to_string(static_cast<long long>(dwErrCode)));
-	}
-	//double check the key is really generated
-	if(m_hCryptKey == NULL) {
-		dwErrCode = GetLastError();
-		throw logic_error(
-				string("Error generating keys (2)")
-						+ to_string(static_cast<long long>(dwErrCode)));
-    }
-}
-
-/* This method calls the CryptExportKey function to get the Public key
- in a string suitable for C source inclusion.
- */
-const string CryptoHelperWindows::exportPublicKey() const {
-	HRESULT hr = S_OK;
-	DWORD dwErrCode;
-	DWORD dwBlobLen;
-	BYTE *pbKeyBlob = nullptr;
-	stringstream ss;
-	// If the handle to key container is NULL, fail.
-	if (m_hCryptKey == NULL)
-		throw logic_error("call GenerateKey first.");
-	// This call here determines the length of the key
-	// blob.
-	if (!CryptExportKey(m_hCryptKey,
-	NULL, PUBLICKEYBLOB, 0, nullptr, &dwBlobLen)) {
-		dwErrCode = GetLastError();
-		throw logic_error(
-				string("Error calculating size of public key ")
-						+ to_string(static_cast<long long>(dwErrCode)));
-	}
-	// Allocate memory for the pbKeyBlob.
-	if ((pbKeyBlob = new BYTE[dwBlobLen]) == nullptr) {
-		throw logic_error(string("Out of memory exporting public key "));
-	}
-	// Do the actual exporting into the key BLOB.
-	if (!CryptExportKey(m_hCryptKey,
-	NULL, PUBLICKEYBLOB, 0, pbKeyBlob, &dwBlobLen)) {
-		delete pbKeyBlob;
-		dwErrCode = GetLastError();
-		throw logic_error(
-				string("Error exporting public key ")
-						+ to_string(static_cast<long long>(dwErrCode)));
-	} else {
-		ss << "\t";
-		for (unsigned int i = 0; i < dwBlobLen; i++) {
-			if (i != 0) {
-				ss << ", ";
-				if (i % 10 == 0) {
-					ss << "\\" << endl << "\t";
-				}
-			}
-			ss << to_string(static_cast<long long>(pbKeyBlob[i]));
-		}
-		delete pbKeyBlob;
-	}
-	return ss.str();
-}
-
-CryptoHelperWindows::~CryptoHelperWindows() {
-	if (m_hCryptProv) {
-		CryptReleaseContext(m_hCryptProv, 0);
-		m_hCryptProv = NULL;
-	}
-	if (m_hCryptKey)
-		m_hCryptKey = NULL;
-}
-
-//--------------------------------------------------------------------
-// This method calls the CryptExportKey function to get the Private key
-// in a byte array. The byte array is allocated on the heap and the size
-// of this is returned to the caller. The caller is responsible for releasing // this memory using a delete call.
-//--------------------------------------------------------------------
-const string CryptoHelperWindows::exportPrivateKey() const {
-	HRESULT hr = S_OK;
-	DWORD dwErrCode;
-	DWORD dwBlobLen;
-	BYTE *pbKeyBlob;
-	stringstream ss;
-	// If the handle to key container is NULL, fail.
-	if (m_hCryptKey == NULL)
-		throw logic_error(string("call GenerateKey first."));
-	// This call here determines the length of the key
-	// blob.
-	if (!CryptExportKey(m_hCryptKey,
-	NULL, PRIVATEKEYBLOB, 0, nullptr, &dwBlobLen)) {
-		dwErrCode = GetLastError();
-		throw logic_error(
-				string("Error calculating size of private key ")
-						+ to_string(static_cast<long long>(dwErrCode)));
-	}
-	// Allocate memory for the pbKeyBlob.
-	if ((pbKeyBlob = new BYTE[dwBlobLen]) == nullptr) {
-		throw logic_error(string("Out of memory exporting private key "));
-	}
-
-	// Do the actual exporting into the key BLOB.
-	if (!CryptExportKey(m_hCryptKey,
-	NULL, PRIVATEKEYBLOB, 0, pbKeyBlob, &dwBlobLen)) {
-		delete pbKeyBlob;
-		dwErrCode = GetLastError();
-		throw logic_error(
-				string("Error exporting private key ")
-						+ to_string(static_cast<long long>(dwErrCode)));
-	} else {
-		ss << "\t";
-		for (unsigned int i = 0; i < dwBlobLen; i++) {
-			if (i != 0) {
-				ss << ", ";
-				if (i % 15 == 0) {
-					ss << "\\" << endl << "\t";
-				}
-			}
-			ss << to_string(static_cast<long long>(pbKeyBlob[i]));
-		}
-		delete pbKeyBlob;
-	}
-	return ss.str();
-}
-
-void CryptoHelperWindows::printHash(HCRYPTHASH *hHash) const {
-	BYTE *pbHash;
-	DWORD dwHashLen;
-	DWORD dwHashLenSize = sizeof(DWORD);
-	char *hashStr;
-	unsigned int i;
-
-	if (CryptGetHashParam(*hHash, HP_HASHSIZE, (BYTE*) &dwHashLen,
-			&dwHashLenSize, 0)) {
-		pbHash = (BYTE*) malloc(dwHashLen);
-		hashStr = (char*) malloc(dwHashLen * 2 + 1);
-		if (CryptGetHashParam(*hHash, HP_HASHVAL, pbHash, &dwHashLen, 0)) {
-			for (i = 0; i < dwHashLen; i++) {
-				sprintf(&hashStr[i * 2], "%02x", pbHash[i]);
-			}
-			printf("hash To be signed: %s \n", hashStr);
-		}
-		free(pbHash);
-		free(hashStr);
-	}
-}
-
-const string CryptoHelperWindows::signString(const void *privateKey,
-		size_t pklen, const string &license) const {
-	BYTE *pbBuffer = (BYTE*) license.c_str();
-	const DWORD dwBufferLen = (DWORD) strlen((char*) pbBuffer);
-	HCRYPTHASH hHash;
-
-	HCRYPTKEY hKey;
-	BYTE *pbSignature;
-	DWORD dwSigLen;
-	DWORD strLen;
-
-	//-------------------------------------------------------------------
-	// Acquire a cryptographic provider context handle.
-
-	if (!CryptImportKey(m_hCryptProv, (const BYTE*) privateKey, (DWORD) pklen,
-			0, 0, &hKey)) {
-		throw logic_error(
-				string("Error in importing the PrivateKey ")
-						+ to_string(static_cast<long long>(GetLastError())));
-	}
-
-	//-------------------------------------------------------------------
-	// Create the hash object.
-
-	if (CryptCreateHash(m_hCryptProv, CALG_SHA1, 0, 0, &hHash)) {
-		printf("Hash object created. \n");
-	} else {
-		CryptDestroyKey(hKey);
-		throw logic_error(string("Error during CryptCreateHash."));
-	}
-	//-------------------------------------------------------------------
-	// Compute the cryptographic hash of the buffer.
-
-	if (CryptHashData(hHash, pbBuffer, dwBufferLen, 0)) {
-#ifdef _DEBUG
-		printf("Length of data to be hashed: %d \n", dwBufferLen);
-		printHash(&hHash);
-#endif 
-	} else {
-		throw logic_error(string("Error during CryptHashData."));
-	}
-	//-------------------------------------------------------------------
-	// Determine the size of the signature and allocate memory.
-
-	dwSigLen = 0;
-	if (CryptSignHash(hHash, AT_SIGNATURE, nullptr, 0, nullptr, &dwSigLen)) {
-		printf("Signature length %d found.\n", dwSigLen);
-	} else {
-		throw logic_error(string("Error during CryptSignHash."));
-	}
-	//-------------------------------------------------------------------
-	// Allocate memory for the signature buffer.
-
-	if (pbSignature = (BYTE*) malloc(dwSigLen)) {
-		printf("Memory allocated for the signature.\n");
-	} else {
-		throw logic_error(string("Out of memory."));
-	}
-	//-------------------------------------------------------------------
-	// Sign the hash object.
-
-	if (CryptSignHash(hHash, AT_SIGNATURE, nullptr, 0, pbSignature,
-			&dwSigLen)) {
-		printf("pbSignature is the signature length. %d\n", dwSigLen);
-	} else {
-		throw logic_error(string("Error during CryptSignHash."));
-	}
-	//-------------------------------------------------------------------
-	// Destroy the hash object.
-
-	CryptDestroyHash(hHash);
-	CryptDestroyKey(hKey);
-
-	CryptBinaryToString(pbSignature, dwSigLen,
-			CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, nullptr, &strLen);
-	vector<char> buffer(strLen);
-	CryptBinaryToString(pbSignature, dwSigLen,
-			CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, &buffer[0], &strLen);
-
-	//-------------------------------------------------------------------
-	// In the second phase, the hash signature is verified.
-	// This would most often be done by a different user in a
-	// separate program. The hash, signature, and the PUBLICKEYBLOB
-	// would be read from a file, an email message,
-	// or some other source.
-
-	// Here, the original pbBuffer, pbSignature, szDescription.
-	// pbKeyBlob, and their lengths are used.
-
-	// The contents of the pbBuffer must be the same data
-	// that was originally signed.
-
-	//-------------------------------------------------------------------
-	// Get the public key of the user who created the digital signature
-	// and import it into the CSP by using CryptImportKey. This returns
-	// a handle to the public key in hPubKey.
-
-	/*if (CryptImportKey(
-	 hProv,
-	 pbKeyBlob,
-	 dwBlobLen,
-	 0,
-	 0,
-	 &hPubKey))
-	 {
-	 printf("The key has been imported.\n");
-	 }
-	 else
-	 {
-	 MyHandleError("Public key import failed.");
-	 }
-	 //-------------------------------------------------------------------
-	 // Create a new hash object.
-
-	 if (CryptCreateHash(
-	 hProv,
-	 CALG_MD5,
-	 0,
-	 0,
-	 &hHash))
-	 {
-	 printf("The hash object has been recreated. \n");
-	 }
-	 else
-	 {
-	 MyHandleError("Error during CryptCreateHash.");
-	 }
-	 //-------------------------------------------------------------------
-	 // Compute the cryptographic hash of the buffer.
-
-	 if (CryptHashData(
-	 hHash,
-	 pbBuffer,
-	 dwBufferLen,
-	 0))
-	 {
-	 printf("The new hash has been created.\n");
-	 }
-	 else
-	 {
-	 MyHandleError("Error during CryptHashData.");
-	 }
-	 //-------------------------------------------------------------------
-	 // Validate the digital signature.
-
-	 if (CryptVerifySignature(
-	 hHash,
-	 pbSignature,
-	 dwSigLen,
-	 hPubKey,
-	 NULL,
-	 0))
-	 {
-	 printf("The signature has been verified.\n");
-	 }
-	 else
-	 {
-	 printf("Signature not validated!\n");
-	 }
-	 //-------------------------------------------------------------------
-	 // Free memory to be used to store signature.
-
-
-
-	 //-------------------------------------------------------------------
-	 // Destroy the hash object.
-
-
-
-	 //-------------------------------------------------------------------
-	 // Release the provider handle.
-
-	 /*if (hProv)
-	 CryptReleaseContext(hProv, 0);*/
-	if (pbSignature) {
-		free(pbSignature);
-	}
-	return string(&buffer[0]);
-}
-} /* namespace license */
+/*
+ * CryptoHelperWindows.cpp
+ *
+ *  Created on: Sep 14, 2014
+ *
+ */
+
+#include <sstream> 
+#include <vector>
+#include <string>
+#include "CryptoHelperWindows.h"
+// The RSA public-key key exchange algorithm
+#define ENCRYPT_ALGORITHM         CALG_RSA_SIGN
+// The high order WORD 0x0200 (decimal 512)
+// determines the key length in bits.
+#define KEYLENGTH                 0x02000000
+#pragma comment(lib, "crypt32.lib")
+
+namespace license {
+
+CryptoHelperWindows::CryptoHelperWindows() {
+	m_hCryptProv = NULL;
+	m_hCryptKey = NULL;
+	if (!CryptAcquireContext(&m_hCryptProv, "license_sign", NULL , PROV_RSA_FULL, 0)) {
+		// If the key container cannot be opened, try creating a new
+		// container by specifying a container name and setting the
+		// CRYPT_NEWKEYSET flag.
+		DWORD lastError = GetLastError();
+		printf("Error in CryptAcquireContext (1) 0x%08x \n", lastError);
+		if (NTE_BAD_KEYSET == lastError) {
+			if (!CryptAcquireContext(&m_hCryptProv, "license_sign", NULL , PROV_RSA_FULL, CRYPT_NEWKEYSET)) {
+				printf("Warn in CryptAcquireContext: acquiring new user keyset failed 0x%08x, trying less secure mackine keyset \n", GetLastError());
+				//maybe access to protected storage disabled. Try with machine keys (less secure)
+				if (!CryptAcquireContext(&m_hCryptProv, "license_sign", NULL, PROV_RSA_FULL, CRYPT_MACHINE_KEYSET)) {
+					printf("Error in CryptAcquireContext (2) 0x%08x \n", GetLastError());
+					if (!CryptAcquireContext(&m_hCryptProv, "license_sign", NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET|CRYPT_MACHINE_KEYSET)) {
+						printf("Error in CryptAcquireContext (3): acquiring new keyset(machine) failed 0x%08x \n", GetLastError());
+						throw logic_error("");
+					}
+				}
+			}
+		} else {
+			printf(" Error in CryptAcquireContext (4) 0x%08x \n", lastError);
+			throw logic_error("");
+		}
+	}
+
+}
+
+/**
+ This method calls the CryptGenKey function to get a handle to an
+
+ exportable key-pair. The key-pair is  generated with the RSA public-key
+ key exchange algorithm using Microsoft Enhanced Cryptographic Provider.
+ */
+void CryptoHelperWindows::generateKeyPair() {
+	HRESULT hr = S_OK;
+	DWORD dwErrCode;
+	// If the handle to key container is NULL, fail.
+	if (m_hCryptProv == NULL)
+		throw logic_error("Cryptocontext not correctly initialized");
+	// Release a previously acquired handle to key-pair.
+	if (m_hCryptKey)
+		m_hCryptKey = NULL;
+	// Call the CryptGenKey method to get a handle
+	// to a new exportable key-pair.
+	if (!CryptGenKey(m_hCryptProv, ENCRYPT_ALGORITHM,
+	KEYLENGTH | CRYPT_EXPORTABLE, &m_hCryptKey)) {
+		dwErrCode = GetLastError();
+		throw logic_error(
+				string("Error generating keys ")
+						+ to_string(static_cast<long long>(dwErrCode)));
+	}
+	//double check the key is really generated
+	if(m_hCryptKey == NULL) {
+		dwErrCode = GetLastError();
+		throw logic_error(
+				string("Error generating keys (2)")
+						+ to_string(static_cast<long long>(dwErrCode)));
+    }
+}
+
+/* This method calls the CryptExportKey function to get the Public key
+ in a string suitable for C source inclusion.
+ */
+const string CryptoHelperWindows::exportPublicKey() const {
+	HRESULT hr = S_OK;
+	DWORD dwErrCode;
+	DWORD dwBlobLen;
+	BYTE *pbKeyBlob = nullptr;
+	stringstream ss;
+	// If the handle to key container is NULL, fail.
+	if (m_hCryptKey == NULL)
+		throw logic_error("call GenerateKey first.");
+	// This call here determines the length of the key
+	// blob.
+	if (!CryptExportKey(m_hCryptKey,
+	NULL, PUBLICKEYBLOB, 0, nullptr, &dwBlobLen)) {
+		dwErrCode = GetLastError();
+		throw logic_error(
+				string("Error calculating size of public key ")
+						+ to_string(static_cast<long long>(dwErrCode)));
+	}
+	// Allocate memory for the pbKeyBlob.
+	if ((pbKeyBlob = new BYTE[dwBlobLen]) == nullptr) {
+		throw logic_error(string("Out of memory exporting public key "));
+	}
+	// Do the actual exporting into the key BLOB.
+	if (!CryptExportKey(m_hCryptKey,
+	NULL, PUBLICKEYBLOB, 0, pbKeyBlob, &dwBlobLen)) {
+		delete pbKeyBlob;
+		dwErrCode = GetLastError();
+		throw logic_error(
+				string("Error exporting public key ")
+						+ to_string(static_cast<long long>(dwErrCode)));
+	} else {
+		ss << "\t";
+		for (unsigned int i = 0; i < dwBlobLen; i++) {
+			if (i != 0) {
+				ss << ", ";
+				if (i % 10 == 0) {
+					ss << "\\" << endl << "\t";
+				}
+			}
+			ss << to_string(static_cast<long long>(pbKeyBlob[i]));
+		}
+		delete pbKeyBlob;
+	}
+	return ss.str();
+}
+
+CryptoHelperWindows::~CryptoHelperWindows() {
+	if (m_hCryptProv) {
+		CryptReleaseContext(m_hCryptProv, 0);
+		m_hCryptProv = NULL;
+	}
+	if (m_hCryptKey)
+		m_hCryptKey = NULL;
+}
+
+//--------------------------------------------------------------------
+// This method calls the CryptExportKey function to get the Private key
+// in a byte array. The byte array is allocated on the heap and the size
+// of this is returned to the caller. The caller is responsible for releasing // this memory using a delete call.
+//--------------------------------------------------------------------
+const string CryptoHelperWindows::exportPrivateKey() const {
+	HRESULT hr = S_OK;
+	DWORD dwErrCode;
+	DWORD dwBlobLen;
+	BYTE *pbKeyBlob;
+	stringstream ss;
+	// If the handle to key container is NULL, fail.
+	if (m_hCryptKey == NULL)
+		throw logic_error(string("call GenerateKey first."));
+	// This call here determines the length of the key
+	// blob.
+	if (!CryptExportKey(m_hCryptKey,
+	NULL, PRIVATEKEYBLOB, 0, nullptr, &dwBlobLen)) {
+		dwErrCode = GetLastError();
+		throw logic_error(
+				string("Error calculating size of private key ")
+						+ to_string(static_cast<long long>(dwErrCode)));
+	}
+	// Allocate memory for the pbKeyBlob.
+	if ((pbKeyBlob = new BYTE[dwBlobLen]) == nullptr) {
+		throw logic_error(string("Out of memory exporting private key "));
+	}
+
+	// Do the actual exporting into the key BLOB.
+	if (!CryptExportKey(m_hCryptKey,
+	NULL, PRIVATEKEYBLOB, 0, pbKeyBlob, &dwBlobLen)) {
+		delete pbKeyBlob;
+		dwErrCode = GetLastError();
+		throw logic_error(
+				string("Error exporting private key ")
+						+ to_string(static_cast<long long>(dwErrCode)));
+	} else {
+		ss << "\t";
+		for (unsigned int i = 0; i < dwBlobLen; i++) {
+			if (i != 0) {
+				ss << ", ";
+				if (i % 15 == 0) {
+					ss << "\\" << endl << "\t";
+				}
+			}
+			ss << to_string(static_cast<long long>(pbKeyBlob[i]));
+		}
+		delete pbKeyBlob;
+	}
+	return ss.str();
+}
+
+void CryptoHelperWindows::printHash(HCRYPTHASH *hHash) const {
+	BYTE *pbHash;
+	DWORD dwHashLen;
+	DWORD dwHashLenSize = sizeof(DWORD);
+	char *hashStr;
+	unsigned int i;
+
+	if (CryptGetHashParam(*hHash, HP_HASHSIZE, (BYTE*) &dwHashLen,
+			&dwHashLenSize, 0)) {
+		pbHash = (BYTE*) malloc(dwHashLen);
+		hashStr = (char*) malloc(dwHashLen * 2 + 1);
+		if (CryptGetHashParam(*hHash, HP_HASHVAL, pbHash, &dwHashLen, 0)) {
+			for (i = 0; i < dwHashLen; i++) {
+				sprintf(&hashStr[i * 2], "%02x", pbHash[i]);
+			}
+			printf("hash To be signed: %s \n", hashStr);
+		}
+		free(pbHash);
+		free(hashStr);
+	}
+}
+
+const string CryptoHelperWindows::signString(const void *privateKey,
+		size_t pklen, const string &license) const {
+	BYTE *pbBuffer = (BYTE*) license.c_str();
+	const DWORD dwBufferLen = (DWORD) strlen((char*) pbBuffer);
+	HCRYPTHASH hHash;
+
+	HCRYPTKEY hKey;
+	BYTE *pbSignature;
+	DWORD dwSigLen;
+	DWORD strLen;
+
+	//-------------------------------------------------------------------
+	// Acquire a cryptographic provider context handle.
+
+	if (!CryptImportKey(m_hCryptProv, (const BYTE*) privateKey, (DWORD) pklen,
+			0, 0, &hKey)) {
+		throw logic_error(
+				string("Error in importing the PrivateKey ")
+						+ to_string(static_cast<long long>(GetLastError())));
+	}
+
+	//-------------------------------------------------------------------
+	// Create the hash object.
+
+	if (CryptCreateHash(m_hCryptProv, CALG_SHA1, 0, 0, &hHash)) {
+		printf("Hash object created. \n");
+	} else {
+		CryptDestroyKey(hKey);
+		throw logic_error(string("Error during CryptCreateHash."));
+	}
+	//-------------------------------------------------------------------
+	// Compute the cryptographic hash of the buffer.
+
+	if (CryptHashData(hHash, pbBuffer, dwBufferLen, 0)) {
+#ifdef _DEBUG
+		printf("Length of data to be hashed: %d \n", dwBufferLen);
+		printHash(&hHash);
+#endif 
+	} else {
+		throw logic_error(string("Error during CryptHashData."));
+	}
+	//-------------------------------------------------------------------
+	// Determine the size of the signature and allocate memory.
+
+	dwSigLen = 0;
+	if (CryptSignHash(hHash, AT_SIGNATURE, nullptr, 0, nullptr, &dwSigLen)) {
+		printf("Signature length %d found.\n", dwSigLen);
+	} else {
+		throw logic_error(string("Error during CryptSignHash."));
+	}
+	//-------------------------------------------------------------------
+	// Allocate memory for the signature buffer.
+
+	if (pbSignature = (BYTE*) malloc(dwSigLen)) {
+		printf("Memory allocated for the signature.\n");
+	} else {
+		throw logic_error(string("Out of memory."));
+	}
+	//-------------------------------------------------------------------
+	// Sign the hash object.
+
+	if (CryptSignHash(hHash, AT_SIGNATURE, nullptr, 0, pbSignature,
+			&dwSigLen)) {
+		printf("pbSignature is the signature length. %d\n", dwSigLen);
+	} else {
+		throw logic_error(string("Error during CryptSignHash."));
+	}
+	//-------------------------------------------------------------------
+	// Destroy the hash object.
+
+	CryptDestroyHash(hHash);
+	CryptDestroyKey(hKey);
+
+	CryptBinaryToString(pbSignature, dwSigLen,
+			CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, nullptr, &strLen);
+	vector<char> buffer(strLen);
+	CryptBinaryToString(pbSignature, dwSigLen,
+			CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, &buffer[0], &strLen);
+
+	//-------------------------------------------------------------------
+	// In the second phase, the hash signature is verified.
+	// This would most often be done by a different user in a
+	// separate program. The hash, signature, and the PUBLICKEYBLOB
+	// would be read from a file, an email message,
+	// or some other source.
+
+	// Here, the original pbBuffer, pbSignature, szDescription.
+	// pbKeyBlob, and their lengths are used.
+
+	// The contents of the pbBuffer must be the same data
+	// that was originally signed.
+
+	//-------------------------------------------------------------------
+	// Get the public key of the user who created the digital signature
+	// and import it into the CSP by using CryptImportKey. This returns
+	// a handle to the public key in hPubKey.
+
+	/*if (CryptImportKey(
+	 hProv,
+	 pbKeyBlob,
+	 dwBlobLen,
+	 0,
+	 0,
+	 &hPubKey))
+	 {
+	 printf("The key has been imported.\n");
+	 }
+	 else
+	 {
+	 MyHandleError("Public key import failed.");
+	 }
+	 //-------------------------------------------------------------------
+	 // Create a new hash object.
+
+	 if (CryptCreateHash(
+	 hProv,
+	 CALG_MD5,
+	 0,
+	 0,
+	 &hHash))
+	 {
+	 printf("The hash object has been recreated. \n");
+	 }
+	 else
+	 {
+	 MyHandleError("Error during CryptCreateHash.");
+	 }
+	 //-------------------------------------------------------------------
+	 // Compute the cryptographic hash of the buffer.
+
+	 if (CryptHashData(
+	 hHash,
+	 pbBuffer,
+	 dwBufferLen,
+	 0))
+	 {
+	 printf("The new hash has been created.\n");
+	 }
+	 else
+	 {
+	 MyHandleError("Error during CryptHashData.");
+	 }
+	 //-------------------------------------------------------------------
+	 // Validate the digital signature.
+
+	 if (CryptVerifySignature(
+	 hHash,
+	 pbSignature,
+	 dwSigLen,
+	 hPubKey,
+	 NULL,
+	 0))
+	 {
+	 printf("The signature has been verified.\n");
+	 }
+	 else
+	 {
+	 printf("Signature not validated!\n");
+	 }
+	 //-------------------------------------------------------------------
+	 // Free memory to be used to store signature.
+
+
+
+	 //-------------------------------------------------------------------
+	 // Destroy the hash object.
+
+
+
+	 //-------------------------------------------------------------------
+	 // Release the provider handle.
+
+	 /*if (hProv)
+	 CryptReleaseContext(hProv, 0);*/
+	if (pbSignature) {
+		free(pbSignature);
+	}
+	return string(&buffer[0]);
+}
+} /* namespace license */
diff --git a/src/tools/base_lib/win/CryptoHelperWindows.h b/src/tools/base_lib/win/CryptoHelperWindows.h
index a432e27..b4e7594 100644
--- a/src/tools/base_lib/win/CryptoHelperWindows.h
+++ b/src/tools/base_lib/win/CryptoHelperWindows.h
@@ -1,46 +1,46 @@
-/*
- * CryptoHelperWindows.h
- *
- *  Created on: Sep 14, 2014
- *
- */
-
-#ifndef CRYPTOHELPERWINDOWS_H_
-#define CRYPTOHELPERWINDOWS_H_
-
-//#define _WIN32_WINNT 0x0400
-#include <windows.h>
-#include <wincrypt.h>
-#include <tchar.h>
-#include <string>
-#include "../CryptoHelper.h"
-
-
-
-namespace license {
-using namespace std;
-
-class CryptoHelperWindows: public CryptoHelper {
-private :
-	void acquireContext();
-	//	Handle to the cryptography provider.
-	HCRYPTPROV m_hCryptProv;
-	//	Handle to the cryptography key.
-	HCRYPTKEY m_hCryptKey;
-	void printHash(HCRYPTHASH* hHash) const;
-public:
-	CryptoHelperWindows();
-
-	virtual void generateKeyPair();
-	virtual const string exportPrivateKey() const;
-	virtual const string exportPublicKey() const;
-
-	virtual const string signString(const void* privateKey, size_t pklen,
-			const string& license) const;
-
-	virtual ~CryptoHelperWindows();
-};
-
-} /* namespace license */
-
-#endif /* CRYPTOHELPERWINDOWS_H_ */
+/*
+ * CryptoHelperWindows.h
+ *
+ *  Created on: Sep 14, 2014
+ *
+ */
+
+#ifndef CRYPTOHELPERWINDOWS_H_
+#define CRYPTOHELPERWINDOWS_H_
+
+//#define _WIN32_WINNT 0x0400
+#include <windows.h>
+#include <wincrypt.h>
+#include <tchar.h>
+#include <string>
+#include "../CryptoHelper.h"
+
+
+
+namespace license {
+using namespace std;
+
+class CryptoHelperWindows: public CryptoHelper {
+private :
+	void acquireContext();
+	//	Handle to the cryptography provider.
+	HCRYPTPROV m_hCryptProv;
+	//	Handle to the cryptography key.
+	HCRYPTKEY m_hCryptKey;
+	void printHash(HCRYPTHASH* hHash) const;
+public:
+	CryptoHelperWindows();
+
+	virtual void generateKeyPair();
+	virtual const string exportPrivateKey() const;
+	virtual const string exportPublicKey() const;
+
+	virtual const string signString(const void* privateKey, size_t pklen,
+			const string& license) const;
+
+	virtual ~CryptoHelperWindows();
+};
+
+} /* namespace license */
+
+#endif /* CRYPTOHELPERWINDOWS_H_ */
diff --git a/src/tools/license-generator/CMakeLists.txt b/src/tools/license-generator/CMakeLists.txt
index e707d5f..334b178 100644
--- a/src/tools/license-generator/CMakeLists.txt
+++ b/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}>
diff --git a/src/tools/license-generator/license-generator.cpp b/src/tools/license-generator/license-generator.cpp
index dcffd7e..d7335cf 100644
--- a/src/tools/license-generator/license-generator.cpp
+++ b/src/tools/license-generator/license-generator.cpp
@@ -1,32 +1,40 @@
-#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;
 
 namespace license {
 
-void LicenseGenerator::printHelp(const char* prog_name,
-		const po::options_description& options) {
+void LicenseGenerator::printHelp(const char *prog_name,
+		const po::options_description &options) {
 	cout << endl;
 	cout << prog_name << " Version " << PROJECT_VERSION << endl << ". Usage:"
 			<< endl;
@@ -40,43 +48,41 @@
 
 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.")
-		("output,o", po::value<string>(), "Output file name. If not specified the "
-			"license will be printed in standard output")
-		;
+	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 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;
 }
 
 vector<FullLicenseInfo> LicenseGenerator::parseLicenseInfo(
-		const po::variables_map& vm) {
+		const po::variables_map &vm) {
 	string begin_date = FullLicenseInfo::UNUSED_TIME;
 	string end_date = FullLicenseInfo::UNUSED_TIME;
 	if (vm.count("expire_date")) {
@@ -108,13 +114,14 @@
 	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: "
-				<< client_signature
-				<< " Please enter a valid signature in format XXXX-XXXX-XXXX-XXXX"
-				<< endl;
+					<< client_signature
+					<< " Please enter a valid signature in format XXXX-XXXX-XXXX-XXXX"
+					<< endl;
 			exit(2);
 		}
 	}
@@ -142,18 +149,32 @@
 	return licInfo;
 }
 
-void LicenseGenerator::generateAndOutputLicenses(const po::variables_map& vm,
-		ostream& outputFile) {
+void LicenseGenerator::generateAndOutputLicenses(const po::variables_map &vm,
+		ostream &outputFile) {
 	vector<FullLicenseInfo> licenseInfo = parseLicenseInfo(vm);
 	const unique_ptr<CryptoHelper> helper = CryptoHelper::getInstance();
 	const unsigned char pkey[] = PRIVATE_KEY;
 	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);
 		}
-		generateAndOutputLicenses(vm, ofstream);
+		if (vm.count("base64")) {
+			generateB64Licenses(vm, ofstream);
+		} else {
+			generateAndOutputLicenses(vm, ofstream);
+		}
 		ofstream.close();
 	} else {
-		generateAndOutputLicenses(vm, cout);
+		if (vm.count("base64")) {
+			generateB64Licenses(vm, cout);
+		} else {
+			generateAndOutputLicenses(vm, cout);
+		}
 	}
 	return 0;
 }
@@ -197,22 +226,24 @@
 const std::string formats[] = { "%4u-%2u-%2u", "%4u/%2u/%2u", "%4u%2u%2u" };
 const size_t formats_n = 3;
 
-string LicenseGenerator::normalize_date(const std::string& sDate) {
-	if(sDate.size()<8)
+string LicenseGenerator::normalize_date(const std::string &sDate) {
+	if (sDate.size() < 8)
 		throw invalid_argument("Date string too small for known formats");
 	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);
-		if(chread==3) {
+		const int chread = sscanf(sDate.c_str(), formats[i].c_str(), &year,
+				&month, &day);
+		if (chread == 3) {
 			found = true;
 			break;
 		}
 	}
-	if(!found)
+	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();
 }
 }
diff --git a/src/tools/license-generator/license-generator.h b/src/tools/license-generator/license-generator.h
index 361f263..04eaee6 100644
--- a/src/tools/license-generator/license-generator.h
+++ b/src/tools/license-generator/license-generator.h
@@ -2,14 +2,14 @@
  * LicenseSigner.h
  *
  *  Created on: Apr 6, 2014
- *      
+ *
  */
 
 #ifndef LICENSE_GENERATOR_H_
 #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:
diff --git a/test/functional/CMakeLists.txt b/test/functional/CMakeLists.txt
index d2c718c..44b4a8d 100644
--- a/test/functional/CMakeLists.txt
+++ b/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()
 
 
diff --git a/test/functional/date_test.cpp b/test/functional/date_test.cpp
index b9d9ddc..44a9911 100644
--- a/test/functional/date_test.cpp
+++ b/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);
 }
+
+}
diff --git a/test/functional/generate-license.cpp b/test/functional/generate-license.cpp
index 8ffac2b..c158c59 100644
--- a/test/functional/generate-license.cpp
+++ b/test/functional/generate-license.cpp
@@ -2,7 +2,7 @@
  * generate-license.c
  *
  *  Created on: Apr 13, 2014
- *      
+ *
  */
 
 #include <boost/test/unit_test.hpp>
@@ -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;
diff --git a/test/functional/generate-license.h b/test/functional/generate-license.h
index c35dabd..4c1dcc0 100644
--- a/test/functional/generate-license.h
+++ b/test/functional/generate-license.h
@@ -1,7 +1,5 @@
-
-
 #include<string>
 #include<vector>
 
 using namespace std;
-void generate_license(const string& fname, const vector<string>& other_args) ;
+void generate_license(const string& fname, const vector<string>& other_args);
diff --git a/test/functional/hijiaking_test.cpp b/test/functional/hijiaking_test.cpp
index b295796..009e47b 100644
--- a/test/functional/hijiaking_test.cpp
+++ b/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);
diff --git a/test/functional/standard-license_test.cpp b/test/functional/standard-license_test.cpp
index 18a6ae0..19b6000 100644
--- a/test/functional/standard-license_test.cpp
+++ b/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);
+}
+}
diff --git a/test/functional/volid_test.cpp b/test/functional/volid_test.cpp
index a91d0bc..3ab5348 100644
--- a/test/functional/volid_test.cpp
+++ b/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);
diff --git a/test/library/CMakeLists.txt b/test/library/CMakeLists.txt
index 49edff0..b7f4d90 100644
--- a/test/library/CMakeLists.txt
+++ b/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()
\ No newline at end of file
diff --git a/test/library/EventRegistry_test.cpp b/test/library/EventRegistry_test.cpp
new file mode 100644
index 0000000..70abe9b
--- /dev/null
+++ b/test/library/EventRegistry_test.cpp
@@ -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
diff --git a/test/library/LicenseLocator_test.cpp b/test/library/LicenseLocator_test.cpp
new file mode 100644
index 0000000..cf532b2
--- /dev/null
+++ b/test/library/LicenseLocator_test.cpp
@@ -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
diff --git a/test/library/LicenseReader_test.cpp b/test/library/LicenseReader_test.cpp
index 6fa4f59..2198ab3 100644
--- a/test/library/LicenseReader_test.cpp
+++ b/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 =
+	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 *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*/
diff --git a/test/license-generator/license-generator_test.cpp b/test/license-generator/license-generator_test.cpp
index 335f787..4e8c6ec 100644
--- a/test/license-generator/license-generator_test.cpp
+++ b/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;

--
Gitblit v1.9.1