2024-01-03 17:59:04 +00:00
|
|
|
package stirling.software.SPDF.utils;
|
|
|
|
|
|
|
|
import java.io.File;
|
|
|
|
import java.io.FileOutputStream;
|
|
|
|
import java.io.IOException;
|
|
|
|
import java.io.InputStream;
|
2024-12-24 09:52:53 +00:00
|
|
|
import java.net.*;
|
2024-10-14 22:34:41 +01:00
|
|
|
import java.nio.charset.StandardCharsets;
|
2024-12-24 09:52:53 +00:00
|
|
|
import java.nio.file.*;
|
2024-01-03 17:59:04 +00:00
|
|
|
import java.nio.file.attribute.BasicFileAttributes;
|
2024-10-14 22:34:41 +01:00
|
|
|
import java.security.MessageDigest;
|
2024-01-03 17:59:04 +00:00
|
|
|
import java.util.ArrayList;
|
2025-01-31 11:00:03 +00:00
|
|
|
import java.util.Arrays;
|
2024-10-14 22:34:41 +01:00
|
|
|
import java.util.Enumeration;
|
2024-01-03 17:59:04 +00:00
|
|
|
import java.util.List;
|
2024-10-14 22:34:41 +01:00
|
|
|
import java.util.UUID;
|
2024-01-03 17:59:04 +00:00
|
|
|
|
2025-03-20 08:58:22 +01:00
|
|
|
import org.springframework.core.io.Resource;
|
|
|
|
import org.springframework.core.io.ResourceLoader;
|
|
|
|
import org.springframework.core.io.support.ResourcePatternUtils;
|
2024-01-03 17:59:04 +00:00
|
|
|
import org.springframework.web.multipart.MultipartFile;
|
|
|
|
|
2024-03-10 14:00:00 +00:00
|
|
|
import com.fathzer.soft.javaluator.DoubleEvaluator;
|
|
|
|
|
2024-02-06 00:00:49 +00:00
|
|
|
import io.github.pixee.security.HostValidator;
|
|
|
|
import io.github.pixee.security.Urls;
|
|
|
|
|
2024-12-17 10:26:18 +01:00
|
|
|
import lombok.extern.slf4j.Slf4j;
|
2025-02-23 13:36:21 +00:00
|
|
|
|
Improved Configuration and YAML Management (#2966)
# Description of Changes
**What was changed:**
- **Configuration Updates:**
Replaced all calls to `GeneralUtils.saveKeyToConfig` with the new
`GeneralUtils.saveKeyToSettings` method across multiple classes (e.g.,
`LicenseKeyChecker`, `InitialSetup`, `SettingsController`, etc.). This
update ensures consistent management of configuration settings.
- **File Path and Exception Handling:**
Updated file path handling in `SPDFApplication` by creating `Path`
objects from string paths and logging these paths for clarity. Also
refined exception handling by catching more specific exceptions (e.g.,
using `IOException` instead of a generic `Exception`).
- **Analytics Flag and Rate Limiting:**
Changed the analytics flag in the application properties from a `String`
to a `Boolean`, and updated related logic in `AppConfig` and
`PostHogService`. The rate-limiting property retrieval in `AppConfig`
was also refined for clarity.
- **YAML Configuration Management:**
Replaced the previous manual, line-based YAML merging logic in
`ConfigInitializer` with a new `YamlHelper` class. This helper leverages
the SnakeYAML engine to load, update, and save YAML configurations more
robustly while preserving comments and formatting.
**Why the change was made:**
- **Improved Maintainability:**
Consolidating configuration update logic into a single utility method
(`saveKeyToSettings`) reduces code duplication and simplifies future
maintenance.
- **Enhanced Robustness:**
The new `YamlHelper` class ensures that configuration files are merged
accurately and safely, minimizing risks of data loss or format
corruption.
- **Better Type Safety and Exception Handling:**
Switching the analytics flag to a Boolean and refining exception
handling improves code robustness and debugging efficiency.
- **Clarity and Consistency:**
Standardizing file path handling and logging practices enhances code
readability across the project.
**Challenges encountered:**
- **YAML Merging Complexity:**
Integrating the new `YamlHelper` required careful handling to preserve
existing settings, comments, and formatting during merges.
- **Type Conversion and Backward Compatibility:**
Updating the analytics flag from a string to a Boolean required
extensive testing to ensure backward compatibility and proper
functionality.
- **Exception Granularity:**
Refactoring exception handling from a generic to a more specific
approach involved a detailed review to cover all edge cases.
Closes #<issue_number>
---
## Checklist
- [x] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md)
(if applicable)
- [x] I have performed a self-review of my own code
- [x] My changes generate no new warnings
### Documentation
- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)
### UI Changes (if applicable)
- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)
### Testing (if applicable)
- [x] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#6-testing)
for more details.
---------
Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
2025-02-25 22:52:59 +01:00
|
|
|
import stirling.software.SPDF.config.YamlHelper;
|
2025-04-28 17:36:27 +01:00
|
|
|
import stirling.software.common.configuration.InstallationPathConfig;
|
2024-01-03 17:59:04 +00:00
|
|
|
|
2024-12-17 10:26:18 +01:00
|
|
|
@Slf4j
|
|
|
|
public class GeneralUtils {
|
2024-06-02 11:59:43 +01:00
|
|
|
|
2024-01-12 23:15:27 +00:00
|
|
|
public static File convertMultipartFileToFile(MultipartFile multipartFile) throws IOException {
|
2024-02-02 00:15:46 +00:00
|
|
|
File tempFile = Files.createTempFile("temp", null).toFile();
|
2025-03-10 20:17:45 +00:00
|
|
|
try (InputStream inputStream = multipartFile.getInputStream();
|
|
|
|
FileOutputStream outputStream = new FileOutputStream(tempFile)) {
|
|
|
|
|
|
|
|
byte[] buffer = new byte[8192];
|
|
|
|
int bytesRead;
|
|
|
|
|
|
|
|
while ((bytesRead = inputStream.read(buffer)) != -1) {
|
|
|
|
outputStream.write(buffer, 0, bytesRead);
|
|
|
|
}
|
2024-01-12 23:15:27 +00:00
|
|
|
}
|
|
|
|
return tempFile;
|
|
|
|
}
|
|
|
|
|
2024-01-03 17:59:04 +00:00
|
|
|
public static void deleteDirectory(Path path) throws IOException {
|
|
|
|
Files.walkFileTree(
|
|
|
|
path,
|
|
|
|
new SimpleFileVisitor<Path>() {
|
|
|
|
@Override
|
|
|
|
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
|
|
|
|
throws IOException {
|
2024-05-27 16:31:00 +01:00
|
|
|
Files.deleteIfExists(file);
|
2024-01-03 17:59:04 +00:00
|
|
|
return FileVisitResult.CONTINUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public FileVisitResult postVisitDirectory(Path dir, IOException exc)
|
|
|
|
throws IOException {
|
2024-05-27 16:31:00 +01:00
|
|
|
Files.deleteIfExists(dir);
|
2024-01-03 17:59:04 +00:00
|
|
|
return FileVisitResult.CONTINUE;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
public static String convertToFileName(String name) {
|
|
|
|
String safeName = name.replaceAll("[^a-zA-Z0-9]", "_");
|
|
|
|
if (safeName.length() > 50) {
|
|
|
|
safeName = safeName.substring(0, 50);
|
|
|
|
}
|
|
|
|
return safeName;
|
|
|
|
}
|
2025-03-20 08:58:22 +01:00
|
|
|
|
|
|
|
// Get resources from a location pattern
|
|
|
|
public static Resource[] getResourcesFromLocationPattern(
|
|
|
|
String locationPattern, ResourceLoader resourceLoader) throws Exception {
|
|
|
|
// Normalize the path for file resources
|
|
|
|
if (locationPattern.startsWith("file:")) {
|
|
|
|
String rawPath = locationPattern.substring(5).replace("\\*", "").replace("/*", "");
|
|
|
|
Path normalizePath = Paths.get(rawPath).normalize();
|
|
|
|
locationPattern = "file:" + normalizePath.toString().replace("\\", "/") + "/*";
|
|
|
|
}
|
|
|
|
return ResourcePatternUtils.getResourcePatternResolver(resourceLoader)
|
|
|
|
.getResources(locationPattern);
|
|
|
|
}
|
2024-01-03 17:59:04 +00:00
|
|
|
|
|
|
|
public static boolean isValidURL(String urlStr) {
|
|
|
|
try {
|
2024-02-06 00:00:49 +00:00
|
|
|
Urls.create(
|
|
|
|
urlStr, Urls.HTTP_PROTOCOLS, HostValidator.DENY_COMMON_INFRASTRUCTURE_TARGETS);
|
2024-01-03 17:59:04 +00:00
|
|
|
return true;
|
|
|
|
} catch (MalformedURLException e) {
|
|
|
|
return false;
|
|
|
|
}
|
2024-08-23 10:17:50 +02:00
|
|
|
}
|
2024-08-08 22:35:15 +02:00
|
|
|
|
|
|
|
public static boolean isURLReachable(String urlStr) {
|
|
|
|
try {
|
2024-12-11 21:06:07 +01:00
|
|
|
// Parse the URL
|
2024-08-23 12:52:45 +02:00
|
|
|
URL url = URI.create(urlStr).toURL();
|
2024-12-11 21:06:07 +01:00
|
|
|
|
|
|
|
// Allow only http and https protocols
|
|
|
|
String protocol = url.getProtocol();
|
2025-01-06 12:41:30 +00:00
|
|
|
if (!"http".equals(protocol) && !"https".equals(protocol)) {
|
2024-12-11 21:06:07 +01:00
|
|
|
return false; // Disallow other protocols
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if the host is a local address
|
|
|
|
String host = url.getHost();
|
|
|
|
if (isLocalAddress(host)) {
|
|
|
|
return false; // Exclude local addresses
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if the URL is reachable
|
2024-08-08 22:35:15 +02:00
|
|
|
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
|
|
|
connection.setRequestMethod("HEAD");
|
2024-12-11 21:10:18 +01:00
|
|
|
// connection.setConnectTimeout(5000); // Set connection timeout
|
|
|
|
// connection.setReadTimeout(5000); // Set read timeout
|
2024-08-08 22:35:15 +02:00
|
|
|
int responseCode = connection.getResponseCode();
|
|
|
|
return (200 <= responseCode && responseCode <= 399);
|
2024-12-11 21:06:07 +01:00
|
|
|
} catch (Exception e) {
|
|
|
|
return false; // Return false in case of any exception
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private static boolean isLocalAddress(String host) {
|
|
|
|
try {
|
|
|
|
// Resolve DNS to IP address
|
|
|
|
InetAddress address = InetAddress.getByName(host);
|
|
|
|
|
|
|
|
// Check for local addresses
|
2024-12-17 10:26:18 +01:00
|
|
|
return address.isAnyLocalAddress()
|
|
|
|
|| // Matches 0.0.0.0 or similar
|
|
|
|
address.isLoopbackAddress()
|
|
|
|
|| // Matches 127.0.0.1 or ::1
|
|
|
|
address.isSiteLocalAddress()
|
|
|
|
|| // Matches private IPv4 ranges: 192.168.x.x, 10.x.x.x, 172.16.x.x to
|
|
|
|
// 172.31.x.x
|
|
|
|
address.getHostAddress()
|
|
|
|
.startsWith("fe80:"); // Matches link-local IPv6 addresses
|
2024-12-11 21:06:07 +01:00
|
|
|
} catch (Exception e) {
|
|
|
|
return false; // Return false for invalid or unresolved addresses
|
2024-08-08 22:35:15 +02:00
|
|
|
}
|
2024-01-03 17:59:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public static File multipartToFile(MultipartFile multipart) throws IOException {
|
|
|
|
Path tempFile = Files.createTempFile("overlay-", ".pdf");
|
|
|
|
try (InputStream in = multipart.getInputStream();
|
|
|
|
FileOutputStream out = new FileOutputStream(tempFile.toFile())) {
|
|
|
|
byte[] buffer = new byte[1024];
|
|
|
|
int bytesRead;
|
|
|
|
while ((bytesRead = in.read(buffer)) != -1) {
|
|
|
|
out.write(buffer, 0, bytesRead);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return tempFile.toFile();
|
|
|
|
}
|
|
|
|
|
|
|
|
public static Long convertSizeToBytes(String sizeStr) {
|
|
|
|
if (sizeStr == null) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
sizeStr = sizeStr.trim().toUpperCase();
|
2024-04-09 18:47:53 +02:00
|
|
|
sizeStr = sizeStr.replace(",", ".").replace(" ", "");
|
2024-01-03 17:59:04 +00:00
|
|
|
try {
|
|
|
|
if (sizeStr.endsWith("KB")) {
|
2024-08-23 10:17:50 +02:00
|
|
|
return (long)
|
|
|
|
(Double.parseDouble(sizeStr.substring(0, sizeStr.length() - 2)) * 1024);
|
2024-01-03 17:59:04 +00:00
|
|
|
} else if (sizeStr.endsWith("MB")) {
|
2024-08-23 10:17:50 +02:00
|
|
|
return (long)
|
|
|
|
(Double.parseDouble(sizeStr.substring(0, sizeStr.length() - 2))
|
|
|
|
* 1024
|
|
|
|
* 1024);
|
2024-01-03 17:59:04 +00:00
|
|
|
} else if (sizeStr.endsWith("GB")) {
|
2024-08-23 10:17:50 +02:00
|
|
|
return (long)
|
|
|
|
(Double.parseDouble(sizeStr.substring(0, sizeStr.length() - 2))
|
|
|
|
* 1024
|
|
|
|
* 1024
|
|
|
|
* 1024);
|
2024-01-03 17:59:04 +00:00
|
|
|
} else if (sizeStr.endsWith("B")) {
|
|
|
|
return Long.parseLong(sizeStr.substring(0, sizeStr.length() - 1));
|
|
|
|
} else {
|
|
|
|
// Assume MB if no unit is specified
|
|
|
|
return (long) (Double.parseDouble(sizeStr) * 1024 * 1024);
|
|
|
|
}
|
|
|
|
} catch (NumberFormatException e) {
|
|
|
|
// The numeric part of the input string cannot be parsed, handle this case
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2025-02-28 20:43:35 +00:00
|
|
|
public static String formatBytes(long bytes) {
|
|
|
|
if (bytes < 1024) {
|
|
|
|
return bytes + " B";
|
|
|
|
} else if (bytes < 1024 * 1024) {
|
|
|
|
return String.format("%.2f KB", bytes / 1024.0);
|
|
|
|
} else if (bytes < 1024 * 1024 * 1024) {
|
|
|
|
return String.format("%.2f MB", bytes / (1024.0 * 1024.0));
|
|
|
|
} else {
|
|
|
|
return String.format("%.2f GB", bytes / (1024.0 * 1024.0 * 1024.0));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-10 14:00:00 +00:00
|
|
|
public static List<Integer> parsePageList(String pages, int totalPages, boolean oneBased) {
|
|
|
|
if (pages == null) {
|
|
|
|
return List.of(1); // Default to first page if input is null
|
2024-02-06 00:00:49 +00:00
|
|
|
}
|
2024-03-10 14:00:00 +00:00
|
|
|
try {
|
|
|
|
return parsePageList(pages.split(","), totalPages, oneBased);
|
|
|
|
} catch (NumberFormatException e) {
|
|
|
|
return List.of(1); // Default to first page if input is invalid
|
2024-02-06 00:00:49 +00:00
|
|
|
}
|
2024-01-03 17:59:04 +00:00
|
|
|
}
|
2024-02-10 14:52:59 +00:00
|
|
|
|
2024-03-10 14:00:00 +00:00
|
|
|
public static List<Integer> parsePageList(String[] pages, int totalPages) {
|
|
|
|
return parsePageList(pages, totalPages, false);
|
2024-02-10 14:52:27 +00:00
|
|
|
}
|
2024-02-10 14:52:59 +00:00
|
|
|
|
2024-03-10 14:00:00 +00:00
|
|
|
public static List<Integer> parsePageList(String[] pages, int totalPages, boolean oneBased) {
|
|
|
|
List<Integer> result = new ArrayList<>();
|
|
|
|
int offset = oneBased ? 1 : 0;
|
|
|
|
for (String page : pages) {
|
|
|
|
if ("all".equalsIgnoreCase(page)) {
|
2024-03-13 19:15:10 +00:00
|
|
|
|
2024-01-03 17:59:04 +00:00
|
|
|
for (int i = 0; i < totalPages; i++) {
|
2024-03-10 14:00:00 +00:00
|
|
|
result.add(i + offset);
|
2024-01-03 17:59:04 +00:00
|
|
|
}
|
2024-03-10 14:00:00 +00:00
|
|
|
} else if (page.contains(",")) {
|
|
|
|
// Split the string into parts, could be single pages or ranges
|
|
|
|
String[] parts = page.split(",");
|
|
|
|
for (String part : parts) {
|
|
|
|
result.addAll(handlePart(part, totalPages, offset));
|
2024-01-03 17:59:04 +00:00
|
|
|
}
|
2024-03-10 14:00:00 +00:00
|
|
|
} else {
|
|
|
|
result.addAll(handlePart(page, totalPages, offset));
|
|
|
|
}
|
|
|
|
}
|
2025-02-18 11:57:56 +00:00
|
|
|
return result;
|
2024-03-10 14:00:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public static List<Integer> evaluateNFunc(String expression, int maxValue) {
|
|
|
|
List<Integer> results = new ArrayList<>();
|
|
|
|
DoubleEvaluator evaluator = new DoubleEvaluator();
|
|
|
|
|
|
|
|
// Validate the expression
|
|
|
|
if (!expression.matches("[0-9n+\\-*/() ]+")) {
|
|
|
|
throw new IllegalArgumentException("Invalid expression");
|
|
|
|
}
|
2024-01-03 17:59:04 +00:00
|
|
|
|
Enhancement: Enhance NFunction evaluation and support advanced NFunctions (#2577)
# Description
Enhance NFunction sanitization and support advanced functions:
- Start page counting from 1 rather than 0 as PDFs are one based from
the user's perspective, thus functions results would be affected by
starting with "0" rather than "1".
- Ignore out of bound results rather than stopping iterations to work
with functions such as (n - 4) when page count is 10 as we would get
positive values when n > 4.
- Remove spaces to support expressions such as 2n + 1 rather just 2n+1.
- Support advanced functions as follows:
- Support expressions such as follows 5(n-1), n(n-1), expressions
followed by opening rounded without '*' operator.
- Support expressions such as follows (n-1)5, (n-1)n, expressions
preceded closing rounded without '*' operator.
- Support consecutive "n" expressions, examples: nnn, 2nn, nn*3, nnnn.
Closes #(issue_number)
## Checklist
- [x] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [x] I have performed a self-review of my own code
- [ ] I have attached images of the change if it is UI based
- [x] I have commented my code, particularly in hard-to-understand areas
- [ ] If my code has heavily changed functionality I have updated
relevant docs on [Stirling-PDFs doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
- [x] My changes generate no new warnings
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)
2025-01-02 16:48:20 +02:00
|
|
|
for (int n = 1; n <= maxValue; n++) {
|
2024-08-08 22:35:15 +02:00
|
|
|
// Replace 'n' with the current value of n, correctly handling numbers before
|
|
|
|
// 'n'
|
Enhancement: Enhance NFunction evaluation and support advanced NFunctions (#2577)
# Description
Enhance NFunction sanitization and support advanced functions:
- Start page counting from 1 rather than 0 as PDFs are one based from
the user's perspective, thus functions results would be affected by
starting with "0" rather than "1".
- Ignore out of bound results rather than stopping iterations to work
with functions such as (n - 4) when page count is 10 as we would get
positive values when n > 4.
- Remove spaces to support expressions such as 2n + 1 rather just 2n+1.
- Support advanced functions as follows:
- Support expressions such as follows 5(n-1), n(n-1), expressions
followed by opening rounded without '*' operator.
- Support expressions such as follows (n-1)5, (n-1)n, expressions
preceded closing rounded without '*' operator.
- Support consecutive "n" expressions, examples: nnn, 2nn, nn*3, nnnn.
Closes #(issue_number)
## Checklist
- [x] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [x] I have performed a self-review of my own code
- [ ] I have attached images of the change if it is UI based
- [x] I have commented my code, particularly in hard-to-understand areas
- [ ] If my code has heavily changed functionality I have updated
relevant docs on [Stirling-PDFs doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
- [x] My changes generate no new warnings
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)
2025-01-02 16:48:20 +02:00
|
|
|
String sanitizedExpression = sanitizeNFunction(expression, n);
|
2024-03-10 14:00:00 +00:00
|
|
|
Double result = evaluator.evaluate(sanitizedExpression);
|
2024-01-03 17:59:04 +00:00
|
|
|
|
2024-03-10 14:00:00 +00:00
|
|
|
// Check if the result is null or not within bounds
|
2025-01-06 12:41:30 +00:00
|
|
|
if (result == null) break;
|
Enhancement: Enhance NFunction evaluation and support advanced NFunctions (#2577)
# Description
Enhance NFunction sanitization and support advanced functions:
- Start page counting from 1 rather than 0 as PDFs are one based from
the user's perspective, thus functions results would be affected by
starting with "0" rather than "1".
- Ignore out of bound results rather than stopping iterations to work
with functions such as (n - 4) when page count is 10 as we would get
positive values when n > 4.
- Remove spaces to support expressions such as 2n + 1 rather just 2n+1.
- Support advanced functions as follows:
- Support expressions such as follows 5(n-1), n(n-1), expressions
followed by opening rounded without '*' operator.
- Support expressions such as follows (n-1)5, (n-1)n, expressions
preceded closing rounded without '*' operator.
- Support consecutive "n" expressions, examples: nnn, 2nn, nn*3, nnnn.
Closes #(issue_number)
## Checklist
- [x] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [x] I have performed a self-review of my own code
- [ ] I have attached images of the change if it is UI based
- [x] I have commented my code, particularly in hard-to-understand areas
- [ ] If my code has heavily changed functionality I have updated
relevant docs on [Stirling-PDFs doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
- [x] My changes generate no new warnings
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)
2025-01-02 16:48:20 +02:00
|
|
|
|
|
|
|
if (result.intValue() > 0 && result.intValue() <= maxValue)
|
2024-03-10 14:00:00 +00:00
|
|
|
results.add(result.intValue());
|
|
|
|
}
|
|
|
|
|
|
|
|
return results;
|
|
|
|
}
|
|
|
|
|
Enhancement: Enhance NFunction evaluation and support advanced NFunctions (#2577)
# Description
Enhance NFunction sanitization and support advanced functions:
- Start page counting from 1 rather than 0 as PDFs are one based from
the user's perspective, thus functions results would be affected by
starting with "0" rather than "1".
- Ignore out of bound results rather than stopping iterations to work
with functions such as (n - 4) when page count is 10 as we would get
positive values when n > 4.
- Remove spaces to support expressions such as 2n + 1 rather just 2n+1.
- Support advanced functions as follows:
- Support expressions such as follows 5(n-1), n(n-1), expressions
followed by opening rounded without '*' operator.
- Support expressions such as follows (n-1)5, (n-1)n, expressions
preceded closing rounded without '*' operator.
- Support consecutive "n" expressions, examples: nnn, 2nn, nn*3, nnnn.
Closes #(issue_number)
## Checklist
- [x] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [x] I have performed a self-review of my own code
- [ ] I have attached images of the change if it is UI based
- [x] I have commented my code, particularly in hard-to-understand areas
- [ ] If my code has heavily changed functionality I have updated
relevant docs on [Stirling-PDFs doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
- [x] My changes generate no new warnings
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)
2025-01-02 16:48:20 +02:00
|
|
|
private static String sanitizeNFunction(String expression, int nValue) {
|
|
|
|
String sanitizedExpression = expression.replace(" ", "");
|
2025-01-06 12:41:30 +00:00
|
|
|
String multiplyByOpeningRoundBracketPattern =
|
|
|
|
"([0-9n)])\\("; // example: n(n-1), 9(n-1), (n-1)(n-2)
|
|
|
|
sanitizedExpression =
|
|
|
|
sanitizedExpression.replaceAll(multiplyByOpeningRoundBracketPattern, "$1*(");
|
Enhancement: Enhance NFunction evaluation and support advanced NFunctions (#2577)
# Description
Enhance NFunction sanitization and support advanced functions:
- Start page counting from 1 rather than 0 as PDFs are one based from
the user's perspective, thus functions results would be affected by
starting with "0" rather than "1".
- Ignore out of bound results rather than stopping iterations to work
with functions such as (n - 4) when page count is 10 as we would get
positive values when n > 4.
- Remove spaces to support expressions such as 2n + 1 rather just 2n+1.
- Support advanced functions as follows:
- Support expressions such as follows 5(n-1), n(n-1), expressions
followed by opening rounded without '*' operator.
- Support expressions such as follows (n-1)5, (n-1)n, expressions
preceded closing rounded without '*' operator.
- Support consecutive "n" expressions, examples: nnn, 2nn, nn*3, nnnn.
Closes #(issue_number)
## Checklist
- [x] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [x] I have performed a self-review of my own code
- [ ] I have attached images of the change if it is UI based
- [x] I have commented my code, particularly in hard-to-understand areas
- [ ] If my code has heavily changed functionality I have updated
relevant docs on [Stirling-PDFs doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
- [x] My changes generate no new warnings
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)
2025-01-02 16:48:20 +02:00
|
|
|
|
2025-01-06 12:41:30 +00:00
|
|
|
String multiplyByClosingRoundBracketPattern =
|
|
|
|
"\\)([0-9n)])"; // example: (n-1)n, (n-1)9, (n-1)(n-2)
|
|
|
|
sanitizedExpression =
|
|
|
|
sanitizedExpression.replaceAll(multiplyByClosingRoundBracketPattern, ")*$1");
|
Enhancement: Enhance NFunction evaluation and support advanced NFunctions (#2577)
# Description
Enhance NFunction sanitization and support advanced functions:
- Start page counting from 1 rather than 0 as PDFs are one based from
the user's perspective, thus functions results would be affected by
starting with "0" rather than "1".
- Ignore out of bound results rather than stopping iterations to work
with functions such as (n - 4) when page count is 10 as we would get
positive values when n > 4.
- Remove spaces to support expressions such as 2n + 1 rather just 2n+1.
- Support advanced functions as follows:
- Support expressions such as follows 5(n-1), n(n-1), expressions
followed by opening rounded without '*' operator.
- Support expressions such as follows (n-1)5, (n-1)n, expressions
preceded closing rounded without '*' operator.
- Support consecutive "n" expressions, examples: nnn, 2nn, nn*3, nnnn.
Closes #(issue_number)
## Checklist
- [x] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [x] I have performed a self-review of my own code
- [ ] I have attached images of the change if it is UI based
- [x] I have commented my code, particularly in hard-to-understand areas
- [ ] If my code has heavily changed functionality I have updated
relevant docs on [Stirling-PDFs doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
- [x] My changes generate no new warnings
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)
2025-01-02 16:48:20 +02:00
|
|
|
|
|
|
|
sanitizedExpression = insertMultiplicationBeforeN(sanitizedExpression, nValue);
|
|
|
|
return sanitizedExpression;
|
|
|
|
}
|
|
|
|
|
2024-03-10 14:00:00 +00:00
|
|
|
private static String insertMultiplicationBeforeN(String expression, int nValue) {
|
|
|
|
// Insert multiplication between a number and 'n' (e.g., "4n" becomes "4*n")
|
|
|
|
String withMultiplication = expression.replaceAll("(\\d)n", "$1*n");
|
Enhancement: Enhance NFunction evaluation and support advanced NFunctions (#2577)
# Description
Enhance NFunction sanitization and support advanced functions:
- Start page counting from 1 rather than 0 as PDFs are one based from
the user's perspective, thus functions results would be affected by
starting with "0" rather than "1".
- Ignore out of bound results rather than stopping iterations to work
with functions such as (n - 4) when page count is 10 as we would get
positive values when n > 4.
- Remove spaces to support expressions such as 2n + 1 rather just 2n+1.
- Support advanced functions as follows:
- Support expressions such as follows 5(n-1), n(n-1), expressions
followed by opening rounded without '*' operator.
- Support expressions such as follows (n-1)5, (n-1)n, expressions
preceded closing rounded without '*' operator.
- Support consecutive "n" expressions, examples: nnn, 2nn, nn*3, nnnn.
Closes #(issue_number)
## Checklist
- [x] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [x] I have performed a self-review of my own code
- [ ] I have attached images of the change if it is UI based
- [x] I have commented my code, particularly in hard-to-understand areas
- [ ] If my code has heavily changed functionality I have updated
relevant docs on [Stirling-PDFs doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
- [x] My changes generate no new warnings
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)
2025-01-02 16:48:20 +02:00
|
|
|
withMultiplication = formatConsecutiveNsForNFunction(withMultiplication);
|
2024-03-10 14:00:00 +00:00
|
|
|
// Now replace 'n' with its current value
|
2024-04-09 06:52:52 +01:00
|
|
|
return withMultiplication.replace("n", String.valueOf(nValue));
|
2024-03-10 14:00:00 +00:00
|
|
|
}
|
|
|
|
|
Enhancement: Enhance NFunction evaluation and support advanced NFunctions (#2577)
# Description
Enhance NFunction sanitization and support advanced functions:
- Start page counting from 1 rather than 0 as PDFs are one based from
the user's perspective, thus functions results would be affected by
starting with "0" rather than "1".
- Ignore out of bound results rather than stopping iterations to work
with functions such as (n - 4) when page count is 10 as we would get
positive values when n > 4.
- Remove spaces to support expressions such as 2n + 1 rather just 2n+1.
- Support advanced functions as follows:
- Support expressions such as follows 5(n-1), n(n-1), expressions
followed by opening rounded without '*' operator.
- Support expressions such as follows (n-1)5, (n-1)n, expressions
preceded closing rounded without '*' operator.
- Support consecutive "n" expressions, examples: nnn, 2nn, nn*3, nnnn.
Closes #(issue_number)
## Checklist
- [x] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [x] I have performed a self-review of my own code
- [ ] I have attached images of the change if it is UI based
- [x] I have commented my code, particularly in hard-to-understand areas
- [ ] If my code has heavily changed functionality I have updated
relevant docs on [Stirling-PDFs doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
- [x] My changes generate no new warnings
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)
2025-01-02 16:48:20 +02:00
|
|
|
private static String formatConsecutiveNsForNFunction(String expression) {
|
|
|
|
String text = expression;
|
|
|
|
while (text.matches(".*n{2,}.*")) {
|
|
|
|
text = text.replaceAll("(?<!n)n{2}", "n*n");
|
|
|
|
}
|
|
|
|
return text;
|
|
|
|
}
|
|
|
|
|
2024-03-10 14:00:00 +00:00
|
|
|
private static List<Integer> handlePart(String part, int totalPages, int offset) {
|
|
|
|
List<Integer> partResult = new ArrayList<>();
|
|
|
|
|
|
|
|
// First check for n-syntax because it should not be processed as a range
|
|
|
|
if (part.contains("n")) {
|
|
|
|
partResult = evaluateNFunc(part, totalPages);
|
|
|
|
// Adjust the results according to the offset
|
|
|
|
for (int i = 0; i < partResult.size(); i++) {
|
|
|
|
int adjustedValue = partResult.get(i) - 1 + offset;
|
|
|
|
partResult.set(i, adjustedValue);
|
|
|
|
}
|
|
|
|
} else if (part.contains("-")) {
|
|
|
|
// Process ranges only if it's not n-syntax
|
|
|
|
String[] rangeParts = part.split("-");
|
|
|
|
try {
|
|
|
|
int start = Integer.parseInt(rangeParts[0]);
|
2025-01-30 23:44:57 +05:30
|
|
|
int end =
|
|
|
|
(rangeParts.length > 1 && !rangeParts[1].isEmpty())
|
|
|
|
? Integer.parseInt(rangeParts[1])
|
|
|
|
: totalPages;
|
2024-03-10 14:00:00 +00:00
|
|
|
for (int i = start; i <= end; i++) {
|
|
|
|
if (i >= 1 && i <= totalPages) {
|
|
|
|
partResult.add(i - 1 + offset);
|
2024-01-03 17:59:04 +00:00
|
|
|
}
|
|
|
|
}
|
2024-03-10 14:00:00 +00:00
|
|
|
} catch (NumberFormatException e) {
|
|
|
|
// Range is invalid, ignore this part
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// This is a single page number
|
|
|
|
try {
|
|
|
|
int pageNum = Integer.parseInt(part.trim());
|
|
|
|
if (pageNum >= 1 && pageNum <= totalPages) {
|
|
|
|
partResult.add(pageNum - 1 + offset);
|
2024-01-03 17:59:04 +00:00
|
|
|
}
|
2024-03-10 14:00:00 +00:00
|
|
|
} catch (NumberFormatException ignored) {
|
|
|
|
// Ignore invalid numbers
|
2024-01-03 17:59:04 +00:00
|
|
|
}
|
|
|
|
}
|
2024-03-10 14:00:00 +00:00
|
|
|
return partResult;
|
2024-01-03 17:59:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public static boolean createDir(String path) {
|
|
|
|
Path folder = Paths.get(path);
|
|
|
|
if (!Files.exists(folder)) {
|
|
|
|
try {
|
|
|
|
Files.createDirectories(folder);
|
|
|
|
} catch (IOException e) {
|
2024-12-17 10:26:18 +01:00
|
|
|
log.error("exception", e);
|
2024-01-03 17:59:04 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
2024-10-14 22:34:41 +01:00
|
|
|
|
|
|
|
public static boolean isValidUUID(String uuid) {
|
|
|
|
if (uuid == null) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
UUID.fromString(uuid);
|
|
|
|
return true;
|
|
|
|
} catch (IllegalArgumentException e) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-01-31 11:00:03 +00:00
|
|
|
/*------------------------------------------------------------------------*
|
|
|
|
* Internal Implementation Details *
|
|
|
|
*------------------------------------------------------------------------*/
|
2024-10-14 22:34:41 +01:00
|
|
|
|
Improved Configuration and YAML Management (#2966)
# Description of Changes
**What was changed:**
- **Configuration Updates:**
Replaced all calls to `GeneralUtils.saveKeyToConfig` with the new
`GeneralUtils.saveKeyToSettings` method across multiple classes (e.g.,
`LicenseKeyChecker`, `InitialSetup`, `SettingsController`, etc.). This
update ensures consistent management of configuration settings.
- **File Path and Exception Handling:**
Updated file path handling in `SPDFApplication` by creating `Path`
objects from string paths and logging these paths for clarity. Also
refined exception handling by catching more specific exceptions (e.g.,
using `IOException` instead of a generic `Exception`).
- **Analytics Flag and Rate Limiting:**
Changed the analytics flag in the application properties from a `String`
to a `Boolean`, and updated related logic in `AppConfig` and
`PostHogService`. The rate-limiting property retrieval in `AppConfig`
was also refined for clarity.
- **YAML Configuration Management:**
Replaced the previous manual, line-based YAML merging logic in
`ConfigInitializer` with a new `YamlHelper` class. This helper leverages
the SnakeYAML engine to load, update, and save YAML configurations more
robustly while preserving comments and formatting.
**Why the change was made:**
- **Improved Maintainability:**
Consolidating configuration update logic into a single utility method
(`saveKeyToSettings`) reduces code duplication and simplifies future
maintenance.
- **Enhanced Robustness:**
The new `YamlHelper` class ensures that configuration files are merged
accurately and safely, minimizing risks of data loss or format
corruption.
- **Better Type Safety and Exception Handling:**
Switching the analytics flag to a Boolean and refining exception
handling improves code robustness and debugging efficiency.
- **Clarity and Consistency:**
Standardizing file path handling and logging practices enhances code
readability across the project.
**Challenges encountered:**
- **YAML Merging Complexity:**
Integrating the new `YamlHelper` required careful handling to preserve
existing settings, comments, and formatting during merges.
- **Type Conversion and Backward Compatibility:**
Updating the analytics flag from a string to a Boolean required
extensive testing to ensure backward compatibility and proper
functionality.
- **Exception Granularity:**
Refactoring exception handling from a generic to a more specific
approach involved a detailed review to cover all edge cases.
Closes #<issue_number>
---
## Checklist
- [x] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md)
(if applicable)
- [x] I have performed a self-review of my own code
- [x] My changes generate no new warnings
### Documentation
- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)
### UI Changes (if applicable)
- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)
### Testing (if applicable)
- [x] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#6-testing)
for more details.
---------
Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
2025-02-25 22:52:59 +01:00
|
|
|
public static void saveKeyToSettings(String key, Object newValue) throws IOException {
|
|
|
|
String[] keyArray = key.split("\\.");
|
2025-01-31 11:00:03 +00:00
|
|
|
Path settingsPath = Paths.get(InstallationPathConfig.getSettingsPath());
|
Improved Configuration and YAML Management (#2966)
# Description of Changes
**What was changed:**
- **Configuration Updates:**
Replaced all calls to `GeneralUtils.saveKeyToConfig` with the new
`GeneralUtils.saveKeyToSettings` method across multiple classes (e.g.,
`LicenseKeyChecker`, `InitialSetup`, `SettingsController`, etc.). This
update ensures consistent management of configuration settings.
- **File Path and Exception Handling:**
Updated file path handling in `SPDFApplication` by creating `Path`
objects from string paths and logging these paths for clarity. Also
refined exception handling by catching more specific exceptions (e.g.,
using `IOException` instead of a generic `Exception`).
- **Analytics Flag and Rate Limiting:**
Changed the analytics flag in the application properties from a `String`
to a `Boolean`, and updated related logic in `AppConfig` and
`PostHogService`. The rate-limiting property retrieval in `AppConfig`
was also refined for clarity.
- **YAML Configuration Management:**
Replaced the previous manual, line-based YAML merging logic in
`ConfigInitializer` with a new `YamlHelper` class. This helper leverages
the SnakeYAML engine to load, update, and save YAML configurations more
robustly while preserving comments and formatting.
**Why the change was made:**
- **Improved Maintainability:**
Consolidating configuration update logic into a single utility method
(`saveKeyToSettings`) reduces code duplication and simplifies future
maintenance.
- **Enhanced Robustness:**
The new `YamlHelper` class ensures that configuration files are merged
accurately and safely, minimizing risks of data loss or format
corruption.
- **Better Type Safety and Exception Handling:**
Switching the analytics flag to a Boolean and refining exception
handling improves code robustness and debugging efficiency.
- **Clarity and Consistency:**
Standardizing file path handling and logging practices enhances code
readability across the project.
**Challenges encountered:**
- **YAML Merging Complexity:**
Integrating the new `YamlHelper` required careful handling to preserve
existing settings, comments, and formatting during merges.
- **Type Conversion and Backward Compatibility:**
Updating the analytics flag from a string to a Boolean required
extensive testing to ensure backward compatibility and proper
functionality.
- **Exception Granularity:**
Refactoring exception handling from a generic to a more specific
approach involved a detailed review to cover all edge cases.
Closes #<issue_number>
---
## Checklist
- [x] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md)
(if applicable)
- [x] I have performed a self-review of my own code
- [x] My changes generate no new warnings
### Documentation
- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)
### UI Changes (if applicable)
- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)
### Testing (if applicable)
- [x] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#6-testing)
for more details.
---------
Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
2025-02-25 22:52:59 +01:00
|
|
|
YamlHelper settingsYaml = new YamlHelper(settingsPath);
|
|
|
|
settingsYaml.updateValue(Arrays.asList(keyArray), newValue);
|
|
|
|
settingsYaml.saveOverride(settingsPath);
|
2024-12-10 20:39:24 +00:00
|
|
|
}
|
2024-10-14 22:34:41 +01:00
|
|
|
|
|
|
|
public static String generateMachineFingerprint() {
|
|
|
|
try {
|
|
|
|
// Get the MAC address
|
|
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
InetAddress ip = InetAddress.getLocalHost();
|
|
|
|
NetworkInterface network = NetworkInterface.getByInetAddress(ip);
|
|
|
|
|
|
|
|
if (network == null) {
|
|
|
|
Enumeration<NetworkInterface> networks = NetworkInterface.getNetworkInterfaces();
|
|
|
|
while (networks.hasMoreElements()) {
|
|
|
|
NetworkInterface net = networks.nextElement();
|
|
|
|
byte[] mac = net.getHardwareAddress();
|
|
|
|
if (mac != null) {
|
|
|
|
for (int i = 0; i < mac.length; i++) {
|
|
|
|
sb.append(String.format("%02X", mac[i]));
|
|
|
|
}
|
|
|
|
break; // Use the first network interface with a MAC address
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
byte[] mac = network.getHardwareAddress();
|
|
|
|
if (mac != null) {
|
|
|
|
for (int i = 0; i < mac.length; i++) {
|
|
|
|
sb.append(String.format("%02X", mac[i]));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Hash the MAC address for privacy and consistency
|
|
|
|
MessageDigest md = MessageDigest.getInstance("SHA-256");
|
|
|
|
byte[] hash = md.digest(sb.toString().getBytes(StandardCharsets.UTF_8));
|
|
|
|
StringBuilder fingerprint = new StringBuilder();
|
|
|
|
for (byte b : hash) {
|
|
|
|
fingerprint.append(String.format("%02x", b));
|
|
|
|
}
|
|
|
|
return fingerprint.toString();
|
|
|
|
} catch (Exception e) {
|
|
|
|
return "GenericID";
|
|
|
|
}
|
|
|
|
}
|
2024-12-10 20:39:24 +00:00
|
|
|
|
2024-12-10 11:17:50 +00:00
|
|
|
public static boolean isVersionHigher(String currentVersion, String compareVersion) {
|
|
|
|
if (currentVersion == null || compareVersion == null) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Split versions into components
|
|
|
|
String[] current = currentVersion.split("\\.");
|
|
|
|
String[] compare = compareVersion.split("\\.");
|
|
|
|
|
|
|
|
// Get the length of the shorter version array
|
|
|
|
int length = Math.min(current.length, compare.length);
|
|
|
|
|
|
|
|
// Compare each component
|
|
|
|
for (int i = 0; i < length; i++) {
|
|
|
|
int currentPart = Integer.parseInt(current[i]);
|
|
|
|
int comparePart = Integer.parseInt(compare[i]);
|
|
|
|
|
|
|
|
if (currentPart > comparePart) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (currentPart < comparePart) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If all components so far are equal, the longer version is considered higher
|
|
|
|
return current.length > compare.length;
|
|
|
|
}
|
2024-01-03 17:59:04 +00:00
|
|
|
}
|