From d2677e64ddb9abb64820bfbb189e176b72a9329b Mon Sep 17 00:00:00 2001
From: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
Date: Mon, 12 Jan 2026 11:18:37 +0000
Subject: [PATCH] OCR fix and Mobile QR changes (#5433)
# Description of Changes
## OCR / Tesseract path handling
Makes tessDataPath resolution deterministic with priority: config >
TESSDATA_PREFIX env > default.
Updates language discovery to use runtimePathConfig.getTessDataPath()
instead of raw config value.
Ensure default OCR dir is debian based not alpine
## Mobile scanner: feature gating + new conversion settings
Adds system.mobileScannerSettings (convert-to-PDF + resolution + page
format + stretch) exposed via backend config and configurable in the
proprietary admin UI.
Enforces enableMobileScanner on the MobileScannerController endpoints
(403 when disabled).
Frontend mobile upload flow can now optionally convert received images
to PDF (pdf-lib + canvas).
## Desktop/Tauri connectivity work
Expands tauri-plugin-http permissions and enables dangerous-settings.
Adds a very comprehensive multi-stage server connection diagnostic
routine (with lots of logging).
---
## 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.
---
.../configuration/RuntimePathConfig.java | 19 +-
.../common/model/ApplicationProperties.java | 9 +
.../SPDF/controller/api/UIDataController.java | 2 +-
.../controller/api/misc/ConfigController.java | 17 +-
.../api/misc/MobileScannerController.java | 60 +-
.../src/main/resources/settings.yml.template | 5 +
build.gradle | 2 +-
docker/unified/entrypoint.sh | 24 +-
.../public/locales/en-GB/translation.toml | 42 +-
frontend/src-tauri/Cargo.toml | 2 +-
frontend/src-tauri/capabilities/default.json | 22 +-
.../fileManager/FileSourceButtons.tsx | 9 +-
.../components/shared/MobileUploadModal.tsx | 44 +-
.../src/core/contexts/AppConfigContext.tsx | 4 +
frontend/src/core/utils/imageToPdfUtils.ts | 297 +++++++
.../SetupWizard/ServerSelection.tsx | 6 +-
.../desktop/services/connectionModeService.ts | 825 ++++++++++++++++--
.../AdminConnectionsSection.tsx | 167 +++-
.../proprietary/routes/authShared/auth.css | 17 +
scripts/init.sh | 38 +-
20 files changed, 1478 insertions(+), 133 deletions(-)
create mode 100644 frontend/src/core/utils/imageToPdfUtils.ts
diff --git a/app/common/src/main/java/stirling/software/common/configuration/RuntimePathConfig.java b/app/common/src/main/java/stirling/software/common/configuration/RuntimePathConfig.java
index 7e6da0f0f..fef6af3ed 100644
--- a/app/common/src/main/java/stirling/software/common/configuration/RuntimePathConfig.java
+++ b/app/common/src/main/java/stirling/software/common/configuration/RuntimePathConfig.java
@@ -94,16 +94,19 @@ public class RuntimePathConfig {
defaultSOfficePath, operations != null ? operations.getSoffice() : null);
// Initialize Tesseract data path
- String defaultTessDataPath =
- isDocker ? "/usr/share/tesseract-ocr/5/tessdata" : "/usr/share/tessdata";
-
+ // Priority: config setting > TESSDATA_PREFIX env var > default path
String tessPath = system.getTessdataDir();
- String tessdataDir = java.lang.System.getenv("TESSDATA_PREFIX");
+ String tessdataPrefix = java.lang.System.getenv("TESSDATA_PREFIX");
+ String defaultPath = "/usr/share/tesseract-ocr/5/tessdata";
+
+ if (tessPath != null && !tessPath.isEmpty()) {
+ this.tessDataPath = tessPath;
+ } else if (tessdataPrefix != null && !tessdataPrefix.isEmpty()) {
+ this.tessDataPath = tessdataPrefix;
+ } else {
+ this.tessDataPath = defaultPath;
+ }
- this.tessDataPath =
- resolvePath(
- defaultTessDataPath,
- (tessPath != null && !tessPath.isEmpty()) ? tessPath : tessdataDir);
log.info("Using Tesseract data path: {}", this.tessDataPath);
}
diff --git a/app/common/src/main/java/stirling/software/common/model/ApplicationProperties.java b/app/common/src/main/java/stirling/software/common/model/ApplicationProperties.java
index a0c3bae91..58c120329 100644
--- a/app/common/src/main/java/stirling/software/common/model/ApplicationProperties.java
+++ b/app/common/src/main/java/stirling/software/common/model/ApplicationProperties.java
@@ -418,6 +418,15 @@ public class ApplicationProperties {
// 'https://app.example.com'). If not set, falls back to backendUrl.
private boolean enableMobileScanner = false; // Enable mobile phone QR code upload feature
+ private MobileScannerSettings mobileScannerSettings = new MobileScannerSettings();
+
+ @Data
+ public static class MobileScannerSettings {
+ private boolean convertToPdf = true; // Whether to automatically convert images to PDF
+ private String imageResolution = "full"; // Options: "full", "reduced"
+ private String pageFormat = "A4"; // Options: "keep", "A4", "letter"
+ private boolean stretchToFit = false; // Whether to stretch image to fill page
+ }
public boolean isAnalyticsEnabled() {
return this.getEnableAnalytics() != null && this.getEnableAnalytics();
diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/UIDataController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/UIDataController.java
index 6285636ef..c60965f72 100644
--- a/app/core/src/main/java/stirling/software/SPDF/controller/api/UIDataController.java
+++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/UIDataController.java
@@ -191,7 +191,7 @@ public class UIDataController {
}
private List getAvailableTesseractLanguages() {
- String tessdataDir = applicationProperties.getSystem().getTessdataDir();
+ String tessdataDir = runtimePathConfig.getTessDataPath();
java.io.File[] files = new java.io.File(tessdataDir).listFiles();
if (files == null) {
return Collections.emptyList();
diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ConfigController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ConfigController.java
index 626703ace..fc73d778e 100644
--- a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ConfigController.java
+++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ConfigController.java
@@ -75,10 +75,25 @@ public class ConfigController {
String frontendUrl = applicationProperties.getSystem().getFrontendUrl();
configData.put("frontendUrl", frontendUrl != null ? frontendUrl : "");
- // Add mobile scanner setting
+ // Add mobile scanner settings
configData.put(
"enableMobileScanner",
applicationProperties.getSystem().isEnableMobileScanner());
+ configData.put(
+ "mobileScannerConvertToPdf",
+ applicationProperties.getSystem().getMobileScannerSettings().isConvertToPdf());
+ configData.put(
+ "mobileScannerImageResolution",
+ applicationProperties
+ .getSystem()
+ .getMobileScannerSettings()
+ .getImageResolution());
+ configData.put(
+ "mobileScannerPageFormat",
+ applicationProperties.getSystem().getMobileScannerSettings().getPageFormat());
+ configData.put(
+ "mobileScannerStretchToFit",
+ applicationProperties.getSystem().getMobileScannerSettings().isStretchToFit());
// Extract values from ApplicationProperties
configData.put("appNameNavbar", applicationProperties.getUi().getAppNameNavbar());
diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/MobileScannerController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/MobileScannerController.java
index a5e3ba7f4..c04911ee5 100644
--- a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/MobileScannerController.java
+++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/MobileScannerController.java
@@ -31,6 +31,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
+import stirling.software.common.model.ApplicationProperties;
import stirling.software.common.service.MobileScannerService;
import stirling.software.common.service.MobileScannerService.FileMetadata;
@@ -51,9 +52,31 @@ import stirling.software.common.service.MobileScannerService.FileMetadata;
public class MobileScannerController {
private final MobileScannerService mobileScannerService;
+ private final ApplicationProperties applicationProperties;
- public MobileScannerController(MobileScannerService mobileScannerService) {
+ public MobileScannerController(
+ MobileScannerService mobileScannerService,
+ ApplicationProperties applicationProperties) {
this.mobileScannerService = mobileScannerService;
+ this.applicationProperties = applicationProperties;
+ }
+
+ /**
+ * Check if mobile scanner feature is enabled
+ *
+ * @return Error response if disabled, null if enabled
+ */
+ private ResponseEntity