Compare commits

...

19 Commits

Author SHA1 Message Date
Dario Ghunney Ware
9c7631f9f2 wip - fixing jar file 2025-05-20 12:35:36 +01:00
Dario Ghunney Ware
28f8f69bea updating paths (DOCKER_SECURITY_ENABLE > ADDITIONAL_FEATURES) 2025-05-19 11:06:06 +01:00
Dario Ghunney Ware
a328ea9d25 multi module build running 2025-05-19 09:50:39 +01:00
Dario Ghunney Ware
ea04596e35 wip - adding missing files 2025-05-19 09:16:28 +01:00
Dario Ghunney Ware
798f4570d5 wip - fixing static resource loading issue. only / missing 2025-05-19 09:16:06 +01:00
Dario Ghunney Ware
0bd4a62e56 wip - fixing fe bug 2025-05-19 09:15:54 +01:00
Dario Ghunney Ware
89760687d2 wip - fixing fe bug 2025-05-19 09:15:54 +01:00
Dario Ghunney Ware
3ea5c4775f wip - fixing fe bug 2025-05-19 09:15:54 +01:00
Dario Ghunney Ware
0145175355 wip - fixing compilation issues 2025-05-19 09:15:54 +01:00
Dario Ghunney Ware
bd39c34468 wip: moved stirling-pdf to submodule 2025-05-19 09:15:51 +01:00
Dario Ghunney Ware
6c3b450d71 renamed module: enterprise > proprietary 2025-05-19 09:15:29 +01:00
Dario Ghunney Ware
5fab82fbcc running with security on/off 2025-05-19 09:15:29 +01:00
Dario Ghunney Ware
19e5ac569a wip - compiling and tests fixed 2025-05-19 09:15:29 +01:00
Dario Ghunney Ware
f9cc7833b4 wip - compiling and tests fixed 2025-05-19 09:15:20 +01:00
Dario Ghunney Ware
8b28c543c4 cleanup 2025-05-19 09:14:33 +01:00
Dario Ghunney Ware
cecdbb9e23 renaming module 2025-05-19 09:14:33 +01:00
Dario Ghunney Ware
63ae3a4596 adding more config to common module 2025-05-19 09:14:33 +01:00
Dario Ghunney Ware
063d7b56fa adding new common module 2025-05-19 09:14:33 +01:00
Dario Ghunney Ware
ba6cc0eed6 wip - making db and sessions conditional 2025-05-19 09:13:20 +01:00
1644 changed files with 153191 additions and 110442 deletions

View File

@ -102,8 +102,8 @@
"java.eclipse.downloadSources": true,
"java.import.gradle.wrapper.enabled": true,
"spring.initializr.defaultLanguage": "Java",
"spring.initializr.defaultGroupId": "stirling.software.SPDF",
"spring.initializr.defaultArtifactId": "SPDF"
"spring.initializr.defaultGroupId": "stirling.software.spdf",
"spring.initializr.defaultArtifactId": "spdf"
},
"extensions": [
"elagil.pre-commit-helper", // Support for pre-commit hooks to enforce code quality

14
.gitattributes vendored
View File

@ -1,10 +1,10 @@
* text=auto eol=lf
# Ignore all JavaScript files in a directory
src/main/resources/static/pdfjs/* linguist-vendored
src/main/resources/static/pdfjs/** linguist-vendored
src/main/resources/static/pdfjs-legacy/* linguist-vendored
src/main/resources/static/pdfjs-legacy/** linguist-vendored
src/main/resources/static/css/bootstrap-icons.css linguist-vendored
src/main/resources/static/css/bootstrap.min.css linguist-vendored
src/main/resources/static/css/fonts/* linguist-vendored
stirling-pdf/src/main/resources/static/pdfjs/* linguist-vendored
stirling-pdf/src/main/resources/static/pdfjs/** linguist-vendored
stirling-pdf/src/main/resources/static/pdfjs-legacy/* linguist-vendored
stirling-pdf/src/main/resources/static/pdfjs-legacy/** linguist-vendored
stirling-pdf/src/main/resources/static/css/bootstrap-icons.css linguist-vendored
stirling-pdf/src/main/resources/static/css/bootstrap.min.css linguist-vendored
stirling-pdf/src/main/resources/static/css/fonts/* linguist-vendored

View File

@ -1,60 +1,45 @@
Translation:
- changed-files:
- any-glob-to-any-file: 'src/main/resources/messages_*_*.properties'
- any-glob-to-any-file: 'stirling-pdf/src/main/resources/messages_*_*.properties'
- any-glob-to-any-file: 'scripts/ignore_translation.toml'
- any-glob-to-any-file: 'src/main/resources/templates/fragments/languages.html'
- any-glob-to-any-file: 'stirling-pdf/src/main/resources/templates/fragments/languages.html'
Front End:
- changed-files:
- any-glob-to-any-file: 'src/main/resources/templates/**/*'
- any-glob-to-any-file: 'src/main/resources/static/**/*'
- any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/controller/web/**'
- any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/UI/**/*'
- any-glob-to-any-file: 'stirling-pdf/src/main/resources/templates/**/*'
- any-glob-to-any-file: 'stirling-pdf/src/main/resources/static/**/*'
- any-glob-to-any-file: 'stirling-pdf/src/main/java/stirling/software/spdf/controller/web/**'
- any-glob-to-any-file: 'stirling-pdf/src/main/java/stirling/software/spdf/UI/**/*'
Java:
- changed-files:
- any-glob-to-any-file: 'src/main/java/**/*.java'
- any-glob-to-any-file: 'common/src/main/java/**/*.java'
- any-glob-to-any-file: 'proprietary/src/main/java/**/*.java'
- any-glob-to-any-file: 'stirling-pdf/src/main/java/**/*.java'
Back End:
- changed-files:
- any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/config/**/*'
- any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/controller/**/*'
- any-glob-to-any-file: 'src/main/resources/settings.yml.template'
- any-glob-to-any-file: 'src/main/resources/application.properties'
- any-glob-to-any-file: 'src/main/resources/banner.txt'
- any-glob-to-any-file: 'stirling-pdf/src/main/java/stirling/software/spdf/config/**/*'
- any-glob-to-any-file: 'stirling-pdf/src/main/java/stirling/software/spdf/controller/**/*'
- any-glob-to-any-file: 'stirling-pdf/src/main/resources/settings.yml.template'
- any-glob-to-any-file: 'stirling-pdf/src/main/resources/application.properties'
- any-glob-to-any-file: 'stirling-pdf/src/main/resources/banner.txt'
- any-glob-to-any-file: 'scripts/png_to_webp.py'
- any-glob-to-any-file: 'split_photos.py'
Security:
- changed-files:
- any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/config/interfaces/DatabaseInterface.java'
- any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/config/security/**/*'
- any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/controller/api/DatabaseController.java'
- any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/controller/api/EmailController.java'
- any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/controller/api/H2SQLController.java'
- any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/controller/web/AccountWebController.java'
- any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/controller/web/DatabaseWebController.java'
- any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/controller/api/UserController.java'
- any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/model/api/Email.java'
- any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/model/exception/BackupNotFoundException.java'
- any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/model/exception/NoProviderFoundExceptionjava'
- any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/model/provider/**/*'
- any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/model/AuthenticationType.java'
- any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/model/ApiKeyAuthenticationToken.java'
- any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/model/AttemptCounter.java'
- any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/model/Authority.java'
- any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/model/PersistentLogin.java'
- any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/model/SessionEntity.java'
- any-glob-to-any-file: 'proprietary/src/main/java/stirling/software/proprietary/security/**/*'
- any-glob-to-any-file: 'scripts/download-security-jar.sh'
- any-glob-to-any-file: '.github/workflows/dependency-review.yml'
- any-glob-to-any-file: '.github/workflows/scorecards.yml'
API:
- changed-files:
- any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/config/OpenApiConfig.java'
- any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/controller/web/MetricsController.java'
- any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/controller/api/**/*'
- any-glob-to-any-file: 'src/main/java/stirling/software/SPDF/model/api/**/*'
- any-glob-to-any-file: 'stirling-pdf/src/main/java/stirling/software/spdf/config/OpenApiConfig.java'
- any-glob-to-any-file: 'stirling-pdf/src/main/java/stirling/software/spdf/controller/web/MetricsController.java'
- any-glob-to-any-file: 'stirling-pdf/src/main/java/stirling/software/spdf/controller/api/**/*'
- any-glob-to-any-file: 'stirling-pdf/src/main/java/stirling/software/spdf/model/api/**/*'
- any-glob-to-any-file: 'scripts/png_to_webp.py'
- any-glob-to-any-file: 'split_photos.py'
- any-glob-to-any-file: '.github/workflows/swagger.yml'
@ -88,7 +73,9 @@ Devtools:
Test:
- changed-files:
- any-glob-to-any-file: 'cucumber/**/*'
- any-glob-to-any-file: 'src/test/**/*'
- any-glob-to-any-file: 'common/src/test/**/*'
- any-glob-to-any-file: 'proprietary/src/test/**/*'
- any-glob-to-any-file: 'stirling-pdf/src/test/**/*'
- any-glob-to-any-file: 'src/testing/**/*'
- any-glob-to-any-file: '.pre-commit-config'
- any-glob-to-any-file: '.github/workflows/pre_commit.yml'

View File

@ -317,7 +317,7 @@ def check_for_differences(reference_file, file_list, branch, actor):
report.append("## ❌ Overall Check Status: **_Failed_**")
report.append("")
report.append(
f"@{actor} please check your translation if it conforms to the standard. Follow the format of [messages_en_GB.properties](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/src/main/resources/messages_en_GB.properties)"
f"@{actor} please check your translation if it conforms to the standard. Follow the format of [messages_en_GB.properties](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/stirling-pdf/src/main/resources/messages_en_GB.properties)"
)
else:
report.append("## ✅ Overall Check Status: **_Success_**")

View File

@ -84,7 +84,7 @@ jobs:
core.setOutput('repository', repository);
core.setOutput('ref', pr.head.ref);
- name: Check for security/login flag
id: check-security-flag
env:
@ -156,9 +156,9 @@ jobs:
- name: Run Gradle Command
run: |
if [ "${{ needs.check-comment.outputs.enable_security }}" == "true" ]; then
export DOCKER_ENABLE_SECURITY=true
export ADDITIONAL_FEATURES=true
else
export DOCKER_ENABLE_SECURITY=false
export ADDITIONAL_FEATURES=false
fi
./gradlew clean build
env:
@ -200,11 +200,11 @@ jobs:
run: |
# Set security settings based on flags
if [ "${{ needs.check-comment.outputs.enable_security }}" == "true" ]; then
DOCKER_SECURITY="true"
ADDITIONAL_FEATURES="true"
LOGIN_SECURITY="true"
SECURITY_STATUS="🔒 Security Enabled"
else
DOCKER_SECURITY="false"
ADDITIONAL_FEATURES="false"
LOGIN_SECURITY="false"
SECURITY_STATUS="Security Disabled"
fi
@ -223,7 +223,7 @@ jobs:
- /stirling/PR-${{ needs.check-comment.outputs.pr_number }}/config:/configs:rw
- /stirling/PR-${{ needs.check-comment.outputs.pr_number }}/logs:/logs:rw
environment:
DOCKER_ENABLE_SECURITY: "${DOCKER_SECURITY}"
ADDITIONAL_FEATURES: "${ADDITIONAL_FEATURES}"
SECURITY_ENABLELOGIN: "${LOGIN_SECURITY}"
SYSTEM_DEFAULTLOCALE: en-GB
UI_APPNAME: "Stirling-PDF PR#${{ needs.check-comment.outputs.pr_number }}"
@ -250,7 +250,7 @@ jobs:
docker-compose pull
docker-compose up -d
ENDSSH
# Set output for use in PR comment
echo "security_status=${SECURITY_STATUS}" >> $GITHUB_ENV

View File

@ -40,12 +40,12 @@ jobs:
- name: Build with Gradle and no spring security
run: ./gradlew clean build
env:
DOCKER_ENABLE_SECURITY: false
ADDITIONAL_FEATURES: false
- name: Build with Gradle and with spring security
run: ./gradlew clean build
env:
DOCKER_ENABLE_SECURITY: true
ADDITIONAL_FEATURES: true
- name: Upload Test Reports
if: always()

View File

@ -4,7 +4,7 @@ on:
pull_request_target:
types: [opened, synchronize, reopened]
paths:
- "src/main/resources/messages_*.properties"
- "stirling-pdf/src/main/resources/messages_*.properties"
permissions:
contents: read # Allow read access to repository content
@ -58,7 +58,7 @@ jobs:
run: |
echo "Fetching PR changed files..."
echo "Getting list of changed files from PR..."
gh pr view ${{ steps.get-pr-data.outputs.pr_number }} --json files -q ".files[].path" | grep -E '^src/main/resources/messages_[a-zA-Z_]{2}_[a-zA-Z_]{2,7}\.properties$' > changed_files.txt # Filter only matching property files
gh pr view ${{ steps.get-pr-data.outputs.pr_number }} --json files -q ".files[].path" | grep -E '^stirling-pdf/src/main/resources/messages_[a-zA-Z_]{2}_[a-zA-Z_]{2,7}\.properties$' > changed_files.txt # Filter only matching property files
- name: Determine reference file test
id: determine-file
@ -137,12 +137,12 @@ jobs:
// Determine reference file
let referenceFilePath;
if (changedFiles.includes("src/main/resources/messages_en_GB.properties")) {
if (changedFiles.includes("stirling-pdf/src/main/resources/messages_en_GB.properties")) {
console.log("Using PR branch reference file.");
const { data: fileContent } = await github.rest.repos.getContent({
owner: prRepoOwner,
repo: prRepoName,
path: "src/main/resources/messages_en_GB.properties",
path: "stirling-pdf/src/main/resources/messages_en_GB.properties",
ref: branch,
});
@ -154,7 +154,7 @@ jobs:
const { data: fileContent } = await github.rest.repos.getContent({
owner: repoOwner,
repo: repoName,
path: "src/main/resources/messages_en_GB.properties",
path: "stirling-pdf/src/main/resources/messages_en_GB.properties",
ref: "main",
});

View File

@ -54,7 +54,7 @@ jobs:
- name: Move and Rename License File
run: |
mv build/reports/dependency-license/index.json src/main/resources/static/3rdPartyLicenses.json
mv build/reports/dependency-license/index.json stirling-pdf/src/main/resources/static/3rdPartyLicenses.json
- name: Set up git config
run: |
@ -63,7 +63,7 @@ jobs:
- name: Run git add
run: |
git add src/main/resources/static/3rdPartyLicenses.json
git add stirling-pdf/src/main/resources/static/3rdPartyLicenses.json
git diff --staged --quiet || echo "CHANGES_DETECTED=true" >> $GITHUB_ENV
- name: Create Pull Request

View File

@ -75,7 +75,7 @@ jobs:
- name: Generate jar (With Security=${{ matrix.enable_security }})
run: ./gradlew clean createExe
env:
DOCKER_ENABLE_SECURITY: ${{ matrix.enable_security }}
ADDITIONAL_FEATURES: ${{ matrix.enable_security }}
STIRLING_PDF_DESKTOP_UI: false
- name: Rename binaries
@ -171,7 +171,7 @@ jobs:
- name: Build Installer
run: ./gradlew build jpackage -x test --info
env:
DOCKER_ENABLE_SECURITY: false
ADDITIONAL_FEATURES: false
STIRLING_PDF_DESKTOP_UI: true
BROWSER_OPEN: true

View File

@ -37,7 +37,7 @@ jobs:
- name: Run Gradle Command
run: ./gradlew clean build
env:
DOCKER_ENABLE_SECURITY: false
ADDITIONAL_FEATURES: false
STIRLING_PDF_DESKTOP_UI: false
- name: Install cosign

View File

@ -42,7 +42,7 @@ jobs:
- name: Generate jar (With Security=${{ matrix.enable_security }})
run: ./gradlew clean createExe
env:
DOCKER_ENABLE_SECURITY: ${{ matrix.enable_security }}
ADDITIONAL_FEATURES: ${{ matrix.enable_security }}
STIRLING_PDF_DESKTOP_UI: false
- name: Get version number

View File

@ -33,7 +33,7 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
DOCKER_ENABLE_SECURITY: true
ADDITIONAL_FEATURES: true
STIRLING_PDF_DESKTOP_UI: true
run: |
./gradlew clean build sonar \

View File

@ -8,8 +8,8 @@ on:
paths:
- "build.gradle"
- "README.md"
- "src/main/resources/messages_*.properties"
- "src/main/resources/static/3rdPartyLicenses.json"
- "stirling-pdf/src/main/resources/messages_*.properties"
- "stirling-pdf/src/main/resources/static/3rdPartyLicenses.json"
- "scripts/ignore_translation.toml"
permissions:
@ -78,7 +78,7 @@ jobs:
- name: Sync translation property files
run: |
python .github/scripts/check_language_properties.py --reference-file "src/main/resources/messages_en_GB.properties" --branch main
python .github/scripts/check_language_properties.py --reference-file "stirling-pdf/src/main/resources/messages_en_GB.properties" --branch main
- name: Set up git config
run: |
@ -87,7 +87,7 @@ jobs:
- name: Run git add
run: |
git add src/main/resources/messages_*.properties
git add stirling-pdf/src/main/resources/messages_*.properties
git diff --staged --quiet || git commit -m ":memo: Sync translation files" || echo "no changes"
- name: Install dependencies
@ -142,4 +142,4 @@ jobs:
sign-commits: true
add-paths: |
README.md
src/main/resources/messages_*.properties
stirling-pdf/src/main/resources/messages_*.properties

View File

@ -28,7 +28,7 @@ jobs:
- name: Build with Gradle
run: ./gradlew clean build
env:
DOCKER_ENABLE_SECURITY: false
ADDITIONAL_FEATURES: false
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0
@ -76,7 +76,7 @@ jobs:
- /stirling/test-${{ github.sha }}/config:/configs:rw
- /stirling/test-${{ github.sha }}/logs:/logs:rw
environment:
DOCKER_ENABLE_SECURITY: "false"
ADDITIONAL_FEATURES: "false"
SECURITY_ENABLELOGIN: "false"
SYSTEM_DEFAULTLOCALE: en-GB
UI_APPNAME: "Stirling-PDF Test"

View File

@ -20,7 +20,7 @@ repos:
- --skip="./.*,*.csv,*.json,*.ambr"
- --quiet-level=2
files: \.(html|css|js|py|md)$
exclude: (.vscode|.devcontainer|src/main/resources|Dockerfile|.*/pdfjs.*|.*/thirdParty.*|bootstrap.*|.*\.min\..*|.*diff\.js)
exclude: (.vscode|.devcontainer|stirling-pdf/src/main/resources|Dockerfile|.*/pdfjs.*|.*/thirdParty.*|bootstrap.*|.*\.min\..*|.*diff\.js)
- repo: https://github.com/gitleaks/gitleaks
rev: v8.24.3
hooks:

View File

@ -78,6 +78,6 @@
// Enables import of the Gradle wrapper.
"java.import.gradle.wrapper.enabled": true,
"spring.initializr.defaultLanguage": "Java",
"spring.initializr.defaultGroupId": "stirling.software.SPDF",
"spring.initializr.defaultArtifactId": "SPDF",
"spring.initializr.defaultGroupId": "stirling.software.spdf",
"spring.initializr.defaultArtifactId": "spdf",
}

View File

@ -55,7 +55,7 @@ Stirling-PDF uses Lombok to reduce boilerplate code. Some IDEs, like Eclipse, do
Visit the [Lombok website](https://projectlombok.org/setup/) for installation instructions specific to your IDE.
5. Add environment variable
For local testing, you should generally be testing the full 'Security' version of Stirling-PDF. To do this, you must add the environment flag DOCKER_ENABLE_SECURITY=true to your system and/or IDE build/run step.
For local testing, you should generally be testing the full 'Security' version of Stirling-PDF. To do this, you must add the environment flag ADDITIONAL_FEATURES=true to your system and/or IDE build/run step.
## 4. Project Structure
@ -76,7 +76,7 @@ Stirling-PDF/
│ │ ├── java/
│ │ │ └── stirling/
│ │ │ └── software/
│ │ │ └── SPDF/
│ │ │ └── spdf/
│ │ │ ├── config/
│ │ │ ├── controller/
│ │ │ ├── model/
@ -93,7 +93,7 @@ Stirling-PDF/
│ └── java/
│ └── stirling/
│ └── software/
│ └── SPDF/
│ └── spdf/
├── build.gradle # Gradle build configuration
├── Dockerfile # Main Dockerfile
├── Dockerfile.ultra-lite # Dockerfile for ultra-lite version
@ -141,7 +141,7 @@ services:
- /stirling/latest/config:/configs:rw
- /stirling/latest/logs:/logs:rw
environment:
DOCKER_ENABLE_SECURITY: "true"
ADDITIONAL_FEATURES: "true"
SECURITY_ENABLELOGIN: "true"
PUID: 1002
PGID: 1002
@ -170,7 +170,7 @@ Stirling-PDF uses different Docker images for various configurations. The build
1. Set the security environment variable:
```bash
export DOCKER_ENABLE_SECURITY=false # or true for security-enabled builds
export ADDITIONAL_FEATURES=false # or true for security-enabled builds
```
2. Build the project with Gradle:
@ -196,7 +196,7 @@ Stirling-PDF uses different Docker images for various configurations. The build
For the fat version (with security enabled):
```bash
export DOCKER_ENABLE_SECURITY=true
export ADDITIONAL_FEATURES=true
docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t stirlingtools/stirling-pdf:latest-fat -f ./Dockerfile.fat .
```
@ -332,7 +332,7 @@ Thymeleaf is a server-side Java HTML template engine. It is used in Stirling-PDF
### Thymeleaf overview
In Stirling-PDF, Thymeleaf is used to create HTML templates that are rendered on the server side. These templates are located in the `src/main/resources/templates` directory. Thymeleaf templates use a combination of HTML and special Thymeleaf attributes to dynamically generate content.
In Stirling-PDF, Thymeleaf is used to create HTML templates that are rendered on the server side. These templates are located in the `stirling-pdf/src/main/resources/templates` directory. Thymeleaf templates use a combination of HTML and special Thymeleaf attributes to dynamically generate content.
Some examples of this are:
@ -384,12 +384,12 @@ This would generate n entries of tr for each person in exampleData
### Adding a New Feature to the Backend (API)
1. **Create a New Controller:**
- Create a new Java class in the `src/main/java/stirling/software/SPDF/controller/api` directory.
- Create a new Java class in the `stirling-pdf/src/main/java/stirling/software/spdf/controller/api` directory.
- Annotate the class with `@RestController` and `@RequestMapping` to define the API endpoint.
- Ensure to add API documentation annotations like `@Tag(name = "General", description = "General APIs")` and `@Operation(summary = "Crops a PDF document", description = "This operation takes an input PDF file and crops it according to the given coordinates. Input:PDF Output:PDF Type:SISO")`.
```java
package stirling.software.SPDF.controller.api;
package stirling.software.spdf.controller.api;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@ -411,11 +411,11 @@ This would generate n entries of tr for each person in exampleData
```
2. **Define the Service Layer:** (Not required but often useful)
- Create a new service class in the `src/main/java/stirling/software/SPDF/service` directory.
- Create a new service class in the `stirling-pdf/src/main/java/stirling/software/spdf/service` directory.
- Implement the business logic for the new feature.
```java
package stirling.software.SPDF.service;
package stirling.software.spdf.service;
import org.springframework.stereotype.Service;
@ -434,13 +434,13 @@ This would generate n entries of tr for each person in exampleData
- Autowire the service class in the controller and use it to handle the API request.
```java
package stirling.software.SPDF.controller.api;
package stirling.software.spdf.controller.api;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import stirling.software.SPDF.service.NewFeatureService;
import stirling.software.spdf.service.NewFeatureService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@ -463,7 +463,7 @@ This would generate n entries of tr for each person in exampleData
### Adding a New Feature to the Frontend (UI)
1. **Create a New Thymeleaf Template:**
- Create a new HTML file in the `src/main/resources/templates` directory.
- Create a new HTML file in the `stirling-pdf/src/main/resources/templates` directory.
- Use Thymeleaf attributes to dynamically generate content.
- Use `extract-page.html` as a base example for the HTML template, which is useful to ensure importing of the general layout, navbar, and footer.
@ -507,18 +507,18 @@ This would generate n entries of tr for each person in exampleData
```
2. **Create a New Controller for the UI:**
- Create a new Java class in the `src/main/java/stirling/software/SPDF/controller/ui` directory.
- Create a new Java class in the `stirling-pdf/src/main/java/stirling/software/spdf/controller/ui` directory.
- Annotate the class with `@Controller` and `@RequestMapping` to define the UI endpoint.
```java
package stirling.software.SPDF.controller.ui;
package stirling.software.spdf.controller.ui;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import stirling.software.SPDF.service.NewFeatureService;
import stirling.software.spdf.service.NewFeatureService;
@Controller
@RequestMapping("/new-feature")
@ -537,7 +537,7 @@ This would generate n entries of tr for each person in exampleData
3. **Update the Navigation Bar:**
- Add a link to the new feature page in the navigation bar.
- Update the `src/main/resources/templates/fragments/navbar.html` file.
- Update the `stirling-pdf/src/main/resources/templates/fragments/navbar.html` file.
```html
<li class="nav-item">
@ -551,7 +551,7 @@ When adding a new feature or modifying existing ones in Stirling-PDF, you'll nee
### 1. Locate Existing Language Files
Find the existing `messages.properties` files in the `src/main/resources` directory. You'll see files like:
Find the existing `messages.properties` files in the `stirling-pdf/src/main/resources` directory. You'll see files like:
- `messages.properties` (default, usually English)
- `messages_en_GB.properties`

View File

@ -4,7 +4,7 @@ FROM alpine:3.21.3@sha256:a8560b36e8b8210634f77d9f7f9efd7ffa463e380b75e2e74aff45
# Copy necessary files
COPY scripts /scripts
COPY pipeline /pipeline
COPY src/main/resources/static/fonts/*.ttf /usr/share/fonts/opentype/noto/
COPY stirling-pdf/src/main/resources/static/fonts/*.ttf /usr/share/fonts/opentype/noto/
#COPY src/main/resources/static/fonts/*.otf /usr/share/fonts/opentype/noto/
COPY build/libs/*.jar app.jar
@ -23,7 +23,7 @@ LABEL org.opencontainers.image.version="${VERSION_TAG}"
LABEL org.opencontainers.image.keywords="PDF, manipulation, merge, split, convert, OCR, watermark"
# Set Environment Variables
ENV DOCKER_ENABLE_SECURITY=false \
ENV ADDITIONAL_FEATURES=false \
VERSION_TAG=$VERSION_TAG \
JAVA_BASE_OPTS="-XX:+UnlockExperimentalVMOptions -XX:MaxRAMPercentage=75 -XX:InitiatingHeapOccupancyPercent=20 -XX:+G1PeriodicGCInvokesConcurrent -XX:G1PeriodicGCInterval=10000 -XX:+UseStringDeduplication -XX:G1PeriodicGCSystemLoadThreshold=70" \
JAVA_CUSTOM_OPTS="" \

View File

@ -13,8 +13,8 @@ WORKDIR /app
# Copy the entire project to the working directory
COPY . .
# Build the application with DOCKER_ENABLE_SECURITY=false
RUN DOCKER_ENABLE_SECURITY=true \
# Build the application with ADDITIONAL_FEATURES=false
RUN ADDITIONAL_FEATURES=true \
STIRLING_PDF_DESKTOP_UI=false \
./gradlew clean build -x spotlessApply -x spotlessCheck -x test -x sonarqube
@ -24,13 +24,13 @@ FROM alpine:3.21.3@sha256:a8560b36e8b8210634f77d9f7f9efd7ffa463e380b75e2e74aff45
# Copy necessary files
COPY scripts /scripts
COPY pipeline /pipeline
COPY src/main/resources/static/fonts/*.ttf /usr/share/fonts/opentype/noto/
COPY stirling-pdf/src/main/resources/static/fonts/*.ttf /usr/share/fonts/opentype/noto/
COPY --from=build /app/build/libs/*.jar app.jar
ARG VERSION_TAG
# Set Environment Variables
ENV DOCKER_ENABLE_SECURITY=false \
ENV ADDITIONAL_FEATURES=false \
VERSION_TAG=$VERSION_TAG \
JAVA_BASE_OPTS="-XX:+UnlockExperimentalVMOptions -XX:MaxRAMPercentage=75 -XX:InitiatingHeapOccupancyPercent=20 -XX:+G1PeriodicGCInvokesConcurrent -XX:G1PeriodicGCInterval=10000 -XX:+UseStringDeduplication -XX:G1PeriodicGCSystemLoadThreshold=70" \
JAVA_CUSTOM_OPTS="" \

View File

@ -4,7 +4,7 @@ FROM alpine:3.21.3@sha256:a8560b36e8b8210634f77d9f7f9efd7ffa463e380b75e2e74aff45
ARG VERSION_TAG
# Set Environment Variables
ENV DOCKER_ENABLE_SECURITY=false \
ENV ADDITIONAL_FEATURES=false \
HOME=/home/stirlingpdfuser \
VERSION_TAG=$VERSION_TAG \
JAVA_BASE_OPTS="-XX:+UnlockExperimentalVMOptions -XX:MaxRAMPercentage=75 -XX:InitiatingHeapOccupancyPercent=20 -XX:+G1PeriodicGCInvokesConcurrent -XX:G1PeriodicGCInterval=10000 -XX:+UseStringDeduplication -XX:G1PeriodicGCSystemLoadThreshold=70" \

View File

@ -10,7 +10,7 @@ Fork Stirling-PDF and create a new branch out of `main`.
Then add a reference to the language in the navbar by adding a new language entry to the dropdown:
- Edit the file: [languages.html](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/src/main/resources/templates/fragments/languages.html)
- Edit the file: [languages.html](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/stirling-pdf/src/main/resources/templates/fragments/languages.html)
For example, to add Polish, you would add:
@ -25,7 +25,7 @@ The `data-bs-language-code` is the code used to reference the file in the next s
Start by copying the existing English property file:
- [messages_en_GB.properties](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/src/main/resources/messages_en_GB.properties)
- [messages_en_GB.properties](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/stirling-pdf/src/main/resources/messages_en_GB.properties)
Copy and rename it to `messages_{your data-bs-language-code here}.properties`. In the Polish example, you would set the name to `messages_pl_PL.properties`.

View File

@ -2,6 +2,11 @@ MIT License
Copyright (c) 2024 Stirling Tools
Portions of this software are licensed as follows:
* All content that resides under the "proprietary/" directory of this repository, if that directory exists, is licensed under the license defined in "proprietary/LICENSE".
* Content outside of the above mentioned directories or restrictions above is available under the MIT License as defined below.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights

View File

@ -8,8 +8,9 @@ plugins {
id "com.diffplug.spotless" version "7.0.3"
id "com.github.jk1.dependency-license-report" version "2.9"
//id "nebula.lint" version "19.0.3"
id("org.panteleyev.jpackageplugin") version "1.6.1"
id "org.panteleyev.jpackageplugin" version "1.6.1"
id "org.sonarqube" version "6.1.0.5360"
id "com.gradleup.shadow" version "8.3.6"
}
import com.github.jk1.license.render.*
@ -25,75 +26,126 @@ ext {
bouncycastleVersion = "1.80"
springSecuritySamlVersion = "6.4.5"
openSamlVersion = "4.3.2"
commonmarkVersion = "0.24.0"
tempJrePath = null
}
group = "stirling.software"
version = "0.46.1"
java {
// 17 is lowest but we support and recommend 21
sourceCompatibility = JavaVersion.VERSION_17
jar {
enabled = false
manifest {
attributes "Implementation-Title": "Stirling-PDF",
"Implementation-Version": project.version
}
}
repositories {
mavenCentral()
maven { url = "https://build.shibboleth.net/maven/releases" }
maven { url = "https://maven.pkg.github.com/jcefmaven/jcefmaven" }
}
licenseReport {
renderers = [new JsonReportRenderer()]
allowedLicensesFile = new File("$projectDir/allowed-licenses.json")
bootJar {
enabled = false
}
sourceSets {
main {
java {
if (System.getenv("DOCKER_ENABLE_SECURITY") == "false") {
exclude "stirling/software/SPDF/config/interfaces/DatabaseInterface.java"
exclude "stirling/software/SPDF/config/security/**"
exclude "stirling/software/SPDF/controller/api/DatabaseController.java"
exclude "stirling/software/SPDF/controller/api/EmailController.java"
exclude "stirling/software/SPDF/controller/api/H2SQLCondition.java"
exclude "stirling/software/SPDF/controller/api/UserController.java"
exclude "stirling/software/SPDF/controller/web/AccountWebController.java"
exclude "stirling/software/SPDF/controller/web/DatabaseWebController.java"
exclude "stirling/software/SPDF/model/api/Email.java"
exclude "stirling/software/SPDF/model/ApiKeyAuthenticationToken.java"
exclude "stirling/software/SPDF/model/AttemptCounter.java"
exclude "stirling/software/SPDF/model/Authority.java"
exclude "stirling/software/SPDF/model/exception/BackupNotFoundException.java"
exclude "stirling/software/SPDF/model/exception/NoProviderFoundException.java"
exclude "stirling/software/SPDF/model/PersistentLogin.java"
exclude "stirling/software/SPDF/model/SessionEntity.java"
exclude "stirling/software/SPDF/model/User.java"
exclude "stirling/software/SPDF/repository/**"
if (System.getenv('ADDITIONAL_FEATURES') == 'false') {
exclude 'stirling/software/proprietary/security/**'
}
if (System.getenv("STIRLING_PDF_DESKTOP_UI") == "false") {
exclude "stirling/software/SPDF/UI/impl/**"
if (System.getenv('STIRLING_PDF_DESKTOP_UI') == 'false') {
exclude 'stirling/software/spdf/UI/impl/**'
}
}
}
test {
java {
if (System.getenv("DOCKER_ENABLE_SECURITY") == "false") {
exclude "stirling/software/SPDF/config/security/**"
exclude "stirling/software/SPDF/model/ApiKeyAuthenticationTokenTest.java"
exclude "stirling/software/SPDF/controller/api/EmailControllerTest.java"
exclude "stirling/software/SPDF/repository/**"
if (System.getenv('ADDITIONAL_FEATURES') == 'false') {
exclude 'stirling/software/proprietary/security/**'
}
if (System.getenv("STIRLING_PDF_DESKTOP_UI") == "false") {
exclude "stirling/software/SPDF/UI/impl/**"
if (System.getenv('STIRLING_PDF_DESKTOP_UI') == 'false') {
exclude 'stirling/software/spdf/UI/impl/**'
}
}
}
}
allprojects {
group = 'stirling.software'
version = '0.46.1'
afterEvaluate {
if (project == rootProject) return
tasks.register('wrapper', Wrapper) {
gradleVersion = '8.14'
distributionType = Wrapper.DistributionType.ALL
}
}
}
subprojects {
apply plugin: 'java'
apply plugin: 'com.diffplug.spotless'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
apply plugin: 'com.gradleup.shadow'
java {
// 17 is lowest but we support and recommend 21
sourceCompatibility = JavaVersion.VERSION_17
}
repositories {
mavenCentral()
}
configurations.configureEach {
exclude group: 'commons-logging', module: 'commons-logging'
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat'
// Exclude vulnerable BouncyCastle version used in tableau
exclude group: 'org.bouncycastle', module: 'bcpkix-jdk15on'
exclude group: 'org.bouncycastle', module: 'bcutil-jdk15on'
exclude group: 'org.bouncycastle', module: 'bcmail-jdk15on'
}
dependencyManagement {
imports {
mavenBom "org.springframework.boot:spring-boot-dependencies:$springBootVersion"
}
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'io.github.pixee:java-security-toolkit:1.2.1'
//tmp for security bumps
implementation 'ch.qos.logback:logback-core:1.5.18'
implementation 'ch.qos.logback:logback-classic:1.5.18'
compileOnly "org.projectlombok:lombok:$lombokVersion"
annotationProcessor "org.projectlombok:lombok:$lombokVersion"
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.mockito:mockito-inline:5.2.0'
}
tasks.withType(JavaCompile).configureEach {
options.encoding = "UTF-8"
dependsOn "spotlessApply"
}
compileJava {
options.compilerArgs << "-parameters"
}
test {
useJUnitPlatform()
}
}
licenseReport {
renderers = [new JsonReportRenderer()]
allowedLicensesFile = new File("$projectDir/allowed-licenses.json")
}
openApi {
apiDocsUrl = "http://localhost:8080/v1/api-docs"
outputDir = file("$projectDir")
@ -114,10 +166,9 @@ jpackage {
mainJar = "Stirling-PDF-${project.version}.jar"
appName = "Stirling PDF"
appVersion = project.version
// appVersion = "2005.45.1"
vendor = "Stirling PDF Inc"
appDescription = "Stirling PDF - Your Local PDF Editor"
icon = "src/main/resources/static/favicon.ico"
icon = "stirling-pdf/src/main/resources/static/favicon.ico"
verbose = true
// mainClass = "org.springframework.boot.loader.launch.JarLauncher"
@ -155,10 +206,10 @@ jpackage {
installDir = "C:/Program Files/Stirling-PDF"
}
// macOS-specific configuration
// MacOS-specific configuration
mac {
appVersion = getMacVersion(project.version.toString())
icon = "src/main/resources/static/favicon.icns"
icon = "stirling-pdf/src/main/resources/static/favicon.icns"
type = "dmg"
macPackageIdentifier = "Stirling PDF"
macPackageName = "Stirling PDF"
@ -180,7 +231,7 @@ jpackage {
// Linux-specific configuration
linux {
appVersion = project.version
icon = "src/main/resources/static/favicon.png"
icon = "stirling-pdf/src/main/resources/static/favicon.png"
type = "deb" // Can also use "rpm" for Red Hat-based systems
// Debian package configuration
@ -220,6 +271,11 @@ jpackage {
licenseFile = "LICENSE"
}
tasks.wrapper {
gradleVersion = "8.14"
distributionType = Wrapper.DistributionType.ALL
}
tasks.register('jpackageMacX64') {
group = 'distribution'
description = 'Packages app for MacOS x86_64'
@ -252,7 +308,7 @@ tasks.register('jpackageMacX64') {
'--main-class', 'org.springframework.boot.loader.launch.JarLauncher',
'--runtime-image', file(jrePath + "/zulu-17.jre/Contents/Home"),
'--dest', 'build/jpackage/x86_64',
'--icon', 'src/main/resources/static/favicon.icns',
'--icon', 'stirling-pdf/src/main/resources/static/favicon.icns',
'--app-version', getMacVersion(project.version.toString()),
'--mac-package-name', 'Stirling PDF (x86_64)',
'--mac-package-identifier', 'Stirling PDF (x86_64)',
@ -289,8 +345,6 @@ tasks.register('jpackageMacX64') {
}
}
//jpackage.finalizedBy(jpackageMacX64)
tasks.register('downloadTempJre') {
group = 'distribution'
description = 'Downloads and extracts a temporary JRE'
@ -302,18 +356,18 @@ tasks.register('downloadTempJre') {
def jreArchive = new File(tmpDir, 'jre.tar.gz')
def jreDir = new File(tmpDir, 'jre')
println "🔽 Downloading JRE to $jreArchive..."
println "Downloading JRE to $jreArchive"
jreArchive.withOutputStream { out ->
new URI(jreUrl).toURL().withInputStream { from -> out << from }
}
println "📦 Extracting JRE to $jreDir..."
println "Extracting JRE to $jreDir"
jreDir.mkdirs()
providers.exec {
commandLine 'tar', '-xzf', jreArchive.absolutePath, '-C', jreDir.absolutePath, '--strip-components=1'
}.result.get()
println "JRE ready at: $jreDir"
println "JRE ready at: $jreDir"
ext.tempJrePath = jreDir.absolutePath
project.ext.tempJrePath = jreDir.absolutePath
} catch (Exception e) {
@ -339,7 +393,7 @@ tasks.register('cleanTempJre') {
}
launch4j {
icon = "${projectDir}/src/main/resources/static/favicon.ico"
icon = "${projectDir}/stirling-pdf/src/main/resources/static/favicon.ico"
outfile="Stirling-PDF.exe"
@ -350,7 +404,7 @@ launch4j {
}
jarTask = tasks.bootJar
errTitle="Encountered error, Do you have Java 21?"
errTitle="Encountered error, do you have Java 21?"
downloadUrl="https://download.oracle.com/java/21/latest/jdk-21_windows-x64_bin.exe"
if(System.getenv("STIRLING_PDF_DESKTOP_UI") == 'true') {
@ -390,186 +444,12 @@ sonar {
property "sonar.projectKey", "Stirling-Tools_Stirling-PDF"
property "sonar.organization", "stirling-tools"
property "sonar.exclusions", "**/build-wrapper-dump.json, src/main/java/org/apache/**, src/main/resources/static/pdfjs/**, src/main/resources/static/pdfjs-legacy/**, src/main/resources/static/js/thirdParty/**"
property "sonar.coverage.exclusions", "src/main/java/org/apache/**, src/main/resources/static/pdfjs/**, src/main/resources/static/pdfjs-legacy/**, src/main/resources/static/js/thirdParty/**"
property "sonar.cpd.exclusions", "src/main/java/org/apache/**, src/main/resources/static/pdfjs/**, src/main/resources/static/pdfjs-legacy/**, src/main/resources/static/js/thirdParty/**"
property "sonar.exclusions", "**/build-wrapper-dump.json, **/src/main/java/org/apache/**, **/src/main/resources/static/pdfjs/**, **/src/main/resources/static/pdfjs-legacy/**, **/src/main/resources/static/js/thirdParty/**"
property "sonar.coverage.exclusions", "**/src/main/java/org/apache/**, **/src/main/resources/static/pdfjs/**, **/src/main/resources/static/pdfjs-legacy/**, **/src/main/resources/static/js/thirdParty/**"
property "sonar.cpd.exclusions", "**/src/main/java/org/apache/**, **/src/main/resources/static/pdfjs/**, **/src/main/resources/static/pdfjs-legacy/**, **/src/main/resources/static/js/thirdParty/**"
}
}
//gradleLint {
// rules=['unused-dependency']
// }
tasks.wrapper {
gradleVersion = "8.14"
distributionType = Wrapper.DistributionType.ALL
}
//tasks.withType(JavaCompile) {
// options.compilerArgs << "-Xlint:deprecation"
//}
configurations.all {
// Remove all commons-logging dependencies so that only spring-jcl is used
exclude group: 'commons-logging', module: 'commons-logging'
// Exclude Tomcat
exclude group: "org.springframework.boot", module: "spring-boot-starter-tomcat"
}
dependencies {
//tmp for security bumps
implementation 'ch.qos.logback:logback-core:1.5.18'
implementation 'ch.qos.logback:logback-classic:1.5.18'
// Exclude vulnerable BouncyCastle version used in tableau
configurations.all {
exclude group: 'org.bouncycastle', module: 'bcpkix-jdk15on'
exclude group: 'org.bouncycastle', module: 'bcutil-jdk15on'
exclude group: 'org.bouncycastle', module: 'bcmail-jdk15on'
}
if (System.getenv("STIRLING_PDF_DESKTOP_UI") != "false") {
implementation "me.friwi:jcefmaven:132.3.1"
implementation "org.openjfx:javafx-controls:21"
implementation "org.openjfx:javafx-swing:21"
}
//security updates
implementation "org.springframework:spring-webmvc:6.2.6"
implementation("io.github.pixee:java-security-toolkit:1.2.1")
// Exclude Tomcat and include Jetty
implementation("org.springframework.boot:spring-boot-starter-web:$springBootVersion")
implementation "org.springframework.boot:spring-boot-starter-jetty:$springBootVersion"
implementation "org.springframework.boot:spring-boot-starter-thymeleaf:$springBootVersion"
implementation 'com.posthog.java:posthog:1.2.0'
implementation 'com.googlecode.owasp-java-html-sanitizer:owasp-java-html-sanitizer:20240325.1'
if (System.getenv("DOCKER_ENABLE_SECURITY") != "false") {
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'io.micrometer:micrometer-registry-prometheus'
implementation "org.springframework.boot:spring-boot-starter-security:$springBootVersion"
implementation "org.thymeleaf.extras:thymeleaf-extras-springsecurity5:3.1.3.RELEASE"
implementation "org.springframework.boot:spring-boot-starter-data-jpa:$springBootVersion"
implementation "org.springframework.boot:spring-boot-starter-oauth2-client:$springBootVersion"
implementation "org.springframework.boot:spring-boot-starter-mail:$springBootVersion"
implementation "org.springframework.session:spring-session-core:3.4.3"
implementation "org.springframework:spring-jdbc:6.2.6"
implementation 'com.unboundid.product.scim2:scim2-sdk-client:2.3.5'
// Don't upgrade h2database
runtimeOnly "com.h2database:h2:2.3.232"
runtimeOnly "org.postgresql:postgresql:42.7.5"
constraints {
implementation "org.opensaml:opensaml-core:$openSamlVersion"
implementation "org.opensaml:opensaml-saml-api:$openSamlVersion"
implementation "org.opensaml:opensaml-saml-impl:$openSamlVersion"
}
implementation "org.springframework.security:spring-security-saml2-service-provider:$springSecuritySamlVersion"
// implementation 'org.springframework.security:spring-security-core:$springSecuritySamlVersion'
implementation 'com.coveo:saml-client:5.0.0'
}
implementation 'org.snakeyaml:snakeyaml-engine:2.9'
testImplementation "org.springframework.boot:spring-boot-starter-test:$springBootVersion"
// Batik
implementation "org.apache.xmlgraphics:batik-all:1.19"
// TwelveMonkeys
runtimeOnly "com.twelvemonkeys.imageio:imageio-batik:$imageioVersion"
runtimeOnly "com.twelvemonkeys.imageio:imageio-bmp:$imageioVersion"
// runtimeOnly "com.twelvemonkeys.imageio:imageio-hdr:$imageioVersion"
// runtimeOnly "com.twelvemonkeys.imageio:imageio-icns:$imageioVersion"
// runtimeOnly "com.twelvemonkeys.imageio:imageio-iff:$imageioVersion"
runtimeOnly "com.twelvemonkeys.imageio:imageio-jpeg:$imageioVersion"
// runtimeOnly "com.twelvemonkeys.imageio:imageio-pcx:$imageioVersion@
// runtimeOnly "com.twelvemonkeys.imageio:imageio-pict:$imageioVersion"
// runtimeOnly "com.twelvemonkeys.imageio:imageio-pnm:$imageioVersion"
// runtimeOnly "com.twelvemonkeys.imageio:imageio-psd:$imageioVersion"
// runtimeOnly "com.twelvemonkeys.imageio:imageio-sgi:$imageioVersion"
// runtimeOnly "com.twelvemonkeys.imageio:imageio-tga:$imageioVersion"
// runtimeOnly "com.twelvemonkeys.imageio:imageio-thumbsdb:$imageioVersion"
runtimeOnly "com.twelvemonkeys.imageio:imageio-tiff:$imageioVersion"
runtimeOnly "com.twelvemonkeys.imageio:imageio-webp:$imageioVersion"
// runtimeOnly "com.twelvemonkeys.imageio:imageio-xwd:$imageioVersion"
// Image metadata extractor
implementation "com.drewnoakes:metadata-extractor:2.19.0"
implementation "commons-io:commons-io:2.19.0"
implementation "org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.8"
//general PDF
// https://mvnrepository.com/artifact/com.opencsv/opencsv
implementation ("com.opencsv:opencsv:5.11")
implementation ("org.apache.pdfbox:pdfbox:$pdfboxVersion")
implementation "org.apache.pdfbox:preflight:$pdfboxVersion"
implementation ("org.apache.pdfbox:xmpbox:$pdfboxVersion")
// https://mvnrepository.com/artifact/technology.tabula/tabula
implementation ('technology.tabula:tabula:1.0.5') {
exclude group: "org.slf4j", module: "slf4j-simple"
exclude group: "org.bouncycastle", module: "bcprov-jdk15on"
exclude group: "com.google.code.gson", module: "gson"
}
implementation 'org.apache.pdfbox:jbig2-imageio:3.0.4'
implementation "org.bouncycastle:bcprov-jdk18on:$bouncycastleVersion"
implementation "org.bouncycastle:bcpkix-jdk18on:$bouncycastleVersion"
implementation "org.springframework.boot:spring-boot-starter-actuator:$springBootVersion"
implementation "io.micrometer:micrometer-core:1.14.7"
implementation group: "com.google.zxing", name: "core", version: "3.5.3"
// https://mvnrepository.com/artifact/org.commonmark/commonmark
implementation "org.commonmark:commonmark:0.24.0"
implementation "org.commonmark:commonmark-ext-gfm-tables:0.24.0"
// https://mvnrepository.com/artifact/com.bucket4j/bucket4j_jdk17
implementation "com.bucket4j:bucket4j_jdk17-core:8.14.0"
implementation "com.fathzer:javaluator:3.0.6"
implementation 'com.vladsch.flexmark:flexmark-html2md-converter:0.64.8'
developmentOnly("org.springframework.boot:spring-boot-devtools:$springBootVersion")
compileOnly "org.projectlombok:lombok:$lombokVersion"
annotationProcessor "org.projectlombok:lombok:$lombokVersion"
testRuntimeOnly 'org.mockito:mockito-inline:5.2.0'
}
tasks.withType(JavaCompile).configureEach {
options.encoding = "UTF-8"
dependsOn "spotlessApply"
}
compileJava {
options.compilerArgs << "-parameters"
}
task writeVersion {
def propsFile = file("$projectDir/src/main/resources/version.properties")
def propsDir = propsFile.parentFile
doLast {
if (!propsDir.exists()) {
propsDir.mkdirs()
}
def props = new Properties()
props.setProperty("version", version)
props.store(propsFile.newWriter(), null)
}
}
processResources.dependsOn(writeVersion)
swaggerhubUpload {
// dependsOn = generateOpenApiDocs // Depends on your task generating Swagger docs
api = "Stirling-PDF" // The name of your API on SwaggerHub
@ -580,25 +460,43 @@ swaggerhubUpload {
oas = "3.0.0" // The version of the OpenAPI Specification you"re using
}
jar {
enabled = false
manifest {
attributes "Implementation-Title": "Stirling-PDF",
"Implementation-Version": project.version
}
}
tasks.named("test") {
useJUnitPlatform()
}
task printVersion {
tasks.register('writeVersion') {
def propsFile = file("$projectDir/stirling-pdf/src/main/resources/version.properties")
def propsDir = propsFile.parentFile
doLast {
if (propsDir.exists()) {
if (propsFile.exists()) {
println "File exists: $propsFile"
} else {
println "$propsFile does not exist. Creating file."
propsFile.createNewFile()
}
} else {
println "Creating directory: $propsDir"
propsDir.mkdirs()
propsFile.createNewFile()
}
def props = new Properties()
props.setProperty("version", version)
props.store(propsFile.newWriter(), null)
}
}
processResources.dependsOn(writeVersion)
tasks.register('printVersion') {
doLast {
println project.version
}
}
task printMacVersion {
tasks.register('printMacVersion') {
doLast {
println getMacVersion(project.version.toString())
}

196
common/.gitignore vendored Normal file
View File

@ -0,0 +1,196 @@
### Eclipse ###
.metadata
bin/
tmp/
*.tmp
*.bak
*.exe
*.swp
*~.nib
local.properties
.settings/
.loadpath
.recommenders
.classpath
.project
version.properties
#### Stirling-PDF Files ###
pipeline/watchedFolders/
pipeline/finishedFolders/
customFiles/
configs/
watchedFolders/
clientWebUI/
!cucumber/
!cucumber/exampleFiles/
!cucumber/exampleFiles/example_html.zip
exampleYmlFiles/stirling/
/testing/file_snapshots
SwaggerDoc.json
# Gradle
.gradle
.lock
# External tool builders
.externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# PyDev specific (Python IDE for Eclipse)
*.pydevproject
# CDT-specific (C/C++ Development Tooling)
.cproject
# CDT- autotools
.autotools
# Java annotation processor (APT)
.factorypath
# PDT-specific (PHP Development Tools)
.buildpath
# sbteclipse plugin
.target
# Tern plugin
.tern-project
# TeXlipse plugin
.texlipse
# STS (Spring Tool Suite)
.springBeans
# Code Recommenders
.recommenders/
# Annotation Processing
.apt_generated/
.apt_generated_test/
# Scala IDE specific (Scala & Java development for Eclipse)
.cache-main
.scala_dependencies
.worksheet
# Uncomment this line if you wish to ignore the project description file.
# Typically, this file would be tracked if it contains build/dependency configurations:
#.project
### Eclipse Patch ###
# Spring Boot Tooling
.sts4-cache/
### Git ###
# Created by git for backups. To disable backups in Git:
# $ git config --global mergetool.keepBackup false
*.orig
# Created by git when using merge tools for conflicts
*.BACKUP.*
*.BASE.*
*.LOCAL.*
*.REMOTE.*
*_BACKUP_*.txt
*_BASE_*.txt
*_LOCAL_*.txt
*_REMOTE_*.txt
### Java ###
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
*.db
/build
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*.pyo
# Virtual environments
.env*
.venv*
env*/
venv*/
ENV/
env.bak/
venv.bak/
# VS Code
/.vscode/**/*
!/.vscode/settings.json
!/.vscode/extensions.json
# IntelliJ IDEA
.idea/
*.iml
out/
# Ignore Mac DS_Store files
.DS_Store
**/.DS_Store
# cucumber
/cucumber/reports/**
# Certs and Security Files
*.p12
*.pk8
*.pem
*.crt
*.cer
*.cert
*.der
*.key
*.csr
*.kdbx
*.jks
*.asc
# SSH Keys
*.pub
*.priv
id_rsa
id_rsa.pub
id_ecdsa
id_ecdsa.pub
id_ed25519
id_ed25519.pub
.ssh/
*ssh
# cache
.cache
.ruff_cache
.mypy_cache
.pytest_cache
.ipynb_checkpoints
**/jcef-bundle/
# node_modules
node_modules/
*.mjs

30
common/build.gradle Normal file
View File

@ -0,0 +1,30 @@
plugins {
id 'java-library'
}
bootJar {
enabled = false
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'com.googlecode.owasp-java-html-sanitizer:owasp-java-html-sanitizer:20240325.1'
implementation 'com.fathzer:javaluator:3.0.6'
implementation 'com.posthog.java:posthog:1.2.0'
implementation 'io.github.pixee:java-security-toolkit:1.2.1'
implementation 'org.apache.commons:commons-lang3:3.17.0'
implementation 'com.drewnoakes:metadata-extractor:2.19.0' // Image metadata extractor
implementation 'com.vladsch.flexmark:flexmark-html2md-converter:0.64.8'
implementation "org.apache.pdfbox:pdfbox:$pdfboxVersion"
implementation 'jakarta.servlet:jakarta.servlet-api:6.0.0'
implementation 'org.snakeyaml:snakeyaml-engine:2.9'
implementation "org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.6"
compileOnly "org.projectlombok:lombok:$lombokVersion"
annotationProcessor "org.projectlombok:lombok:$lombokVersion"
testImplementation "org.springframework.boot:spring-boot-starter-test"
testRuntimeOnly 'org.springframework.boot:spring-boot-starter-data-jpa'
testRuntimeOnly 'org.mockito:mockito-inline:5.2.0'
}

View File

@ -0,0 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-all.zip
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

251
common/gradlew vendored Executable file
View File

@ -0,0 +1,251 @@
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH="\\\"\\\""
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"

94
common/gradlew.bat vendored Normal file
View File

@ -0,0 +1,94 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@rem SPDX-License-Identifier: Apache-2.0
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
:execute
@rem Setup the command line
set CLASSPATH=
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config;
package stirling.software.common.configuration;
import java.io.IOException;
import java.nio.file.Files;
@ -8,7 +8,9 @@ import java.util.List;
import java.util.Locale;
import java.util.Properties;
import java.util.function.Predicate;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@ -21,21 +23,29 @@ import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.thymeleaf.spring6.SpringTemplateEngine;
import stirling.software.common.model.ApplicationProperties;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.model.ApplicationProperties;
@Configuration
@Lazy
@Slf4j
@Configuration
@RequiredArgsConstructor
public class AppConfig {
private final Environment env;
private final ApplicationProperties applicationProperties;
private final Environment env;
@Getter
@Value("${baseUrl:http://localhost}")
private String baseUrl;
@Getter
@Value("${server.servlet.context-path:/}")
private String contextPath;
@Getter
@Value("${server.port:8080}")
private String serverPort;
@Bean
@ConditionalOnProperty(name = "system.customHTMLFiles", havingValue = "true")
@ -50,6 +60,11 @@ public class AppConfig {
return applicationProperties.getSecurity().getEnableLogin();
}
@Bean
public boolean activeSecurity() {
return env.getProperty("ADDITIONAL_FEATURES", Boolean.class, true);
}
@Bean(name = "appName")
public String appName() {
String homeTitle = applicationProperties.getUi().getAppName();
@ -133,10 +148,10 @@ public class AppConfig {
}
}
@ConditionalOnMissingClass("stirling.software.SPDF.config.security.SecurityConfiguration")
@Bean(name = "activeSecurity")
@Bean(name = "missingActiveSecurity")
@ConditionalOnMissingClass("stirling.software.proprietary.security.SecurityConfiguration")
public boolean missingActiveSecurity() {
return false;
return true;
}
@Bean(name = "directoryFilter")
@ -198,6 +213,31 @@ public class AppConfig {
return applicationProperties.getAutomaticallyGenerated().getUUID();
}
@Bean
public ApplicationProperties.Security security() {
return applicationProperties.getSecurity();
}
@Bean
public ApplicationProperties.Security.OAUTH2 oAuth2() {
return applicationProperties.getSecurity().getOauth2();
}
@Bean
public ApplicationProperties.Premium premium() {
return applicationProperties.getPremium();
}
@Bean
public ApplicationProperties.System system() {
return applicationProperties.getSystem();
}
@Bean
public ApplicationProperties.Datasource datasource() {
return applicationProperties.getSystem().getDatasource();
}
@Bean(name = "disablePixel")
public boolean disablePixel() {
return Boolean.getBoolean(env.getProperty("DISABLE_PIXEL"));

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config;
package stirling.software.common.configuration;
import java.io.FileNotFoundException;
import java.io.IOException;
@ -13,6 +13,8 @@ import java.util.List;
import lombok.extern.slf4j.Slf4j;
import stirling.software.common.util.YamlHelper;
/**
* A naive, line-based approach to merging "settings.yml" with "settings.yml.template" while
* preserving exact whitespace, blank lines, and inline comments -- but we only rewrite the file if
@ -76,7 +78,7 @@ public class ConfigInitializer {
Path customSettingsPath = Paths.get(InstallationPathConfig.getCustomSettingsPath());
if (Files.notExists(customSettingsPath)) {
Files.createFile(customSettingsPath);
log.info("Created custom_settings file: {}", customSettingsPath.toString());
log.info("Created custom_settings file: {}", customSettingsPath);
}
}

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config;
package stirling.software.common.configuration;
import java.io.IOException;
import java.io.InputStream;
@ -10,8 +10,7 @@ import org.thymeleaf.IEngineConfiguration;
import org.thymeleaf.templateresolver.AbstractConfigurableTemplateResolver;
import org.thymeleaf.templateresource.FileTemplateResource;
import org.thymeleaf.templateresource.ITemplateResource;
import stirling.software.SPDF.model.InputStreamTemplateResource;
import stirling.software.common.model.InputStreamTemplateResource;
public class FileFallbackTemplateResolver extends AbstractConfigurableTemplateResolver {

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config;
package stirling.software.common.configuration;
import java.io.File;
import java.nio.file.Paths;
@ -48,25 +48,22 @@ public class InstallationPathConfig {
String os = System.getProperty("os.name").toLowerCase();
if (os.contains("win")) {
return Paths.get(
System.getenv("APPDATA"), // parent path
"Stirling-PDF")
.toString()
+ File.separator;
System.getenv("APPDATA"), // parent path
"Stirling-PDF")
+ File.separator;
} else if (os.contains("mac")) {
return Paths.get(
System.getProperty("user.home"),
"Library",
"Application Support",
"Stirling-PDF")
.toString()
+ File.separator;
System.getProperty("user.home"),
"Library",
"Application Support",
"Stirling-PDF")
+ File.separator;
} else {
return Paths.get(
System.getProperty("user.home"), // parent path
".config",
"Stirling-PDF")
.toString()
+ File.separator;
System.getProperty("user.home"), // parent path
".config",
"Stirling-PDF")
+ File.separator;
}
}
return "." + File.separator;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config;
package stirling.software.common.configuration;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config;
package stirling.software.common.configuration;
import org.springframework.stereotype.Component;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config;
package stirling.software.common.configuration;
import java.nio.file.Files;
import java.nio.file.Path;
@ -9,9 +9,9 @@ import org.springframework.context.annotation.Configuration;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.model.ApplicationProperties;
import stirling.software.SPDF.model.ApplicationProperties.CustomPaths.Operations;
import stirling.software.SPDF.model.ApplicationProperties.CustomPaths.Pipeline;
import stirling.software.common.model.ApplicationProperties;
import stirling.software.common.model.ApplicationProperties.CustomPaths.Operations;
import stirling.software.common.model.ApplicationProperties.CustomPaths.Pipeline;
@Slf4j
@Configuration

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config;
package stirling.software.common.configuration;
import java.io.IOException;
import java.util.Properties;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.interfaces;
package stirling.software.common.configuration.interfaces;
public interface ShowAdminInterface {
default boolean getShowUpdateOnlyAdmins() {

View File

@ -1,6 +1,4 @@
package stirling.software.SPDF.model;
import static stirling.software.SPDF.utils.validation.Validator.*;
package stirling.software.common.model;
import java.io.File;
import java.io.FileNotFoundException;
@ -14,7 +12,11 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@ -26,20 +28,17 @@ import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.EncodedResource;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.InstallationPathConfig;
import stirling.software.SPDF.config.YamlPropertySourceFactory;
import stirling.software.SPDF.model.exception.UnsupportedProviderException;
import stirling.software.SPDF.model.provider.GitHubProvider;
import stirling.software.SPDF.model.provider.GoogleProvider;
import stirling.software.SPDF.model.provider.KeycloakProvider;
import stirling.software.SPDF.model.provider.Provider;
import org.springframework.stereotype.Component;
import stirling.software.common.configuration.InstallationPathConfig;
import stirling.software.common.configuration.YamlPropertySourceFactory;
import stirling.software.common.model.exception.UnsupportedProviderException;
import stirling.software.common.util.ValidationUtil;
import stirling.software.common.model.oauth2.provider.GitHubProvider;
import stirling.software.common.model.oauth2.provider.GoogleProvider;
import stirling.software.common.model.oauth2.provider.KeycloakProvider;
import stirling.software.common.model.oauth2.provider.Provider;
import static stirling.software.common.util.ValidationUtil.isCollectionEmpty;
import static stirling.software.common.util.ValidationUtil.isStringEmpty;
@Configuration
@ConfigurationProperties(prefix = "")
@ -50,9 +49,9 @@ public class ApplicationProperties {
@Bean
public PropertySource<?> dynamicYamlPropertySource(ConfigurableEnvironment environment)
throws IOException {
throws IOException {
String configPath = InstallationPathConfig.getSettingsPath();
log.debug("Attempting to load settings from: " + configPath);
log.info("Attempting to load settings from: " + configPath);
File file = new File(configPath);
if (!file.exists()) {
@ -66,10 +65,10 @@ public class ApplicationProperties {
EncodedResource encodedResource = new EncodedResource(resource);
PropertySource<?> propertySource =
new YamlPropertySourceFactory().createPropertySource(null, encodedResource);
new YamlPropertySourceFactory().createPropertySource(null, encodedResource);
environment.getPropertySources().addFirst(propertySource);
log.debug("Loaded properties: " + propertySource.getSource());
log.info("Loaded properties: " + propertySource.getSource());
return propertySource;
}
@ -139,19 +138,19 @@ public class ApplicationProperties {
public boolean isUserPass() {
return (loginMethod.equalsIgnoreCase(LoginMethods.NORMAL.toString())
|| loginMethod.equalsIgnoreCase(LoginMethods.ALL.toString()));
|| loginMethod.equalsIgnoreCase(LoginMethods.ALL.toString()));
}
public boolean isOauth2Active() {
return (oauth2 != null
&& oauth2.getEnabled()
&& !loginMethod.equalsIgnoreCase(LoginMethods.NORMAL.toString()));
&& oauth2.getEnabled()
&& !loginMethod.equalsIgnoreCase(LoginMethods.NORMAL.toString()));
}
public boolean isSaml2Active() {
return (saml2 != null
&& saml2.getEnabled()
&& !loginMethod.equalsIgnoreCase(LoginMethods.NORMAL.toString()));
&& saml2.getEnabled()
&& !loginMethod.equalsIgnoreCase(LoginMethods.NORMAL.toString()));
}
@Data
@ -180,7 +179,7 @@ public class ApplicationProperties {
public InputStream getIdpMetadataUri() throws IOException {
if (idpMetadataUri.startsWith("classpath:")) {
return new ClassPathResource(idpMetadataUri.substring("classpath".length()))
.getInputStream();
.getInputStream();
}
try {
URI uri = new URI(idpMetadataUri);
@ -235,7 +234,7 @@ public class ApplicationProperties {
public void setScopes(String scopes) {
List<String> scopesList =
Arrays.stream(scopes.split(",")).map(String::trim).toList();
Arrays.stream(scopes.split(",")).map(String::trim).toList();
this.scopes.addAll(scopesList);
}
@ -249,10 +248,10 @@ public class ApplicationProperties {
public boolean isSettingsValid() {
return !isStringEmpty(this.getIssuer())
&& !isStringEmpty(this.getClientId())
&& !isStringEmpty(this.getClientSecret())
&& !isCollectionEmpty(this.getScopes())
&& !isStringEmpty(this.getUseAsUsername());
&& !isStringEmpty(this.getClientId())
&& !isStringEmpty(this.getClientSecret())
&& !isCollectionEmpty(this.getScopes())
&& !isStringEmpty(this.getUseAsUsername());
}
@Data
@ -267,11 +266,11 @@ public class ApplicationProperties {
case "github" -> getGithub();
case "keycloak" -> getKeycloak();
default ->
throw new UnsupportedProviderException(
"Logout from the provider "
+ registrationId
+ " is not supported. "
+ "Report it at https://github.com/Stirling-Tools/Stirling-PDF/issues");
throw new UnsupportedProviderException(
"Logout from the provider "
+ registrationId
+ " is not supported. "
+ "Report it at https://github.com/Stirling-Tools/Stirling-PDF/issues");
};
}
}
@ -349,7 +348,7 @@ public class ApplicationProperties {
driverName='%s'
}
"""
.formatted(driverName);
.formatted(driverName);
}
}
@ -366,14 +365,14 @@ public class ApplicationProperties {
public String getHomeDescription() {
return homeDescription != null && homeDescription.trim().length() > 0
? homeDescription
: null;
? homeDescription
: null;
}
public String getAppNameNavbar() {
return appNameNavbar != null && appNameNavbar.trim().length() > 0
? appNameNavbar
: null;
? appNameNavbar
: null;
}
}
@ -459,8 +458,8 @@ public class ApplicationProperties {
public String getProducer() {
return producer == null || producer.trim().isEmpty()
? "Stirling-PDF"
: producer;
? "Stirling-PDF"
: producer;
}
}

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.utils;
package stirling.software.common.model;
import java.nio.file.Path;
import java.nio.file.Paths;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.model;
package stirling.software.common.model;
import java.io.IOException;
import java.io.InputStream;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.model;
package stirling.software.common.model;
import java.util.Calendar;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.model.api;
package stirling.software.common.model.api;
import org.springframework.web.multipart.MultipartFile;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.model.api;
package stirling.software.common.model.api;
import org.springframework.web.multipart.MultipartFile;

View File

@ -1,11 +1,10 @@
package stirling.software.SPDF.model.api.converters;
package stirling.software.common.model.api.converters;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import stirling.software.SPDF.model.api.PDFFile;
import stirling.software.common.model.api.PDFFile;
@Data
@EqualsAndHashCode(callSuper = true)

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.model.api.misc;
package stirling.software.common.model.api.misc;
public enum HighContrastColorCombination {
WHITE_TEXT_ON_BLACK,

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.model.api.misc;
package stirling.software.common.model.api.misc;
public enum ReplaceAndInvert {
HIGH_CONTRAST_COLOR,

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.model.api.security;
package stirling.software.common.model.api.security;
import io.swagger.v3.oas.annotations.media.Schema;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.model;
package stirling.software.common.model.enumeration;
import java.util.LinkedHashMap;
import java.util.Map;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.model;
package stirling.software.common.model.enumeration;
import lombok.Getter;

View File

@ -0,0 +1,7 @@
package stirling.software.common.model.exception;
public class UnsupportedClaimException extends RuntimeException {
public UnsupportedClaimException(String message) {
super(message);
}
}

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.model.exception;
package stirling.software.common.model.exception;
public class UnsupportedProviderException extends Exception {
public UnsupportedProviderException(String message) {

View File

@ -1,11 +1,9 @@
package stirling.software.SPDF.model.provider;
package stirling.software.common.model.oauth2.provider;
import java.util.ArrayList;
import java.util.Collection;
import lombok.NoArgsConstructor;
import stirling.software.SPDF.model.UsernameAttribute;
import stirling.software.common.model.enumeration.UsernameAttribute;
@NoArgsConstructor
public class GitHubProvider extends Provider {

View File

@ -1,11 +1,9 @@
package stirling.software.SPDF.model.provider;
package stirling.software.common.model.oauth2.provider;
import java.util.ArrayList;
import java.util.Collection;
import lombok.NoArgsConstructor;
import stirling.software.SPDF.model.UsernameAttribute;
import stirling.software.common.model.enumeration.UsernameAttribute;
@NoArgsConstructor
public class GoogleProvider extends Provider {

View File

@ -1,11 +1,9 @@
package stirling.software.SPDF.model.provider;
package stirling.software.common.model.oauth2.provider;
import java.util.ArrayList;
import java.util.Collection;
import lombok.NoArgsConstructor;
import stirling.software.SPDF.model.UsernameAttribute;
import stirling.software.common.model.enumeration.UsernameAttribute;
@NoArgsConstructor
public class KeycloakProvider extends Provider {

View File

@ -1,16 +1,13 @@
package stirling.software.SPDF.model.provider;
import static stirling.software.SPDF.model.UsernameAttribute.EMAIL;
package stirling.software.common.model.oauth2.provider;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import lombok.Data;
import lombok.NoArgsConstructor;
import stirling.software.SPDF.model.UsernameAttribute;
import stirling.software.SPDF.model.exception.UnsupportedUsernameAttribute;
import stirling.software.common.model.enumeration.UsernameAttribute;
import stirling.software.common.model.exception.UnsupportedClaimException;
import static stirling.software.common.model.enumeration.UsernameAttribute.EMAIL;
@Data
@NoArgsConstructor
@ -83,7 +80,7 @@ public class Provider {
return usernameAttribute;
}
default ->
throw new UnsupportedUsernameAttribute(
throw new UnsupportedClaimException(
String.format(EXCEPTION_MESSAGE, usernameAttribute, clientName));
}
}
@ -94,7 +91,7 @@ public class Provider {
return usernameAttribute;
}
default ->
throw new UnsupportedUsernameAttribute(
throw new UnsupportedClaimException(
String.format(EXCEPTION_MESSAGE, usernameAttribute, clientName));
}
}
@ -105,7 +102,7 @@ public class Provider {
return usernameAttribute;
}
default ->
throw new UnsupportedUsernameAttribute(
throw new UnsupportedClaimException(
String.format(EXCEPTION_MESSAGE, usernameAttribute, clientName));
}
}

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.service;
package stirling.software.common.service;
import java.io.ByteArrayOutputStream;
import java.io.File;
@ -22,7 +22,7 @@ import org.springframework.web.multipart.MultipartFile;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.model.api.PDFFile;
import stirling.software.common.model.api.PDFFile;
/**
* Adaptive PDF document factory that optimizes memory usage based on file size and available system

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.service;
package stirling.software.common.service;
import java.util.Calendar;
@ -7,9 +7,8 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import stirling.software.SPDF.controller.api.pipeline.UserServiceInterface;
import stirling.software.SPDF.model.ApplicationProperties;
import stirling.software.SPDF.model.PdfMetadata;
import stirling.software.common.model.ApplicationProperties;
import stirling.software.common.model.PdfMetadata;
@Service
public class PdfMetadataService {

View File

@ -1,12 +1,21 @@
package stirling.software.SPDF.service;
package stirling.software.common.service;
import java.io.File;
import java.lang.management.*;
import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.OperatingSystemMXBean;
import java.lang.management.RuntimeMXBean;
import java.lang.management.ThreadMXBean;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
@ -16,8 +25,7 @@ import org.springframework.stereotype.Service;
import com.posthog.java.PostHog;
import stirling.software.SPDF.controller.api.pipeline.UserServiceInterface;
import stirling.software.SPDF.model.ApplicationProperties;
import stirling.software.common.model.ApplicationProperties;
@Service
public class PostHogService {
@ -200,7 +208,7 @@ public class PostHogService {
// New environment variables
dockerMetrics.put("version_tag", System.getenv("VERSION_TAG"));
dockerMetrics.put("docker_enable_security", System.getenv("DOCKER_ENABLE_SECURITY"));
dockerMetrics.put("additional_features", System.getenv("ADDITIONAL_FEATURES"));
dockerMetrics.put("fat_docker", System.getenv("FAT_DOCKER"));
return dockerMetrics;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.controller.api.pipeline;
package stirling.software.common.service;
public interface UserServiceInterface {
String getApiKeyForUser(String username);

View File

@ -1,10 +1,10 @@
package stirling.software.SPDF.utils;
package stirling.software.common.util;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult;
import stirling.software.common.util.ProcessExecutor.ProcessExecutorResult;
public class CheckProgramInstall {

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.utils;
package stirling.software.common.util;
import org.owasp.html.HtmlPolicyBuilder;
import org.owasp.html.PolicyFactory;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.utils;
package stirling.software.common.util;
import java.io.PrintWriter;
import java.io.StringWriter;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.utils;
package stirling.software.common.util;
import static java.nio.file.StandardWatchEventKinds.*;
@ -17,8 +17,7 @@ import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.RuntimePathConfig;
import stirling.software.common.configuration.RuntimePathConfig;
@Component
@Slf4j

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.utils;
package stirling.software.common.util;
import java.io.*;
import java.nio.charset.StandardCharsets;
@ -16,8 +16,8 @@ import java.util.zip.ZipOutputStream;
import io.github.pixee.security.ZipSecurity;
import stirling.software.SPDF.model.api.converters.HTMLToPdfRequest;
import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult;
import stirling.software.common.model.api.converters.HTMLToPdfRequest;
import stirling.software.common.util.ProcessExecutor.ProcessExecutorResult;
public class FileToPdf {

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.utils;
package stirling.software.common.util;
import java.io.File;
import java.io.FileOutputStream;
@ -27,11 +27,10 @@ import io.github.pixee.security.Urls;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.InstallationPathConfig;
import stirling.software.SPDF.config.YamlHelper;
import stirling.software.common.configuration.InstallationPathConfig;
@Slf4j
public class GeneralUtils {
public class GeneralUtil {
public static File convertMultipartFileToFile(MultipartFile multipartFile) throws IOException {
File tempFile = Files.createTempFile("temp", null).toFile();

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.utils;
package stirling.software.common.util;
import java.awt.geom.AffineTransform;
import java.awt.image.*;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.utils;
package stirling.software.common.util;
import java.io.ByteArrayOutputStream;
import java.io.File;
@ -28,7 +28,7 @@ import io.github.pixee.security.Filenames;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult;
import stirling.software.common.util.ProcessExecutor.ProcessExecutorResult;
@Slf4j
@NoArgsConstructor

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.utils;
package stirling.software.common.util;
import java.awt.*;
import java.awt.image.BufferedImage;
@ -34,8 +34,7 @@ import org.springframework.web.multipart.MultipartFile;
import io.github.pixee.security.Filenames;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.service.CustomPDFDocumentFactory;
import stirling.software.common.service.CustomPDFDocumentFactory;
@Slf4j
public class PdfUtils {
@ -85,7 +84,7 @@ public class PdfUtils {
public static boolean hasImages(PDDocument document, String pagesToCheck) throws IOException {
String[] pageOrderArr = pagesToCheck.split(",");
List<Integer> pageList =
GeneralUtils.parsePageList(pageOrderArr, document.getNumberOfPages());
GeneralUtil.parsePageList(pageOrderArr, document.getNumberOfPages());
for (int pageNumber : pageList) {
PDPage page = document.getPage(pageNumber);
@ -101,7 +100,7 @@ public class PdfUtils {
throws IOException {
String[] pageOrderArr = pageNumbersToCheck.split(",");
List<Integer> pageList =
GeneralUtils.parsePageList(pageOrderArr, document.getNumberOfPages());
GeneralUtil.parsePageList(pageOrderArr, document.getNumberOfPages());
for (int pageNumber : pageList) {
PDPage page = document.getPage(pageNumber);

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.utils;
package stirling.software.common.util;
import java.io.BufferedReader;
import java.io.File;
@ -17,7 +17,7 @@ import io.github.pixee.security.BoundedLineReader;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.model.ApplicationProperties;
import stirling.software.common.model.ApplicationProperties;
@Slf4j
public class ProcessExecutor {

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.utils;
package stirling.software.common.util;
import java.util.List;

View File

@ -1,10 +1,10 @@
package stirling.software.SPDF.utils.validation;
package stirling.software.common.util;
import java.util.Collection;
import stirling.software.common.model.oauth2.provider.Provider;
import static stirling.software.common.util.ValidationUtil.isCollectionEmpty;
import static stirling.software.common.util.ValidationUtil.isStringEmpty;
import stirling.software.SPDF.model.provider.Provider;
public class Validator {
public class ProviderUtil {
public static boolean validateProvider(Provider provider) {
if (provider == null) {
@ -25,12 +25,4 @@ public class Validator {
return true;
}
public static boolean isStringEmpty(String input) {
return input == null || input.isBlank();
}
public static boolean isCollectionEmpty(Collection<String> input) {
return input == null || input.isEmpty();
}
}

View File

@ -1,14 +1,12 @@
package stirling.software.SPDF.utils;
package stirling.software.common.util;
public class RequestUriUtils {
public class RequestUriUtil {
public static boolean isStaticResource(String requestURI) {
return isStaticResource("", requestURI);
}
public static boolean isStaticResource(String contextPath, String requestURI) {
return requestURI.startsWith(contextPath + "/css/")
|| requestURI.startsWith(contextPath + "/fonts/")
|| requestURI.startsWith(contextPath + "/js/")

View File

@ -1,9 +1,7 @@
package stirling.software.SPDF.utils;
package stirling.software.common.util;
import java.awt.*;
import javax.swing.*;
public class UIScaling {
private static final double BASE_RESOLUTION_WIDTH = 1920.0;
private static final double BASE_RESOLUTION_HEIGHT = 1080.0;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.utils;
package stirling.software.common.util;
import java.io.IOException;
import java.net.ServerSocket;

View File

@ -0,0 +1,14 @@
package stirling.software.common.util;
import java.util.Collection;
public class ValidationUtil {
public static boolean isStringEmpty(String input) {
return input == null || input.isBlank();
}
public static boolean isCollectionEmpty(Collection<String> input) {
return input == null || input.isEmpty();
}
}

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.utils;
package stirling.software.common.util;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config;
package stirling.software.common.util;
import java.io.IOException;
import java.io.StringWriter;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.utils.misc;
package stirling.software.common.util.misc;
import java.awt.*;
import java.io.ByteArrayInputStream;
@ -23,9 +23,8 @@ import org.springframework.core.io.InputStreamResource;
import org.springframework.web.multipart.MultipartFile;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.model.api.misc.HighContrastColorCombination;
import stirling.software.SPDF.model.api.misc.ReplaceAndInvert;
import stirling.software.common.model.api.misc.HighContrastColorCombination;
import stirling.software.common.model.api.misc.ReplaceAndInvert;
@Slf4j
public class CustomColorReplaceStrategy extends ReplaceAndInvertColorStrategy {

View File

@ -1,7 +1,7 @@
package stirling.software.SPDF.utils.misc;
package stirling.software.common.util.misc;
import stirling.software.SPDF.model.api.misc.HighContrastColorCombination;
import stirling.software.SPDF.model.api.misc.ReplaceAndInvert;
import stirling.software.common.model.api.misc.HighContrastColorCombination;
import stirling.software.common.model.api.misc.ReplaceAndInvert;
public class HighContrastColorReplaceDecider {

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.utils.misc;
package stirling.software.common.util.misc;
import java.awt.*;
import java.awt.image.BufferedImage;
@ -18,8 +18,7 @@ import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.springframework.core.io.InputStreamResource;
import org.springframework.web.multipart.MultipartFile;
import stirling.software.SPDF.model.api.misc.ReplaceAndInvert;
import stirling.software.common.model.api.misc.ReplaceAndInvert;
public class InvertFullColorStrategy extends ReplaceAndInvertColorStrategy {

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.utils.misc;
package stirling.software.common.util.misc;
import java.awt.geom.Rectangle2D;
import java.io.IOException;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.utils.misc;
package stirling.software.common.util.misc;
import java.io.IOException;
@ -8,8 +8,8 @@ import org.springframework.web.multipart.MultipartFile;
import lombok.Data;
import lombok.EqualsAndHashCode;
import stirling.software.SPDF.model.api.PDFFile;
import stirling.software.SPDF.model.api.misc.ReplaceAndInvert;
import stirling.software.common.model.api.PDFFile;
import stirling.software.common.model.api.misc.ReplaceAndInvert;
@Data
@EqualsAndHashCode(callSuper = true)

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.utils.propertyeditor;
package stirling.software.common.util.propertyeditor;
import java.beans.PropertyEditorSupport;
import java.util.ArrayList;
@ -9,8 +9,7 @@ import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.model.api.security.RedactionArea;
import stirling.software.common.model.api.security.RedactionArea;
@Slf4j
public class StringToArrayListPropertyEditor extends PropertyEditorSupport {
@ -26,7 +25,8 @@ public class StringToArrayListPropertyEditor extends PropertyEditorSupport {
try {
objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
TypeReference<ArrayList<RedactionArea>> typeRef =
new TypeReference<ArrayList<RedactionArea>>() {};
new TypeReference<>() {
};
List<RedactionArea> list = objectMapper.readValue(text, typeRef);
setValue(list);
} catch (Exception e) {

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.utils.propertyeditor;
package stirling.software.common.util.propertyeditor;
import java.beans.PropertyEditorSupport;
import java.util.HashMap;
@ -15,7 +15,7 @@ public class StringToMapPropertyEditor extends PropertyEditorSupport {
public void setAsText(String text) throws IllegalArgumentException {
try {
TypeReference<HashMap<String, String>> typeRef =
new TypeReference<HashMap<String, String>>() {};
new TypeReference<>() {};
Map<String, String> map = objectMapper.readValue(text, typeRef);
setValue(map);
} catch (Exception e) {

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.utils;
package stirling.software.common.util;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.utils;
package stirling.software.common.util;
import static org.junit.jupiter.api.Assertions.assertEquals;
@ -7,6 +7,8 @@ import java.time.LocalDateTime;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import stirling.software.common.model.FileInfo;
public class FileInfoTest {
@ParameterizedTest(name = "{index}: fileSize={0}")

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.utils;
package stirling.software.common.util;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
@ -8,7 +8,7 @@ import java.io.IOException;
import org.junit.jupiter.api.Test;
import stirling.software.SPDF.model.api.converters.HTMLToPdfRequest;
import stirling.software.common.model.api.converters.HTMLToPdfRequest;
public class FileToPdfTest {

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.utils;
package stirling.software.common.util;
import static org.junit.jupiter.api.Assertions.assertEquals;
@ -6,152 +6,152 @@ import java.util.List;
import org.junit.jupiter.api.Test;
public class GeneralUtilsTest {
public class GeneralUtilTest {
@Test
void testParsePageListWithAll() {
List<Integer> result = GeneralUtils.parsePageList(new String[] {"all"}, 5, false);
List<Integer> result = GeneralUtil.parsePageList(new String[] {"all"}, 5, false);
assertEquals(List.of(0, 1, 2, 3, 4), result, "'All' keyword should return all pages.");
}
@Test
void testParsePageListWithAllOneBased() {
List<Integer> result = GeneralUtils.parsePageList(new String[] {"all"}, 5, true);
List<Integer> result = GeneralUtil.parsePageList(new String[] {"all"}, 5, true);
assertEquals(List.of(1, 2, 3, 4, 5), result, "'All' keyword should return all pages.");
}
@Test
void nFunc() {
List<Integer> result = GeneralUtils.parsePageList(new String[] {"n"}, 5, true);
List<Integer> result = GeneralUtil.parsePageList(new String[] {"n"}, 5, true);
assertEquals(List.of(1, 2, 3, 4, 5), result, "'n' keyword should return all pages.");
}
@Test
void nFuncAdvanced() {
List<Integer> result = GeneralUtils.parsePageList(new String[] {"4n"}, 9, true);
List<Integer> result = GeneralUtil.parsePageList(new String[] {"4n"}, 9, true);
// skip 0 as not valid
assertEquals(List.of(4, 8), result, "'All' keyword should return all pages.");
}
@Test
void nFuncAdvancedZero() {
List<Integer> result = GeneralUtils.parsePageList(new String[] {"4n"}, 9, false);
List<Integer> result = GeneralUtil.parsePageList(new String[] {"4n"}, 9, false);
// skip 0 as not valid
assertEquals(List.of(3, 7), result, "'All' keyword should return all pages.");
}
@Test
void nFuncAdvanced2() {
List<Integer> result = GeneralUtils.parsePageList(new String[] {"4n-1"}, 9, true);
List<Integer> result = GeneralUtil.parsePageList(new String[] {"4n-1"}, 9, true);
// skip -1 as not valid
assertEquals(List.of(3, 7), result, "4n-1 should do (0-1), (4-1), (8-1)");
}
@Test
void nFuncAdvanced3() {
List<Integer> result = GeneralUtils.parsePageList(new String[] {"4n+1"}, 9, true);
List<Integer> result = GeneralUtil.parsePageList(new String[] {"4n+1"}, 9, true);
assertEquals(List.of(5, 9), result, "'All' keyword should return all pages.");
}
@Test
void nFunc_spaces() {
List<Integer> result = GeneralUtils.parsePageList(new String[] {"n + 1"}, 9, true);
List<Integer> result = GeneralUtil.parsePageList(new String[] {"n + 1"}, 9, true);
assertEquals(List.of(2, 3, 4, 5, 6, 7, 8, 9), result);
}
@Test
void nFunc_consecutive_Ns_nnn() {
List<Integer> result = GeneralUtils.parsePageList(new String[] {"nnn"}, 9, true);
List<Integer> result = GeneralUtil.parsePageList(new String[] {"nnn"}, 9, true);
assertEquals(List.of(1, 8), result);
}
@Test
void nFunc_consecutive_Ns_nn() {
List<Integer> result = GeneralUtils.parsePageList(new String[] {"nn"}, 9, true);
List<Integer> result = GeneralUtil.parsePageList(new String[] {"nn"}, 9, true);
assertEquals(List.of(1, 4, 9), result);
}
@Test
void nFunc_opening_closing_round_brackets() {
List<Integer> result = GeneralUtils.parsePageList(new String[] {"(n-1)(n-2)"}, 9, true);
List<Integer> result = GeneralUtil.parsePageList(new String[] {"(n-1)(n-2)"}, 9, true);
assertEquals(List.of(2, 6), result);
}
@Test
void nFunc_opening_round_brackets() {
List<Integer> result = GeneralUtils.parsePageList(new String[] {"2(n-1)"}, 9, true);
List<Integer> result = GeneralUtil.parsePageList(new String[] {"2(n-1)"}, 9, true);
assertEquals(List.of(2, 4, 6, 8), result);
}
@Test
void nFunc_opening_round_brackets_n() {
List<Integer> result = GeneralUtils.parsePageList(new String[] {"n(n-1)"}, 9, true);
List<Integer> result = GeneralUtil.parsePageList(new String[] {"n(n-1)"}, 9, true);
assertEquals(List.of(2, 6), result);
}
@Test
void nFunc_closing_round_brackets() {
List<Integer> result = GeneralUtils.parsePageList(new String[] {"(n-1)2"}, 9, true);
List<Integer> result = GeneralUtil.parsePageList(new String[] {"(n-1)2"}, 9, true);
assertEquals(List.of(2, 4, 6, 8), result);
}
@Test
void nFunc_closing_round_brackets_n() {
List<Integer> result = GeneralUtils.parsePageList(new String[] {"(n-1)n"}, 9, true);
List<Integer> result = GeneralUtil.parsePageList(new String[] {"(n-1)n"}, 9, true);
assertEquals(List.of(2, 6), result);
}
@Test
void nFunc_function_surrounded_with_brackets() {
List<Integer> result = GeneralUtils.parsePageList(new String[] {"(n-1)"}, 9, true);
List<Integer> result = GeneralUtil.parsePageList(new String[] {"(n-1)"}, 9, true);
assertEquals(List.of(1, 2, 3, 4, 5, 6, 7, 8), result);
}
@Test
void nFuncAdvanced4() {
List<Integer> result = GeneralUtils.parsePageList(new String[] {"3+2n"}, 9, true);
List<Integer> result = GeneralUtil.parsePageList(new String[] {"3+2n"}, 9, true);
assertEquals(List.of(5, 7, 9), result, "'All' keyword should return all pages.");
}
@Test
void nFuncAdvancedZerobased() {
List<Integer> result = GeneralUtils.parsePageList(new String[] {"4n"}, 9, false);
List<Integer> result = GeneralUtil.parsePageList(new String[] {"4n"}, 9, false);
assertEquals(List.of(3, 7), result, "'All' keyword should return all pages.");
}
@Test
void nFuncAdvanced2Zerobased() {
List<Integer> result = GeneralUtils.parsePageList(new String[] {"4n-1"}, 9, false);
List<Integer> result = GeneralUtil.parsePageList(new String[] {"4n-1"}, 9, false);
assertEquals(List.of(2, 6), result, "'All' keyword should return all pages.");
}
@Test
void testParsePageListWithRangeOneBasedOutput() {
List<Integer> result = GeneralUtils.parsePageList(new String[] {"1-3"}, 5, true);
List<Integer> result = GeneralUtil.parsePageList(new String[] {"1-3"}, 5, true);
assertEquals(List.of(1, 2, 3), result, "Range should be parsed correctly.");
}
@Test
void testParsePageListWithRangeZeroBaseOutput() {
List<Integer> result = GeneralUtils.parsePageList(new String[] {"1-3"}, 5, false);
List<Integer> result = GeneralUtil.parsePageList(new String[] {"1-3"}, 5, false);
assertEquals(List.of(0, 1, 2), result, "Range should be parsed correctly.");
}
@Test
void testParsePageListWithRangeOneBasedOutputFull() {
List<Integer> result = GeneralUtils.parsePageList(new String[] {"1,3,7-8"}, 8, true);
List<Integer> result = GeneralUtil.parsePageList(new String[] {"1,3,7-8"}, 8, true);
assertEquals(List.of(1, 3, 7, 8), result, "Range should be parsed correctly.");
}
@Test
void testParsePageListWithRangeOneBasedOutputFullOutOfRange() {
List<Integer> result = GeneralUtils.parsePageList(new String[] {"1,3,7-8"}, 5, true);
List<Integer> result = GeneralUtil.parsePageList(new String[] {"1,3,7-8"}, 5, true);
assertEquals(List.of(1, 3), result, "Range should be parsed correctly.");
}
@Test
void testParsePageListWithRangeZeroBaseOutputFull() {
List<Integer> result = GeneralUtils.parsePageList(new String[] {"1,3,7-8"}, 8, false);
List<Integer> result = GeneralUtil.parsePageList(new String[] {"1,3,7-8"}, 8, false);
assertEquals(List.of(0, 2, 6, 7), result, "Range should be parsed correctly.");
}
}

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.utils;
package stirling.software.common.util;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.utils;
package stirling.software.common.util;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.utils;
package stirling.software.common.util;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.utils;
package stirling.software.common.util;
import static org.junit.jupiter.api.Assertions.assertEquals;

View File

@ -1,27 +1,22 @@
package stirling.software.SPDF.utils.validation;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
package stirling.software.common.util;
import java.util.List;
import java.util.stream.Stream;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.mockito.junit.jupiter.MockitoExtension;
import stirling.software.SPDF.model.UsernameAttribute;
import stirling.software.SPDF.model.provider.GitHubProvider;
import stirling.software.SPDF.model.provider.GoogleProvider;
import stirling.software.SPDF.model.provider.Provider;
import stirling.software.common.model.enumeration.UsernameAttribute;
import stirling.software.common.model.oauth2.provider.GitHubProvider;
import stirling.software.common.model.oauth2.provider.GoogleProvider;
import stirling.software.common.model.oauth2.provider.Provider;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
class ValidatorTest {
class ProviderUtilTest {
@Test
void testSuccessfulValidation() {
@ -31,13 +26,13 @@ class ValidatorTest {
when(provider.getClientSecret()).thenReturn("clientSecret");
when(provider.getScopes()).thenReturn(List.of("read:user"));
assertTrue(Validator.validateProvider(provider));
Assertions.assertTrue(ProviderUtil.validateProvider(provider));
}
@ParameterizedTest
@MethodSource("providerParams")
void testUnsuccessfulValidation(Provider provider) {
assertFalse(Validator.validateProvider(provider));
Assertions.assertFalse(ProviderUtil.validateProvider(provider));
}
public static Stream<Arguments> providerParams() {

View File

@ -0,0 +1,26 @@
package stirling.software.common.util;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.Test;
public class RequestUriUtilTest {
@Test
public void testIsStaticResource() {
assertTrue(RequestUriUtil.isStaticResource("/css/styles.css"));
assertTrue(RequestUriUtil.isStaticResource("/js/script.js"));
assertTrue(RequestUriUtil.isStaticResource("/images/logo.png"));
assertTrue(RequestUriUtil.isStaticResource("/public/index.html"));
assertTrue(RequestUriUtil.isStaticResource("/pdfjs/pdf.worker.js"));
assertTrue(RequestUriUtil.isStaticResource("/api/v1/info/status"));
assertTrue(RequestUriUtil.isStaticResource("/some-path/icon.svg"));
assertFalse(RequestUriUtil.isStaticResource("/api/v1/users"));
assertFalse(RequestUriUtil.isStaticResource("/api/v1/orders"));
assertFalse(RequestUriUtil.isStaticResource("/"));
assertTrue(RequestUriUtil.isStaticResource("/login"));
assertFalse(RequestUriUtil.isStaticResource("/register"));
assertFalse(RequestUriUtil.isStaticResource("/api/v1/products"));
}
}

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.utils;
package stirling.software.common.util;
import static org.junit.jupiter.api.Assertions.assertEquals;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.utils;
package stirling.software.common.util;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;

View File

@ -20,7 +20,7 @@ services:
- ./stirling/latest/logs:/logs:rw
- ../testing/allEndpointsRemovedSettings.yml:/configs/settings.yml:rw
environment:
DOCKER_ENABLE_SECURITY: "true"
ADDITIONAL_FEATURES: "true"
SECURITY_ENABLELOGIN: "false"
PUID: 1002
PGID: 1002

View File

@ -20,7 +20,7 @@ services:
- ./stirling/latest/config:/configs:rw
- ./stirling/latest/logs:/logs:rw
environment:
DOCKER_ENABLE_SECURITY: "true"
ADDITIONAL_FEATURES: "true"
SECURITY_ENABLELOGIN: "false"
PUID: 1002
PGID: 1002

View File

@ -18,7 +18,7 @@ services:
- ./stirling/latest/config:/configs:rw
- ./stirling/latest/logs:/logs:rw
environment:
DOCKER_ENABLE_SECURITY: "true"
ADDITIONAL_FEATURES: "true"
SECURITY_ENABLELOGIN: "false"
PUID: 1002
PGID: 1002

Some files were not shown because too many files have changed in this diff Show More