Compare commits

...

33 Commits

Author SHA1 Message Date
Dario Ghunney Ware
0523470c35 resolving conflicts 2025-06-05 18:13:52 +01:00
Dario Ghunney Ware
b570a5ad14 clean up 2025-06-05 18:13:52 +01:00
Dario Ghunney Ware
58c1bccfcc renamed module: enterprise > proprietary
updating paths (DOCKER_SECURITY_ENABLE > ADDITIONAL_FEATURES)
2025-06-05 18:13:50 +01:00
Dario Ghunney Ware
75ec5e00ab moving security package and relevant files over to proprietary 2025-06-05 18:13:01 +01:00
DarioGii
b500236733 removing DOCKER_ENABLE_SECURITY flag
moving security package and relevant files over to proprietary
2025-06-05 18:13:01 +01:00
Dario Ghunney Ware
66cebc7f9f updating LICENSE-proprietary 2025-06-05 18:13:01 +01:00
Dario Ghunney Ware
f9df824705 creating new proprietary module 2025-06-05 18:12:59 +01:00
stirlingbot[bot]
47ac4a4730
🌐 Sync Translations + Update README Progress Table (#3644)
### Description of Changes

This Pull Request was automatically generated to synchronize updates to
translation files and documentation. Below are the details of the
changes made:

#### **1. Synchronization of Translation Files**
- Updated translation files (`messages_*.properties`) to reflect changes
in the reference file `messages_en_GB.properties`.
- Ensured consistency and synchronization across all supported language
files.
- Highlighted any missing or incomplete translations.

#### **2. Update README.md**
- Generated the translation progress table in `README.md`.
- Added a summary of the current translation status for all supported
languages.
- Included up-to-date statistics on translation coverage.

#### **Why these changes are necessary**
- Keeps translation files aligned with the latest reference updates.
- Ensures the documentation reflects the current translation progress.

---

Auto-generated by [create-pull-request][1].

[1]: https://github.com/peter-evans/create-pull-request

Co-authored-by: stirlingbot[bot] <195170888+stirlingbot[bot]@users.noreply.github.com>
2025-06-05 16:53:36 +01:00
Balázs Szücs
2d5091c8e3
Updated Hungarian translation for new features: fake-scan, get-info, and for some misc front-end updates. (#3646)
# Changes 

Updated the hungarian translation for get-info, fake-scan and misc.

---

## Checklist

### General

- [x] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [x] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md)
(if applicable)
- [x] I have performed a self-review of my own code
- [x] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [x] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

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

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-06-05 16:52:08 +01:00
stirlingbot[bot]
b78d05e8ee
Update 3rd Party Licenses (#3647)
Auto-generated by stirlingbot[bot]

Signed-off-by: stirlingbot[bot] <stirlingbot[bot]@users.noreply.github.com>
Co-authored-by: stirlingbot[bot] <195170888+stirlingbot[bot]@users.noreply.github.com>
2025-06-05 16:51:16 +01:00
Anthony Stirling
4272dfa240
Merge pull request #3619 from Stirling-Tools/proprietary_module
Proprietary module
2025-06-05 12:29:02 +01:00
Dario Ghunney Ware
0006a77b5d updated comments in DeveloperGuide.md 2025-06-05 11:02:56 +01:00
Dario Ghunney Ware
6cef1fac5f renamed proprietary/LICENSE and fixed main LICENSE 2025-06-05 11:02:56 +01:00
Dario Ghunney Ware
2df70daf16 updated jpackage 2025-06-05 11:02:56 +01:00
Dario Ghunney Ware
a0cb56ab0c correcting security logic
This Pull Request was automatically generated to synchronize updates to
translation files and documentation. Below are the details of the
changes made:

- Updated translation files (`messages_*.properties`) to reflect changes
in the reference file `messages_en_GB.properties`.
- Ensured consistency and synchronization across all supported language
files.
- Highlighted any missing or incomplete translations.

- Generated the translation progress table in `README.md`.
- Added a summary of the current translation status for all supported
languages.
- Included up-to-date statistics on translation coverage.

- Keeps translation files aligned with the latest reference updates.
- Ensures the documentation reflects the current translation progress.

---

Auto-generated by [create-pull-request][1].

[1]: https://github.com/peter-evans/create-pull-request

Co-authored-by: stirlingbot[bot] <195170888+stirlingbot[bot]@users.noreply.github.com>

Update messages_de_DE.properties (#3618)

Please provide a summary of the changes, including:

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

Closes #(issue_number)

---

- [x] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [x] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md)
(if applicable)
- [x] I have performed a self-review of my own code
- [x] My changes generate no new warnings

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

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

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

Fix error display for Split by Chapter (#3621)

- throw `IllegalArgumentException` when bookmark level is invalid or
when a PDF has no outline
- rely on global error handling so frontend shows the message

- `./gradlew build`

------
https://chatgpt.com/codex/tasks/task_b_683dc51dd31083288be3f9892889fa59

🌐 Sync Translations + Update README Progress Table (#3638)

This Pull Request was automatically generated to synchronize updates to
translation files and documentation. Below are the details of the
changes made:

- Updated translation files (`messages_*.properties`) to reflect changes
in the reference file `messages_en_GB.properties`.
- Ensured consistency and synchronization across all supported language
files.
- Highlighted any missing or incomplete translations.

- Generated the translation progress table in `README.md`.
- Added a summary of the current translation status for all supported
languages.
- Included up-to-date statistics on translation coverage.

- Keeps translation files aligned with the latest reference updates.
- Ensures the documentation reflects the current translation progress.

---

Auto-generated by [create-pull-request][1].

[1]: https://github.com/peter-evans/create-pull-request

Co-authored-by: stirlingbot[bot] <195170888+stirlingbot[bot]@users.noreply.github.com>

GetInfo summary #2388 (#3585)

Please provide a summary of the changes, including:

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

Closes #(issue_number)

---

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

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

Co-authored-by: a <a>

🌐 Sync Translations + Update README Progress Table (#3639)

This Pull Request was automatically generated to synchronize updates to
translation files and documentation. Below are the details of the
changes made:

- Updated translation files (`messages_*.properties`) to reflect changes
in the reference file `messages_en_GB.properties`.
- Ensured consistency and synchronization across all supported language
files.
- Highlighted any missing or incomplete translations.

- Generated the translation progress table in `README.md`.
- Added a summary of the current translation status for all supported
languages.
- Included up-to-date statistics on translation coverage.

- Keeps translation files aligned with the latest reference updates.
- Ensures the documentation reflects the current translation progress.

---

Auto-generated by [create-pull-request][1].

[1]: https://github.com/peter-evans/create-pull-request

---------

Co-authored-by: stirlingbot[bot] <195170888+stirlingbot[bot]@users.noreply.github.com>

clean up

🌐 Sync Translations + Update README Progress Table (#3639)

This Pull Request was automatically generated to synchronize updates to
translation files and documentation. Below are the details of the
changes made:

- Updated translation files (`messages_*.properties`) to reflect changes
in the reference file `messages_en_GB.properties`.
- Ensured consistency and synchronization across all supported language
files.
- Highlighted any missing or incomplete translations.

- Generated the translation progress table in `README.md`.
- Added a summary of the current translation status for all supported
languages.
- Included up-to-date statistics on translation coverage.

- Keeps translation files aligned with the latest reference updates.
- Ensures the documentation reflects the current translation progress.

---

Auto-generated by [create-pull-request][1].

[1]: https://github.com/peter-evans/create-pull-request

---------

Co-authored-by: stirlingbot[bot] <195170888+stirlingbot[bot]@users.noreply.github.com>

ADDITIONAL_FEATURES_OFF > ADDITIONAL_FEATURES

renamed flag

renamed flag in workflows
2025-06-05 11:02:53 +01:00
Dario Ghunney Ware
febe67eac8 moving security package and relevant files over to proprietary 2025-06-05 11:02:40 +01:00
DarioGii
41cd7d8f47 removing DOCKER_ENABLE_SECURITY flag 2025-06-05 11:02:40 +01:00
Dario Ghunney Ware
5a50947e5e updated build.gradle 2025-06-05 11:02:40 +01:00
Dario Ghunney Ware
392a10a8c1 added back activeSecurity bean 2025-06-05 11:02:40 +01:00
Dario Ghunney Ware
275039015d updating LICENSE-proprietary 2025-06-05 11:02:40 +01:00
Dario Ghunney Ware
149fe8755d DOCKER_ENABLE_SECURITY > ADDITIONAL_FEATURES_OFF 2025-06-05 11:02:40 +01:00
Dario Ghunney Ware
2b9a3924d3 added proprietary module to base packages for scanning
clean up
2025-06-05 11:02:40 +01:00
Dario Ghunney Ware
6d8173b021 updating license 2025-06-05 11:02:40 +01:00
Dario Ghunney Ware
58937a6e91 moving security package and relevant files over to proprietary 2025-06-05 11:02:40 +01:00
Dario Ghunney Ware
3d312c2fd1 creating new proprietary module 2025-06-05 11:02:40 +01:00
Dario Ghunney Ware
6aaedf52ea wip - making db and sessions conditional 2025-06-05 11:02:13 +01:00
albanobattistella
3591ef5cb7
Update messages_it_IT.properties (#3641)
# Description of Changes

Please provide a summary of the changes, including:

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

Closes #(issue_number)

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#6-testing)
for more details.
2025-06-05 10:35:14 +01:00
stirlingbot[bot]
02799b8aa5
🌐 Sync Translations + Update README Progress Table (#3639)
### Description of Changes

This Pull Request was automatically generated to synchronize updates to
translation files and documentation. Below are the details of the
changes made:

#### **1. Synchronization of Translation Files**
- Updated translation files (`messages_*.properties`) to reflect changes
in the reference file `messages_en_GB.properties`.
- Ensured consistency and synchronization across all supported language
files.
- Highlighted any missing or incomplete translations.

#### **2. Update README.md**
- Generated the translation progress table in `README.md`.
- Added a summary of the current translation status for all supported
languages.
- Included up-to-date statistics on translation coverage.

#### **Why these changes are necessary**
- Keeps translation files aligned with the latest reference updates.
- Ensures the documentation reflects the current translation progress.

---

Auto-generated by [create-pull-request][1].

[1]: https://github.com/peter-evans/create-pull-request

---------

Co-authored-by: stirlingbot[bot] <195170888+stirlingbot[bot]@users.noreply.github.com>
2025-06-03 19:42:12 +01:00
Anthony Stirling
28a259ec95
GetInfo summary #2388 (#3585)
# Description of Changes

Please provide a summary of the changes, including:

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

Closes #(issue_number)

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

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

Co-authored-by: a <a>
2025-06-03 17:48:17 +01:00
stirlingbot[bot]
9cc4f14465
🌐 Sync Translations + Update README Progress Table (#3638)
### Description of Changes

This Pull Request was automatically generated to synchronize updates to
translation files and documentation. Below are the details of the
changes made:

#### **1. Synchronization of Translation Files**
- Updated translation files (`messages_*.properties`) to reflect changes
in the reference file `messages_en_GB.properties`.
- Ensured consistency and synchronization across all supported language
files.
- Highlighted any missing or incomplete translations.

#### **2. Update README.md**
- Generated the translation progress table in `README.md`.
- Added a summary of the current translation status for all supported
languages.
- Included up-to-date statistics on translation coverage.

#### **Why these changes are necessary**
- Keeps translation files aligned with the latest reference updates.
- Ensures the documentation reflects the current translation progress.

---

Auto-generated by [create-pull-request][1].

[1]: https://github.com/peter-evans/create-pull-request

Co-authored-by: stirlingbot[bot] <195170888+stirlingbot[bot]@users.noreply.github.com>
2025-06-03 17:46:14 +01:00
Anthony Stirling
5d9d8a5625
Fix error display for Split by Chapter (#3621)
## Summary
- throw `IllegalArgumentException` when bookmark level is invalid or
when a PDF has no outline
- rely on global error handling so frontend shows the message

## Testing
- `./gradlew build`


------
https://chatgpt.com/codex/tasks/task_b_683dc51dd31083288be3f9892889fa59
2025-06-03 17:44:35 +01:00
Ludy
a8c6a8342c
Update messages_de_DE.properties (#3618)
# Description of Changes

Please provide a summary of the changes, including:

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

Closes #(issue_number)

---

## Checklist

### General

- [x] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [x] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md)
(if applicable)
- [x] I have performed a self-review of my own code
- [x] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

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

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-06-03 17:43:51 +01:00
stirlingbot[bot]
9697d1abe1
🌐 Sync Translations + Update README Progress Table (#3635)
### Description of Changes

This Pull Request was automatically generated to synchronize updates to
translation files and documentation. Below are the details of the
changes made:

#### **1. Synchronization of Translation Files**
- Updated translation files (`messages_*.properties`) to reflect changes
in the reference file `messages_en_GB.properties`.
- Ensured consistency and synchronization across all supported language
files.
- Highlighted any missing or incomplete translations.

#### **2. Update README.md**
- Generated the translation progress table in `README.md`.
- Added a summary of the current translation status for all supported
languages.
- Included up-to-date statistics on translation coverage.

#### **Why these changes are necessary**
- Keeps translation files aligned with the latest reference updates.
- Ensures the documentation reflects the current translation progress.

---

Auto-generated by [create-pull-request][1].

[1]: https://github.com/peter-evans/create-pull-request

Co-authored-by: stirlingbot[bot] <195170888+stirlingbot[bot]@users.noreply.github.com>
2025-06-03 17:43:28 +01:00
1589 changed files with 152347 additions and 116252 deletions

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

@ -37,7 +37,7 @@ jobs:
pr_repository: ${{ steps.get-pr-info.outputs.repository }}
pr_ref: ${{ steps.get-pr-info.outputs.ref }}
comment_id: ${{ github.event.comment.id }}
enable_security: ${{ steps.check-security-flag.outputs.enable_security }}
disable_security: ${{ steps.check-security-flag.outputs.disable_security }}
steps:
- name: Harden Runner
@ -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:
@ -92,10 +92,10 @@ jobs:
run: |
if [[ "$COMMENT_BODY" == *"security"* ]] || [[ "$COMMENT_BODY" == *"login"* ]]; then
echo "Security flags detected in comment"
echo "enable_security=true" >> $GITHUB_OUTPUT
echo "disable_security=false" >> $GITHUB_OUTPUT
else
echo "No security flags detected in comment"
echo "enable_security=false" >> $GITHUB_OUTPUT
echo "disable_security=true" >> $GITHUB_OUTPUT
fi
- name: Add 'in_progress' reaction to comment
@ -155,10 +155,10 @@ jobs:
- name: Run Gradle Command
run: |
if [ "${{ needs.check-comment.outputs.enable_security }}" == "true" ]; then
export DOCKER_ENABLE_SECURITY=true
if [ "${{ needs.check-comment.outputs.disable_security }}" == "true" ]; then
export DISABLE_ADDITIONAL_FEATURES=true
else
export DOCKER_ENABLE_SECURITY=false
export DISABLE_ADDITIONAL_FEATURES=false
fi
./gradlew clean build
env:
@ -199,7 +199,7 @@ jobs:
id: deploy
run: |
# Set security settings based on flags
if [ "${{ needs.check-comment.outputs.enable_security }}" == "true" ]; then
if [ "${{ needs.check-comment.outputs.disable_security }}" == "false" ]; then
DOCKER_SECURITY="true"
LOGIN_SECURITY="true"
SECURITY_STATUS="🔒 Security Enabled"
@ -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}"
DISABLE_ADDITIONAL_FEATURES: "${DOCKER_SECURITY}"
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
DISABLE_ADDITIONAL_FEATURES: true
- name: Build with Gradle and with spring security
run: ./gradlew clean build
env:
DOCKER_ENABLE_SECURITY: true
DISABLE_ADDITIONAL_FEATURES: false
- 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
@ -61,7 +61,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
@ -141,12 +141,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,
});
@ -158,7 +158,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

@ -57,11 +57,11 @@ 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: Commit changes
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

@ -48,11 +48,11 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
enable_security: [true, false]
disable_security: [true, false]
include:
- enable_security: true
- disable_security: false
file_suffix: "-with-login"
- enable_security: false
- disable_security: true
file_suffix: ""
steps:
- name: Harden Runner
@ -72,10 +72,10 @@ jobs:
with:
gradle-version: 8.14
- name: Generate jar (With Security=${{ matrix.enable_security }})
- name: Generate jar (Disable Security=${{ matrix.disable_security }})
run: ./gradlew clean createExe
env:
DOCKER_ENABLE_SECURITY: ${{ matrix.enable_security }}
DISABLE_ADDITIONAL_FEATURES: ${{ matrix.disable_security }}
STIRLING_PDF_DESKTOP_UI: false
- name: Rename binaries
@ -98,11 +98,11 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
enable_security: [true, false]
disable_security: [true, false]
include:
- enable_security: true
- disable_security: false
file_suffix: "with-login-"
- enable_security: false
- disable_security: true
file_suffix: ""
steps:
- name: Harden Runner
@ -171,7 +171,7 @@ jobs:
- name: Build Installer
run: ./gradlew build jpackage -x test --info
env:
DOCKER_ENABLE_SECURITY: false
DISABLE_ADDITIONAL_FEATURES: true
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
DISABLE_ADDITIONAL_FEATURES: true
STIRLING_PDF_DESKTOP_UI: false
- name: Install cosign

View File

@ -13,11 +13,11 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
enable_security: [true, false]
disable_security: [true, false]
include:
- enable_security: true
- disable_security: false
file_suffix: "-with-login"
- enable_security: false
- disable_security: true
file_suffix: ""
outputs:
version: ${{ steps.versionNumber.outputs.versionNumber }}
@ -39,10 +39,10 @@ jobs:
with:
gradle-version: 8.14
- name: Generate jar (With Security=${{ matrix.enable_security }})
- name: Generate jar (Disable Security=${{ matrix.disable_security }})
run: ./gradlew clean createExe
env:
DOCKER_ENABLE_SECURITY: ${{ matrix.enable_security }}
DISABLE_ADDITIONAL_FEATURES: ${{ matrix.disable_security }}
STIRLING_PDF_DESKTOP_UI: false
- name: Get version number
@ -75,11 +75,11 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
enable_security: [true, false]
disable_security: [true, false]
include:
- enable_security: true
- disable_security: false
file_suffix: "-with-login"
- enable_security: false
- disable_security: true
file_suffix: ""
steps:
- name: Harden Runner
@ -153,11 +153,11 @@ jobs:
contents: write
strategy:
matrix:
enable_security: [true, false]
disable_security: [true, false]
include:
- enable_security: true
- disable_security: false
file_suffix: "-with-login"
- enable_security: false
- disable_security: true
file_suffix: ""
steps:
- name: Harden Runner

View File

@ -33,7 +33,7 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
DOCKER_ENABLE_SECURITY: true
DISABLE_ADDITIONAL_FEATURES: false
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:
@ -41,11 +41,11 @@ 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: Commit translation files
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 detected"
- name: Install dependencies
@ -101,4 +101,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
DISABLE_ADDITIONAL_FEATURES: true
- 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"
DISABLE_ADDITIONAL_FEATURES: "true"
SECURITY_ENABLELOGIN: "false"
SYSTEM_DEFAULTLOCALE: en-GB
UI_APPNAME: "Stirling-PDF Test"

4
.gitignore vendored
View File

@ -13,6 +13,7 @@ local.properties
.recommenders
.classpath
.project
*.local.json
version.properties
#### Stirling-PDF Files ###
@ -124,6 +125,9 @@ SwaggerDoc.json
*.rar
*.db
/build
/stirling-pdf/build
/common/build
/proprietary/build
# Byte-compiled / optimized / DLL files
__pycache__/

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.26.0
hooks:

View File

@ -50,8 +50,10 @@
".vscode/",
"bin/",
"common/bin/",
"proprietary/bin/",
"build/",
"common/build/",
"proprietary/build/",
"configs/",
"customFiles/",
"docs/",
@ -66,6 +68,7 @@
".gitattributes",
".gitignore",
"common/.gitignore",
"proprietary/.gitignore",
".pre-commit-config.yaml",
],
// Enables signature help in Java.

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 DISABLE_ADDITIONAL_FEATURES=false to your system and/or IDE build/run step.
## 4. Project Structure
@ -114,9 +114,9 @@ Stirling-PDF offers several Docker versions:
Stirling-PDF provides several example Docker Compose files in the `exampleYmlFiles` directory, such as:
- `docker-compose-latest.yml`: Latest version without security features
- `docker-compose-latest-security.yml`: Latest version with security features enabled
- `docker-compose-latest-fat-security.yml`: Fat version with security features enabled
- `docker-compose-latest.yml`: Latest version without login and security features
- `docker-compose-latest-security.yml`: Latest version with login and security features enabled
- `docker-compose-latest-fat-security.yml`: Fat version with login and security features enabled
These files provide pre-configured setups for different scenarios. For example, here's a snippet from `docker-compose-latest-security.yml`:
@ -141,7 +141,7 @@ services:
- /stirling/latest/config:/configs:rw
- /stirling/latest/logs:/logs:rw
environment:
DOCKER_ENABLE_SECURITY: "true"
DISABLE_ADDITIONAL_FEATURES: "false"
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 DISABLE_ADDITIONAL_FEATURES=true # or false for to enable login and security features for builds
```
2. Build the project with Gradle:
@ -193,10 +193,10 @@ Stirling-PDF uses different Docker images for various configurations. The build
docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t stirlingtools/stirling-pdf:latest-ultra-lite -f ./Dockerfile.ultra-lite .
```
For the fat version (with security enabled):
For the fat version (with login and security features enabled):
```bash
export DOCKER_ENABLE_SECURITY=true
export DISABLE_ADDITIONAL_FEATURES=false
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,7 +384,7 @@ 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")`.
@ -411,7 +411,7 @@ 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
@ -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,7 +507,7 @@ 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
@ -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.22.0@sha256:8a1f59ffb675680d47db6337b49d22281a139e9d709335b492be02
# 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 DISABLE_ADDITIONAL_FEATURES=true \
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

@ -5,6 +5,8 @@ COPY build.gradle .
COPY settings.gradle .
COPY gradlew .
COPY gradle gradle/
COPY common/build.gradle common/.
COPY proprietary/build.gradle proprietary/.
RUN ./gradlew build -x spotlessApply -x spotlessCheck -x test -x sonarqube || return 0
# Set the working directory
@ -13,8 +15,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 DISABLE_ADDITIONAL_FEATURES=false
RUN DISABLE_ADDITIONAL_FEATURES=false \
STIRLING_PDF_DESKTOP_UI=false \
./gradlew clean build -x spotlessApply -x spotlessCheck -x test -x sonarqube
@ -24,13 +26,13 @@ FROM alpine:3.22.0@sha256:8a1f59ffb675680d47db6337b49d22281a139e9d709335b492be02
# 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 DISABLE_ADDITIONAL_FEATURES=true \
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.22.0@sha256:8a1f59ffb675680d47db6337b49d22281a139e9d709335b492be02
ARG VERSION_TAG
# Set Environment Variables
ENV DOCKER_ENABLE_SECURITY=false \
ENV DISABLE_ADDITIONAL_FEATURES=true \
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

@ -1,6 +1,13 @@
MIT License
Copyright (c) 2024 Stirling Tools
Copyright (c) 2025 Stirling PDF Inc.
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

View File

@ -116,47 +116,47 @@ Stirling-PDF currently supports 40 languages!
| Language | Progress |
| -------------------------------------------- | -------------------------------------- |
| Arabic (العربية) (ar_AR) | ![73%](https://geps.dev/progress/73) |
| Azerbaijani (Azərbaycan Dili) (az_AZ) | ![74%](https://geps.dev/progress/74) |
| Basque (Euskara) (eu_ES) | ![43%](https://geps.dev/progress/43) |
| Bulgarian (Български) (bg_BG) | ![81%](https://geps.dev/progress/81) |
| Catalan (Català) (ca_CA) | ![81%](https://geps.dev/progress/81) |
| Croatian (Hrvatski) (hr_HR) | ![72%](https://geps.dev/progress/72) |
| Czech (Česky) (cs_CZ) | ![83%](https://geps.dev/progress/83) |
| Danish (Dansk) (da_DK) | ![73%](https://geps.dev/progress/73) |
| Dutch (Nederlands) (nl_NL) | ![71%](https://geps.dev/progress/71) |
| Arabic (العربية) (ar_AR) | ![72%](https://geps.dev/progress/72) |
| Azerbaijani (Azərbaycan Dili) (az_AZ) | ![72%](https://geps.dev/progress/72) |
| Basque (Euskara) (eu_ES) | ![42%](https://geps.dev/progress/42) |
| Bulgarian (Български) (bg_BG) | ![80%](https://geps.dev/progress/80) |
| Catalan (Català) (ca_CA) | ![79%](https://geps.dev/progress/79) |
| Croatian (Hrvatski) (hr_HR) | ![71%](https://geps.dev/progress/71) |
| Czech (Česky) (cs_CZ) | ![82%](https://geps.dev/progress/82) |
| Danish (Dansk) (da_DK) | ![72%](https://geps.dev/progress/72) |
| Dutch (Nederlands) (nl_NL) | ![70%](https://geps.dev/progress/70) |
| English (English) (en_GB) | ![100%](https://geps.dev/progress/100) |
| English (US) (en_US) | ![100%](https://geps.dev/progress/100) |
| French (Français) (fr_FR) | ![82%](https://geps.dev/progress/82) |
| German (Deutsch) (de_DE) | ![89%](https://geps.dev/progress/89) |
| Greek (Ελληνικά) (el_GR) | ![80%](https://geps.dev/progress/80) |
| Hindi (हिंदी) (hi_IN) | ![80%](https://geps.dev/progress/80) |
| Hungarian (Magyar) (hu_HU) | ![87%](https://geps.dev/progress/87) |
| Indonesian (Bahasa Indonesia) (id_ID) | ![74%](https://geps.dev/progress/74) |
| Irish (Gaeilge) (ga_IE) | ![81%](https://geps.dev/progress/81) |
| Italian (Italiano) (it_IT) | ![95%](https://geps.dev/progress/95) |
| Japanese (日本語) (ja_JP) | ![82%](https://geps.dev/progress/82) |
| Korean (한국어) (ko_KR) | ![80%](https://geps.dev/progress/80) |
| Norwegian (Norsk) (no_NB) | ![78%](https://geps.dev/progress/78) |
| Persian (فارسی) (fa_IR) | ![76%](https://geps.dev/progress/76) |
| Polish (Polski) (pl_PL) | ![86%](https://geps.dev/progress/86) |
| Portuguese (Português) (pt_PT) | ![82%](https://geps.dev/progress/82) |
| Portuguese Brazilian (Português) (pt_BR) | ![87%](https://geps.dev/progress/87) |
| Romanian (Română) (ro_RO) | ![68%](https://geps.dev/progress/68) |
| Russian (Русский) (ru_RU) | ![87%](https://geps.dev/progress/87) |
| Serbian Latin alphabet (Srpski) (sr_LATN_RS) | ![52%](https://geps.dev/progress/52) |
| Simplified Chinese (简体中文) (zh_CN) | ![86%](https://geps.dev/progress/86) |
| Slovakian (Slovensky) (sk_SK) | ![61%](https://geps.dev/progress/61) |
| Slovenian (Slovenščina) (sl_SI) | ![85%](https://geps.dev/progress/85) |
| Spanish (Español) (es_ES) | ![88%](https://geps.dev/progress/88) |
| Swedish (Svenska) (sv_SE) | ![78%](https://geps.dev/progress/78) |
| Thai (ไทย) (th_TH) | ![70%](https://geps.dev/progress/70) |
| Tibetan (བོད་ཡིག་) (bo_CN) | ![77%](https://geps.dev/progress/77) |
| Traditional Chinese (繁體中文) (zh_TW) | ![87%](https://geps.dev/progress/87) |
| Turkish (Türkçe) (tr_TR) | ![87%](https://geps.dev/progress/87) |
| Ukrainian (Українська) (uk_UA) | ![87%](https://geps.dev/progress/87) |
| Vietnamese (Tiếng Việt) (vi_VN) | ![68%](https://geps.dev/progress/68) |
| Malayalam (മലയാളം) (ml_IN) | ![87%](https://geps.dev/progress/87) |
| French (Français) (fr_FR) | ![81%](https://geps.dev/progress/81) |
| German (Deutsch) (de_DE) | ![98%](https://geps.dev/progress/98) |
| Greek (Ελληνικά) (el_GR) | ![79%](https://geps.dev/progress/79) |
| Hindi (हिंदी) (hi_IN) | ![78%](https://geps.dev/progress/78) |
| Hungarian (Magyar) (hu_HU) | ![90%](https://geps.dev/progress/90) |
| Indonesian (Bahasa Indonesia) (id_ID) | ![72%](https://geps.dev/progress/72) |
| Irish (Gaeilge) (ga_IE) | ![80%](https://geps.dev/progress/80) |
| Italian (Italiano) (it_IT) | ![98%](https://geps.dev/progress/98) |
| Japanese (日本語) (ja_JP) | ![80%](https://geps.dev/progress/80) |
| Korean (한국어) (ko_KR) | ![79%](https://geps.dev/progress/79) |
| Norwegian (Norsk) (no_NB) | ![77%](https://geps.dev/progress/77) |
| Persian (فارسی) (fa_IR) | ![75%](https://geps.dev/progress/75) |
| Polish (Polski) (pl_PL) | ![84%](https://geps.dev/progress/84) |
| Portuguese (Português) (pt_PT) | ![80%](https://geps.dev/progress/80) |
| Portuguese Brazilian (Português) (pt_BR) | ![85%](https://geps.dev/progress/85) |
| Romanian (Română) (ro_RO) | ![67%](https://geps.dev/progress/67) |
| Russian (Русский) (ru_RU) | ![85%](https://geps.dev/progress/85) |
| Serbian Latin alphabet (Srpski) (sr_LATN_RS) | ![51%](https://geps.dev/progress/51) |
| Simplified Chinese (简体中文) (zh_CN) | ![85%](https://geps.dev/progress/85) |
| Slovakian (Slovensky) (sk_SK) | ![60%](https://geps.dev/progress/60) |
| Slovenian (Slovenščina) (sl_SI) | ![83%](https://geps.dev/progress/83) |
| Spanish (Español) (es_ES) | ![87%](https://geps.dev/progress/87) |
| Swedish (Svenska) (sv_SE) | ![76%](https://geps.dev/progress/76) |
| Thai (ไทย) (th_TH) | ![69%](https://geps.dev/progress/69) |
| Tibetan (བོད་ཡིག་) (bo_CN) | ![76%](https://geps.dev/progress/76) |
| Traditional Chinese (繁體中文) (zh_TW) | ![85%](https://geps.dev/progress/85) |
| Turkish (Türkçe) (tr_TR) | ![86%](https://geps.dev/progress/86) |
| Ukrainian (Українська) (uk_UA) | ![85%](https://geps.dev/progress/85) |
| Vietnamese (Tiếng Việt) (vi_VN) | ![67%](https://geps.dev/progress/67) |
| Malayalam (മലയാളം) (ml_IN) | ![85%](https://geps.dev/progress/85) |
## Stirling PDF Enterprise

View File

@ -9,7 +9,7 @@ plugins {
id "com.diffplug.spotless" version "7.0.4"
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.2.0.5505"
}
@ -26,21 +26,124 @@ ext {
bouncycastleVersion = "1.80"
springSecuritySamlVersion = "6.5.0"
openSamlVersion = "4.3.2"
commonmarkVersion = "0.24.0"
tempJrePath = null
}
group = "stirling.software"
version = "0.46.2"
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" }
bootJar {
enabled = false
}
sourceSets {
main {
java {
if (System.getenv('DOCKER_ENABLE_SECURITY') == 'false' || System.getenv('DISABLE_ADDITIONAL_FEATURES') == 'true'
|| (project.hasProperty('DISABLE_ADDITIONAL_FEATURES')
&& System.getProperty('DISABLE_ADDITIONAL_FEATURES') == 'true')) {
exclude 'stirling/software/proprietary/security/**'
}
if (System.getenv('STIRLING_PDF_DESKTOP_UI') == 'false') {
exclude 'stirling/software/SPDF/UI/impl/**'
}
}
}
test {
java {
if (System.getenv('DOCKER_ENABLE_SECURITY') == 'false' || System.getenv('DISABLE_ADDITIONAL_FEATURES') == 'true'
|| (project.hasProperty('DISABLE_ADDITIONAL_FEATURES')
&& System.getProperty('DISABLE_ADDITIONAL_FEATURES') == 'true')) {
exclude 'stirling/software/proprietary/security/**'
}
if (System.getenv('STIRLING_PDF_DESKTOP_UI') == 'false') {
exclude 'stirling/software/SPDF/UI/impl/**'
}
}
}
}
allprojects {
group = 'stirling.software'
version = '0.46.2'
configurations.configureEach {
exclude group: 'commons-logging', module: 'commons-logging'
exclude group: "org.springframework.boot", module: "spring-boot-starter-tomcat"
}
}
subprojects {
apply plugin: 'java'
apply plugin: 'java-library'
apply plugin: 'com.diffplug.spotless'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
java {
// 17 is lowest but we support and recommend 21
sourceCompatibility = JavaVersion.VERSION_17
}
bootJar {
enabled = false
}
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-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 {
@ -51,29 +154,14 @@ licenseReport {
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('DOCKER_ENABLE_SECURITY') == 'false' || System.getenv('DISABLE_ADDITIONAL_FEATURES') == 'true'
|| (project.hasProperty('DISABLE_ADDITIONAL_FEATURES')
&& System.getProperty('DISABLE_ADDITIONAL_FEATURES') == 'true')) {
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/**'
}
}
@ -81,15 +169,14 @@ sourceSets {
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('DOCKER_ENABLE_SECURITY') == 'false' || System.getenv('DISABLE_ADDITIONAL_FEATURES') == 'true'
|| (project.hasProperty('DISABLE_ADDITIONAL_FEATURES')
&& System.getProperty('DISABLE_ADDITIONAL_FEATURES') == 'true')) {
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/**'
}
}
}
@ -115,10 +202,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"
@ -126,6 +212,7 @@ jpackage {
javaOptions = [
"-DBROWSER_OPEN=true",
"-DSTIRLING_PDF_DESKTOP_UI=true",
"-DDISABLE_ADDITIONAL_FEATURES=false",
"-Djava.awt.headless=false",
"-Dapple.awt.UIElement=true",
"--add-opens=java.base/java.lang=ALL-UNNAMED",
@ -156,10 +243,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"
@ -181,7 +268,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
@ -217,10 +304,15 @@ jpackage {
]*/
// Add copyright and license information
copyright = "Copyright © 2024 Stirling Software"
copyright = "Copyright © 2025 Stirling PDF Inc."
licenseFile = "LICENSE"
}
//tasks.wrapper {
// gradleVersion = "8.14"
// distributionType = Wrapper.DistributionType.ALL
//}
tasks.register('jpackageMacX64') {
group = 'distribution'
description = 'Packages app for MacOS x86_64'
@ -253,7 +345,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)',
@ -262,6 +354,7 @@ tasks.register('jpackageMacX64') {
// Java options
'--java-options', '-DBROWSER_OPEN=true',
'--java-options', '-DSTIRLING_PDF_DESKTOP_UI=true',
'--java-options', '-DDISABLE_ADDITIONAL_FEATURES=false',
'--java-options', '-Djava.awt.headless=false',
'--java-options', '-Dapple.awt.UIElement=true',
'--java-options', '--add-opens=java.base/java.lang=ALL-UNNAMED',
@ -290,8 +383,6 @@ tasks.register('jpackageMacX64') {
}
}
//jpackage.finalizedBy(jpackageMacX64)
tasks.register('downloadTempJre') {
group = 'distribution'
description = 'Downloads and extracts a temporary JRE'
@ -303,18 +394,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) {
@ -340,7 +431,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"
@ -351,7 +442,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') {
@ -376,6 +467,7 @@ spotless {
java {
target sourceSets.main.allJava
target project(':common').sourceSets.main.allJava
target project(':proprietary').sourceSets.main.allJava
googleJavaFormat("1.27.0").aosp().reorderImports(false)
@ -392,188 +484,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 {
implementation project(':common')
//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:135.0.20"
implementation "org.openjfx:javafx-controls:21"
implementation "org.openjfx:javafx-swing:21"
}
//security updates
implementation "org.springframework:spring-webmvc:6.2.7"
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 '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.5.0"
implementation "org.springframework:spring-jdbc:6.2.7"
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.6"
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"
exclude group: "commons-io", module: "commons-io"
}
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.15.0"
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"
// Mockito (core)
testImplementation 'org.mockito:mockito-core:5.18.0'
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
@ -584,25 +500,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())
}

View File

@ -1,52 +1,14 @@
plugins {
id 'java-library'
id 'io.spring.dependency-management' version '1.1.7'
}
group = 'stirling.software'
version = '0.46.2'
ext {
lombokVersion = "1.18.38"
}
java {
sourceCompatibility = JavaVersion.VERSION_17
}
repositories {
mavenCentral()
}
configurations.all {
exclude group: 'commons-logging', module: 'commons-logging'
exclude group: "org.springframework.boot", module: "spring-boot-starter-tomcat"
}
dependencyManagement {
imports {
mavenBom 'org.springframework.boot:spring-boot-dependencies:3.5.0'
}
}
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.1.0'
implementation 'org.snakeyaml:snakeyaml-engine:2.9'
implementation "org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.8"
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'
api 'org.springframework.boot:spring-boot-starter-web'
api 'org.springframework.boot:spring-boot-starter-thymeleaf'
api 'com.googlecode.owasp-java-html-sanitizer:owasp-java-html-sanitizer:20240325.1'
api 'com.fathzer:javaluator:3.0.6'
api 'com.posthog.java:posthog:1.2.0'
api 'org.apache.commons:commons-lang3:3.17.0'
api 'com.drewnoakes:metadata-extractor:2.19.0' // Image metadata extractor
api 'com.vladsch.flexmark:flexmark-html2md-converter:0.64.8'
api "org.apache.pdfbox:pdfbox:$pdfboxVersion"
api 'jakarta.servlet:jakarta.servlet-api:6.1.0'
api 'org.snakeyaml:snakeyaml-engine:2.9'
api "org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.8"
}

View File

@ -1,5 +1,7 @@
package stirling.software.common.configuration;
import io.github.pixee.security.SystemCommand;
import jakarta.annotation.PostConstruct;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
@ -10,6 +12,7 @@ import java.util.Properties;
import java.util.function.Predicate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
@ -146,10 +149,24 @@ public class AppConfig {
}
}
@ConditionalOnMissingClass("stirling.software.SPDF.config.security.SecurityConfiguration")
@Bean(name = "activeSecurity")
public boolean activeSecurity() {
String disableAdditionalFeatures = env.getProperty("DISABLE_ADDITIONAL_FEATURES");
if (disableAdditionalFeatures != null) {
// DISABLE_ADDITIONAL_FEATURES=true means security OFF, so return false
// DISABLE_ADDITIONAL_FEATURES=false means security ON, so return true
return !Boolean.parseBoolean(disableAdditionalFeatures);
}
return env.getProperty("DOCKER_ENABLE_SECURITY", Boolean.class, true);
}
@Bean(name = "missingActiveSecurity")
@ConditionalOnMissingClass(
"stirling.software.proprietary.security.configuration.SecurityConfiguration")
public boolean missingActiveSecurity() {
return false;
return true;
}
@Bean(name = "directoryFilter")

View File

@ -344,10 +344,10 @@ public class ApplicationProperties {
@Override
public String toString() {
return """
Driver {
driverName='%s'
}
"""
Driver {
driverName='%s'
}
"""
.formatted(driverName);
}
}

View File

@ -208,7 +208,7 @@ public class PostHogService {
// New environment variables
dockerMetrics.put("version_tag", System.getenv("VERSION_TAG"));
dockerMetrics.put("without_enhanced_features", System.getenv("WITHOUT_ENHANCED_FEATURES"));
dockerMetrics.put("additional_features_off", System.getenv("ADDITIONAL_FEATURES_OFF"));
dockerMetrics.put("fat_docker", System.getenv("FAT_DOCKER"));
return dockerMetrics;

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,5 +1,14 @@
package stirling.software.common.util;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.Arrays;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import stirling.software.common.util.ProcessExecutor.ProcessExecutorResult;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
@ -10,18 +19,6 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.Arrays;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import stirling.software.common.util.ProcessExecutor.ProcessExecutorResult;
class CheckProgramInstallTest {
private MockedStatic<ProcessExecutor> mockProcessExecutor;

View File

@ -19,7 +19,6 @@ import org.junit.jupiter.api.io.TempDir;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import stirling.software.common.configuration.RuntimePathConfig;
@ExtendWith(MockitoExtension.class)

View File

@ -1,10 +1,7 @@
package stirling.software.common.util;
import static org.mockito.Mockito.*;
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;
@ -12,11 +9,13 @@ 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.common.model.enumeration.UsernameAttribute;
import stirling.software.common.model.oauth2.GitHubProvider;
import stirling.software.common.model.oauth2.GoogleProvider;
import stirling.software.common.model.oauth2.Provider;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
class ProviderUtilsTest {
@ -29,19 +28,19 @@ class ProviderUtilsTest {
when(provider.getClientSecret()).thenReturn("clientSecret");
when(provider.getScopes()).thenReturn(List.of("read:user"));
Assertions.assertTrue(ProviderUtils.validateProvider(provider));
assertTrue(ProviderUtils.validateProvider(provider));
}
@ParameterizedTest
@MethodSource("providerParams")
void testUnsuccessfulValidation(Provider provider) {
Assertions.assertFalse(ProviderUtils.validateProvider(provider));
assertFalse(ProviderUtils.validateProvider(provider));
}
public static Stream<Arguments> providerParams() {
Provider generic = null;
var google =
new GoogleProvider(null, "clientSecret", List.of("scope"), UsernameAttribute.EMAIL);
new GoogleProvider(null, "clientSecret", List.of("scope"), UsernameAttribute.EMAIL);
var github = new GitHubProvider("clientId", "", List.of("scope"), UsernameAttribute.LOGIN);
return Stream.of(Arguments.of(generic), Arguments.of(google), Arguments.of(github));

View File

@ -1,12 +1,10 @@
package stirling.software.common.util.misc;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import org.junit.jupiter.api.Test;
import stirling.software.common.model.api.misc.HighContrastColorCombination;
import stirling.software.common.model.api.misc.ReplaceAndInvert;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
class HighContrastColorReplaceDeciderTest {

View File

@ -26,7 +26,6 @@ import org.junit.jupiter.api.Test;
import org.springframework.core.io.InputStreamResource;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;
import stirling.software.common.model.api.misc.ReplaceAndInvert;
class InvertFullColorStrategyTest {

View File

@ -9,7 +9,6 @@ import org.junit.jupiter.api.Test;
import org.springframework.core.io.InputStreamResource;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;
import stirling.software.common.model.api.misc.ReplaceAndInvert;
class ReplaceAndInvertColorStrategyTest {

View File

@ -1,17 +1,14 @@
package stirling.software.common.util.propertyeditor;
import java.util.List;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import stirling.software.common.model.api.security.RedactionArea;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.List;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import stirling.software.common.model.api.security.RedactionArea;
class StringToArrayListPropertyEditorTest {
private StringToArrayListPropertyEditor editor;

View File

@ -20,7 +20,7 @@ services:
- ./stirling/latest/logs:/logs:rw
- ../testing/allEndpointsRemovedSettings.yml:/configs/settings.yml:rw
environment:
DOCKER_ENABLE_SECURITY: "true"
DISABLE_ADDITIONAL_FEATURES: "false"
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"
DISABLE_ADDITIONAL_FEATURES: "false"
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"
DISABLE_ADDITIONAL_FEATURES: "false"
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"
DISABLE_ADDITIONAL_FEATURES: "false"
SECURITY_ENABLELOGIN: "true"
SECURITY_OAUTH2_ENABLED: "true"
SECURITY_OAUTH2_AUTOCREATEUSER: "true" # This is set to true to allow auto-creation of non-existing users in Stirling-PDF

View File

@ -18,7 +18,7 @@ services:
- ./stirling/latest/config:/configs:rw
- ./stirling/latest/logs:/logs:rw
environment:
DOCKER_ENABLE_SECURITY: "true"
DISABLE_ADDITIONAL_FEATURES: "false"
SECURITY_ENABLELOGIN: "true"
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"
DISABLE_ADDITIONAL_FEATURES: "false"
SECURITY_ENABLELOGIN: "true"
SYSTEM_DEFAULTLOCALE: en-US
UI_APPNAME: Stirling-PDF-Lite

View File

@ -17,7 +17,7 @@ services:
- /stirling/latest/config:/configs:rw
- /stirling/latest/logs:/logs:rw
environment:
DOCKER_ENABLE_SECURITY: "false"
DISABLE_ADDITIONAL_FEATURES: "true"
SECURITY_ENABLELOGIN: "false"
SYSTEM_DEFAULTLOCALE: en-US
UI_APPNAME: Stirling-PDF-Ultra-lite

View File

@ -18,7 +18,7 @@ services:
- /stirling/latest/config:/configs:rw
- /stirling/latest/logs:/logs:rw
environment:
DOCKER_ENABLE_SECURITY: "false"
DISABLE_ADDITIONAL_FEATURES: "true"
SECURITY_ENABLELOGIN: "false"
LANGS: "en_GB,en_US,ar_AR,de_DE,fr_FR,es_ES,zh_CN,zh_TW,ca_CA,it_IT,sv_SE,pl_PL,ro_RO,ko_KR,pt_BR,ru_RU,el_GR,hi_IN,hu_HU,tr_TR,id_ID"
SYSTEM_DEFAULTLOCALE: en-US

View File

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

196
proprietary/.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

51
proprietary/LICENSE Normal file
View File

@ -0,0 +1,51 @@
Stirling PDF User License
Copyright (c) 2025 Stirling PDF Inc.
License Scope & Usage Rights
Production use of the Stirling PDF Software is only permitted with a valid Stirling PDF User License.
For purposes of this license, “the Software” refers to the Stirling PDF application and any associated documentation files
provided by Stirling PDF Inc. You or your organization may not use the Software in production, at scale, or for business-critical
processes unless you have agreed to, and remain in compliance with, the Stirling PDF Subscription Terms of Service
(https://www.stirlingpdf.com/terms) or another valid agreement with Stirling PDF, and hold an active User License subscription
covering the appropriate number of licensed users.
Trial and Minimal Use
You may use the Software without a paid subscription for the sole purposes of internal trial, evaluation, or minimal use, provided that:
* Use is limited to the capabilities and restrictions defined by the Software itself;
* You do not copy, distribute, sublicense, reverse-engineer, or use the Software in client-facing or commercial contexts.
Continued use beyond this scope requires a valid Stirling PDF User License.
Modifications and Derivative Works
You may modify the Software only for development or internal testing purposes. Any such modifications or derivative works:
* May not be deployed in production environments without a valid User License;
* May not be distributed or sublicensed;
* Remain the intellectual property of Stirling PDF and/or its licensors;
* May only be used, copied, or exploited in accordance with the terms of a valid Stirling PDF User License subscription.
Prohibited Actions
Unless explicitly permitted by a paid license or separate agreement, you may not:
* Use the Software in production environments;
* Copy, merge, distribute, sublicense, or sell the Software;
* Remove or alter any licensing or copyright notices;
* Circumvent access restrictions or licensing requirements.
Third-Party Components
The Stirling PDF Software may include components subject to separate open source licenses. Such components remain governed by
their original license terms as provided by their respective owners.
Disclaimer
THE SOFTWARE IS PROVIDED “AS IS,” WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF, OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

37
proprietary/build.gradle Normal file
View File

@ -0,0 +1,37 @@
repositories {
maven { url = "https://build.shibboleth.net/maven/releases" }
}
dependencies {
implementation project(':common')
api 'org.springframework:spring-jdbc'
api 'org.springframework:spring-webmvc'
api 'org.springframework.session:spring-session-core'
api "org.springframework.security:spring-security-core:$springSecuritySamlVersion"
api "org.springframework.security:spring-security-saml2-service-provider:$springSecuritySamlVersion"
api 'org.springframework.boot:spring-boot-starter-jetty'
api 'org.springframework.boot:spring-boot-starter-security'
api 'org.springframework.boot:spring-boot-starter-data-jpa'
api 'org.springframework.boot:spring-boot-starter-oauth2-client'
api 'org.springframework.boot:spring-boot-starter-mail'
api 'io.swagger.core.v3:swagger-core-jakarta:2.2.30'
implementation 'com.bucket4j:bucket4j_jdk17-core:8.14.0'
// https://mvnrepository.com/artifact/com.bucket4j/bucket4j_jdk17
implementation 'org.bouncycastle:bcprov-jdk18on:1.80'
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5:3.1.3.RELEASE'
api 'io.micrometer:micrometer-registry-prometheus'
implementation 'com.unboundid.product.scim2:scim2-sdk-client:2.3.5'
runtimeOnly 'com.h2database:h2:2.3.232' // Don't upgrade h2database
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 'com.coveo:saml-client:5.0.0'
}
tasks.register('prepareKotlinBuildScriptModel') {}

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security;
package stirling.software.proprietary.security;
import java.io.IOException;
import java.util.Optional;
@ -17,7 +17,9 @@ import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.model.User;
import stirling.software.proprietary.security.model.User;
import stirling.software.proprietary.security.service.LoginAttemptService;
import stirling.software.proprietary.security.service.UserService;
@Slf4j
public class CustomAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security;
package stirling.software.proprietary.security;
import java.io.IOException;
@ -14,6 +14,8 @@ import jakarta.servlet.http.HttpSession;
import lombok.extern.slf4j.Slf4j;
import stirling.software.common.util.RequestUriUtils;
import stirling.software.proprietary.security.service.LoginAttemptService;
import stirling.software.proprietary.security.service.UserService;
@Slf4j
public class CustomAuthenticationSuccessHandler

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security;
package stirling.software.proprietary.security;
import java.io.IOException;
import java.security.cert.X509Certificate;
@ -22,14 +22,14 @@ import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.SPDFApplication;
import stirling.software.SPDF.config.security.saml2.CertificateUtils;
import stirling.software.SPDF.config.security.saml2.CustomSaml2AuthenticatedPrincipal;
import stirling.software.common.configuration.AppConfig;
import stirling.software.common.model.ApplicationProperties;
import stirling.software.common.model.ApplicationProperties.Security.OAUTH2;
import stirling.software.common.model.ApplicationProperties.Security.SAML2;
import stirling.software.common.model.oauth2.KeycloakProvider;
import stirling.software.common.util.UrlUtils;
import stirling.software.proprietary.security.saml2.CertificateUtils;
import stirling.software.proprietary.security.saml2.CustomSaml2AuthenticatedPrincipal;
@Slf4j
@RequiredArgsConstructor
@ -39,6 +39,8 @@ public class CustomLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
private final ApplicationProperties applicationProperties;
private final AppConfig appConfig;
@Override
public void onLogoutSuccess(
HttpServletRequest request, HttpServletResponse response, Authentication authentication)
@ -102,7 +104,7 @@ public class CustomLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
// Set service provider keys for the SamlClient
samlClient.setSPKeys(certificate, privateKey);
// Redirect to identity provider for logout
// Redirect to identity provider for logout. todo: add relay state
samlClient.redirectToIdentityProvider(response, null, nameIdValue);
} catch (Exception e) {
log.error(
@ -172,11 +174,10 @@ public class CustomLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
}
}
private static SamlClient getSamlClient(
private SamlClient getSamlClient(
String registrationId, SAML2 samlConf, List<X509Certificate> certificates)
throws SamlException {
String serverUrl =
SPDFApplication.getStaticBaseUrl() + ":" + SPDFApplication.getStaticPort();
String serverUrl = appConfig.getBaseUrl() + ":" + appConfig.getServerPort();
String relyingPartyIdentifier =
serverUrl + "/saml2/service-provider-metadata/" + registrationId;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security;
package stirling.software.proprietary.security;
import java.sql.SQLException;
import java.util.UUID;
@ -10,10 +10,11 @@ import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.interfaces.DatabaseInterface;
import stirling.software.SPDF.model.Role;
import stirling.software.common.model.ApplicationProperties;
import stirling.software.common.model.enumeration.Role;
import stirling.software.common.model.exception.UnsupportedProviderException;
import stirling.software.proprietary.security.service.DatabaseServiceInterface;
import stirling.software.proprietary.security.service.UserService;
@Slf4j
@Component
@ -24,7 +25,7 @@ public class InitialSecuritySetup {
private final ApplicationProperties applicationProperties;
private final DatabaseInterface databaseService;
private final DatabaseServiceInterface databaseService;
@PostConstruct
public void init() {

View File

@ -1,10 +1,12 @@
package stirling.software.SPDF.config.security;
package stirling.software.proprietary.security;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import lombok.RequiredArgsConstructor;
import stirling.software.proprietary.security.filter.IPRateLimitingFilter;
@Component
@RequiredArgsConstructor
public class RateLimitResetScheduler {

View File

@ -1,11 +1,15 @@
package stirling.software.SPDF.config.security.database;
package stirling.software.proprietary.security.configuration;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.boot.jdbc.DatabaseDriver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
@ -17,14 +21,14 @@ import stirling.software.common.model.exception.UnsupportedProviderException;
@Slf4j
@Getter
@Configuration
@EnableJpaRepositories(basePackages = "stirling.software.proprietary.security.database.repository")
@EntityScan({"stirling.software.proprietary.security.model"})
public class DatabaseConfig {
public final String DATASOURCE_DEFAULT_URL;
public static final String DATASOURCE_URL_TEMPLATE = "jdbc:%s://%s:%4d/%s";
public static final String DEFAULT_DRIVER = "org.h2.Driver";
public static final String DEFAULT_USERNAME = "sa";
public static final String POSTGRES_DRIVER = "org.postgresql.Driver";
private final ApplicationProperties.Datasource datasource;
private final boolean runningProOrHigher;
@ -54,19 +58,32 @@ public class DatabaseConfig {
public DataSource dataSource() throws UnsupportedProviderException {
DataSourceBuilder<?> dataSourceBuilder = DataSourceBuilder.create();
if (!runningProOrHigher) {
if (!runningProOrHigher || !datasource.isEnableCustomDatabase()) {
return useDefaultDataSource(dataSourceBuilder);
}
if (!datasource.isEnableCustomDatabase()) {
return useDefaultDataSource(dataSourceBuilder);
}
return useCustomDataSource(dataSourceBuilder);
}
private DataSource useDefaultDataSource(DataSourceBuilder<?> dataSourceBuilder) {
log.info("Using default H2 database");
dataSourceBuilder
.url(DATASOURCE_DEFAULT_URL)
.driverClassName(DatabaseDriver.H2.getDriverClassName())
.username(DEFAULT_USERNAME);
return dataSourceBuilder.build();
}
@ConditionalOnBooleanProperty(name = "premium.enabled")
private DataSource useCustomDataSource(DataSourceBuilder<?> dataSourceBuilder)
throws UnsupportedProviderException {
log.info("Using custom database configuration");
if (!datasource.getCustomDatabaseUrl().isBlank()) {
if (datasource.getCustomDatabaseUrl().contains("postgresql")) {
dataSourceBuilder.driverClassName(POSTGRES_DRIVER);
dataSourceBuilder.driverClassName(DatabaseDriver.POSTGRESQL.getDriverClassName());
}
dataSourceBuilder.url(datasource.getCustomDatabaseUrl());
@ -85,15 +102,6 @@ public class DatabaseConfig {
return dataSourceBuilder.build();
}
private DataSource useDefaultDataSource(DataSourceBuilder<?> dataSourceBuilder) {
log.info("Using default H2 database");
dataSourceBuilder.url(DATASOURCE_DEFAULT_URL);
dataSourceBuilder.username(DEFAULT_USERNAME);
return dataSourceBuilder.build();
}
/**
* Generate the URL the <code>DataSource</code> will use to connect to the database
*
@ -123,11 +131,11 @@ public class DatabaseConfig {
switch (driver) {
case H2 -> {
log.debug("H2 driver selected");
return DEFAULT_DRIVER;
return DatabaseDriver.H2.getDriverClassName();
}
case POSTGRESQL -> {
log.debug("Postgres driver selected");
return POSTGRES_DRIVER;
return DatabaseDriver.POSTGRESQL.getDriverClassName();
}
default -> {
log.warn("{} driver selected", driverName);

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security.mail;
package stirling.software.proprietary.security.configuration;
import java.util.Properties;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security;
package stirling.software.proprietary.security.configuration;
import java.util.Optional;
@ -30,22 +30,32 @@ import org.springframework.security.web.servlet.util.matcher.PathPatternRequestM
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.security.oauth2.CustomOAuth2AuthenticationFailureHandler;
import stirling.software.SPDF.config.security.oauth2.CustomOAuth2AuthenticationSuccessHandler;
import stirling.software.SPDF.config.security.oauth2.CustomOAuth2UserService;
import stirling.software.SPDF.config.security.saml2.CustomSaml2AuthenticationFailureHandler;
import stirling.software.SPDF.config.security.saml2.CustomSaml2AuthenticationSuccessHandler;
import stirling.software.SPDF.config.security.saml2.CustomSaml2ResponseAuthenticationConverter;
import stirling.software.SPDF.config.security.session.SessionPersistentRegistry;
import stirling.software.SPDF.model.User;
import stirling.software.SPDF.repository.JPATokenRepositoryImpl;
import stirling.software.SPDF.repository.PersistentLoginRepository;
import stirling.software.common.configuration.AppConfig;
import stirling.software.common.model.ApplicationProperties;
import stirling.software.proprietary.security.CustomAuthenticationFailureHandler;
import stirling.software.proprietary.security.CustomAuthenticationSuccessHandler;
import stirling.software.proprietary.security.CustomLogoutSuccessHandler;
import stirling.software.proprietary.security.database.repository.JPATokenRepositoryImpl;
import stirling.software.proprietary.security.database.repository.PersistentLoginRepository;
import stirling.software.proprietary.security.filter.FirstLoginFilter;
import stirling.software.proprietary.security.filter.IPRateLimitingFilter;
import stirling.software.proprietary.security.filter.UserAuthenticationFilter;
import stirling.software.proprietary.security.model.User;
import stirling.software.proprietary.security.oauth2.CustomOAuth2AuthenticationFailureHandler;
import stirling.software.proprietary.security.oauth2.CustomOAuth2AuthenticationSuccessHandler;
import stirling.software.proprietary.security.saml2.CustomSaml2AuthenticationFailureHandler;
import stirling.software.proprietary.security.saml2.CustomSaml2AuthenticationSuccessHandler;
import stirling.software.proprietary.security.saml2.CustomSaml2ResponseAuthenticationConverter;
import stirling.software.proprietary.security.service.CustomOAuth2UserService;
import stirling.software.proprietary.security.service.CustomUserDetailsService;
import stirling.software.proprietary.security.service.LoginAttemptService;
import stirling.software.proprietary.security.service.UserService;
import stirling.software.proprietary.security.session.SessionPersistentRegistry;
@Slf4j
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
@Slf4j
@DependsOn("runningProOrHigher")
public class SecurityConfiguration {
@ -55,6 +65,7 @@ public class SecurityConfiguration {
private final boolean runningProOrHigher;
private final ApplicationProperties applicationProperties;
private final AppConfig appConfig;
private final UserAuthenticationFilter userAuthenticationFilter;
private final LoginAttemptService loginAttemptService;
private final FirstLoginFilter firstLoginFilter;
@ -70,6 +81,7 @@ public class SecurityConfiguration {
@Lazy UserService userService,
@Qualifier("loginEnabled") boolean loginEnabledValue,
@Qualifier("runningProOrHigher") boolean runningProOrHigher,
AppConfig appConfig,
ApplicationProperties applicationProperties,
UserAuthenticationFilter userAuthenticationFilter,
LoginAttemptService loginAttemptService,
@ -84,6 +96,7 @@ public class SecurityConfiguration {
this.userService = userService;
this.loginEnabledValue = loginEnabledValue;
this.runningProOrHigher = runningProOrHigher;
this.appConfig = appConfig;
this.applicationProperties = applicationProperties;
this.userAuthenticationFilter = userAuthenticationFilter;
this.loginAttemptService = loginAttemptService;
@ -161,7 +174,8 @@ public class SecurityConfiguration {
PathPatternRequestMatcher.withDefaults()
.matcher("/logout"))
.logoutSuccessHandler(
new CustomLogoutSuccessHandler(applicationProperties))
new CustomLogoutSuccessHandler(
applicationProperties, appConfig))
.clearAuthentication(true)
.invalidateHttpSession(true)
.deleteCookies("JSESSIONID", "remember-me"));
@ -229,13 +243,12 @@ public class SecurityConfiguration {
http.oauth2Login(
oauth2 ->
oauth2.loginPage("/oauth2")
.
/*
This Custom handler is used to check if the OAUTH2 user trying to log in, already exists in the database.
If user exists, login proceeds as usual. If user does not exist, then it is auto-created but only if 'OAUTH2AutoCreateUser'
is set as true, else login fails with an error message advising the same.
*/
successHandler(
.successHandler(
new CustomOAuth2AuthenticationSuccessHandler(
loginAttemptService,
applicationProperties,
@ -287,15 +300,14 @@ public class SecurityConfiguration {
});
}
} else {
log.debug("SAML 2 login is not enabled. Using default.");
log.debug("Login is not enabled.");
http.authorizeHttpRequests(authz -> authz.anyRequest().permitAll());
}
return http.build();
}
public DaoAuthenticationProvider daoAuthenticationProvider() {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setUserDetailsService(userDetailsService);
DaoAuthenticationProvider provider = new DaoAuthenticationProvider(userDetailsService);
provider.setPasswordEncoder(passwordEncoder());
return provider;
}
@ -311,9 +323,4 @@ public class SecurityConfiguration {
public PersistentTokenRepository persistentTokenRepository() {
return new JPATokenRepositoryImpl(persistentLoginRepository);
}
@Bean
public boolean activeSecurity() {
return true;
}
}

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.controller.api;
package stirling.software.proprietary.security.controller.api;
import java.io.IOException;
import java.io.InputStream;
@ -27,7 +27,8 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.security.database.DatabaseService;
import stirling.software.proprietary.security.database.H2SQLCondition;
import stirling.software.proprietary.security.service.DatabaseService;
@Slf4j
@Controller

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.controller.api;
package stirling.software.proprietary.security.controller.api;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.http.HttpStatus;
@ -18,8 +18,8 @@ import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.security.mail.EmailService;
import stirling.software.SPDF.model.api.Email;
import stirling.software.proprietary.security.model.api.Email;
import stirling.software.proprietary.security.service.EmailService;
/**
* Controller for handling email-related API requests. This controller exposes an endpoint for

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.controller.api;
package stirling.software.proprietary.security.controller.api;
import java.io.IOException;
import java.security.Principal;
@ -29,15 +29,15 @@ import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.security.UserService;
import stirling.software.SPDF.config.security.saml2.CustomSaml2AuthenticatedPrincipal;
import stirling.software.SPDF.config.security.session.SessionPersistentRegistry;
import stirling.software.SPDF.model.AuthenticationType;
import stirling.software.SPDF.model.Role;
import stirling.software.SPDF.model.User;
import stirling.software.SPDF.model.api.user.UsernameAndPass;
import stirling.software.common.model.ApplicationProperties;
import stirling.software.common.model.enumeration.Role;
import stirling.software.common.model.exception.UnsupportedProviderException;
import stirling.software.proprietary.security.model.AuthenticationType;
import stirling.software.proprietary.security.model.User;
import stirling.software.proprietary.security.model.api.user.UsernameAndPass;
import stirling.software.proprietary.security.saml2.CustomSaml2AuthenticatedPrincipal;
import stirling.software.proprietary.security.service.UserService;
import stirling.software.proprietary.security.session.SessionPersistentRegistry;
@Controller
@Tag(name = "User", description = "User APIs")

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.controller.web;
package stirling.software.proprietary.security.controller.web;
import static stirling.software.common.util.ProviderUtils.validateProvider;
@ -29,21 +29,21 @@ import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.security.saml2.CustomSaml2AuthenticatedPrincipal;
import stirling.software.SPDF.config.security.session.SessionPersistentRegistry;
import stirling.software.SPDF.model.Authority;
import stirling.software.SPDF.model.Role;
import stirling.software.SPDF.model.SessionEntity;
import stirling.software.SPDF.model.User;
import stirling.software.SPDF.repository.UserRepository;
import stirling.software.common.model.ApplicationProperties;
import stirling.software.common.model.ApplicationProperties.Security;
import stirling.software.common.model.ApplicationProperties.Security.OAUTH2;
import stirling.software.common.model.ApplicationProperties.Security.OAUTH2.Client;
import stirling.software.common.model.ApplicationProperties.Security.SAML2;
import stirling.software.common.model.enumeration.Role;
import stirling.software.common.model.oauth2.GitHubProvider;
import stirling.software.common.model.oauth2.GoogleProvider;
import stirling.software.common.model.oauth2.KeycloakProvider;
import stirling.software.proprietary.security.database.repository.UserRepository;
import stirling.software.proprietary.security.model.Authority;
import stirling.software.proprietary.security.model.SessionEntity;
import stirling.software.proprietary.security.model.User;
import stirling.software.proprietary.security.saml2.CustomSaml2AuthenticatedPrincipal;
import stirling.software.proprietary.security.session.SessionPersistentRegistry;
@Controller
@Slf4j

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.controller.web;
package stirling.software.proprietary.security.controller.web;
import java.util.List;
@ -14,8 +14,8 @@ import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import stirling.software.SPDF.config.security.database.DatabaseService;
import stirling.software.common.model.FileInfo;
import stirling.software.proprietary.security.service.DatabaseService;
@Controller
@Tag(name = "Database Management", description = "Database management and security APIs")

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.controller.api;
package stirling.software.proprietary.security.database;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
@ -12,8 +12,12 @@ public class H2SQLCondition implements Condition {
Boolean.parseBoolean(
context.getEnvironment()
.getProperty("system.datasource.enableCustomDatabase"));
if (!enableCustomDatabase) {
return false;
}
String dataSourceType = context.getEnvironment().getProperty("system.datasource.type");
return !enableCustomDatabase
|| (enableCustomDatabase && "h2".equalsIgnoreCase(dataSourceType));
return "h2".equalsIgnoreCase(dataSourceType);
}
}

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security.database;
package stirling.software.proprietary.security.database;
import java.sql.SQLException;
@ -8,16 +8,15 @@ import org.springframework.stereotype.Component;
import lombok.RequiredArgsConstructor;
import stirling.software.SPDF.config.interfaces.DatabaseInterface;
import stirling.software.SPDF.controller.api.H2SQLCondition;
import stirling.software.common.model.exception.UnsupportedProviderException;
import stirling.software.proprietary.security.service.DatabaseServiceInterface;
@Component
@Conditional(H2SQLCondition.class)
@RequiredArgsConstructor
public class ScheduledTasks {
private final DatabaseInterface databaseService;
private final DatabaseServiceInterface databaseService;
@Scheduled(cron = "0 0 0 * * ?")
public void performBackup() throws SQLException, UnsupportedProviderException {

View File

@ -1,11 +1,11 @@
package stirling.software.SPDF.repository;
package stirling.software.proprietary.security.database.repository;
import java.util.Set;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import stirling.software.SPDF.model.Authority;
import stirling.software.proprietary.security.model.Authority;
@Repository
public interface AuthorityRepository extends JpaRepository<Authority, Long> {

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.repository;
package stirling.software.proprietary.security.database.repository;
import java.util.Date;
@ -6,7 +6,7 @@ import org.springframework.security.web.authentication.rememberme.PersistentReme
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import org.springframework.transaction.annotation.Transactional;
import stirling.software.SPDF.model.PersistentLogin;
import stirling.software.proprietary.security.model.PersistentLogin;
public class JPATokenRepositoryImpl implements PersistentTokenRepository {

View File

@ -1,9 +1,9 @@
package stirling.software.SPDF.repository;
package stirling.software.proprietary.security.database.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import stirling.software.SPDF.model.PersistentLogin;
import stirling.software.proprietary.security.model.PersistentLogin;
@Repository
public interface PersistentLoginRepository extends JpaRepository<PersistentLogin, String> {

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security.session;
package stirling.software.proprietary.security.database.repository;
import java.util.Date;
import java.util.List;
@ -11,7 +11,7 @@ import org.springframework.stereotype.Repository;
import jakarta.transaction.Transactional;
import stirling.software.SPDF.model.SessionEntity;
import stirling.software.proprietary.security.model.SessionEntity;
@Repository
public interface SessionRepository extends JpaRepository<SessionEntity, String> {

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.repository;
package stirling.software.proprietary.security.database.repository;
import java.util.List;
import java.util.Optional;
@ -8,7 +8,7 @@ import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import stirling.software.SPDF.model.User;
import stirling.software.proprietary.security.model.User;
@Repository
public interface UserRepository extends JpaRepository<User, Long> {

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config;
package stirling.software.proprietary.security.filter;
import java.io.IOException;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security;
package stirling.software.proprietary.security.filter;
import java.io.IOException;
import java.text.SimpleDateFormat;
@ -19,8 +19,9 @@ import jakarta.servlet.http.HttpSession;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.model.User;
import stirling.software.common.util.RequestUriUtils;
import stirling.software.proprietary.security.model.User;
import stirling.software.proprietary.security.service.UserService;
@Slf4j
@Component

View File

@ -1,10 +1,14 @@
package stirling.software.SPDF.config.security;
package stirling.software.proprietary.security.filter;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import jakarta.servlet.*;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security;
package stirling.software.proprietary.security.filter;
import java.io.IOException;
import java.util.List;
@ -24,13 +24,14 @@ import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.security.saml2.CustomSaml2AuthenticatedPrincipal;
import stirling.software.SPDF.config.security.session.SessionPersistentRegistry;
import stirling.software.SPDF.model.ApiKeyAuthenticationToken;
import stirling.software.SPDF.model.User;
import stirling.software.common.model.ApplicationProperties;
import stirling.software.common.model.ApplicationProperties.Security.OAUTH2;
import stirling.software.common.model.ApplicationProperties.Security.SAML2;
import stirling.software.proprietary.security.model.ApiKeyAuthenticationToken;
import stirling.software.proprietary.security.model.User;
import stirling.software.proprietary.security.saml2.CustomSaml2AuthenticatedPrincipal;
import stirling.software.proprietary.security.service.UserService;
import stirling.software.proprietary.security.session.SessionPersistentRegistry;
@Slf4j
@Component

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security;
package stirling.software.proprietary.security.filter;
import java.io.IOException;
import java.time.Duration;
@ -24,7 +24,7 @@ import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import stirling.software.SPDF.model.Role;
import stirling.software.common.model.enumeration.Role;
@Component
public class UserBasedRateLimitingFilter extends OncePerRequestFilter {

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.model;
package stirling.software.proprietary.security.model;
import java.util.Collection;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.model;
package stirling.software.proprietary.security.model;
public class AttemptCounter {
private int attemptCount;

View File

@ -0,0 +1,6 @@
package stirling.software.proprietary.security.model;
public enum AuthenticationType {
WEB,
SSO
}

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.model;
package stirling.software.proprietary.security.model;
import java.io.Serializable;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.model;
package stirling.software.proprietary.security.model;
import java.util.Date;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.model;
package stirling.software.proprietary.security.model;
import java.io.Serializable;
import java.util.Date;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.model;
package stirling.software.proprietary.security.model;
import java.io.Serializable;
import java.util.HashMap;
@ -15,6 +15,8 @@ import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import stirling.software.common.model.enumeration.Role;
@Entity
@Table(name = "users")
@NoArgsConstructor

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.model.api;
package stirling.software.proprietary.security.model.api;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@ -8,6 +8,8 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import stirling.software.common.model.api.GeneralFile;
@Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)

View File

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

View File

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

View File

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

View File

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

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.model.exception;
package stirling.software.proprietary.security.model.exception;
public class BackupNotFoundException extends RuntimeException {
public BackupNotFoundException(String message) {

View File

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

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security.oauth2;
package stirling.software.proprietary.security.oauth2;
import java.io.IOException;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security.oauth2;
package stirling.software.proprietary.security.oauth2;
import java.io.IOException;
import java.sql.SQLException;
@ -17,13 +17,13 @@ import jakarta.servlet.http.HttpSession;
import lombok.RequiredArgsConstructor;
import stirling.software.SPDF.config.security.LoginAttemptService;
import stirling.software.SPDF.config.security.UserService;
import stirling.software.SPDF.model.AuthenticationType;
import stirling.software.common.model.ApplicationProperties;
import stirling.software.common.model.ApplicationProperties.Security.OAUTH2;
import stirling.software.common.model.exception.UnsupportedProviderException;
import stirling.software.common.util.RequestUriUtils;
import stirling.software.proprietary.security.model.AuthenticationType;
import stirling.software.proprietary.security.service.LoginAttemptService;
import stirling.software.proprietary.security.service.UserService;
@RequiredArgsConstructor
public class CustomOAuth2AuthenticationSuccessHandler

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security.oauth2;
package stirling.software.proprietary.security.oauth2;
import static org.springframework.security.oauth2.core.AuthorizationGrantType.AUTHORIZATION_CODE;
import static stirling.software.common.util.ProviderUtils.validateProvider;
@ -10,6 +10,7 @@ import java.util.List;
import java.util.Optional;
import java.util.Set;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@ -25,9 +26,6 @@ import org.springframework.security.oauth2.core.user.OAuth2UserAuthority;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.security.UserService;
import stirling.software.SPDF.model.User;
import stirling.software.SPDF.model.exception.NoProviderFoundException;
import stirling.software.common.model.ApplicationProperties;
import stirling.software.common.model.ApplicationProperties.Security.OAUTH2;
import stirling.software.common.model.ApplicationProperties.Security.OAUTH2.Client;
@ -36,10 +34,13 @@ import stirling.software.common.model.oauth2.GitHubProvider;
import stirling.software.common.model.oauth2.GoogleProvider;
import stirling.software.common.model.oauth2.KeycloakProvider;
import stirling.software.common.model.oauth2.Provider;
import stirling.software.proprietary.security.model.User;
import stirling.software.proprietary.security.model.exception.NoProviderFoundException;
import stirling.software.proprietary.security.service.UserService;
@Slf4j
@Configuration
@ConditionalOnProperty(value = "security.oauth2.enabled", havingValue = "true")
@ConditionalOnBooleanProperty("security.oauth2.enabled")
public class OAuth2Configuration {
public static final String REDIRECT_URI_PATH = "{baseUrl}/login/oauth2/code/";
@ -54,7 +55,6 @@ public class OAuth2Configuration {
}
@Bean
@ConditionalOnProperty(value = "security.oauth2.enabled", havingValue = "true")
public ClientRegistrationRepository clientRegistrationRepository()
throws NoProviderFoundException {
List<ClientRegistration> registrations = new ArrayList<>();

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security.saml2;
package stirling.software.proprietary.security.saml2;
import java.io.ByteArrayInputStream;
import java.io.InputStreamReader;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security.saml2;
package stirling.software.proprietary.security.saml2;
import java.io.Serializable;
import java.util.List;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security.saml2;
package stirling.software.proprietary.security.saml2;
import java.io.IOException;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security.saml2;
package stirling.software.proprietary.security.saml2;
import java.io.IOException;
import java.sql.SQLException;
@ -16,13 +16,13 @@ import jakarta.servlet.http.HttpSession;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.security.LoginAttemptService;
import stirling.software.SPDF.config.security.UserService;
import stirling.software.SPDF.model.AuthenticationType;
import stirling.software.common.model.ApplicationProperties;
import stirling.software.common.model.ApplicationProperties.Security.SAML2;
import stirling.software.common.model.exception.UnsupportedProviderException;
import stirling.software.common.util.RequestUriUtils;
import stirling.software.proprietary.security.model.AuthenticationType;
import stirling.software.proprietary.security.service.LoginAttemptService;
import stirling.software.proprietary.security.service.UserService;
@AllArgsConstructor
@Slf4j

View File

@ -1,6 +1,10 @@
package stirling.software.SPDF.config.security.saml2;
package stirling.software.proprietary.security.saml2;
import java.util.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.opensaml.core.xml.XMLObject;
import org.opensaml.saml.saml2.core.Assertion;
@ -16,8 +20,8 @@ import org.springframework.security.saml2.provider.service.authentication.Saml2A
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.security.UserService;
import stirling.software.SPDF.model.User;
import stirling.software.proprietary.security.model.User;
import stirling.software.proprietary.security.service.UserService;
@Slf4j
@ConditionalOnProperty(name = "security.saml2.enabled", havingValue = "true")

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security.saml2;
package stirling.software.proprietary.security.saml2;
import java.security.cert.X509Certificate;
import java.util.Collections;

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security;
package stirling.software.proprietary.security.service;
import java.util.Optional;
@ -8,10 +8,10 @@ import org.springframework.stereotype.Service;
import lombok.RequiredArgsConstructor;
import stirling.software.SPDF.config.interfaces.ShowAdminInterface;
import stirling.software.SPDF.model.User;
import stirling.software.SPDF.repository.UserRepository;
import stirling.software.common.configuration.interfaces.ShowAdminInterface;
import stirling.software.common.model.ApplicationProperties;
import stirling.software.proprietary.security.database.repository.UserRepository;
import stirling.software.proprietary.security.model.User;
@Service
@RequiredArgsConstructor

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security.oauth2;
package stirling.software.proprietary.security.service;
import java.util.Optional;
@ -13,12 +13,10 @@ import org.springframework.security.oauth2.core.oidc.user.OidcUser;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.security.LoginAttemptService;
import stirling.software.SPDF.config.security.UserService;
import stirling.software.SPDF.model.User;
import stirling.software.common.model.ApplicationProperties;
import stirling.software.common.model.ApplicationProperties.Security.OAUTH2;
import stirling.software.common.model.enumeration.UsernameAttribute;
import stirling.software.proprietary.security.model.User;
@Slf4j
public class CustomOAuth2UserService implements OAuth2UserService<OidcUserRequest, OidcUser> {

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security;
package stirling.software.proprietary.security.service;
import java.util.Collection;
import java.util.Set;
@ -13,9 +13,9 @@ import org.springframework.stereotype.Service;
import lombok.RequiredArgsConstructor;
import stirling.software.SPDF.model.Authority;
import stirling.software.SPDF.model.User;
import stirling.software.SPDF.repository.UserRepository;
import stirling.software.proprietary.security.database.repository.UserRepository;
import stirling.software.proprietary.security.model.Authority;
import stirling.software.proprietary.security.model.User;
@Service
@RequiredArgsConstructor

View File

@ -1,4 +1,4 @@
package stirling.software.SPDF.config.security.database;
package stirling.software.proprietary.security.service;
import java.io.IOException;
import java.nio.file.DirectoryStream;
@ -27,15 +27,14 @@ import org.springframework.stereotype.Service;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.interfaces.DatabaseInterface;
import stirling.software.SPDF.model.exception.BackupNotFoundException;
import stirling.software.common.configuration.InstallationPathConfig;
import stirling.software.common.model.ApplicationProperties;
import stirling.software.common.model.FileInfo;
import stirling.software.proprietary.security.model.exception.BackupNotFoundException;
@Slf4j
@Service
public class DatabaseService implements DatabaseInterface {
public class DatabaseService implements DatabaseServiceInterface {
public static final String BACKUP_PREFIX = "backup_";
public static final String SQL_SUFFIX = ".sql";

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