99using System . Text . RegularExpressions ;
1010using System . Threading ;
1111using ServiceStack . Text ;
12+ using ServiceStack . Text . Common ;
1213
1314namespace ServiceStack
1415{
1516 public class LicenseException : Exception
1617 {
1718 public LicenseException ( string message ) : base ( message ) { }
19+ public LicenseException ( string message , Exception innerException ) : base ( message , innerException ) { }
1820 }
1921
2022 public enum LicenseType
@@ -167,6 +169,9 @@ public static void RegisterLicense(string licenseKeyText)
167169 {
168170 JsConfig . InitStatics ( ) ;
169171
172+ if ( __activatedLicense != null ) //Skip multple license registrations. Use RemoveLicense() to reset.
173+ return ;
174+
170175 string subId = null ;
171176#if ! ( PCL || NETSTANDARD1_1 )
172177 var hold = Thread . CurrentThread . CurrentCulture ;
@@ -182,17 +187,7 @@ public static void RegisterLicense(string licenseKeyText)
182187 throw new LicenseException ( "This subscription has been revoked. " + ContactDetails ) ;
183188
184189 var key = PclExport . Instance . VerifyLicenseKeyText ( licenseKeyText ) ;
185-
186- var releaseDate = Env . GetReleaseDate ( ) ;
187- if ( releaseDate > key . Expiry )
188- throw new LicenseException ( "This license has expired on {0} and is not valid for use with this release."
189- . Fmt ( key . Expiry . ToString ( "d" ) ) + ContactDetails ) . Trace ( ) ;
190-
191- if ( key . Type == LicenseType . Trial && DateTime . UtcNow > key . Expiry )
192- throw new LicenseException ( "This trial license has expired on {0}."
193- . Fmt ( key . Expiry . ToString ( "d" ) ) + ContactDetails ) . Trace ( ) ;
194-
195- __activatedLicense = key ;
190+ ValidateLicenseKey ( key ) ;
196191 }
197192 catch ( Exception ex )
198193 {
@@ -201,9 +196,22 @@ public static void RegisterLicense(string licenseKeyText)
201196
202197 var msg = "This license is invalid." + ContactDetails ;
203198 if ( ! string . IsNullOrEmpty ( subId ) )
204- msg += " The id for this license is '{0}'" . Fmt ( subId ) ;
199+ msg += $ " The id for this license is '{ subId } '";
200+
201+ lock ( typeof ( LicenseUtils ) )
202+ {
203+ try
204+ {
205+ var key = PclExport . Instance . VerifyLicenseKeyTextFallback ( licenseKeyText ) ;
206+ ValidateLicenseKey ( key ) ;
207+ }
208+ catch ( Exception exFallback )
209+ {
210+ throw new LicenseException ( msg , exFallback ) . Trace ( ) ;
211+ }
212+ }
205213
206- throw new LicenseException ( msg ) . Trace ( ) ;
214+ throw new LicenseException ( msg , ex ) . Trace ( ) ;
207215 }
208216 finally
209217 {
@@ -213,6 +221,19 @@ public static void RegisterLicense(string licenseKeyText)
213221 }
214222 }
215223
224+ private static void ValidateLicenseKey ( LicenseKey key )
225+ {
226+ var releaseDate = Env . GetReleaseDate ( ) ;
227+ if ( releaseDate > key . Expiry )
228+ throw new LicenseException ( $ "This license has expired on { key . Expiry : d} and is not valid for use with this release."
229+ + ContactDetails ) . Trace ( ) ;
230+
231+ if ( key . Type == LicenseType . Trial && DateTime . UtcNow > key . Expiry )
232+ throw new LicenseException ( $ "This trial license has expired on { key . Expiry : d} ." + ContactDetails ) . Trace ( ) ;
233+
234+ __activatedLicense = key ;
235+ }
236+
216237 public static void RemoveLicense ( )
217238 {
218239 __activatedLicense = null ;
@@ -365,7 +386,7 @@ public static LicenseKey ToLicenseKey(this string licenseKeyText)
365386 var key = jsv . FromJsv < LicenseKey > ( ) ;
366387
367388 if ( key . Ref != refId )
368- throw new LicenseException ( "The license '{0}' is not assigned to CustomerId '{1}'." . Fmt ( base64 ) ) . Trace ( ) ;
389+ throw new LicenseException ( "The license '{0}' is not assigned to CustomerId '{1}'." . Fmt ( base64 , refId ) ) . Trace ( ) ;
369390
370391 return key ;
371392 }
@@ -376,9 +397,33 @@ public static LicenseKey ToLicenseKey(this string licenseKeyText)
376397 }
377398 }
378399
400+ public static LicenseKey ToLicenseKeyFallback ( this string licenseKeyText )
401+ {
402+ licenseKeyText = Regex . Replace ( licenseKeyText , @"\s+" , "" ) ;
403+ var parts = licenseKeyText . SplitOnFirst ( '-' ) ;
404+ var refId = parts [ 0 ] ;
405+ var base64 = parts [ 1 ] ;
406+ var jsv = Convert . FromBase64String ( base64 ) . FromUtf8Bytes ( ) ;
407+
408+ var map = jsv . FromJsv < Dictionary < string , string > > ( ) ;
409+ var key = new LicenseKey
410+ {
411+ Ref = map . Get ( "Ref" ) ,
412+ Name = map . Get ( "Name" ) ,
413+ Type = ( LicenseType ) Enum . Parse ( typeof ( LicenseType ) , map . Get ( "Type" ) , ignoreCase : true ) ,
414+ Hash = map . Get ( "Hash" ) ,
415+ Expiry = DateTimeSerializer . ParseManual ( map . Get ( "Expiry" ) , DateTimeKind . Utc ) . GetValueOrDefault ( ) ,
416+ } ;
417+
418+ if ( key . Ref != refId )
419+ throw new LicenseException ( $ "The license '{ base64 } ' is not assigned to CustomerId '{ refId } '.") . Trace ( ) ;
420+
421+ return key ;
422+ }
423+
379424 public static string GetHashKeyToSign ( this LicenseKey key )
380425 {
381- return "{0 }:{1 }:{2}:{3}" . Fmt ( key . Ref , key . Name , key . Expiry . ToString ( " yyyy-MM-dd" ) , key . Type ) ;
426+ return $ " { key . Ref } :{ key . Name } :{ key . Expiry : yyyy-MM-dd} : { key . Type } " ;
382427 }
383428
384429 public static Exception GetInnerMostException ( this Exception ex )
0 commit comments