Files

1315 lines
36 KiB
C++
Raw Permalink Normal View History

2026-03-28 16:54:11 +11:00
//
// Copyright (c) ANSCENTER. All rights reserved.
//
#include "precomp.h"
#include "anslicensing.h"
#include "template.h"
#include "base64.h"
#include "except.h"
#include "uniconv.h"
#include "tinyxml2.h"
#include "picojson.h"
using namespace std;
const unsigned char LicenseTemplateImpl::m_demoPublicKeys[10][23] = {
{8, 0x67, 0xC9, 0x0C, 0xB9, 0xF9, 0x7D, 0x1C, 0x9C},
{11, 0x76, 0x8C, 0x73, 0xC8, 0xC3, 0x6E, 0xEE, 0x7E, 0x3A, 0xC2, 0x13},
{12, 0xC2, 0x8F, 0x03, 0x24, 0x4B, 0xAF, 0xC7, 0x94, 0x20, 0x3D, 0x46, 0x03},
{13, 0xC8, 0xC3, 0x75, 0x6A, 0x9E, 0x74, 0x5F, 0xC9, 0x18, 0xCF, 0xA0, 0xD4, 0xA9},
{14, 0x75, 0xD5, 0x7F, 0xDC, 0x08, 0x48, 0x93, 0x55, 0xDF, 0x63, 0xF9, 0xC4, 0x2C, 0x48},
{14, 0xE1, 0x5A, 0xA2, 0xE0, 0xB7, 0x33, 0xFF, 0x88, 0x20, 0xFF, 0x1F, 0x91, 0xC9, 0x77},
{17, 0xCC, 0x50, 0x01, 0x33, 0x11, 0x20, 0xFF, 0xA8, 0xED, 0x4F, 0xF2, 0x0A, 0xD7, 0xCB, 0xD0, 0xC3, 0x14},
{18, 0x5A, 0xCC, 0xFB, 0xF5, 0x00, 0x62, 0xB5, 0x6B, 0xEE, 0x28, 0xE3, 0x92, 0x56, 0x2C, 0xAD, 0x76, 0xB8, 0xAE},
{20, 0x4B, 0x36, 0x14, 0x2C, 0x29, 0xF0, 0x0C, 0xCD, 0x2F, 0xC2, 0xE0, 0x24, 0x4A, 0x6E, 0xCA, 0x83, 0x7B, 0xA7, 0xB1, 0x05},
{22, 0x6B, 0x3C, 0x1D, 0xD7, 0x6F, 0xAC, 0x59, 0x37, 0xAA, 0xCC, 0x52, 0xF9, 0xBB, 0x7B, 0x25, 0x34, 0x93, 0x40, 0x7D, 0xE0, 0x90, 0x07}
};
const unsigned char LicenseTemplateImpl::m_demoPrivateKeys[10][23] = {
{7, 0x5B, 0x3C, 0x97, 0xDC, 0x58, 0x4C, 0x37},
{9, 0xC3, 0xD3, 0xB3, 0xE7, 0x13, 0x0E, 0xC2, 0x46, 0x2F},
{10, 0x25, 0x72, 0x41, 0x0A, 0x22, 0x8E, 0x88, 0x25, 0x1C, 0x01},
{12, 0x23, 0x5F, 0xA9, 0x40, 0x61, 0x5A, 0xB6, 0xC9, 0x07, 0x86, 0x1E, 0x01},
{12, 0x24, 0x2F, 0x29, 0xA7, 0xE1, 0xAF, 0xC1, 0x42, 0x41, 0x82, 0xAF, 0x67},
{13, 0xA8, 0x89, 0x6A, 0x64, 0x85, 0x9D, 0x00, 0xBC, 0x06, 0x92, 0xF0, 0xF9, 0x08},
{15, 0x00, 0x8F, 0x7E, 0x9F, 0x61, 0x38, 0x8B, 0xB3, 0x9D, 0x2D, 0x68, 0x17, 0x7E, 0x7D, 0x19},
{17, 0xBE, 0x53, 0x27, 0xF2, 0xB4, 0xD6, 0xA0, 0xA8, 0xF9, 0x10, 0x67, 0x94, 0x61, 0xD9, 0x8B, 0x4B, 0x03},
{18, 0x0E, 0x15, 0xCB, 0xFC, 0x8D, 0x6C, 0x93, 0xA3, 0x1F, 0x70, 0xB8, 0xFB, 0x25, 0xB4, 0xB8, 0xE1, 0xED, 0x04},
{20, 0x66, 0x8C, 0xE8, 0x03, 0x44, 0x4E, 0x5C, 0x81, 0x15, 0xBF, 0x01, 0x07, 0x6A, 0xA3, 0x59, 0xF6, 0xE0, 0x97, 0x76, 0x45}
};
#define TEMPLATE "LicenseKeyTemplate"
#define FORMAT "LicenseKey"
#define DATA "Data"
#define FIELD "Field"
#define SIGNATURE "Signature"
#define SIGNATURE_PUBLIC_KEY "SignaturePublicKey"
#define SIGNATURE_PRIVATE_KEY "SignaturePrivateKey"
#define SIGNING_SERVICE_URL "SigningServiceUrl"
#define SIGNING_SERVICE_TEMPLATE_ID "SigningServiceTemplateId"
#define DATA_FIELDS "DataFields"
#define VALIDATION_FIELDS "ValidationFields"
void LicenseTemplateImpl::LoadXml(const char * xmlTemplate)
{
tinyxml2::XMLDocument xml;
if (xml.Parse(xmlTemplate) != tinyxml2::XML_NO_ERROR)
throw new LicensingException(STATUS_OUT_OF_MEMORY);
std::string rootElementName;
const char * attr;
tinyxml2::XMLElement * element, * rootElement;
if ((element = rootElement = xml.FirstChildElement()) == NULL) throw new LicensingException(STATUS_OUT_OF_MEMORY);
rootElementName = rootElement->Name();
int templateVersion;
if ((attr = element->Attribute("version")) == NULL)
templateVersion = 1;
else
templateVersion = atoi(attr);
if (templateVersion < 1 && templateVersion > 3)
throw new LicensingException(STATUS_GENERIC_ERROR, "unsupported template version");
if ((element = element->FirstChildElement("LicenseKey")) == NULL) throw new LicensingException(STATUS_OUT_OF_MEMORY);
m_keyEncoding = ENCODING_BASE32X;
if ((attr = element->Attribute("encoding")) != NULL)
if (_stricmp(attr, "base64") == 0)
m_keyEncoding = ENCODING_BASE64X;
if ((attr = element->Attribute("characterGroups")) == NULL)
throw new LicensingException(STATUS_OUT_OF_MEMORY);
m_numGroups = atoi(attr);
if ((attr = element->Attribute("charactersPerGroup")) == NULL)
throw new LicensingException(STATUS_OUT_OF_MEMORY);
m_charsPerGroup = atoi(attr);
m_groupSeparator = "-";
if ((attr = element->Attribute("groupSeparator")) != NULL)
m_groupSeparator = attr;
m_header = "";
if ((attr = element->Attribute("header")) != NULL)
m_header = attr;
m_footer = "";
if ((attr = element->Attribute("footer")) != NULL)
m_footer = attr;
int type, offset, size;
if ((element = xml.FirstChildElement()) == NULL) throw new LicensingException(STATUS_GENERIC_ERROR);
if ((element = element->FirstChildElement("LicenseKey")) == NULL) throw new LicensingException(STATUS_GENERIC_ERROR);
if ((element = element->FirstChildElement("Data")) == NULL) throw new LicensingException(STATUS_GENERIC_ERROR);
if ((element = element->FirstChildElement("DataFields")) == NULL) throw new LicensingException(STATUS_GENERIC_ERROR);
for (element = element->FirstChildElement("Field"); element != NULL; element = element->NextSiblingElement())
{
attr = element->Attribute("type");
if ( _stricmp( attr, "raw" ) == 0 )
type = FIELD_TYPE_RAW;
else
if ( _stricmp( attr, "integer" ) == 0 )
type = FIELD_TYPE_INTEGER;
else
if ( _stricmp( attr, "string" ) == 0 )
type = FIELD_TYPE_STRING;
else
if ( _stricmp( attr, "date13") == 0 )
type = FIELD_TYPE_DATE13;
else
if ( _stricmp( attr, "date14" ) == 0 )
type = FIELD_TYPE_DATE14;
else
if ( _stricmp( attr, "date16" ) == 0 )
type = FIELD_TYPE_DATE16;
else
throw new LicensingException(STATUS_GENERIC_ERROR);
offset = 0;
if ((attr = element->Attribute("offset")) != NULL )
{
offset = atoi(attr);
}
if ((attr = element->Attribute("size")) == NULL )
throw new LicensingException(STATUS_GENERIC_ERROR);
size = atoi(attr);
if ((attr = element->Attribute("name")) == NULL)
throw new LicensingException(STATUS_GENERIC_ERROR);
m_dataFields.emplace(piecewise_construct, forward_as_tuple(attr), forward_as_tuple(type, size, offset));
}
if ((element = xml.FirstChildElement()) == NULL) throw new LicensingException(STATUS_GENERIC_ERROR);
if ((element = element->FirstChildElement("LicenseKey")) == NULL) throw new LicensingException(STATUS_GENERIC_ERROR);
if ((element = element->FirstChildElement("Data")) == NULL) throw new LicensingException(STATUS_GENERIC_ERROR);
if ((element = element->FirstChildElement("ValidationFields")) == NULL) throw new LicensingException(STATUS_GENERIC_ERROR);
m_validationDataSize = 0;
for (element = element->FirstChildElement("Field"); element != NULL; element = element->NextSiblingElement())
{
attr = element->Attribute("type");
if ( _stricmp( attr, "raw" ) == 0 )
type = FIELD_TYPE_RAW;
else
if ( _stricmp( attr, "integer" ) == 0 )
type = FIELD_TYPE_INTEGER;
else
if ( _stricmp( attr, "string" ) == 0 )
type = FIELD_TYPE_STRING;
else
if ( _stricmp ( attr, "date13" ) == 0 )
type = FIELD_TYPE_DATE13;
else
if ( _stricmp( attr, "date14" ) == 0 )
type = FIELD_TYPE_DATE14;
else
if ( _stricmp( attr, "date16" ) == 0 )
type = FIELD_TYPE_DATE16;
else
throw new LicensingException(STATUS_GENERIC_ERROR);
offset = 0;
if ((attr = element->Attribute("offset")) != NULL )
{
offset = atoi(attr);
}
if ((attr = element->Attribute("size")) == NULL )
throw new LicensingException(STATUS_GENERIC_ERROR);
size = atoi(attr);
if ((attr = element->Attribute("name")) == NULL)
throw new LicensingException(STATUS_GENERIC_ERROR);
m_validationFields.emplace(piecewise_construct, forward_as_tuple(attr), forward_as_tuple(type, size, offset));
if (m_validationDataSize < offset + size)
m_validationDataSize = offset + size;
}
if ((element = xml.FirstChildElement()) == NULL) throw new LicensingException(STATUS_GENERIC_ERROR);
if ((element = element->FirstChildElement("LicenseKey")) == NULL) throw new LicensingException(STATUS_GENERIC_ERROR);
if ((element = element->FirstChildElement("Signature")) == NULL) throw new LicensingException(STATUS_GENERIC_ERROR);
if ((attr = element->Attribute("size")) == NULL)
throw new LicensingException(STATUS_GENERIC_ERROR, "signature size not provided in template");
int signatureSize = atoi(attr);
if (signatureSize <= 0)
throw new LicensingException(STATUS_GENERIC_ERROR, "invalid signature size");
SetSignatureSize(signatureSize);
SetDataSize((m_numGroups * m_charsPerGroup * m_keyEncoding) - signatureSize);
tinyxml2::XMLElement * element2;
if ((element2 = element->FirstChildElement("SignaturePrivateKey")) != NULL)
{
if (templateVersion == 1)
{
m_signingKey = make_unique<Key>(element2->GetText(), m_signatureKeyType);
int len = 1024;
void * buf = _alloca(1024);
if (!m_signingKey->Store(buf, &len))
throw new LicensingException(STATUS_GENERIC_ERROR, "invalid private key");
ValidatePrivateKey(buf, len);
} else
if (templateVersion <= 3)
SetPrivateKey(element2->GetText());
else
throw new LicensingException(STATUS_GENERIC_ERROR, "unsupported template version");
}
if ((element2 = element->FirstChildElement("SignaturePublicKey")) != NULL)
{
if (templateVersion == 1)
{
m_verificationKey = make_unique<Key>(element2->GetText(), m_signatureKeyType);
m_certificate.reset(Certificate::Generate(signatureSize, m_signingKey.get(), m_verificationKey.get(), NULL, NULL, NULL, 0));
ValidateCertificate();
}
else
if (templateVersion <= 3)
SetPublicKeyCertificate(element2->GetText());
else
throw new LicensingException(STATUS_GENERIC_ERROR, "unsupported template version");
}
if ((element2 = element->FirstChildElement("SigningServiceUrl")) != NULL)
SetLicensingServiceUrl(element2->GetText());
if ((element2 = element->FirstChildElement("SigningServiceTemplateId")) != NULL)
SetTemplateId(element2->GetText());
if (templateVersion < 3)
return;
if ((element = rootElement->FirstChildElement("Properties")) != NULL)
{
m_properties.LoadXml(element);
}
}
#ifndef MAX_XML_BUFFER_SIZE
#define MAX_XML_BUFFER_SIZE 4096
#endif
const char * LicenseTemplateImpl::SaveXml(bool savePrivateKey)
{
BASE64 base64;
char buffer[ MAX_XML_BUFFER_SIZE ];
m_xmlTemplate.resize(0);
snprintf(buffer, MAX_XML_BUFFER_SIZE, "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n");m_xmlTemplate.append(buffer);
snprintf(buffer, MAX_XML_BUFFER_SIZE, "<LicenseTemplate version=\"%d\">\n", m_version);m_xmlTemplate.append(buffer);
snprintf(buffer, MAX_XML_BUFFER_SIZE, "\t<LicenseKey\n"
"\t\tencoding=\"%s\"\n"
"\t\tcharacterGroups=\"%d\"\n"
"\t\tcharactersPerGroup=\"%d\"\n"
"\t\tgroupSeparator=\"%s\"\n"
"\t\theader=\"%s\"\n"
"\t\tfooter=\"%s\">\n", (m_keyEncoding == ENCODING_BASE64X) ? "BASE64" : "BASE32X", m_numGroups, m_charsPerGroup, m_groupSeparator.c_str(), m_header.c_str(), m_footer.c_str());m_xmlTemplate.append(buffer);
snprintf(buffer, MAX_XML_BUFFER_SIZE, "\t\t<Data>\n");m_xmlTemplate.append(buffer);
snprintf(buffer, MAX_XML_BUFFER_SIZE, "\t\t\t<DataFields size=\"%d\">\n", m_dataSize);m_xmlTemplate.append(buffer);
const char * name;
BitStruct::FIELD_TYPE type;
int size, offset;
string fieldType;
for (const auto& field : m_dataFields)
{
name = field.first.c_str();
type = field.second.type;
size = field.second.size;
offset = field.second.offset;
switch ((int)type)
{
case FIELD_TYPE_INTEGER:
fieldType = "Integer";
break;
case FIELD_TYPE_STRING:
fieldType = "String";
break;
case FIELD_TYPE_RAW:
fieldType = "Raw";
break;
case FIELD_TYPE_DATE13:
fieldType = "Date13";
break;
case FIELD_TYPE_DATE14:
fieldType = "Date14";
break;
case FIELD_TYPE_DATE16:
fieldType = "Date16";
break;
default:
fieldType = "Raw";
}
snprintf(buffer, MAX_XML_BUFFER_SIZE, "\t\t\t\t<Field name=\"%s\" type=\"%s\" size=\"%d\" offset=\"%d\" />\n", name, fieldType.c_str(), size, offset);
m_xmlTemplate.append(buffer);
}
snprintf(buffer, MAX_XML_BUFFER_SIZE, "\t\t\t</DataFields>\n");m_xmlTemplate.append(buffer);
snprintf(buffer, MAX_XML_BUFFER_SIZE, "\t\t\t<ValidationFields>\n");m_xmlTemplate.append(buffer);
for (const auto& field : m_validationFields)
{
name = field.first.c_str();
type = field.second.type;
size = field.second.size;
offset = field.second.offset;
switch ((int)type)
{
case FIELD_TYPE_INTEGER:
fieldType = "Integer";
break;
case FIELD_TYPE_STRING:
fieldType = "String";
break;
case FIELD_TYPE_RAW:
fieldType = "Raw";
break;
case FIELD_TYPE_DATE13:
fieldType = "Date13";
break;
case FIELD_TYPE_DATE14:
fieldType = "Date14";
break;
case FIELD_TYPE_DATE16:
fieldType = "Date16";
break;
default:
fieldType = "Raw";
}
snprintf(buffer, MAX_XML_BUFFER_SIZE, "\t\t\t\t<Field name=\"%s\" type=\"%s\" size=\"%d\" offset=\"%d\" />\n", name, fieldType.c_str(), size, offset);
m_xmlTemplate.append(buffer);
}
snprintf(buffer, MAX_XML_BUFFER_SIZE, "\t\t\t</ValidationFields>\n");m_xmlTemplate.append(buffer);
snprintf(buffer, MAX_XML_BUFFER_SIZE, "\t\t</Data>\n");m_xmlTemplate.append(buffer);
snprintf(buffer, MAX_XML_BUFFER_SIZE, "\t\t<Signature size=\"%d\">\n", m_signatureSize);m_xmlTemplate.append(buffer);
if (m_certificate)
{
snprintf(buffer, MAX_XML_BUFFER_SIZE, "\t\t\t<SignaturePublicKey>%s</SignaturePublicKey>\n", m_certificate->ToString() );m_xmlTemplate.append(buffer);
if (savePrivateKey && m_signingKey)
{
snprintf(buffer, MAX_XML_BUFFER_SIZE, "\t\t\t<SignaturePrivateKey>%s</SignaturePrivateKey>\n", m_signingKey->ToString() );m_xmlTemplate.append(buffer);
}
}
if (m_licensingServiceUrl.length() > 0)
{
snprintf(buffer, MAX_XML_BUFFER_SIZE, "\t\t\t<SigningServiceUrl>%s</SigningServiceUrl>\n", m_licensingServiceUrl.c_str() );m_xmlTemplate.append(buffer);
}
if (!m_templateId.empty())
{
snprintf(buffer, MAX_XML_BUFFER_SIZE, "\t\t\t<SigningServiceTemplateId>%s</SigningServiceTemplateId>\n", m_templateId.c_str() );m_xmlTemplate.append(buffer);
}
snprintf(buffer, MAX_XML_BUFFER_SIZE, "\t\t</Signature>\n");m_xmlTemplate.append(buffer);
snprintf(buffer, MAX_XML_BUFFER_SIZE, "\t</LicenseKey>\n");m_xmlTemplate.append(buffer);
snprintf(buffer, MAX_XML_BUFFER_SIZE, "\t<Properties>\n");m_xmlTemplate.append(buffer);
m_properties.SaveXml(m_xmlTemplate);
snprintf(buffer, MAX_XML_BUFFER_SIZE, "\t</Properties>\n");m_xmlTemplate.append(buffer);
snprintf(buffer, MAX_XML_BUFFER_SIZE, "</LicenseTemplate>");m_xmlTemplate.append(buffer);
return m_xmlTemplate.c_str();
}
void LicenseTemplateImpl::LoadJson(const char * xmlTemplate)
{
picojson::value json;
try {
std::string err = picojson::parse(json, xmlTemplate);
if (!err.empty())
throw new LicensingException(STATUS_GENERIC_ERROR, err.c_str());
if (!json.is<picojson::object>())
throw new LicensingException(STATUS_GENERIC_ERROR, "invalid license template");
picojson::object obj = json.get<picojson::object>();
int templateVersion = 1;
try { templateVersion = obj["version"].get<double>(); } catch (std::out_of_range &) {}
if (templateVersion < 1 && templateVersion > 3)
throw new LicensingException(STATUS_GENERIC_ERROR, "unsupported template version");
m_keyEncoding = ENCODING_BASE32X;
try {
if (obj["encoding"].is<std::string>() && obj["encoding"].get<std::string>().compare("base64") == 0)
m_keyEncoding = ENCODING_BASE64X;
} catch (std::out_of_range &) {}
m_numGroups = obj["char_groups"].get<double>();
m_charsPerGroup = obj["chars_per_group"].get<double>();
m_groupSeparator = obj["group_sep"].get<std::string>().c_str();
m_header = obj["header"].get<std::string>().c_str();
m_footer = obj["footer"].get<std::string>().c_str();
std::string name; int type, size, offset;
picojson::object field;
picojson::array fieldList = obj["data_fields"].get<picojson::array>();
for (picojson::array::iterator iter = fieldList.begin(); iter != fieldList.end(); iter++) {
field = iter->get<picojson::object>();
name = field["type"].get<std::string>();
if ((name.compare("raw") == 0) || (name.compare("Raw") == 0))
type = FIELD_TYPE_RAW;
else
if ((name.compare("int") == 0) || (name.compare("integer") == 0) || (name.compare("Integer") == 0))
type = FIELD_TYPE_INTEGER;
else
if ((name.compare("string") == 0) || (name.compare("String") == 0))
type = FIELD_TYPE_STRING;
else
if ((name.compare("date13") == 0) || (name.compare("Date13") == 0))
type = FIELD_TYPE_DATE13;
else
if ((name.compare("date14") == 0) || (name.compare("Date14") == 0))
type = FIELD_TYPE_DATE14;
else
if ((name.compare("date16") == 0) || (name.compare("Date16") == 0))
type = FIELD_TYPE_DATE16;
else
throw new LicensingException(STATUS_GENERIC_ERROR);
name = field["name"].get<std::string>();
size = field["size"].get<double>();
offset = 0;
try { offset = field["offset"].get<double>(); } catch (std::out_of_range &) {}
m_dataFields.emplace(piecewise_construct, forward_as_tuple(name.c_str()), forward_as_tuple(type, size, offset));
}
m_validationDataSize = 0;
if (obj["validation_fields"].is<picojson::array>()) {
fieldList = obj["validation_fields"].get<picojson::array>();
for (picojson::array::iterator iter = fieldList.begin(); iter != fieldList.end(); iter++) {
field = iter->get<picojson::object>();
name = field["type"].get<std::string>();
if ((name.compare("raw") == 0) || (name.compare("Raw") == 0))
type = FIELD_TYPE_RAW;
else
if ((name.compare("int") == 0) || (name.compare("integer") == 0) || (name.compare("Integer") == 0))
type = FIELD_TYPE_INTEGER;
else
if ((name.compare("string") == 0) || (name.compare("String") == 0))
type = FIELD_TYPE_STRING;
else
if ((name.compare("date13") == 0) || (name.compare("Date13") == 0))
type = FIELD_TYPE_DATE13;
else
if ((name.compare("date14") == 0) || (name.compare("Date14") == 0))
type = FIELD_TYPE_DATE14;
else
if ((name.compare("date16") == 0) || (name.compare("Date16") == 0))
type = FIELD_TYPE_DATE16;
else
throw new LicensingException(STATUS_GENERIC_ERROR);
name = field["name"].get<std::string>();
size = field["size"].get<double>();
offset = 0;
try { offset = field["offset"].get<double>(); }
catch (std::out_of_range &) {}
m_validationFields.emplace(piecewise_construct, forward_as_tuple(name.c_str()), forward_as_tuple(type, size, offset));
if (m_validationDataSize < offset + size)
m_validationDataSize = offset + size;
}
}
SetSignatureSize(obj["signature_size"].get<double>());
SetDataSize((m_numGroups * m_charsPerGroup * m_keyEncoding) - m_signatureSize);
if (obj["private_key"].is<picojson::object>())
SetPrivateKey(obj["private_key"].get<picojson::object>()["k"].get<std::string>().c_str());
if (obj["public_cert"].is<picojson::object>())
SetPublicKeyCertificate(obj["public_cert"].get<picojson::object>()["p"].get<std::string>().c_str());
if (obj["licensing_service_url"].is<std::string>())
SetLicensingServiceUrl(obj["licensing_service_url"].get<std::string>().c_str());
if (obj["licensing_service_template_id"].is<std::string>())
SetTemplateId(obj["licensing_service_template_id"].get<std::string>().c_str());
if (obj["properties"].is<picojson::object>())
m_properties.LoadJson(obj["properties"].get<picojson::object>());
}
catch (std::exception & e) {
throw new LicensingException(STATUS_GENERIC_ERROR, "error loading JSON license template");
}
}
#ifndef MAX_JSON_BUFFER_SIZE
#define MAX_JSON_BUFFER_SIZE 4096
#endif
const char * LicenseTemplateImpl::SaveJson(bool savePrivateKey)
{
BASE64 base64;
char buffer[MAX_XML_BUFFER_SIZE];
m_xmlTemplate.resize(0);
snprintf(buffer, MAX_XML_BUFFER_SIZE, "{"
"\n\t\"version\":%d"
",\n\t\"encoding\":\"%s\""
",\n\t\"char_groups\":%d"
",\n\t\"chars_per_group\":%d"
",\n\t\"group_sep\":\"%s\""
",\n\t\"header\":\"%s\""
",\n\t\"footer\":\"%s\""
",\n\t\"data_size\":%d", m_version, (m_keyEncoding == ENCODING_BASE64X) ? "BASE64" : "BASE32X", m_numGroups, m_charsPerGroup, m_groupSeparator.c_str(), m_header.c_str(), m_footer.c_str(), m_dataSize); m_xmlTemplate.append(buffer);
snprintf(buffer, MAX_XML_BUFFER_SIZE, ",\n\t\"data_fields\":["); m_xmlTemplate.append(buffer);
const char * name;
BitStruct::FIELD_TYPE type;
int size, offset;
string fieldType;
bool first = true;
for (const auto& field : m_dataFields)
{
name = field.first.c_str();
type = field.second.type;
size = field.second.size;
offset = field.second.offset;
if (!first) m_xmlTemplate.append(",");
switch ((int)type)
{
case FIELD_TYPE_INTEGER:
fieldType = "int";
break;
case FIELD_TYPE_STRING:
fieldType = "string";
break;
case FIELD_TYPE_RAW:
fieldType = "raw";
break;
case FIELD_TYPE_DATE13:
fieldType = "date13";
break;
case FIELD_TYPE_DATE14:
fieldType = "date14";
break;
case FIELD_TYPE_DATE16:
fieldType = "date16";
break;
default:
fieldType = "raw";
}
snprintf(buffer, MAX_XML_BUFFER_SIZE, "\n\t\t{ \"name\":\"%s\", \"type\":\"%s\", \"size\":%d, \"offset\":%d }", name, fieldType.c_str(), size, offset);
m_xmlTemplate.append(buffer);
first = false;
}
snprintf(buffer, MAX_XML_BUFFER_SIZE, "\n\t]"); m_xmlTemplate.append(buffer);
snprintf(buffer, MAX_XML_BUFFER_SIZE, ",\n\t\"validation_data_size\":%d", m_validationDataSize); m_xmlTemplate.append(buffer);
snprintf(buffer, MAX_XML_BUFFER_SIZE, ",\n\t\"validation_fields\":["); m_xmlTemplate.append(buffer);
first = true;
for (const auto& field : m_validationFields)
{
name = field.first.c_str();
type = field.second.type;
size = field.second.size;
offset = field.second.offset;
if (!first) m_xmlTemplate.append(",");
switch ((int)type)
{
case FIELD_TYPE_INTEGER:
fieldType = "int";
break;
case FIELD_TYPE_STRING:
fieldType = "string";
break;
case FIELD_TYPE_RAW:
fieldType = "raw";
break;
case FIELD_TYPE_DATE13:
fieldType = "date13";
break;
case FIELD_TYPE_DATE14:
fieldType = "date14";
break;
case FIELD_TYPE_DATE16:
fieldType = "date16";
break;
default:
fieldType = "raw";
}
snprintf(buffer, MAX_XML_BUFFER_SIZE, "\n\t\t{ \"name\":\"%s\", \"type\":\"%s\", \"size\":%d, \"offset\":%d }", name, fieldType.c_str(), size, offset);
m_xmlTemplate.append(buffer);
first = false;
}
snprintf(buffer, MAX_XML_BUFFER_SIZE, "\n\t]"); m_xmlTemplate.append(buffer);
snprintf(buffer, MAX_XML_BUFFER_SIZE, ",\n\t\"signature_size\":%d", m_signatureSize); m_xmlTemplate.append(buffer);
if (m_certificate)
{
snprintf(buffer, MAX_XML_BUFFER_SIZE, ",\n\t\"public_cert\": {\"kty\":\"softactivate_ec_v1\", \"p\":\"%s\"}", m_certificate->ToString()); m_xmlTemplate.append(buffer);
if (savePrivateKey && m_signingKey)
{
snprintf(buffer, MAX_XML_BUFFER_SIZE, ",\n\t\"private_key\": {\"kty\":\"softactivate_ec_v1\", \"k\":\"%s\"}", m_signingKey->ToString()); m_xmlTemplate.append(buffer);
}
}
if (m_licensingServiceUrl.length() > 0)
{
snprintf(buffer, MAX_XML_BUFFER_SIZE, ",\n\t\"licensing_service_url\":\"%s\"", m_licensingServiceUrl.c_str()); m_xmlTemplate.append(buffer);
}
if (!m_templateId.empty())
{
snprintf(buffer, MAX_XML_BUFFER_SIZE, ",\n\t\"licensing_service_template_id\":\"%s\"", m_templateId.c_str()); m_xmlTemplate.append(buffer);
}
if (m_properties.GetSize() > 0)
{
snprintf(buffer, MAX_XML_BUFFER_SIZE, ",\n\t\"properties\":"); m_xmlTemplate.append(buffer);
m_properties.SaveJson(m_xmlTemplate, "\t");
}
snprintf(buffer, MAX_XML_BUFFER_SIZE, "\n}"); m_xmlTemplate.append(buffer);
return m_xmlTemplate.c_str();
}
namespace ANSCENTER {
namespace Licensing {
template<>
LicenseTemplateT<char>::LicenseTemplateT():
m_Impl(*(new LicenseTemplateImpl()))
{
}
template<>
LicenseTemplateT<wchar_t>::LicenseTemplateT():
m_Impl(*(new LicenseTemplateImpl()))
{
}
template<>
LicenseTemplateT<char>::~LicenseTemplateT()
{
delete & m_Impl;
}
template<>
LicenseTemplateT<wchar_t>::~LicenseTemplateT()
{
delete & m_Impl;
}
template<>
LicenseTemplateT<char> * LicenseTemplateT<char>::Create()
{
return new LicenseTemplateT<char>();
}
template<>
LicenseTemplateT<wchar_t> * LicenseTemplateT<wchar_t>::Create()
{
return new LicenseTemplateT<wchar_t>();
}
template<>
void LicenseTemplateT<char>::Destroy(LicenseTemplateT<char> * obj)
{
delete obj;
}
template<>
void LicenseTemplateT<wchar_t>::Destroy(LicenseTemplateT<wchar_t> * obj)
{
delete obj;
}
template<>
void LicenseTemplateT<char>::SetNumberOfGroups(int numGroups)
{
m_Impl.SetNumberOfGroups(numGroups);
}
template<>
void LicenseTemplateT<wchar_t>::SetNumberOfGroups(int numGroups)
{
m_Impl.SetNumberOfGroups(numGroups);
}
template<>
unsigned LicenseTemplateT<char>::GetNumberOfGroups()
{
return m_Impl.GetNumberOfGroups();
}
template<>
unsigned LicenseTemplateT<wchar_t>::GetNumberOfGroups()
{
return m_Impl.GetNumberOfGroups();
}
template<>
void LicenseTemplateT<char>::SetCharactersPerGroup(int charsPerGroup)
{
m_Impl.SetCharactersPerGroup(charsPerGroup);
}
template<>
void LicenseTemplateT<wchar_t>::SetCharactersPerGroup(int charsPerGroup)
{
m_Impl.SetCharactersPerGroup(charsPerGroup);
}
template<>
unsigned LicenseTemplateT<char>::GetCharactersPerGroup()
{
return m_Impl.GetCharactersPerGroup();
}
template<>
unsigned LicenseTemplateT<wchar_t>::GetCharactersPerGroup()
{
return m_Impl.GetCharactersPerGroup();
}
template<>
void LicenseTemplateT<char>::SetGroupSeparator(const char * groupSep)
{
m_Impl.SetGroupSeparator(groupSep);
}
template<>
void LicenseTemplateT<wchar_t>::SetGroupSeparator(const wchar_t * groupSep)
{
m_Impl.SetGroupSeparator(w2s(groupSep).c_str());
}
template<>
const char * LicenseTemplateT<char>::GetGroupSeparator()
{
return m_Impl.GetGroupSeparator();
}
template<>
const wchar_t * LicenseTemplateT<wchar_t>::GetGroupSeparator()
{
static wstring wstr1;
wstr1 = s2w(m_Impl.GetGroupSeparator());
return wstr1.c_str();
}
template<>
void LicenseTemplateT<char>::SetEncoding(int encoding)
{
m_Impl.SetEncoding(encoding);
}
template<>
void LicenseTemplateT<wchar_t>::SetEncoding(int encoding)
{
m_Impl.SetEncoding(encoding);
}
template<>
int LicenseTemplateT<char>::GetEncoding()
{
return m_Impl.GetEncoding();
}
template<>
int LicenseTemplateT<wchar_t>::GetEncoding()
{
return m_Impl.GetEncoding();
}
template<>
void LicenseTemplateT<char>::SetHeader(const char * header)
{
m_Impl.SetHeader(header);
}
template<>
void LicenseTemplateT<wchar_t>::SetHeader(const wchar_t * header)
{
m_Impl.SetHeader(w2s(header).c_str());
}
template<>
const char * LicenseTemplateT<char>::GetHeader()
{
return m_Impl.GetHeader();
}
template<>
const wchar_t * LicenseTemplateT<wchar_t>::GetHeader()
{
static wstring wstr1;
wstr1 = s2w(m_Impl.GetHeader());
return wstr1.c_str();
}
template<>
void LicenseTemplateT<char>::SetFooter(const char * footer)
{
m_Impl.SetFooter(footer);
}
template<>
void LicenseTemplateT<wchar_t>::SetFooter(const wchar_t * footer)
{
m_Impl.SetFooter(w2s(footer).c_str());
}
template<>
const char * LicenseTemplateT<char>::GetFooter()
{
return m_Impl.GetFooter();
}
template<>
const wchar_t * LicenseTemplateT<wchar_t>::GetFooter()
{
static wstring wstr1;
wstr1 = s2w(m_Impl.GetFooter());
return wstr1.c_str();
}
template<>
void LicenseTemplateT<char>::SetDataSize(int sizeInBits)
{
m_Impl.SetDataSize(sizeInBits);
}
template<>
void LicenseTemplateT<wchar_t>::SetDataSize(int sizeInBits)
{
m_Impl.SetDataSize(sizeInBits);
}
template<>
unsigned LicenseTemplateT<char>::GetDataSize()
{
return m_Impl.GetDataSize();
}
template<>
unsigned LicenseTemplateT<wchar_t>::GetDataSize()
{
return m_Impl.GetDataSize();
}
template<>
void LicenseTemplateT<char>::AddDataField(const char * fieldName, int fieldType, int fieldBitSize, int offset)
{
m_Impl.AddDataField(fieldName, fieldType, fieldBitSize, offset);
}
template<>
void LicenseTemplateT<wchar_t>::AddDataField(const wchar_t * fieldName, int fieldType, int fieldBitSize, int offset)
{
m_Impl.AddDataField(w2s(fieldName).c_str(), fieldType, fieldBitSize, offset);
}
template<>
bool LicenseTemplateT<wchar_t>::GetDataField(const wchar_t * fieldName, int * fieldType, int * fieldBitSize, int * offset)
{
return m_Impl.GetDataField(w2s(fieldName).c_str(), fieldType, fieldBitSize, offset);
}
template<>
bool LicenseTemplateT<char>::GetDataField(const char * fieldName, int * fieldType, int * fieldBitSize, int * offset)
{
return m_Impl.GetDataField(fieldName, fieldType, fieldBitSize, offset);
}
template<>
bool LicenseTemplateT<char>::EnumDataFields(void **enumHandle, const char **fieldName, int * fieldType, int * fieldSize, int * offset)
{
return m_Impl.EnumDataFields(enumHandle, fieldName, fieldType, fieldSize, offset);
}
template<>
bool LicenseTemplateT<wchar_t>::EnumDataFields(void **enumHandle, const wchar_t **fieldName, int * fieldType, int * fieldSize, int * offset)
{
const char * name;
static std::wstring staticName;
bool result = m_Impl.EnumDataFields(enumHandle, &name, fieldType, fieldSize, offset);
if (result)
{
staticName = s2w(name);
*fieldName = staticName.c_str();
}
return result;
}
template<>
void LicenseTemplateT<char>::SetValidationDataSize(int sizeInBits)
{
m_Impl.SetValidationDataSize(sizeInBits);
}
template<>
void LicenseTemplateT<wchar_t>::SetValidationDataSize(int sizeInBits)
{
m_Impl.SetValidationDataSize(sizeInBits);
}
template<>
unsigned LicenseTemplateT<char>::GetValidationDataSize()
{
return m_Impl.GetValidationDataSize();
}
template<>
unsigned LicenseTemplateT<wchar_t>::GetValidationDataSize()
{
return m_Impl.GetValidationDataSize();
}
template<>
void LicenseTemplateT<char>::AddValidationField(const char * fieldName, int fieldType, int fieldBitSize, int offset)
{
m_Impl.AddValidationField(fieldName, fieldType, fieldBitSize, offset);
}
template<>
void LicenseTemplateT<wchar_t>::AddValidationField(const wchar_t * fieldName, int fieldType, int fieldBitSize, int offset)
{
m_Impl.AddValidationField(w2s(fieldName).c_str(), fieldType, fieldBitSize, offset);
}
template<>
bool LicenseTemplateT<char>::EnumValidationFields(void **enumHandle, const char **fieldName, int * fieldType, int * fieldSize, int * offset)
{
return m_Impl.EnumValidationFields(enumHandle, fieldName, fieldType, fieldSize, offset);
}
template<>
bool LicenseTemplateT<wchar_t>::EnumValidationFields(void **enumHandle, const wchar_t **fieldName, int * fieldType, int * fieldSize, int * offset)
{
const char * name;
static std::wstring staticName;
bool result = m_Impl.EnumValidationFields(enumHandle, &name, fieldType, fieldSize, offset);
if (result)
{
staticName = s2w(name);
*fieldName = staticName.c_str();
}
return result;
}
template<>
bool LicenseTemplateT<wchar_t>::GetValidationField(const wchar_t * fieldName, int * fieldType, int * fieldBitSize, int * offset)
{
return m_Impl.GetValidationField(w2s(fieldName).c_str(), fieldType, fieldBitSize, offset);
}
template<>
bool LicenseTemplateT<char>::GetValidationField(const char * fieldName, int * fieldType, int * fieldBitSize, int * offset)
{
return m_Impl.GetValidationField(fieldName, fieldType, fieldBitSize, offset);
}
template<>
void LicenseTemplateT<char>::SetSignatureSize(int signatureSize)
{
m_Impl.SetSignatureSize(signatureSize);
}
template<>
void LicenseTemplateT<wchar_t>::SetSignatureSize(int signatureSize)
{
m_Impl.SetSignatureSize(signatureSize);
}
template<>
unsigned LicenseTemplateT<char>::GetSignatureSize()
{
return m_Impl.GetSignatureSize();
}
template<>
unsigned LicenseTemplateT<wchar_t>::GetSignatureSize()
{
return m_Impl.GetSignatureSize();
}
template<>
void LicenseTemplateT<char>::SetVersion(int version)
{
m_Impl.SetVersion(version);
}
template<>
void LicenseTemplateT<wchar_t>::SetVersion(int version)
{
m_Impl.SetVersion(version);
}
template<>
unsigned LicenseTemplateT<char>::GetVersion()
{
return m_Impl.GetVersion();
}
template<>
void LicenseTemplateT<char>::SetTemplateId(const char * templateId)
{
m_Impl.SetTemplateId(templateId);
}
template<>
void LicenseTemplateT<wchar_t>::SetTemplateId(const wchar_t * templateId)
{
m_Impl.SetTemplateId(w2s(templateId).c_str());
}
template<>
unsigned LicenseTemplateT<wchar_t>::GetVersion()
{
return m_Impl.GetVersion();
}
template<>
void LicenseTemplateT<char>::LoadXml(const char * xmlTemplate)
{
m_Impl.LoadXml(xmlTemplate);
}
template<>
void LicenseTemplateT<wchar_t>::LoadXml(const char * xmlTemplate)
{
m_Impl.LoadXml(xmlTemplate);
}
template<>
const char * LicenseTemplateT<char>::SaveXml(bool savePrivateKey)
{
return m_Impl.SaveXml(savePrivateKey);
}
template<>
const char * LicenseTemplateT<wchar_t>::SaveXml(bool savePrivateKey)
{
return m_Impl.SaveXml(savePrivateKey);
}
template<>
void LicenseTemplateT<char>::LoadJson(const char * jsonTemplate)
{
m_Impl.LoadJson(jsonTemplate);
}
template<>
void LicenseTemplateT<wchar_t>::LoadJson(const char * jsonTemplate)
{
m_Impl.LoadJson(jsonTemplate);
}
template<>
const char * LicenseTemplateT<char>::SaveJson(bool savePrivateKey)
{
return m_Impl.SaveJson(savePrivateKey);
}
template<>
const char * LicenseTemplateT<wchar_t>::SaveJson(bool savePrivateKey)
{
return m_Impl.SaveJson(savePrivateKey);
}
template<>
void LicenseTemplateT<char>::SetLicensingServiceUrl(const char * url)
{
m_Impl.SetLicensingServiceUrl(url);
}
template<>
void LicenseTemplateT<wchar_t>::SetLicensingServiceUrl(const wchar_t * url)
{
m_Impl.SetLicensingServiceUrl(w2s(url).c_str());
}
template<>
const char * LicenseTemplateT<char>::GetLicensingServiceUrl()
{
return m_Impl.GetLicensingServiceUrl();
}
template<>
const wchar_t * LicenseTemplateT<wchar_t>::GetLicensingServiceUrl()
{
static wstring wstr1;
wstr1 = s2w(m_Impl.GetLicensingServiceUrl());
return wstr1.c_str();
}
template<>
void LicenseTemplateT<char>::SetPublicKeyCertificate(const char * base64Certificate)
{
m_Impl.SetPublicKeyCertificate(base64Certificate);
}
template<>
void LicenseTemplateT<wchar_t>::SetPublicKeyCertificate(const wchar_t * base64Certificate)
{
m_Impl.SetPublicKeyCertificate(w2s(base64Certificate).c_str());
}
template<>
const char * LicenseTemplateT<char>::GetPublicKeyCertificate()
{
return m_Impl.GetPublicKeyCertificate();
}
template<>
const wchar_t * LicenseTemplateT<wchar_t>::GetPublicKeyCertificate()
{
static wstring wstr1;
wstr1 = s2w(m_Impl.GetPublicKeyCertificate());
return wstr1.c_str();
}
template<>
void LicenseTemplateT<char>::SetPrivateKey(const char * base64Key)
{
m_Impl.SetPrivateKey(base64Key);
}
template<>
void LicenseTemplateT<wchar_t>::SetPrivateKey(const wchar_t * base64Key)
{
m_Impl.SetPrivateKey(w2s(base64Key).c_str());
}
template<>
const char * LicenseTemplateT<char>::GetPrivateKey()
{
return m_Impl.GetPrivateKey();
}
template<>
const wchar_t * LicenseTemplateT<wchar_t>::GetPrivateKey()
{
static wstring wstr1;
wstr1 = s2w(m_Impl.GetPrivateKey());
return wstr1.c_str();
}
template<>
void LicenseTemplateT<char>::SetProperty(const char * path, const char * name, const char * value)
{
m_Impl.SetProperty(path, (name) ? name : nullptr, value);
}
template<>
void LicenseTemplateT<wchar_t>::SetProperty(const wchar_t * path, const wchar_t * name, const wchar_t * value)
{
m_Impl.SetProperty(w2s(path).c_str(), (name) ? w2s(name).c_str() : nullptr, w2s(value).c_str());
}
template<>
const char * LicenseTemplateT<char>::GetProperty(const char * path, const char * name)
{
return m_Impl.GetProperty(path, name);
}
template<>
const wchar_t * LicenseTemplateT<wchar_t>::GetProperty(const wchar_t * path, const wchar_t * name)
{
static wstring wstr1;
wstr1 = s2w(m_Impl.GetProperty(w2s(path).c_str(), w2s(name).c_str()));
return wstr1.c_str();
}
template<>
void LicenseTemplateT<char>::GenerateSigningKeyPair()
{
m_Impl.GenerateSigningKeyPair();
}
template<>
void LicenseTemplateT<wchar_t>::GenerateSigningKeyPair()
{
m_Impl.GenerateSigningKeyPair();
}
};
};