@@ -68,7 +68,7 @@ public sealed class Version {
6868 /// iText is a registered trademark by iText Group NV.
6969 /// Please don't change this constant.
7070 /// </remarks>
71- private static String iText = "iText\u00ae " ;
71+ private static String iTextProductName = "iText\u00ae " ;
7272
7373 /// <summary>This String contains the version number of this iText release.</summary>
7474 /// <remarks>
@@ -84,7 +84,7 @@ public sealed class Version {
8484 /// iText Group requests that you retain the iText producer line
8585 /// in every PDF that is created or manipulated using iText.
8686 /// </remarks>
87- private String iTextVersion = iText + " " + release + " \u00a9 2000-2017 iText Group NV" ;
87+ private String producerLine = iTextProductName + " " + release + " \u00a9 2000-2017 iText Group NV" ;
8888
8989 /// <summary>The license key.</summary>
9090 private String key = null ;
@@ -102,14 +102,9 @@ public static iText.Kernel.Version GetInstance() {
102102 version = new iText . Kernel . Version ( ) ;
103103 lock ( version ) {
104104 try {
105- String licenseeInfoMethodName = "GetLicenseeInfoForVersion" ;
106- Type klass = GetLicenseKeyClass ( ) ;
107- if ( klass != null ) {
108- Type [ ] cArg = new Type [ ] { typeof ( String ) } ;
109- MethodInfo m = klass . GetMethod ( licenseeInfoMethodName , cArg ) ;
110- String coreVersion = release ;
111- Object [ ] args = new Object [ ] { coreVersion } ;
112- String [ ] info = ( String [ ] ) m . Invoke ( System . Activator . CreateInstance ( klass ) , args ) ;
105+ String coreVersion = release ;
106+ String [ ] info = GetLicenseeInfoFromLicenseKey ( coreVersion ) ;
107+ if ( info != null ) {
113108 if ( info [ 3 ] != null && info [ 3 ] . Trim ( ) . Length > 0 ) {
114109 version . key = info [ 3 ] ;
115110 }
@@ -124,13 +119,12 @@ public static iText.Kernel.Version GetInstance() {
124119 }
125120 if ( info . Length > 6 ) {
126121 if ( info [ 6 ] != null && info [ 6 ] . Trim ( ) . Length > 0 ) {
127- if ( ! release . StartsWith ( info [ 6 ] ) ) {
128- throw new ArgumentException ( "Your license key version doesn't match the iText version." ) ;
129- }
122+ //Compare versions with this release versions
123+ CheckLicenseVersion ( coreVersion , info [ 6 ] ) ;
130124 }
131125 }
132126 if ( info [ 4 ] != null && info [ 4 ] . Trim ( ) . Length > 0 ) {
133- version . iTextVersion = info [ 4 ] ;
127+ version . producerLine = info [ 4 ] ;
134128 }
135129 else {
136130 if ( info [ 2 ] != null && info [ 2 ] . Trim ( ) . Length > 0 ) {
@@ -153,10 +147,24 @@ public static iText.Kernel.Version GetInstance() {
153147 version . AddAGPLPostfix ( null ) ;
154148 }
155149 }
156- catch ( ArgumentException iae ) {
157- version . AddAGPLPostfix ( iae . InnerException ) ;
150+ catch ( LicenseVersionException lve ) {
151+ //Catch the exception
152+ //Rethrow license version exceptions
153+ throw ;
154+ }
155+ catch ( TypeLoadException ) {
156+ //License key library not on classpath, switch to AGPL
157+ version . AddAGPLPostfix ( null ) ;
158158 }
159159 catch ( Exception e ) {
160+ //Check if an iText5 license is loaded
161+ if ( e . InnerException != null && e . InnerException . Message . Equals ( LicenseVersionException . LICENSE_FILE_NOT_LOADED
162+ ) ) {
163+ if ( IsiText5licenseLoaded ( ) ) {
164+ throw new LicenseVersionException ( LicenseVersionException . NO_I_TEXT7_LICENSE_IS_LOADED_BUT_AN_I_TEXT5_LICENSE_IS_LOADED
165+ ) ;
166+ }
167+ }
160168 version . AddAGPLPostfix ( e . InnerException ) ;
161169 }
162170 }
@@ -184,7 +192,7 @@ public static bool IsExpired() {
184192 /// </remarks>
185193 /// <returns>the product name</returns>
186194 public String GetProduct ( ) {
187- return iText ;
195+ return iTextProductName ;
188196 }
189197
190198 /// <summary>Gets the release number.</summary>
@@ -207,7 +215,7 @@ public String GetRelease() {
207215 /// </remarks>
208216 /// <returns>iText version</returns>
209217 public String GetVersion ( ) {
210- return iTextVersion ;
218+ return producerLine ;
211219 }
212220
213221 /// <summary>Returns a license key if one was provided, or null if not.</summary>
@@ -217,22 +225,113 @@ public String GetKey() {
217225 }
218226
219227 private void AddLicensedPostfix ( String ownerName ) {
220- iTextVersion += " (" + ownerName ;
228+ producerLine += " (" + ownerName ;
221229 if ( ! key . ToLowerInvariant ( ) . StartsWith ( "trial" ) ) {
222- iTextVersion += "; licensed version)" ;
230+ producerLine += "; licensed version)" ;
223231 }
224232 else {
225- iTextVersion += "; " + key + ")" ;
233+ producerLine += "; " + key + ")" ;
226234 }
227235 }
228236
229237 private void AddAGPLPostfix ( Exception cause ) {
230- iTextVersion += AGPL ;
238+ producerLine += AGPL ;
231239 if ( cause != null && cause . Message != null && cause . Message . Contains ( "expired" ) ) {
232240 expired = true ;
233241 }
234242 }
235243
244+ private static void CheckLicenseVersion ( String coreVersionString , String licenseVersionString ) {
245+ String [ ] coreVersions = ParseVersionString ( coreVersionString ) ;
246+ String [ ] licenseVersions = ParseVersionString ( licenseVersionString ) ;
247+ int coreMajor = System . Convert . ToInt32 ( coreVersions [ 0 ] ) ;
248+ int coreMinor = System . Convert . ToInt32 ( coreVersions [ 1 ] ) ;
249+ int licenseMajor = System . Convert . ToInt32 ( licenseVersions [ 0 ] ) ;
250+ int licenseMinor = System . Convert . ToInt32 ( licenseVersions [ 1 ] ) ;
251+ //Major version check
252+ if ( licenseMajor < coreMajor ) {
253+ throw new LicenseVersionException ( LicenseVersionException . THE_MAJOR_VERSION_OF_THE_LICENSE_0_IS_LOWER_THAN_THE_MAJOR_VERSION_1_OF_THE_CORE_LIBRARY
254+ ) . SetMessageParams ( licenseMajor , coreMajor ) ;
255+ }
256+ if ( licenseMajor > coreMajor ) {
257+ throw new LicenseVersionException ( LicenseVersionException . THE_MAJOR_VERSION_OF_THE_LICENSE_0_IS_HIGHER_THAN_THE_MAJOR_VERSION_1_OF_THE_CORE_LIBRARY
258+ ) . SetMessageParams ( licenseMajor , coreMajor ) ;
259+ }
260+ //Minor version check
261+ if ( licenseMinor < coreMinor ) {
262+ throw new LicenseVersionException ( LicenseVersionException . THE_MINOR_VERSION_OF_THE_LICENSE_0_IS_LOWER_THAN_THE_MINOR_VERSION_1_OF_THE_CORE_LIBRARY
263+ ) . SetMessageParams ( licenseMinor , coreMinor ) ;
264+ }
265+ }
266+
267+ private static String [ ] ParseVersionString ( String version ) {
268+ String splitRegex = "\\ ." ;
269+ String [ ] split = iText . IO . Util . StringUtil . Split ( version , splitRegex ) ;
270+ //Guard for empty versions and throw exceptions
271+ if ( split . Length == 0 ) {
272+ throw new LicenseVersionException ( LicenseVersionException . VERSION_STRING_IS_EMPTY_AND_CANNOT_BE_PARSED ) ;
273+ }
274+ //Desired Format: X.Y.Z-....
275+ //Also catch X, X.Y-...
276+ String major = split [ 0 ] ;
277+ String minor = "0" ;
278+ //If no minor version is present, default to 0
279+ if ( split . Length > 1 ) {
280+ minor = split [ 1 ] . Substring ( 0 ) ;
281+ }
282+ //Check if both values are numbers
283+ if ( ! IsVersionNumeric ( major ) ) {
284+ throw new LicenseVersionException ( LicenseVersionException . MAJOR_VERSION_IS_NOT_NUMERIC ) ;
285+ }
286+ if ( ! IsVersionNumeric ( minor ) ) {
287+ throw new LicenseVersionException ( LicenseVersionException . MINOR_VERSION_IS_NOT_NUMERIC ) ;
288+ }
289+ return new String [ ] { major , minor } ;
290+ }
291+
292+ /// <exception cref="System.TypeLoadException"/>
293+ /// <exception cref="System.MissingMethodException"/>
294+ /// <exception cref="System.MemberAccessException"/>
295+ /// <exception cref="Java.Lang.InstantiationException"/>
296+ /// <exception cref="System.Reflection.TargetInvocationException"/>
297+ private static String [ ] GetLicenseeInfoFromLicenseKey ( String validatorKey ) {
298+ String licenseeInfoMethodName = "getLicenseeInfoForVersion" ;
299+ Type klass = GetLicenseKeyClass ( ) ;
300+ if ( klass != null ) {
301+ Type [ ] cArg = new Type [ ] { typeof ( String ) } ;
302+ MethodInfo m = klass . GetMethod ( licenseeInfoMethodName , cArg ) ;
303+ Object [ ] args = new Object [ ] { validatorKey } ;
304+ String [ ] info = ( String [ ] ) m . Invoke ( System . Activator . CreateInstance ( klass ) , args ) ;
305+ return info ;
306+ }
307+ return null ;
308+ }
309+
310+ private static bool IsiText5licenseLoaded ( ) {
311+ String validatorKey5 = "5" ;
312+ bool result = false ;
313+ try {
314+ String [ ] info = GetLicenseeInfoFromLicenseKey ( validatorKey5 ) ;
315+ result = true ;
316+ }
317+ catch ( Exception ) {
318+ }
319+ //TODO: Log this exception?
320+ return result ;
321+ }
322+
323+ private static bool IsVersionNumeric ( String version ) {
324+ //I did not want to introduce an extra dependency on apache.commons in order to use StringUtils.
325+ //This small method is not the most optimal, but it should do for release
326+ try {
327+ System . Double . Parse ( version , System . Globalization . CultureInfo . InvariantCulture ) ;
328+ return true ;
329+ }
330+ catch ( FormatException ) {
331+ return false ;
332+ }
333+ }
334+
236335 private static Type GetLicenseKeyClass ( ) {
237336 String licenseKeyClassPartialName = "iText.License.LicenseKey, itext.licensekey" ;
238337 String licenseKeyClassFullName = null ;
0 commit comments