Skip to content

Commit f146856

Browse files
Samuel Huylebroeckitext-teamcity
authored andcommitted
Version checking
DEVSIX-1698 Autoported commit. Original commit hash: [44d7a03af]
1 parent 47cd340 commit f146856

File tree

3 files changed

+236
-23
lines changed

3 files changed

+236
-23
lines changed
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using iText.IO.Util;
4+
5+
namespace iText.Kernel {
6+
/// <summary>Exception class for License-key version exceptions throw in the Version class</summary>
7+
public class LicenseVersionException : Exception {
8+
public const String NO_I_TEXT7_LICENSE_IS_LOADED_BUT_AN_I_TEXT5_LICENSE_IS_LOADED = "No iText7 License is loaded but an iText5 license is loaded.";
9+
10+
public const String THE_MAJOR_VERSION_OF_THE_LICENSE_0_IS_LOWER_THAN_THE_MAJOR_VERSION_1_OF_THE_CORE_LIBRARY
11+
= "The major version of the license ({0}) is lower than the major version ({1}) of the Core library.";
12+
13+
public const String THE_MAJOR_VERSION_OF_THE_LICENSE_0_IS_HIGHER_THAN_THE_MAJOR_VERSION_1_OF_THE_CORE_LIBRARY
14+
= "The major version of the license ({0}) is higher than the major version ({1}) of the Core library.";
15+
16+
public const String THE_MINOR_VERSION_OF_THE_LICENSE_0_IS_LOWER_THAN_THE_MINOR_VERSION_1_OF_THE_CORE_LIBRARY
17+
= "The minor version of the license ({0}) is lower than the minor version ({1}) of the Core library.";
18+
19+
public const String THE_MINOR_VERSION_OF_THE_LICENSE_0_IS_HIGHER_THAN_THE_MINOR_VERSION_1_OF_THE_CORE_LIBRARY
20+
= "The minor version of the license ({0}) is higher than the minor version ({1}) of the Core library.";
21+
22+
public const String VERSION_STRING_IS_EMPTY_AND_CANNOT_BE_PARSED = "Version string is empty and cannot be parsed.";
23+
24+
public const String MAJOR_VERSION_IS_NOT_NUMERIC = "Major version is not numeric";
25+
26+
public const String MINOR_VERSION_IS_NOT_NUMERIC = "Minor version is not numeric";
27+
28+
public const String UNKNOWN_EXCEPTION_WHEN_CHECKING_LICENSE_VERSION = "Unknown Exception when checking License version";
29+
30+
public const String LICENSE_FILE_NOT_LOADED = "License file not loaded.";
31+
32+
/// <summary>Object for more details</summary>
33+
protected internal Object @object;
34+
35+
private IList<Object> messageParams;
36+
37+
/// <summary>Creates a new instance of PdfException.</summary>
38+
/// <param name="message">the detail message.</param>
39+
public LicenseVersionException(String message)
40+
: base(message) {
41+
}
42+
43+
/// <summary>Creates a new instance of PdfException.</summary>
44+
/// <param name="cause">
45+
/// the cause (which is saved for later retrieval by
46+
/// <see cref="System.Exception.InnerException()"/>
47+
/// method).
48+
/// </param>
49+
public LicenseVersionException(Exception cause)
50+
: this(UNKNOWN_EXCEPTION_WHEN_CHECKING_LICENSE_VERSION, cause) {
51+
}
52+
53+
/// <summary>Creates a new instance of PdfException.</summary>
54+
/// <param name="message">the detail message.</param>
55+
/// <param name="obj">an object for more details.</param>
56+
public LicenseVersionException(String message, Object obj)
57+
: this(message) {
58+
this.@object = obj;
59+
}
60+
61+
/// <summary>Creates a new instance of PdfException.</summary>
62+
/// <param name="message">the detail message.</param>
63+
/// <param name="cause">
64+
/// the cause (which is saved for later retrieval by
65+
/// <see cref="System.Exception.InnerException()"/>
66+
/// method).
67+
/// </param>
68+
public LicenseVersionException(String message, Exception cause)
69+
: base(message, cause) {
70+
}
71+
72+
/// <summary>Creates a new instance of PdfException.</summary>
73+
/// <param name="message">the detail message.</param>
74+
/// <param name="cause">
75+
/// the cause (which is saved for later retrieval by
76+
/// <see cref="System.Exception.InnerException()"/>
77+
/// method).
78+
/// </param>
79+
/// <param name="obj">an object for more details.</param>
80+
public LicenseVersionException(String message, Exception cause, Object obj)
81+
: this(message, cause) {
82+
this.@object = obj;
83+
}
84+
85+
public override String Message {
86+
get {
87+
if (messageParams == null || messageParams.Count == 0) {
88+
return base.Message;
89+
}
90+
else {
91+
return MessageFormatUtil.Format(base.Message, GetMessageParams());
92+
}
93+
}
94+
}
95+
96+
/// <summary>Sets additional params for Exception message.</summary>
97+
/// <param name="messageParams">additional params.</param>
98+
/// <returns>object itself.</returns>
99+
public virtual iText.Kernel.LicenseVersionException SetMessageParams(params Object[] messageParams) {
100+
this.messageParams = new List<Object>();
101+
this.messageParams.AddAll(messageParams);
102+
return this;
103+
}
104+
105+
/// <summary>Gets additional params for Exception message.</summary>
106+
protected internal virtual Object[] GetMessageParams() {
107+
Object[] parameters = new Object[messageParams.Count];
108+
for (int i = 0; i < messageParams.Count; i++) {
109+
parameters[i] = messageParams[i];
110+
}
111+
return parameters;
112+
}
113+
}
114+
}

itext/itext.kernel/itext/kernel/Version.cs

Lines changed: 121 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -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 + " \u00a92000-2017 iText Group NV";
87+
private String producerLine = iTextProductName + " " + release + " \u00a92000-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;

port-hash

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
f2eea8ee75c83026cba91bb84d1833c59d08bcf0
1+
44d7a03afc6a80eb4ac12ef4f1418e2480b5f54f

0 commit comments

Comments
 (0)