From d4dff9b18547f2b1c2877312247c8f740070eaf1 Mon Sep 17 00:00:00 2001 From: Dale Fugier Date: Wed, 24 Jan 2018 14:55:26 -0800 Subject: [PATCH] Updated SampleWithLicensing --- .../SampleWithLicensingPlugIn.cpp | 43 ++-- .../SampleWithLicensingPlugIn.h | 2 +- .../SampleWithLicensingValidator.cpp | 195 +++++++++--------- .../cmdSampleWithLicensing.cpp | 7 +- 4 files changed, 126 insertions(+), 121 deletions(-) diff --git a/cpp/SampleWithLicensing/SampleWithLicensingPlugIn.cpp b/cpp/SampleWithLicensing/SampleWithLicensingPlugIn.cpp index 4d742ee8..925ddfae 100644 --- a/cpp/SampleWithLicensing/SampleWithLicensingPlugIn.cpp +++ b/cpp/SampleWithLicensing/SampleWithLicensingPlugIn.cpp @@ -42,14 +42,28 @@ RHINO_PLUG_IN_UPDATE_URL(L"https://github.com/mcneel/rhino-developer-samples"); // The one and only CSampleWithLicensingPlugIn object static CSampleWithLicensingPlugIn thePlugIn; -static CRhinoPlugIn::license_capabilities g_capabilities = ( - CRhinoPlugIn::license_capabilities)(CRhinoPlugIn::license_capabilities::can_be_evaluated - | CRhinoPlugIn::license_capabilities::can_be_purchased - | CRhinoPlugIn::license_capabilities::can_be_specified - //| CRhinoPlugIn::license_capabilities::supports_rhino_accounts - ); +///////////////////////////////////////////////////////////////////////////// +// CSampleWithLicensingPlugIn licensing info + +// When prompted for a license, the use interface will use this text +// mask to assist the user in entering the correct code. +static wchar_t* g_text_mask = L"AAAAAAAA-AAA-AAA"; + +// The UUID used by this plug0in to request a license. +// {FBDC82F8-578C-4DD7-827C-51B8C3DA7BD1} +static const GUID g_license_id = +{ 0xfbdc82f8, 0x578c, 0x4dd7,{ 0x82, 0x7c, 0x51, 0xb8, 0xc3, 0xda, 0x7b, 0xd1 } }; + +// Our plug-in's license capabilities +static CRhinoPlugIn::license_capabilities g_capabilities = (CRhinoPlugIn::license_capabilities) +( + CRhinoPlugIn::license_capabilities::can_be_evaluated + | CRhinoPlugIn::license_capabilities::can_be_purchased + | CRhinoPlugIn::license_capabilities::can_be_specified + // This sample current does not support Rhino accounts. + //| CRhinoPlugIn::license_capabilities::supports_rhino_accounts +); -static wchar_t* g_text_mask = L"AAAAAAA-AAA-AAA"; ///////////////////////////////////////////////////////////////////////////// // CSampleWithLicensingPlugIn definition @@ -62,41 +76,34 @@ CSampleWithLicensingPlugIn& SampleWithLicensingPlugIn() CSampleWithLicensingPlugIn::CSampleWithLicensingPlugIn() { - // TODO: Add construction code here m_plugin_version = RhinoPlugInVersion(); } -CSampleWithLicensingPlugIn::~CSampleWithLicensingPlugIn() -{ - // TODO: Add destruction code here -} - ///////////////////////////////////////////////////////////////////////////// // Required overrides const wchar_t* CSampleWithLicensingPlugIn::PlugInName() const { - // TODO: Return a short, friendly name for the plug-in. return RhinoPlugInName(); } const wchar_t* CSampleWithLicensingPlugIn::PlugInVersion() const { - // TODO: Return the version number of the plug-in. return m_plugin_version; } GUID CSampleWithLicensingPlugIn::PlugInID() const { - // TODO: Return a unique identifier for the plug-in. // {1F88325E-FA51-4B61-B3AC-27B589B70670} return ON_UuidFromString(RhinoPlugInId()); } BOOL CSampleWithLicensingPlugIn::OnLoadPlugIn() { - SetLicenseCapabilities(g_text_mask, g_capabilities, ON_UuidFromString(L"1ABD5EFC-2C65-11D7-B6F7-0050BABF6BC2")); - + // Before requesting a license, we must inform the license + // manager what we are capable of supporting. + SetLicenseCapabilities(g_text_mask, g_capabilities, g_license_id); + // Ask Rhino to get a product license for us. bool rc = GetLicense(); if (!rc) diff --git a/cpp/SampleWithLicensing/SampleWithLicensingPlugIn.h b/cpp/SampleWithLicensing/SampleWithLicensingPlugIn.h index a8d58324..c440d920 100644 --- a/cpp/SampleWithLicensing/SampleWithLicensingPlugIn.h +++ b/cpp/SampleWithLicensing/SampleWithLicensingPlugIn.h @@ -9,7 +9,7 @@ class CSampleWithLicensingPlugIn : public CRhinoUtilityPlugIn { public: CSampleWithLicensingPlugIn(); - ~CSampleWithLicensingPlugIn(); + ~CSampleWithLicensingPlugIn() = default; // Required overrides const wchar_t* PlugInName() const; diff --git a/cpp/SampleWithLicensing/SampleWithLicensingValidator.cpp b/cpp/SampleWithLicensing/SampleWithLicensingValidator.cpp index 6ebf13c4..312a588a 100644 --- a/cpp/SampleWithLicensing/SampleWithLicensingValidator.cpp +++ b/cpp/SampleWithLicensing/SampleWithLicensingValidator.cpp @@ -1,4 +1,5 @@ #include "stdafx.h" +#include "SampleWithLicensingPlugIn.h" #include "resource.h" //////////////////////////////////////////////////////////////// @@ -16,7 +17,7 @@ class CSampleWithLicensingValidator : public CRhinoLicenseValidator // Returns the 'build' type of this plug-in CRhinoLicenseValidator::product_build_type ProductBuildType() override; - // Obsolete + // This member is obsolete. CRhinoLicenseValidator::result ValidateProductKey(const wchar_t* product_key) override; // This member is called by Rhino, from CRhinoPlugIn::GetLicense(), when it @@ -31,45 +32,107 @@ class CSampleWithLicensingValidator : public CRhinoLicenseValidator // Called by Rhino, from CRhinoPlugIn::GetLicense(), after a call to VerifyLicenseKey that // sets m_requires_previous_version_license_verification to true. bool VerifyPreviousVersionLicense( - const wchar_t* license, - const wchar_t* previousVersionLicense + const wchar_t* licenseKey, + const wchar_t* previousVersionLicenseKey ) override; // When Rhino Accounts gets a new lease, this function is called. void OnLeaseChanged(CRhinoLeaseChangedEventArgs&) override; private: - ON_wString Reverse(const wchar_t* input); + bool ValidateSampleLicenseKey(const wchar_t* licenseKey); }; // The one and only CSampleWithLicensingValidator object static class CSampleWithLicensingValidator theSampleWithLicensingValidator; +// Class constructor CSampleWithLicensingValidator::CSampleWithLicensingValidator() { - m_requires_online_validation = true; + m_date_to_expire = 0.0; + m_license_count = 1; } +// Return the 'build' type of this plug-in CRhinoLicenseValidator::product_build_type CSampleWithLicensingValidator::ProductBuildType() { return CRhinoLicenseValidator::release_build; } +// This member is obsolete. CRhinoLicenseValidator::result CSampleWithLicensingValidator::ValidateProductKey(const wchar_t* product_key) +{ + return CRhinoLicenseValidator::result::error_show_message; +} + +// This member is called by Rhino, from CRhinoPlugIn::GetLicense(), when it +// needs your plug-in to validate your product key or license. +CRhinoLicenseValidator::result CSampleWithLicensingValidator::VerifyLicenseKey( + const wchar_t* licenseKey, + const wchar_t* validationCode, + const double validationCodeInstalledDate, + bool gracePeriodExpired +) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); - if (nullptr == product_key || 0 == product_key[0]) - return CSampleWithLicensingValidator::error_show_message; + // This icon will displayed in the "Licenses" page in the Options dialog. + // TODO: provide a a product icon here. + if (0 == m_product_icon) + { + int size = CRhinoDpi::IconSize(CRhinoDpi::IconType::NormalIcon); + m_product_icon = CRhinoDpi::LoadIcon(AfxGetInstanceHandle(), IDI_MAIN, size); + } + + CString license_key(licenseKey); + CString validation_code(validationCode); + + // This sample current does not support Rhino accounts. + m_requires_online_validation = false; + + m_requires_previous_version_license_verification = false; + bool bEvaluation = false; + + // Verify license key (if provided) + if (license_key.IsEmpty()) + { + license_key = "evaluate-111-222"; + } + else if (license_key.Left(8).CompareNoCase(L"EVALUATE-") == 0) + { + bEvaluation = true; + } + else if (license_key.Left(8).CompareNoCase(L"UPGRADE*-") == 0) + { + m_requires_previous_version_license_verification = true; + } + else if (!ValidateSampleLicenseKey(licenseKey)) + { + m_error_message = L"The license key is invalid."; + return CRhinoLicenseValidator::error_show_message; + } + + // Verify validation code (if provided) + if (!validation_code.IsEmpty()) + { + if (validation_code.CompareNoCase(L"invalid") == 0) + { + m_error_message = L"Your validation code is invalid."; + return CRhinoLicenseValidator::error_show_message; + } + } + + // Fill in the class members based on the license key + // and validation code. // This value will never be display in any user interface. - // When your plugin's ValidateProductKey function is called, it is + // When your plugin's VerifyLicenseKey function is called, it is // passed a a product, or CD, key that was entered into the Zoo - // administrator console. Your ValidateProductKey function will validate + // administrator console. Your VerifyLicenseKey function will validate // the product key and decode it into a product license. This is // where you can store this license. This value will be passed // to your application at runtime when it requests a license. - m_product_license = product_key; + m_product_license = license_key; // This value will display in user interface items, such as in // the Zoo console and in About dialog boxes. Also, this value @@ -77,100 +140,40 @@ CRhinoLicenseValidator::result CSampleWithLicensingValidator::ValidateProductKey // critical that this value be unique per product key, entered // by the administrator. No other license of this product, as // validated by this plugin, should return this value. - // - // This example just reverses product_key... - m_serial_number = Reverse(product_key); + // TODO: provide an obfuscated license string here. + m_serial_number = license_key; // This value will display in user interface items, such as in // the Zoo console and in About dialog boxes. // (e.g. "Rhinoceros 6", "Rhinoceros 6 Commercial", etc.) - m_license_title = "SampleWithLicensing 1.0 Commercial"; - - // The build of the product that this license work with. - // When your product requests a license from the Zoo, it - // will specify one of these build types. Note, this is just - // the int version of CRhinoLicenseValidator::product_build_type - // enum value. - m_build_type = CRhinoLicenseValidator::release_build; - - // Zoo licenses can be used by more than one instance of any application. - // For example, a single Rhino Education Lab license can be used by up - // to 30 systems simultaneously. If your license supports multiple instance, - // then specify the number of supported instances here. Otherwise just - // specify a value of 1 for single instance use. - m_license_count = 1; + // TODO: provide a license title string here. + m_license_title = SampleWithLicensingPlugIn().PlugInName(); // The Zoo supports licenses that expire. If your licensing scheme // is sophisticated enough to support this, then specify the // expiration date here. Note, this value must be specified in // Coordinated Universal Time (UTC). If your license does not expire, // then just this value to null. - memset(&m_date_to_expire, 0, sizeof(m_date_to_expire)); - - // This icon will displayed in the "Licenses" page in the Options dialog. - // Note, Rhino will make a copy of this icon.. - m_product_icon = CRhinoDpi::LoadIcon(AfxGetInstanceHandle(), IDI_MAIN, 32, 32); - - return CRhinoLicenseValidator::success; -} - -CRhinoLicenseValidator::result CSampleWithLicensingValidator::VerifyLicenseKey( - const wchar_t* licenseKey, - const wchar_t* validationCode, - const double validationCodeInstalledDate, - bool gracePeriodExpired -) -{ - CString sLicenseKey(licenseKey); - CString sValidationCode(validationCode); - m_requires_online_validation = false; - m_requires_previous_version_license_verification = false; - if (sLicenseKey.IsEmpty()) - { - sLicenseKey = "evaluate-111-222"; - } - - if (sLicenseKey.Left(8).CompareNoCase(L"evaluate-") == 0) - { - // Hard-coded evaluation licenses don't get validated online - m_requires_online_validation = false; - } - - m_product_license = sLicenseKey; - m_serial_number = sLicenseKey.MakeReverse(); - m_license_title = L"Sample License"; - m_license_count = 1; - - // This license expires in 90 days. - COleDateTime expire_date = COleDateTime::GetCurrentTime(); - COleDateTimeSpan interval; - interval.SetDateTimeSpan(90, 0, 0, 0); - m_date_to_expire = expire_date + interval; - - if (!sValidationCode.IsEmpty()) - { - if (sValidationCode.CompareNoCase(L"invalid") == 0) - { - m_error_message = L"Your validation code is invalid"; - return CRhinoLicenseValidator::error_show_message; - } - } - - if (sLicenseKey.Left(8).CompareNoCase(L"upgrade-") == 0) + if (bEvaluation) { - m_requires_previous_version_license_verification = true; + COleDateTime expire_date = COleDateTime::GetCurrentTime(); + COleDateTimeSpan interval; + interval.SetDateTimeSpan(90, 0, 0, 0); + m_date_to_expire = expire_date + interval; } return CRhinoLicenseValidator::success; } +// Called by Rhino, from CRhinoPlugIn::GetLicense(), after a call to VerifyLicenseKey that +// sets m_requires_previous_version_license_verification to true. bool CSampleWithLicensingValidator::VerifyPreviousVersionLicense( - const wchar_t* license, - const wchar_t* previousVersionLicense + const wchar_t* licenseKey, + const wchar_t* previousVersionLicenseKey ) { - CString sLicense(license); - CString sPrevVersionLicense(previousVersionLicense); + CString sLicense(licenseKey); + CString sPrevVersionLicense(previousVersionLicenseKey); if (sLicense.IsEmpty()) return false; @@ -181,10 +184,13 @@ bool CSampleWithLicensingValidator::VerifyPreviousVersionLicense( return true; } +// When Rhino Accounts gets a new lease, this function is called. void CSampleWithLicensingValidator::OnLeaseChanged(CRhinoLeaseChangedEventArgs& args) { + // This sample current does not support Rhino accounts. + CRhinoLicenseLease* pLease = args.GetLease(); - if (pLease == nullptr) + if (nullptr == pLease) { // Lease has been voided; this product should behave as if it has no // license. It is up to the plug-in to determine what that looks like. @@ -197,19 +203,16 @@ void CSampleWithLicensingValidator::OnLeaseChanged(CRhinoLeaseChangedEventArgs& // Verify that pLease->IsExpired() is false } -ON_wString CSampleWithLicensingValidator::Reverse(const wchar_t* input) +// Our license key validation code. In this example, we'll accept +// anything but a null or empty string. +bool CSampleWithLicensingValidator::ValidateSampleLicenseKey(const wchar_t* licenseKey) { - ON_wString str; - - if (nullptr == input || 0 == input[0]) - return str; - - str = input; - str.MakeReverse(); - - return str; + if (nullptr == licenseKey || 0 == licenseKey) + return false; + return true; } + // // END SampleWithLicensingValidator license validator // diff --git a/cpp/SampleWithLicensing/cmdSampleWithLicensing.cpp b/cpp/SampleWithLicensing/cmdSampleWithLicensing.cpp index 3e1af82e..8cd21f5c 100644 --- a/cpp/SampleWithLicensing/cmdSampleWithLicensing.cpp +++ b/cpp/SampleWithLicensing/cmdSampleWithLicensing.cpp @@ -30,12 +30,7 @@ static class CCommandSampleWithLicensing theSampleWithLicensingCommand; CRhinoCommand::result CCommandSampleWithLicensing::RunCommand(const CRhinoCommandContext& context) { - ON_wString wStr; - wStr.Format(L"The \"%s\" command is under construction.\n", EnglishCommandName()); - if (context.IsInteractive()) - RhinoMessageBox(wStr, PlugIn()->PlugInName(), MB_OK); - else - RhinoApp().Print(wStr); + RhinoApp().Print(L"%s plug-in loaded.\n", SampleWithLicensingPlugIn().PlugInName()); return CRhinoCommand::success; }