From 263a0f6f6f0cdedd563bb7ae9723db6b096486b2 Mon Sep 17 00:00:00 2001
From: Gabriele Contini <contini.mailing@gmail.com>
Date: 周六, 19 10月 2019 08:50:45 +0800
Subject: [PATCH] issue #64 , issue #56 (part)

---
 src/library/locate/EnvironmentVarData.hpp         |    5 
 src/library/locate/ExternalDefinition.cpp         |   62 +
 .gitignore                                        |    3 
 src/library/base/base64.h                         |  140 ---
 src/library/api/datatypes.h                       |   38 
 src/library/api/license++.h                       |   19 
 src/tools/license-generator/license-generator.cpp |  141 ++-
 src/library/locate/EnvironmentVarData.cpp         |   44 
 src/library/locate/ExternalDefinition.hpp         |    8 
 src/library/os/os.h                               |   10 
 src/library/base/base64.c                         |  133 +++
 src/library/locate/LocatorStrategy.hpp            |   20 
 src/library/base/CMakeLists.txt                   |    1 
 src/library/locate/EnvironmentVarLocation.hpp     |    2 
 src/library/locate/LocatorStrategy.cpp            |    2 
 test/library/CMakeLists.txt                       |   18 
 src/library/base/EventRegistry.h                  |   48 
 test/functional/CMakeLists.txt                    |    8 
 src/library/locate/ApplicationFolder.hpp          |    2 
 src/library/locate/LocatorFactory.cpp             |   22 
 test/functional/standard-license_test.cpp         |   39 
 test/functional/hijiaking_test.cpp                |    2 
 src/library/locate/LocatorFactory.hpp             |    5 
 src/tools/license-generator/license-generator.h   |   12 
 src/library/locate/ApplicationFolder.cpp          |   13 
 test/library/EventRegistry_test.cpp               |   41 +
 src/library/base/StringUtils.cpp                  |   39 
 src/library/CMakeLists.txt                        |    1 
 src/library/base/FileUtils.cpp                    |   11 
 test/library/LicenseLocator_test.cpp              |   60 
 CONTRIBUTING.md                                   |    9 
 test/functional/date_test.cpp                     |   11 
 src/library/base/EventRegistry.cpp                |  188 ++-
 test/library/LicenseReader_test.cpp               |   68 +
 example/example.cpp                               |   77 -
 src/library/license++.cpp                         |   25 
 test/functional/volid_test.cpp                    |    5 
 README.md                                         |    2 
 src/tools/license-generator/CMakeLists.txt        |    1 
 src/library/locate/EnvironmentVarLocation.cpp     |   20 
 src/library/LicenseReader.hpp                     |   56 
 src/library/base/StringUtils.h                    |   13 
 src/library/LicenseReader.cpp                     |   75 -
 src/tools/base_lib/win/CryptoHelperWindows.h      |   92 +-
 src/library/base/FileUtils.hpp                    |    5 
 src/tools/base_lib/win/CryptoHelperWindows.cpp    |  788 +++++++++---------
 46 files changed, 1,349 insertions(+), 1,035 deletions(-)

diff --git a/.gitignore b/.gitignore
index 0018bea..7165b6c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,6 +7,9 @@
 *.so
 *.dylib
 
+#Visual studio files
+.vs
+
 # Compiled Static libraries
 *.lai
 *.la
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/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/library/CMakeLists.txt b/src/library/CMakeLists.txt
index 2fe7c85..0589736 100644
--- a/src/library/CMakeLists.txt
+++ b/src/library/CMakeLists.txt
@@ -15,6 +15,7 @@
      ini
      locators
      os
+     base
 )
 
 install(TARGETS licensecc_static ARCHIVE DESTINATION lib)
diff --git a/src/library/LicenseReader.cpp b/src/library/LicenseReader.cpp
index 7c020b1..84de09d 100644
--- a/src/library/LicenseReader.cpp
+++ b/src/library/LicenseReader.cpp
@@ -52,35 +52,42 @@
 		extra_data(extra_data) {
 }
 
-EventRegistry FullLicenseInfo::validate(int sw_version) {
-	EventRegistry er;
+bool FullLicenseInfo::validate(int sw_version,
+		EventRegistry &eventRegistryOut) {
 	os_initialize();
 	const FUNCTION_RETURN sigVer = verifySignature(printForSign().c_str(),
 			license_signature.c_str());
-	const bool sigVerified = sigVer == FUNC_RET_OK;
-	if (sigVerified) {
-		er.addEvent(LICENSE_VERIFIED, SVRT_INFO);
+	bool is_valid = (sigVer == FUNC_RET_OK);
+	if (is_valid) {
+		eventRegistryOut.addEvent(SIGNATURE_VERIFIED, source);
 	} else {
-		er.addEvent(LICENSE_CORRUPTED, SVRT_ERROR);
+		eventRegistryOut.addEvent(LICENSE_CORRUPTED, source);
 	}
 	if (has_expiry) {
+		cout<<source<<endl;
 		const time_t now = time(nullptr);
 		if (expires_on() < now) {
-			er.addEvent(PRODUCT_EXPIRED, SVRT_ERROR, "");
+/*
+			eventRegistryOut.addEvent(PRODUCT_EXPIRED, source.c_str(),
+					string("Expired on: " + this->to_date).c_str());*/
+			eventRegistryOut.addEvent(PRODUCT_EXPIRED, source.c_str(),nullptr);
+			is_valid = false;
 		}
 		if (valid_from() > now) {
-			er.addEvent(PRODUCT_EXPIRED, SVRT_ERROR);
+			/*eventRegistryOut.addEvent(PRODUCT_EXPIRED, source.c_str(),
+					string("Valid from " + this->from_date).c_str());*/
+			eventRegistryOut.addEvent(PRODUCT_EXPIRED, source.c_str(),nullptr);
+			is_valid = false;
 		}
 	}
 	if (has_client_sig) {
 		PcSignature str_code;
 		strncpy(str_code, client_signature.c_str(), sizeof(str_code) - 1);
 		const EVENT_TYPE event = validate_pc_signature(str_code);
-		if (event != LICENSE_OK) {
-			er.addEvent(event, SVRT_ERROR);
-		}
+		eventRegistryOut.addEvent(event, source);
+		is_valid = is_valid && (event == LICENSE_OK);
 	}
-	return er;
+	return is_valid;
 }
 
 void FullLicenseInfo::toLicenseInfo(LicenseInfo *license) const {
@@ -102,7 +109,7 @@
 	}
 }
 
-LicenseReader::LicenseReader(const LicenseLocation &licenseLocation) :
+LicenseReader::LicenseReader(const LicenseLocation* licenseLocation) :
 		licenseLocation(licenseLocation) {
 }
 
@@ -110,48 +117,39 @@
 		vector<FullLicenseInfo> &licenseInfoOut) {
 	vector<string> diskFiles;
 	vector<unique_ptr<locate::LocatorStrategy>> locator_strategies;
-	FUNCTION_RETURN ret = locate::LocatorFactory::getActiveStrategies(
-			locator_strategies, licenseLocation.licenseFileLocation);
+	FUNCTION_RETURN ret = locate::LocatorFactory::get_active_strategies(
+			locator_strategies, licenseLocation);
 	EventRegistry eventRegistry;
 	if (ret != FUNC_RET_OK) {
-		eventRegistry.addError(LICENSE_FILE_NOT_FOUND);
+		eventRegistry.addEvent(LICENSE_FILE_NOT_FOUND);
+		eventRegistry.turnWarningsIntoErrors();
 		return eventRegistry;
 	}
 
-	if (!eventRegistry.isGood()) {
-		return eventRegistry;
-	}
-	bool atLeastOneFileFound = false;
-	bool atLeastOneFileRecognized = false;
-	bool atLeastOneProductLicensed = false;
 	bool atLeastOneLicenseComplete = false;
-	for (unique_ptr<locate::LocatorStrategy>& locator : locator_strategies) {
-		vector<string> licenseLocations = locator->licenseLocations(
+	for (unique_ptr<locate::LocatorStrategy> &locator : locator_strategies) {
+		vector<string> licenseLocations = locator->license_locations(
 				eventRegistry);
 		if (licenseLocations.size() == 0) {
 			continue;
 		}
-		atLeastOneFileFound = true;
 		CSimpleIniA ini;
 		for (auto it = licenseLocations.begin(); it != licenseLocations.end();
 				it++) {
 			ini.Reset();
-			string license = locator->retrieveLicense((*it).c_str());
+			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, SVRT_WARN,
-						*it);
+				eventRegistry.addEvent(FILE_FORMAT_NOT_RECOGNIZED, 	*it);
 				continue;
-			} else {
-				atLeastOneFileRecognized = true;
 			}
 			const char *productNamePtr = product.c_str();
 			const int sectionSize = ini.GetSectionSize(productNamePtr);
 			if (sectionSize <= 0) {
-				eventRegistry.addEvent(PRODUCT_NOT_LICENSED, SVRT_WARN, *it);
+				eventRegistry.addEvent(PRODUCT_NOT_LICENSED, *it);
 				continue;
 			} else {
-				atLeastOneProductLicensed = true;
+				eventRegistry.addEvent(PRODUCT_FOUND, 	*it);
 			}
 			/*
 			 *  sw_version_from = (optional int)
@@ -193,19 +191,12 @@
 				licenseInfoOut.push_back(licInfo);
 				atLeastOneLicenseComplete = true;
 			} else {
-				eventRegistry.addEvent(LICENSE_MALFORMED, SVRT_WARN, *it);
+				eventRegistry.addEvent(LICENSE_MALFORMED, *it);
 			}
 		}
 	}
-	if (!atLeastOneFileFound) {
-		eventRegistry.turnEventIntoError(ENVIRONMENT_VARIABLE_NOT_DEFINED);
-		eventRegistry.turnEventIntoError(LICENSE_FILE_NOT_FOUND);
-	} else if (!atLeastOneFileRecognized) {
-		eventRegistry.turnEventIntoError(FILE_FORMAT_NOT_RECOGNIZED);
-	} else if (!atLeastOneProductLicensed) {
-		eventRegistry.turnEventIntoError(PRODUCT_NOT_LICENSED);
-	} else	if (!atLeastOneLicenseComplete) {
-		eventRegistry.turnEventIntoError(LICENSE_MALFORMED);
+	if (!atLeastOneLicenseComplete) {
+		eventRegistry.turnWarningsIntoErrors();
 	}
 	return eventRegistry;
 }
diff --git a/src/library/LicenseReader.hpp b/src/library/LicenseReader.hpp
index c42be92..661bd05 100644
--- a/src/library/LicenseReader.hpp
+++ b/src/library/LicenseReader.hpp
@@ -2,55 +2,53 @@
  * 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 "locate/LocatorStrategy.hpp"
-#define SI_SUPPORT_IOSTREAMS
 #include "ini/SimpleIni.h"
-#include <string>
-#include <ctime>
-namespace license {
 
-using namespace std;
+namespace license {
 
 class FullLicenseInfo {
 public:
-	string source;
-	string product;
-	string license_signature;
+	std::string source;
+	std::string product;
+	std::string license_signature;
 	int license_version;
-	string from_date;
-	string to_date;
+	std::string from_date;
+	std::string to_date;
 	bool has_expiry;
 	unsigned int from_sw_version;
 	unsigned int to_sw_version;
 	bool has_versions;
-	string client_signature;
+	std::string client_signature;
 	bool has_client_sig;
-	string extra_data;
+	std::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 = "", //
+	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 string& extra_data = "");
-	string printForSign() const;
-	void printAsIni(ostream & a_ostream) const;
+			const std::string& extra_data = "");
+	std::string printForSign() const;
+	void printAsIni(std::ostream & a_ostream) const;
 	void toLicenseInfo(LicenseInfo* license) const;
-	EventRegistry validate(int sw_version);
+	bool validate(int sw_version, EventRegistry& eventRegistryOut);
 	time_t expires_on() const;
 	time_t valid_from() const;
 };
@@ -67,19 +65,19 @@
  *  sw_version_to = (optional int)
  *  from_date = YYYY-MM-DD (optional)
  *  to_date  = YYYY-MM-DD (optional)
- *  client_signature = XXXXXXXX (optional string 16)
+ *  client_signature = XXXXXXXX (optional std::string 16)
  *  license_signature = XXXXXXXXXX (mandatory, 1024)
- *  application_data = xxxxxxxxx (optional string 16)
+ *  application_data = xxxxxxxxx (optional std::string 16)
  *	license_version = 100 (mandatory int)
  *  </pre>
  */
 class LicenseReader {
 private:
-	const LicenseLocation licenseLocation;
+	const LicenseLocation* licenseLocation;
 public:
-	LicenseReader(const LicenseLocation& licenseLocation);
-	EventRegistry readLicenses(const string &product,
-			vector<FullLicenseInfo>& licenseInfoOut);
+	LicenseReader(const LicenseLocation* licenseLocation);
+	EventRegistry readLicenses(const std::string &product,
+			std::vector<FullLicenseInfo>& licenseInfoOut);
 	virtual ~LicenseReader();
 };
 }
diff --git a/src/library/api/datatypes.h b/src/library/api/datatypes.h
index 1eadf88..439f477 100644
--- a/src/library/api/datatypes.h
+++ b/src/library/api/datatypes.h
@@ -13,13 +13,18 @@
 
 #ifdef __unix__
 #define DllExport
+#ifndef MAX_PATH
+	#define MAX_PATH 1024
+#endif
 #else
 #include <windows.h>
 #define DllExport  __declspec( dllexport )
 #endif
 
+
 #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"
@@ -36,8 +41,10 @@
 	LICENSE_CORRUPTED = 8,		//License signature didn't match with current license
 	IDENTIFIERS_MISMATCH = 9,   //Calculated identifier and the one provided in license didn't match
 
-	LICENSE_FILE_FOUND = 100,
-	LICENSE_VERIFIED = 101
+	LICENSE_SPECIFIED = 100,	//license location was specified
+	LICENSE_FOUND = 101, 		//License file has been found or license data has been located
+	PRODUCT_FOUND = 102,		//License has been loaded and the declared product has been found
+	SIGNATURE_VERIFIED = 103
 
 } EVENT_TYPE;
 
@@ -52,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 185a3f3..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"
@@ -53,7 +40,7 @@
  */
 
 EVENT_TYPE acquire_license(const char * productName,
-		LicenseLocation licenseLocation, LicenseInfo* license);
+		const LicenseLocation* licenseLocation, LicenseInfo* license);
 
 /**
  * Do nothing for now, useful for network licenses.
@@ -61,7 +48,7 @@
  * license.
  */
 EVENT_TYPE confirm_license(char * featureName,
-		LicenseLocation licenseLocation);
+		LicenseLocation* licenseLocation);
 /**
  * Do nothing for now, useful for network licenses.
  */
diff --git a/src/library/base/CMakeLists.txt b/src/library/base/CMakeLists.txt
index ab0a196..0a61fdf 100644
--- a/src/library/base/CMakeLists.txt
+++ b/src/library/base/CMakeLists.txt
@@ -3,6 +3,7 @@
     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 389ee42..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>
+
+#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 c8bc3b9..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 {
 
-/*
- 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
+	friend std::ostream & operator << (std::ostream &out, const EventRegistry &er);
+
 	std::vector<AuditEvent> logs;
-	//Forbid copy
-	//EventRegistry(const EventRegistry& that) = delete;
+	/**
+	 * For every license keep track of the events who progressed most
+	 * in the validation process
+	 */
+	std::map<std::string,int> mostAdvancedLogIdx_by_LicenseId;
+	int current_validation_step;
+
 public:
 	EventRegistry();
 	//operator <<
 	void append(const EventRegistry &eventRegistry);
-	void turnLastEventIntoError();
-	bool turnEventIntoError(EVENT_TYPE event);
-	bool turnErrosIntoWarnings();
 	/**
+	 * Turn the event warning for the license with the most advanced status
+	 * into an error.
+	 */
+	bool turnWarningsIntoErrors();
+	bool turnErrorsIntoWarnings();
+	bool isGood() const;
+	/**
+	 * Return the last failure (event with warn or error status)
+	 * for the license with the most advanced status.
 	 * @return NULL if no failures are found.
 	 */
 	AuditEvent const* getLastFailure() const;
-	bool isGood() const;
-
-	void addError(EVENT_TYPE event);
-	void addEvent(EVENT_TYPE event, SEVERITY severity);
-	void addEvent(EVENT_TYPE event, SEVERITY severity,
-			const std::string &eventParameter);
+	void addEvent(EVENT_TYPE event, const std::string &licenseLocationId);
+	void addEvent(EVENT_TYPE event, const char *licenseLocationId = nullptr,
+			const char *info = nullptr);
 	void exportLastEvents(AuditEvent *auditEvents, int nlogs);
-
 };
 }
 #endif /* EVENTREGISTRY_H_ */
diff --git a/src/library/base/FileUtils.cpp b/src/library/base/FileUtils.cpp
index ff79406..f8fcc20 100644
--- a/src/library/base/FileUtils.cpp
+++ b/src/library/base/FileUtils.cpp
@@ -9,19 +9,24 @@
 #include <string>
 #include <cerrno>
 #include <iostream>
-#include <algorithm> 
+#include <algorithm>
 
 #include "FileUtils.hpp"
 
 namespace license {
 using namespace std;
 
-vector<string> filter_existing_files(const vector<string> &fileList) {
+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();
 	}
@@ -57,7 +62,7 @@
 		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
index ac73a3a..e6f9e9e 100644
--- a/src/library/base/FileUtils.hpp
+++ b/src/library/base/FileUtils.hpp
@@ -2,17 +2,18 @@
  * 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);
+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);
 
diff --git a/src/library/base/StringUtils.cpp b/src/library/base/StringUtils.cpp
index 3e34432..cf9da96 100644
--- a/src/library/base/StringUtils.cpp
+++ b/src/library/base/StringUtils.cpp
@@ -2,17 +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
@@ -21,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++;
@@ -33,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) {
@@ -48,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;
@@ -70,8 +73,8 @@
 	return mktime(&tm);
 }
 
-
-const vector<string> split_string(const string& licensePositions,char splitchar) {
+const vector<string> split_string(const string &licensePositions,
+		char splitchar) {
 	std::stringstream streamToSplit(licensePositions);
 	std::string segment;
 	std::vector<string> seglist;
@@ -82,4 +85,18 @@
 	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 a52376d..dee0526 100644
--- a/src/library/base/StringUtils.h
+++ b/src/library/base/StringUtils.h
@@ -2,11 +2,13 @@
  * StringUtils.h
  *
  *  Created on: Apr 8, 2014
- *      
+ *
  */
 
 #ifndef STRINGUTILS_H_
 #define STRINGUTILS_H_
+
+#include <bits/types/time_t.h>
 #include <string>
 #include <vector>
 
@@ -28,7 +30,14 @@
 /**
  * Split a string on a given character
  */
-const vector<string> split_string(const string& licensePositions, const char splitchar);
+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 */
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 3e4ae40..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,6 +9,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <cstring>
+#include <iostream>
 
 #include "api/license++.h"
 
@@ -41,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);
@@ -50,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
index 9ba99ee..b1fb0e3 100644
--- a/src/library/locate/ApplicationFolder.cpp
+++ b/src/library/locate/ApplicationFolder.cpp
@@ -23,18 +23,15 @@
 namespace locate {
 using namespace std;
 
-
-
 ApplicationFolder::ApplicationFolder() :
 		LocatorStrategy("ApplicationFolder") {
-
 }
 
 ApplicationFolder::~ApplicationFolder() {
 }
 
-const vector<string> ApplicationFolder::licenseLocations(
-		EventRegistry &eventRegistry) const {
+const vector<string> ApplicationFolder::license_locations(
+		EventRegistry &eventRegistry) {
 	vector<string> diskFiles;
 	char fname[MAX_PATH] = { 0 };
 	const FUNCTION_RETURN fret = getModuleName(fname);
@@ -44,11 +41,9 @@
 		ifstream f(temptativeLicense.c_str());
 		if (f.good()) {
 			diskFiles.push_back(temptativeLicense);
-			eventRegistry.addEvent((EVENT_TYPE) LICENSE_FILE_FOUND,
-					(SEVERITY) SVRT_INFO, temptativeLicense);
+			eventRegistry.addEvent(LICENSE_FOUND, temptativeLicense.c_str());
 		} else {
-			eventRegistry.addEvent(LICENSE_FILE_NOT_FOUND, SVRT_WARN,
-					temptativeLicense);
+			eventRegistry.addEvent(LICENSE_FILE_NOT_FOUND, temptativeLicense.c_str());
 		}
 		f.close();
 	} else {
diff --git a/src/library/locate/ApplicationFolder.hpp b/src/library/locate/ApplicationFolder.hpp
index b98182e..649d8da 100644
--- a/src/library/locate/ApplicationFolder.hpp
+++ b/src/library/locate/ApplicationFolder.hpp
@@ -18,7 +18,7 @@
 class ApplicationFolder: public LocatorStrategy {
 public:
 	ApplicationFolder();
-	virtual const std::vector<std::string> licenseLocations(EventRegistry& eventRegistry) const;
+	virtual const std::vector<std::string> license_locations(EventRegistry& eventRegistry);
 	virtual ~ApplicationFolder();
 };
 
diff --git a/src/library/locate/EnvironmentVarData.cpp b/src/library/locate/EnvironmentVarData.cpp
index 844470e..616b948 100644
--- a/src/library/locate/EnvironmentVarData.cpp
+++ b/src/library/locate/EnvironmentVarData.cpp
@@ -6,6 +6,18 @@
  */
 
 #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 {
 
@@ -18,15 +30,37 @@
 EnvironmentVarData::~EnvironmentVarData() {
 }
 
-const vector<string> EnvironmentVarData::licenseLocations(
-		EventRegistry &eventRegistry) const {
+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::retrieveLicense(const std::string &licenseLocation) const{
-	return "";
+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
index 1a1dd36..5698975 100644
--- a/src/library/locate/EnvironmentVarData.hpp
+++ b/src/library/locate/EnvironmentVarData.hpp
@@ -14,11 +14,12 @@
 namespace locate {
 class EnvironmentVarData: public LocatorStrategy {
 private:
+	bool isBase64 = false;
 
 public:
 	EnvironmentVarData();
-	virtual const std::vector<std::string> licenseLocations(EventRegistry& eventRegistr) const;
-	virtual const std::string retrieveLicense(const std::string &licenseLocation) const;
+	virtual const std::vector<std::string> license_locations(EventRegistry& eventRegistr);
+	virtual const std::string retrieve_license_content(const std::string &licenseLocation) const;
 	virtual ~EnvironmentVarData();
 };
 
diff --git a/src/library/locate/EnvironmentVarLocation.cpp b/src/library/locate/EnvironmentVarLocation.cpp
index c8b23dc..a904b9a 100644
--- a/src/library/locate/EnvironmentVarLocation.cpp
+++ b/src/library/locate/EnvironmentVarLocation.cpp
@@ -22,8 +22,8 @@
 EnvironmentVarLocation::~EnvironmentVarLocation() {
 }
 
-const vector<string> EnvironmentVarLocation::licenseLocations(
-		EventRegistry &eventRegistry) const {
+const vector<string> EnvironmentVarLocation::license_locations(
+		EventRegistry &eventRegistry) {
 	vector<string> licenseFileFoundWithEnvVariable;
 
 	const string varName(LICENSE_LOCATION_ENV_VAR);
@@ -33,20 +33,10 @@
 		if (env_var_value != nullptr && env_var_value[0] != '\0') {
 			const vector<string> declared_positions = license::split_string(
 					string(env_var_value), ';');
-			vector<string> existing_pos = license::filter_existing_files(
-					declared_positions);
-			if (existing_pos.size() > 0) {
-				for (auto it = existing_pos.begin(); it != existing_pos.end();
-						++it) {
-					licenseFileFoundWithEnvVariable.push_back(*it);
-					eventRegistry.addEvent(LICENSE_FILE_FOUND, SVRT_INFO, *it);
-				}
-			} else {
-				eventRegistry.addEvent(LICENSE_FILE_NOT_FOUND, SVRT_WARN,
-						env_var_value);
-			}
+			licenseFileFoundWithEnvVariable = license::filter_existing_files(
+					declared_positions, eventRegistry, LICENSE_LOCATION_ENV_VAR);
 		} else {
-			eventRegistry.addEvent(ENVIRONMENT_VARIABLE_NOT_DEFINED, SVRT_WARN);
+			eventRegistry.addEvent(ENVIRONMENT_VARIABLE_NOT_DEFINED);
 		}
 	}
 	return licenseFileFoundWithEnvVariable;
diff --git a/src/library/locate/EnvironmentVarLocation.hpp b/src/library/locate/EnvironmentVarLocation.hpp
index 7e5ef60..b2f9b6a 100644
--- a/src/library/locate/EnvironmentVarLocation.hpp
+++ b/src/library/locate/EnvironmentVarLocation.hpp
@@ -17,7 +17,7 @@
 
 public:
 	EnvironmentVarLocation();
-	virtual const std::vector<std::string> licenseLocations(EventRegistry& eventRegistry) const;
+	virtual const std::vector<std::string> license_locations(EventRegistry& eventRegistry);
 	virtual ~EnvironmentVarLocation();
 };
 
diff --git a/src/library/locate/ExternalDefinition.cpp b/src/library/locate/ExternalDefinition.cpp
index af9af5e..ec0428f 100644
--- a/src/library/locate/ExternalDefinition.cpp
+++ b/src/library/locate/ExternalDefinition.cpp
@@ -5,36 +5,72 @@
  *      Author: Gabriele Contini
  */
 
-#include "../base/StringUtils.h"
+#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 char *location) :
+ExternalDefinition::ExternalDefinition(const LicenseLocation *location) :
 		LocatorStrategy("ExternalDefinition"), m_location(location) {
 }
 
 ExternalDefinition::~ExternalDefinition() {
 }
 
-const std::vector<std::string> ExternalDefinition::licenseLocations(
-		EventRegistry &eventRegistry) const {
-	const vector<string> declared_positions = license::split_string(m_location,
-			';');
-	const vector<string> existing_pos = license::filter_existing_files(
-			declared_positions);
-	if (existing_pos.size() > 0) {
-		for (auto it = existing_pos.begin(); it != existing_pos.end(); ++it) {
-			eventRegistry.addEvent(LICENSE_FILE_FOUND, SVRT_INFO, *it);
+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);
 		}
-	} else {
-		eventRegistry.addEvent(LICENSE_FILE_NOT_FOUND, SVRT_WARN, m_location);
+	}
+	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
index 3f50ee9..c70775a 100644
--- a/src/library/locate/ExternalDefinition.hpp
+++ b/src/library/locate/ExternalDefinition.hpp
@@ -15,10 +15,12 @@
 
 class ExternalDefinition: public LocatorStrategy {
 private:
-	const std::string m_location;
+	const LicenseLocation* m_location;
+	bool licenseDataIsBase64 = false;
 public:
-	ExternalDefinition(const char* location);
-	virtual const std::vector<std::string> licenseLocations(EventRegistry& eventRegistry) const;
+	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();
 };
 
diff --git a/src/library/locate/LocatorFactory.cpp b/src/library/locate/LocatorFactory.cpp
index be9cd67..1b45752 100644
--- a/src/library/locate/LocatorFactory.cpp
+++ b/src/library/locate/LocatorFactory.cpp
@@ -10,34 +10,32 @@
 #include "LocatorStrategy.hpp"
 #include "LocatorFactory.hpp"
 #include "ApplicationFolder.hpp"
-//#include "EnvironmentVarData.hpp"
+#include "EnvironmentVarData.hpp"
 #include "EnvironmentVarLocation.hpp"
 #include "ExternalDefinition.hpp"
 
 namespace license {
 namespace locate {
 
-using namespace std;
-
-FUNCTION_RETURN LocatorFactory::getActiveStrategies(
-		vector<unique_ptr<LocatorStrategy>> &strategies,
-		const char *locationHint) {
+FUNCTION_RETURN LocatorFactory::get_active_strategies(
+		std::vector<std::unique_ptr<LocatorStrategy>> &strategies,
+		const LicenseLocation *locationHint) {
 #if(FIND_LICENSE_NEAR_MODULE)
 	strategies.push_back(
-			unique_ptr<LocatorStrategy>(
+			std::unique_ptr<LocatorStrategy>(
 					(LocatorStrategy*) new ApplicationFolder()));
 #endif
 #if(FIND_LICENSE_WITH_ENV_VAR)
 	strategies.push_back(
-			unique_ptr<LocatorStrategy>(
+			std::unique_ptr<LocatorStrategy>(
 					(LocatorStrategy*) new EnvironmentVarLocation()));
-//	strategies.push_back(
-//			unique_ptr<LocatorStrategy>(
-//					(LocatorStrategy*) new EnvironmentVarData()));
+	strategies.push_back(
+			std::unique_ptr<LocatorStrategy>(
+					(LocatorStrategy*) new EnvironmentVarData()));
 #endif
 	if (locationHint != nullptr) {
 		strategies.push_back(
-				unique_ptr<LocatorStrategy>(
+				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
index 5231107..6f1cd30 100644
--- a/src/library/locate/LocatorFactory.hpp
+++ b/src/library/locate/LocatorFactory.hpp
@@ -6,6 +6,7 @@
 #include <vector>
 
 #include "../base/base.h"
+#include "../api/datatypes.h"
 #include "LocatorStrategy.hpp"
 
 namespace license {
@@ -19,9 +20,9 @@
 	}
 public:
 
-	static FUNCTION_RETURN getActiveStrategies(
+	static FUNCTION_RETURN get_active_strategies(
 			std::vector<std::unique_ptr<LocatorStrategy>> &strategiesOut,
-			const char *locationHint);
+			const LicenseLocation *locationHint);
 
 };
 
diff --git a/src/library/locate/LocatorStrategy.cpp b/src/library/locate/LocatorStrategy.cpp
index fc7f3ab..e1319b2 100644
--- a/src/library/locate/LocatorStrategy.cpp
+++ b/src/library/locate/LocatorStrategy.cpp
@@ -14,7 +14,7 @@
 namespace locate {
 using namespace std;
 
-const string LocatorStrategy::retrieveLicense(
+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
index 4aabd6d..278c6a3 100644
--- a/src/library/locate/LocatorStrategy.hpp
+++ b/src/library/locate/LocatorStrategy.hpp
@@ -31,18 +31,26 @@
 	virtual const std::string get_strategy_name() const {
 		return m_strategy_name;
 	}
-
-	virtual const std::vector<std::string> licenseLocations(
-			EventRegistry &eventRegistry) const = 0;
+	/**
+	 * 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 licenseLocation
+	 * @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 retrieveLicense(
-			const std::string &licenseLocation) const;
+	virtual const std::string retrieve_license_content(
+			const std::string &licenseLocationId) const;
 	inline virtual ~LocatorStrategy() {
 	}
 };
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 f86817b..334b178 100644
--- a/src/tools/license-generator/CMakeLists.txt
+++ b/src/tools/license-generator/CMakeLists.txt
@@ -10,6 +10,7 @@
 target_link_libraries(
      license_generator_lib
      tools_base
+     base
      licensecc_static
 	 $<$<CONFIG:Debug>:${Boost_PROGRAM_OPTIONS_LIBRARY_DEBUG}>
      $<$<NOT:$<CONFIG:Debug>>:${Boost_PROGRAM_OPTIONS_LIBRARY_RELEASE}>	 
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 531e01b..04eaee6 100644
--- a/src/tools/license-generator/license-generator.h
+++ b/src/tools/license-generator/license-generator.h
@@ -2,14 +2,13 @@
  * LicenseSigner.h
  *
  *  Created on: Apr 6, 2014
- *      
+ *
  */
 
 #ifndef LICENSE_GENERATOR_H_
 #define LICENSE_GENERATOR_H_
 
 #include <boost/program_options.hpp>
-
 #include "../../library/LicenseReader.hpp"
 
 namespace license {
@@ -22,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 3d122ea..44b4a8d 100644
--- a/test/functional/CMakeLists.txt
+++ b/test/functional/CMakeLists.txt
@@ -8,12 +8,12 @@
 )
 
 add_executable(
- standard_license_test
+ test_standard_license
  standard-license_test.cpp
 )
 
 target_link_libraries(
- standard_license_test
+ test_standard_license
  licensecc_static
  license_generator_snippet
  ${Boost_LIBRARIES}
@@ -46,11 +46,11 @@
 
 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 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 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 b07216b..44a9911 100644
--- a/test/functional/date_test.cpp
+++ b/test/functional/date_test.cpp
@@ -24,10 +24,9 @@
 	/* */
 	LicenseInfo license;
 	LicenseLocation licenseLocation;
-	licenseLocation.openFileNearModule = false;
 	licenseLocation.licenseFileLocation = licLocation.c_str();
-	licenseLocation.environmentVariableName = "";
-	const EVENT_TYPE result = acquire_license("TEST", licenseLocation,
+	licenseLocation.licenseData = "";
+	const EVENT_TYPE result = acquire_license("TEST", &licenseLocation,
 			&license);
 	BOOST_CHECK_EQUAL(result, LICENSE_OK);
 	BOOST_CHECK_EQUAL(license.has_expiry, true);
@@ -44,10 +43,10 @@
 	/* */
 	LicenseInfo license;
 	LicenseLocation licenseLocation;
-	licenseLocation.openFileNearModule = false;
 	licenseLocation.licenseFileLocation = licLocation.c_str();
-	licenseLocation.environmentVariableName = "";
-	const EVENT_TYPE result = acquire_license("TEST", licenseLocation,
+	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);
diff --git a/test/functional/hijiaking_test.cpp b/test/functional/hijiaking_test.cpp
index 6ada4fa..009e47b 100644
--- a/test/functional/hijiaking_test.cpp
+++ b/test/functional/hijiaking_test.cpp
@@ -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 67e8d67..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,12 +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;
-
-namespace test {
 
 BOOST_AUTO_TEST_CASE( standard_lic_file ) {
 	const string licLocation(PROJECT_TEST_TEMP_DIR "/standard_license.lic");
@@ -22,10 +21,29 @@
 	/* */
 	LicenseInfo license;
 	LicenseLocation licenseLocation;
-	licenseLocation.openFileNearModule = false;
 	licenseLocation.licenseFileLocation = licLocation.c_str();
-	licenseLocation.environmentVariableName = "";
-	const EVENT_TYPE result = acquire_license("TEST", licenseLocation,
+	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);
@@ -39,10 +57,9 @@
 
 	LicenseInfo license;
 	LicenseLocation licenseLocation;
-	licenseLocation.openFileNearModule = false;
 	licenseLocation.licenseFileLocation = licLocation.c_str();
-	licenseLocation.environmentVariableName = "";
-	const EVENT_TYPE result = acquire_license("TEST", licenseLocation,
+	licenseLocation.licenseData = "";
+	const EVENT_TYPE result = acquire_license("TEST", &licenseLocation,
 			&license);
 	BOOST_CHECK_EQUAL(result, IDENTIFIERS_MISMATCH);
 	BOOST_CHECK_EQUAL(license.has_expiry, false);
diff --git a/test/functional/volid_test.cpp b/test/functional/volid_test.cpp
index d02b36d..3ab5348 100644
--- a/test/functional/volid_test.cpp
+++ b/test/functional/volid_test.cpp
@@ -35,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 78ad9ad..b7f4d90 100644
--- a/test/library/CMakeLists.txt
+++ b/test/library/CMakeLists.txt
@@ -51,4 +51,22 @@
 	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
index eb4bda0..cf532b2 100644
--- a/test/library/LicenseLocator_test.cpp
+++ b/test/library/LicenseLocator_test.cpp
@@ -14,6 +14,8 @@
 #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"
@@ -69,13 +71,13 @@
 
 		license::EventRegistry registry;
 		ApplicationFolder applicationFolder;
-		vector<string> licenseInfos = applicationFolder.licenseLocations(registry);
+		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.retrieveLicense(
+		string licenseRealContent = applicationFolder.retrieve_license_content(
 			currentLocation);
 		src.seekg(0, ios::beg);
 		std::string referenceContent((std::istreambuf_iterator<char>(src)),
@@ -100,31 +102,33 @@
 	std::string referenceContent((std::istreambuf_iterator<char>(src)),
 			std::istreambuf_iterator<char>());
 	license::EventRegistry registry;
-	ExternalDefinition externalDefinition(applicationDefinedString);
-	vector<string> licenseInfos = externalDefinition.licenseLocations(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.retrieveLicense(
+	string licenseRealContent = externalDefinition.retrieve_license_content(
 			currentLocation);
 	BOOST_CHECK_MESSAGE(referenceContent.compare(licenseRealContent) == 0,
 			"File content is same");
 }
 
 /**
- * The license file doesn't exist. Chech that the locator reports the right error
+ * 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;
-	ExternalDefinition externalDefinition(applicationDefinedString);
-	vector<string> licenseInfos = externalDefinition.licenseLocations(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.turnEventIntoError(LICENSE_FILE_NOT_FOUND);
+	registry.turnWarningsIntoErrors();
 	BOOST_REQUIRE_MESSAGE(!registry.isGood(), "Error detected");
 	BOOST_CHECK_EQUAL(0, licenseInfos.size());
 	BOOST_CHECK_MESSAGE(
@@ -152,23 +156,18 @@
 	license::EventRegistry registry;
 
 	EnvironmentVarLocation envVarLocationStrategy;
-	vector<string> licenseInfos = envVarLocationStrategy.licenseLocations(
+	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.retrieveLicense(
+	string licenseRealContent = envVarLocationStrategy.retrieve_license_content(
 			currentLocation);
 	BOOST_CHECK_MESSAGE(referenceContent.compare(licenseRealContent) == 0,
 			"File content is same");
-#ifdef _WIN32
-	_putenv_s(LICENSE_LOCATION_ENV_VAR, "");
-#else
-	unsetenv(LICENSE_LOCATION_ENV_VAR);
-#endif
-
+	UNSETENV(LICENSE_LOCATION_ENV_VAR);
 }
 
 /**
@@ -177,47 +176,36 @@
 BOOST_AUTO_TEST_CASE( environment_var_location_not_found ) {
 	const char *environment_variable_value =
 	PROJECT_TEST_SRC_DIR "/this/file/doesnt/exist";
-#ifdef _WIN32
-	_putenv_s(LICENSE_LOCATION_ENV_VAR, environment_variable_value);
-#else
-	setenv(LICENSE_LOCATION_ENV_VAR, environment_variable_value, 1);
-#endif
+    SETENV(LICENSE_LOCATION_ENV_VAR, environment_variable_value);
+
 	license::EventRegistry registry;
 	EnvironmentVarLocation envVarLocationStrategy;
-	vector<string> licenseInfos = envVarLocationStrategy.licenseLocations(
+	vector<string> licenseInfos = envVarLocationStrategy.license_locations(
 			registry);
 	BOOST_CHECK_MESSAGE(registry.isGood(),
 			"No fatal error for now, only warnings");
-	registry.turnEventIntoError(LICENSE_FILE_NOT_FOUND);
+	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");
-#ifdef _WIN32
-	_putenv_s(LICENSE_LOCATION_ENV_VAR, "");
-#else
-	unsetenv(LICENSE_LOCATION_ENV_VAR);
-#endif
+	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 ) {
-#ifdef _WIN32
-	_putenv_s(LICENSE_LOCATION_ENV_VAR, "");
-#else
-	unsetenv(LICENSE_LOCATION_ENV_VAR);
-#endif
+	UNSETENV(LICENSE_LOCATION_ENV_VAR);
 	license::EventRegistry registry;
 	EnvironmentVarLocation environmentVarLocation;
-	vector<string> licenseInfos = environmentVarLocation.licenseLocations(
+	vector<string> licenseInfos = environmentVarLocation.license_locations(
 			registry);
 
 	BOOST_CHECK_MESSAGE(registry.isGood(),
 			"No fatal error for now, only warnings");
-	registry.turnEventIntoError(ENVIRONMENT_VARIABLE_NOT_DEFINED);
+	registry.turnWarningsIntoErrors();
 	BOOST_REQUIRE_MESSAGE(!registry.isGood(), "Error detected");
 	BOOST_CHECK_EQUAL(0, licenseInfos.size());
 	BOOST_CHECK_MESSAGE(
diff --git a/test/library/LicenseReader_test.cpp b/test/library/LicenseReader_test.cpp
index df86061..2198ab3 100644
--- a/test/library/LicenseReader_test.cpp
+++ b/test/library/LicenseReader_test.cpp
@@ -1,4 +1,14 @@
 #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 <stdlib.h>
@@ -6,13 +16,17 @@
 #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 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",
 			licenseInfos);
@@ -20,11 +34,14 @@
 	BOOST_CHECK_EQUAL(1, licenseInfos.size());
 }
 
+/**
+ * Test the error return if the product code is not found in the license
+ */
 BOOST_AUTO_TEST_CASE( product_not_licensed ) {
 	const char *licLocation =
 	PROJECT_TEST_SRC_DIR "/library/test_reader.ini";
-	const LicenseLocation location = { licLocation, nullptr, false };
-	LicenseReader licenseReader(location);
+	const LicenseLocation location = { licLocation, nullptr };
+	LicenseReader licenseReader(&location);
 	vector<FullLicenseInfo> licenseInfos;
 	const EventRegistry registry = licenseReader.readLicenses("PRODUCT-NOT",
 			licenseInfos);
@@ -35,11 +52,14 @@
 			registry.getLastFailure()->event_type);
 }
 
+/**
+ * Test the error code if the license file is specified but doesn't exists
+ */
 BOOST_AUTO_TEST_CASE( file_not_found ) {
 	const char *licLocation = PROJECT_TEST_SRC_DIR "/library/not_found.ini";
 	//const char * envName = "MYVAR";
-	const LicenseLocation location = { licLocation, nullptr, false };
-	LicenseReader licenseReader(location);
+	const LicenseLocation location = { licLocation, nullptr };
+	LicenseReader licenseReader(&location);
 	vector<FullLicenseInfo> licenseInfos;
 	const EventRegistry registry = licenseReader.readLicenses("PRODUCT",
 			licenseInfos);
@@ -50,10 +70,13 @@
 			registry.getLastFailure()->event_type);
 }
 
+/**
+ * Test the error code if the license default environment variable isn't specified
+ */
 BOOST_AUTO_TEST_CASE( env_var_not_defined ) {
-	const char *envName = "MYVAR";
-	const LicenseLocation location = { nullptr, envName, false };
-	LicenseReader licenseReader(location);
+	UNSETENV(LICENSE_LOCATION_ENV_VAR);
+	const LicenseLocation location = { nullptr, nullptr };
+	LicenseReader licenseReader(&location);
 	vector<FullLicenseInfo> licenseInfos;
 	const EventRegistry registry = licenseReader.readLicenses("PRODUCT",
 			licenseInfos);
@@ -64,3 +87,26 @@
 			registry.getLastFailure()->event_type);
 }
 
+/**
+ * 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*/

--
Gitblit v1.9.1