refactor(api): replace regex string literals with Pattern instances for improved performance and readability (#5680)

# Description of Changes

<!--
Please provide a summary of the changes, including:

- What was changed
- Why the change was made
- Any challenges encountered

Closes #(issue_number)
-->

---

## Checklist

### General

- [ ] 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/devGuide/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/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] 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/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### 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)

- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing)
for more details.

---------

Signed-off-by: Balázs Szücs <[email protected]>
This commit is contained in:
Balázs Szücs
2026-02-14 21:01:19 +00:00
committed by GitHub
parent 0a1d2effdc
commit e310493966
17 changed files with 130 additions and 53 deletions
@@ -9,6 +9,7 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.*;
import java.util.regex.Pattern;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
@@ -36,6 +37,7 @@ import stirling.software.common.configuration.RuntimePathConfig;
@RequiredArgsConstructor
public class UIDataTessdataController {
private static final Pattern INVALID_LANG_CHARS_PATTERN = Pattern.compile("[^A-Za-z0-9_+\\-]");
private final RuntimePathConfig runtimePathConfig;
private static volatile List<String> cachedRemoteTessdata = null;
private static volatile long cachedRemoteTessdataExpiry = 0L;
@@ -88,7 +90,7 @@ public class UIDataTessdataController {
failed.add(language);
continue;
}
String safeLang = language.replaceAll("[^A-Za-z0-9_+\\-]", "");
String safeLang = INVALID_LANG_CHARS_PATTERN.matcher(language).replaceAll("");
if (!safeLang.equals(language)) {
failed.add(language);
continue;
@@ -6,6 +6,7 @@ import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.time.Instant;
import java.util.regex.Pattern;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
@@ -33,6 +34,7 @@ public class TotpService {
private static final String HMAC_ALGORITHM = "HmacSHA1";
private static final String DEFAULT_ISSUER = "Stirling PDF";
private static final SecureRandom SECURE_RANDOM = new SecureRandom();
private static final Pattern TOTP_CODE_PATTERN = Pattern.compile("\\d{6}");
private final ApplicationProperties applicationProperties;
@@ -71,7 +73,7 @@ public class TotpService {
}
String normalizedCode = code.replace(" ", "");
if (!normalizedCode.matches("\\d{6}")) {
if (!TOTP_CODE_PATTERN.matcher(normalizedCode).matches()) {
return null;
}
@@ -10,6 +10,7 @@ import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Stream;
import org.springframework.stereotype.Service;
@@ -32,6 +33,7 @@ import stirling.software.proprietary.model.api.signature.SavedSignatureResponse;
@Slf4j
public class SignatureService implements PersonalSignatureServiceInterface {
private static final Pattern FILENAME_VALIDATION_PATTERN = Pattern.compile("^[a-zA-Z0-9_.-]+$");
private final String SIGNATURE_BASE_PATH;
private final String ALL_USERS_FOLDER = "ALL_USERS";
private final ObjectMapper objectMapper = new ObjectMapper();
@@ -366,14 +368,14 @@ public class SignatureService implements PersonalSignatureServiceInterface {
if (fileName.contains("..") || fileName.contains("/") || fileName.contains("\\")) {
throw new IllegalArgumentException("Invalid filename");
}
if (!fileName.matches("^[a-zA-Z0-9_.-]+$")) {
if (!FILENAME_VALIDATION_PATTERN.matcher(fileName).matches()) {
throw new IllegalArgumentException("Filename contains invalid characters");
}
}
private String validateAndNormalizeExtension(String extension) {
String normalized = extension.toLowerCase().trim();
if (normalized.equals("png") || normalized.equals("jpg") || normalized.equals("jpeg")) {
if ("png".equals(normalized) || "jpg".equals(normalized) || "jpeg".equals(normalized)) {
return normalized;
}
throw new IllegalArgumentException("Unsupported image extension: " + extension);