Compare commits

..

62 Commits

Author SHA1 Message Date
Anthony Stirling
f5f84f3fc9 Update build.gradle 2024-07-20 12:25:20 +01:00
github-actions[bot]
cbe92269f4 Update 3rd Party Licenses (#1572)
Signed-off-by: GitHub Action <action@github.com>
Co-authored-by: GitHub Action <action@github.com>
2024-07-20 10:49:09 +01:00
dependabot[bot]
81871a6f10 Bump springBootVersion from 3.3.0 to 3.3.2 (#1570)
Bumps `springBootVersion` from 3.3.0 to 3.3.2.

Updates `org.springframework.boot:spring-boot-starter-web` from 3.3.0 to 3.3.2
- [Release notes](https://github.com/spring-projects/spring-boot/releases)
- [Commits](https://github.com/spring-projects/spring-boot/compare/v3.3.0...v3.3.2)

Updates `org.springframework.boot:spring-boot-starter-jetty` from 3.3.0 to 3.3.2
- [Release notes](https://github.com/spring-projects/spring-boot/releases)
- [Commits](https://github.com/spring-projects/spring-boot/compare/v3.3.0...v3.3.2)

Updates `org.springframework.boot:spring-boot-starter-thymeleaf` from 3.3.0 to 3.3.2
- [Release notes](https://github.com/spring-projects/spring-boot/releases)
- [Commits](https://github.com/spring-projects/spring-boot/compare/v3.3.0...v3.3.2)

Updates `org.springframework.boot:spring-boot-starter-security` from 3.3.0 to 3.3.2
- [Release notes](https://github.com/spring-projects/spring-boot/releases)
- [Commits](https://github.com/spring-projects/spring-boot/compare/v3.3.0...v3.3.2)

Updates `org.springframework.boot:spring-boot-starter-data-jpa` from 3.3.0 to 3.3.2
- [Release notes](https://github.com/spring-projects/spring-boot/releases)
- [Commits](https://github.com/spring-projects/spring-boot/compare/v3.3.0...v3.3.2)

Updates `org.springframework.boot:spring-boot-starter-oauth2-client` from 3.3.0 to 3.3.2
- [Release notes](https://github.com/spring-projects/spring-boot/releases)
- [Commits](https://github.com/spring-projects/spring-boot/compare/v3.3.0...v3.3.2)

Updates `org.springframework.boot:spring-boot-starter-test` from 3.3.0 to 3.3.2
- [Release notes](https://github.com/spring-projects/spring-boot/releases)
- [Commits](https://github.com/spring-projects/spring-boot/compare/v3.3.0...v3.3.2)

Updates `org.springframework.boot:spring-boot-starter-actuator` from 3.3.0 to 3.3.2
- [Release notes](https://github.com/spring-projects/spring-boot/releases)
- [Commits](https://github.com/spring-projects/spring-boot/compare/v3.3.0...v3.3.2)

Updates `org.springframework.boot:spring-boot-devtools` from 3.3.0 to 3.3.2
- [Release notes](https://github.com/spring-projects/spring-boot/releases)
- [Commits](https://github.com/spring-projects/spring-boot/compare/v3.3.0...v3.3.2)

---
updated-dependencies:
- dependency-name: org.springframework.boot:spring-boot-starter-web
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.springframework.boot:spring-boot-starter-jetty
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.springframework.boot:spring-boot-starter-thymeleaf
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.springframework.boot:spring-boot-starter-security
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.springframework.boot:spring-boot-starter-data-jpa
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.springframework.boot:spring-boot-starter-oauth2-client
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.springframework.boot:spring-boot-starter-test
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.springframework.boot:spring-boot-starter-actuator
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.springframework.boot:spring-boot-devtools
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-20 10:42:03 +01:00
github-actions[bot]
cf2a7896da 📝 Update README: Translation Progress Table (#1571)
📝 Sync README
> Made via sync_files.yml

Co-authored-by: GitHub Action action@github.com <GitHub Action action@github.com>
2024-07-20 10:41:32 +01:00
Oğuz Ersen
6a3d95ba09 Add missing Turkish translation (#1549)
Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
2024-07-20 09:15:03 +00:00
Ludy
85ed0c38d1 Adding declaration as repository component & changing primary key type (#1559)
* Adding declaration as repository component & changing primary key type

* Update AuthorityRepository.java

* Update PersistentLoginRepository.java

---------

Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
2024-07-20 10:13:49 +01:00
Ludy
6c7dc34640 Add: Label manager (#1560) 2024-07-20 09:57:27 +01:00
Anthony Stirling
ecfdfa5644 Update init-without-ocr.sh 2024-07-20 09:56:39 +01:00
Anthony Stirling
11e279bd12 Remove calibre for now 2024-07-20 09:54:46 +01:00
Anthony Stirling
929f0bbbe5 version bump, multi file fix and disable survey (#1550)
* version bump, multi file fix and disable survey

* example test stuff

* logs

* Update docker-compose-latest.yml

---------

Co-authored-by: a <a>
2024-07-20 09:53:58 +01:00
Ludy
5751b1ac2d adds Thai to the languages ​​table (#1555)
This PR makes #1554 obsolete
2024-07-11 23:35:01 +01:00
taesaeng28
4bf78ffd5d Added support for Thai language (#1551)
* Added support for Thai language

* Correct Thai national flag proportions in SVG

* Remove th_TH from env.LANGS

causer
Failed tests:
Stirling-PDF-Regression
Some tests failed.
Error: Process completed with exit code 1.

* fix incorrect syntax
2024-07-10 18:05:29 +00:00
pixeebot[bot]
b7d37deb85 Refactored to use parameterized SQL APIs (#1545)
Co-authored-by: pixeebot[bot] <104101892+pixeebot[bot]@users.noreply.github.com>
2024-07-09 21:18:32 +01:00
github-actions[bot]
2a65fd0825 📝 Update README: Translation Progress Table (#1538)
📝 Sync README
> Made via sync_files.yml

Co-authored-by: GitHub Action action@github.com <GitHub Action action@github.com>
2024-07-07 11:45:50 +01:00
Ludy
422264a288 added non-translatable strings (#1537)
Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
2024-07-06 21:54:04 +00:00
github-actions[bot]
695fbb0150 📝 Update README: Translation Progress Table (#1536)
📝 Sync README
> Made via sync_files.yml

Co-authored-by: GitHub Action action@github.com <GitHub Action action@github.com>
2024-07-06 21:48:53 +00:00
Ludy
a17105e650 Create stale.yml (#1530)
* Create stale.yml

* Update stale.yml
2024-07-06 20:25:38 +00:00
Ludy
32ac38e93f Add missing translations strings (#1535)
* Add missing translations strings

* Update messages_de_DE.properties
2024-07-06 19:48:39 +01:00
Ludy
3c0d2b908f Update messages_de_DE.properties (#1532)
Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
2024-07-06 18:17:30 +00:00
Ludy
ab62a93a0d Fix labeler 2 (#1534) 2024-07-06 19:15:19 +01:00
Ludy
5189708d25 Fix labeler (#1533)
* Update labeler.yml

* Update labeler.yml
2024-07-06 17:48:06 +01:00
Ludy
19831c050c Add labeler action for pull requests (#1529)
* Automatically label PRs

* Update labeler-config.yml
2024-07-06 15:43:53 +01:00
albanobattistella
e426d99145 Update messages_it_IT.properties (#1527) 2024-07-06 12:27:19 +00:00
Ludy
4088208fc8 adding documentation for database import and export (#1528)
* adding documentation for database import and export

* Update DATABASE.md
2024-07-06 13:24:32 +01:00
albanobattistella
31ce5b1221 Update messages_it_IT.properties (#1526)
Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
2024-07-05 20:50:22 +01:00
Ludy
be05db22f5 Preparation for Switching to a New Database Version (#1521)
* preparing to switch to a new database version

* add PreAuthorize

---------

Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
2024-07-05 20:48:33 +01:00
Ludy
79927416e5 standardize the layout (#1525) 2024-07-04 21:13:03 +00:00
Shawn Johnston
f95ee31bbd Highlight color selection for the Compare PDFs page. (#1515)
* Update compare.html

* Update compare.html

* Conform to text requirements

Changed text in some labels to conform to Thymeleaf format.

* Add GB to th:text for label
2024-07-04 21:11:41 +00:00
Ludy
40042c37f2 [Bugfix] the Manifest Syntax error (#1524)
Fixes the Manifest Syntax error
2024-07-04 21:05:45 +00:00
Ludy
1c90b65bca removes empty list entries (#1523) 2024-07-04 21:04:21 +00:00
Ludy
2971425544 [Bugfix] Prevents the deletion of productive data (#1522)
prevents the deletion of productive data
2024-07-04 22:02:35 +01:00
Prerak Trivedi
a9ee698432 Update README.md (#1518)
removed dead link to a screenshot
2024-07-02 20:29:22 +01:00
github-actions[bot]
15b5d51957 📝 Update README: Translation Progress Table (#1514)
📝 Sync README
> Made via sync_files.yml

Co-authored-by: GitHub Action action@github.com <GitHub Action action@github.com>
2024-06-30 15:11:18 +01:00
eruditus-ginkgo
92893b8d4c Update messages_zh_CN.properties (#1513)
Translate untranslated text to Simplified Chinese;
Standardize Chinese expressions for identical English phrases;
Remove spaces between Chinese and English text for consistency.
2024-06-29 17:45:31 +01:00
Ludy
3a6969cad0 Fix: synchronizing the browser settings to the database #1481 (#1510)
Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
2024-06-26 20:48:50 +00:00
Ludy
88e8663d44 Rename from translation_status.toml to ignore_translation.toml and more (#1511) 2024-06-26 21:47:20 +01:00
github-actions[bot]
a2d7490d45 📝 Update README: Translation Progress Table (#1507)
📝 Sync README
> Made via sync_files.yml

Co-authored-by: GitHub Action action@github.com <GitHub Action action@github.com>
2024-06-25 23:21:57 +01:00
Alex
c363a1c4e0 Add some translations and add ignored translations (#1501)
* Create ignore_translation.toml

Added ignored translations

* Update messages_nl_NL.properties

Changed a few translations to be better

* Update ignore_translation.toml

Deleted wrong ignore
2024-06-25 23:16:09 +01:00
Anthony Stirling
9e84836cfe Update pipeline.html 2024-06-22 23:29:36 +01:00
ProvaTeams
c8a2789caf Missing description for Split function in top bar (#1492) 2024-06-20 20:39:59 +01:00
Anthony Stirling
202b996c2b Update README.md 2024-06-19 21:05:56 +01:00
github-actions[bot]
e766a5f583 Update 3rd Party Licenses (#1490)
Signed-off-by: GitHub Action <action@github.com>
Co-authored-by: GitHub Action <action@github.com>
2024-06-19 18:37:43 +01:00
dependabot[bot]
c7d18939fc Bump org.springframework:spring-webmvc from 6.1.5 to 6.1.9 (#1462)
Bumps [org.springframework:spring-webmvc](https://github.com/spring-projects/spring-framework) from 6.1.5 to 6.1.9.
- [Release notes](https://github.com/spring-projects/spring-framework/releases)
- [Commits](https://github.com/spring-projects/spring-framework/compare/v6.1.5...v6.1.9)

---
updated-dependencies:
- dependency-name: org.springframework:spring-webmvc
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
2024-06-19 18:25:09 +01:00
dependabot[bot]
34e198d8e6 Bump com.twelvemonkeys.imageio:imageio-jpeg from 3.10.1 to 3.11.0 (#1486)
Bumps com.twelvemonkeys.imageio:imageio-jpeg from 3.10.1 to 3.11.0.

---
updated-dependencies:
- dependency-name: com.twelvemonkeys.imageio:imageio-jpeg
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-19 18:24:09 +01:00
anthonyp-cns
f6a31e6ed0 Update README.md adjusting system to security as shown later in the readme for consistency (#1488)
Update README.md

Updated readme changing system to security tag to make enabling logins easy to find / implement for new users via docker environment variable
2024-06-19 06:14:52 +01:00
github-actions[bot]
7768dc9fd9 📝 Update README: Translation Progress Table (#1485)
📝 Sync README
> Made via sync_files.yml

Co-authored-by: GitHub Action action@github.com <GitHub Action action@github.com>
2024-06-17 20:37:27 +01:00
Alex
b739d3847e Update messages_nl_NL.properties (#1483)
Added new translations
2024-06-17 20:36:41 +01:00
M0C
a3e5cb51b0 Polish translation (#1482)
pigers full polish translation
2024-06-17 20:36:29 +01:00
Anthony Stirling
ab7a41d155 Update README.md 2024-06-17 18:40:07 +01:00
Anthony Stirling
3576c32c52 add fat jar 2024-06-16 15:42:45 +01:00
Ludy
f43fe15193 further bug fixes when using context path (#1475)
Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
2024-06-15 22:07:09 +01:00
arsvendg
234ae17dc8 Edit norwegian translations (#1476)
* Minor correction

* Endringer oversettelser
2024-06-15 21:40:52 +01:00
github-actions[bot]
7ee14ac794 📝 Update README: Translation Progress Table (#1473)
📝 Sync README
> Made via sync_files.yml

Co-authored-by: GitHub Action action@github.com <GitHub Action action@github.com>
2024-06-15 16:08:07 +01:00
albanobattistella
ba604bda3e Update messages_it_IT.properties (#1472) 2024-06-15 15:21:08 +01:00
Ludy
036c10fc27 added: Differentiate login methods and more (#1471)
- Added Portuguese in the table (README.md)
- ApplicationProperties.class diluted, provider outsourced to its own class
- Added UnsupportedProviderException to indicate a meaningful error
- Closes #1357
- Closes #1238
2024-06-15 13:15:09 +01:00
github-actions[bot]
baa9410242 📝 Update README: Translation Progress Table (#1469)
📝 Sync README
> Made via sync_files.yml

Co-authored-by: GitHub Action action@github.com <GitHub Action action@github.com>
2024-06-15 12:07:20 +01:00
Ludy
ab2fe5ef81 Add: missing string pdfOrganiser.mode.10 (#1468)
* Add: missing string pdfOrganiser.mode.10

* Update messages_it_IT.properties
2024-06-15 12:06:38 +01:00
github-actions[bot]
a926289fb0 Update 3rd Party Licenses (#1466)
Signed-off-by: GitHub Action <action@github.com>
Co-authored-by: GitHub Action <action@github.com>
2024-06-15 11:50:58 +01:00
Anthony Stirling
b711be3061 Update build.gradle 2024-06-15 11:50:31 +01:00
Ludy
f07ba9192b Updating build.gradle libraries (#1465) 2024-06-15 11:47:16 +01:00
github-actions[bot]
dc2f891632 Update 3rd Party Licenses (#1464)
Signed-off-by: GitHub Action <action@github.com>
Co-authored-by: GitHub Action <action@github.com>
2024-06-15 10:32:23 +01:00
Ludy
fe9c5a7351 Change: method write and read settings.yml #1441 (#1463)
Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
2024-06-15 09:05:31 +01:00
158 changed files with 6560 additions and 1865 deletions

20
.github/labeler-config.yml vendored Normal file
View File

@@ -0,0 +1,20 @@
translation:
- changed-files:
- any-glob-to-any-file: 'src/main/resources/messages_*_*.properties'
Front End:
- changed-files:
- any-glob-to-any-file: 'src/main/resources/templates/**'
java:
- changed-files:
- any-glob-to-any-file: 'src/main/java/**/*.java'
documentation:
- changed-files:
- any-glob-to-any-file: '**/*.md'
docker:
- changed-files:
- any-glob-to-any-file: 'Dockerfile'
- any-glob-to-any-file: 'Dockerfile-*'

91
.github/labels.yml vendored Normal file
View File

@@ -0,0 +1,91 @@
# Labels names are important as they are used by Release Drafter to decide
# regarding where to record them in changelog or if to skip them.
#
# The repository labels will be automatically configured using this file and
# the GitHub Action https://github.com/marketplace/actions/github-labeler.
- name: "Back End"
color: "20CE6C"
description: "Issues related to back-end development"
from_name: "Back end"
- name: "Bug"
description: "Something isn't working"
color: "EB9CA6"
from_name: "bug"
- name: "dependencies"
description: "Pull requests that update a dependency file"
color: "5AA8FC"
- name: "Docker"
description: "Pull requests that update Docker code"
color: "1FCEFF"
from_name: "docker"
- name: "Documentation"
description: "Improvements or additions to documentation"
color: "35ABFF"
from_name: "documentation"
- name: "Done for next release"
color: "0CDBD1"
- name: "Done"
color: "60F13B"
- name: "duplicate"
description: "This issue or pull request already exists"
color: "CDD1D5"
- name: "enhancement"
description: "New feature or request"
color: "A0EEEE"
- name: "fix needs confirmation"
color: "60A1E7"
description: "Fix needs to be confirmed"
- name: "Front End"
color: "BBD2F1"
description: "Issues related to front-end development"
- name: "github-actions"
description: "Pull requests that update GitHub Actions code"
color: "999999"
from_name: "github_actions"
- name: "good first issue"
description: "Good for newcomers"
color: "C1B8FF"
- name: "help wanted"
description: "Extra attention is needed"
color: "00E6C4"
- name: "invalid"
description: "This doesn't seem right"
color: "E5E566"
- name: "Java"
description: "Pull requests that update Java code"
color: "FF9E1F"
from_name: "java"
- name: "Long-term Enhancement"
color: "BFDEC3"
description: "Enhancements planned for the long term"
- name: "more-info-needed"
color: "00E4F8"
description: "More information is needed"
- name: "needs investigation"
color: "B8C3A7"
description: "Issues that require further investigation"
- name: "Prioritised enhancement"
color: "4BA2EE"
description: "High-priority enhancements"
- name: "question"
description: "Further information is requested"
color: "D97EE5"
- name: "Translation"
color: "9FABF9"
from_name: "translation"
- name: "upstream"
color: "DEDEDE"
- name: "v2"
color: "FFFF00"
- name: "wontfix"
description: "This will not be worked on"
color: "FFFFFF"
- name: "Security"
color: "000000"
description: "Security-related issues or pull requests"
- name: "API"
color: "FFFF00"
description: "API-related issues or pull requests"
- name: "Test"
color: "FF9E1F"
description: "Testing-related issues or pull requests"

18
.github/workflows/labeler.yml vendored Normal file
View File

@@ -0,0 +1,18 @@
name: "Pull Request Labeler"
on:
pull_request_target:
types: [opened, synchronize]
jobs:
labeler:
permissions:
contents: read
pull-requests: write
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/labeler@v5
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
configuration-path: .github/labeler-config.yml
sync-labels: true

24
.github/workflows/manage-label.yml vendored Normal file
View File

@@ -0,0 +1,24 @@
name: Manage labels
on:
schedule:
- cron: "30 20 * * *"
permissions:
contents: read
issues: write
jobs:
labeler:
name: Labeler
runs-on: ubuntu-latest
steps:
- name: Check out the repository
uses: actions/checkout@v4
- name: Run Labeler
uses: crazy-max/ghaction-github-labeler@v5
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
yaml-file: .github/labels.yml
skip-delete: true

32
.github/workflows/stale.yml vendored Normal file
View File

@@ -0,0 +1,32 @@
name: Close stale issues
on:
schedule:
- cron: "30 0 * * *"
workflow_dispatch:
jobs:
stale:
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
steps:
- name: 30 days stale issues
uses: actions/stale@v9
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
days-before-stale: 30
days-before-close: 7
stale-issue-message: >
This issue has been automatically marked as stale because it has had no recent activity.
It will be closed if no further activity occurs. Thank you for your contributions.
close-issue-message: >
This issue has been automatically closed because it has had no recent activity after being marked as stale.
Please reopen if you need further assistance.
stale-issue-label: "Stale"
remove-stale-when-updated: true
only-issue-labels: "more-info-needed"
days-before-pr-stale: -1 # Prevents PRs from being marked as stale
days-before-pr-close: -1 # Prevents PRs from being closed
start-date: '2024-07-06T00:00:00Z' # ISO 8601 Format

View File

@@ -7,7 +7,7 @@ on:
paths: paths:
- "build.gradle" - "build.gradle"
- "src/main/resources/messages_*.properties" - "src/main/resources/messages_*.properties"
- "scripts/translation_status.toml" - "scripts/ignore_translation.toml"
permissions: permissions:
contents: write contents: write
@@ -17,9 +17,9 @@ jobs:
sync-versions: sync-versions:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4.1.1 - uses: actions/checkout@v4
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v5.1.0 uses: actions/setup-python@v5
with: with:
python-version: "3.x" python-version: "3.x"
- name: Install dependencies - name: Install dependencies
@@ -36,7 +36,7 @@ jobs:
git diff --staged --quiet || git commit -m ":floppy_disk: Sync Versions git diff --staged --quiet || git commit -m ":floppy_disk: Sync Versions
> Made via sync_files.yml" || echo "no changes" > Made via sync_files.yml" || echo "no changes"
- name: Create Pull Request - name: Create Pull Request
uses: peter-evans/create-pull-request@v6.0.1 uses: peter-evans/create-pull-request@v6
with: with:
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}
commit-message: Update files commit-message: Update files
@@ -54,9 +54,9 @@ jobs:
sync-readme: sync-readme:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4.1.1 - uses: actions/checkout@v4
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v5.1.0 uses: actions/setup-python@v5
with: with:
python-version: "3.x" python-version: "3.x"
- name: Install dependencies - name: Install dependencies
@@ -73,7 +73,7 @@ jobs:
git diff --staged --quiet || git commit -m ":memo: Sync README git diff --staged --quiet || git commit -m ":memo: Sync README
> Made via sync_files.yml" || echo "no changes" > Made via sync_files.yml" || echo "no changes"
- name: Create Pull Request - name: Create Pull Request
uses: peter-evans/create-pull-request@v6.0.1 uses: peter-evans/create-pull-request@v6
with: with:
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}
commit-message: Update files commit-message: Update files

View File

@@ -6,9 +6,11 @@ repos:
args: args:
- --fix - --fix
- --line-length=127 - --line-length=127
files: ^((.github/scripts)/.+)?[^/]+\.py$ files: ^((.github/scripts|scripts)/.+)?[^/]+\.py$
exclude: (split_photos.py)
- id: ruff-format - id: ruff-format
files: ^((.github/scripts)/.+)?[^/]+\.py$ files: ^((.github/scripts|scripts)/.+)?[^/]+\.py$
exclude: (split_photos.py)
- repo: https://github.com/codespell-project/codespell - repo: https://github.com/codespell-project/codespell
rev: v2.2.6 rev: v2.2.6
hooks: hooks:
@@ -33,5 +35,5 @@ repos:
# args: ["--replace_with= "] # args: ["--replace_with= "]
entry: python .github/scripts/check_tabulator.py entry: python .github/scripts/check_tabulator.py
language: python language: python
exclude: ^src/main/resources/static/pdfjs/ exclude: ^(src/main/resources/static/pdfjs|src/main/resources/static/pdfjs-legacy)
files: ^.*(\.html|\.css|\.js)$ files: ^.*(\.html|\.css|\.js)$

40
DATABASE.md Normal file
View File

@@ -0,0 +1,40 @@
# New Database Backup and Import Functionality
**Full activation will take place on approximately January 5th, 2025!**
Why is the waiting time six months?
There are users who only install updates sporadically; if they skip the preparation, it can/will lead to data loss in the database.
## Functionality Overview
The newly introduced feature enhances the application with robust database backup and import capabilities. This feature is designed to ensure data integrity and provide a straightforward way to manage database backups. Here's how it works:
1. Automatic Backup Creation
- The system automatically creates a database backup every day at midnight. This ensures that there is always a recent backup available, minimizing the risk of data loss.
2. Manual Backup Export
- Admin actions that modify the user database trigger a manual export of the database. This keeps the backup up-to-date with the latest changes and provides an extra layer of data security.
3. Importing Database Backups
- Admin users can import a database backup either via the web interface or API endpoints. This allows for easy restoration of the database to a previous state in case of data corruption or other issues.
- The import process ensures that the database structure and data are correctly restored, maintaining the integrity of the application.
4. Managing Backup Files
- Admins can view a list of all existing backup files, along with their creation dates and sizes. This helps in managing storage and identifying the most recent or relevant backups.
- Backup files can be downloaded for offline storage or transferred to other environments, providing flexibility in database management.
- Unnecessary backup files can be deleted through the interface to free up storage space and maintain an organized backup directory.
## User Interface
### Web Interface
1. Upload SQL files to import database backups.
2. View details of existing backups, such as file names, creation dates, and sizes.
3. Download backup files for offline storage.
4. Delete outdated or unnecessary backup files.
### API Endpoints
1. Import database backups by uploading SQL files.
2. Download backup files.
3. Delete backup files.
This new functionality streamlines database management, ensuring that backups are always available and easy to manage, thus improving the reliability and resilience of the application.

View File

@@ -31,7 +31,7 @@ ENV DOCKER_ENABLE_SECURITY=false \
PGID=1000 \ PGID=1000 \
UMASK=022 \ UMASK=022 \
FAT_DOCKER=true \ FAT_DOCKER=true \
INSTALL_BOOK_AND_ADVANCED_HTML_OPS=true INSTALL_BOOK_AND_ADVANCED_HTML_OPS=false
# JDK for app # JDK for app
@@ -45,7 +45,6 @@ RUN echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /et
tini \ tini \
bash \ bash \
curl \ curl \
calibre@testing \
shadow \ shadow \
su-exec \ su-exec \
openssl \ openssl \

163
README.md
View File

@@ -9,6 +9,7 @@
[![Github Sponsor](https://img.shields.io/badge/Github%20Sponsor-yellow?style=flat&logo=github)](https://github.com/sponsors/Frooodle) [![Github Sponsor](https://img.shields.io/badge/Github%20Sponsor-yellow?style=flat&logo=github)](https://github.com/sponsors/Frooodle)
[![Deploy to DO](https://www.deploytodo.com/do-btn-blue.svg)](https://cloud.digitalocean.com/apps/new?repo=https://github.com/Stirling-Tools/Stirling-PDF/tree/digitalOcean&refcode=c3210994b1af) [![Deploy to DO](https://www.deploytodo.com/do-btn-blue.svg)](https://cloud.digitalocean.com/apps/new?repo=https://github.com/Stirling-Tools/Stirling-PDF/tree/digitalOcean&refcode=c3210994b1af)
[<img src="https://www.ssdnodes.com/wp-content/uploads/2023/11/footer-logo.svg" alt="Name" height="40">](https://www.ssdnodes.com/manage/aff.php?aff=2216&register=true)
This is a robust, locally hosted web-based PDF manipulation tool using Docker. It enables you to carry out various operations on PDF files, including splitting, merging, converting, reorganizing, adding images, rotating, compressing, and more. This locally hosted web application has evolved to encompass a comprehensive set of features, addressing all your PDF requirements. This is a robust, locally hosted web-based PDF manipulation tool using Docker. It enables you to carry out various operations on PDF files, including splitting, merging, converting, reorganizing, adding images, rotating, compressing, and more. This locally hosted web application has evolved to encompass a comprehensive set of features, addressing all your PDF requirements.
@@ -21,10 +22,11 @@ All files and PDFs exist either exclusively on the client side, reside in server
## Features ## Features
- Dark mode support. - Dark mode support.
- Custom download options (see [here](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/images/settings.png) for example) - Custom download options
- Parallel file processing and downloads - Parallel file processing and downloads
- API for integration with external scripts - API for integration with external scripts
- Optional Login and Authentication support (see [here](https://github.com/Stirling-Tools/Stirling-PDF/tree/main#login-authentication) for documentation) - Optional Login and Authentication support (see [here](https://github.com/Stirling-Tools/Stirling-PDF/tree/main#login-authentication) for documentation)
- Database Backup and Import (see [here](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DATABASE.md) for documentation)
## **PDF Features** ## **PDF Features**
@@ -82,7 +84,8 @@ All files and PDFs exist either exclusively on the client side, reside in server
- Get all information on a PDF to view or export as JSON. - Get all information on a PDF to view or export as JSON.
For a overview of the tasks and the technology each uses please view [Endpoint-groups.md](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/Endpoint-groups.md) For a overview of the tasks and the technology each uses please view [Endpoint-groups.md](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/Endpoint-groups.md)
Demo of the app is available [here](https://stirlingpdf.io). username: demo, password: demo
Demo of the app is available [here](https://stirlingpdf.io).
## Technologies used ## Technologies used
@@ -105,33 +108,36 @@ Please view https://github.com/Stirling-Tools/Stirling-PDF/blob/main/LocalRunGui
https://hub.docker.com/r/frooodle/s-pdf https://hub.docker.com/r/frooodle/s-pdf
Stirling PDF has 2 different versions, a Full version and ultra-Lite version. Depending on the types of features you use you may want a smaller image to save on space. Stirling PDF has 3 different versions, a Full version and ultra-Lite version as well as a 'Fat' version. Depending on the types of features you use you may want a smaller image to save on space.
To see what the different versions offer please look at our [version mapping](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/Version-groups.md) To see what the different versions offer please look at our [version mapping](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/Version-groups.md)
For people that don't mind about space optimization just use the latest tag. For people that don't mind about space optimization just use the latest tag.
![Docker Image Size (tag)](https://img.shields.io/docker/image-size/frooodle/s-pdf/latest?label=Stirling-PDF%20Full) ![Docker Image Size (tag)](https://img.shields.io/docker/image-size/frooodle/s-pdf/latest?label=Stirling-PDF%20Full)
![Docker Image Size (tag)](https://img.shields.io/docker/image-size/frooodle/s-pdf/latest-ultra-lite?label=Stirling-PDF%20Ultra-Lite) ![Docker Image Size (tag)](https://img.shields.io/docker/image-size/frooodle/s-pdf/latest-ultra-lite?label=Stirling-PDF%20Ultra-Lite)
![Docker Image Size (tag)](https://img.shields.io/docker/image-size/frooodle/s-pdf/latest-fat?label=Stirling-PDF%20Fat)
Docker Run Please note in below examples you may need to change the volume paths as needed, current examples install them to the current working directory
eg ``./extraConfigs:/configs`` to ``/opt/stirlingpdf/extraConfigs:/configs``
### Docker Run
```bash ```bash
docker run -d \ docker run -d \
-p 8080:8080 \ -p 8080:8080 \
-v /location/of/trainingData:/usr/share/tessdata \ -v ./trainingData:/usr/share/tessdata \
-v /location/of/extraConfigs:/configs \ -v ./extraConfigs:/configs \
-v /location/of/logs:/logs \ -v ./logs:/logs \
-e DOCKER_ENABLE_SECURITY=false \ -e DOCKER_ENABLE_SECURITY=false \
-e INSTALL_BOOK_AND_ADVANCED_HTML_OPS=false \ -e INSTALL_BOOK_AND_ADVANCED_HTML_OPS=false \
-e LANGS=en_GB \ -e LANGS=en_GB \
--name stirling-pdf \ --name stirling-pdf \
frooodle/s-pdf:latest frooodle/s-pdf:latest
Can also add these for customisation but are not required Can also add these for customisation but are not required
-v /location/of/customFiles:/customFiles \ -v /location/of/customFiles:/customFiles \
``` ```
Docker Compose ### Docker Compose
```yaml ```yaml
version: '3.3' version: '3.3'
@@ -141,10 +147,10 @@ services:
ports: ports:
- '8080:8080' - '8080:8080'
volumes: volumes:
- /location/of/trainingData:/usr/share/tessdata #Required for extra OCR languages - ./trainingData:/usr/share/tessdata #Required for extra OCR languages
- /location/of/extraConfigs:/configs - ./extraConfigs:/configs
# - /location/of/customFiles:/customFiles/ # - ./customFiles:/customFiles/
# - /location/of/logs:/logs/ # - ./logs:/logs/
environment: environment:
- DOCKER_ENABLE_SECURITY=false - DOCKER_ENABLE_SECURITY=false
- INSTALL_BOOK_AND_ADVANCED_HTML_OPS=false - INSTALL_BOOK_AND_ADVANCED_HTML_OPS=false
@@ -159,41 +165,43 @@ Please view https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToUseOCR
## Supported Languages ## Supported Languages
Stirling PDF currently supports 32! Stirling PDF currently supports 33!
| Language | Progress | | Language | Progress |
| ------------------------------------------- | -------------------------------------- | | ------------------------------------------- | -------------------------------------- |
| English (English) (en_GB) | ![100%](https://geps.dev/progress/100) | | English (English) (en_GB) | ![100%](https://geps.dev/progress/100) |
| English (US) (en_US) | ![100%](https://geps.dev/progress/100) | | English (US) (en_US) | ![100%](https://geps.dev/progress/100) |
| Arabic (العربية) (ar_AR) | ![46%](https://geps.dev/progress/46) | | Arabic (العربية) (ar_AR) | ![45%](https://geps.dev/progress/45) |
| German (Deutsch) (de_DE) | ![99%](https://geps.dev/progress/99) | | German (Deutsch) (de_DE) | ![100%](https://geps.dev/progress/100) |
| French (Français) (fr_FR) | ![93%](https://geps.dev/progress/93) | | French (Français) (fr_FR) | ![94%](https://geps.dev/progress/94) |
| Spanish (Español) (es_ES) | ![93%](https://geps.dev/progress/93) | | Spanish (Español) (es_ES) | ![92%](https://geps.dev/progress/92) |
| Simplified Chinese (简体中文) (zh_CN) | ![94%](https://geps.dev/progress/94) | | Simplified Chinese (简体中文) (zh_CN) | ![98%](https://geps.dev/progress/98) |
| Traditional Chinese (繁體中文) (zh_TW) | ![98%](https://geps.dev/progress/98) | | Traditional Chinese (繁體中文) (zh_TW) | ![96%](https://geps.dev/progress/96) |
| Catalan (Català) (ca_CA) | ![49%](https://geps.dev/progress/49) | | Catalan (Català) (ca_CA) | ![48%](https://geps.dev/progress/48) |
| Italian (Italiano) (it_IT) | ![98%](https://geps.dev/progress/98) | | Italian (Italiano) (it_IT) | ![99%](https://geps.dev/progress/99) |
| Swedish (Svenska) (sv_SE) | ![40%](https://geps.dev/progress/40) | | Swedish (Svenska) (sv_SE) | ![39%](https://geps.dev/progress/39) |
| Polish (Polski) (pl_PL) | ![42%](https://geps.dev/progress/42) | | Polish (Polski) (pl_PL) | ![90%](https://geps.dev/progress/90) |
| Romanian (Română) (ro_RO) | ![39%](https://geps.dev/progress/39) | | Romanian (Română) (ro_RO) | ![39%](https://geps.dev/progress/39) |
| Korean (한국어) (ko_KR) | ![86%](https://geps.dev/progress/86) | | Korean (한국어) (ko_KR) | ![84%](https://geps.dev/progress/84) |
| Portuguese Brazilian (Português) (pt_BR) | ![61%](https://geps.dev/progress/61) | | Portuguese Brazilian (Português) (pt_BR) | ![60%](https://geps.dev/progress/60) |
| Russian (Русский) (ru_RU) | ![86%](https://geps.dev/progress/86) | | Portuguese (Português) (pt_PT) | ![78%](https://geps.dev/progress/78) |
| Basque (Euskara) (eu_ES) | ![63%](https://geps.dev/progress/63) | | Russian (Русский) (ru_RU) | ![84%](https://geps.dev/progress/84) |
| Japanese (日本語) (ja_JP) | ![86%](https://geps.dev/progress/86) | | Basque (Euskara) (eu_ES) | ![62%](https://geps.dev/progress/62) |
| Dutch (Nederlands) (nl_NL) | ![83%](https://geps.dev/progress/83) | | Japanese (日本語) (ja_JP) | ![90%](https://geps.dev/progress/90) |
| Greek (Ελληνικά) (el_GR) | ![84%](https://geps.dev/progress/84) | | Dutch (Nederlands) (nl_NL) | ![96%](https://geps.dev/progress/96) |
| Turkish (Türkçe) (tr_TR) | ![96%](https://geps.dev/progress/96) | | Greek (Ελληνικά) (el_GR) | ![82%](https://geps.dev/progress/82) |
| Indonesia (Bahasa Indonesia) (id_ID) | ![78%](https://geps.dev/progress/78) | | Turkish (Türkçe) (tr_TR) | ![99%](https://geps.dev/progress/99) |
| Hindi (हिंदी) (hi_IN) | ![79%](https://geps.dev/progress/79) | | Indonesia (Bahasa Indonesia) (id_ID) | ![76%](https://geps.dev/progress/76) |
| Hungarian (Magyar) (hu_HU) | ![77%](https://geps.dev/progress/77) | | Hindi (हिंदी) (hi_IN) | ![77%](https://geps.dev/progress/77) |
| Bulgarian (Български) (bg_BG) | ![96%](https://geps.dev/progress/96) | | Hungarian (Magyar) (hu_HU) | ![76%](https://geps.dev/progress/76) |
| Sebian Latin alphabet (Srpski) (sr_LATN_RS) | ![80%](https://geps.dev/progress/80) | | Bulgarian (Български) (bg_BG) | ![94%](https://geps.dev/progress/94) |
| Ukrainian (Українська) (uk_UA) | ![85%](https://geps.dev/progress/85) | | Sebian Latin alphabet (Srpski) (sr_LATN_RS) | ![78%](https://geps.dev/progress/78) |
| Slovakian (Slovensky) (sk_SK) | ![93%](https://geps.dev/progress/93) | | Ukrainian (Українська) (uk_UA) | ![90%](https://geps.dev/progress/90) |
| Czech (Česky) (cs_CZ) | ![92%](https://geps.dev/progress/92) | | Slovakian (Slovensky) (sk_SK) | ![92%](https://geps.dev/progress/92) |
| Croatian (Hrvatski) (hr_HR) | ![97%](https://geps.dev/progress/97) | | Czech (Česky) (cs_CZ) | ![90%](https://geps.dev/progress/90) |
| Norwegian (Norsk) (no_NB) | ![97%](https://geps.dev/progress/97) | | Croatian (Hrvatski) (hr_HR) | ![95%](https://geps.dev/progress/95) |
| Norwegian (Norsk) (no_NB) | ![96%](https://geps.dev/progress/96) |
| Thai (ไทย) (th_TH) | ![100%](https://geps.dev/progress/100) |
## Contributing (creating issues, translations, fixing bugs, etc.) ## Contributing (creating issues, translations, fixing bugs, etc.)
@@ -214,11 +222,11 @@ Environment variables are also supported and would override the settings file
For example in the settings.yml you have For example in the settings.yml you have
```yaml ```yaml
system: security:
enableLogin: 'true' enableLogin: 'true'
``` ```
To have this via an environment variable you would have ``SYSTEM_ENABLELOGIN`` To have this via an environment variable you would have ``SECURITY_ENABLELOGIN``
The Current list of settings is The Current list of settings is
@@ -228,35 +236,36 @@ security:
csrfDisabled: true # Set to 'true' to disable CSRF protection (not recommended for production) csrfDisabled: true # Set to 'true' to disable CSRF protection (not recommended for production)
loginAttemptCount: 5 # lock user account after 5 tries loginAttemptCount: 5 # lock user account after 5 tries
loginResetTimeMinutes: 120 # lock account for 2 hours after x attempts loginResetTimeMinutes: 120 # lock account for 2 hours after x attempts
# initialLogin: loginMethod: all # 'all' (Login Username/Password and OAuth2[must be enabled and configured]), 'normal'(only Login with Username/Password) or 'oauth2'(only Login with OAuth2)
# username: "admin" # Initial username for the first login initialLogin:
# password: "stirling" # Initial password for the first login username: '' # Initial username for the first login
# oauth2: password: '' # Initial password for the first login
# enabled: false # set to 'true' to enable login (Note: enableLogin must also be 'true' for this to work) oauth2:
# issuer: "" # set to any provider that supports OpenID Connect Discovery (/.well-known/openid-configuration) end-point enabled: false # set to 'true' to enable login (Note: enableLogin must also be 'true' for this to work)
# clientId: "" # Client ID from your provider client:
# clientSecret: "" # Client Secret from your provider keycloak:
# autoCreateUser: false # set to 'true' to allow auto-creation of non-existing users issuer: '' # URL of the Keycloak realm's OpenID Connect Discovery endpoint
# useAsUsername: "email" # Default is 'email'; custom fields can be used as the username clientId: '' # Client ID for Keycloak OAuth2
# scopes: "openid, profile, email" # Specify the scopes for which the application will request permissions clientSecret: '' # Client Secret for Keycloak OAuth2
# provider: "google" # Set this to your OAuth provider's name, e.g., 'google' or 'keycloak' scopes: openid, profile, email # Scopes for Keycloak OAuth2
# client: useAsUsername: preferred_username # Field to use as the username for Keycloak OAuth2
# google: google:
# clientId: "" # Client ID for Google OAuth2 clientId: '' # Client ID for Google OAuth2
# clientSecret: "" # Client Secret for Google OAuth2 clientSecret: '' # Client Secret for Google OAuth2
# scopes: "https://www.googleapis.com/auth/userinfo.email, https://www.googleapis.com/auth/userinfo.profile" # Scopes for Google OAuth2 scopes: https://www.googleapis.com/auth/userinfo.email, https://www.googleapis.com/auth/userinfo.profile # Scopes for Google OAuth2
# useAsUsername: "email" # Field to use as the username for Google OAuth2 useAsUsername: email # Field to use as the username for Google OAuth2
# github: github:
# clientId: "" # Client ID for GitHub OAuth2 clientId: '' # Client ID for GitHub OAuth2
# clientSecret: "" # Client Secret for GitHub OAuth2 clientSecret: '' # Client Secret for GitHub OAuth2
# scopes: "read:user" # Scope for GitHub OAuth2 scopes: read:user # Scope for GitHub OAuth2
# useAsUsername: "login" # Field to use as the username for GitHub OAuth2 useAsUsername: login # Field to use as the username for GitHub OAuth2
# keycloak: issuer: '' # set to any provider that supports OpenID Connect Discovery (/.well-known/openid-configuration) end-point
# issuer: "http://192.168.0.123:8888/realms/stirling-pdf" # URL of the Keycloak realm's OpenID Connect Discovery endpoint clientId: '' # Client ID from your provider
# clientId: "stirling-pdf" # Client ID for Keycloak OAuth2 clientSecret: '' # Client Secret from your provider
# clientSecret: "" # Client Secret for Keycloak OAuth2 autoCreateUser: false # set to 'true' to allow auto-creation of non-existing users
# scopes: "openid, profile, email" # Scopes for Keycloak OAuth2 useAsUsername: email # Default is 'email'; custom fields can be used as the username
# useAsUsername: "email" # Field to use as the username for Keycloak OAuth2 scopes: openid, profile, email # Specify the scopes for which the application will request permissions
provider: google # Set this to your OAuth provider's name, e.g., 'google' or 'keycloak'
system: system:
defaultLocale: 'en-US' # Set the default language (e.g. 'de-DE', 'fr-FR', etc) defaultLocale: 'en-US' # Set the default language (e.g. 'de-DE', 'fr-FR', etc)
@@ -267,9 +276,9 @@ system:
customHTMLFiles: false # enable to have files placed in /customFiles/templates override the existing template html files customHTMLFiles: false # enable to have files placed in /customFiles/templates override the existing template html files
ui: ui:
appName: null # Application's visible name appName: '' # Application's visible name
homeDescription: null # Short description or tagline shown on homepage. homeDescription: '' # Short description or tagline shown on homepage.
appNameNavbar: null # Name displayed on the navigation bar appNameNavbar: '' # Name displayed on the navigation bar
endpoints: endpoints:
toRemove: [] # List endpoints to disable (e.g. ['img-to-pdf', 'remove-pages']) toRemove: [] # List endpoints to disable (e.g. ['img-to-pdf', 'remove-pages'])
@@ -303,7 +312,7 @@ For those wanting to use Stirling-PDFs backend API to link with their own custom
![stirling-login](images/login-light.png) ![stirling-login](images/login-light.png)
### Prerequisites: ### Prerequisites
- User must have the folder ./configs volumed within docker so that it is retained during updates. - User must have the folder ./configs volumed within docker so that it is retained during updates.
- Docker users must download the security jar version by setting ``DOCKER_ENABLE_SECURITY`` to ``true`` in environment variables. - Docker users must download the security jar version by setting ``DOCKER_ENABLE_SECURITY`` to ``true`` in environment variables.

View File

@@ -1,4 +1,7 @@
| Technology | Ultra-Lite | Full | |All versions in a Docker environment can download Calibre as a optional extra at runtime to support `book-to-pdf` and `pdf-to-book` using parameter ``INSTALL_BOOK_AND_ADVANCED_HTML_OPS``.
The 'Fat' container contains all those found in 'Full' with security jar along with this Calibre install.
Technology | Ultra-Lite | Full |
| ---------- | :--------: | :---: | | ---------- | :--------: | :---: |
| Java | ✔️ | ✔️ | | Java | ✔️ | ✔️ |
| JavaScript | ✔️ | ✔️ | | JavaScript | ✔️ | ✔️ |

View File

@@ -1,24 +1,29 @@
plugins { plugins {
id 'java' id "java"
id 'org.springframework.boot' version '3.2.4' id "org.springframework.boot" version "3.3.0"
id 'io.spring.dependency-management' version '1.1.3' id "io.spring.dependency-management" version "1.1.5"
id 'org.springdoc.openapi-gradle-plugin' version '1.8.0' id "org.springdoc.openapi-gradle-plugin" version "1.8.0"
id "io.swagger.swaggerhub" version "1.3.2" id "io.swagger.swaggerhub" version "1.3.2"
id 'edu.sc.seis.launch4j' version '3.0.5' id "edu.sc.seis.launch4j" version "3.0.5"
id 'com.diffplug.spotless' version '6.25.0' id "com.diffplug.spotless" version "6.25.0"
id 'com.github.jk1.dependency-license-report' version '2.6' id "com.github.jk1.dependency-license-report" version "2.8"
} }
import com.github.jk1.license.render.* import com.github.jk1.license.render.*
group = 'stirling.software' ext {
version = '0.26.1' springBootVersion = "3.3.2"
}
//17 is lowest but we support and recommend 21 group = "stirling.software"
sourceCompatibility = '17' version = "0.27.0"
// 17 is lowest but we support and recommend 21
sourceCompatibility = "17"
repositories { repositories {
mavenCentral() mavenCentral()
maven { url "https://jitpack.io" }
} }
licenseReport { licenseReport {
@@ -28,15 +33,17 @@ licenseReport {
sourceSets { sourceSets {
main { main {
java { java {
if (System.getenv('DOCKER_ENABLE_SECURITY') == 'false') { if (System.getenv("DOCKER_ENABLE_SECURITY") == "false") {
exclude 'stirling/software/SPDF/config/security/**' exclude "stirling/software/SPDF/config/security/**"
exclude 'stirling/software/SPDF/controller/api/UserController.java' exclude "stirling/software/SPDF/controller/api/UserController.java"
exclude 'stirling/software/SPDF/controller/web/AccountWebController.java' exclude "stirling/software/SPDF/controller/api/DatabaseController.java"
exclude 'stirling/software/SPDF/model/ApiKeyAuthenticationToken.java' exclude "stirling/software/SPDF/controller/web/AccountWebController.java"
exclude 'stirling/software/SPDF/model/Authority.java' exclude "stirling/software/SPDF/controller/web/DatabaseWebController.java"
exclude 'stirling/software/SPDF/model/PersistentLogin.java' exclude "stirling/software/SPDF/model/ApiKeyAuthenticationToken.java"
exclude 'stirling/software/SPDF/model/User.java' exclude "stirling/software/SPDF/model/Authority.java"
exclude 'stirling/software/SPDF/repository/**' exclude "stirling/software/SPDF/model/PersistentLogin.java"
exclude "stirling/software/SPDF/model/User.java"
exclude "stirling/software/SPDF/repository/**"
} }
} }
} }
@@ -49,34 +56,34 @@ openApi {
} }
launch4j { launch4j {
icon = "${projectDir}/src/main/resources/static/favicon.ico" icon = "${projectDir}/src/main/resources/static/favicon.ico"
outfile="Stirling-PDF.exe" outfile="Stirling-PDF.exe"
headerType="console" headerType="console"
jarTask = tasks.bootJar 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" downloadUrl="https://download.oracle.com/java/21/latest/jdk-21_windows-x64_bin.exe"
variables=["BROWSER_OPEN=true", "ENDPOINTS_GROUPS_TO_REMOVE=CLI"] variables=["BROWSER_OPEN=true", "ENDPOINTS_GROUPS_TO_REMOVE=CLI"]
jreMinVersion="17" jreMinVersion="17"
mutexName="Stirling-PDF" mutexName="Stirling-PDF"
windowTitle="Stirling-PDF" windowTitle="Stirling-PDF"
messagesStartupError="An error occurred while starting Stirling-PDF" messagesStartupError="An error occurred while starting Stirling-PDF"
//messagesJreNotFoundError="This application requires a Java Runtime Environment, Please download Java 17." // messagesJreNotFoundError="This application requires a Java Runtime Environment, Please download Java 17."
messagesJreVersionError="You are running the wrong version of Java, Please download Java 21." messagesJreVersionError="You are running the wrong version of Java, Please download Java 21."
messagesLauncherError="Java is corrupted. Please uninstall and then install Java 21." messagesLauncherError="Java is corrupted. Please uninstall and then install Java 21."
messagesInstanceAlreadyExists="Stirling-PDF is already running." messagesInstanceAlreadyExists="Stirling-PDF is already running."
} }
spotless { spotless {
java { java {
target project.fileTree('src/main/java') target project.fileTree('src/main/java')
googleJavaFormat('1.19.1').aosp().reorderImports(false) googleJavaFormat("1.22.0").aosp().reorderImports(false)
importOrder('java', 'javax', 'org', 'com', 'net', 'io') importOrder("java", "javax", "org", "com", "net", "io")
toggleOffOn() toggleOffOn()
trimTrailingWhitespace() trimTrailingWhitespace()
indentWithSpaces() indentWithSpaces()
@@ -84,127 +91,137 @@ spotless {
} }
} }
tasks.wrapper {
gradleVersion = "8.7"
}
dependencies { dependencies {
//security updates //security updates
implementation 'ch.qos.logback:logback-classic:1.5.3' implementation "ch.qos.logback:logback-classic:1.5.6"
implementation 'ch.qos.logback:logback-core:1.5.3' implementation "ch.qos.logback:logback-core:1.5.6"
implementation 'org.springframework:spring-webmvc:6.1.5' implementation "org.springframework:spring-webmvc:6.1.9"
implementation("io.github.pixee:java-security-toolkit:1.1.3") implementation("io.github.pixee:java-security-toolkit:1.1.3")
implementation 'org.yaml:snakeyaml:2.2' // implementation "org.yaml:snakeyaml:2.2"
implementation 'com.github.Carleslc.Simple-YAML:Simple-Yaml:1.8.4'
// Exclude Tomcat and include Jetty // Exclude Tomcat and include Jetty
implementation('org.springframework.boot:spring-boot-starter-web:3.2.4') { implementation("org.springframework.boot:spring-boot-starter-web:$springBootVersion") {
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat' exclude group: "org.springframework.boot", module: "spring-boot-starter-tomcat"
} }
implementation 'org.springframework.boot:spring-boot-starter-jetty:3.2.4' implementation "org.springframework.boot:spring-boot-starter-jetty:$springBootVersion"
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf:3.2.4'
if (System.getenv('DOCKER_ENABLE_SECURITY') != 'false') { implementation "org.springframework.boot:spring-boot-starter-thymeleaf:$springBootVersion"
implementation 'org.springframework.boot:spring-boot-starter-security:3.2.4'
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5:3.1.2.RELEASE' if (System.getenv("DOCKER_ENABLE_SECURITY") != "false") {
implementation "org.springframework.boot:spring-boot-starter-data-jpa:3.2.4" implementation "org.springframework.boot:spring-boot-starter-security:$springBootVersion"
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client:3.2.4' implementation "org.thymeleaf.extras:thymeleaf-extras-springsecurity5:3.1.2.RELEASE"
implementation "org.springframework.boot:spring-boot-starter-data-jpa:$springBootVersion"
implementation "org.springframework.boot:spring-boot-starter-oauth2-client:$springBootVersion"
//2.2.x requires rebuild of DB file.. need migration path //2.2.x requires rebuild of DB file.. need migration path
implementation "com.h2database:h2:2.1.214" implementation "com.h2database:h2:2.1.214"
// implementation "com.h2database:h2:2.2.224"
} }
testImplementation 'org.springframework.boot:spring-boot-starter-test:3.2.4' testImplementation "org.springframework.boot:spring-boot-starter-test:$springBootVersion"
// Batik // Batik
implementation 'org.apache.xmlgraphics:batik-all:1.17' implementation "org.apache.xmlgraphics:batik-all:1.17"
// TwelveMonkeys // TwelveMonkeys
implementation 'com.twelvemonkeys.imageio:imageio-batik:3.10.1' implementation "com.twelvemonkeys.imageio:imageio-batik:3.10.1"
implementation 'com.twelvemonkeys.imageio:imageio-bmp:3.10.1' implementation "com.twelvemonkeys.imageio:imageio-bmp:3.10.1"
// implementation 'com.twelvemonkeys.imageio:imageio-hdr:3.10.1' // implementation "com.twelvemonkeys.imageio:imageio-hdr:3.10.1"
// implementation 'com.twelvemonkeys.imageio:imageio-icns:3.10.1' // implementation "com.twelvemonkeys.imageio:imageio-icns:3.10.1"
// implementation 'com.twelvemonkeys.imageio:imageio-iff:3.10.1' // implementation "com.twelvemonkeys.imageio:imageio-iff:3.10.1"
implementation 'com.twelvemonkeys.imageio:imageio-jpeg:3.10.1' implementation "com.twelvemonkeys.imageio:imageio-jpeg:3.11.0"
// implementation 'com.twelvemonkeys.imageio:imageio-pcx:3.10.1' // implementation "com.twelvemonkeys.imageio:imageio-pcx:3.10.1"
// implementation 'com.twelvemonkeys.imageio:imageio-pict:3.10.1' // implementation "com.twelvemonkeys.imageio:imageio-pict:3.10.1"
// implementation 'com.twelvemonkeys.imageio:imageio-pnm:3.10.1' // implementation "com.twelvemonkeys.imageio:imageio-pnm:3.10.1"
// implementation 'com.twelvemonkeys.imageio:imageio-psd:3.10.1' // implementation "com.twelvemonkeys.imageio:imageio-psd:3.10.1"
// implementation 'com.twelvemonkeys.imageio:imageio-sgi:3.10.1' // implementation "com.twelvemonkeys.imageio:imageio-sgi:3.10.1"
// implementation 'com.twelvemonkeys.imageio:imageio-tga:3.10.1' // implementation "com.twelvemonkeys.imageio:imageio-tga:3.10.1"
// implementation 'com.twelvemonkeys.imageio:imageio-thumbsdb:3.10.1' // implementation "com.twelvemonkeys.imageio:imageio-thumbsdb:3.10.1"
implementation 'com.twelvemonkeys.imageio:imageio-tiff:3.10.1' implementation "com.twelvemonkeys.imageio:imageio-tiff:3.10.1"
implementation 'com.twelvemonkeys.imageio:imageio-webp:3.10.1' implementation "com.twelvemonkeys.imageio:imageio-webp:3.10.1"
// implementation 'com.twelvemonkeys.imageio:imageio-xwd:3.10.1' // implementation "com.twelvemonkeys.imageio:imageio-xwd:3.10.1"
implementation 'commons-io:commons-io:2.16.1' implementation "commons-io:commons-io:2.16.1"
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0' implementation "org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0"
//general PDF //general PDF
// https://mvnrepository.com/artifact/com.opencsv/opencsv // https://mvnrepository.com/artifact/com.opencsv/opencsv
implementation ('com.opencsv:opencsv:5.9') { implementation ("com.opencsv:opencsv:5.9") {
exclude group: 'commons-logging', module: 'commons-logging' exclude group: "commons-logging", module: "commons-logging"
} }
implementation ('org.apache.pdfbox:pdfbox:3.0.2'){ implementation ("org.apache.pdfbox:pdfbox:3.0.2") {
exclude group: 'commons-logging', module: 'commons-logging' exclude group: "commons-logging", module: "commons-logging"
} }
implementation ('org.apache.pdfbox:xmpbox:3.0.2'){ implementation ("org.apache.pdfbox:xmpbox:3.0.2") {
exclude group: 'commons-logging', module: 'commons-logging' exclude group: "commons-logging", module: "commons-logging"
} }
implementation "com.github.Carleslc.Simple-YAML:Simple-Yaml:1.8.4"
implementation 'org.bouncycastle:bcprov-jdk18on:1.77' implementation "org.bouncycastle:bcprov-jdk18on:1.78.1"
implementation 'org.bouncycastle:bcpkix-jdk18on:1.77' implementation "org.bouncycastle:bcpkix-jdk18on:1.78.1"
implementation 'org.springframework.boot:spring-boot-starter-actuator:3.2.4' implementation "org.springframework.boot:spring-boot-starter-actuator:$springBootVersion"
implementation 'io.micrometer:micrometer-core:1.12.4' implementation "io.micrometer:micrometer-core:1.13.0"
implementation group: 'com.google.zxing', name: 'core', version: '3.5.3' implementation group: "com.google.zxing", name: "core", version: "3.5.3"
// https://mvnrepository.com/artifact/org.commonmark/commonmark // https://mvnrepository.com/artifact/org.commonmark/commonmark
implementation 'org.commonmark:commonmark:0.22.0' implementation "org.commonmark:commonmark:0.22.0"
implementation 'org.commonmark:commonmark-ext-gfm-tables:0.22.0' implementation "org.commonmark:commonmark-ext-gfm-tables:0.22.0"
// https://mvnrepository.com/artifact/com.github.vladimir-bukhtoyarov/bucket4j-core // https://mvnrepository.com/artifact/com.bucket4j/bucket4j_jdk17
implementation 'com.github.vladimir-bukhtoyarov:bucket4j-core:7.6.0' implementation "com.bucket4j:bucket4j_jdk17-core:8.12.1"
implementation 'com.fathzer:javaluator:3.0.3' implementation "com.fathzer:javaluator:3.0.4"
developmentOnly("org.springframework.boot:spring-boot-devtools:3.2.4") developmentOnly("org.springframework.boot:spring-boot-devtools:$springBootVersion")
compileOnly 'org.projectlombok:lombok:1.18.32' compileOnly "org.projectlombok:lombok:1.18.32"
annotationProcessor 'org.projectlombok:lombok:1.18.32' annotationProcessor "org.projectlombok:lombok:1.18.32"
testImplementation 'org.mockito:mockito-inline:3.12.4'
} }
tasks.withType(JavaCompile).configureEach { tasks.withType(JavaCompile).configureEach {
dependsOn 'spotlessApply' options.encoding = "UTF-8"
dependsOn "spotlessApply"
} }
compileJava { compileJava {
options.compilerArgs << '-parameters' options.compilerArgs << "-parameters"
} }
task writeVersion { task writeVersion {
def propsFile = file('src/main/resources/version.properties') def propsFile = file("src/main/resources/version.properties")
def props = new Properties() def props = new Properties()
props.setProperty('version', version) props.setProperty("version", version)
props.store(propsFile.newWriter(), null) props.store(propsFile.newWriter(), null)
} }
swaggerhubUpload { swaggerhubUpload {
//dependsOn generateOpenApiDocs // Depends on your task generating Swagger docs //dependsOn generateOpenApiDocs // Depends on your task generating Swagger docs
api 'Stirling-PDF' // The name of your API on SwaggerHub api "Stirling-PDF" // The name of your API on SwaggerHub
owner 'Frooodle' // Your SwaggerHub username (or organization name) owner "Frooodle" // Your SwaggerHub username (or organization name)
version project.version // The version of your API version project.version // The version of your API
inputFile './SwaggerDoc.json' // The path to your Swagger docs inputFile "./SwaggerDoc.json" // The path to your Swagger docs
token "${System.getenv('SWAGGERHUB_API_KEY')}" // Your SwaggerHub API key, passed as an environment variable token "${System.getenv("SWAGGERHUB_API_KEY")}" // Your SwaggerHub API key, passed as an environment variable
oas '3.0.0' // The version of the OpenAPI Specification you're using oas "3.0.0" // The version of the OpenAPI Specification you"re using
} }
jar { jar {
enabled = false enabled = false
manifest { manifest {
attributes 'Implementation-Title': 'Stirling-PDF', attributes "Implementation-Title": "Stirling-PDF",
'Implementation-Version': project.version "Implementation-Version": project.version
} }
} }
tasks.named('test') { tasks.named("test") {
useJUnitPlatform() useJUnitPlatform()
} }

View File

@@ -1,5 +1,5 @@
apiVersion: v2 apiVersion: v2
appVersion: 0.26.1 appVersion: 0.26.2
description: locally hosted web application that allows you to perform various operations description: locally hosted web application that allows you to perform various operations
on PDF files on PDF files
home: https://github.com/Stirling-Tools/Stirling-PDF home: https://github.com/Stirling-Tools/Stirling-PDF

View File

@@ -0,0 +1,106 @@
%PDF-1.3
%“Œ‹ž ReportLab Generated PDF document http://www.reportlab.com
1 0 obj
<<
/F1 2 0 R
>>
endobj
2 0 obj
<<
/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font
>>
endobj
3 0 obj
<<
/Contents 9 0 R /MediaBox [ 0 0 612 792 ] /Parent 8 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
4 0 obj
<<
/Contents 10 0 R /MediaBox [ 0 0 612 792 ] /Parent 8 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
5 0 obj
<<
/Contents 11 0 R /MediaBox [ 0 0 612 792 ] /Parent 8 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
6 0 obj
<<
/PageMode /UseNone /Pages 8 0 R /Type /Catalog
>>
endobj
7 0 obj
<<
/Author (anonymous) /CreationDate (D:20240718233034+00'00') /Creator (ReportLab PDF Library - www.reportlab.com) /Keywords () /ModDate (D:20240718233034+00'00') /Producer (ReportLab PDF Library - www.reportlab.com)
/Subject (unspecified) /Title (untitled) /Trapped /False
>>
endobj
8 0 obj
<<
/Count 3 /Kids [ 3 0 R 4 0 R 5 0 R ] /Type /Pages
>>
endobj
9 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 210
>>
stream
Gap@Gb79+X'F"5[`EfJOD4:mD<%*=m+N>oDG,>NK`<U'B^0WYY,dWl^i_UcRk`<"L=<NPC$BtQ<5l$3<Y!?BuoCSYQ6GSt25lpqr0IrP?S[b)9%M"e'HHFqcRO'9eRaR0'DYi*Y.:nEMFAoTM;rPL%EF]`CfoELVl_Q,"LS:%iI;Nc[&bG.*65O]ecfK1'*<>5P_s[usI/ph*0pV~>endstream
endobj
10 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 209
>>
stream
Gap@Gb79+X'F"5Y`EfJOV2A9=!fB]F'tK1LS`,]G+MiTenb&V2-^hqa(5IE#Nr59/!"Qm*5_(BdF!0&h!Yhk/A+\iS'%6tuO$O)9LaZS+flr([1p2&#RS1p/gT[B;rDj-=&=iqUlj(P^/5U@eCFqn4:<lU`l`.HXqG-',hJH.DI.(6L\luSAW`Q'oje[qgVLVIXg%PXe+,<$7('~>endstream
endobj
11 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 209
>>
stream
Gap@GbmK%f(e+0_`ODoa2.):e/i+N3r(.o*Qf\gSNb(bt4FIubi@GIOE=p8Ir3;CbQ@KuG^cdJhODZKQ*upt+*rdZ%!mFmN$*.P)K;`s#]G=8AO3s3DGB.RCOn?[F]bEIg,a>25?B%dh\Z/C6opFE'el@I,P\u\V\]:*JYrrsNJ&d,11VL;$h!43eGu&1X6$+5-h\Vr6!+>4Je,~>endstream
endobj
xref
0 12
0000000000 65535 f
0000000073 00000 n
0000000104 00000 n
0000000211 00000 n
0000000404 00000 n
0000000598 00000 n
0000000792 00000 n
0000000860 00000 n
0000001156 00000 n
0000001227 00000 n
0000001527 00000 n
0000001827 00000 n
trailer
<<
/ID
[<0d5cf047e754e05f8d574f067785875c><0d5cf047e754e05f8d574f067785875c>]
% ReportLab generated PDF document -- digest (http://www.reportlab.com)
/Info 7 0 R
/Root 6 0 R
/Size 12
>>
startxref
2127
%%EOF

View File

@@ -0,0 +1,106 @@
%PDF-1.3
%“Œ‹ž ReportLab Generated PDF document http://www.reportlab.com
1 0 obj
<<
/F1 2 0 R
>>
endobj
2 0 obj
<<
/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font
>>
endobj
3 0 obj
<<
/Contents 9 0 R /MediaBox [ 0 0 612 792 ] /Parent 8 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
4 0 obj
<<
/Contents 10 0 R /MediaBox [ 0 0 612 792 ] /Parent 8 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
5 0 obj
<<
/Contents 11 0 R /MediaBox [ 0 0 612 792 ] /Parent 8 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
6 0 obj
<<
/PageMode /UseNone /Pages 8 0 R /Type /Catalog
>>
endobj
7 0 obj
<<
/Author (anonymous) /CreationDate (D:20240718233034+00'00') /Creator (ReportLab PDF Library - www.reportlab.com) /Keywords () /ModDate (D:20240718233034+00'00') /Producer (ReportLab PDF Library - www.reportlab.com)
/Subject (unspecified) /Title (untitled) /Trapped /False
>>
endobj
8 0 obj
<<
/Count 3 /Kids [ 3 0 R 4 0 R 5 0 R ] /Type /Pages
>>
endobj
9 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 207
>>
stream
Gap@G:CDb.*/<p2MVk["e@)7*Z0@"b%+@f/9pA%_U<oOkVp?PnGRb81iPg?0i?(]%^_CSf##%;<!7Ne/-%RR^p@t7hKYZ9eJVHV]fjjHIB:6DrW+2\p16@*`r^CpQZZH'2Pjqd<.&hM2UO%$Wi$te%4QmS;<E"QS\!deQG_XtuEK>b(UbS>%`/0S`k\\5'TNY0mmgH?`8]i_0~>endstream
endobj
10 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 207
>>
stream
Gap@G]afWJ'Lm;=if<;s>V*7BTJ]oQ@P!(q5S+WG1%>L@?8Ue;c>[fY&&IOd5@t@TY@+q.5T<Z'81"J("KhsBa+&u4"n'#6)AjfImh)%$0tVC:aGk",=aJJH#/4]i.WJr9c"cibYm:M-44<%FFlG0Cl\Z'nmo7C"TR+7dk3T#iD(9Pq'\;rQku%o>A_`50SO&7M04=8M'O<Am~>endstream
endobj
11 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 209
>>
stream
Gap@GYmu@>'Ld5[if35r/JNaJ.A.7fP9RpSN*8k^-sEER0,enq1Rsuo@R/uCO-^&Y`F'9d^a?9)?ns+F&dXm[HMgPn6Ep+%TRk5Nh+!(+[H#H:U^.^(YL,PKS'%j/:3O\hJVEK-UUekJTd[A$N^((K^#0Du`i@,/^f5KiUISGr")3/+f9NF8NO1+iUgm^b"X\cE^+[:s!0]Gu6i~>endstream
endobj
xref
0 12
0000000000 65535 f
0000000073 00000 n
0000000104 00000 n
0000000211 00000 n
0000000404 00000 n
0000000598 00000 n
0000000792 00000 n
0000000860 00000 n
0000001156 00000 n
0000001227 00000 n
0000001524 00000 n
0000001822 00000 n
trailer
<<
/ID
[<407fc55425168745e56176202aad30c9><407fc55425168745e56176202aad30c9>]
% ReportLab generated PDF document -- digest (http://www.reportlab.com)
/Info 7 0 R
/Root 6 0 R
/Size 12
>>
startxref
2122
%%EOF

View File

@@ -0,0 +1,106 @@
%PDF-1.3
%“Œ‹ž ReportLab Generated PDF document http://www.reportlab.com
1 0 obj
<<
/F1 2 0 R
>>
endobj
2 0 obj
<<
/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font
>>
endobj
3 0 obj
<<
/Contents 9 0 R /MediaBox [ 0 0 612 792 ] /Parent 8 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
4 0 obj
<<
/Contents 10 0 R /MediaBox [ 0 0 612 792 ] /Parent 8 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
5 0 obj
<<
/Contents 11 0 R /MediaBox [ 0 0 612 792 ] /Parent 8 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
6 0 obj
<<
/PageMode /UseNone /Pages 8 0 R /Type /Catalog
>>
endobj
7 0 obj
<<
/Author (anonymous) /CreationDate (D:20240718233034+00'00') /Creator (ReportLab PDF Library - www.reportlab.com) /Keywords () /ModDate (D:20240718233034+00'00') /Producer (ReportLab PDF Library - www.reportlab.com)
/Subject (unspecified) /Title (untitled) /Trapped /False
>>
endobj
8 0 obj
<<
/Count 3 /Kids [ 3 0 R 4 0 R 5 0 R ] /Type /Pages
>>
endobj
9 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 209
>>
stream
Gap@G]+0EH(e/_@iZH]:>:>hu1e>07BJg5<'#:.C1n)e#(QJ6R1Rsuo_gpn.+0-H5$/#"iYR[B.9\'>7!aDAC*rf/t&6O#aH<?-7IT'\?X(&TcABG=ON*Nq`4k=o&p@3,0*31r<)TAP2Pk94p0\"R-_sY1$AYo[8B\?4R>feLAB\mpjZhp"`@J3;"Fm97#9+W,"eb95\+#p\^HN~>endstream
endobj
10 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 209
>>
stream
Gap@G]+0EX'Eriuig+>QHNeD'#n%Sq#n%BW`C'uDUOYK)HdS4E9JMsp+HUmDj&H-t*4?UamXX0peVspk"i_@ba+&u"J>UYDKV_^G,7V==aTZZ<YO7:sNSQ[6"Ja-29NtYjd#=`J@D'h+[QW=:EEb?A<k!f+\`g^?,Vgp7_)91[lR\f.Tkf7VIPLVYM&deF!aYt9Ip^"N",3F'*W~>endstream
endobj
11 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 209
>>
stream
Gap@G]+0EH(e/_@iZH]:>J`g!jPCLm;?AgU"fdk"PQZD\d?lRI_oWc[$tp^]O\:3fK8kWeX2&Jcg0+RoJ]j;2j*upu!b4.o&f)b$I@7CfIYjP^#\VjhC=QhQ]^lV-@<0Tam!0.+Dn@("AK%N,Uc7hb+6VoQ$q2q[7]BB92RoY/.j2N028i1jNf'@<1+Fqf$1&"8omHk`#DHP>OT~>endstream
endobj
xref
0 12
0000000000 65535 f
0000000073 00000 n
0000000104 00000 n
0000000211 00000 n
0000000404 00000 n
0000000598 00000 n
0000000792 00000 n
0000000860 00000 n
0000001156 00000 n
0000001227 00000 n
0000001526 00000 n
0000001826 00000 n
trailer
<<
/ID
[<80da26147a484f2b7573da8151a93d2e><80da26147a484f2b7573da8151a93d2e>]
% ReportLab generated PDF document -- digest (http://www.reportlab.com)
/Info 7 0 R
/Root 6 0 R
/Size 12
>>
startxref
2126
%%EOF

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,106 @@
%PDF-1.3
%“Œ‹ž ReportLab Generated PDF document http://www.reportlab.com
1 0 obj
<<
/F1 2 0 R
>>
endobj
2 0 obj
<<
/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font
>>
endobj
3 0 obj
<<
/Contents 9 0 R /MediaBox [ 0 0 612 792 ] /Parent 8 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
4 0 obj
<<
/Contents 10 0 R /MediaBox [ 0 0 612 792 ] /Parent 8 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
5 0 obj
<<
/Contents 11 0 R /MediaBox [ 0 0 612 792 ] /Parent 8 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
6 0 obj
<<
/PageMode /UseNone /Pages 8 0 R /Type /Catalog
>>
endobj
7 0 obj
<<
/Author (anonymous) /CreationDate (D:20240718233034+00'00') /Creator (ReportLab PDF Library - www.reportlab.com) /Keywords () /ModDate (D:20240718233034+00'00') /Producer (ReportLab PDF Library - www.reportlab.com)
/Subject (unspecified) /Title (untitled) /Trapped /False
>>
endobj
8 0 obj
<<
/Count 3 /Kids [ 3 0 R 4 0 R 5 0 R ] /Type /Pages
>>
endobj
9 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 206
>>
stream
Gap@G\IO3f&4Lr[@S4&T2aReWZ3N'9",Ncra>5AuK^J(o@r?=EP>b]h[L@XZ8q7#[c:#H2:^/=b,p3^,&f-Q.'H%!U?%N\iVa1pLMlh/41\A8@dF5@0al:-1?L;D%LpL3g\9`.3c6N/Mp=sE/nO%^@%Cc3`]e`qqS@[pkUWemMZC<P\fkqa55u)*hIUoU437-gb!e_*&B/,&~>endstream
endobj
10 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 209
>>
stream
Gap@G\IO3V'LdA_ig"8P1PS=kA5Q_GQ\P]*S3\>Q`jHYt?8UdkV`6]UV*On)+1VMV+A@.iF:*6sWfM9f"s.NmVuMto!p7-+,Rb<.h,pdi-&OQ5KO\RRFj.j"A)ScTQ7$hudF^TnZ'XuQA5"O]rYkt><-DJmj'"Ri>n!4`^m409XX`e)AR'*rGsn6m79.18+^ba=qRuss"-A3k+9~>endstream
endobj
11 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 210
>>
stream
Gap@G]+0EH(e/_@iZH]:.1fBHK`Xl'[i1&AjX(\k8hbgo(QJ6R1Rsuo6_I1A5Gg$JL;D#$J2CX;+Cf*cUHk2%H1XmpWe+qZ5moJ#B]>b%%[d,mfSSkS4A:Q4NlOFfrL7eA,s45"eUSakM;927AA,1"-LZ)&nZ/ah=8_X7:?ZMj@J@;r7d`t]Z0\d39M%:$k8[S5D"2oSap4s80l?~>endstream
endobj
xref
0 12
0000000000 65535 f
0000000073 00000 n
0000000104 00000 n
0000000211 00000 n
0000000404 00000 n
0000000598 00000 n
0000000792 00000 n
0000000860 00000 n
0000001156 00000 n
0000001227 00000 n
0000001523 00000 n
0000001823 00000 n
trailer
<<
/ID
[<88edee24ee67bd7d6b7cf53cfa2222b0><88edee24ee67bd7d6b7cf53cfa2222b0>]
% ReportLab generated PDF document -- digest (http://www.reportlab.com)
/Info 7 0 R
/Root 6 0 R
/Size 12
>>
startxref
2124
%%EOF

View File

@@ -0,0 +1,106 @@
%PDF-1.3
%“Œ‹ž ReportLab Generated PDF document http://www.reportlab.com
1 0 obj
<<
/F1 2 0 R
>>
endobj
2 0 obj
<<
/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font
>>
endobj
3 0 obj
<<
/Contents 9 0 R /MediaBox [ 0 0 612 792 ] /Parent 8 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
4 0 obj
<<
/Contents 10 0 R /MediaBox [ 0 0 612 792 ] /Parent 8 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
5 0 obj
<<
/Contents 11 0 R /MediaBox [ 0 0 612 792 ] /Parent 8 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
6 0 obj
<<
/PageMode /UseNone /Pages 8 0 R /Type /Catalog
>>
endobj
7 0 obj
<<
/Author (anonymous) /CreationDate (D:20240718233034+00'00') /Creator (ReportLab PDF Library - www.reportlab.com) /Keywords () /ModDate (D:20240718233034+00'00') /Producer (ReportLab PDF Library - www.reportlab.com)
/Subject (unspecified) /Title (untitled) /Trapped /False
>>
endobj
8 0 obj
<<
/Count 3 /Kids [ 3 0 R 4 0 R 5 0 R ] /Type /Pages
>>
endobj
9 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 209
>>
stream
Gap@GYmu@>'Ld5[if35rI0]sG)F[U^"c>T)"\\os-r:1V0,enq1Rsuo,*67.@k7U.LRF-P.e"CM2V!>iYi<g`nXh!K?n@$t^rY1$+^0'>=B8H6e;F1WmG#,(eS00(Qe9&:O@nI879DTsT,njXAB?`8:>,Hn3*RV!qh4;&@6%]<9Y*>QZ].Z5o;RAZXg7d[#+bphHs_Ep!QR2TZ2~>endstream
endobj
10 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 210
>>
stream
Gap@G]+0EH(e/_@iZH]:>=,iY1bE)XN?M;1'J/>i&HY;gks]*rj:!DKpb8@`prC#N+9E#o#-<G*!#p7e6j-1sX2k5S,6XmM"taYkfK^k">%usEeEk=sR<UT"dm`rXD;!S`_jS9LU+(R%e'V%WSMfHP.pXZEQqTQq=&D[I[PS(41(NIAZ1R/U?:Z=hSXu!NDF)bpG2F+/I/q/u1-Y~>endstream
endobj
11 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 209
>>
stream
Gap@G_$YcZ'LhbF`EQB$nqi=8S<;#HbK3&f>rnodRPo`Vf4P[3cJidY(I=[K5NWCT'<lHgci?oCRVNST&[k#q4oSC0FWgAt1pD4d_(hIRjn_Nt+cFgJlfm[1U8@/M4r^Pk<@F!@e?%/!-Vq;]nfdLi9]P2M)ck9?)%oNXa_\N<-d"(pjlH%-G`T@Sj&P(j6.@#Xh\Vr6!1iI2/H~>endstream
endobj
xref
0 12
0000000000 65535 f
0000000073 00000 n
0000000104 00000 n
0000000211 00000 n
0000000404 00000 n
0000000598 00000 n
0000000792 00000 n
0000000860 00000 n
0000001156 00000 n
0000001227 00000 n
0000001526 00000 n
0000001827 00000 n
trailer
<<
/ID
[<4fcc82a085fe71e34a32d1b23c8b939f><4fcc82a085fe71e34a32d1b23c8b939f>]
% ReportLab generated PDF document -- digest (http://www.reportlab.com)
/Info 7 0 R
/Root 6 0 R
/Size 12
>>
startxref
2127
%%EOF

View File

@@ -14,3 +14,8 @@ def after_scenario(context, scenario):
os.remove('response_file') os.remove('response_file')
if hasattr(context, 'file_name') and os.path.exists(context.file_name): if hasattr(context, 'file_name') and os.path.exists(context.file_name):
os.remove(context.file_name) os.remove(context.file_name)
# Remove any temporary files
for temp_file in os.listdir('.'):
if temp_file.startswith('genericNonCustomisableName') or temp_file.startswith('temp_image_'):
os.remove(temp_file)

View File

@@ -1,4 +1,4 @@
@example @example @general
Feature: API Validation Feature: API Validation
@positive @password @positive @password

View File

@@ -32,7 +32,7 @@ Feature: API Validation
@ocr @positive @ocr @positive
Scenario: Extract Image Scans Scenario: Extract Image Scans
Given I generate a PDF file as "fileInput" Given I generate a PDF file as "fileInput"
And the pdf contains 3 images on 2 pages And the pdf contains 3 images of size 300x300 on 2 pages
And the request data includes And the request data includes
| parameter | value | | parameter | value |
| angleThreshold | 5 | | angleThreshold | 5 |
@@ -125,8 +125,7 @@ Feature: API Validation
@ocr @ocr
Scenario: PDFA Scenario: PDFA
Given I generate a PDF file as "fileInput" Given I use an example file at "exampleFiles/pdfa2.pdf" as parameter "fileInput"
And the pdf contains 3 pages with random text
And the request data includes And the request data includes
| parameter | value | | parameter | value |
| outputFormat | pdfa | | outputFormat | pdfa |
@@ -137,8 +136,7 @@ Feature: API Validation
@ocr @ocr
Scenario: PDFA1 Scenario: PDFA1
Given I generate a PDF file as "fileInput" Given I use an example file at "exampleFiles/pdfa1.pdf" as parameter "fileInput"
And the pdf contains 3 pages with random text
And the request data includes And the request data includes
| parameter | value | | parameter | value |
| outputFormat | pdfa-1 | | outputFormat | pdfa-1 |
@@ -149,8 +147,7 @@ Feature: API Validation
@compress @ghostscript @positive @compress @ghostscript @positive
Scenario: Compress Scenario: Compress
Given I generate a PDF file as "fileInput" Given I use an example file at "exampleFiles/ghost3.pdf" as parameter "fileInput"
And the pdf contains 3 pages with random text
And the request data includes And the request data includes
| parameter | value | | parameter | value |
| optimizeLevel | 4 | | optimizeLevel | 4 |
@@ -161,8 +158,7 @@ Feature: API Validation
@compress @ghostscript @positive @compress @ghostscript @positive
Scenario: Compress Scenario: Compress
Given I generate a PDF file as "fileInput" Given I use an example file at "exampleFiles/ghost2.pdf" as parameter "fileInput"
And the pdf contains 3 pages with random text
And the request data includes And the request data includes
| parameter | value | | parameter | value |
| optimizeLevel | 1 | | optimizeLevel | 1 |
@@ -175,8 +171,7 @@ Feature: API Validation
@compress @ghostscript @positive @compress @ghostscript @positive
Scenario: Compress Scenario: Compress
Given I generate a PDF file as "fileInput" Given I use an example file at "exampleFiles/ghost1.pdf" as parameter "fileInput"
And the pdf contains 3 pages with random text
And the request data includes And the request data includes
| parameter | value | | parameter | value |
| optimizeLevel | 1 | | optimizeLevel | 1 |

View File

@@ -94,3 +94,23 @@ Feature: API Validation
| 1 | 10 | 2 | 10 | | 1 | 10 | 2 | 10 |
@extract-images
Scenario Outline: Extract Image Scans
Given I use an example file at "exampleFiles/images.pdf" as parameter "fileInput"
And the request data includes
| parameter | value |
| format | <format> |
When I send the API request to the endpoint "/api/v1/misc/extract-images"
Then the response content type should be "application/octet-stream"
And the response file should have extension ".zip"
And the response ZIP should contain 20 files
And the response file should have size greater than 0
And the response status code should be 200
Examples:
| format |
| png |
| gif |
| jpeg |

View File

@@ -6,11 +6,14 @@ import io
import random import random
import string import string
from reportlab.lib.pagesizes import letter from reportlab.lib.pagesizes import letter
from reportlab.lib.utils import ImageReader
from reportlab.pdfgen import canvas from reportlab.pdfgen import canvas
import mimetypes import mimetypes
import requests import requests
import zipfile import zipfile
import shutil import shutil
import re
from PIL import Image, ImageDraw
######### #########
# GIVEN # # GIVEN #
@@ -43,8 +46,6 @@ def step_use_example_file(context, filePath, fileInput):
except FileNotFoundError: except FileNotFoundError:
raise FileNotFoundError(f"The example file '{filePath}' does not exist.") raise FileNotFoundError(f"The example file '{filePath}' does not exist.")
@given('the pdf contains {page_count:d} pages') @given('the pdf contains {page_count:d} pages')
def step_pdf_contains_pages(context, page_count): def step_pdf_contains_pages(context, page_count):
writer = PdfWriter() writer = PdfWriter()
@@ -66,8 +67,6 @@ def step_pdf_contains_blank_pages(context, page_count):
context.files[context.param_name].close() context.files[context.param_name].close()
context.files[context.param_name] = open(context.file_name, 'rb') context.files[context.param_name] = open(context.file_name, 'rb')
def create_black_box_image(file_name, size): def create_black_box_image(file_name, size):
can = canvas.Canvas(file_name, pagesize=size) can = canvas.Canvas(file_name, pagesize=size)
width, height = size width, height = size
@@ -76,36 +75,75 @@ def create_black_box_image(file_name, size):
can.showPage() can.showPage()
can.save() can.save()
def create_pdf_with_black_boxes(file_name, image_count, page_count): @given(u'the pdf contains {image_count:d} images of size {width:d}x{height:d} on {page_count:d} pages')
page_width, page_height = letter def step_impl(context, image_count, width, height, page_count):
box_size = 72 # 1 inch by 1 inch black box context.param_name = "fileInput"
context.file_name = "genericNonCustomisableName.pdf"
create_pdf_with_images_and_boxes(context.file_name, image_count, page_count, width, height)
if not hasattr(context, 'files'):
context.files = {}
context.files[context.param_name] = open(context.file_name, 'rb')
def add_black_boxes_to_image(image):
if isinstance(image, str):
image = Image.open(image)
draw = ImageDraw.Draw(image)
draw.rectangle([(0, 0), image.size], fill=(0, 0, 0)) # Fill image with black
return image
def create_pdf_with_images_and_boxes(file_name, image_count, page_count, image_width, image_height):
page_width, page_height = max(letter[0], image_width), max(letter[1], image_height)
boxes_per_page = image_count // page_count + (1 if image_count % page_count != 0 else 0) boxes_per_page = image_count // page_count + (1 if image_count % page_count != 0 else 0)
writer = PdfWriter() writer = PdfWriter()
box_counter = 0 box_counter = 0
for page in range(page_count): for page in range(page_count):
packet = io.BytesIO() packet = io.BytesIO()
can = canvas.Canvas(packet, pagesize=letter) can = canvas.Canvas(packet, pagesize=(page_width, page_height))
for i in range(boxes_per_page): for i in range(boxes_per_page):
if box_counter >= image_count: if box_counter >= image_count:
break break
x = (i % (page_width // box_size)) * box_size
y = page_height - ((i // (page_width // box_size) + 1) * box_size) # Simulating a dynamic image creation (replace this with your actual image creation logic)
can.setFillColorRGB(0, 0, 0) # For demonstration, we'll create a simple black image
can.rect(x, y, box_size, box_size, fill=1) dummy_image = Image.new('RGB', (image_width, image_height), color='white') # Create a white image
dummy_image = add_black_boxes_to_image(dummy_image) # Add black boxes
# Convert the PIL Image to bytes to pass to drawImage
image_bytes = io.BytesIO()
dummy_image.save(image_bytes, format='PNG')
image_bytes.seek(0)
# Check if the image fits in the current page dimensions
x = (i % (page_width // image_width)) * image_width
y = page_height - (((i % (page_height // image_height)) + 1) * image_height)
if x + image_width > page_width or y < 0:
break
# Add the image to the PDF
can.drawImage(ImageReader(image_bytes), x, y, width=image_width, height=image_height)
box_counter += 1 box_counter += 1
can.showPage() can.showPage()
can.save() can.save()
packet.seek(0) packet.seek(0)
new_pdf = PdfReader(packet) new_pdf = PdfReader(packet)
writer.add_page(new_pdf.pages[0]) writer.add_page(new_pdf.pages[0])
# Write the PDF to file
with open(file_name, 'wb') as f: with open(file_name, 'wb') as f:
writer.write(f) writer.write(f)
# Clean up temporary image files
for i in range(image_count):
temp_image_path = f"temp_image_{i}.png"
if os.path.exists(temp_image_path):
os.remove(temp_image_path)
@given('the pdf contains {image_count:d} images on {page_count:d} pages') @given('the pdf contains {image_count:d} images on {page_count:d} pages')
def step_pdf_contains_images(context, image_count, page_count): def step_pdf_contains_images(context, image_count, page_count):
if not hasattr(context, 'param_name'): if not hasattr(context, 'param_name'):
@@ -118,7 +156,6 @@ def step_pdf_contains_images(context, image_count, page_count):
context.files[context.param_name].close() context.files[context.param_name].close()
context.files[context.param_name] = open(context.file_name, 'rb') context.files[context.param_name] = open(context.file_name, 'rb')
@given('the pdf contains {page_count:d} pages with random text') @given('the pdf contains {page_count:d} pages with random text')
def step_pdf_contains_pages_with_random_text(context, page_count): def step_pdf_contains_pages_with_random_text(context, page_count):
buffer = io.BytesIO() buffer = io.BytesIO()
@@ -186,6 +223,21 @@ def save_generated_pdf(context, filename):
# WHEN # # WHEN #
######## ########
@when('I send a GET request to "{endpoint}"')
def step_send_get_request(context, endpoint):
base_url = "http://localhost:8080"
full_url = f"{base_url}{endpoint}"
response = requests.get(full_url)
context.response = response
@when('I send a GET request to "{endpoint}" with parameters')
def step_send_get_request_with_params(context, endpoint):
base_url = "http://localhost:8080"
params = {row['parameter']: row['value'] for row in context.table}
full_url = f"{base_url}{endpoint}"
response = requests.get(full_url, params=params)
context.response = response
@when('I send the API request to the endpoint "{endpoint}"') @when('I send the API request to the endpoint "{endpoint}"')
def step_send_api_request(context, endpoint): def step_send_api_request(context, endpoint):
url = f"http://localhost:8080{endpoint}" url = f"http://localhost:8080{endpoint}"
@@ -278,7 +330,6 @@ def step_save_response_file(context, filename):
f.write(context.response.content) f.write(context.response.content)
print(f"Saved response content to {filename}") print(f"Saved response content to {filename}")
@then('the response PDF should contain {page_count:d} pages') @then('the response PDF should contain {page_count:d} pages')
def step_check_response_pdf_page_count(context, page_count): def step_check_response_pdf_page_count(context, page_count):
response_file = io.BytesIO(context.response.content) response_file = io.BytesIO(context.response.content)
@@ -305,3 +356,26 @@ def step_check_response_zip_doc_page_count(context, doc_count, pages_per_doc):
reader = PdfReader(pdf_file) reader = PdfReader(pdf_file)
actual_pages_per_doc = len(reader.pages) actual_pages_per_doc = len(reader.pages)
assert actual_pages_per_doc == pages_per_doc, f"Expected {pages_per_doc} pages per document but got {actual_pages_per_doc} pages in document {file_name}" assert actual_pages_per_doc == pages_per_doc, f"Expected {pages_per_doc} pages per document but got {actual_pages_per_doc} pages in document {file_name}"
@then('the JSON value of "{key}" should be "{expected_value}"')
def step_check_json_value(context, key, expected_value):
actual_value = context.response.json().get(key)
assert actual_value == expected_value, \
f"Expected JSON value for '{key}' to be '{expected_value}' but got '{actual_value}'"
@then('JSON list entry containing "{identifier_key}" as "{identifier_value}" should have "{target_key}" as "{target_value}"')
def step_check_json_list_entry(context, identifier_key, identifier_self, target_key, target_value):
json_response = context.response.json()
for entry in json_response:
if entry.get(identifier_key) == identifier_value:
assert entry.get(target_key) == target_value, \
f"Expected {target_key} to be {target_value} in entry where {identifier_key} is {identifier_value}, but found {entry.get(target_key)}"
break
else:
raise AssertionError(f"No entry with {identifier_key} as {identifier_value} found")
@then('the response should match the regex "{pattern}"')
def step_response_matches_regex(context, pattern):
response_text = context.response.text
assert re.match(pattern, response_text), \
f"Response '{response_text}' does not match the expected pattern '{pattern}'"

View File

@@ -22,7 +22,6 @@ services:
DOCKER_ENABLE_SECURITY: "false" DOCKER_ENABLE_SECURITY: "false"
SECURITY_ENABLELOGIN: "false" 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" 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"
INSTALL_BOOK_AND_ADVANCED_HTML_OPS: "true"
SYSTEM_DEFAULTLOCALE: en-US SYSTEM_DEFAULTLOCALE: en-US
UI_APPNAME: Stirling-PDF UI_APPNAME: Stirling-PDF
UI_HOMEDESCRIPTION: Demo site for Stirling-PDF Latest UI_HOMEDESCRIPTION: Demo site for Stirling-PDF Latest

View File

@@ -79,7 +79,9 @@ def write_readme(progress_list: list[tuple[str, int]]) -> None:
file.writelines(content) file.writelines(content)
def compare_files(default_file_path, file_paths, translation_status_file) -> list[tuple[str, int]]: def compare_files(
default_file_path, file_paths, ignore_translation_file
) -> list[tuple[str, int]]:
"""Compares the default properties file with other """Compares the default properties file with other
properties files in the directory. properties files in the directory.
@@ -92,18 +94,24 @@ def compare_files(default_file_path, file_paths, translation_status_file) -> lis
language and progress percentage. language and progress percentage.
""" # noqa: D205 """ # noqa: D205
num_lines = sum( num_lines = sum(
1 for line in open(default_file_path, encoding="utf-8") if line.strip() and not line.strip().startswith("#") 1
for line in open(default_file_path, encoding="utf-8")
if line.strip() and not line.strip().startswith("#")
) )
result_list = [] result_list = []
sort_translation_status: tomlkit.TOMLDocument sort_ignore_translation: tomlkit.TOMLDocument
# read toml # read toml
with open(translation_status_file, encoding="utf-8") as f: with open(ignore_translation_file, encoding="utf-8") as f:
sort_translation_status = tomlkit.parse(f.read()) sort_ignore_translation = tomlkit.parse(f.read())
for file_path in file_paths: for file_path in file_paths:
language = os.path.basename(file_path).split("messages_", 1)[1].split(".properties", 1)[0] language = (
os.path.basename(file_path)
.split("messages_", 1)[1]
.split(".properties", 1)[0]
)
fails = 0 fails = 0
if "en_GB" in language or "en_US" in language: if "en_GB" in language or "en_US" in language:
@@ -111,21 +119,25 @@ def compare_files(default_file_path, file_paths, translation_status_file) -> lis
result_list.append(("en_US", 100)) result_list.append(("en_US", 100))
continue continue
if language not in sort_translation_status: if language not in sort_ignore_translation:
sort_translation_status[language] = tomlkit.table() sort_ignore_translation[language] = tomlkit.table()
if ( if (
"ignore" not in sort_translation_status[language] "ignore" not in sort_ignore_translation[language]
or len(sort_translation_status[language].get("ignore", [])) < 1 or len(sort_ignore_translation[language].get("ignore", [])) < 1
): ):
sort_translation_status[language]["ignore"] = tomlkit.array(["language.direction"]) sort_ignore_translation[language]["ignore"] = tomlkit.array(
["language.direction"]
)
# if "missing" not in sort_translation_status[language]: # if "missing" not in sort_ignore_translation[language]:
# sort_translation_status[language]["missing"] = tomlkit.array() # sort_ignore_translation[language]["missing"] = tomlkit.array()
# elif "language.direction" in sort_translation_status[language]["missing"]: # elif "language.direction" in sort_ignore_translation[language]["missing"]:
# sort_translation_status[language]["missing"].remove("language.direction") # sort_ignore_translation[language]["missing"].remove("language.direction")
with open(default_file_path, encoding="utf-8") as default_file, open(file_path, encoding="utf-8") as file: with open(default_file_path, encoding="utf-8") as default_file, open(
file_path, encoding="utf-8"
) as file:
for _ in range(5): for _ in range(5):
next(default_file) next(default_file)
try: try:
@@ -133,34 +145,45 @@ def compare_files(default_file_path, file_paths, translation_status_file) -> lis
except StopIteration: except StopIteration:
fails = num_lines fails = num_lines
for line_num, (line_default, line_file) in enumerate(zip(default_file, file), start=6): for line_num, (line_default, line_file) in enumerate(
zip(default_file, file), start=6
):
try: try:
# Ignoring empty lines and lines start with # # Ignoring empty lines and lines start with #
if line_default.strip() == "" or line_default.startswith("#"): if line_default.strip() == "" or line_default.startswith("#"):
continue continue
default_key, default_value = line_default.split("=", 1) default_key, default_value = line_default.split("=", 1)
file_key, file_value = line_file.split("=", 1) file_key, file_value = line_file.split("=", 1)
if ( if (
default_value.strip() == file_value.strip() default_value.strip() == file_value.strip()
and default_key.strip() not in sort_translation_status[language]["ignore"] and default_key.strip()
not in sort_ignore_translation[language]["ignore"]
): ):
print(f"{language}: Line {line_num} is missing the translation.") print(
# if default_key.strip() not in sort_translation_status[language]["missing"]: f"{language}: Line {line_num} is missing the translation."
)
# if default_key.strip() not in sort_ignore_translation[language]["missing"]:
# missing_array = tomlkit.array() # missing_array = tomlkit.array()
# missing_array.append(default_key.strip()) # missing_array.append(default_key.strip())
# missing_array.multiline(True) # missing_array.multiline(True)
# sort_translation_status[language]["missing"].extend(missing_array) # sort_ignore_translation[language]["missing"].extend(missing_array)
fails += 1 fails += 1
# elif default_key.strip() in sort_translation_status[language]["ignore"]: # elif default_key.strip() in sort_ignore_translation[language]["ignore"]:
# if default_key.strip() in sort_translation_status[language]["missing"]: # if default_key.strip() in sort_ignore_translation[language]["missing"]:
# sort_translation_status[language]["missing"].remove(default_key.strip()) # sort_ignore_translation[language]["missing"].remove(default_key.strip())
if default_value.strip() != file_value.strip(): if default_value.strip() != file_value.strip():
# if default_key.strip() in sort_translation_status[language]["missing"]: # if default_key.strip() in sort_ignore_translation[language]["missing"]:
# sort_translation_status[language]["missing"].remove(default_key.strip()) # sort_ignore_translation[language]["missing"].remove(default_key.strip())
if default_key.strip() in sort_translation_status[language]["ignore"]: if (
sort_translation_status[language]["ignore"].remove(default_key.strip()) default_key.strip()
in sort_ignore_translation[language]["ignore"]
):
sort_ignore_translation[language]["ignore"].remove(
default_key.strip()
)
except ValueError:
print(f"{line_default}|{line_file}")
exit(1)
except IndexError: except IndexError:
pass pass
@@ -171,9 +194,9 @@ def compare_files(default_file_path, file_paths, translation_status_file) -> lis
int((num_lines - fails) * 100 / num_lines), int((num_lines - fails) * 100 / num_lines),
) )
) )
translation_status = convert_to_multiline(sort_translation_status) ignore_translation = convert_to_multiline(sort_ignore_translation)
with open(translation_status_file, "w", encoding="utf-8") as file: with open(ignore_translation_file, "w", encoding="utf-8") as file:
file.write(tomlkit.dumps(translation_status)) file.write(tomlkit.dumps(ignore_translation))
unique_data = list(set(result_list)) unique_data = list(set(result_list))
unique_data.sort(key=lambda x: x[1], reverse=True) unique_data.sort(key=lambda x: x[1], reverse=True)
@@ -187,6 +210,8 @@ if __name__ == "__main__":
reference_file = os.path.join(directory, "messages_en_GB.properties") reference_file = os.path.join(directory, "messages_en_GB.properties")
scripts_directory = os.path.join(os.getcwd(), "scripts") scripts_directory = os.path.join(os.getcwd(), "scripts")
translation_state_file = os.path.join(scripts_directory, "translation_status.toml") translation_state_file = os.path.join(scripts_directory, "ignore_translation.toml")
write_readme(compare_files(reference_file, messages_file_paths, translation_state_file)) write_readme(
compare_files(reference_file, messages_file_paths, translation_state_file)
)

View File

@@ -10,7 +10,11 @@ ignore = [
[ca_CA] [ca_CA]
ignore = [ ignore = [
'PDFToText.tags',
'adminUserSettings.admin',
'language.direction', 'language.direction',
'survey.button',
'watermark.type.1',
] ]
[cs_CZ] [cs_CZ]
@@ -48,6 +52,7 @@ ignore = [
ignore = [ ignore = [
'adminUserSettings.roles', 'adminUserSettings.roles',
'color', 'color',
'error',
'language.direction', 'language.direction',
'no', 'no',
'showJS.tags', 'showJS.tags',
@@ -60,8 +65,26 @@ ignore = [
[fr_FR] [fr_FR]
ignore = [ ignore = [
'AddStampRequest.alphabet',
'AddStampRequest.position',
'AddStampRequest.rotation',
'PDFToBook.selectText.1',
'addPageNumbers.selectText.3',
'adminUserSettings.actions',
'alphabet',
'compare.document.1',
'compare.document.2',
'info',
'language.direction', 'language.direction',
'licenses.license',
'licenses.module',
'licenses.nav',
'licenses.version',
'pdfOrganiser.mode',
'pipeline.title',
'pipelineOptions.pipelineHeader',
'sponsor', 'sponsor',
'watermark.type.2',
] ]
[hi_IN] [hi_IN]
@@ -71,6 +94,7 @@ ignore = [
[hr_HR] [hr_HR]
ignore = [ ignore = [
'PDFToBook.selectText.1',
'font', 'font',
'home.pipeline.title', 'home.pipeline.title',
'info', 'info',
@@ -114,16 +138,34 @@ ignore = [
[nl_NL] [nl_NL]
ignore = [ ignore = [
'HTMLToPDF.print',
'adjustContrast.contrast',
'compare.document.1',
'compare.document.2',
'error',
'getPdfInfo.downloadJson',
'help',
'info',
'language.direction', 'language.direction',
'navbar.allTools',
'printFile.submit',
'showJS.downloadJS',
'sponsor',
] ]
[no_NB] [no_NB]
ignore = [ ignore = [
'PDFToBook.selectText.1',
'adminUserSettings.admin',
'info',
'language.direction', 'language.direction',
'oops',
'sponsor',
] ]
[pl_PL] [pl_PL]
ignore = [ ignore = [
'PDFToBook.selectText.1',
'language.direction', 'language.direction',
] ]
@@ -149,12 +191,20 @@ ignore = [
[sk_SK] [sk_SK]
ignore = [ ignore = [
'adminUserSettings.admin',
'home.multiTool.title',
'info',
'language.direction', 'language.direction',
'navbar.sections.security',
'text',
'watermark.type.1',
] ]
[sr_LATN_RS] [sr_LATN_RS]
ignore = [ ignore = [
'language.direction', 'language.direction',
'licenses.version',
'poweredBy',
] ]
[sv_SE] [sv_SE]
@@ -162,6 +212,14 @@ ignore = [
'language.direction', 'language.direction',
] ]
[th_TH]
ignore = [
'language.direction',
'pipeline.title',
'pipelineOptions.pipelineHeader',
'showJS.tags',
]
[tr_TR] [tr_TR]
ignore = [ ignore = [
'language.direction', 'language.direction',

View File

@@ -12,7 +12,8 @@ fi
umask "$UMASK" || true umask "$UMASK" || true
if [[ "$INSTALL_BOOK_AND_ADVANCED_HTML_OPS" == "true" && "$FAT_DOCKER" != "true" ]]; then if [[ "$INSTALL_BOOK_AND_ADVANCED_HTML_OPS" == "true" && "$FAT_DOCKER" != "true" ]]; then
apk add --no-cache calibre@testing echo "issue with calibre in current version, feature currently disabled on Stirling-PDF"
#apk add --no-cache calibre@testing
fi fi
if [[ "$FAT_DOCKER" != "true" ]]; then if [[ "$FAT_DOCKER" != "true" ]]; then

View File

@@ -22,7 +22,8 @@ public class CleanUrlInterceptor implements HandlerInterceptor {
"error", "error",
"erroroauth", "erroroauth",
"file", "file",
"messageType"); "messageType",
"infoMessage");
@Override @Override
public boolean preHandle( public boolean preHandle(

View File

@@ -4,17 +4,26 @@ import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.Arrays;
import java.util.List; import java.util.List;
import org.simpleyaml.configuration.comments.CommentType;
import org.simpleyaml.configuration.file.YamlFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.ConfigurableApplicationContext;
public class ConfigInitializer public class ConfigInitializer
implements ApplicationContextInitializer<ConfigurableApplicationContext> { implements ApplicationContextInitializer<ConfigurableApplicationContext> {
private static final Logger logger = LoggerFactory.getLogger(ConfigInitializer.class);
@Override @Override
public void initialize(ConfigurableApplicationContext applicationContext) { public void initialize(ConfigurableApplicationContext applicationContext) {
try { try {
@@ -44,95 +53,89 @@ public class ConfigInitializer
} }
} }
} else { } else {
// Path templatePath =
// Paths.get( // Define the path to the config settings file
// getClass() Path settingsPath = Paths.get("configs", "settings.yml");
// .getClassLoader() // Load the template resource
// .getResource("settings.yml.template") URL settingsTemplateResource =
// .toURI()); getClass().getClassLoader().getResource("settings.yml.template");
// Path userPath = Paths.get("configs", "settings.yml"); if (settingsTemplateResource == null) {
// throw new IOException("Resource not found: settings.yml.template");
// List<String> templateLines = Files.readAllLines(templatePath); }
// List<String> userLines =
// Files.exists(userPath) ? Files.readAllLines(userPath) : new // Create a temporary file to copy the resource content
// ArrayList<>(); Path tempTemplatePath = Files.createTempFile("settings.yml", ".template");
//
// List<String> resultLines = new ArrayList<>(); try (InputStream in = settingsTemplateResource.openStream()) {
// int position = 0; Files.copy(in, tempTemplatePath, StandardCopyOption.REPLACE_EXISTING);
// for (String templateLine : templateLines) { }
// // Check if the line is a comment
// if (templateLine.trim().startsWith("#")) { final YamlFile settingsTemplateFile = new YamlFile(tempTemplatePath.toFile());
// String entry = templateLine.trim().substring(1).trim(); settingsTemplateFile.loadWithComments();
// if (!entry.isEmpty()) {
// // Check if this comment has been uncommented in userLines final YamlFile settingsFile = new YamlFile(settingsPath.toFile());
// String key = entry.split(":")[0].trim(); settingsFile.loadWithComments();
// addLine(resultLines, userLines, templateLine, key, position);
// } else { // Load headers and comments
// resultLines.add(templateLine); String header = settingsTemplateFile.getHeader();
// }
// } // Create a new file for temporary settings
// // Check if the line is a key-value pair final YamlFile tempSettingFile = new YamlFile(settingsPath.toFile());
// else if (templateLine.contains(":")) { tempSettingFile.createNewFile(true);
// String key = templateLine.split(":")[0].trim(); tempSettingFile.setHeader(header);
// addLine(resultLines, userLines, templateLine, key, position);
// } // Get all keys from the template
// // Handle empty lines List<String> keys =
// else if (templateLine.trim().length() == 0) { Arrays.asList(settingsTemplateFile.getKeys(true).toArray(new String[0]));
// resultLines.add("");
// } for (String key : keys) {
// position++; if (!key.contains(".")) {
// } // Add blank lines and comments to specific sections
// tempSettingFile
// // Write the result to the user settings file .path(key)
// Files.write(userPath, resultLines); .comment(settingsTemplateFile.getComment(key))
.blankLine();
continue;
}
// Copy settings from the template to the settings.yml file
changeConfigItemFromCommentToKeyValue(
settingsTemplateFile, settingsFile, tempSettingFile, key);
}
// Save the settings.yml file
tempSettingFile.save();
} }
// Create custom settings file if it doesn't exist
Path customSettingsPath = Paths.get("configs", "custom_settings.yml"); Path customSettingsPath = Paths.get("configs", "custom_settings.yml");
if (!Files.exists(customSettingsPath)) { if (!Files.exists(customSettingsPath)) {
Files.createFile(customSettingsPath); Files.createFile(customSettingsPath);
} }
} }
// TODO check parent value instead of just indent lines for duplicate keys (like enabled etc) private void changeConfigItemFromCommentToKeyValue(
private static void addLine( final YamlFile settingsTemplateFile,
List<String> resultLines, final YamlFile settingsFile,
List<String> userLines, final YamlFile tempSettingFile,
String templateLine, String path) {
String key, if (settingsFile.get(path) == null && settingsTemplateFile.get(path) != null) {
int position) { // If the key is only in the template, add it to the temporary settings with comments
boolean added = false; tempSettingFile
int templateIndentationLevel = getIndentationLevel(templateLine); .path(path)
int pos = 0; .set(settingsTemplateFile.get(path))
for (String settingsLine : userLines) { .comment(settingsTemplateFile.getComment(path, CommentType.BLOCK))
if (settingsLine.trim().startsWith(key + ":") && position == pos) { .commentSide(settingsTemplateFile.getComment(path, CommentType.SIDE));
int settingsIndentationLevel = getIndentationLevel(settingsLine); } else if (settingsFile.get(path) != null && settingsTemplateFile.get(path) != null) {
// Check if it is correct settingsLine and has the same parent as templateLine // If the key is in both, update the temporary settings with the main settings' value
if (settingsIndentationLevel == templateIndentationLevel) { // and comments
resultLines.add(settingsLine); tempSettingFile
added = true; .path(path)
break; .set(settingsFile.get(path))
} .comment(settingsTemplateFile.getComment(path, CommentType.BLOCK))
} .commentSide(settingsTemplateFile.getComment(path, CommentType.SIDE));
pos++; } else {
// Log if the key is not found in both YAML files
logger.info("Key not found in both YAML files: " + path);
} }
if (!added) {
resultLines.add(templateLine);
}
}
private static int getIndentationLevel(String line) {
int indentationLevel = 0;
String trimmedLine = line.trim();
if (trimmedLine.startsWith("#")) {
line = trimmedLine.substring(1);
}
for (char c : line.toCharArray()) {
if (c == ' ') {
indentationLevel++;
} else {
break;
}
}
return indentationLevel;
} }
} }

View File

@@ -0,0 +1,16 @@
package stirling.software.SPDF.config;
import java.io.IOException;
import java.util.List;
import stirling.software.SPDF.utils.FileInfo;
public interface DatabaseBackupInterface {
void exportDatabase() throws IOException;
boolean importDatabase();
boolean hasBackup();
List<FileInfo> getBackupList();
}

View File

@@ -1,34 +1,38 @@
package stirling.software.SPDF.config.security; package stirling.software.SPDF.config.security;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.List;
import java.util.UUID; import java.util.UUID;
import org.slf4j.Logger; import org.simpleyaml.configuration.file.YamlFile;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import jakarta.annotation.PostConstruct; import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.DatabaseBackupInterface;
import stirling.software.SPDF.model.ApplicationProperties; import stirling.software.SPDF.model.ApplicationProperties;
import stirling.software.SPDF.model.Role; import stirling.software.SPDF.model.Role;
@Component @Component
@Slf4j
public class InitialSecuritySetup { public class InitialSecuritySetup {
@Autowired private UserService userService; @Autowired private UserService userService;
@Autowired private ApplicationProperties applicationProperties; @Autowired private ApplicationProperties applicationProperties;
private static final Logger logger = LoggerFactory.getLogger(InitialSecuritySetup.class); @Autowired private DatabaseBackupInterface databaseBackupHelper;
@PostConstruct @PostConstruct
public void init() { public void init() throws IllegalArgumentException, IOException {
if (!userService.hasUsers()) { if (databaseBackupHelper.hasBackup() && !userService.hasUsers()) {
databaseBackupHelper.importDatabase();
} else if (!userService.hasUsers()) {
initializeAdminUser(); initializeAdminUser();
} else {
databaseBackupHelper.exportDatabase();
} }
initializeInternalApiUser(); initializeInternalApiUser();
} }
@@ -42,12 +46,11 @@ public class InitialSecuritySetup {
} }
} }
private void initializeAdminUser() { private void initializeAdminUser() throws IOException {
String initialUsername = String initialUsername =
applicationProperties.getSecurity().getInitialLogin().getUsername(); applicationProperties.getSecurity().getInitialLogin().getUsername();
String initialPassword = String initialPassword =
applicationProperties.getSecurity().getInitialLogin().getPassword(); applicationProperties.getSecurity().getInitialLogin().getPassword();
if (initialUsername != null if (initialUsername != null
&& !initialUsername.isEmpty() && !initialUsername.isEmpty()
&& initialPassword != null && initialPassword != null
@@ -55,9 +58,9 @@ public class InitialSecuritySetup {
&& !userService.findByUsernameIgnoreCase(initialUsername).isPresent()) { && !userService.findByUsernameIgnoreCase(initialUsername).isPresent()) {
try { try {
userService.saveUser(initialUsername, initialPassword, Role.ADMIN.getRoleId()); userService.saveUser(initialUsername, initialPassword, Role.ADMIN.getRoleId());
logger.info("Admin user created: " + initialUsername); log.info("Admin user created: " + initialUsername);
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
logger.error("Failed to initialize security setup", e); log.error("Failed to initialize security setup", e);
System.exit(1); System.exit(1);
} }
} else { } else {
@@ -65,54 +68,38 @@ public class InitialSecuritySetup {
} }
} }
private void createDefaultAdminUser() { private void createDefaultAdminUser() throws IllegalArgumentException, IOException {
String defaultUsername = "admin"; String defaultUsername = "admin";
String defaultPassword = "stirling"; String defaultPassword = "stirling";
if (!userService.findByUsernameIgnoreCase(defaultUsername).isPresent()) { if (!userService.findByUsernameIgnoreCase(defaultUsername).isPresent()) {
userService.saveUser(defaultUsername, defaultPassword, Role.ADMIN.getRoleId(), true); userService.saveUser(defaultUsername, defaultPassword, Role.ADMIN.getRoleId(), true);
logger.info("Default admin user created: " + defaultUsername); log.info("Default admin user created: " + defaultUsername);
} }
} }
private void initializeInternalApiUser() { private void initializeInternalApiUser() throws IllegalArgumentException, IOException {
if (!userService.usernameExistsIgnoreCase(Role.INTERNAL_API_USER.getRoleId())) { if (!userService.usernameExistsIgnoreCase(Role.INTERNAL_API_USER.getRoleId())) {
userService.saveUser( userService.saveUser(
Role.INTERNAL_API_USER.getRoleId(), Role.INTERNAL_API_USER.getRoleId(),
UUID.randomUUID().toString(), UUID.randomUUID().toString(),
Role.INTERNAL_API_USER.getRoleId()); Role.INTERNAL_API_USER.getRoleId());
userService.addApiKeyToUser(Role.INTERNAL_API_USER.getRoleId()); userService.addApiKeyToUser(Role.INTERNAL_API_USER.getRoleId());
logger.info("Internal API user created: " + Role.INTERNAL_API_USER.getRoleId()); log.info("Internal API user created: " + Role.INTERNAL_API_USER.getRoleId());
} }
} }
private void saveKeyToConfig(String key) throws IOException { private void saveKeyToConfig(String key) throws IOException {
Path path = Paths.get("configs", "settings.yml"); // Target the configs/settings.yml Path path = Paths.get("configs", "settings.yml"); // Target the configs/settings.yml
List<String> lines = Files.readAllLines(path);
boolean keyFound = false;
// Search for the existing key to replace it or place to add it final YamlFile settingsYml = new YamlFile(path.toFile());
for (int i = 0; i < lines.size(); i++) {
if (lines.get(i).startsWith("AutomaticallyGenerated:")) {
keyFound = true;
if (i + 1 < lines.size() && lines.get(i + 1).trim().startsWith("key:")) {
lines.set(i + 1, " key: " + key);
break;
} else {
lines.add(i + 1, " key: " + key);
break;
}
}
}
// If the section doesn't exist, append it settingsYml.loadWithComments();
if (!keyFound) {
lines.add("# Automatically Generated Settings (Do Not Edit Directly)");
lines.add("AutomaticallyGenerated:");
lines.add(" key: " + key);
}
// Write back to the file settingsYml
Files.write(path, lines); .path("AutomaticallyGenerated.key")
.set(key)
.comment("# Automatically Generated Settings (Do Not Edit Directly)");
settingsYml.save();
} }
private boolean isValidUUID(String uuid) { private boolean isValidUUID(String uuid) {

View File

@@ -38,12 +38,12 @@ import stirling.software.SPDF.config.security.oauth2.CustomOAuth2AuthenticationS
import stirling.software.SPDF.config.security.oauth2.CustomOAuth2LogoutSuccessHandler; import stirling.software.SPDF.config.security.oauth2.CustomOAuth2LogoutSuccessHandler;
import stirling.software.SPDF.config.security.oauth2.CustomOAuth2UserService; import stirling.software.SPDF.config.security.oauth2.CustomOAuth2UserService;
import stirling.software.SPDF.model.ApplicationProperties; import stirling.software.SPDF.model.ApplicationProperties;
import stirling.software.SPDF.model.ApplicationProperties.GithubProvider;
import stirling.software.SPDF.model.ApplicationProperties.GoogleProvider;
import stirling.software.SPDF.model.ApplicationProperties.KeycloakProvider;
import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2; import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2;
import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2.Client; import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2.Client;
import stirling.software.SPDF.model.User; import stirling.software.SPDF.model.User;
import stirling.software.SPDF.model.provider.GithubProvider;
import stirling.software.SPDF.model.provider.GoogleProvider;
import stirling.software.SPDF.model.provider.KeycloakProvider;
import stirling.software.SPDF.repository.JPATokenRepositoryImpl; import stirling.software.SPDF.repository.JPATokenRepositoryImpl;
@Configuration @Configuration

View File

@@ -19,7 +19,6 @@ import org.springframework.web.filter.OncePerRequestFilter;
import io.github.bucket4j.Bandwidth; import io.github.bucket4j.Bandwidth;
import io.github.bucket4j.Bucket; import io.github.bucket4j.Bucket;
import io.github.bucket4j.ConsumptionProbe; import io.github.bucket4j.ConsumptionProbe;
import io.github.bucket4j.Refill;
import io.github.pixee.security.Newlines; import io.github.pixee.security.Newlines;
import jakarta.servlet.FilterChain; import jakarta.servlet.FilterChain;
@@ -142,7 +141,10 @@ public class UserBasedRateLimitingFilter extends OncePerRequestFilter {
private Bucket createUserBucket(int limitPerDay) { private Bucket createUserBucket(int limitPerDay) {
Bandwidth limit = Bandwidth limit =
Bandwidth.classic(limitPerDay, Refill.intervally(limitPerDay, Duration.ofDays(1))); Bandwidth.builder()
.capacity(limitPerDay)
.refillIntervally(limitPerDay, Duration.ofDays(1))
.build();
return Bucket.builder().addLimit(limit).build(); return Bucket.builder().addLimit(limit).build();
} }
} }

View File

@@ -1,5 +1,6 @@
package stirling.software.SPDF.config.security; package stirling.software.SPDF.config.security;
import java.io.IOException;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@@ -19,6 +20,7 @@ import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import stirling.software.SPDF.config.DatabaseBackupInterface;
import stirling.software.SPDF.controller.api.pipeline.UserServiceInterface; import stirling.software.SPDF.controller.api.pipeline.UserServiceInterface;
import stirling.software.SPDF.model.AuthenticationType; import stirling.software.SPDF.model.AuthenticationType;
import stirling.software.SPDF.model.Authority; import stirling.software.SPDF.model.Authority;
@@ -38,8 +40,11 @@ public class UserService implements UserServiceInterface {
@Autowired private MessageSource messageSource; @Autowired private MessageSource messageSource;
@Autowired DatabaseBackupInterface databaseBackupHelper;
// Handle OAUTH2 login and user auto creation. // Handle OAUTH2 login and user auto creation.
public boolean processOAuth2PostLogin(String username, boolean autoCreateUser) { public boolean processOAuth2PostLogin(String username, boolean autoCreateUser)
throws IllegalArgumentException, IOException {
if (!isUsernameValid(username)) { if (!isUsernameValid(username)) {
return false; return false;
} }
@@ -131,7 +136,7 @@ public class UserService implements UserServiceInterface {
} }
public void saveUser(String username, AuthenticationType authenticationType) public void saveUser(String username, AuthenticationType authenticationType)
throws IllegalArgumentException { throws IllegalArgumentException, IOException {
if (!isUsernameValid(username)) { if (!isUsernameValid(username)) {
throw new IllegalArgumentException(getInvalidUsernameMessage()); throw new IllegalArgumentException(getInvalidUsernameMessage());
} }
@@ -142,9 +147,11 @@ public class UserService implements UserServiceInterface {
user.addAuthority(new Authority(Role.USER.getRoleId(), user)); user.addAuthority(new Authority(Role.USER.getRoleId(), user));
user.setAuthenticationType(authenticationType); user.setAuthenticationType(authenticationType);
userRepository.save(user); userRepository.save(user);
databaseBackupHelper.exportDatabase();
} }
public void saveUser(String username, String password) throws IllegalArgumentException { public void saveUser(String username, String password)
throws IllegalArgumentException, IOException {
if (!isUsernameValid(username)) { if (!isUsernameValid(username)) {
throw new IllegalArgumentException(getInvalidUsernameMessage()); throw new IllegalArgumentException(getInvalidUsernameMessage());
} }
@@ -154,10 +161,11 @@ public class UserService implements UserServiceInterface {
user.setEnabled(true); user.setEnabled(true);
user.setAuthenticationType(AuthenticationType.WEB); user.setAuthenticationType(AuthenticationType.WEB);
userRepository.save(user); userRepository.save(user);
databaseBackupHelper.exportDatabase();
} }
public void saveUser(String username, String password, String role, boolean firstLogin) public void saveUser(String username, String password, String role, boolean firstLogin)
throws IllegalArgumentException { throws IllegalArgumentException, IOException {
if (!isUsernameValid(username)) { if (!isUsernameValid(username)) {
throw new IllegalArgumentException(getInvalidUsernameMessage()); throw new IllegalArgumentException(getInvalidUsernameMessage());
} }
@@ -169,10 +177,11 @@ public class UserService implements UserServiceInterface {
user.setAuthenticationType(AuthenticationType.WEB); user.setAuthenticationType(AuthenticationType.WEB);
user.setFirstLogin(firstLogin); user.setFirstLogin(firstLogin);
userRepository.save(user); userRepository.save(user);
databaseBackupHelper.exportDatabase();
} }
public void saveUser(String username, String password, String role) public void saveUser(String username, String password, String role)
throws IllegalArgumentException { throws IllegalArgumentException, IOException {
saveUser(username, password, role, false); saveUser(username, password, role, false);
} }
@@ -206,7 +215,8 @@ public class UserService implements UserServiceInterface {
return userCount > 0; return userCount > 0;
} }
public void updateUserSettings(String username, Map<String, String> updates) { public void updateUserSettings(String username, Map<String, String> updates)
throws IOException {
Optional<User> userOpt = userRepository.findByUsernameIgnoreCase(username); Optional<User> userOpt = userRepository.findByUsernameIgnoreCase(username);
if (userOpt.isPresent()) { if (userOpt.isPresent()) {
User user = userOpt.get(); User user = userOpt.get();
@@ -220,6 +230,7 @@ public class UserService implements UserServiceInterface {
user.setSettings(settingsMap); user.setSettings(settingsMap);
userRepository.save(user); userRepository.save(user);
databaseBackupHelper.exportDatabase();
} }
} }
@@ -235,22 +246,26 @@ public class UserService implements UserServiceInterface {
return authorityRepository.findByUserId(user.getId()); return authorityRepository.findByUserId(user.getId());
} }
public void changeUsername(User user, String newUsername) throws IllegalArgumentException { public void changeUsername(User user, String newUsername)
throws IllegalArgumentException, IOException {
if (!isUsernameValid(newUsername)) { if (!isUsernameValid(newUsername)) {
throw new IllegalArgumentException(getInvalidUsernameMessage()); throw new IllegalArgumentException(getInvalidUsernameMessage());
} }
user.setUsername(newUsername); user.setUsername(newUsername);
userRepository.save(user); userRepository.save(user);
databaseBackupHelper.exportDatabase();
} }
public void changePassword(User user, String newPassword) { public void changePassword(User user, String newPassword) throws IOException {
user.setPassword(passwordEncoder.encode(newPassword)); user.setPassword(passwordEncoder.encode(newPassword));
userRepository.save(user); userRepository.save(user);
databaseBackupHelper.exportDatabase();
} }
public void changeFirstUse(User user, boolean firstUse) { public void changeFirstUse(User user, boolean firstUse) throws IOException {
user.setFirstLogin(firstUse); user.setFirstLogin(firstUse);
userRepository.save(user); userRepository.save(user);
databaseBackupHelper.exportDatabase();
} }
public void changeRole(User user, String newRole) { public void changeRole(User user, String newRole) {

View File

@@ -0,0 +1,204 @@
package stirling.software.SPDF.config.security.database;
import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.DatabaseBackupInterface;
import stirling.software.SPDF.utils.FileInfo;
@Slf4j
@Configuration
public class DatabaseBackupHelper implements DatabaseBackupInterface {
@Value("${spring.datasource.url}")
private String url;
private Path backupPath = Paths.get("configs/db/backup/");
@Override
public boolean hasBackup() {
// Check if there is at least one backup
return !getBackupList().isEmpty();
}
@Override
public List<FileInfo> getBackupList() {
// Check if the backup directory exists, and create it if it does not
ensureBackupDirectoryExists();
List<FileInfo> backupFiles = new ArrayList<>();
// Read the backup directory and filter for files with the prefix "backup_" and suffix
// ".sql"
try (DirectoryStream<Path> stream =
Files.newDirectoryStream(
backupPath,
path ->
path.getFileName().toString().startsWith("backup_")
&& path.getFileName().toString().endsWith(".sql"))) {
for (Path entry : stream) {
BasicFileAttributes attrs = Files.readAttributes(entry, BasicFileAttributes.class);
LocalDateTime modificationDate =
LocalDateTime.ofInstant(
attrs.lastModifiedTime().toInstant(), ZoneId.systemDefault());
LocalDateTime creationDate =
LocalDateTime.ofInstant(
attrs.creationTime().toInstant(), ZoneId.systemDefault());
long fileSize = attrs.size();
backupFiles.add(
new FileInfo(
entry.getFileName().toString(),
entry.toString(),
modificationDate,
fileSize,
creationDate));
}
} catch (IOException e) {
log.error("Error reading backup directory: {}", e.getMessage(), e);
}
return backupFiles;
}
// Imports a database backup from the specified file.
public boolean importDatabaseFromUI(String fileName) throws IOException {
return this.importDatabaseFromUI(getBackupFilePath(fileName));
}
// Imports a database backup from the specified path.
public boolean importDatabaseFromUI(Path tempTemplatePath) throws IOException {
boolean success = executeDatabaseScript(tempTemplatePath);
if (success) {
LocalDateTime dateNow = LocalDateTime.now();
DateTimeFormatter myFormatObj = DateTimeFormatter.ofPattern("yyyyMMddHHmm");
Path insertOutputFilePath =
this.getBackupFilePath("backup_user_" + dateNow.format(myFormatObj) + ".sql");
Files.copy(tempTemplatePath, insertOutputFilePath);
Files.deleteIfExists(tempTemplatePath);
}
return success;
}
@Override
public boolean importDatabase() {
if (!this.hasBackup()) return false;
List<FileInfo> backupList = this.getBackupList();
backupList.sort(Comparator.comparing(FileInfo::getModificationDate).reversed());
return executeDatabaseScript(Paths.get(backupList.get(0).getFilePath()));
}
@Override
public void exportDatabase() throws IOException {
// Check if the backup directory exists, and create it if it does not
ensureBackupDirectoryExists();
// Filter and delete old backups if there are more than 5
List<FileInfo> filteredBackupList =
this.getBackupList().stream()
.filter(backup -> !backup.getFileName().startsWith("backup_user_"))
.collect(Collectors.toList());
if (filteredBackupList.size() > 5) {
filteredBackupList.sort(
Comparator.comparing(
p -> p.getFileName().substring(7, p.getFileName().length() - 4)));
Files.deleteIfExists(Paths.get(filteredBackupList.get(0).getFilePath()));
log.info("Deleted oldest backup: {}", filteredBackupList.get(0).getFileName());
}
LocalDateTime dateNow = LocalDateTime.now();
DateTimeFormatter myFormatObj = DateTimeFormatter.ofPattern("yyyyMMddHHmm");
Path insertOutputFilePath =
this.getBackupFilePath("backup_" + dateNow.format(myFormatObj) + ".sql");
String query = "SCRIPT SIMPLE COLUMNS DROP to ?;";
try (Connection conn = DriverManager.getConnection(url, "sa", "");
PreparedStatement stmt = conn.prepareStatement(query)) {
stmt.setString(1, insertOutputFilePath.toString());
stmt.execute();
log.info("Database export completed: {}", insertOutputFilePath);
} catch (SQLException e) {
log.error("Error during database export: {}", e.getMessage(), e);
}
}
// Retrieves the H2 database version.
public String getH2Version() {
String version = "Unknown";
try (Connection conn = DriverManager.getConnection(url, "sa", "")) {
try (Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT H2VERSION() AS version")) {
if (rs.next()) {
version = rs.getString("version");
log.info("H2 Database Version: {}", version);
}
}
} catch (SQLException e) {
log.error("Error retrieving H2 version: {}", e.getMessage(), e);
}
return version;
}
// Deletes a backup file.
public boolean deleteBackupFile(String fileName) throws IOException {
Path filePath = this.getBackupFilePath(fileName);
if (Files.deleteIfExists(filePath)) {
log.info("Deleted backup file: {}", fileName);
return true;
} else {
log.error("File not found or could not be deleted: {}", fileName);
return false;
}
}
// Gets the Path object for a given backup file name.
public Path getBackupFilePath(String fileName) {
return Paths.get(backupPath.toString(), fileName);
}
private boolean executeDatabaseScript(Path scriptPath) {
try (Connection conn = DriverManager.getConnection(url, "sa", "");
Statement stmt = conn.createStatement()) {
String query = "RUNSCRIPT from '" + scriptPath.toString() + "';";
stmt.execute(query);
log.info("Database import completed: {}", scriptPath);
return true;
} catch (SQLException e) {
log.error("Error during database import: {}", e.getMessage(), e);
return false;
}
}
private void ensureBackupDirectoryExists() {
if (Files.notExists(backupPath)) {
try {
Files.createDirectories(backupPath);
} catch (IOException e) {
log.error("Error creating directories: {}", e.getMessage());
}
}
}
}

View File

@@ -0,0 +1,18 @@
package stirling.software.SPDF.config.security.database;
import java.io.IOException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class ScheduledTasks {
@Autowired private DatabaseBackupHelper databaseBackupService;
@Scheduled(cron = "0 0 0 * * ?")
public void performBackup() throws IOException {
databaseBackupService.exportDatabase();
}
}

View File

@@ -16,6 +16,7 @@ import jakarta.servlet.http.HttpSession;
import stirling.software.SPDF.model.ApplicationProperties; import stirling.software.SPDF.model.ApplicationProperties;
import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2; import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2;
import stirling.software.SPDF.model.Provider; import stirling.software.SPDF.model.Provider;
import stirling.software.SPDF.model.provider.UnsupportedProviderException;
import stirling.software.SPDF.utils.UrlUtils; import stirling.software.SPDF.utils.UrlUtils;
public class CustomOAuth2LogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler { public class CustomOAuth2LogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
@@ -51,8 +52,8 @@ public class CustomOAuth2LogoutSuccessHandler extends SimpleUrlLogoutSuccessHand
Provider provider = oauth.getClient().get(registrationId); Provider provider = oauth.getClient().get(registrationId);
issuer = provider.getIssuer(); issuer = provider.getIssuer();
clientId = provider.getClientId(); clientId = provider.getClientId();
} catch (Exception e) { } catch (UnsupportedProviderException e) {
logger.error("exception", e); logger.error(e.getMessage());
} }
} else { } else {

View File

@@ -0,0 +1,144 @@
package stirling.software.SPDF.controller.api;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import org.eclipse.jetty.http.HttpStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import io.swagger.v3.oas.annotations.Hidden;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.security.database.DatabaseBackupHelper;
@Slf4j
@Controller
@RequestMapping("/api/v1/database")
@PreAuthorize("hasRole('ROLE_ADMIN')")
@Tag(name = "Database", description = "Database APIs")
public class DatabaseController {
@Autowired DatabaseBackupHelper databaseBackupHelper;
@Hidden
@PostMapping(consumes = "multipart/form-data", value = "import-database")
@Operation(
summary = "Import database backup",
description = "This endpoint imports a database backup from a SQL file.")
public String importDatabase(
@RequestParam("fileInput") MultipartFile file, RedirectAttributes redirectAttributes)
throws IllegalArgumentException, IOException {
if (file == null || file.isEmpty()) {
redirectAttributes.addAttribute("error", "fileNullOrEmpty");
return "redirect:/database";
}
log.info("Received file: {}", file.getOriginalFilename());
Path tempTemplatePath = Files.createTempFile("backup_", ".sql");
try (InputStream in = file.getInputStream()) {
Files.copy(in, tempTemplatePath, StandardCopyOption.REPLACE_EXISTING);
boolean importSuccess = databaseBackupHelper.importDatabaseFromUI(tempTemplatePath);
if (importSuccess) {
redirectAttributes.addAttribute("infoMessage", "importIntoDatabaseSuccessed");
} else {
redirectAttributes.addAttribute("error", "failedImportFile");
}
} catch (Exception e) {
log.error("Error importing database: {}", e.getMessage());
redirectAttributes.addAttribute("error", "failedImportFile");
}
return "redirect:/database";
}
@Hidden
@GetMapping("/import-database-file/{fileName}")
public String importDatabaseFromBackupUI(@PathVariable String fileName)
throws IllegalArgumentException, IOException {
if (fileName == null || fileName.isEmpty()) {
return "redirect:/database?error=fileNullOrEmpty";
}
// Check if the file exists in the backup list
boolean fileExists =
databaseBackupHelper.getBackupList().stream()
.anyMatch(backup -> backup.getFileName().equals(fileName));
if (!fileExists) {
log.error("File {} not found in backup list", fileName);
return "redirect:/database?error=fileNotFound";
}
log.info("Received file: {}", fileName);
if (databaseBackupHelper.importDatabaseFromUI(fileName)) {
log.info("File {} imported to database", fileName);
return "redirect:/database?infoMessage=importIntoDatabaseSuccessed";
}
return "redirect:/database?error=failedImportFile";
}
@Hidden
@GetMapping("/delete/{fileName}")
@Operation(
summary = "Delete a database backup file",
description =
"This endpoint deletes a database backup file with the specified file name.")
public String deleteFile(@PathVariable String fileName) {
if (fileName == null || fileName.isEmpty()) {
throw new IllegalArgumentException("File must not be null or empty");
}
try {
if (databaseBackupHelper.deleteBackupFile(fileName)) {
log.info("Deleted file: {}", fileName);
} else {
log.error("Failed to delete file: {}", fileName);
return "redirect:/database?error=failedToDeleteFile";
}
} catch (IOException e) {
log.error("Error deleting file: {}", e.getMessage());
return "redirect:/database?error=" + e.getMessage();
}
return "redirect:/database";
}
@Hidden
@GetMapping("/download/{fileName}")
@Operation(
summary = "Download a database backup file",
description =
"This endpoint downloads a database backup file with the specified file name.")
public ResponseEntity<?> downloadFile(@PathVariable String fileName) {
if (fileName == null || fileName.isEmpty()) {
throw new IllegalArgumentException("File must not be null or empty");
}
try {
Path filePath = databaseBackupHelper.getBackupFilePath(fileName);
InputStreamResource resource = new InputStreamResource(Files.newInputStream(filePath));
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + fileName)
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.contentLength(Files.size(filePath))
.body(resource);
} catch (IOException e) {
log.error("Error downloading file: {}", e.getMessage());
return ResponseEntity.status(HttpStatus.SEE_OTHER_303)
.location(URI.create("/database?error=downloadFailed"))
.build();
}
}
}

View File

@@ -1,5 +1,6 @@
package stirling.software.SPDF.controller.api; package stirling.software.SPDF.controller.api;
import java.io.IOException;
import java.security.Principal; import java.security.Principal;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@@ -42,7 +43,8 @@ public class UserController {
@PreAuthorize("!hasAuthority('ROLE_DEMO_USER')") @PreAuthorize("!hasAuthority('ROLE_DEMO_USER')")
@PostMapping("/register") @PostMapping("/register")
public String register(@ModelAttribute UsernameAndPass requestModel, Model model) { public String register(@ModelAttribute UsernameAndPass requestModel, Model model)
throws IOException {
if (userService.usernameExistsIgnoreCase(requestModel.getUsername())) { if (userService.usernameExistsIgnoreCase(requestModel.getUsername())) {
model.addAttribute("error", "Username already exists"); model.addAttribute("error", "Username already exists");
return "register"; return "register";
@@ -63,7 +65,8 @@ public class UserController {
@RequestParam(name = "newUsername") String newUsername, @RequestParam(name = "newUsername") String newUsername,
HttpServletRequest request, HttpServletRequest request,
HttpServletResponse response, HttpServletResponse response,
RedirectAttributes redirectAttributes) { RedirectAttributes redirectAttributes)
throws IOException {
if (!userService.isUsernameValid(newUsername)) { if (!userService.isUsernameValid(newUsername)) {
return new RedirectView("/account?messageType=invalidUsername", true); return new RedirectView("/account?messageType=invalidUsername", true);
@@ -116,7 +119,8 @@ public class UserController {
@RequestParam(name = "newPassword") String newPassword, @RequestParam(name = "newPassword") String newPassword,
HttpServletRequest request, HttpServletRequest request,
HttpServletResponse response, HttpServletResponse response,
RedirectAttributes redirectAttributes) { RedirectAttributes redirectAttributes)
throws IOException {
if (principal == null) { if (principal == null) {
return new RedirectView("/change-creds?messageType=notAuthenticated", true); return new RedirectView("/change-creds?messageType=notAuthenticated", true);
} }
@@ -149,7 +153,8 @@ public class UserController {
@RequestParam(name = "newPassword") String newPassword, @RequestParam(name = "newPassword") String newPassword,
HttpServletRequest request, HttpServletRequest request,
HttpServletResponse response, HttpServletResponse response,
RedirectAttributes redirectAttributes) { RedirectAttributes redirectAttributes)
throws IOException {
if (principal == null) { if (principal == null) {
return new RedirectView("/account?messageType=notAuthenticated", true); return new RedirectView("/account?messageType=notAuthenticated", true);
} }
@@ -176,7 +181,8 @@ public class UserController {
@PreAuthorize("!hasAuthority('ROLE_DEMO_USER')") @PreAuthorize("!hasAuthority('ROLE_DEMO_USER')")
@PostMapping("/updateUserSettings") @PostMapping("/updateUserSettings")
public String updateUserSettings(HttpServletRequest request, Principal principal) { public String updateUserSettings(HttpServletRequest request, Principal principal)
throws IOException {
Map<String, String[]> paramMap = request.getParameterMap(); Map<String, String[]> paramMap = request.getParameterMap();
Map<String, String> updates = new HashMap<>(); Map<String, String> updates = new HashMap<>();
@@ -201,7 +207,8 @@ public class UserController {
@RequestParam(name = "password") String password, @RequestParam(name = "password") String password,
@RequestParam(name = "role") String role, @RequestParam(name = "role") String role,
@RequestParam(name = "forceChange", required = false, defaultValue = "false") @RequestParam(name = "forceChange", required = false, defaultValue = "false")
boolean forceChange) { boolean forceChange)
throws IllegalArgumentException, IOException {
if (!userService.isUsernameValid(username)) { if (!userService.isUsernameValid(username)) {
return new RedirectView("/addUsers?messageType=invalidUsername", true); return new RedirectView("/addUsers?messageType=invalidUsername", true);

View File

@@ -99,7 +99,7 @@ public class CompressController {
List<String> command = new ArrayList<>(); List<String> command = new ArrayList<>();
command.add("gs"); command.add("gs");
command.add("-sDEVICE=pdfwrite"); command.add("-sDEVICE=pdfwrite");
command.add("-dCompatibilityLevel=1.4"); command.add("-dCompatibilityLevel=1.5");
switch (optimizeLevel) { switch (optimizeLevel) {
case 1: case 1:

View File

@@ -24,14 +24,14 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import stirling.software.SPDF.model.ApplicationProperties; import stirling.software.SPDF.model.ApplicationProperties;
import stirling.software.SPDF.model.ApplicationProperties.GithubProvider;
import stirling.software.SPDF.model.ApplicationProperties.GoogleProvider;
import stirling.software.SPDF.model.ApplicationProperties.KeycloakProvider;
import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2; import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2;
import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2.Client; import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2.Client;
import stirling.software.SPDF.model.Authority; import stirling.software.SPDF.model.Authority;
import stirling.software.SPDF.model.Role; import stirling.software.SPDF.model.Role;
import stirling.software.SPDF.model.User; import stirling.software.SPDF.model.User;
import stirling.software.SPDF.model.provider.GithubProvider;
import stirling.software.SPDF.model.provider.GoogleProvider;
import stirling.software.SPDF.model.provider.KeycloakProvider;
import stirling.software.SPDF.repository.UserRepository; import stirling.software.SPDF.repository.UserRepository;
@Controller @Controller
@@ -43,6 +43,7 @@ public class AccountWebController {
@GetMapping("/login") @GetMapping("/login")
public String login(HttpServletRequest request, Model model, Authentication authentication) { public String login(HttpServletRequest request, Model model, Authentication authentication) {
if (authentication != null && authentication.isAuthenticated()) { if (authentication != null && authentication.isAuthenticated()) {
return "redirect:/"; return "redirect:/";
} }
@@ -72,8 +73,13 @@ public class AccountWebController {
} }
} }
} }
// Remove any null keys/values from the providerList
providerList
.entrySet()
.removeIf(entry -> entry.getKey() == null || entry.getValue() == null);
model.addAttribute("providerlist", providerList); model.addAttribute("providerlist", providerList);
model.addAttribute("loginMethod", applicationProperties.getSecurity().getLoginMethod());
model.addAttribute( model.addAttribute(
"oAuth2Enabled", applicationProperties.getSecurity().getOAUTH2().getEnabled()); "oAuth2Enabled", applicationProperties.getSecurity().getOAUTH2().getEnabled());

View File

@@ -0,0 +1,41 @@
package stirling.software.SPDF.controller.web;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import stirling.software.SPDF.config.security.database.DatabaseBackupHelper;
import stirling.software.SPDF.utils.FileInfo;
@Controller
@Tag(name = "Database Management", description = "Database management and security APIs")
public class DatabaseWebController {
@Autowired private DatabaseBackupHelper databaseBackupHelper;
@PreAuthorize("hasRole('ROLE_ADMIN')")
@GetMapping("/database")
public String database(HttpServletRequest request, Model model, Authentication authentication) {
String error = request.getParameter("error");
String confirmed = request.getParameter("infoMessage");
if (error != null) {
model.addAttribute("error", error);
} else if (confirmed != null) {
model.addAttribute("infoMessage", confirmed);
}
List<FileInfo> backupList = databaseBackupHelper.getBackupList();
model.addAttribute("systemUpdate", backupList);
return "database";
}
}

View File

@@ -13,6 +13,10 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource; import org.springframework.context.annotation.PropertySource;
import stirling.software.SPDF.config.YamlPropertySourceFactory; import stirling.software.SPDF.config.YamlPropertySourceFactory;
import stirling.software.SPDF.model.provider.GithubProvider;
import stirling.software.SPDF.model.provider.GoogleProvider;
import stirling.software.SPDF.model.provider.KeycloakProvider;
import stirling.software.SPDF.model.provider.UnsupportedProviderException;
@Configuration @Configuration
@ConfigurationProperties(prefix = "") @ConfigurationProperties(prefix = "")
@@ -128,6 +132,15 @@ public class ApplicationProperties {
private OAUTH2 oauth2; private OAUTH2 oauth2;
private int loginAttemptCount; private int loginAttemptCount;
private long loginResetTimeMinutes; private long loginResetTimeMinutes;
private String loginMethod = "all";
public String getLoginMethod() {
return loginMethod;
}
public void setLoginMethod(String loginMethod) {
this.loginMethod = loginMethod;
}
public int getLoginAttemptCount() { public int getLoginAttemptCount() {
return loginAttemptCount; return loginAttemptCount;
@@ -187,6 +200,8 @@ public class ApplicationProperties {
+ initialLogin + initialLogin
+ ", csrfDisabled=" + ", csrfDisabled="
+ csrfDisabled + csrfDisabled
+ ", loginMethod="
+ loginMethod
+ "]"; + "]";
} }
@@ -355,7 +370,7 @@ public class ApplicationProperties {
private GithubProvider github = new GithubProvider(); private GithubProvider github = new GithubProvider();
private KeycloakProvider keycloak = new KeycloakProvider(); private KeycloakProvider keycloak = new KeycloakProvider();
public Provider get(String registrationId) throws Exception { public Provider get(String registrationId) throws UnsupportedProviderException {
switch (registrationId.toLowerCase()) { switch (registrationId.toLowerCase()) {
case "google": case "google":
return getGoogle(); return getGoogle();
@@ -366,7 +381,8 @@ public class ApplicationProperties {
default: default:
break; break;
} }
throw new Exception("Provider not supported, use custom setting."); throw new UnsupportedProviderException(
"Logout from the provider is not supported? Report it at https://github.com/Stirling-Tools/Stirling-PDF/issues");
} }
public GoogleProvider getGoogle() { public GoogleProvider getGoogle() {
@@ -407,311 +423,6 @@ public class ApplicationProperties {
} }
} }
public static class GoogleProvider extends Provider {
private static final String authorizationUri =
"https://accounts.google.com/o/oauth2/v2/auth";
private static final String tokenUri = "https://www.googleapis.com/oauth2/v4/token";
private static final String userInfoUri =
"https://www.googleapis.com/oauth2/v3/userinfo?alt=json";
public String getAuthorizationuri() {
return authorizationUri;
}
public String getTokenuri() {
return tokenUri;
}
public String getUserinfouri() {
return userInfoUri;
}
private String clientId;
private String clientSecret;
private Collection<String> scopes = new ArrayList<>();
private String useAsUsername = "email";
@Override
public String getClientId() {
return this.clientId;
}
@Override
public void setClientId(String clientId) {
this.clientId = clientId;
}
@Override
public String getClientSecret() {
return this.clientSecret;
}
@Override
public void setClientSecret(String clientSecret) {
this.clientSecret = clientSecret;
}
@Override
public Collection<String> getScopes() {
if (scopes == null || scopes.isEmpty()) {
scopes = new ArrayList<>();
scopes.add("https://www.googleapis.com/auth/userinfo.email");
scopes.add("https://www.googleapis.com/auth/userinfo.profile");
}
return scopes;
}
@Override
public void setScopes(String scopes) {
this.scopes =
Arrays.stream(scopes.split(",")).map(String::trim).collect(Collectors.toList());
}
@Override
public String getUseAsUsername() {
return this.useAsUsername;
}
@Override
public void setUseAsUsername(String useAsUsername) {
this.useAsUsername = useAsUsername;
}
@Override
public String toString() {
return "Google [clientId="
+ clientId
+ ", clientSecret="
+ (clientSecret != null && !clientSecret.isEmpty() ? "MASKED" : "NULL")
+ ", scopes="
+ scopes
+ ", useAsUsername="
+ useAsUsername
+ "]";
}
@Override
public String getName() {
return "google";
}
@Override
public String getClientName() {
return "Google";
}
public boolean isSettingsValid() {
return super.isValid(this.getClientId(), "clientId")
&& super.isValid(this.getClientSecret(), "clientSecret")
&& super.isValid(this.getScopes(), "scopes")
&& isValid(this.getUseAsUsername(), "useAsUsername");
}
}
public static class GithubProvider extends Provider {
private static final String authorizationUri = "https://github.com/login/oauth/authorize";
private static final String tokenUri = "https://github.com/login/oauth/access_token";
private static final String userInfoUri = "https://api.github.com/user";
public String getAuthorizationuri() {
return authorizationUri;
}
public String getTokenuri() {
return tokenUri;
}
public String getUserinfouri() {
return userInfoUri;
}
private String clientId;
private String clientSecret;
private Collection<String> scopes = new ArrayList<>();
private String useAsUsername = "login";
@Override
public String getIssuer() {
return new String();
}
@Override
public void setIssuer(String issuer) {}
@Override
public String getClientId() {
return this.clientId;
}
@Override
public void setClientId(String clientId) {
this.clientId = clientId;
}
@Override
public String getClientSecret() {
return this.clientSecret;
}
@Override
public void setClientSecret(String clientSecret) {
this.clientSecret = clientSecret;
}
@Override
public Collection<String> getScopes() {
if (scopes == null || scopes.isEmpty()) {
scopes = new ArrayList<>();
scopes.add("read:user");
}
return scopes;
}
@Override
public void setScopes(String scopes) {
this.scopes =
Arrays.stream(scopes.split(",")).map(String::trim).collect(Collectors.toList());
}
@Override
public String getUseAsUsername() {
return this.useAsUsername;
}
@Override
public void setUseAsUsername(String useAsUsername) {
this.useAsUsername = useAsUsername;
}
@Override
public String toString() {
return "GitHub [clientId="
+ clientId
+ ", clientSecret="
+ (clientSecret != null && !clientSecret.isEmpty() ? "MASKED" : "NULL")
+ ", scopes="
+ scopes
+ ", useAsUsername="
+ useAsUsername
+ "]";
}
@Override
public String getName() {
return "github";
}
@Override
public String getClientName() {
return "GitHub";
}
public boolean isSettingsValid() {
return super.isValid(this.getClientId(), "clientId")
&& super.isValid(this.getClientSecret(), "clientSecret")
&& super.isValid(this.getScopes(), "scopes")
&& isValid(this.getUseAsUsername(), "useAsUsername");
}
}
public static class KeycloakProvider extends Provider {
private String issuer;
private String clientId;
private String clientSecret;
private Collection<String> scopes = new ArrayList<>();
private String useAsUsername = "email";
@Override
public String getIssuer() {
return this.issuer;
}
@Override
public void setIssuer(String issuer) {
this.issuer = issuer;
}
@Override
public String getClientId() {
return this.clientId;
}
@Override
public void setClientId(String clientId) {
this.clientId = clientId;
}
@Override
public String getClientSecret() {
return this.clientSecret;
}
@Override
public void setClientSecret(String clientSecret) {
this.clientSecret = clientSecret;
}
@Override
public Collection<String> getScopes() {
if (scopes == null || scopes.isEmpty()) {
scopes = new ArrayList<>();
scopes.add("profile");
scopes.add("email");
}
return scopes;
}
@Override
public void setScopes(String scopes) {
this.scopes =
Arrays.stream(scopes.split(",")).map(String::trim).collect(Collectors.toList());
}
@Override
public String getUseAsUsername() {
return this.useAsUsername;
}
@Override
public void setUseAsUsername(String useAsUsername) {
this.useAsUsername = useAsUsername;
}
@Override
public String toString() {
return "Keycloak [issuer="
+ issuer
+ ", clientId="
+ clientId
+ ", clientSecret="
+ (clientSecret != null && !clientSecret.isEmpty() ? "MASKED" : "NULL")
+ ", scopes="
+ scopes
+ ", useAsUsername="
+ useAsUsername
+ "]";
}
@Override
public String getName() {
return "keycloak";
}
@Override
public String getClientName() {
return "Keycloak";
}
public boolean isSettingsValid() {
return isValid(this.getIssuer(), "issuer")
&& isValid(this.getClientId(), "clientId")
&& isValid(this.getClientSecret(), "clientSecret")
&& isValid(this.getScopes(), "scopes")
&& isValid(this.getUseAsUsername(), "useAsUsername");
}
}
public static class System { public static class System {
private String defaultLocale; private String defaultLocale;
private Boolean googlevisibility; private Boolean googlevisibility;

View File

@@ -16,6 +16,7 @@ import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType; import jakarta.persistence.GenerationType;
import jakarta.persistence.Id; import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn; import jakarta.persistence.JoinColumn;
import jakarta.persistence.Lob;
import jakarta.persistence.MapKeyColumn; import jakarta.persistence.MapKeyColumn;
import jakarta.persistence.OneToMany; import jakarta.persistence.OneToMany;
import jakarta.persistence.Table; import jakarta.persistence.Table;
@@ -55,7 +56,8 @@ public class User {
@ElementCollection @ElementCollection
@MapKeyColumn(name = "setting_key") @MapKeyColumn(name = "setting_key")
@Column(name = "setting_value") @Lob
@Column(name = "setting_value", columnDefinition = "CLOB")
@CollectionTable(name = "user_settings", joinColumns = @JoinColumn(name = "user_id")) @CollectionTable(name = "user_settings", joinColumns = @JoinColumn(name = "user_id"))
private Map<String, String> settings = new HashMap<>(); // Key-value pairs of settings. private Map<String, String> settings = new HashMap<>(); // Key-value pairs of settings.

View File

@@ -0,0 +1,115 @@
package stirling.software.SPDF.model.provider;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.stream.Collectors;
import stirling.software.SPDF.model.Provider;
public class GithubProvider extends Provider {
private static final String authorizationUri = "https://github.com/login/oauth/authorize";
private static final String tokenUri = "https://github.com/login/oauth/access_token";
private static final String userInfoUri = "https://api.github.com/user";
public String getAuthorizationuri() {
return authorizationUri;
}
public String getTokenuri() {
return tokenUri;
}
public String getUserinfouri() {
return userInfoUri;
}
private String clientId;
private String clientSecret;
private Collection<String> scopes = new ArrayList<>();
private String useAsUsername = "login";
@Override
public String getIssuer() {
return new String();
}
@Override
public void setIssuer(String issuer) {}
@Override
public String getClientId() {
return this.clientId;
}
@Override
public void setClientId(String clientId) {
this.clientId = clientId;
}
@Override
public String getClientSecret() {
return this.clientSecret;
}
@Override
public void setClientSecret(String clientSecret) {
this.clientSecret = clientSecret;
}
@Override
public Collection<String> getScopes() {
if (scopes == null || scopes.isEmpty()) {
scopes = new ArrayList<>();
scopes.add("read:user");
}
return scopes;
}
@Override
public void setScopes(String scopes) {
this.scopes =
Arrays.stream(scopes.split(",")).map(String::trim).collect(Collectors.toList());
}
@Override
public String getUseAsUsername() {
return this.useAsUsername;
}
@Override
public void setUseAsUsername(String useAsUsername) {
this.useAsUsername = useAsUsername;
}
@Override
public String toString() {
return "GitHub [clientId="
+ clientId
+ ", clientSecret="
+ (clientSecret != null && !clientSecret.isEmpty() ? "MASKED" : "NULL")
+ ", scopes="
+ scopes
+ ", useAsUsername="
+ useAsUsername
+ "]";
}
@Override
public String getName() {
return "github";
}
@Override
public String getClientName() {
return "GitHub";
}
public boolean isSettingsValid() {
return super.isValid(this.getClientId(), "clientId")
&& super.isValid(this.getClientSecret(), "clientSecret")
&& super.isValid(this.getScopes(), "scopes")
&& isValid(this.getUseAsUsername(), "useAsUsername");
}
}

View File

@@ -0,0 +1,109 @@
package stirling.software.SPDF.model.provider;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.stream.Collectors;
import stirling.software.SPDF.model.Provider;
public class GoogleProvider extends Provider {
private static final String authorizationUri = "https://accounts.google.com/o/oauth2/v2/auth";
private static final String tokenUri = "https://www.googleapis.com/oauth2/v4/token";
private static final String userInfoUri =
"https://www.googleapis.com/oauth2/v3/userinfo?alt=json";
public String getAuthorizationuri() {
return authorizationUri;
}
public String getTokenuri() {
return tokenUri;
}
public String getUserinfouri() {
return userInfoUri;
}
private String clientId;
private String clientSecret;
private Collection<String> scopes = new ArrayList<>();
private String useAsUsername = "email";
@Override
public String getClientId() {
return this.clientId;
}
@Override
public void setClientId(String clientId) {
this.clientId = clientId;
}
@Override
public String getClientSecret() {
return this.clientSecret;
}
@Override
public void setClientSecret(String clientSecret) {
this.clientSecret = clientSecret;
}
@Override
public Collection<String> getScopes() {
if (scopes == null || scopes.isEmpty()) {
scopes = new ArrayList<>();
scopes.add("https://www.googleapis.com/auth/userinfo.email");
scopes.add("https://www.googleapis.com/auth/userinfo.profile");
}
return scopes;
}
@Override
public void setScopes(String scopes) {
this.scopes =
Arrays.stream(scopes.split(",")).map(String::trim).collect(Collectors.toList());
}
@Override
public String getUseAsUsername() {
return this.useAsUsername;
}
@Override
public void setUseAsUsername(String useAsUsername) {
this.useAsUsername = useAsUsername;
}
@Override
public String toString() {
return "Google [clientId="
+ clientId
+ ", clientSecret="
+ (clientSecret != null && !clientSecret.isEmpty() ? "MASKED" : "NULL")
+ ", scopes="
+ scopes
+ ", useAsUsername="
+ useAsUsername
+ "]";
}
@Override
public String getName() {
return "google";
}
@Override
public String getClientName() {
return "Google";
}
public boolean isSettingsValid() {
return super.isValid(this.getClientId(), "clientId")
&& super.isValid(this.getClientSecret(), "clientSecret")
&& super.isValid(this.getScopes(), "scopes")
&& isValid(this.getUseAsUsername(), "useAsUsername");
}
}

View File

@@ -0,0 +1,106 @@
package stirling.software.SPDF.model.provider;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.stream.Collectors;
import stirling.software.SPDF.model.Provider;
public class KeycloakProvider extends Provider {
private String issuer;
private String clientId;
private String clientSecret;
private Collection<String> scopes = new ArrayList<>();
private String useAsUsername = "email";
@Override
public String getIssuer() {
return this.issuer;
}
@Override
public void setIssuer(String issuer) {
this.issuer = issuer;
}
@Override
public String getClientId() {
return this.clientId;
}
@Override
public void setClientId(String clientId) {
this.clientId = clientId;
}
@Override
public String getClientSecret() {
return this.clientSecret;
}
@Override
public void setClientSecret(String clientSecret) {
this.clientSecret = clientSecret;
}
@Override
public Collection<String> getScopes() {
if (scopes == null || scopes.isEmpty()) {
scopes = new ArrayList<>();
scopes.add("profile");
scopes.add("email");
}
return scopes;
}
@Override
public void setScopes(String scopes) {
this.scopes =
Arrays.stream(scopes.split(",")).map(String::trim).collect(Collectors.toList());
}
@Override
public String getUseAsUsername() {
return this.useAsUsername;
}
@Override
public void setUseAsUsername(String useAsUsername) {
this.useAsUsername = useAsUsername;
}
@Override
public String toString() {
return "Keycloak [issuer="
+ issuer
+ ", clientId="
+ clientId
+ ", clientSecret="
+ (clientSecret != null && !clientSecret.isEmpty() ? "MASKED" : "NULL")
+ ", scopes="
+ scopes
+ ", useAsUsername="
+ useAsUsername
+ "]";
}
@Override
public String getName() {
return "keycloak";
}
@Override
public String getClientName() {
return "Keycloak";
}
public boolean isSettingsValid() {
return isValid(this.getIssuer(), "issuer")
&& isValid(this.getClientId(), "clientId")
&& isValid(this.getClientSecret(), "clientSecret")
&& isValid(this.getScopes(), "scopes")
&& isValid(this.getUseAsUsername(), "useAsUsername");
}
}

View File

@@ -0,0 +1,7 @@
package stirling.software.SPDF.model.provider;
public class UnsupportedProviderException extends Exception {
public UnsupportedProviderException(String message) {
super(message);
}
}

View File

@@ -3,9 +3,11 @@ package stirling.software.SPDF.repository;
import java.util.Set; import java.util.Set;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import stirling.software.SPDF.model.Authority; import stirling.software.SPDF.model.Authority;
@Repository
public interface AuthorityRepository extends JpaRepository<Authority, Long> { public interface AuthorityRepository extends JpaRepository<Authority, Long> {
// Set<Authority> findByUsername(String username); // Set<Authority> findByUsername(String username);
Set<Authority> findByUser_Username(String username); Set<Authority> findByUser_Username(String username);

View File

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

View File

@@ -3,10 +3,12 @@ package stirling.software.SPDF.repository;
import java.util.Optional; import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import stirling.software.SPDF.model.User; import stirling.software.SPDF.model.User;
public interface UserRepository extends JpaRepository<User, String> { @Repository
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByUsernameIgnoreCase(String username); Optional<User> findByUsernameIgnoreCase(String username);
Optional<User> findByUsername(String username); Optional<User> findByUsername(String username);

View File

@@ -0,0 +1,50 @@
package stirling.software.SPDF.utils;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import lombok.AllArgsConstructor;
import lombok.Data;
@AllArgsConstructor
@Data
public class FileInfo {
private String fileName;
private String filePath;
private LocalDateTime modificationDate;
private long fileSize;
private LocalDateTime creationDate;
private static final DateTimeFormatter DATE_FORMATTER =
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// Converts the file path string to a Path object.
public Path getFilePathAsPath() {
return Paths.get(filePath);
}
// Formats the file size into a human-readable string.
public String getFormattedFileSize() {
if (fileSize >= 1024 * 1024 * 1024) {
return String.format("%.2f GB", fileSize / (1024.0 * 1024 * 1024));
} else if (fileSize >= 1024 * 1024) {
return String.format("%.2f MB", fileSize / (1024.0 * 1024));
} else if (fileSize >= 1024) {
return String.format("%.2f KB", fileSize / 1024.0);
} else {
return String.format("%d Bytes", fileSize);
}
}
// Formats the modification date to a string.
public String getFormattedModificationDate() {
return modificationDate.format(DATE_FORMATTER);
}
// Formats the creation date to a string.
public String getFormattedCreationDate() {
return creationDate.format(DATE_FORMATTER);
}
}

View File

@@ -191,6 +191,23 @@ adminUserSettings.submit=Save User
adminUserSettings.changeUserRole=تغيير دور المستخدم adminUserSettings.changeUserRole=تغيير دور المستخدم
adminUserSettings.authenticated=Authenticated adminUserSettings.authenticated=Authenticated
database.title=Database Import/Export
database.header=Database Import/Export
database.fileName=File Name
database.creationDate=Creation Date
database.fileSize=File Size
database.deleteBackupFile=Delete Backup File
database.importBackupFile=Import Backup File
database.downloadBackupFile=Download Backup File
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
database.submit=Import Backup
database.importIntoDatabaseSuccessed=Import into database successed
database.fileNotFound=File not Found
database.fileNullOrEmpty=File must not be null or empty
database.failedImportFile=Failed Import File
############# #############
# HOME-PAGE # # HOME-PAGE #
############# #############
@@ -689,6 +706,8 @@ removeAnnotations.submit=إزالة
#compare #compare
compare.title=يقارن compare.title=يقارن
compare.header=قارن ملفات PDF compare.header=قارن ملفات PDF
compare.highlightColor.1=Highlight Color 1:
compare.highlightColor.2=Highlight Color 2:
compare.document.1=المستند 1 compare.document.1=المستند 1
compare.document.2=المستند 2 compare.document.2=المستند 2
compare.submit=يقارن compare.submit=يقارن
@@ -821,6 +840,7 @@ pdfOrganiser.mode.6=Odd-Even Split
pdfOrganiser.mode.7=Remove First pdfOrganiser.mode.7=Remove First
pdfOrganiser.mode.8=Remove Last pdfOrganiser.mode.8=Remove Last
pdfOrganiser.mode.9=Remove First and Last pdfOrganiser.mode.9=Remove First and Last
pdfOrganiser.mode.10=Odd-Even Merge
pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1) pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)

View File

@@ -191,6 +191,23 @@ adminUserSettings.submit=Съхранете потребителя
adminUserSettings.changeUserRole=Промяна на ролята на потребителя adminUserSettings.changeUserRole=Промяна на ролята на потребителя
adminUserSettings.authenticated=Удостоверен adminUserSettings.authenticated=Удостоверен
database.title=Database Import/Export
database.header=Database Import/Export
database.fileName=File Name
database.creationDate=Creation Date
database.fileSize=File Size
database.deleteBackupFile=Delete Backup File
database.importBackupFile=Import Backup File
database.downloadBackupFile=Download Backup File
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
database.submit=Import Backup
database.importIntoDatabaseSuccessed=Import into database successed
database.fileNotFound=File not Found
database.fileNullOrEmpty=File must not be null or empty
database.failedImportFile=Failed Import File
############# #############
# HOME-PAGE # # HOME-PAGE #
############# #############
@@ -689,6 +706,8 @@ removeAnnotations.submit=Премахване
#compare #compare
compare.title=Сравнявай compare.title=Сравнявай
compare.header=Сравнявай PDF-и compare.header=Сравнявай PDF-и
compare.highlightColor.1=Highlight Color 1:
compare.highlightColor.2=Highlight Color 2:
compare.document.1=Документ 1 compare.document.1=Документ 1
compare.document.2=Документ 2 compare.document.2=Документ 2
compare.submit=Сравнявай compare.submit=Сравнявай
@@ -821,6 +840,7 @@ pdfOrganiser.mode.6=Четно-нечетно разделяне
pdfOrganiser.mode.7=Премахни първо pdfOrganiser.mode.7=Премахни първо
pdfOrganiser.mode.8=Премахване на последния pdfOrganiser.mode.8=Премахване на последния
pdfOrganiser.mode.9=Премахване на първия и последния pdfOrganiser.mode.9=Премахване на първия и последния
pdfOrganiser.mode.10=Odd-Even Merge
pdfOrganiser.placeholder=(напр. 1,3,2 или 4-8,2,10-12 или 2n-1) pdfOrganiser.placeholder=(напр. 1,3,2 или 4-8,2,10-12 или 2n-1)

View File

@@ -191,6 +191,23 @@ adminUserSettings.submit=Desar Usuari
adminUserSettings.changeUserRole=Canvia el rol de l'usuari adminUserSettings.changeUserRole=Canvia el rol de l'usuari
adminUserSettings.authenticated=Authenticated adminUserSettings.authenticated=Authenticated
database.title=Database Import/Export
database.header=Database Import/Export
database.fileName=File Name
database.creationDate=Creation Date
database.fileSize=File Size
database.deleteBackupFile=Delete Backup File
database.importBackupFile=Import Backup File
database.downloadBackupFile=Download Backup File
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
database.submit=Import Backup
database.importIntoDatabaseSuccessed=Import into database successed
database.fileNotFound=File not Found
database.fileNullOrEmpty=File must not be null or empty
database.failedImportFile=Failed Import File
############# #############
# HOME-PAGE # # HOME-PAGE #
############# #############
@@ -689,6 +706,8 @@ removeAnnotations.submit=Remove
#compare #compare
compare.title=Comparar compare.title=Comparar
compare.header=Compara PDF compare.header=Compara PDF
compare.highlightColor.1=Highlight Color 1:
compare.highlightColor.2=Highlight Color 2:
compare.document.1=Document 1 compare.document.1=Document 1
compare.document.2=Document 2 compare.document.2=Document 2
compare.submit=Comparar compare.submit=Comparar
@@ -821,6 +840,7 @@ pdfOrganiser.mode.6=Odd-Even Split
pdfOrganiser.mode.7=Remove First pdfOrganiser.mode.7=Remove First
pdfOrganiser.mode.8=Remove Last pdfOrganiser.mode.8=Remove Last
pdfOrganiser.mode.9=Remove First and Last pdfOrganiser.mode.9=Remove First and Last
pdfOrganiser.mode.10=Odd-Even Merge
pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1) pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)

View File

@@ -191,6 +191,23 @@ adminUserSettings.submit=Uložit Uživatele
adminUserSettings.changeUserRole=Zmenit Roli Uživatele adminUserSettings.changeUserRole=Zmenit Roli Uživatele
adminUserSettings.authenticated=Ověřeno adminUserSettings.authenticated=Ověřeno
database.title=Database Import/Export
database.header=Database Import/Export
database.fileName=File Name
database.creationDate=Creation Date
database.fileSize=File Size
database.deleteBackupFile=Delete Backup File
database.importBackupFile=Import Backup File
database.downloadBackupFile=Download Backup File
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
database.submit=Import Backup
database.importIntoDatabaseSuccessed=Import into database successed
database.fileNotFound=File not Found
database.fileNullOrEmpty=File must not be null or empty
database.failedImportFile=Failed Import File
############# #############
# HOME-PAGE # # HOME-PAGE #
############# #############
@@ -689,6 +706,8 @@ removeAnnotations.submit=Odebrat
#compare #compare
compare.title=Porovnat compare.title=Porovnat
compare.header=Porovnat PDF compare.header=Porovnat PDF
compare.highlightColor.1=Highlight Color 1:
compare.highlightColor.2=Highlight Color 2:
compare.document.1=Dokument 1 compare.document.1=Dokument 1
compare.document.2=Dokument 2 compare.document.2=Dokument 2
compare.submit=Porovnat compare.submit=Porovnat
@@ -821,6 +840,7 @@ pdfOrganiser.mode.6=Liché-Sudé rozdělení
pdfOrganiser.mode.7=Odstranit první pdfOrganiser.mode.7=Odstranit první
pdfOrganiser.mode.8=Odstranit poslední pdfOrganiser.mode.8=Odstranit poslední
pdfOrganiser.mode.9=Odstranit první a poslední pdfOrganiser.mode.9=Odstranit první a poslední
pdfOrganiser.mode.10=Odd-Even Merge
pdfOrganiser.placeholder=(např. 1,3,2 nebo 4-8,2,10-12 nebo 2n-1) pdfOrganiser.placeholder=(např. 1,3,2 nebo 4-8,2,10-12 nebo 2n-1)

View File

@@ -86,7 +86,7 @@ pipeline.defaultOption=Benutzerdefiniert
pipeline.submitButton=Speichern pipeline.submitButton=Speichern
pipeline.help=Hilfe für Pipeline pipeline.help=Hilfe für Pipeline
pipeline.scanHelp=Hilfe zum Ordnerscan pipeline.scanHelp=Hilfe zum Ordnerscan
pipeline.deletePrompt=Are you sure you want to delete pipeline pipeline.deletePrompt=Möchten Sie die Pipeline wirklich löschen?
###################### ######################
# Pipeline Options # # Pipeline Options #
@@ -191,6 +191,23 @@ adminUserSettings.submit=Benutzer speichern
adminUserSettings.changeUserRole=Benutzerrolle ändern adminUserSettings.changeUserRole=Benutzerrolle ändern
adminUserSettings.authenticated=Authentifiziert adminUserSettings.authenticated=Authentifiziert
database.title=Datenbank Import/Export
database.header=Datenbank Import/Export
database.fileName=Dateiname
database.creationDate=Erstellungsdatum
database.fileSize=Dateigröße
database.deleteBackupFile=Sicherungsdatei löschen
database.importBackupFile=Sicherungsdatei importieren
database.downloadBackupFile=Sicherungsdatei herunterladen
database.info_1=Beim Importieren der Daten ist es von größter Bedeutung, die korrekte Struktur zu gewährleisten. Wenn Sie nicht sicher sind, was Sie tun, suchen Sie Rat und Unterstützung von einem Fachmann. Ein Fehler in der Struktur kann zu Fehlfunktionen der Anwendung führen, bis hin zur vollständigen Nicht-Lauffähigkeit der Anwendung.
database.info_2=Der Dateiname spielt beim Hochladen keine Rolle. Dieser wird nachträglich in das Format backup_user_yyyyMMddHHmm.sql geändert, um eine einheitliche Benennung zu gewährleisten.
database.submit=Sicherungsdatei importieren
database.importIntoDatabaseSuccessed=Import in die Datenbank erfolgreich
database.fileNotFound=Datei nicht gefunden
database.fileNullOrEmpty=Datei darf nicht null oder leer sein
database.failedImportFile=Dateiimport fehlgeschlagen
############# #############
# HOME-PAGE # # HOME-PAGE #
############# #############
@@ -689,6 +706,8 @@ removeAnnotations.submit=Entfernen
#compare #compare
compare.title=Vergleichen compare.title=Vergleichen
compare.header=PDFs vergleichen compare.header=PDFs vergleichen
compare.highlightColor.1=Highlight-Farbe 1:
compare.highlightColor.2=Highlight-Farbe 2:
compare.document.1=Dokument 1 compare.document.1=Dokument 1
compare.document.2=Dokument 2 compare.document.2=Dokument 2
compare.submit=Vergleichen compare.submit=Vergleichen
@@ -1084,13 +1103,13 @@ licenses.version=Version
licenses.license=Lizenz licenses.license=Lizenz
#survey #survey
survey.nav=Survey survey.nav=Umfrage
survey.title=Stirling-PDF Survey survey.title=Stirling-PDF-Umfrage
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF! survey.description=Stirling-PDF hat kein Tracking, daher möchten wir von unseren Benutzern hören, wie wir Stirling-PDF verbessern können!
survey.please=Please consider taking our survey! survey.please=Bitte nehmen Sie an unserer Umfrage teil!
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page) survey.disabled=(Das Umfrage-Popup wird in folgenden Updates deaktiviert, ist aber am Fuß der Seite verfügbar.)
survey.button=Take Survey survey.button=Umfrage durchführen
survey.dontShowAgain=Don't show again survey.dontShowAgain=Nicht mehr anzeigen
#error #error

View File

@@ -191,6 +191,23 @@ adminUserSettings.submit=Αποθήκευση Χρήστη
adminUserSettings.changeUserRole=Αλλαγή ρόλου χρήστη adminUserSettings.changeUserRole=Αλλαγή ρόλου χρήστη
adminUserSettings.authenticated=Authenticated adminUserSettings.authenticated=Authenticated
database.title=Database Import/Export
database.header=Database Import/Export
database.fileName=File Name
database.creationDate=Creation Date
database.fileSize=File Size
database.deleteBackupFile=Delete Backup File
database.importBackupFile=Import Backup File
database.downloadBackupFile=Download Backup File
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
database.submit=Import Backup
database.importIntoDatabaseSuccessed=Import into database successed
database.fileNotFound=File not Found
database.fileNullOrEmpty=File must not be null or empty
database.failedImportFile=Failed Import File
############# #############
# HOME-PAGE # # HOME-PAGE #
############# #############
@@ -689,6 +706,8 @@ removeAnnotations.submit=Κατάργηση
#compare #compare
compare.title=Σύγκριση compare.title=Σύγκριση
compare.header=Σύγκριση PDFs compare.header=Σύγκριση PDFs
compare.highlightColor.1=Highlight Color 1:
compare.highlightColor.2=Highlight Color 2:
compare.document.1=Έγγραφο 1 compare.document.1=Έγγραφο 1
compare.document.2=Έγγραφο 2 compare.document.2=Έγγραφο 2
compare.submit=Σύγκριση compare.submit=Σύγκριση
@@ -821,6 +840,7 @@ pdfOrganiser.mode.6=Διαίρεση Μονού-Ζυγού
pdfOrganiser.mode.7=Αφαίρεση Πρώτου pdfOrganiser.mode.7=Αφαίρεση Πρώτου
pdfOrganiser.mode.8=Αφαίρεση Τελευταίου pdfOrganiser.mode.8=Αφαίρεση Τελευταίου
pdfOrganiser.mode.9=Αφαίρεση Πρώτου και Τελευταίου pdfOrganiser.mode.9=Αφαίρεση Πρώτου και Τελευταίου
pdfOrganiser.mode.10=Odd-Even Merge
pdfOrganiser.placeholder=(π.χ. 1,3,2 ή 4-8,2,10-12 ή 2n-1) pdfOrganiser.placeholder=(π.χ. 1,3,2 ή 4-8,2,10-12 ή 2n-1)

View File

@@ -191,6 +191,23 @@ adminUserSettings.submit=Save User
adminUserSettings.changeUserRole=Change User's Role adminUserSettings.changeUserRole=Change User's Role
adminUserSettings.authenticated=Authenticated adminUserSettings.authenticated=Authenticated
database.title=Database Import/Export
database.header=Database Import/Export
database.fileName=File Name
database.creationDate=Creation Date
database.fileSize=File Size
database.deleteBackupFile=Delete Backup File
database.importBackupFile=Import Backup File
database.downloadBackupFile=Download Backup File
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
database.submit=Import Backup
database.importIntoDatabaseSuccessed=Import into database successed
database.fileNotFound=File not found
database.fileNullOrEmpty=File must not be null or empty
database.failedImportFile=Failed to import file
############# #############
# HOME-PAGE # # HOME-PAGE #
############# #############
@@ -689,6 +706,8 @@ removeAnnotations.submit=Remove
#compare #compare
compare.title=Compare compare.title=Compare
compare.header=Compare PDFs compare.header=Compare PDFs
compare.highlightColor.1=Highlight Color 1:
compare.highlightColor.2=Highlight Color 2:
compare.document.1=Document 1 compare.document.1=Document 1
compare.document.2=Document 2 compare.document.2=Document 2
compare.submit=Compare compare.submit=Compare

View File

@@ -191,6 +191,23 @@ adminUserSettings.submit=Save User
adminUserSettings.changeUserRole=Change User's Role adminUserSettings.changeUserRole=Change User's Role
adminUserSettings.authenticated=Authenticated adminUserSettings.authenticated=Authenticated
database.title=Database Import/Export
database.header=Database Import/Export
database.fileName=File Name
database.creationDate=Creation Date
database.fileSize=File Size
database.deleteBackupFile=Delete Backup File
database.importBackupFile=Import Backup File
database.downloadBackupFile=Download Backup File
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
database.submit=Import Backup
database.importIntoDatabaseSuccessed=Import into database successed
database.fileNotFound=File not Found
database.fileNullOrEmpty=File must not be null or empty
database.failedImportFile=Failed Import File
############# #############
# HOME-PAGE # # HOME-PAGE #
############# #############
@@ -689,6 +706,8 @@ removeAnnotations.submit=Remove
#compare #compare
compare.title=Compare compare.title=Compare
compare.header=Compare PDFs compare.header=Compare PDFs
compare.highlightColor.1=Highlight Color 1:
compare.highlightColor.2=Highlight Color 2:
compare.document.1=Document 1 compare.document.1=Document 1
compare.document.2=Document 2 compare.document.2=Document 2
compare.submit=Compare compare.submit=Compare

View File

@@ -191,6 +191,23 @@ adminUserSettings.submit=Guardar Usuario
adminUserSettings.changeUserRole=Cambiar rol de usuario adminUserSettings.changeUserRole=Cambiar rol de usuario
adminUserSettings.authenticated=Authenticated adminUserSettings.authenticated=Authenticated
database.title=Database Import/Export
database.header=Database Import/Export
database.fileName=File Name
database.creationDate=Creation Date
database.fileSize=File Size
database.deleteBackupFile=Delete Backup File
database.importBackupFile=Import Backup File
database.downloadBackupFile=Download Backup File
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
database.submit=Import Backup
database.importIntoDatabaseSuccessed=Import into database successed
database.fileNotFound=File not Found
database.fileNullOrEmpty=File must not be null or empty
database.failedImportFile=Failed Import File
############# #############
# HOME-PAGE # # HOME-PAGE #
############# #############
@@ -689,6 +706,8 @@ removeAnnotations.submit=Eliminar
#compare #compare
compare.title=Comparar compare.title=Comparar
compare.header=Comparar archivos PDF compare.header=Comparar archivos PDF
compare.highlightColor.1=Highlight Color 1:
compare.highlightColor.2=Highlight Color 2:
compare.document.1=Documento 1 compare.document.1=Documento 1
compare.document.2=Documento 2 compare.document.2=Documento 2
compare.submit=Comparar compare.submit=Comparar
@@ -821,6 +840,7 @@ pdfOrganiser.mode.6=División par-impar
pdfOrganiser.mode.7=Quitar primera pdfOrganiser.mode.7=Quitar primera
pdfOrganiser.mode.8=Quitar última pdfOrganiser.mode.8=Quitar última
pdfOrganiser.mode.9=Quitar primera y última pdfOrganiser.mode.9=Quitar primera y última
pdfOrganiser.mode.10=Odd-Even Merge
pdfOrganiser.placeholder=(por ej., 1,3,2 o 4-8,2,10-12 o 2n-1) pdfOrganiser.placeholder=(por ej., 1,3,2 o 4-8,2,10-12 o 2n-1)

View File

@@ -191,6 +191,23 @@ adminUserSettings.submit=Gorde Erabiltzailea
adminUserSettings.changeUserRole=Erabiltzailearen rola aldatu adminUserSettings.changeUserRole=Erabiltzailearen rola aldatu
adminUserSettings.authenticated=Authenticated adminUserSettings.authenticated=Authenticated
database.title=Database Import/Export
database.header=Database Import/Export
database.fileName=File Name
database.creationDate=Creation Date
database.fileSize=File Size
database.deleteBackupFile=Delete Backup File
database.importBackupFile=Import Backup File
database.downloadBackupFile=Download Backup File
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
database.submit=Import Backup
database.importIntoDatabaseSuccessed=Import into database successed
database.fileNotFound=File not Found
database.fileNullOrEmpty=File must not be null or empty
database.failedImportFile=Failed Import File
############# #############
# HOME-PAGE # # HOME-PAGE #
############# #############
@@ -689,6 +706,8 @@ removeAnnotations.submit=Remove
#compare #compare
compare.title=Konparatu compare.title=Konparatu
compare.header=Konparatu PDF fitxategiak compare.header=Konparatu PDF fitxategiak
compare.highlightColor.1=Highlight Color 1:
compare.highlightColor.2=Highlight Color 2:
compare.document.1=1. dokumentua compare.document.1=1. dokumentua
compare.document.2=2. dokumentua compare.document.2=2. dokumentua
compare.submit=Konparatu compare.submit=Konparatu
@@ -821,6 +840,7 @@ pdfOrganiser.mode.6=Odd-Even Split
pdfOrganiser.mode.7=Remove First pdfOrganiser.mode.7=Remove First
pdfOrganiser.mode.8=Remove Last pdfOrganiser.mode.8=Remove Last
pdfOrganiser.mode.9=Remove First and Last pdfOrganiser.mode.9=Remove First and Last
pdfOrganiser.mode.10=Odd-Even Merge
pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1) pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)

View File

@@ -191,6 +191,23 @@ adminUserSettings.submit=Ajouter
adminUserSettings.changeUserRole=Changer le rôle de l'utilisateur adminUserSettings.changeUserRole=Changer le rôle de l'utilisateur
adminUserSettings.authenticated=Authentifié adminUserSettings.authenticated=Authentifié
database.title=Database Import/Export
database.header=Database Import/Export
database.fileName=File Name
database.creationDate=Creation Date
database.fileSize=File Size
database.deleteBackupFile=Delete Backup File
database.importBackupFile=Import Backup File
database.downloadBackupFile=Download Backup File
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
database.submit=Import Backup
database.importIntoDatabaseSuccessed=Import into database successed
database.fileNotFound=File not Found
database.fileNullOrEmpty=File must not be null or empty
database.failedImportFile=Failed Import File
############# #############
# HOME-PAGE # # HOME-PAGE #
############# #############
@@ -689,6 +706,8 @@ removeAnnotations.submit=Supprimer
#compare #compare
compare.title=Comparer compare.title=Comparer
compare.header=Comparer compare.header=Comparer
compare.highlightColor.1=Highlight Color 1:
compare.highlightColor.2=Highlight Color 2:
compare.document.1=Document 1 compare.document.1=Document 1
compare.document.2=Document 2 compare.document.2=Document 2
compare.submit=Comparer compare.submit=Comparer
@@ -821,6 +840,7 @@ pdfOrganiser.mode.6=Partage impair-pair
pdfOrganiser.mode.7=Supprimer le premier pdfOrganiser.mode.7=Supprimer le premier
pdfOrganiser.mode.8=Supprimer le dernier pdfOrganiser.mode.8=Supprimer le dernier
pdfOrganiser.mode.9=Supprimer le premier et le dernier pdfOrganiser.mode.9=Supprimer le premier et le dernier
pdfOrganiser.mode.10=Odd-Even Merge
pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1) pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)

View File

@@ -191,6 +191,23 @@ adminUserSettings.submit=उपयोगकर्ता को सहेजे
adminUserSettings.changeUserRole=यूज़र की भूमिका बदलें adminUserSettings.changeUserRole=यूज़र की भूमिका बदलें
adminUserSettings.authenticated=Authenticated adminUserSettings.authenticated=Authenticated
database.title=Database Import/Export
database.header=Database Import/Export
database.fileName=File Name
database.creationDate=Creation Date
database.fileSize=File Size
database.deleteBackupFile=Delete Backup File
database.importBackupFile=Import Backup File
database.downloadBackupFile=Download Backup File
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
database.submit=Import Backup
database.importIntoDatabaseSuccessed=Import into database successed
database.fileNotFound=File not Found
database.fileNullOrEmpty=File must not be null or empty
database.failedImportFile=Failed Import File
############# #############
# HOME-PAGE # # HOME-PAGE #
############# #############
@@ -689,6 +706,8 @@ removeAnnotations.submit=हटाएं
#compare #compare
compare.title=तुलना करें compare.title=तुलना करें
compare.header=पीडीएफ़ तुलना करें compare.header=पीडीएफ़ तुलना करें
compare.highlightColor.1=Highlight Color 1:
compare.highlightColor.2=Highlight Color 2:
compare.document.1=दस्तावेज़ 1 compare.document.1=दस्तावेज़ 1
compare.document.2=दस्तावेज़ 2 compare.document.2=दस्तावेज़ 2
compare.submit=तुलना करें compare.submit=तुलना करें
@@ -821,6 +840,7 @@ pdfOrganiser.mode.6=Odd-Even Split
pdfOrganiser.mode.7=Remove First pdfOrganiser.mode.7=Remove First
pdfOrganiser.mode.8=Remove Last pdfOrganiser.mode.8=Remove Last
pdfOrganiser.mode.9=Remove First and Last pdfOrganiser.mode.9=Remove First and Last
pdfOrganiser.mode.10=Odd-Even Merge
pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1) pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)

View File

@@ -191,6 +191,23 @@ adminUserSettings.submit=Spremi korisnika
adminUserSettings.changeUserRole=Promijenite korisničku ulogu adminUserSettings.changeUserRole=Promijenite korisničku ulogu
adminUserSettings.authenticated=Autentificirano adminUserSettings.authenticated=Autentificirano
database.title=Database Import/Export
database.header=Database Import/Export
database.fileName=File Name
database.creationDate=Creation Date
database.fileSize=File Size
database.deleteBackupFile=Delete Backup File
database.importBackupFile=Import Backup File
database.downloadBackupFile=Download Backup File
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
database.submit=Import Backup
database.importIntoDatabaseSuccessed=Import into database successed
database.fileNotFound=File not Found
database.fileNullOrEmpty=File must not be null or empty
database.failedImportFile=Failed Import File
############# #############
# HOME-PAGE # # HOME-PAGE #
############# #############
@@ -689,6 +706,8 @@ removeAnnotations.submit=Ukloni
#compare #compare
compare.title=Uporedite compare.title=Uporedite
compare.header=Usporedite PDF-ove compare.header=Usporedite PDF-ove
compare.highlightColor.1=Highlight Color 1:
compare.highlightColor.2=Highlight Color 2:
compare.document.1=Dokument 1 compare.document.1=Dokument 1
compare.document.2=Dokument 2 compare.document.2=Dokument 2
compare.submit=Uporedi compare.submit=Uporedi
@@ -821,6 +840,7 @@ pdfOrganiser.mode.6=Par-Nepar Podjela
pdfOrganiser.mode.7=Ukloni Prvu pdfOrganiser.mode.7=Ukloni Prvu
pdfOrganiser.mode.8=Ukloni Zadnju pdfOrganiser.mode.8=Ukloni Zadnju
pdfOrganiser.mode.9=Ukloni Prvu i Zadnju pdfOrganiser.mode.9=Ukloni Prvu i Zadnju
pdfOrganiser.mode.10=Odd-Even Merge
pdfOrganiser.placeholder=(npr. 1,3,2 ili 4-8,2,10-12 ili 2n-1) pdfOrganiser.placeholder=(npr. 1,3,2 ili 4-8,2,10-12 ili 2n-1)

View File

@@ -191,6 +191,23 @@ adminUserSettings.submit=Felhasználó mentése
adminUserSettings.changeUserRole=Felhasználó szerepkörének módosítása adminUserSettings.changeUserRole=Felhasználó szerepkörének módosítása
adminUserSettings.authenticated=Authenticated adminUserSettings.authenticated=Authenticated
database.title=Database Import/Export
database.header=Database Import/Export
database.fileName=File Name
database.creationDate=Creation Date
database.fileSize=File Size
database.deleteBackupFile=Delete Backup File
database.importBackupFile=Import Backup File
database.downloadBackupFile=Download Backup File
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
database.submit=Import Backup
database.importIntoDatabaseSuccessed=Import into database successed
database.fileNotFound=File not Found
database.fileNullOrEmpty=File must not be null or empty
database.failedImportFile=Failed Import File
############# #############
# HOME-PAGE # # HOME-PAGE #
############# #############
@@ -689,6 +706,8 @@ removeAnnotations.submit=Remove
#compare #compare
compare.title=Összehasonlítás compare.title=Összehasonlítás
compare.header=PDF-ek összehasonlítása compare.header=PDF-ek összehasonlítása
compare.highlightColor.1=Highlight Color 1:
compare.highlightColor.2=Highlight Color 2:
compare.document.1=Dokumentum 1 compare.document.1=Dokumentum 1
compare.document.2=Dokumentum 2 compare.document.2=Dokumentum 2
compare.submit=Összehasonlítás compare.submit=Összehasonlítás
@@ -821,6 +840,7 @@ pdfOrganiser.mode.6=Odd-Even Split
pdfOrganiser.mode.7=Remove First pdfOrganiser.mode.7=Remove First
pdfOrganiser.mode.8=Remove Last pdfOrganiser.mode.8=Remove Last
pdfOrganiser.mode.9=Remove First and Last pdfOrganiser.mode.9=Remove First and Last
pdfOrganiser.mode.10=Odd-Even Merge
pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1) pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)

View File

@@ -191,6 +191,23 @@ adminUserSettings.submit=Simpan Pengguna
adminUserSettings.changeUserRole=Ubah Peran Pengguna adminUserSettings.changeUserRole=Ubah Peran Pengguna
adminUserSettings.authenticated=Authenticated adminUserSettings.authenticated=Authenticated
database.title=Database Import/Export
database.header=Database Import/Export
database.fileName=File Name
database.creationDate=Creation Date
database.fileSize=File Size
database.deleteBackupFile=Delete Backup File
database.importBackupFile=Import Backup File
database.downloadBackupFile=Download Backup File
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
database.submit=Import Backup
database.importIntoDatabaseSuccessed=Import into database successed
database.fileNotFound=File not Found
database.fileNullOrEmpty=File must not be null or empty
database.failedImportFile=Failed Import File
############# #############
# HOME-PAGE # # HOME-PAGE #
############# #############
@@ -689,6 +706,8 @@ removeAnnotations.submit=Hapus
#compare #compare
compare.title=Bandingkan compare.title=Bandingkan
compare.header=Bandingkan PDF compare.header=Bandingkan PDF
compare.highlightColor.1=Highlight Color 1:
compare.highlightColor.2=Highlight Color 2:
compare.document.1=Dokumen 1 compare.document.1=Dokumen 1
compare.document.2=Dokumen 2 compare.document.2=Dokumen 2
compare.submit=Bandingkan compare.submit=Bandingkan
@@ -821,6 +840,7 @@ pdfOrganiser.mode.6=Odd-Even Split
pdfOrganiser.mode.7=Remove First pdfOrganiser.mode.7=Remove First
pdfOrganiser.mode.8=Remove Last pdfOrganiser.mode.8=Remove Last
pdfOrganiser.mode.9=Remove First and Last pdfOrganiser.mode.9=Remove First and Last
pdfOrganiser.mode.10=Odd-Even Merge
pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1) pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)

View File

@@ -35,7 +35,7 @@ sizes.large=Largo
sizes.x-large=Extra-Large sizes.x-large=Extra-Large
error.pdfPassword=Il documento PDF è protetto da password e la password non è stata fornita oppure non era corretta error.pdfPassword=Il documento PDF è protetto da password e la password non è stata fornita oppure non era corretta
delete=Elimina delete=Elimina
username=Username username=Nome utente
password=Password password=Password
welcome=Benvenuto welcome=Benvenuto
property=Proprietà property=Proprietà
@@ -87,6 +87,7 @@ pipeline.submitButton=Invia
pipeline.help=Aiuto sulla pipeline pipeline.help=Aiuto sulla pipeline
pipeline.scanHelp=Aiuto per la scansione delle cartelle pipeline.scanHelp=Aiuto per la scansione delle cartelle
pipeline.deletePrompt=Sei sicuro di voler eliminare la pipeline? pipeline.deletePrompt=Sei sicuro di voler eliminare la pipeline?
###################### ######################
# Pipeline Options # # Pipeline Options #
###################### ######################
@@ -115,7 +116,7 @@ navbar.multiTool=Strumenti multipli
navbar.sections.organize=Organizza navbar.sections.organize=Organizza
navbar.sections.convertTo=Converti in PDF navbar.sections.convertTo=Converti in PDF
navbar.sections.convertFrom=Converti da PDF navbar.sections.convertFrom=Converti da PDF
navbar.sections.security=Firma Firma & Sicurezza navbar.sections.security=Firma & Sicurezza
navbar.sections.advance=Avanzate navbar.sections.advance=Avanzate
navbar.sections.edit=Visualizza & Modifica navbar.sections.edit=Visualizza & Modifica
@@ -190,6 +191,23 @@ adminUserSettings.submit=Salva utente
adminUserSettings.changeUserRole=Cambia il ruolo dell'utente adminUserSettings.changeUserRole=Cambia il ruolo dell'utente
adminUserSettings.authenticated=Autenticato adminUserSettings.authenticated=Autenticato
database.title=Importazione/Esportazione database
database.header=Importazione/esportazione database
database.fileName=Nome file
database.creationDate=Data di creazione
database.fileSize=Dimensione
database.deleteBackupFile=Elimina file di backup
database.importBackupFile=Importa file di backup
database.downloadBackupFile=Scarica il file di backup
database.info_1=Quando si importano i dati, è fondamentale garantire la struttura corretta. Se non sei sicuro di quello che stai facendo, chiedi consiglio e supporto a un professionista. Un errore nella struttura può causare malfunzionamenti dell'applicazione, fino alla completa impossibilità di eseguire l'applicazione.
database.info_2=Il nome del file non ha importanza durante il caricamento. Verrà rinominato in seguito per seguire il formato backup_user__yyyyMMddHHmm.sql,garantendo una convenzione di denominazione coerente.
database.submit=Importa Backup
database.importIntoDatabaseSuccessed=L'importazione nel database è avvenuta con successo
database.fileNotFound=File non trovato
database.fileNullOrEmpty=Il file non deve essere nullo o vuoto
database.failedImportFile=Importazione file non riuscita
############# #############
# HOME-PAGE # # HOME-PAGE #
############# #############
@@ -233,7 +251,7 @@ pdfOrganiser.tags=duplex,pari,dispari,ordinamento,spostamento
home.addImage.title=Aggiungi Immagine home.addImage.title=Aggiungi Immagine
home.addImage.desc=Aggiungi un'immagine in un punto specifico del PDF (Lavori in corso) home.addImage.desc=Aggiungi un'immagine in un punto specifico del PDF (Lavori in corso)
addImage.tags=img,jpg,immagine,photo addImage.tags=img,jpg,immagine,foto
home.watermark.title=Aggiungi Filigrana home.watermark.title=Aggiungi Filigrana
home.watermark.desc=Aggiungi una filigrana al tuo PDF. home.watermark.desc=Aggiungi una filigrana al tuo PDF.
@@ -688,6 +706,8 @@ removeAnnotations.submit=Rimuovi
#compare #compare
compare.title=Compara compare.title=Compara
compare.header=Compara PDF compare.header=Compara PDF
compare.highlightColor.1=Highlight Color 1:
compare.highlightColor.2=Highlight Color 2:
compare.document.1=Documento 1 compare.document.1=Documento 1
compare.document.2=Documento 2 compare.document.2=Documento 2
compare.submit=Compara compare.submit=Compara
@@ -802,7 +822,7 @@ merge.title=Unisci
merge.header=Unisci 2 o più PDF merge.header=Unisci 2 o più PDF
merge.sortByName=Ordina per nome merge.sortByName=Ordina per nome
merge.sortByDate=Ordina per data merge.sortByDate=Ordina per data
merge.removeCertSign=Remove digital signature in the merged file? merge.removeCertSign=Rimuovere la firma digitale nel file unito?
merge.submit=Unisci merge.submit=Unisci
@@ -820,6 +840,7 @@ pdfOrganiser.mode.6=Divisione pari-dispari
pdfOrganiser.mode.7=Rimuovi prima pdfOrganiser.mode.7=Rimuovi prima
pdfOrganiser.mode.8=Rimuovi ultima pdfOrganiser.mode.8=Rimuovi ultima
pdfOrganiser.mode.9=Rimuovi la prima e l'ultima pdfOrganiser.mode.9=Rimuovi la prima e l'ultima
pdfOrganiser.mode.10=Unione pari-dispari
pdfOrganiser.placeholder=(ad es. 1,3,2 o 4-8,2,10-12 o 2n-1) pdfOrganiser.placeholder=(ad es. 1,3,2 o 4-8,2,10-12 o 2n-1)

View File

@@ -191,6 +191,23 @@ adminUserSettings.submit=ユーザーの保存
adminUserSettings.changeUserRole=ユーザーの役割を変更する adminUserSettings.changeUserRole=ユーザーの役割を変更する
adminUserSettings.authenticated=認証済 adminUserSettings.authenticated=認証済
database.title=Database Import/Export
database.header=Database Import/Export
database.fileName=File Name
database.creationDate=Creation Date
database.fileSize=File Size
database.deleteBackupFile=Delete Backup File
database.importBackupFile=Import Backup File
database.downloadBackupFile=Download Backup File
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
database.submit=Import Backup
database.importIntoDatabaseSuccessed=Import into database successed
database.fileNotFound=File not Found
database.fileNullOrEmpty=File must not be null or empty
database.failedImportFile=Failed Import File
############# #############
# HOME-PAGE # # HOME-PAGE #
############# #############
@@ -689,6 +706,8 @@ removeAnnotations.submit=削除
#compare #compare
compare.title=比較 compare.title=比較
compare.header=PDFの比較 compare.header=PDFの比較
compare.highlightColor.1=Highlight Color 1:
compare.highlightColor.2=Highlight Color 2:
compare.document.1=ドキュメント 1 compare.document.1=ドキュメント 1
compare.document.2=ドキュメント 2 compare.document.2=ドキュメント 2
compare.submit=比較 compare.submit=比較
@@ -821,6 +840,7 @@ pdfOrganiser.mode.6=奇数-偶数分割
pdfOrganiser.mode.7=最初に削除 pdfOrganiser.mode.7=最初に削除
pdfOrganiser.mode.8=最後を削除 pdfOrganiser.mode.8=最後を削除
pdfOrganiser.mode.9=最初と最後を削除 pdfOrganiser.mode.9=最初と最後を削除
pdfOrganiser.mode.10=Odd-Even Merge
pdfOrganiser.placeholder=(例:1,3,2または4-8,2,10-12または2n-1) pdfOrganiser.placeholder=(例:1,3,2または4-8,2,10-12または2n-1)

View File

@@ -191,6 +191,23 @@ adminUserSettings.submit=사용자 저장
adminUserSettings.changeUserRole=사용자의 역할 변경 adminUserSettings.changeUserRole=사용자의 역할 변경
adminUserSettings.authenticated=Authenticated adminUserSettings.authenticated=Authenticated
database.title=Database Import/Export
database.header=Database Import/Export
database.fileName=File Name
database.creationDate=Creation Date
database.fileSize=File Size
database.deleteBackupFile=Delete Backup File
database.importBackupFile=Import Backup File
database.downloadBackupFile=Download Backup File
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
database.submit=Import Backup
database.importIntoDatabaseSuccessed=Import into database successed
database.fileNotFound=File not Found
database.fileNullOrEmpty=File must not be null or empty
database.failedImportFile=Failed Import File
############# #############
# HOME-PAGE # # HOME-PAGE #
############# #############
@@ -689,6 +706,8 @@ removeAnnotations.submit=제거하다
#compare #compare
compare.title=비교 compare.title=비교
compare.header=PDF 문서 비교 compare.header=PDF 문서 비교
compare.highlightColor.1=Highlight Color 1:
compare.highlightColor.2=Highlight Color 2:
compare.document.1=문서 1 compare.document.1=문서 1
compare.document.2=문서 2 compare.document.2=문서 2
compare.submit=비교 compare.submit=비교
@@ -821,6 +840,7 @@ pdfOrganiser.mode.6=홀수-짝수 분할
pdfOrganiser.mode.7=첫 번째 항목 삭제 pdfOrganiser.mode.7=첫 번째 항목 삭제
pdfOrganiser.mode.8=마지막 항목 제거 pdfOrganiser.mode.8=마지막 항목 제거
pdfOrganiser.mode.9=첫 번째와 마지막 제거 pdfOrganiser.mode.9=첫 번째와 마지막 제거
pdfOrganiser.mode.10=Odd-Even Merge
pdfOrganiser.placeholder=(예: 1,3,2 또는 4-8,2,10-12 또는 2n-1) pdfOrganiser.placeholder=(예: 1,3,2 또는 4-8,2,10-12 또는 2n-1)

View File

@@ -11,17 +11,17 @@ imgPrompt=Selecteer afbeelding(en)
genericSubmit=Indienen genericSubmit=Indienen
processTimeWarning=Waarschuwing: Dit proces kan tot een minuut duren afhankelijk van de bestandsgrootte processTimeWarning=Waarschuwing: Dit proces kan tot een minuut duren afhankelijk van de bestandsgrootte
pageOrderPrompt=Aangepaste pagina volgorde (Voer een komma-gescheiden lijst van paginanummers of functies in, zoals 2n+1) : pageOrderPrompt=Aangepaste pagina volgorde (Voer een komma-gescheiden lijst van paginanummers of functies in, zoals 2n+1) :
pageSelectionPrompt=Custom Page Selection (Enter a comma-separated list of page numbers 1,5,6 or Functions like 2n+1) : pageSelectionPrompt=Aangepaste pagina selectie (Voer een komma-gescheiden lijst van paginanummer 1,5,6 of functies zoals 2n+1 in) :
goToPage=Ga goToPage=Ga
true=Waar true=Waar
false=Onwaar false=Onwaar
unknown=Onbekend unknown=Onbekend
save=Opslaan save=Opslaan
saveToBrowser=Save to Browser saveToBrowser=Opslaan in browser
close=Sluiten close=Sluiten
filesSelected=Bestanden geselecteerd filesSelected=Bestanden geselecteerd
noFavourites=Geen favorieten toegevoegd noFavourites=Geen favorieten toegevoegd
downloadComplete=Download Complete downloadComplete=Download klaar
bored=Verveeld met wachten? bored=Verveeld met wachten?
alphabet=Alfabet alphabet=Alfabet
downloadPdf=Download PDF downloadPdf=Download PDF
@@ -54,23 +54,23 @@ notAuthenticatedMessage=Gebruiker niet ingelogd.
userNotFoundMessage=Gebruiker niet gevonden. userNotFoundMessage=Gebruiker niet gevonden.
incorrectPasswordMessage=Huidige wachtwoord is onjuist. incorrectPasswordMessage=Huidige wachtwoord is onjuist.
usernameExistsMessage=Nieuwe gebruikersnaam bestaat al. usernameExistsMessage=Nieuwe gebruikersnaam bestaat al.
invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address. invalidUsernameMessage=Ongeldige gebruikersnaam, gebruikersnaam kan alleen letters, nummers en de volgende speciale tekens @._+- bevatten of moet een geldig emailadres zijn.
confirmPasswordErrorMessage=New Password and Confirm New Password must match. confirmPasswordErrorMessage=Nieuw wachtwoord en bevestig wachtwoord moeten overeenkomen.
deleteCurrentUserMessage=Cannot delete currently logged in user. deleteCurrentUserMessage=Kan niet een momenteel ingelogde gebruiker verwijderen.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted. deleteUsernameExistsMessage=De gebruikersnaam bestaat niet en kan niet verwijderd worden.
downgradeCurrentUserMessage=Kan de rol van de huidige gebruiker niet downgraden downgradeCurrentUserMessage=Kan de rol van de huidige gebruiker niet downgraden
downgradeCurrentUserLongMessage=Kan de rol van de huidige gebruiker niet downgraden. Huidige gebruiker wordt dus niet weergegeven. downgradeCurrentUserLongMessage=Kan de rol van de huidige gebruiker niet downgraden. Huidige gebruiker wordt dus niet weergegeven.
userAlreadyExistsOAuthMessage=The user already exists as an OAuth2 user. userAlreadyExistsOAuthMessage=De gebruiker bestaat al als een OAuth2 gebruiker.
userAlreadyExistsWebMessage=The user already exists as an web user. userAlreadyExistsWebMessage=De gebruiker bestaat al als een web gebruiker.
error=Error error=Error
oops=Oops! oops=Oeps!
help=Help help=Help
goHomepage=Go to Homepage goHomepage=Ga naar de startpagina
joinDiscord=Join our Discord server joinDiscord=Word lid van onze Discord server
seeDockerHub=See Docker Hub seeDockerHub=Zie Docker Hub
visitGithub=Visit Github Repository visitGithub=Ga naar de Github Repository
donate=Donate donate=Doneer
color=Color color=Kleur
sponsor=Sponsor sponsor=Sponsor
info=Info info=Info
@@ -79,14 +79,14 @@ info=Info
############### ###############
# Pipeline # # Pipeline #
############### ###############
pipeline.header=Pijplijn menu (Alpha) pipeline.header=Pijplijn menu (Beta)
pipeline.uploadButton=Aangepast uploaden pipeline.uploadButton=Aangepast uploaden
pipeline.configureButton=Configureren pipeline.configureButton=Configureren
pipeline.defaultOption=Aangepast pipeline.defaultOption=Aangepast
pipeline.submitButton=Opslaan pipeline.submitButton=Opslaan
pipeline.help=Pipeline Help pipeline.help=Pijplijn help
pipeline.scanHelp=Folder Scanning Help pipeline.scanHelp=Map scannen help
pipeline.deletePrompt=Are you sure you want to delete pipeline pipeline.deletePrompt=Weet je zeker dat je deze pijplijn wil verwijderen?
###################### ######################
# Pipeline Options # # Pipeline Options #
@@ -107,25 +107,25 @@ pipelineOptions.validateButton=Valideren
############# #############
# NAVBAR # # NAVBAR #
############# #############
navbar.favorite=Favorites navbar.favorite=Favorieten
navbar.darkmode=Donkere modus navbar.darkmode=Donkere modus
navbar.language=Languages navbar.language=Talen
navbar.settings=Instellingen navbar.settings=Instellingen
navbar.allTools=Tools navbar.allTools=Tools
navbar.multiTool=Multi Tools navbar.multiTool=Multitools
navbar.sections.organize=Organize navbar.sections.organize=Organizeren
navbar.sections.convertTo=Convert to PDF navbar.sections.convertTo=Converteren naar PDF
navbar.sections.convertFrom=Convert from PDF navbar.sections.convertFrom=Converteren van PDF
navbar.sections.security=Sign & Security navbar.sections.security=Ondertekenen & beveiliging
navbar.sections.advance=Advanced navbar.sections.advance=Geavanceerd
navbar.sections.edit=View & Edit navbar.sections.edit=Bekijken & wijzigen
############# #############
# SETTINGS # # SETTINGS #
############# #############
settings.title=Instellingen settings.title=Instellingen
settings.update=Update beschikbaar settings.update=Update beschikbaar
settings.updateAvailable={0} is the current installed version. A new version ({1}) is available. settings.updateAvailable={0} is de huidig geïnstalleerde versie. Een nieuwe versie ({1}) is beschikbaar.
settings.appVersion=App versie: settings.appVersion=App versie:
settings.downloadOption.title=Kies download optie (Voor enkelvoudige bestanddownloads zonder zip): settings.downloadOption.title=Kies download optie (Voor enkelvoudige bestanddownloads zonder zip):
settings.downloadOption.1=Open in hetzelfde venster settings.downloadOption.1=Open in hetzelfde venster
@@ -134,13 +134,13 @@ settings.downloadOption.3=Download bestand
settings.zipThreshold=Bestanden zippen wanneer het aantal gedownloade bestanden meer is dan settings.zipThreshold=Bestanden zippen wanneer het aantal gedownloade bestanden meer is dan
settings.signOut=Uitloggen settings.signOut=Uitloggen
settings.accountSettings=Account instellingen settings.accountSettings=Account instellingen
settings.bored.help=Enables easter egg game settings.bored.help=Schakelt geheim spelletje in
settings.cacheInputs.name=Save form inputs settings.cacheInputs.name=Sla invoer in formulieren op
settings.cacheInputs.help=Enable to store previously used inputs for future runs settings.cacheInputs.help=Schakel in om eerdere invoeren op te slaan voor toekomstige uitvoeren
changeCreds.title=Inloggegevens wijzigen changeCreds.title=Inloggegevens wijzigen
changeCreds.header=Werk je accountgegevens bij changeCreds.header=Werk je accountgegevens bij
changeCreds.changePassword=You are using default login credentials. Please enter a new password changeCreds.changePassword=Je gebruikt de standaard inloggegevens. Voer alstublieft een nieuw wachtwoord in
changeCreds.newUsername=Nieuwe gebruikersnaam changeCreds.newUsername=Nieuwe gebruikersnaam
changeCreds.oldPassword=Huidige wachtwoord changeCreds.oldPassword=Huidige wachtwoord
changeCreds.newPassword=Nieuw wachtwoord changeCreds.newPassword=Nieuw wachtwoord
@@ -175,27 +175,44 @@ adminUserSettings.header=Beheer gebruikers
adminUserSettings.admin=Beheerder adminUserSettings.admin=Beheerder
adminUserSettings.user=Gebruiker adminUserSettings.user=Gebruiker
adminUserSettings.addUser=Voeg nieuwe gebruiker toe adminUserSettings.addUser=Voeg nieuwe gebruiker toe
adminUserSettings.deleteUser=Delete User adminUserSettings.deleteUser=Verwijder gebruiker
adminUserSettings.confirmDeleteUser=Should the user be deleted? adminUserSettings.confirmDeleteUser=Moet deze gebruiker verwijderd worden?
adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address. adminUserSettings.usernameInfo=Gebruikersnaam kan alleen letters, nummers en de volgende speciale tekens @._+- bevatten of moet een geldig emailadres zijn.
adminUserSettings.roles=Rollen adminUserSettings.roles=Rollen
adminUserSettings.role=Rol adminUserSettings.role=Rol
adminUserSettings.actions=Acties adminUserSettings.actions=Acties
adminUserSettings.apiUser=Beperkte API gebruiker adminUserSettings.apiUser=Beperkte API gebruiker
adminUserSettings.extraApiUser=Additional Limited API User adminUserSettings.extraApiUser=Extra beperkte API gebruiker
adminUserSettings.webOnlyUser=Alleen web gebruiker adminUserSettings.webOnlyUser=Alleen web gebruiker
adminUserSettings.demoUser=Demogebruiker (geen aangepaste instellingen) adminUserSettings.demoUser=Demogebruiker (geen aangepaste instellingen)
adminUserSettings.internalApiUser=Internal API User adminUserSettings.internalApiUser=Interne API gebruiker
adminUserSettings.forceChange=Forceer gebruiker om gebruikersnaam/wachtwoord te wijzigen bij inloggen adminUserSettings.forceChange=Forceer gebruiker om gebruikersnaam/wachtwoord te wijzigen bij inloggen
adminUserSettings.submit=Gebruiker opslaan adminUserSettings.submit=Gebruiker opslaan
adminUserSettings.changeUserRole=De rol van de gebruiker wijzigen adminUserSettings.changeUserRole=De rol van de gebruiker wijzigen
adminUserSettings.authenticated=Authenticated adminUserSettings.authenticated=Geauthenticeerd
database.title=Database Import/Export
database.header=Database Import/Export
database.fileName=File Name
database.creationDate=Creation Date
database.fileSize=File Size
database.deleteBackupFile=Delete Backup File
database.importBackupFile=Import Backup File
database.downloadBackupFile=Download Backup File
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
database.submit=Import Backup
database.importIntoDatabaseSuccessed=Import into database successed
database.fileNotFound=File not Found
database.fileNullOrEmpty=File must not be null or empty
database.failedImportFile=Failed Import File
############# #############
# HOME-PAGE # # HOME-PAGE #
############# #############
home.desc=Jouw lokaal gehoste one-stop-shop voor al je PDF-behoeften. home.desc=Jouw lokaal gehoste one-stop-shop voor al je PDF-behoeften.
home.searchBar=Zoeken naar functies... home.searchBar=Zoek naar functies...
home.viewPdf.title=PDF bekijken home.viewPdf.title=PDF bekijken
@@ -204,11 +221,11 @@ viewPdf.tags=bekijken,lezen,annoteren,tekst,afbeelding
home.multiTool.title=PDF multitool home.multiTool.title=PDF multitool
home.multiTool.desc=Pagina's samenvoegen, draaien, herschikken en verwijderen home.multiTool.desc=Pagina's samenvoegen, draaien, herschikken en verwijderen
multiTool.tags=Multitool,Multi bewerking,UI,klik sleep,voorkant,clientzijde,interactief,beweegbaar,verplaats multiTool.tags=Multitool,meerdere bewerkingen,UI,klik sleep,voorkant,clientzijde,interactief,beweegbaar,verplaats
home.merge.title=Samenvoegen home.merge.title=Samenvoegen
home.merge.desc=Voeg eenvoudig meerdere PDF's samen tot één. home.merge.desc=Voeg eenvoudig meerdere PDF's samen tot één.
merge.tags=samenvoegen,Pagina bewerkingen,Serverkant merge.tags=samenvoegen,pagina bewerkingen,serverzijde
home.split.title=Splitsen home.split.title=Splitsen
home.split.desc=Splits PDF's in meerdere documenten home.split.desc=Splits PDF's in meerdere documenten
@@ -255,7 +272,7 @@ addPassword.tags=veilig,beveiliging
home.removePassword.title=Wachtwoord verwijderen home.removePassword.title=Wachtwoord verwijderen
home.removePassword.desc=Verwijder wachtwoordbeveiliging van je PDF-document. home.removePassword.desc=Verwijder wachtwoordbeveiliging van je PDF-document.
removePassword.tags=veilig,Decrypteren,beveiliging,wachtwoord verwijderen removePassword.tags=veilig,ontsleutelen,beveiliging,wachtwoord verwijderen
home.compressPdfs.title=Comprimeren home.compressPdfs.title=Comprimeren
home.compressPdfs.desc=Comprimeer PDF's om hun bestandsgrootte te verkleinen. home.compressPdfs.desc=Comprimeer PDF's om hun bestandsgrootte te verkleinen.
@@ -336,9 +353,9 @@ home.certSign.title=Ondertekenen met certificaat
home.certSign.desc=Ondertekent een PDF met een certificaat/sleutel (PEM/P12) home.certSign.desc=Ondertekent een PDF met een certificaat/sleutel (PEM/P12)
certSign.tags=authenticeren,PEM,P12,officieel,versleutelen certSign.tags=authenticeren,PEM,P12,officieel,versleutelen
home.removeCertSign.title=Remove Certificate Sign home.removeCertSign.title=Verwijder certificaat
home.removeCertSign.desc=Remove certificate signature from PDF home.removeCertSign.desc=Verwijder certificaat van PDF
removeCertSign.tags=authenticate,PEM,P12,official,decrypt removeCertSign.tags=authenticeren,PEM,P12,officieel,ontsleutelen
home.pageLayout.title=Multi-pagina indeling home.pageLayout.title=Multi-pagina indeling
home.pageLayout.desc=Voeg meerdere pagina's van een PDF-document samen op één pagina home.pageLayout.desc=Voeg meerdere pagina's van een PDF-document samen op één pagina
@@ -436,13 +453,13 @@ home.AddStampRequest.desc=Voeg tekst of afbeeldingsstempels toe op vaste locatie
AddStampRequest.tags=Stempel, Afbeelding toevoegen, afbeelding centreren, watermerk, PDF, Insluiten, Aanpassen AddStampRequest.tags=Stempel, Afbeelding toevoegen, afbeelding centreren, watermerk, PDF, Insluiten, Aanpassen
home.PDFToBook.title=PDF to Book home.PDFToBook.title=PDF naar Boek
home.PDFToBook.desc=Converts PDF to Book/Comic formats using calibre home.PDFToBook.desc=Converteert PDF naar boek-/stripformaat met gebruik van Calibre
PDFToBook.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle PDFToBook.tags=Boek,Strip,Comic,Calibre,Converteren,manga,amazon,kindle
home.BookToPDF.title=Book to PDF home.BookToPDF.title=Boek naar PDF
home.BookToPDF.desc=Converts Books/Comics formats to PDF using calibre home.BookToPDF.desc=Converteert boek-/stripformaat naar PDF met gebruik van Calibre
BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle BookToPDF.tags=Boek,Strip,Comic,Calibre,Converteren,manga,amazon,kindle
########################### ###########################
@@ -460,12 +477,12 @@ login.locked=Je account is geblokkeerd.
login.signinTitle=Gelieve in te loggen login.signinTitle=Gelieve in te loggen
login.ssoSignIn=Inloggen via Single Sign-on login.ssoSignIn=Inloggen via Single Sign-on
login.oauth2AutoCreateDisabled=OAUTH2 Automatisch aanmaken gebruiker uitgeschakeld login.oauth2AutoCreateDisabled=OAUTH2 Automatisch aanmaken gebruiker uitgeschakeld
login.oauth2RequestNotFound=Authorization request not found login.oauth2RequestNotFound=Autorisatieverzoek niet gevonden
login.oauth2InvalidUserInfoResponse=Invalid User Info Response login.oauth2InvalidUserInfoResponse=Ongeldige reactie op gebruikersinfo
login.oauth2invalidRequest=Invalid Request login.oauth2invalidRequest=Ongeldig verzoek
login.oauth2AccessDenied=Access Denied login.oauth2AccessDenied=Toegang geweigerd
login.oauth2InvalidTokenResponse=Invalid Token Response login.oauth2InvalidTokenResponse=Ongeldige tokenreactie
login.oauth2InvalidIdToken=Invalid Id Token login.oauth2InvalidIdToken=Ongeldige ID token
#auto-redact #auto-redact
@@ -512,7 +529,7 @@ getPdfInfo.downloadJson=Download JSON
MarkdownToPDF.title=Markdown naar PDF MarkdownToPDF.title=Markdown naar PDF
MarkdownToPDF.header=Markdown naar PDF MarkdownToPDF.header=Markdown naar PDF
MarkdownToPDF.submit=Converteren MarkdownToPDF.submit=Converteren
MarkdownToPDF.help=in ontwikkeling MarkdownToPDF.help=In ontwikkeling
MarkdownToPDF.credit=Gebruikt WeasyPrint MarkdownToPDF.credit=Gebruikt WeasyPrint
@@ -542,7 +559,7 @@ HTMLToPDF.defaultHeader=Standaard koptekst weergeven (naam en paginanummer)
HTMLToPDF.cssMediaType=Wijzig het CSS-mediatype van de pagina. HTMLToPDF.cssMediaType=Wijzig het CSS-mediatype van de pagina.
HTMLToPDF.none=Geen HTMLToPDF.none=Geen
HTMLToPDF.print=Print HTMLToPDF.print=Print
HTMLToPDF.screen=Screen HTMLToPDF.screen=Scherm
#AddStampRequest #AddStampRequest
@@ -664,10 +681,10 @@ certSign.submit=PDF ondertekenen
#removeCertSign #removeCertSign
removeCertSign.title=Remove Certificate Signature removeCertSign.title=Verwijder certificaat
removeCertSign.header=Remove the digital certificate from the PDF removeCertSign.header=Verwijder het digitale certificaat van de PDF
removeCertSign.selectPDF=Select a PDF file: removeCertSign.selectPDF=Selecteer een PDF bestand:
removeCertSign.submit=Remove Signature removeCertSign.submit=Verwijder certificaat
#removeBlanks #removeBlanks
@@ -689,22 +706,24 @@ removeAnnotations.submit=Verwijderen
#compare #compare
compare.title=Vergelijken compare.title=Vergelijken
compare.header=PDF's vergelijken compare.header=PDF's vergelijken
compare.highlightColor.1=Highlight Color 1:
compare.highlightColor.2=Highlight Color 2:
compare.document.1=Document 1 compare.document.1=Document 1
compare.document.2=Document 2 compare.document.2=Document 2
compare.submit=Vergelijken compare.submit=Vergelijken
#BookToPDF #BookToPDF
BookToPDF.title=Books and Comics to PDF BookToPDF.title=Boeken en strips naar PDF
BookToPDF.header=Book to PDF BookToPDF.header=Boek naar PDF
BookToPDF.credit=Uses Calibre BookToPDF.credit=Gebruikt Calibre
BookToPDF.submit=Convert BookToPDF.submit=Converteer
#PDFToBook #PDFToBook
PDFToBook.title=PDF to Book PDFToBook.title=PDF naar boek
PDFToBook.header=PDF to Book PDFToBook.header=PDF naar boek
PDFToBook.selectText.1=Format PDFToBook.selectText.1=Formaat
PDFToBook.credit=Uses Calibre PDFToBook.credit=Gebruikt Calibre
PDFToBook.submit=Convert PDFToBook.submit=Converteer
#sign #sign
sign.title=Ondertekenen sign.title=Ondertekenen
@@ -725,7 +744,7 @@ repair.submit=Repareren
#flatten #flatten
flatten.title=Afvlakken flatten.title=Afvlakken
flatten.header=PDF's afvlakken flatten.header=PDF's afvlakken
flatten.flattenOnlyForms=Flatten only forms flatten.flattenOnlyForms=Alleen formulieren afvlakken
flatten.submit=Afvlakken flatten.submit=Afvlakken
@@ -756,7 +775,7 @@ ocr.selectText.8=Normaal (Zal een fout geven als de PDF tekst bevat)
ocr.selectText.9=Aanvullende instellingen ocr.selectText.9=Aanvullende instellingen
ocr.selectText.10=OCR-modus ocr.selectText.10=OCR-modus
ocr.selectText.11=Verwijder afbeeldingen na OCR (Verwijdert ALLE afbeeldingen, alleen nuttig als onderdeel van conversiestap) ocr.selectText.11=Verwijder afbeeldingen na OCR (Verwijdert ALLE afbeeldingen, alleen nuttig als onderdeel van conversiestap)
ocr.selectText.12=Render Type (Geavanceerd) ocr.selectText.12=Weergave Type (Geavanceerd)
ocr.help=Lees deze documentatie over hoe dit te gebruiken voor andere talen en/of gebruik buiten docker ocr.help=Lees deze documentatie over hoe dit te gebruiken voor andere talen en/of gebruik buiten docker
ocr.credit=Deze dienst maakt gebruik van OCRmyPDF en Tesseract voor OCR. ocr.credit=Deze dienst maakt gebruik van OCRmyPDF en Tesseract voor OCR.
ocr.submit=Verwerk PDF met OCR ocr.submit=Verwerk PDF met OCR
@@ -803,7 +822,7 @@ merge.title=Samenvoegen
merge.header=Meerdere PDF's samenvoegen (2+) merge.header=Meerdere PDF's samenvoegen (2+)
merge.sortByName=Sorteer op naam merge.sortByName=Sorteer op naam
merge.sortByDate=Sorteer op datum merge.sortByDate=Sorteer op datum
merge.removeCertSign=Remove digital signature in the merged file? merge.removeCertSign=Verwijder digitale handtekening in het samengevoegde bestand?
merge.submit=Samenvoegen merge.submit=Samenvoegen
@@ -811,23 +830,24 @@ merge.submit=Samenvoegen
pdfOrganiser.title=Pagina organisator pdfOrganiser.title=Pagina organisator
pdfOrganiser.header=PDF pagina organisator pdfOrganiser.header=PDF pagina organisator
pdfOrganiser.submit=Pagina's herschikken pdfOrganiser.submit=Pagina's herschikken
pdfOrganiser.mode=Mode pdfOrganiser.mode=Modus
pdfOrganiser.mode.1=Custom Page Order pdfOrganiser.mode.1=Aangepaste paginavolgorde
pdfOrganiser.mode.2=Reverse Order pdfOrganiser.mode.2=Omgekeerde volgorde
pdfOrganiser.mode.3=Duplex Sort pdfOrganiser.mode.3=Duplex sorteren
pdfOrganiser.mode.4=Booklet Sort pdfOrganiser.mode.4=Boekje sorteren
pdfOrganiser.mode.5=Side Stitch Booklet Sort pdfOrganiser.mode.5=Zijsteek boekje sorteren
pdfOrganiser.mode.6=Odd-Even Split pdfOrganiser.mode.6=Oneven-even splitsen
pdfOrganiser.mode.7=Remove First pdfOrganiser.mode.7=Eerste verwijderen
pdfOrganiser.mode.8=Remove Last pdfOrganiser.mode.8=Laatste verwijderen
pdfOrganiser.mode.9=Remove First and Last pdfOrganiser.mode.9=Eerste en laaste verwijderen
pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1) pdfOrganiser.mode.10=Oneven-even samenvoeken
pdfOrganiser.placeholder=(bijv. 1,3,2 of 4-8,2,10-12 of 2n-1)
#multiTool #multiTool
multiTool.title=PDF Multitool multiTool.title=PDF Multitool
multiTool.header=PDF Multitool multiTool.header=PDF Multitool
multiTool.uploadPrompts=File Name multiTool.uploadPrompts=Bestandsnaam
#view pdf #view pdf
viewPdf.title=PDF bekijken viewPdf.title=PDF bekijken
@@ -838,7 +858,7 @@ pageRemover.title=Pagina verwijderaar
pageRemover.header=PDF pagina verwijderaar pageRemover.header=PDF pagina verwijderaar
pageRemover.pagesToDelete=Te verwijderen pagina's (Voer een door komma's gescheiden lijst met paginanummers in): pageRemover.pagesToDelete=Te verwijderen pagina's (Voer een door komma's gescheiden lijst met paginanummers in):
pageRemover.submit=Pagina's verwijderen pageRemover.submit=Pagina's verwijderen
pageRemover.placeholder=(e.g. 1,2,6 or 1-10,15-30) pageRemover.placeholder=(bijv. 1,2,6 of 1-10,15-30)
#rotate #rotate
@@ -979,9 +999,9 @@ pdfToPDFA.title=PDF naar PDF/A
pdfToPDFA.header=PDF naar PDF/A pdfToPDFA.header=PDF naar PDF/A
pdfToPDFA.credit=Deze service gebruikt OCRmyPDF voor PDF/A-conversie pdfToPDFA.credit=Deze service gebruikt OCRmyPDF voor PDF/A-conversie
pdfToPDFA.submit=Converteren pdfToPDFA.submit=Converteren
pdfToPDFA.tip=Currently does not work for multiple inputs at once pdfToPDFA.tip=Werkt momenteel niet voor meerdere inputs tegelijkertijd.
pdfToPDFA.outputFormat=Output format pdfToPDFA.outputFormat=Output format
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step. pdfToPDFA.pdfWithDigitalSignature=Dit PDF bestand bevat een digitale handtekening. Deze wordt in de volgende stap verwijderd.
#PDFToWord #PDFToWord
@@ -1063,14 +1083,14 @@ split-by-sections.vertical.label=Verticale secties
split-by-sections.horizontal.placeholder=Voer het aantal horizontale secties in split-by-sections.horizontal.placeholder=Voer het aantal horizontale secties in
split-by-sections.vertical.placeholder=Voer het aantal verticale secties in split-by-sections.vertical.placeholder=Voer het aantal verticale secties in
split-by-sections.submit=PDF splitsen split-by-sections.submit=PDF splitsen
split-by-sections.merge=Merge Into One PDF split-by-sections.merge=Samenvoegen in één PDF
#printFile #printFile
printFile.title=Print File printFile.title=Print bestand
printFile.header=Print File to Printer printFile.header=Print bestand naar printer
printFile.selectText.1=Select File to Print printFile.selectText.1=Selecteer bestand om te printen
printFile.selectText.2=Enter Printer Name printFile.selectText.2=Voer printernaam in
printFile.submit=Print printFile.submit=Print
@@ -1083,25 +1103,25 @@ licenses.version=Versie
licenses.license=Licentie licenses.license=Licentie
#survey #survey
survey.nav=Survey survey.nav=Enquête
survey.title=Stirling-PDF Survey survey.title=Stirling-PDF Enquête
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF! survey.description=Stirling-PDF heeft geen tracking, dus we willen van onze gebruikers horen om Stirling-PDF te verbeteren.
survey.please=Please consider taking our survey! survey.please=Overweeg alstublieft om onze enquête in te vullen!
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page) survey.disabled=(Enquête popup wordt in een toekomstige update weggehaald, maar is beschikbaar aan de onderkant van de pagina.)
survey.button=Take Survey survey.button=Vul enquête in.
survey.dontShowAgain=Don't show again survey.dontShowAgain=Niet weer tonen
#error #error
error.sorry=Sorry for the issue! error.sorry=Excuses voor het probleem!
error.needHelp=Need help / Found an issue? error.needHelp=Hulp nodig / probleem gevonden?
error.contactTip=If you're still having trouble, don't hesitate to reach out to us for help. You can submit a ticket on our GitHub page or contact us through Discord: error.contactTip=Als je nog steeds problemen hebt, schroom niet om contact met ons op te nemen voor hulp. Je kan een ticket op onze Github pagina indienen of ons via Discord bereiken:
error.404.head=404 - Page Not Found | Oops, we tripped in the code! error.404.head=404 - Pagina niet gevonden | Oeps, we struikelden over de code!
error.404.1=We can't seem to find the page you're looking for. error.404.1=We kunnen de pagina die je zoek niet vinden.
error.404.2=Something went wrong error.404.2=Er ging iets mis.
error.github=Submit a ticket on GitHub error.github=Dien een ticket op Github in.
error.showStack=Show Stack Trace error.showStack=Geeft tracering weer
error.copyStack=Copy Stack Trace error.copyStack=Kopieer tracering
error.githubSubmit=GitHub - Submit a ticket error.githubSubmit=GitHub - Dien een ticket in
error.discordSubmit=Discord - Submit Support post error.discordSubmit=Discord - Maak een support post

View File

@@ -55,7 +55,7 @@ userNotFoundMessage=Bruker ikke funnet.
incorrectPasswordMessage=Nåværende passord er feil. incorrectPasswordMessage=Nåværende passord er feil.
usernameExistsMessage=Det nye brukernavnet eksisterer allerede. usernameExistsMessage=Det nye brukernavnet eksisterer allerede.
invalidUsernameMessage=Ugyldig brukernavn, brukernavnet kan bare inneholde bokstaver, tall og følgende spesialtegn @._+- eller må være en gyldig e-postadresse. invalidUsernameMessage=Ugyldig brukernavn, brukernavnet kan bare inneholde bokstaver, tall og følgende spesialtegn @._+- eller må være en gyldig e-postadresse.
confirmPasswordErrorMessage=New Password and Confirm New Password must match. confirmPasswordErrorMessage=Nytt passord og Bekreft nytt passord må være like.
deleteCurrentUserMessage=Kan ikke slette den innloggede brukeren. deleteCurrentUserMessage=Kan ikke slette den innloggede brukeren.
deleteUsernameExistsMessage=Brukernavnet eksisterer ikke og kan ikke slettes. deleteUsernameExistsMessage=Brukernavnet eksisterer ikke og kan ikke slettes.
downgradeCurrentUserMessage=Kan ikke nedgradere den innloggede brukerens rolle. downgradeCurrentUserMessage=Kan ikke nedgradere den innloggede brukerens rolle.
@@ -175,8 +175,8 @@ adminUserSettings.header=Admin Brukerkontroll Innstillinger
adminUserSettings.admin=Admin adminUserSettings.admin=Admin
adminUserSettings.user=Bruker adminUserSettings.user=Bruker
adminUserSettings.addUser=Legg til Ny Bruker adminUserSettings.addUser=Legg til Ny Bruker
adminUserSettings.deleteUser=Delete User adminUserSettings.deleteUser=Slett Bruker
adminUserSettings.confirmDeleteUser=Should the user be deleted? adminUserSettings.confirmDeleteUser=Skal brukeren slettes?
adminUserSettings.usernameInfo=Brukernavn kan bare inneholde bokstaver, tall og følgende spesialtegn @._+- eller må være en gyldig e-postadresse. adminUserSettings.usernameInfo=Brukernavn kan bare inneholde bokstaver, tall og følgende spesialtegn @._+- eller må være en gyldig e-postadresse.
adminUserSettings.roles=Roller adminUserSettings.roles=Roller
adminUserSettings.role=Rolle adminUserSettings.role=Rolle
@@ -191,6 +191,23 @@ adminUserSettings.submit=Lagre Bruker
adminUserSettings.changeUserRole=Endre Brukerens Rolle adminUserSettings.changeUserRole=Endre Brukerens Rolle
adminUserSettings.authenticated=Autentisert adminUserSettings.authenticated=Autentisert
database.title=Database Import/Export
database.header=Database Import/Export
database.fileName=File Name
database.creationDate=Creation Date
database.fileSize=File Size
database.deleteBackupFile=Delete Backup File
database.importBackupFile=Import Backup File
database.downloadBackupFile=Download Backup File
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
database.submit=Import Backup
database.importIntoDatabaseSuccessed=Import into database successed
database.fileNotFound=File not Found
database.fileNullOrEmpty=File must not be null or empty
database.failedImportFile=Failed Import File
############# #############
# HOME-PAGE # # HOME-PAGE #
############# #############
@@ -540,8 +557,8 @@ HTMLToPDF.marginRight=Høyre margin på siden i millimeter. (Blank for standard)
HTMLToPDF.printBackground=Vis bakgrunnen til nettsider. HTMLToPDF.printBackground=Vis bakgrunnen til nettsider.
HTMLToPDF.defaultHeader=Aktiver standardtopp (Navn og sidenummer) HTMLToPDF.defaultHeader=Aktiver standardtopp (Navn og sidenummer)
HTMLToPDF.cssMediaType=Endre CSS-mediatypen til siden. HTMLToPDF.cssMediaType=Endre CSS-mediatypen til siden.
HTMLToPDF.none=None HTMLToPDF.none=Ingen
HTMLToPDF.print=Print HTMLToPDF.print=Utskrift
HTMLToPDF.screen=Skjerm HTMLToPDF.screen=Skjerm
@@ -689,6 +706,8 @@ removeAnnotations.submit=Fjern
#compare #compare
compare.title=Sammenlign compare.title=Sammenlign
compare.header=Sammenlign PDF-er compare.header=Sammenlign PDF-er
compare.highlightColor.1=Highlight Color 1:
compare.highlightColor.2=Highlight Color 2:
compare.document.1=Dokument 1 compare.document.1=Dokument 1
compare.document.2=Dokument 2 compare.document.2=Dokument 2
compare.submit=Sammenlign compare.submit=Sammenlign
@@ -803,7 +822,7 @@ merge.title=Slå sammen
merge.header=Slå sammen flere PDF-er (2+) merge.header=Slå sammen flere PDF-er (2+)
merge.sortByName=Sorter etter navn merge.sortByName=Sorter etter navn
merge.sortByDate=Sorter etter dato merge.sortByDate=Sorter etter dato
merge.removeCertSign=Remove digital signature in the merged file? merge.removeCertSign=Fjern digital signatur i den sammenslåtte filen?
merge.submit=Slå sammen merge.submit=Slå sammen
@@ -821,6 +840,7 @@ pdfOrganiser.mode.6=Oddetall-jevntall splitt
pdfOrganiser.mode.7=Fjern først pdfOrganiser.mode.7=Fjern først
pdfOrganiser.mode.8=Fjern sist pdfOrganiser.mode.8=Fjern sist
pdfOrganiser.mode.9=Fjern først og sist pdfOrganiser.mode.9=Fjern først og sist
pdfOrganiser.mode.10=Partall-Oddetall Sammenslåing
pdfOrganiser.placeholder=(f.eks. 1,3,2 eller 4-8,2,10-12 eller 2n-1) pdfOrganiser.placeholder=(f.eks. 1,3,2 eller 4-8,2,10-12 eller 2n-1)

830
src/main/resources/messages_pl_PL.properties Normal file → Executable file

File diff suppressed because it is too large Load Diff

View File

@@ -191,6 +191,23 @@ adminUserSettings.submit=Save User
adminUserSettings.changeUserRole=Alterar Função de Usuário adminUserSettings.changeUserRole=Alterar Função de Usuário
adminUserSettings.authenticated=Authenticated adminUserSettings.authenticated=Authenticated
database.title=Database Import/Export
database.header=Database Import/Export
database.fileName=File Name
database.creationDate=Creation Date
database.fileSize=File Size
database.deleteBackupFile=Delete Backup File
database.importBackupFile=Import Backup File
database.downloadBackupFile=Download Backup File
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
database.submit=Import Backup
database.importIntoDatabaseSuccessed=Import into database successed
database.fileNotFound=File not Found
database.fileNullOrEmpty=File must not be null or empty
database.failedImportFile=Failed Import File
############# #############
# HOME-PAGE # # HOME-PAGE #
############# #############
@@ -689,6 +706,8 @@ removeAnnotations.submit=Remove
#compare #compare
compare.title=Comparar compare.title=Comparar
compare.header=Comparar PDFs compare.header=Comparar PDFs
compare.highlightColor.1=Highlight Color 1:
compare.highlightColor.2=Highlight Color 2:
compare.document.1=Documento 1 compare.document.1=Documento 1
compare.document.2=Documento 2 compare.document.2=Documento 2
compare.submit=Comparar compare.submit=Comparar
@@ -821,6 +840,7 @@ pdfOrganiser.mode.6=Odd-Even Split
pdfOrganiser.mode.7=Remove First pdfOrganiser.mode.7=Remove First
pdfOrganiser.mode.8=Remove Last pdfOrganiser.mode.8=Remove Last
pdfOrganiser.mode.9=Remove First and Last pdfOrganiser.mode.9=Remove First and Last
pdfOrganiser.mode.10=Odd-Even Merge
pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1) pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)

View File

@@ -191,6 +191,23 @@ adminUserSettings.submit=Save User
adminUserSettings.changeUserRole=Alterar usuário adminUserSettings.changeUserRole=Alterar usuário
adminUserSettings.authenticated=Authenticated adminUserSettings.authenticated=Authenticated
database.title=Database Import/Export
database.header=Database Import/Export
database.fileName=File Name
database.creationDate=Creation Date
database.fileSize=File Size
database.deleteBackupFile=Delete Backup File
database.importBackupFile=Import Backup File
database.downloadBackupFile=Download Backup File
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
database.submit=Import Backup
database.importIntoDatabaseSuccessed=Import into database successed
database.fileNotFound=File not Found
database.fileNullOrEmpty=File must not be null or empty
database.failedImportFile=Failed Import File
############# #############
# HOME-PAGE # # HOME-PAGE #
############# #############
@@ -689,6 +706,8 @@ removeAnnotations.submit=Remover
#compare #compare
compare.title=Comparar compare.title=Comparar
compare.header=Comparar PDFs compare.header=Comparar PDFs
compare.highlightColor.1=Highlight Color 1:
compare.highlightColor.2=Highlight Color 2:
compare.document.1=Documento 1 compare.document.1=Documento 1
compare.document.2=Documento 2 compare.document.2=Documento 2
compare.submit=Comparar compare.submit=Comparar
@@ -821,6 +840,7 @@ pdfOrganiser.mode.6=Odd-Even Split
pdfOrganiser.mode.7=Remove First pdfOrganiser.mode.7=Remove First
pdfOrganiser.mode.8=Remove Last pdfOrganiser.mode.8=Remove Last
pdfOrganiser.mode.9=Remove First and Last pdfOrganiser.mode.9=Remove First and Last
pdfOrganiser.mode.10=Odd-Even Merge
pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1) pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)

View File

@@ -191,6 +191,23 @@ adminUserSettings.submit=Save User
adminUserSettings.changeUserRole=Schimbați rolul utilizatorului adminUserSettings.changeUserRole=Schimbați rolul utilizatorului
adminUserSettings.authenticated=Authenticated adminUserSettings.authenticated=Authenticated
database.title=Database Import/Export
database.header=Database Import/Export
database.fileName=File Name
database.creationDate=Creation Date
database.fileSize=File Size
database.deleteBackupFile=Delete Backup File
database.importBackupFile=Import Backup File
database.downloadBackupFile=Download Backup File
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
database.submit=Import Backup
database.importIntoDatabaseSuccessed=Import into database successed
database.fileNotFound=File not Found
database.fileNullOrEmpty=File must not be null or empty
database.failedImportFile=Failed Import File
############# #############
# HOME-PAGE # # HOME-PAGE #
############# #############
@@ -689,6 +706,8 @@ removeAnnotations.submit=Remove
#compare #compare
compare.title=Compară compare.title=Compară
compare.header=Compară PDF-uri compare.header=Compară PDF-uri
compare.highlightColor.1=Highlight Color 1:
compare.highlightColor.2=Highlight Color 2:
compare.document.1=Document 1 compare.document.1=Document 1
compare.document.2=Document 2 compare.document.2=Document 2
compare.submit=Compară compare.submit=Compară
@@ -821,6 +840,7 @@ pdfOrganiser.mode.6=Odd-Even Split
pdfOrganiser.mode.7=Remove First pdfOrganiser.mode.7=Remove First
pdfOrganiser.mode.8=Remove Last pdfOrganiser.mode.8=Remove Last
pdfOrganiser.mode.9=Remove First and Last pdfOrganiser.mode.9=Remove First and Last
pdfOrganiser.mode.10=Odd-Even Merge
pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1) pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)

View File

@@ -191,6 +191,23 @@ adminUserSettings.submit=Сохранить пользователя
adminUserSettings.changeUserRole=Изменить роль пользователя adminUserSettings.changeUserRole=Изменить роль пользователя
adminUserSettings.authenticated=Authenticated adminUserSettings.authenticated=Authenticated
database.title=Database Import/Export
database.header=Database Import/Export
database.fileName=File Name
database.creationDate=Creation Date
database.fileSize=File Size
database.deleteBackupFile=Delete Backup File
database.importBackupFile=Import Backup File
database.downloadBackupFile=Download Backup File
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
database.submit=Import Backup
database.importIntoDatabaseSuccessed=Import into database successed
database.fileNotFound=File not Found
database.fileNullOrEmpty=File must not be null or empty
database.failedImportFile=Failed Import File
############# #############
# HOME-PAGE # # HOME-PAGE #
############# #############
@@ -689,6 +706,8 @@ removeAnnotations.submit=Удалить
#compare #compare
compare.title=Сравнение compare.title=Сравнение
compare.header=Сравнение PDFы compare.header=Сравнение PDFы
compare.highlightColor.1=Highlight Color 1:
compare.highlightColor.2=Highlight Color 2:
compare.document.1=Документ 1 compare.document.1=Документ 1
compare.document.2=Документ 2 compare.document.2=Документ 2
compare.submit=Сравнить compare.submit=Сравнить
@@ -821,6 +840,7 @@ pdfOrganiser.mode.6=Разделение на чётные и нечётные
pdfOrganiser.mode.7=Удалить первую pdfOrganiser.mode.7=Удалить первую
pdfOrganiser.mode.8=Удалить последнюю pdfOrganiser.mode.8=Удалить последнюю
pdfOrganiser.mode.9=Удалить первую и последнюю pdfOrganiser.mode.9=Удалить первую и последнюю
pdfOrganiser.mode.10=Odd-Even Merge
pdfOrganiser.placeholder=(например, 1,3,2 или 4-8,2,10-12 или 2n-1) pdfOrganiser.placeholder=(например, 1,3,2 или 4-8,2,10-12 или 2n-1)

View File

@@ -191,6 +191,23 @@ adminUserSettings.submit=Uložiť používateľa
adminUserSettings.changeUserRole=Zmeniť rolu používateľa adminUserSettings.changeUserRole=Zmeniť rolu používateľa
adminUserSettings.authenticated=Authenticated adminUserSettings.authenticated=Authenticated
database.title=Database Import/Export
database.header=Database Import/Export
database.fileName=File Name
database.creationDate=Creation Date
database.fileSize=File Size
database.deleteBackupFile=Delete Backup File
database.importBackupFile=Import Backup File
database.downloadBackupFile=Download Backup File
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
database.submit=Import Backup
database.importIntoDatabaseSuccessed=Import into database successed
database.fileNotFound=File not Found
database.fileNullOrEmpty=File must not be null or empty
database.failedImportFile=Failed Import File
############# #############
# HOME-PAGE # # HOME-PAGE #
############# #############
@@ -689,6 +706,8 @@ removeAnnotations.submit=Odstrániť
#compare #compare
compare.title=Porovnať compare.title=Porovnať
compare.header=Porovnať PDF compare.header=Porovnať PDF
compare.highlightColor.1=Highlight Color 1:
compare.highlightColor.2=Highlight Color 2:
compare.document.1=Dokument 1 compare.document.1=Dokument 1
compare.document.2=Dokument 2 compare.document.2=Dokument 2
compare.submit=Porovnať compare.submit=Porovnať
@@ -821,6 +840,7 @@ pdfOrganiser.mode.6=Rozdelenie na nepárne a párne
pdfOrganiser.mode.7=Odstrániť prvú pdfOrganiser.mode.7=Odstrániť prvú
pdfOrganiser.mode.8=Odstrániť poslednú pdfOrganiser.mode.8=Odstrániť poslednú
pdfOrganiser.mode.9=Odstrániť prvú aj poslednú pdfOrganiser.mode.9=Odstrániť prvú aj poslednú
pdfOrganiser.mode.10=Odd-Even Merge
pdfOrganiser.placeholder=(napr. 1,3,2 alebo 4-8,2,10-12 alebo 2n-1) pdfOrganiser.placeholder=(napr. 1,3,2 alebo 4-8,2,10-12 alebo 2n-1)

View File

@@ -191,6 +191,23 @@ adminUserSettings.submit=Sačuvaj korisnika
adminUserSettings.changeUserRole=Promenite ulogu korisnika adminUserSettings.changeUserRole=Promenite ulogu korisnika
adminUserSettings.authenticated=Authenticated adminUserSettings.authenticated=Authenticated
database.title=Database Import/Export
database.header=Database Import/Export
database.fileName=File Name
database.creationDate=Creation Date
database.fileSize=File Size
database.deleteBackupFile=Delete Backup File
database.importBackupFile=Import Backup File
database.downloadBackupFile=Download Backup File
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
database.submit=Import Backup
database.importIntoDatabaseSuccessed=Import into database successed
database.fileNotFound=File not Found
database.fileNullOrEmpty=File must not be null or empty
database.failedImportFile=Failed Import File
############# #############
# HOME-PAGE # # HOME-PAGE #
############# #############
@@ -689,6 +706,8 @@ removeAnnotations.submit=Ukloni
#compare #compare
compare.title=Uporedi compare.title=Uporedi
compare.header=Uporedi PDF fajlove compare.header=Uporedi PDF fajlove
compare.highlightColor.1=Highlight Color 1:
compare.highlightColor.2=Highlight Color 2:
compare.document.1=Dokument 1 compare.document.1=Dokument 1
compare.document.2=Dokument 2 compare.document.2=Dokument 2
compare.submit=Uporedi compare.submit=Uporedi
@@ -821,6 +840,7 @@ pdfOrganiser.mode.6=Odd-Even Split
pdfOrganiser.mode.7=Remove First pdfOrganiser.mode.7=Remove First
pdfOrganiser.mode.8=Remove Last pdfOrganiser.mode.8=Remove Last
pdfOrganiser.mode.9=Remove First and Last pdfOrganiser.mode.9=Remove First and Last
pdfOrganiser.mode.10=Odd-Even Merge
pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1) pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)

View File

@@ -191,6 +191,23 @@ adminUserSettings.submit=Save User
adminUserSettings.changeUserRole=Ändra användarens roll adminUserSettings.changeUserRole=Ändra användarens roll
adminUserSettings.authenticated=Authenticated adminUserSettings.authenticated=Authenticated
database.title=Database Import/Export
database.header=Database Import/Export
database.fileName=File Name
database.creationDate=Creation Date
database.fileSize=File Size
database.deleteBackupFile=Delete Backup File
database.importBackupFile=Import Backup File
database.downloadBackupFile=Download Backup File
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
database.submit=Import Backup
database.importIntoDatabaseSuccessed=Import into database successed
database.fileNotFound=File not Found
database.fileNullOrEmpty=File must not be null or empty
database.failedImportFile=Failed Import File
############# #############
# HOME-PAGE # # HOME-PAGE #
############# #############
@@ -689,6 +706,8 @@ removeAnnotations.submit=Remove
#compare #compare
compare.title=Jämför compare.title=Jämför
compare.header=Jämför PDF-filer compare.header=Jämför PDF-filer
compare.highlightColor.1=Highlight Color 1:
compare.highlightColor.2=Highlight Color 2:
compare.document.1=Dokument 1 compare.document.1=Dokument 1
compare.document.2=Dokument 2 compare.document.2=Dokument 2
compare.submit=Jämför compare.submit=Jämför
@@ -821,6 +840,7 @@ pdfOrganiser.mode.6=Odd-Even Split
pdfOrganiser.mode.7=Remove First pdfOrganiser.mode.7=Remove First
pdfOrganiser.mode.8=Remove Last pdfOrganiser.mode.8=Remove Last
pdfOrganiser.mode.9=Remove First and Last pdfOrganiser.mode.9=Remove First and Last
pdfOrganiser.mode.10=Odd-Even Merge
pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1) pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)

File diff suppressed because it is too large Load Diff

View File

@@ -55,7 +55,7 @@ userNotFoundMessage=Kullanıcı bulunamadı.
incorrectPasswordMessage=Mevcut şifre yanlış. incorrectPasswordMessage=Mevcut şifre yanlış.
usernameExistsMessage=Yeni Kullanıcı Adı zaten var. usernameExistsMessage=Yeni Kullanıcı Adı zaten var.
invalidUsernameMessage=Geçersiz kullanıcı adı, kullanıcı adı yalnızca harf, rakam ve aşağıdaki özel karakterleri @._+- içerebilir veya geçerli bir e-posta adresi olmalıdır. invalidUsernameMessage=Geçersiz kullanıcı adı, kullanıcı adı yalnızca harf, rakam ve aşağıdaki özel karakterleri @._+- içerebilir veya geçerli bir e-posta adresi olmalıdır.
confirmPasswordErrorMessage=New Password and Confirm New Password must match. confirmPasswordErrorMessage=Yeni Şifre ve Yeni Şifreyi Onayla eşleşmelidir.
deleteCurrentUserMessage=Şu anda oturum açmış olan kullanıcı silinemiyor. deleteCurrentUserMessage=Şu anda oturum açmış olan kullanıcı silinemiyor.
deleteUsernameExistsMessage=Kullanıcı adı mevcut değil ve silinemez. deleteUsernameExistsMessage=Kullanıcı adı mevcut değil ve silinemez.
downgradeCurrentUserMessage=Mevcut kullanıcının rolü düşürülemiyor downgradeCurrentUserMessage=Mevcut kullanıcının rolü düşürülemiyor
@@ -86,7 +86,7 @@ pipeline.defaultOption=Özel
pipeline.submitButton=Gönder pipeline.submitButton=Gönder
pipeline.help=Çoklu İşlemler Yardım pipeline.help=Çoklu İşlemler Yardım
pipeline.scanHelp=Klasör Tarama Yardımı pipeline.scanHelp=Klasör Tarama Yardımı
pipeline.deletePrompt=Are you sure you want to delete pipeline pipeline.deletePrompt=Çoklu işlemleri silmek istediğinizden emin misiniz
###################### ######################
# Pipeline Options # # Pipeline Options #
@@ -116,7 +116,7 @@ navbar.multiTool=Çoklu Araçlar
navbar.sections.organize=Düzenle navbar.sections.organize=Düzenle
navbar.sections.convertTo=PDF'ye dönüştür navbar.sections.convertTo=PDF'ye dönüştür
navbar.sections.convertFrom=PDF'den dönüştür navbar.sections.convertFrom=PDF'den dönüştür
navbar.sections.security=Oturum & Güvenlik navbar.sections.security=Oturum ve Güvenlik
navbar.sections.advance=Gelişmiş navbar.sections.advance=Gelişmiş
navbar.sections.edit=Görüntüle ve Düzenle navbar.sections.edit=Görüntüle ve Düzenle
@@ -175,8 +175,8 @@ adminUserSettings.header=Yönetici Kullanıcı Kontrol Ayarları
adminUserSettings.admin=Yönetici adminUserSettings.admin=Yönetici
adminUserSettings.user=Kullanıcı adminUserSettings.user=Kullanıcı
adminUserSettings.addUser=Yeni Kullanıcı Ekle adminUserSettings.addUser=Yeni Kullanıcı Ekle
adminUserSettings.deleteUser=Delete User adminUserSettings.deleteUser=Kullanıcı Sil
adminUserSettings.confirmDeleteUser=Should the user be deleted? adminUserSettings.confirmDeleteUser=Kullanıcı silinsin mi?
adminUserSettings.usernameInfo=Kullanıcı adı yalnızca harf, rakam ve aşağıdaki özel karakterleri @._+- içerebilir veya geçerli bir e-posta adresi olmalıdır. adminUserSettings.usernameInfo=Kullanıcı adı yalnızca harf, rakam ve aşağıdaki özel karakterleri @._+- içerebilir veya geçerli bir e-posta adresi olmalıdır.
adminUserSettings.roles=Roller adminUserSettings.roles=Roller
adminUserSettings.role=Rol adminUserSettings.role=Rol
@@ -191,6 +191,23 @@ adminUserSettings.submit=Kullanıcıyı Kaydet
adminUserSettings.changeUserRole=Kullanıcı rolünü değiştir adminUserSettings.changeUserRole=Kullanıcı rolünü değiştir
adminUserSettings.authenticated=Onaylandı adminUserSettings.authenticated=Onaylandı
database.title=Veri Tabanını İçe/Dışa Aktar
database.header=Veri Tabanını İçe/Dışa Aktar
database.fileName=Dosya Adı
database.creationDate=Oluşturulma Tarihi
database.fileSize=Dosya Boyutu
database.deleteBackupFile=Yedekleme Dosyasını Sil
database.importBackupFile=Yedekleme Dosyasını İçe Aktar
database.downloadBackupFile=Yedekleme Dosyasını İndir
database.info_1=Verileri içe aktarırken, yapının doğru olduğundan emin olmak çok önemlidir. Ne yaptığınızdan emin değilseniz, bir uzmandan tavsiye ve destek alın. Yapıdaki bir hata, uygulamanın tamamen çalıştırılamaması da dahil olmak üzere uygulama sorunlarına neden olabilir.
database.info_2=Karşıya yüklerken dosya adı önemli değildir. Daha sonra yedekleme_kullanıcısı_yyyyAAggSdd.sql biçiminde yeniden adlandırılacak ve tutarlı bir adlandırma kuralı sağlanacaktır.
database.submit=Yedeklemeyi İçe Aktar
database.importIntoDatabaseSuccessed=Veri tabanına başarıyla aktarıldı
database.fileNotFound=Dosya bulunamadı
database.fileNullOrEmpty=Dosya yok veya boş olmamalıdır
database.failedImportFile=Dosya İçe Aktarılamadı
############# #############
# HOME-PAGE # # HOME-PAGE #
############# #############
@@ -336,9 +353,9 @@ home.certSign.title=Sertifika ile İmzala
home.certSign.desc=Bir PDF'i Sertifika/Anahtar (PEM/P12) ile imzalar home.certSign.desc=Bir PDF'i Sertifika/Anahtar (PEM/P12) ile imzalar
certSign.tags=doğrula,PEM,P12,resmi,şifrele certSign.tags=doğrula,PEM,P12,resmi,şifrele
home.removeCertSign.title=Remove Certificate Sign home.removeCertSign.title=Sertifika İmzasını Kaldır
home.removeCertSign.desc=Remove certificate signature from PDF home.removeCertSign.desc=PDF'ten sertifika imzasını kaldırır
removeCertSign.tags=authenticate,PEM,P12,official,decrypt removeCertSign.tags=doğrula,PEM,P12,resmi,şifre çöz
home.pageLayout.title=Çoklu-Sayfa Düzeni home.pageLayout.title=Çoklu-Sayfa Düzeni
home.pageLayout.desc=Bir PDF belgesinin çoklu sayfalarını tek bir sayfada birleştirir home.pageLayout.desc=Bir PDF belgesinin çoklu sayfalarını tek bir sayfada birleştirir
@@ -460,12 +477,12 @@ login.locked=Hesabınız kilitlendi.
login.signinTitle=Lütfen giriş yapınız. login.signinTitle=Lütfen giriş yapınız.
login.ssoSignIn=Tek Oturum Açma ile Giriş Yap login.ssoSignIn=Tek Oturum Açma ile Giriş Yap
login.oauth2AutoCreateDisabled=OAUTH2 Otomatik Oluşturma Kullanıcı Devre Dışı Bırakıldı login.oauth2AutoCreateDisabled=OAUTH2 Otomatik Oluşturma Kullanıcı Devre Dışı Bırakıldı
login.oauth2RequestNotFound=Authorization request not found login.oauth2RequestNotFound=Yetkilendirme isteği bulunamadı
login.oauth2InvalidUserInfoResponse=Invalid User Info Response login.oauth2InvalidUserInfoResponse=Geçersiz Kullanıcı Bilgisi Yanıtı
login.oauth2invalidRequest=Invalid Request login.oauth2invalidRequest=Geçersiz İstek
login.oauth2AccessDenied=Access Denied login.oauth2AccessDenied=Erişim Reddedildi
login.oauth2InvalidTokenResponse=Invalid Token Response login.oauth2InvalidTokenResponse=Geçersiz Belirteç Yanıtı
login.oauth2InvalidIdToken=Invalid Id Token login.oauth2InvalidIdToken=Geçersiz Kimlik Belirteci
#auto-redact #auto-redact
@@ -664,10 +681,10 @@ certSign.submit=PDF'i İmzala
#removeCertSign #removeCertSign
removeCertSign.title=Remove Certificate Signature removeCertSign.title=Sertifika İmzasını Kaldır
removeCertSign.header=Remove the digital certificate from the PDF removeCertSign.header=PDF'ten dijital sertifikayı kaldırın
removeCertSign.selectPDF=Select a PDF file: removeCertSign.selectPDF=PDF dosyası seçin:
removeCertSign.submit=Remove Signature removeCertSign.submit=İmzayı Kaldır
#removeBlanks #removeBlanks
@@ -689,6 +706,8 @@ removeAnnotations.submit=Kaldır
#compare #compare
compare.title=Karşılaştır compare.title=Karşılaştır
compare.header=PDF'leri Karşılaştır compare.header=PDF'leri Karşılaştır
compare.highlightColor.1=Vurgu Rengi 1:
compare.highlightColor.2=Vurgu Rengi 2:
compare.document.1=Belge 1 compare.document.1=Belge 1
compare.document.2=Belge 2 compare.document.2=Belge 2
compare.submit=Karşılaştır compare.submit=Karşılaştır
@@ -725,7 +744,7 @@ repair.submit=Onar
#flatten #flatten
flatten.title=Düzleştir flatten.title=Düzleştir
flatten.header=PDF'leri Düzleştir flatten.header=PDF'leri Düzleştir
flatten.flattenOnlyForms=Flatten only forms flatten.flattenOnlyForms=Yalnızca formları düzleştir
flatten.submit=Düzleştir flatten.submit=Düzleştir
@@ -803,7 +822,7 @@ merge.title=Birleştir
merge.header=Çoklu PDF'leri Birleştir (2+) merge.header=Çoklu PDF'leri Birleştir (2+)
merge.sortByName=İsme göre sırala merge.sortByName=İsme göre sırala
merge.sortByDate=Tarihe göre sırala merge.sortByDate=Tarihe göre sırala
merge.removeCertSign=Remove digital signature in the merged file? merge.removeCertSign=Birleştirilen dosyadaki dijital imza kaldırılsın mı?
merge.submit=Birleştir merge.submit=Birleştir
@@ -821,6 +840,7 @@ pdfOrganiser.mode.6=Tek-Çift Ayrımı
pdfOrganiser.mode.7=İlk Önce Kaldır pdfOrganiser.mode.7=İlk Önce Kaldır
pdfOrganiser.mode.8=Sonuncuyu Kaldır pdfOrganiser.mode.8=Sonuncuyu Kaldır
pdfOrganiser.mode.9=İlk ve Sonu Kaldır pdfOrganiser.mode.9=İlk ve Sonu Kaldır
pdfOrganiser.mode.10=Tek-Çift Birleştirme
pdfOrganiser.placeholder=(örn. 1,3,2 veya 4-8,2,10-12 veya 2n-1) pdfOrganiser.placeholder=(örn. 1,3,2 veya 4-8,2,10-12 veya 2n-1)
@@ -1079,17 +1099,17 @@ licenses.nav=Lisanslar
licenses.title=3. Taraf Lisansları licenses.title=3. Taraf Lisansları
licenses.header=3. Taraf Lisansları licenses.header=3. Taraf Lisansları
licenses.module=Modül licenses.module=Modül
licenses.version=Versiyon licenses.version=Sürüm
licenses.license=Lisans licenses.license=Lisans
#survey #survey
survey.nav=Survey survey.nav=Anket
survey.title=Stirling-PDF Survey survey.title=Stirling-PDF Anketi
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF! survey.description=Stirling-PDF'te izleme yok, bu yüzden Stirling-PDF'i iyileştirmek için kullanıcılarımızdan geri bildirim almak istiyoruz!
survey.please=Please consider taking our survey! survey.please=Lütfen anketimize katılmayı düşünün!
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page) survey.disabled=(Anket açılır penceresi sonraki güncellemelerde devre dışı bırakılacak ancak sayfanın alt kısmında yer alacaktır)
survey.button=Take Survey survey.button=Ankete Katıl
survey.dontShowAgain=Don't show again survey.dontShowAgain=Tekrar gösterme
#error #error

View File

@@ -191,6 +191,23 @@ adminUserSettings.submit=Зберегти користувача
adminUserSettings.changeUserRole=Змінити роль користувача adminUserSettings.changeUserRole=Змінити роль користувача
adminUserSettings.authenticated=Автентифіковано adminUserSettings.authenticated=Автентифіковано
database.title=Database Import/Export
database.header=Database Import/Export
database.fileName=File Name
database.creationDate=Creation Date
database.fileSize=File Size
database.deleteBackupFile=Delete Backup File
database.importBackupFile=Import Backup File
database.downloadBackupFile=Download Backup File
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
database.submit=Import Backup
database.importIntoDatabaseSuccessed=Import into database successed
database.fileNotFound=File not Found
database.fileNullOrEmpty=File must not be null or empty
database.failedImportFile=Failed Import File
############# #############
# HOME-PAGE # # HOME-PAGE #
############# #############
@@ -689,6 +706,8 @@ removeAnnotations.submit=Видалити
#compare #compare
compare.title=Порівняння compare.title=Порівняння
compare.header=Порівняння PDF compare.header=Порівняння PDF
compare.highlightColor.1=Highlight Color 1:
compare.highlightColor.2=Highlight Color 2:
compare.document.1=Документ 1 compare.document.1=Документ 1
compare.document.2=Документ 2 compare.document.2=Документ 2
compare.submit=Порівняти compare.submit=Порівняти
@@ -821,6 +840,7 @@ pdfOrganiser.mode.6=Розділення на парні та непарні с
pdfOrganiser.mode.7=Видалити першу pdfOrganiser.mode.7=Видалити першу
pdfOrganiser.mode.8=Видалити останню pdfOrganiser.mode.8=Видалити останню
pdfOrganiser.mode.9=Видалити першу та останню pdfOrganiser.mode.9=Видалити першу та останню
pdfOrganiser.mode.10=Odd-Even Merge
pdfOrganiser.placeholder=(наприклад, 1,3,2 або 4-8,2,10-12 або 2n-1) pdfOrganiser.placeholder=(наприклад, 1,3,2 або 4-8,2,10-12 або 2n-1)

View File

@@ -10,8 +10,8 @@ multiPdfDropPrompt=选择或拖拽所需的PDF
imgPrompt=选择图像 imgPrompt=选择图像
genericSubmit=提交 genericSubmit=提交
processTimeWarning=警告:此过程可能需要多达一分钟,具体时间取决于文件大小 processTimeWarning=警告:此过程可能需要多达一分钟,具体时间取决于文件大小
pageOrderPrompt=页面顺序(输入逗号分隔的页码列表): pageOrderPrompt=页面顺序(输入逗号分隔的页码列表或函数
pageSelectionPrompt=自定义页面选择(输入以逗号分隔的页码列表 1,5,62n+1 等函数 pageSelectionPrompt=自定义页面选择(输入以逗号分隔的页码列表或函数:1,5,62n+1
goToPage= goToPage=
true= true=
false= false=
@@ -33,7 +33,7 @@ sizes.small=小型尺寸
sizes.medium=中型尺寸 sizes.medium=中型尺寸
sizes.large=大型尺寸 sizes.large=大型尺寸
sizes.x-large=超大型尺寸 sizes.x-large=超大型尺寸
error.pdfPassword=PDF 文档有密码,未提供密码或密码不正确 error.pdfPassword=PDF文档有密码未提供密码或密码不正确
delete=删除 delete=删除
username=用户名 username=用户名
password=密码 password=密码
@@ -55,13 +55,13 @@ userNotFoundMessage=未找到用户。
incorrectPasswordMessage=当前密码不正确。 incorrectPasswordMessage=当前密码不正确。
usernameExistsMessage=新用户名已存在。 usernameExistsMessage=新用户名已存在。
invalidUsernameMessage=用户名无效,用户名只能包含字母、数字和以下特殊字符@._+- 或必须是有效的电子邮件地址。 invalidUsernameMessage=用户名无效,用户名只能包含字母、数字和以下特殊字符@._+- 或必须是有效的电子邮件地址。
confirmPasswordErrorMessage=New Password and Confirm New Password must match. confirmPasswordErrorMessage=两次密码不一致。
deleteCurrentUserMessage=无法删除当前登录的用户。 deleteCurrentUserMessage=无法删除当前登录的用户。
deleteUsernameExistsMessage=用户名不存在,无法删除。 deleteUsernameExistsMessage=用户名不存在,无法删除。
downgradeCurrentUserMessage=无法降级当前用户的角色 downgradeCurrentUserMessage=无法降级当前用户的角色
downgradeCurrentUserLongMessage=无法降级当前用户的角色。因此,当前用户将不会显示。 downgradeCurrentUserLongMessage=无法降级当前用户的角色。因此,当前用户将不会显示。
userAlreadyExistsOAuthMessage=The user already exists as an OAuth2 user. userAlreadyExistsOAuthMessage=该用户已作为OAuth2用户存在。
userAlreadyExistsWebMessage=The user already exists as an web user. userAlreadyExistsWebMessage=该用户已作为Web用户存在。
error=错误 error=错误
oops=哎呀! oops=哎呀!
help=帮助 help=帮助
@@ -72,21 +72,21 @@ visitGithub=访问Github仓库
donate=捐款 donate=捐款
color=颜色 color=颜色
sponsor=赞助 sponsor=赞助
info=Info info=信息
############### ###############
# Pipeline # # Pipeline #
############### ###############
pipeline.header=流水线菜单 (Beta) pipeline.header=流水线菜单Beta
pipeline.uploadButton=上传自定义流水线 pipeline.uploadButton=上传自定义流水线
pipeline.configureButton=配置 pipeline.configureButton=配置
pipeline.defaultOption=自定义 pipeline.defaultOption=自定义
pipeline.submitButton=提交 pipeline.submitButton=提交
pipeline.help=工作流帮助 pipeline.help=工作流帮助
pipeline.scanHelp=文件夹扫描帮助 pipeline.scanHelp=文件夹扫描帮助
pipeline.deletePrompt=Are you sure you want to delete pipeline pipeline.deletePrompt=确认删除该工作流?
###################### ######################
# Pipeline Options # # Pipeline Options #
@@ -125,7 +125,7 @@ navbar.sections.edit=查看和编辑
############# #############
settings.title=设置 settings.title=设置
settings.update=可更新 settings.update=可更新
settings.updateAvailable={0} is the current installed version. A new version ({1}) is available. settings.updateAvailable=当前版本为 {0},新版本 ({1}) 可用。
settings.appVersion=应用程序版本: settings.appVersion=应用程序版本:
settings.downloadOption.title=选择下载选项(单个文件非压缩文件): settings.downloadOption.title=选择下载选项(单个文件非压缩文件):
settings.downloadOption.1=在同一窗口打开 settings.downloadOption.1=在同一窗口打开
@@ -133,10 +133,10 @@ settings.downloadOption.2=在新窗口中打开
settings.downloadOption.3=下载文件 settings.downloadOption.3=下载文件
settings.zipThreshold=当下载的文件数量超过限制时,将文件压缩。 settings.zipThreshold=当下载的文件数量超过限制时,将文件压缩。
settings.signOut=登出 settings.signOut=登出
settings.accountSettings=号设定 settings.accountSettings=号设定
settings.bored.help=Enables easter egg game settings.bored.help=启用彩蛋游戏
settings.cacheInputs.name=Save form inputs settings.cacheInputs.name=保存表单输入
settings.cacheInputs.help=Enable to store previously used inputs for future runs settings.cacheInputs.help=保存先前输入以供日后使用
changeCreds.title=更改凭证 changeCreds.title=更改凭证
changeCreds.header=更新您的账户详情 changeCreds.header=更新您的账户详情
@@ -149,8 +149,8 @@ changeCreds.submit=提交更改
account.title=号设定 account.title=号设定
account.accountSettings=号设定 account.accountSettings=号设定
account.adminSettings=管理员设置 - 查看和添加用户 account.adminSettings=管理员设置 - 查看和添加用户
account.userControlSettings=用户控制设置 account.userControlSettings=用户控制设置
account.changeUsername=更改用户名 account.changeUsername=更改用户名
@@ -161,11 +161,11 @@ account.newPassword=新密码
account.changePassword=更改密码 account.changePassword=更改密码
account.confirmNewPassword=确认新密码 account.confirmNewPassword=确认新密码
account.signOut=退出登录 account.signOut=退出登录
account.yourApiKey=您的 API 密钥 account.yourApiKey=您的API密钥
account.syncTitle=将浏览器设置与账户同步 account.syncTitle=将浏览器设置与账户同步
account.settingsCompare=设置比较: account.settingsCompare=设置比较:
account.property=属性 account.property=属性
account.webBrowserSettings=Web 浏览器设置 account.webBrowserSettings=Web浏览器设置
account.syncToBrowser=同步账户 -> 浏览器 account.syncToBrowser=同步账户 -> 浏览器
account.syncToAccount=同步账户 <- 浏览器 account.syncToAccount=同步账户 <- 浏览器
@@ -175,21 +175,38 @@ adminUserSettings.header=管理员用户控制设置
adminUserSettings.admin=管理员 adminUserSettings.admin=管理员
adminUserSettings.user=用户 adminUserSettings.user=用户
adminUserSettings.addUser=添加新用户 adminUserSettings.addUser=添加新用户
adminUserSettings.deleteUser=Delete User adminUserSettings.deleteUser=删除用户
adminUserSettings.confirmDeleteUser=Should the user be deleted? adminUserSettings.confirmDeleteUser=确认删除该用户?
adminUserSettings.usernameInfo=用户名只能包含字母、数字和以下特殊字符@._+-,或者必须是有效的电子邮件地址。 adminUserSettings.usernameInfo=用户名只能包含字母、数字和以下特殊字符@._+-,或者必须是有效的电子邮件地址。
adminUserSettings.roles=角色 adminUserSettings.roles=角色
adminUserSettings.role=角色 adminUserSettings.role=角色
adminUserSettings.actions=操作 adminUserSettings.actions=操作
adminUserSettings.apiUser=受限制的 API 用户 adminUserSettings.apiUser=受限制的API用户
adminUserSettings.extraApiUser=额外受限制的 API 用户 adminUserSettings.extraApiUser=额外受限制的API用户
adminUserSettings.webOnlyUser=仅限 Web 用户 adminUserSettings.webOnlyUser=仅限Web用户
adminUserSettings.demoUser=演示用户(无自定义设置) adminUserSettings.demoUser=演示用户(无自定义设置)
adminUserSettings.internalApiUser=内部API用户 adminUserSettings.internalApiUser=内部API用户
adminUserSettings.forceChange=强制用户在登录时更改用户名/密码 adminUserSettings.forceChange=强制用户在登录时更改用户名/密码
adminUserSettings.submit=保存用户 adminUserSettings.submit=保存用户
adminUserSettings.changeUserRole=更改用户角色 adminUserSettings.changeUserRole=更改用户角色
adminUserSettings.authenticated=Authenticated adminUserSettings.authenticated=已验证
database.title=Database Import/Export
database.header=Database Import/Export
database.fileName=File Name
database.creationDate=Creation Date
database.fileSize=File Size
database.deleteBackupFile=Delete Backup File
database.importBackupFile=Import Backup File
database.downloadBackupFile=Download Backup File
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
database.submit=Import Backup
database.importIntoDatabaseSuccessed=Import into database successed
database.fileNotFound=File not Found
database.fileNullOrEmpty=File must not be null or empty
database.failedImportFile=Failed Import File
############# #############
# HOME-PAGE # # HOME-PAGE #
@@ -332,13 +349,13 @@ home.compare.title=比较
home.compare.desc=比较并显示两个PDF文档之间的差异 home.compare.desc=比较并显示两个PDF文档之间的差异
compare.tags=区分、对比、更改、分析 compare.tags=区分、对比、更改、分析
home.certSign.title=使用证书签 home.certSign.title=使用证书签
home.certSign.desc=使用证书/密钥PEM/P12对PDF进行签 home.certSign.desc=使用证书/密钥PEM/P12对PDF进行签
certSign.tags=身份验证、PEM、P12、官方、加密 certSign.tags=身份验证、PEM、P12、官方、加密
home.removeCertSign.title=Remove Certificate Sign home.removeCertSign.title=移除证书签名
home.removeCertSign.desc=Remove certificate signature from PDF home.removeCertSign.desc=移除PDF的证书签名
removeCertSign.tags=authenticate,PEM,P12,official,decrypt removeCertSign.tags=身份验证、PEMP12、官方、加密
home.pageLayout.title=多页布局 home.pageLayout.title=多页布局
home.pageLayout.desc=将PDF文档的多个页面合并成一页 home.pageLayout.desc=将PDF文档的多个页面合并成一页
@@ -459,13 +476,13 @@ login.invalid=用户名或密码无效。
login.locked=您的账户已被锁定。 login.locked=您的账户已被锁定。
login.signinTitle=请登录 login.signinTitle=请登录
login.ssoSignIn=通过单点登录登录 login.ssoSignIn=通过单点登录登录
login.oauth2AutoCreateDisabled=OAUTH2自动创建用户已禁用 login.oauth2AutoCreateDisabled=OAuth2自动创建用户已禁用
login.oauth2RequestNotFound=Authorization request not found login.oauth2RequestNotFound=找不到验证请求
login.oauth2InvalidUserInfoResponse=Invalid User Info Response login.oauth2InvalidUserInfoResponse=无效的用户信息响应
login.oauth2invalidRequest=Invalid Request login.oauth2invalidRequest=无效请求
login.oauth2AccessDenied=Access Denied login.oauth2AccessDenied=拒绝访问
login.oauth2InvalidTokenResponse=Invalid Token Response login.oauth2InvalidTokenResponse=无效的Token响应
login.oauth2InvalidIdToken=Invalid Id Token login.oauth2InvalidIdToken=无效的Token
#auto-redact #auto-redact
@@ -482,15 +499,15 @@ autoRedact.submitButton=提交
#showJS #showJS
showJS.title=显示 JavaScript showJS.title=显示JavaScript
showJS.header=显示 JavaScript showJS.header=显示JavaScript
showJS.downloadJS=下载 JavaScript showJS.downloadJS=下载JavaScript
showJS.submit=显示 showJS.submit=显示
#pdfToSinglePage #pdfToSinglePage
pdfToSinglePage.title=PDF转单页 pdfToSinglePage.title=PDF转单页
pdfToSinglePage.header=PDF转为单页 pdfToSinglePage.header=PDF转为单页
pdfToSinglePage.submit=转为单页 pdfToSinglePage.submit=转为单页
@@ -498,7 +515,7 @@ pdfToSinglePage.submit=转为单页
pageExtracter.title=提取页面 pageExtracter.title=提取页面
pageExtracter.header=提取页面 pageExtracter.header=提取页面
pageExtracter.submit=提取 pageExtracter.submit=提取
pageExtracter.placeholder=(例如 1,2,8 或 4,7,12-16 或 2n-1 pageExtracter.placeholder=(例如1,2,8 或 4,7,12-16 或 2n-1
#getPdfInfo #getPdfInfo
@@ -510,7 +527,7 @@ getPdfInfo.downloadJson=下载JSON
#markdown-to-pdf #markdown-to-pdf
MarkdownToPDF.title=Markdown转PDF MarkdownToPDF.title=Markdown转PDF
MarkdownToPDF.header=Markdown转PDF MarkdownToPDF.header=Markdown转换为PDF
MarkdownToPDF.submit=转换 MarkdownToPDF.submit=转换
MarkdownToPDF.help=正在努力中 MarkdownToPDF.help=正在努力中
MarkdownToPDF.credit=此服务使用WeasyPrint进行文件转换。 MarkdownToPDF.credit=此服务使用WeasyPrint进行文件转换。
@@ -519,14 +536,14 @@ MarkdownToPDF.credit=此服务使用WeasyPrint进行文件转换。
#url-to-pdf #url-to-pdf
URLToPDF.title=URL转PDF URLToPDF.title=URL转PDF
URLToPDF.header=URL转PDF URLToPDF.header=URL转换为PDF
URLToPDF.submit=转换 URLToPDF.submit=转换
URLToPDF.credit=此服务使用WeasyPrint进行文件转换。 URLToPDF.credit=此服务使用WeasyPrint进行文件转换。
#html-to-pdf #html-to-pdf
HTMLToPDF.title=HTML转PDF HTMLToPDF.title=HTML转PDF
HTMLToPDF.header=HTML转PDF HTMLToPDF.header=HTML转换为PDF
HTMLToPDF.help=接受HTML文件和包含所需的html/css/images等的ZIP文件 HTMLToPDF.help=接受HTML文件和包含所需的html/css/images等的ZIP文件
HTMLToPDF.submit=转换 HTMLToPDF.submit=转换
HTMLToPDF.credit=此服务使用WeasyPrint进行文件转换。 HTMLToPDF.credit=此服务使用WeasyPrint进行文件转换。
@@ -539,7 +556,7 @@ HTMLToPDF.marginLeft=页面左上边距-以毫米为单位(填空则使用默
HTMLToPDF.marginRight=页面右边距-以毫米为单位(填空则使用默认值) HTMLToPDF.marginRight=页面右边距-以毫米为单位(填空则使用默认值)
HTMLToPDF.printBackground=页面背景渲染 HTMLToPDF.printBackground=页面背景渲染
HTMLToPDF.defaultHeader=启用默认页头(文件名称和页码) HTMLToPDF.defaultHeader=启用默认页头(文件名称和页码)
HTMLToPDF.cssMediaType=更换页面的CSS media type. HTMLToPDF.cssMediaType=更换页面的CSS媒体类型。
HTMLToPDF.none= HTMLToPDF.none=
HTMLToPDF.print=打印 HTMLToPDF.print=打印
HTMLToPDF.screen=屏幕 HTMLToPDF.screen=屏幕
@@ -556,8 +573,8 @@ AddStampRequest.fontSize=字体/图片大小
AddStampRequest.rotation=旋转角度 AddStampRequest.rotation=旋转角度
AddStampRequest.opacity=透明度 AddStampRequest.opacity=透明度
AddStampRequest.position=定位 AddStampRequest.position=定位
AddStampRequest.overrideX=覆盖 X 坐标 AddStampRequest.overrideX=覆盖X坐标
AddStampRequest.overrideY=覆盖 Y 坐标 AddStampRequest.overrideY=覆盖Y坐标
AddStampRequest.customMargin=自定义外边距 AddStampRequest.customMargin=自定义外边距
AddStampRequest.customColor=自定义文本颜色 AddStampRequest.customColor=自定义文本颜色
AddStampRequest.submit=提交 AddStampRequest.submit=提交
@@ -647,27 +664,27 @@ scalePages.submit=提交
#certSign #certSign
certSign.title=证书签名 certSign.title=证书签名
certSign.header=使用您的证书签PDF进行中 certSign.header=使用您的证书签PDF进行中
certSign.selectPDF=选择要签名的 PDF 文件: certSign.selectPDF=选择要签名的PDF文件
certSign.jksNote=注意:如果您的证书类型未在下面列出,请使用 keytool 命令行工具将其转换为 Java Keystore (.jks) 文件。 然后,选择下面的 .jks 文件选项。 certSign.jksNote=注意如果您的证书类型未在下面列出请使用keytool命令行工具将其转换为Java Keystore.jks文件。 然后,选择下面的.jks文件选项。
certSign.selectKey=选择您的私钥文件PKCS#8 格式,可以是 .pem.der certSign.selectKey=选择您的私钥文件PKCS#8格式可以是.pem.der
certSign.selectCert=选择您的证书文件X.509 格式,可以是 .pem.der certSign.selectCert=选择您的证书文件X.509格式,可以是.pem.der
certSign.selectP12=选择您的 PKCS#12 密钥库文件(.p12.pfx可选如果提供它应该包含您的私钥和证书 certSign.selectP12=选择您的PKCS#12密钥库文件.p12.pfx可选如果提供它应该包含您的私钥和证书
certSign.selectJKS=选择你的 Java Keystore 文件 (.jks.keystore): certSign.selectJKS=选择你的Java Keystore文件 (.jks.keystore):
certSign.certType=证书类型 certSign.certType=证书类型
certSign.password=输入您的密钥库或私钥密码(如果有): certSign.password=输入您的密钥库或私钥密码(如果有):
certSign.showSig=显示签名 certSign.showSig=显示签名
certSign.reason=原因 certSign.reason=原因
certSign.location=位置 certSign.location=位置
certSign.name=名称 certSign.name=名称
certSign.submit=签署 PDF certSign.submit=PDF签名
#removeCertSign #removeCertSign
removeCertSign.title=Remove Certificate Signature removeCertSign.title=移除证书签名
removeCertSign.header=Remove the digital certificate from the PDF removeCertSign.header=移除PDF的证书签名
removeCertSign.selectPDF=Select a PDF file: removeCertSign.selectPDF=选择PDF文件
removeCertSign.submit=Remove Signature removeCertSign.submit=移除签名
#removeBlanks #removeBlanks
@@ -688,7 +705,9 @@ removeAnnotations.submit=删除
#compare #compare
compare.title=比较 compare.title=比较
compare.header=比较 PDF compare.header=比较PDF
compare.highlightColor.1=Highlight Color 1:
compare.highlightColor.2=Highlight Color 2:
compare.document.1=文档 1 compare.document.1=文档 1
compare.document.2=文档 2 compare.document.2=文档 2
compare.submit=比较 compare.submit=比较
@@ -718,14 +737,14 @@ sign.add=添加
#repair #repair
repair.title=修复 repair.title=修复
repair.header=修复 PDF repair.header=修复PDF
repair.submit=修复 repair.submit=修复
#flatten #flatten
flatten.title=展平 flatten.title=展平
flatten.header=展平 PDF flatten.header=展平 PDF
flatten.flattenOnlyForms=Flatten only forms flatten.flattenOnlyForms=仅展平表格
flatten.submit=展平 flatten.submit=展平
@@ -752,7 +771,7 @@ ocr.selectText.4=清理页面降低OCR在噪点中识别到文本的可能。
ocr.selectText.5=清洁页面降低OCR在噪点中识别到文本的可能保持输出的清洁。 ocr.selectText.5=清洁页面降低OCR在噪点中识别到文本的可能保持输出的清洁。
ocr.selectText.6=忽略有交互式文本的页面只对有图像的页面进行OCR。 ocr.selectText.6=忽略有交互式文本的页面只对有图像的页面进行OCR。
ocr.selectText.7=强制OCR将OCR每个页面删除所有的原始文本元素。 ocr.selectText.7=强制OCR将OCR每个页面删除所有的原始文本元素。
ocr.selectText.8=Normal (如果PDF包含文本将出现错误) ocr.selectText.8=正常 (如果PDF包含文本将出现错误)
ocr.selectText.9=额外设置 ocr.selectText.9=额外设置
ocr.selectText.10=OCR模式 ocr.selectText.10=OCR模式
ocr.selectText.11=OCR后移除图像移除所有图像只有在转换步骤中才有用 ocr.selectText.11=OCR后移除图像移除所有图像只有在转换步骤中才有用
@@ -773,7 +792,7 @@ extractImages.submit=提取
fileToPDF.title=文件转换为PDF fileToPDF.title=文件转换为PDF
fileToPDF.header=将任何文件转换为PDF。 fileToPDF.header=将任何文件转换为PDF。
fileToPDF.credit=此服务使用LibreOffice和Unoconv进行文件转换。 fileToPDF.credit=此服务使用LibreOffice和Unoconv进行文件转换。
fileToPDF.supportedFileTypesInfo=Supported File types fileToPDF.supportedFileTypesInfo=支持的文件类型
fileToPDF.supportedFileTypes=支持的文件类型应该包括以下几种但是对于支持的格式的完整更新列表请参考LibreOffice文档。 fileToPDF.supportedFileTypes=支持的文件类型应该包括以下几种但是对于支持的格式的完整更新列表请参考LibreOffice文档。
fileToPDF.submit=转换为 PDF fileToPDF.submit=转换为 PDF
@@ -781,12 +800,12 @@ fileToPDF.submit=转换为 PDF
#compress #compress
compress.title=压缩 compress.title=压缩
compress.header=压缩PDF compress.header=压缩PDF
compress.credit=此服务使用 Ghostscript 进行 PDF 压缩/优化。 compress.credit=此服务使用Ghostscript进行PDF压缩/优化。
compress.selectText.1=手动模式 - 从 1 到 4 compress.selectText.1=手动模式 - 从 1 到 4
compress.selectText.2=优化级别: compress.selectText.2=优化级别:
compress.selectText.3=4文本图像很糟糕 compress.selectText.3=4文本图像很糟糕
compress.selectText.4=自动模式 - 自动调整质量以获得精确大小的 PDF compress.selectText.4=自动模式 - 自动调整质量以获得精确大小的PDF
compress.selectText.5=预期 PDF 大小(例如 25MB、10.8MB、25KB compress.selectText.5=预期PDF大小例如25MB、10.8MB、25KB
compress.submit=压缩 compress.submit=压缩
@@ -803,7 +822,7 @@ merge.title=合并
merge.header=合并多个PDF2个以上 merge.header=合并多个PDF2个以上
merge.sortByName=按名称排序 merge.sortByName=按名称排序
merge.sortByDate=按日期排序 merge.sortByDate=按日期排序
merge.removeCertSign=Remove digital signature in the merged file? merge.removeCertSign=删除合并文件的数字签名吗?
merge.submit=合并 merge.submit=合并
@@ -821,7 +840,8 @@ pdfOrganiser.mode.6=奇偶拆分
pdfOrganiser.mode.7=删除第一页 pdfOrganiser.mode.7=删除第一页
pdfOrganiser.mode.8=删除最后一页 pdfOrganiser.mode.8=删除最后一页
pdfOrganiser.mode.9=删除第一页和最后一页 pdfOrganiser.mode.9=删除第一页和最后一页
pdfOrganiser.placeholder=(例如 1,3,2 或 4-8,2,10-12 或 2n-1 pdfOrganiser.mode.10=奇偶合并
pdfOrganiser.placeholder=例如1,3,2 或 4-8,2,10-12 或 2n-1
#multiTool #multiTool
@@ -838,7 +858,7 @@ pageRemover.title=删除页面
pageRemover.header=PDF页面移除器 pageRemover.header=PDF页面移除器
pageRemover.pagesToDelete=要删除的页面(输入一个用逗号分隔的页码列表): pageRemover.pagesToDelete=要删除的页面(输入一个用逗号分隔的页码列表):
pageRemover.submit=删除页面 pageRemover.submit=删除页面
pageRemover.placeholder=(例如 1,2,6 或 1-10,15-30 pageRemover.placeholder=(例如1,2,6 或 1-10,15-30
#rotate #rotate
@@ -865,7 +885,7 @@ split.submit=拆分
#merge #merge
imageToPDF.title=图片转PDF imageToPDF.title=图片转PDF
imageToPDF.header=图像转为PDF imageToPDF.header=将图片转换为PDF
imageToPDF.submit=转换 imageToPDF.submit=转换
imageToPDF.selectLabel=图片适应选项 imageToPDF.selectLabel=图片适应选项
imageToPDF.fillPage=填充页面 imageToPDF.fillPage=填充页面
@@ -879,7 +899,7 @@ imageToPDF.selectText.5=转换为独立的PDF文件
#pdfToImage #pdfToImage
pdfToImage.title=PDF转图片 pdfToImage.title=PDF转图片
pdfToImage.header=PDF转图片 pdfToImage.header=PDF转换为图片
pdfToImage.selectText=图像格式 pdfToImage.selectText=图像格式
pdfToImage.singleOrMultiple=图像结果类型 pdfToImage.singleOrMultiple=图像结果类型
pdfToImage.single=单张图片 pdfToImage.single=单张图片
@@ -975,55 +995,55 @@ changeMetadata.submit=更改
#pdfToPDFA #pdfToPDFA
pdfToPDFA.title=PDF转换为PDF/A pdfToPDFA.title=PDF转PDF/A
pdfToPDFA.header=PDF转换为PDF/A pdfToPDFA.header=PDF转换为PDF/A
pdfToPDFA.credit=此服务使用OCRmyPDF进行PDF/A转换 pdfToPDFA.credit=此服务使用OCRmyPDF进行PDF/A转换
pdfToPDFA.submit=转换 pdfToPDFA.submit=转换
pdfToPDFA.tip=目前不支持上传多个 pdfToPDFA.tip=目前不支持上传多个
pdfToPDFA.outputFormat=Output format pdfToPDFA.outputFormat=输出格式
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step. pdfToPDFA.pdfWithDigitalSignature=该PDF包含数字签名下一步将移除该签名。
#PDFToWord #PDFToWord
PDFToWord.title=PDF to Word PDFToWord.title=PDFWord
PDFToWord.header=将PDF转换Word PDFToWord.header=将PDF转换Word
PDFToWord.selectText.1=输出文件格式 PDFToWord.selectText.1=输出文件格式
PDFToWord.credit=此服务使用LibreOffice进行文件转换。 PDFToWord.credit=此服务使用LibreOffice进行文件转换。
PDFToWord.submit=转换 PDFToWord.submit=转换
#PDFToPresentation #PDFToPresentation
PDFToPresentation.title=PDF转换为演示文稿 PDFToPresentation.title=PDF转演示文稿
PDFToPresentation.header=将PDF转为演示文稿 PDFToPresentation.header=将PDF转为演示文稿
PDFToPresentation.selectText.1=输出文件格式 PDFToPresentation.selectText.1=输出文件格式
PDFToPresentation.credit=此服务使用LibreOffice进行文件转换。 PDFToPresentation.credit=此服务使用LibreOffice进行文件转换。
PDFToPresentation.submit=转换 PDFToPresentation.submit=转换
#PDFToText #PDFToText
PDFToText.title=PDF to RTF (Text) PDFToText.title=PDF转文本/RTF
PDFToText.header=将PDF转换文本/RTF PDFToText.header=将PDF转换文本/RTF
PDFToText.selectText.1=输出文件格式 PDFToText.selectText.1=输出文件格式
PDFToText.credit=此服务使用LibreOffice进行文件转换。 PDFToText.credit=此服务使用LibreOffice进行文件转换。
PDFToText.submit=转换 PDFToText.submit=转换
#PDFToHTML #PDFToHTML
PDFToHTML.title=PDF To HTML PDFToHTML.title=PDFHTML
PDFToHTML.header=将PDF转换HTML PDFToHTML.header=将PDF转换HTML
PDFToHTML.credit=此服务使用pdftohtml进行文件转换。 PDFToHTML.credit=此服务使用pdftohtml进行文件转换。
PDFToHTML.submit=转换 PDFToHTML.submit=转换
#PDFToXML #PDFToXML
PDFToXML.title=PDF To XML PDFToXML.title=PDFXML
PDFToXML.header=将PDF转换为XML PDFToXML.header=将PDF转换为XML
PDFToXML.credit=此服务使用LibreOffice进行文件转换。 PDFToXML.credit=此服务使用LibreOffice进行文件转换。
PDFToXML.submit=转换 PDFToXML.submit=转换
#PDFToCSV #PDFToCSV
PDFToCSV.title=PDF To CSV PDFToCSV.title=PDFCSV
PDFToCSV.header= PDF 转换为 CSV PDFToCSV.header=将PDF转换为CSV
PDFToCSV.prompt=选择需要提取表格的页面 PDFToCSV.prompt=选择需要提取表格的页面
PDFToCSV.submit=提取 PDFToCSV.submit=提取
@@ -1035,7 +1055,7 @@ split-by-size-or-count.type.size=按照大小
split-by-size-or-count.type.pageCount=按照页数 split-by-size-or-count.type.pageCount=按照页数
split-by-size-or-count.type.docCount=按照文档数 split-by-size-or-count.type.docCount=按照文档数
split-by-size-or-count.value.label=输入数值 split-by-size-or-count.value.label=输入数值
split-by-size-or-count.value.placeholder=输入大小(例如2MB或3KB或数目例如5 split-by-size-or-count.value.placeholder=输入大小(例如2MB或3KB或数目例如5
split-by-size-or-count.submit=提交 split-by-size-or-count.submit=提交
@@ -1048,7 +1068,7 @@ overlay-pdfs.mode.sequential=按顺序叠加
overlay-pdfs.mode.interleaved=交错叠加 overlay-pdfs.mode.interleaved=交错叠加
overlay-pdfs.mode.fixedRepeat=固定重复叠加 overlay-pdfs.mode.fixedRepeat=固定重复叠加
overlay-pdfs.counts.label=叠加次数(仅限固定重复叠加模式) overlay-pdfs.counts.label=叠加次数(仅限固定重复叠加模式)
overlay-pdfs.counts.placeholder=输入用逗号分隔的次数(例如2,3,1 overlay-pdfs.counts.placeholder=输入用逗号分隔的次数(例如2,3,1
overlay-pdfs.position.label=选择叠加位置 overlay-pdfs.position.label=选择叠加位置
overlay-pdfs.position.foreground=前面(上面) overlay-pdfs.position.foreground=前面(上面)
overlay-pdfs.position.background=后面(下面) overlay-pdfs.position.background=后面(下面)
@@ -1067,11 +1087,11 @@ split-by-sections.merge=是否合并为一个pdf
#printFile #printFile
printFile.title=Print File printFile.title=打印文件
printFile.header=Print File to Printer printFile.header=使用打印机打印文件
printFile.selectText.1=Select File to Print printFile.selectText.1=选择要打印的文件
printFile.selectText.2=Enter Printer Name printFile.selectText.2=输入打印机名称
printFile.submit=Print printFile.submit=打印
#licenses #licenses
@@ -1083,13 +1103,13 @@ licenses.version=版本
licenses.license=许可证 licenses.license=许可证
#survey #survey
survey.nav=Survey survey.nav=调查
survey.title=Stirling-PDF Survey survey.title=Stirling-PDF调查
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF! survey.description=Stirling-PDF没有跟踪器,所以我们希望听取用户的意见来改进Stirling-PDF
survey.please=Please consider taking our survey! survey.please=请考虑参加我们的调查!
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page) survey.disabled=(调查弹出窗口将在后续更新中被禁用,但可在页脚处查看)
survey.button=Take Survey survey.button=参与调查
survey.dontShowAgain=Don't show again survey.dontShowAgain=不再显示
#error #error

View File

@@ -191,6 +191,23 @@ adminUserSettings.submit=儲存
adminUserSettings.changeUserRole=更改使用者身份 adminUserSettings.changeUserRole=更改使用者身份
adminUserSettings.authenticated=已驗證 adminUserSettings.authenticated=已驗證
database.title=Database Import/Export
database.header=Database Import/Export
database.fileName=File Name
database.creationDate=Creation Date
database.fileSize=File Size
database.deleteBackupFile=Delete Backup File
database.importBackupFile=Import Backup File
database.downloadBackupFile=Download Backup File
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
database.submit=Import Backup
database.importIntoDatabaseSuccessed=Import into database successed
database.fileNotFound=File not Found
database.fileNullOrEmpty=File must not be null or empty
database.failedImportFile=Failed Import File
############# #############
# HOME-PAGE # # HOME-PAGE #
############# #############
@@ -689,6 +706,8 @@ removeAnnotations.submit=移除
#compare #compare
compare.title=比較 compare.title=比較
compare.header=比較 PDF compare.header=比較 PDF
compare.highlightColor.1=Highlight Color 1:
compare.highlightColor.2=Highlight Color 2:
compare.document.1=文件 1 compare.document.1=文件 1
compare.document.2=文件 2 compare.document.2=文件 2
compare.submit=比較 compare.submit=比較
@@ -821,6 +840,7 @@ pdfOrganiser.mode.6=奇偶拆分
pdfOrganiser.mode.7=刪除第一頁 pdfOrganiser.mode.7=刪除第一頁
pdfOrganiser.mode.8=刪除最後一頁 pdfOrganiser.mode.8=刪除最後一頁
pdfOrganiser.mode.9=刪除第一頁和最後一頁 pdfOrganiser.mode.9=刪除第一頁和最後一頁
pdfOrganiser.mode.10=Odd-Even Merge
pdfOrganiser.placeholder=(例如 1,3,2 或 4-8,2,10-12 或 2n-1 pdfOrganiser.placeholder=(例如 1,3,2 或 4-8,2,10-12 或 2n-1

View File

@@ -1,44 +1,54 @@
# Welcome to settings file #############################################################################################################
# Remove comment marker # if on start of line to enable the configuration # Welcome to settings file from #
# If you want to override with environment parameter follow parameter naming SECURITY_INITIALLOGIN_USERNAME # ____ _____ ___ ____ _ ___ _ _ ____ ____ ____ _____ #
# / ___|_ _|_ _| _ \| | |_ _| \ | |/ ___| | _ \| _ \| ___| #
# \___ \ | | | || |_) | | | || \| | | _ _____| |_) | | | | |_ #
# ___) || | | || _ <| |___ | || |\ | |_| |_____| __/| |_| | _| #
# |____/ |_| |___|_| \_\_____|___|_| \_|\____| |_| |____/|_| #
# #
# Do not comment out any entry, it will be removed on next startup #
# If you want to override with environment parameter follow parameter naming SECURITY_INITIALLOGIN_USERNAME #
#############################################################################################################
security: security:
enableLogin: false # set to 'true' to enable login enableLogin: false # set to 'true' to enable login
csrfDisabled: true # Set to 'true' to disable CSRF protection (not recommended for production) csrfDisabled: true # Set to 'true' to disable CSRF protection (not recommended for production)
loginAttemptCount: 5 # lock user account after 5 tries loginAttemptCount: 5 # lock user account after 5 tries
loginResetTimeMinutes: 120 # lock account for 2 hours after x attempts loginResetTimeMinutes: 120 # lock account for 2 hours after x attempts
# initialLogin: loginMethod: all # 'all' (Login Username/Password and OAuth2[must be enabled and configured]), 'normal'(only Login with Username/Password) or 'oauth2'(only Login with OAuth2)
# username: "admin" # Initial username for the first login initialLogin:
# password: "stirling" # Initial password for the first login username: '' # Initial username for the first login
# oauth2: password: '' # Initial password for the first login
# enabled: false # set to 'true' to enable login (Note: enableLogin must also be 'true' for this to work) oauth2:
# issuer: "" # set to any provider that supports OpenID Connect Discovery (/.well-known/openid-configuration) end-point enabled: false # set to 'true' to enable login (Note: enableLogin must also be 'true' for this to work)
# clientId: "" # Client ID from your provider client:
# clientSecret: "" # Client Secret from your provider keycloak:
# autoCreateUser: false # set to 'true' to allow auto-creation of non-existing users issuer: '' # URL of the Keycloak realm's OpenID Connect Discovery endpoint
# useAsUsername: "email" # Default is 'email'; custom fields can be used as the username clientId: '' # Client ID for Keycloak OAuth2
# scopes: "openid, profile, email" # Specify the scopes for which the application will request permissions clientSecret: '' # Client Secret for Keycloak OAuth2
# provider: "google" # Set this to your OAuth provider's name, e.g., 'google' or 'keycloak' scopes: openid, profile, email # Scopes for Keycloak OAuth2
# client: useAsUsername: preferred_username # Field to use as the username for Keycloak OAuth2
# google: google:
# clientId: "" # Client ID for Google OAuth2 clientId: '' # Client ID for Google OAuth2
# clientSecret: "" # Client Secret for Google OAuth2 clientSecret: '' # Client Secret for Google OAuth2
# scopes: "https://www.googleapis.com/auth/userinfo.email, https://www.googleapis.com/auth/userinfo.profile" # Scopes for Google OAuth2 scopes: https://www.googleapis.com/auth/userinfo.email, https://www.googleapis.com/auth/userinfo.profile # Scopes for Google OAuth2
# useAsUsername: "email" # Field to use as the username for Google OAuth2 useAsUsername: email # Field to use as the username for Google OAuth2
# github: github:
# clientId: "" # Client ID for GitHub OAuth2 clientId: '' # Client ID for GitHub OAuth2
# clientSecret: "" # Client Secret for GitHub OAuth2 clientSecret: '' # Client Secret for GitHub OAuth2
# scopes: "read:user" # Scope for GitHub OAuth2 scopes: read:user # Scope for GitHub OAuth2
# useAsUsername: "login" # Field to use as the username for GitHub OAuth2 useAsUsername: login # Field to use as the username for GitHub OAuth2
# keycloak: issuer: '' # set to any provider that supports OpenID Connect Discovery (/.well-known/openid-configuration) end-point
# issuer: "http://192.168.0.123:8888/realms/stirling-pdf" # URL of the Keycloak realm's OpenID Connect Discovery endpoint clientId: '' # Client ID from your provider
# clientId: "stirling-pdf" # Client ID for Keycloak OAuth2 clientSecret: '' # Client Secret from your provider
# clientSecret: "" # Client Secret for Keycloak OAuth2 autoCreateUser: false # set to 'true' to allow auto-creation of non-existing users
# scopes: "openid, profile, email" # Scopes for Keycloak OAuth2 useAsUsername: email # Default is 'email'; custom fields can be used as the username
# useAsUsername: "email" # Field to use as the username for Keycloak OAuth2 scopes: openid, profile, email # Specify the scopes for which the application will request permissions
provider: google # Set this to your OAuth provider's name, e.g., 'google' or 'keycloak'
system: system:
defaultLocale: 'en-US' # Set the default language (e.g. 'de-DE', 'fr-FR', etc) defaultLocale: en-US # Set the default language (e.g. 'de-DE', 'fr-FR', etc)
googlevisibility: false # 'true' to allow Google visibility (via robots.txt), 'false' to disallow googlevisibility: false # 'true' to allow Google visibility (via robots.txt), 'false' to disallow
enableAlphaFunctionality: false # Set to enable functionality which might need more testing before it fully goes live (This feature might make no changes) enableAlphaFunctionality: false # Set to enable functionality which might need more testing before it fully goes live (This feature might make no changes)
showUpdate: false # see when a new update is available showUpdate: false # see when a new update is available
@@ -46,9 +56,9 @@ system:
customHTMLFiles: false # enable to have files placed in /customFiles/templates override the existing template html files customHTMLFiles: false # enable to have files placed in /customFiles/templates override the existing template html files
ui: ui:
appName: null # Application's visible name appName: '' # Application's visible name
homeDescription: null # Short description or tagline shown on homepage. homeDescription: '' # Short description or tagline shown on homepage.
appNameNavbar: null # Name displayed on the navigation bar appNameNavbar: '' # Name displayed on the navigation bar
endpoints: endpoints:
toRemove: [] # List endpoints to disable (e.g. ['img-to-pdf', 'remove-pages']) toRemove: [] # List endpoints to disable (e.g. ['img-to-pdf', 'remove-pages'])

View File

@@ -3,83 +3,106 @@
{ {
"moduleName": "ch.qos.logback:logback-classic", "moduleName": "ch.qos.logback:logback-classic",
"moduleUrl": "http://www.qos.ch", "moduleUrl": "http://www.qos.ch",
"moduleVersion": "1.5.3", "moduleVersion": "1.5.6",
"moduleLicense": "GNU Lesser General Public License", "moduleLicense": "GNU Lesser General Public License",
"moduleLicenseUrl": "http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html" "moduleLicenseUrl": "http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html"
}, },
{ {
"moduleName": "ch.qos.logback:logback-core", "moduleName": "ch.qos.logback:logback-core",
"moduleUrl": "http://www.qos.ch", "moduleUrl": "http://www.qos.ch",
"moduleVersion": "1.5.3", "moduleVersion": "1.5.6",
"moduleLicense": "GNU Lesser General Public License", "moduleLicense": "GNU Lesser General Public License",
"moduleLicenseUrl": "http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html" "moduleLicenseUrl": "http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html"
}, },
{
"moduleName": "com.bucket4j:bucket4j_jdk17-core",
"moduleUrl": "http://github.com/bucket4j/bucket4j/bucket4j_jdk17-core",
"moduleVersion": "8.12.1",
"moduleLicense": "The Apache Software License, Version 2.0",
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0"
},
{ {
"moduleName": "com.fasterxml.jackson.core:jackson-annotations", "moduleName": "com.fasterxml.jackson.core:jackson-annotations",
"moduleUrl": "https://github.com/FasterXML/jackson", "moduleUrl": "https://github.com/FasterXML/jackson",
"moduleVersion": "2.15.4", "moduleVersion": "2.17.1",
"moduleLicense": "The Apache Software License, Version 2.0", "moduleLicense": "The Apache Software License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
}, },
{ {
"moduleName": "com.fasterxml.jackson.core:jackson-core", "moduleName": "com.fasterxml.jackson.core:jackson-core",
"moduleUrl": "https://github.com/FasterXML/jackson-core", "moduleUrl": "https://github.com/FasterXML/jackson-core",
"moduleVersion": "2.15.4", "moduleVersion": "2.17.1",
"moduleLicense": "The Apache Software License, Version 2.0", "moduleLicense": "The Apache Software License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
}, },
{ {
"moduleName": "com.fasterxml.jackson.core:jackson-databind", "moduleName": "com.fasterxml.jackson.core:jackson-databind",
"moduleUrl": "https://github.com/FasterXML/jackson", "moduleUrl": "https://github.com/FasterXML/jackson",
"moduleVersion": "2.15.4", "moduleVersion": "2.17.1",
"moduleLicense": "The Apache Software License, Version 2.0", "moduleLicense": "The Apache Software License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
}, },
{ {
"moduleName": "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml", "moduleName": "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml",
"moduleUrl": "https://github.com/FasterXML/jackson-dataformats-text", "moduleUrl": "https://github.com/FasterXML/jackson-dataformats-text",
"moduleVersion": "2.15.4", "moduleVersion": "2.17.1",
"moduleLicense": "The Apache Software License, Version 2.0", "moduleLicense": "The Apache Software License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
}, },
{ {
"moduleName": "com.fasterxml.jackson.datatype:jackson-datatype-jdk8", "moduleName": "com.fasterxml.jackson.datatype:jackson-datatype-jdk8",
"moduleUrl": "https://github.com/FasterXML/jackson-modules-java8/jackson-datatype-jdk8", "moduleUrl": "https://github.com/FasterXML/jackson-modules-java8/jackson-datatype-jdk8",
"moduleVersion": "2.15.4", "moduleVersion": "2.17.1",
"moduleLicense": "The Apache Software License, Version 2.0", "moduleLicense": "The Apache Software License, Version 2.0",
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt" "moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
}, },
{ {
"moduleName": "com.fasterxml.jackson.datatype:jackson-datatype-jsr310", "moduleName": "com.fasterxml.jackson.datatype:jackson-datatype-jsr310",
"moduleUrl": "https://github.com/FasterXML/jackson-modules-java8/jackson-datatype-jsr310", "moduleUrl": "https://github.com/FasterXML/jackson-modules-java8/jackson-datatype-jsr310",
"moduleVersion": "2.15.4", "moduleVersion": "2.17.1",
"moduleLicense": "The Apache Software License, Version 2.0", "moduleLicense": "The Apache Software License, Version 2.0",
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt" "moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
}, },
{ {
"moduleName": "com.fasterxml.jackson.module:jackson-module-parameter-names", "moduleName": "com.fasterxml.jackson.module:jackson-module-parameter-names",
"moduleUrl": "https://github.com/FasterXML/jackson-modules-java8/jackson-module-parameter-names", "moduleUrl": "https://github.com/FasterXML/jackson-modules-java8/jackson-module-parameter-names",
"moduleVersion": "2.15.4", "moduleVersion": "2.17.1",
"moduleLicense": "The Apache Software License, Version 2.0", "moduleLicense": "The Apache Software License, Version 2.0",
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt" "moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
}, },
{ {
"moduleName": "com.fasterxml.jackson:jackson-bom", "moduleName": "com.fasterxml.jackson:jackson-bom",
"moduleVersion": "2.15.4" "moduleUrl": "https://github.com/FasterXML/jackson-bom",
"moduleVersion": "2.17.1",
"moduleLicense": "The Apache Software License, Version 2.0",
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
}, },
{ {
"moduleName": "com.fasterxml:classmate", "moduleName": "com.fasterxml:classmate",
"moduleUrl": "https://github.com/FasterXML/java-classmate", "moduleUrl": "https://github.com/FasterXML/java-classmate",
"moduleVersion": "1.6.0", "moduleVersion": "1.7.0",
"moduleLicense": "The Apache Software License, Version 2.0", "moduleLicense": "The Apache Software License, Version 2.0",
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt" "moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
}, },
{ {
"moduleName": "com.fathzer:javaluator", "moduleName": "com.fathzer:javaluator",
"moduleUrl": "http://javaluator.fathzer.com", "moduleVersion": "3.0.4",
"moduleVersion": "3.0.3", "moduleLicense": "Apache License, Version 2.0",
"moduleLicense": "GNU Lesser General Public License v3 (LGPL-v3)", "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
"moduleLicenseUrl": "http://www.gnu.org/licenses/lgpl-3.0.html" },
{
"moduleName": "com.github.Carleslc.Simple-YAML:Simple-Configuration",
"moduleUrl": "https://carleslc.me/Simple-YAML",
"moduleVersion": "1.8.4",
"moduleLicense": "GNU General Public License v3.0",
"moduleLicenseUrl": "https://api.github.com/licenses/gpl-3.0"
},
{
"moduleName": "com.github.Carleslc.Simple-YAML:Simple-Yaml",
"moduleUrl": "https://carleslc.me/Simple-YAML",
"moduleVersion": "1.8.4",
"moduleLicense": "GNU General Public License v3.0",
"moduleLicenseUrl": "https://api.github.com/licenses/gpl-3.0"
}, },
{ {
"moduleName": "com.github.stephenc.jcip:jcip-annotations", "moduleName": "com.github.stephenc.jcip:jcip-annotations",
@@ -88,13 +111,6 @@
"moduleLicense": "Apache License, Version 2.0", "moduleLicense": "Apache License, Version 2.0",
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt" "moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
}, },
{
"moduleName": "com.github.vladimir-bukhtoyarov:bucket4j-core",
"moduleUrl": "http://github.com/vladimir-bukhtoyarov/bucket4j/bucket4j-core",
"moduleVersion": "7.6.0",
"moduleLicense": "The Apache Software License, Version 2.0",
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0"
},
{ {
"moduleName": "com.google.zxing:core", "moduleName": "com.google.zxing:core",
"moduleUrl": "https://github.com/zxing/zxing/core", "moduleUrl": "https://github.com/zxing/zxing/core",
@@ -133,14 +149,14 @@
{ {
"moduleName": "com.nimbusds:nimbus-jose-jwt", "moduleName": "com.nimbusds:nimbus-jose-jwt",
"moduleUrl": "https://connect2id.com", "moduleUrl": "https://connect2id.com",
"moduleVersion": "9.24.4", "moduleVersion": "9.37.3",
"moduleLicense": "The Apache Software License, Version 2.0", "moduleLicense": "The Apache Software License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
}, },
{ {
"moduleName": "com.nimbusds:oauth2-oidc-sdk", "moduleName": "com.nimbusds:oauth2-oidc-sdk",
"moduleUrl": "https://bitbucket.org/connect2id/oauth-2.0-sdk-with-openid-connect-extensions", "moduleUrl": "https://bitbucket.org/connect2id/oauth-2.0-sdk-with-openid-connect-extensions",
"moduleVersion": "9.43.3", "moduleVersion": "9.43.4",
"moduleLicense": "Apache License, version 2.0", "moduleLicense": "Apache License, version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.html" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.html"
}, },
@@ -160,19 +176,19 @@
}, },
{ {
"moduleName": "com.twelvemonkeys.common:common-image", "moduleName": "com.twelvemonkeys.common:common-image",
"moduleVersion": "3.10.1", "moduleVersion": "3.11.0",
"moduleLicense": "The BSD License", "moduleLicense": "The BSD License",
"moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license" "moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license"
}, },
{ {
"moduleName": "com.twelvemonkeys.common:common-io", "moduleName": "com.twelvemonkeys.common:common-io",
"moduleVersion": "3.10.1", "moduleVersion": "3.11.0",
"moduleLicense": "The BSD License", "moduleLicense": "The BSD License",
"moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license" "moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license"
}, },
{ {
"moduleName": "com.twelvemonkeys.common:common-lang", "moduleName": "com.twelvemonkeys.common:common-lang",
"moduleVersion": "3.10.1", "moduleVersion": "3.11.0",
"moduleLicense": "The BSD License", "moduleLicense": "The BSD License",
"moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license" "moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license"
}, },
@@ -190,19 +206,19 @@
}, },
{ {
"moduleName": "com.twelvemonkeys.imageio:imageio-core", "moduleName": "com.twelvemonkeys.imageio:imageio-core",
"moduleVersion": "3.10.1", "moduleVersion": "3.11.0",
"moduleLicense": "The BSD License", "moduleLicense": "The BSD License",
"moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license" "moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license"
}, },
{ {
"moduleName": "com.twelvemonkeys.imageio:imageio-jpeg", "moduleName": "com.twelvemonkeys.imageio:imageio-jpeg",
"moduleVersion": "3.10.1", "moduleVersion": "3.11.0",
"moduleLicense": "The BSD License", "moduleLicense": "The BSD License",
"moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license" "moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license"
}, },
{ {
"moduleName": "com.twelvemonkeys.imageio:imageio-metadata", "moduleName": "com.twelvemonkeys.imageio:imageio-metadata",
"moduleVersion": "3.10.1", "moduleVersion": "3.11.0",
"moduleLicense": "The BSD License", "moduleLicense": "The BSD License",
"moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license" "moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license"
}, },
@@ -221,9 +237,9 @@
{ {
"moduleName": "com.zaxxer:HikariCP", "moduleName": "com.zaxxer:HikariCP",
"moduleUrl": "https://github.com/brettwooldridge/HikariCP", "moduleUrl": "https://github.com/brettwooldridge/HikariCP",
"moduleVersion": "5.0.1", "moduleVersion": "5.1.0",
"moduleLicense": "The Apache Software License, Version 2.0", "moduleLicense": "The Apache Software License, Version 2.0",
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
}, },
{ {
"moduleName": "commons-beanutils:commons-beanutils", "moduleName": "commons-beanutils:commons-beanutils",
@@ -263,28 +279,28 @@
{ {
"moduleName": "io.micrometer:micrometer-commons", "moduleName": "io.micrometer:micrometer-commons",
"moduleUrl": "https://github.com/micrometer-metrics/micrometer", "moduleUrl": "https://github.com/micrometer-metrics/micrometer",
"moduleVersion": "1.12.4", "moduleVersion": "1.13.0",
"moduleLicense": "The Apache Software License, Version 2.0", "moduleLicense": "The Apache Software License, Version 2.0",
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt" "moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
}, },
{ {
"moduleName": "io.micrometer:micrometer-core", "moduleName": "io.micrometer:micrometer-core",
"moduleUrl": "https://github.com/micrometer-metrics/micrometer", "moduleUrl": "https://github.com/micrometer-metrics/micrometer",
"moduleVersion": "1.12.4", "moduleVersion": "1.13.0",
"moduleLicense": "The Apache Software License, Version 2.0", "moduleLicense": "The Apache Software License, Version 2.0",
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt" "moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
}, },
{ {
"moduleName": "io.micrometer:micrometer-jakarta9", "moduleName": "io.micrometer:micrometer-jakarta9",
"moduleUrl": "https://github.com/micrometer-metrics/micrometer", "moduleUrl": "https://github.com/micrometer-metrics/micrometer",
"moduleVersion": "1.12.4", "moduleVersion": "1.13.0",
"moduleLicense": "The Apache Software License, Version 2.0", "moduleLicense": "The Apache Software License, Version 2.0",
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt" "moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
}, },
{ {
"moduleName": "io.micrometer:micrometer-observation", "moduleName": "io.micrometer:micrometer-observation",
"moduleUrl": "https://github.com/micrometer-metrics/micrometer", "moduleUrl": "https://github.com/micrometer-metrics/micrometer",
"moduleVersion": "1.12.4", "moduleVersion": "1.13.0",
"moduleLicense": "The Apache Software License, Version 2.0", "moduleLicense": "The Apache Software License, Version 2.0",
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt" "moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
}, },
@@ -329,6 +345,20 @@
"moduleLicense": "GPL2 w/ CPE", "moduleLicense": "GPL2 w/ CPE",
"moduleLicenseUrl": "https://www.gnu.org/software/classpath/license.html" "moduleLicenseUrl": "https://www.gnu.org/software/classpath/license.html"
}, },
{
"moduleName": "jakarta.enterprise:jakarta.enterprise.cdi-api",
"moduleUrl": "https://jboss.org",
"moduleVersion": "4.0.1",
"moduleLicense": "GNU General Public License, version 2 with the GNU Classpath Exception",
"moduleLicenseUrl": "https://www.gnu.org/software/classpath/license.html"
},
{
"moduleName": "jakarta.enterprise:jakarta.enterprise.lang-model",
"moduleUrl": "https://www.eclipse.org",
"moduleVersion": "4.0.1",
"moduleLicense": "GNU General Public License, version 2 with the GNU Classpath Exception",
"moduleLicenseUrl": "https://www.gnu.org/software/classpath/license.html"
},
{ {
"moduleName": "jakarta.inject:jakarta.inject-api", "moduleName": "jakarta.inject:jakarta.inject-api",
"moduleUrl": "https://www.eclipse.org", "moduleUrl": "https://www.eclipse.org",
@@ -336,6 +366,13 @@
"moduleLicense": "The Apache Software License, Version 2.0", "moduleLicense": "The Apache Software License, Version 2.0",
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt" "moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
}, },
{
"moduleName": "jakarta.interceptor:jakarta.interceptor-api",
"moduleUrl": "https://www.eclipse.org",
"moduleVersion": "2.1.0",
"moduleLicense": "GPL2 w/ CPE",
"moduleLicenseUrl": "https://www.gnu.org/software/classpath/license.html"
},
{ {
"moduleName": "jakarta.persistence:jakarta.persistence-api", "moduleName": "jakarta.persistence:jakarta.persistence-api",
"moduleUrl": "https://www.eclipse.org", "moduleUrl": "https://www.eclipse.org",
@@ -387,21 +424,21 @@
}, },
{ {
"moduleName": "net.bytebuddy:byte-buddy", "moduleName": "net.bytebuddy:byte-buddy",
"moduleVersion": "1.14.12", "moduleVersion": "1.14.16",
"moduleLicense": "Apache License, Version 2.0", "moduleLicense": "Apache License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
}, },
{ {
"moduleName": "net.minidev:accessors-smart", "moduleName": "net.minidev:accessors-smart",
"moduleUrl": "https://urielch.github.io/", "moduleUrl": "https://urielch.github.io/",
"moduleVersion": "2.5.0", "moduleVersion": "2.5.1",
"moduleLicense": "The Apache Software License, Version 2.0", "moduleLicense": "The Apache Software License, Version 2.0",
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt" "moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
}, },
{ {
"moduleName": "net.minidev:json-smart", "moduleName": "net.minidev:json-smart",
"moduleUrl": "https://urielch.github.io/", "moduleUrl": "https://urielch.github.io/",
"moduleVersion": "2.5.0", "moduleVersion": "2.5.1",
"moduleLicense": "The Apache Software License, Version 2.0", "moduleLicense": "The Apache Software License, Version 2.0",
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt" "moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
}, },
@@ -422,7 +459,7 @@
{ {
"moduleName": "org.apache.commons:commons-lang3", "moduleName": "org.apache.commons:commons-lang3",
"moduleUrl": "https://commons.apache.org/proper/commons-lang/", "moduleUrl": "https://commons.apache.org/proper/commons-lang/",
"moduleVersion": "3.13.0", "moduleVersion": "3.14.0",
"moduleLicense": "Apache-2.0", "moduleLicense": "Apache-2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
}, },
@@ -435,13 +472,13 @@
}, },
{ {
"moduleName": "org.apache.logging.log4j:log4j-api", "moduleName": "org.apache.logging.log4j:log4j-api",
"moduleVersion": "2.21.1", "moduleVersion": "2.23.1",
"moduleLicense": "Apache-2.0", "moduleLicense": "Apache-2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
}, },
{ {
"moduleName": "org.apache.logging.log4j:log4j-to-slf4j", "moduleName": "org.apache.logging.log4j:log4j-to-slf4j",
"moduleVersion": "2.21.1", "moduleVersion": "2.23.1",
"moduleLicense": "Apache-2.0", "moduleLicense": "Apache-2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
}, },
@@ -476,7 +513,7 @@
{ {
"moduleName": "org.apache.tomcat.embed:tomcat-embed-el", "moduleName": "org.apache.tomcat.embed:tomcat-embed-el",
"moduleUrl": "https://tomcat.apache.org/", "moduleUrl": "https://tomcat.apache.org/",
"moduleVersion": "10.1.19", "moduleVersion": "10.1.24",
"moduleLicense": "Apache License, Version 2.0", "moduleLicense": "Apache License, Version 2.0",
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt" "moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
}, },
@@ -496,7 +533,7 @@
{ {
"moduleName": "org.aspectj:aspectjweaver", "moduleName": "org.aspectj:aspectjweaver",
"moduleUrl": "https://www.eclipse.org/aspectj/", "moduleUrl": "https://www.eclipse.org/aspectj/",
"moduleVersion": "1.9.21", "moduleVersion": "1.9.22",
"moduleLicense": "Eclipse Public License - v 2.0", "moduleLicense": "Eclipse Public License - v 2.0",
"moduleLicenseUrl": "https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt" "moduleLicenseUrl": "https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt"
}, },
@@ -510,21 +547,21 @@
{ {
"moduleName": "org.bouncycastle:bcpkix-jdk18on", "moduleName": "org.bouncycastle:bcpkix-jdk18on",
"moduleUrl": "https://www.bouncycastle.org/java.html", "moduleUrl": "https://www.bouncycastle.org/java.html",
"moduleVersion": "1.77", "moduleVersion": "1.78.1",
"moduleLicense": "Bouncy Castle Licence", "moduleLicense": "Bouncy Castle Licence",
"moduleLicenseUrl": "https://www.bouncycastle.org/licence.html" "moduleLicenseUrl": "https://www.bouncycastle.org/licence.html"
}, },
{ {
"moduleName": "org.bouncycastle:bcprov-jdk18on", "moduleName": "org.bouncycastle:bcprov-jdk18on",
"moduleUrl": "https://www.bouncycastle.org/java.html", "moduleUrl": "https://www.bouncycastle.org/java.html",
"moduleVersion": "1.77", "moduleVersion": "1.78.1",
"moduleLicense": "Bouncy Castle Licence", "moduleLicense": "Bouncy Castle Licence",
"moduleLicenseUrl": "https://www.bouncycastle.org/licence.html" "moduleLicenseUrl": "https://www.bouncycastle.org/licence.html"
}, },
{ {
"moduleName": "org.bouncycastle:bcutil-jdk18on", "moduleName": "org.bouncycastle:bcutil-jdk18on",
"moduleUrl": "https://www.bouncycastle.org/java.html", "moduleUrl": "https://www.bouncycastle.org/java.html",
"moduleVersion": "1.77", "moduleVersion": "1.78.1",
"moduleLicense": "Bouncy Castle Licence", "moduleLicense": "Bouncy Castle Licence",
"moduleLicenseUrl": "https://www.bouncycastle.org/licence.html" "moduleLicenseUrl": "https://www.bouncycastle.org/licence.html"
}, },
@@ -550,182 +587,182 @@
{ {
"moduleName": "org.eclipse.jetty.ee10.websocket:jetty-ee10-websocket-jakarta-client", "moduleName": "org.eclipse.jetty.ee10.websocket:jetty-ee10-websocket-jakarta-client",
"moduleUrl": "https://eclipse.dev/jetty/", "moduleUrl": "https://eclipse.dev/jetty/",
"moduleVersion": "12.0.7", "moduleVersion": "12.0.9",
"moduleLicense": "Eclipse Public License - Version 2.0", "moduleLicense": "Eclipse Public License - Version 2.0",
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/" "moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
}, },
{ {
"moduleName": "org.eclipse.jetty.ee10.websocket:jetty-ee10-websocket-jakarta-common", "moduleName": "org.eclipse.jetty.ee10.websocket:jetty-ee10-websocket-jakarta-common",
"moduleUrl": "https://eclipse.dev/jetty/", "moduleUrl": "https://eclipse.dev/jetty/",
"moduleVersion": "12.0.7", "moduleVersion": "12.0.9",
"moduleLicense": "Eclipse Public License - Version 2.0", "moduleLicense": "Eclipse Public License - Version 2.0",
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/" "moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
}, },
{ {
"moduleName": "org.eclipse.jetty.ee10.websocket:jetty-ee10-websocket-jakarta-server", "moduleName": "org.eclipse.jetty.ee10.websocket:jetty-ee10-websocket-jakarta-server",
"moduleUrl": "https://eclipse.dev/jetty/", "moduleUrl": "https://eclipse.dev/jetty/",
"moduleVersion": "12.0.7", "moduleVersion": "12.0.9",
"moduleLicense": "Eclipse Public License - Version 2.0", "moduleLicense": "Eclipse Public License - Version 2.0",
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/" "moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
}, },
{ {
"moduleName": "org.eclipse.jetty.ee10.websocket:jetty-ee10-websocket-jetty-server", "moduleName": "org.eclipse.jetty.ee10.websocket:jetty-ee10-websocket-jetty-server",
"moduleUrl": "https://eclipse.dev/jetty/", "moduleUrl": "https://eclipse.dev/jetty/",
"moduleVersion": "12.0.7", "moduleVersion": "12.0.9",
"moduleLicense": "Eclipse Public License - Version 2.0", "moduleLicense": "Eclipse Public License - Version 2.0",
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/" "moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
}, },
{ {
"moduleName": "org.eclipse.jetty.ee10.websocket:jetty-ee10-websocket-servlet", "moduleName": "org.eclipse.jetty.ee10.websocket:jetty-ee10-websocket-servlet",
"moduleUrl": "https://eclipse.dev/jetty/", "moduleUrl": "https://eclipse.dev/jetty/",
"moduleVersion": "12.0.7", "moduleVersion": "12.0.9",
"moduleLicense": "Eclipse Public License - Version 2.0", "moduleLicense": "Eclipse Public License - Version 2.0",
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/" "moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
}, },
{ {
"moduleName": "org.eclipse.jetty.ee10:jetty-ee10-annotations", "moduleName": "org.eclipse.jetty.ee10:jetty-ee10-annotations",
"moduleUrl": "https://eclipse.dev/jetty/", "moduleUrl": "https://eclipse.dev/jetty/",
"moduleVersion": "12.0.7", "moduleVersion": "12.0.9",
"moduleLicense": "Eclipse Public License - Version 2.0", "moduleLicense": "Eclipse Public License - Version 2.0",
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/" "moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
}, },
{ {
"moduleName": "org.eclipse.jetty.ee10:jetty-ee10-plus", "moduleName": "org.eclipse.jetty.ee10:jetty-ee10-plus",
"moduleUrl": "https://eclipse.dev/jetty/", "moduleUrl": "https://eclipse.dev/jetty/",
"moduleVersion": "12.0.7", "moduleVersion": "12.0.9",
"moduleLicense": "Eclipse Public License - Version 2.0", "moduleLicense": "Eclipse Public License - Version 2.0",
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/" "moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
}, },
{ {
"moduleName": "org.eclipse.jetty.ee10:jetty-ee10-servlet", "moduleName": "org.eclipse.jetty.ee10:jetty-ee10-servlet",
"moduleUrl": "https://eclipse.dev/jetty/", "moduleUrl": "https://eclipse.dev/jetty/",
"moduleVersion": "12.0.7", "moduleVersion": "12.0.9",
"moduleLicense": "Eclipse Public License - Version 2.0", "moduleLicense": "Eclipse Public License - Version 2.0",
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/" "moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
}, },
{ {
"moduleName": "org.eclipse.jetty.ee10:jetty-ee10-servlets", "moduleName": "org.eclipse.jetty.ee10:jetty-ee10-servlets",
"moduleUrl": "https://eclipse.dev/jetty/", "moduleUrl": "https://eclipse.dev/jetty/",
"moduleVersion": "12.0.7", "moduleVersion": "12.0.9",
"moduleLicense": "Eclipse Public License - Version 2.0", "moduleLicense": "Eclipse Public License - Version 2.0",
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/" "moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
}, },
{ {
"moduleName": "org.eclipse.jetty.ee10:jetty-ee10-webapp", "moduleName": "org.eclipse.jetty.ee10:jetty-ee10-webapp",
"moduleUrl": "https://eclipse.dev/jetty/", "moduleUrl": "https://eclipse.dev/jetty/",
"moduleVersion": "12.0.7", "moduleVersion": "12.0.9",
"moduleLicense": "Eclipse Public License - Version 2.0", "moduleLicense": "Eclipse Public License - Version 2.0",
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/" "moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
}, },
{ {
"moduleName": "org.eclipse.jetty.websocket:jetty-websocket-core-client", "moduleName": "org.eclipse.jetty.websocket:jetty-websocket-core-client",
"moduleUrl": "https://eclipse.dev/jetty/", "moduleUrl": "https://eclipse.dev/jetty/",
"moduleVersion": "12.0.7", "moduleVersion": "12.0.9",
"moduleLicense": "Eclipse Public License - Version 2.0", "moduleLicense": "Eclipse Public License - Version 2.0",
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/" "moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
}, },
{ {
"moduleName": "org.eclipse.jetty.websocket:jetty-websocket-core-common", "moduleName": "org.eclipse.jetty.websocket:jetty-websocket-core-common",
"moduleUrl": "https://eclipse.dev/jetty/", "moduleUrl": "https://eclipse.dev/jetty/",
"moduleVersion": "12.0.7", "moduleVersion": "12.0.9",
"moduleLicense": "Eclipse Public License - Version 2.0", "moduleLicense": "Eclipse Public License - Version 2.0",
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/" "moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
}, },
{ {
"moduleName": "org.eclipse.jetty.websocket:jetty-websocket-core-server", "moduleName": "org.eclipse.jetty.websocket:jetty-websocket-core-server",
"moduleUrl": "https://eclipse.dev/jetty/", "moduleUrl": "https://eclipse.dev/jetty/",
"moduleVersion": "12.0.7", "moduleVersion": "12.0.9",
"moduleLicense": "Eclipse Public License - Version 2.0", "moduleLicense": "Eclipse Public License - Version 2.0",
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/" "moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
}, },
{ {
"moduleName": "org.eclipse.jetty.websocket:jetty-websocket-jetty-api", "moduleName": "org.eclipse.jetty.websocket:jetty-websocket-jetty-api",
"moduleUrl": "https://eclipse.dev/jetty/", "moduleUrl": "https://eclipse.dev/jetty/",
"moduleVersion": "12.0.7", "moduleVersion": "12.0.9",
"moduleLicense": "Eclipse Public License - Version 2.0", "moduleLicense": "Eclipse Public License - Version 2.0",
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/" "moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
}, },
{ {
"moduleName": "org.eclipse.jetty.websocket:jetty-websocket-jetty-common", "moduleName": "org.eclipse.jetty.websocket:jetty-websocket-jetty-common",
"moduleUrl": "https://eclipse.dev/jetty/", "moduleUrl": "https://eclipse.dev/jetty/",
"moduleVersion": "12.0.7", "moduleVersion": "12.0.9",
"moduleLicense": "Eclipse Public License - Version 2.0", "moduleLicense": "Eclipse Public License - Version 2.0",
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/" "moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
}, },
{ {
"moduleName": "org.eclipse.jetty:jetty-alpn-client", "moduleName": "org.eclipse.jetty:jetty-alpn-client",
"moduleUrl": "https://eclipse.dev/jetty/", "moduleUrl": "https://eclipse.dev/jetty/",
"moduleVersion": "12.0.7", "moduleVersion": "12.0.9",
"moduleLicense": "Eclipse Public License - Version 2.0", "moduleLicense": "Eclipse Public License - Version 2.0",
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/" "moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
}, },
{ {
"moduleName": "org.eclipse.jetty:jetty-client", "moduleName": "org.eclipse.jetty:jetty-client",
"moduleUrl": "https://eclipse.dev/jetty/", "moduleUrl": "https://eclipse.dev/jetty/",
"moduleVersion": "12.0.7", "moduleVersion": "12.0.9",
"moduleLicense": "Eclipse Public License - Version 2.0",
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
},
{
"moduleName": "org.eclipse.jetty:jetty-ee",
"moduleUrl": "https://eclipse.dev/jetty/",
"moduleVersion": "12.0.9",
"moduleLicense": "Eclipse Public License - Version 2.0", "moduleLicense": "Eclipse Public License - Version 2.0",
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/" "moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
}, },
{ {
"moduleName": "org.eclipse.jetty:jetty-http", "moduleName": "org.eclipse.jetty:jetty-http",
"moduleUrl": "https://eclipse.dev/jetty/", "moduleUrl": "https://eclipse.dev/jetty/",
"moduleVersion": "12.0.7", "moduleVersion": "12.0.9",
"moduleLicense": "Eclipse Public License - Version 2.0", "moduleLicense": "Eclipse Public License - Version 2.0",
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/" "moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
}, },
{ {
"moduleName": "org.eclipse.jetty:jetty-io", "moduleName": "org.eclipse.jetty:jetty-io",
"moduleUrl": "https://eclipse.dev/jetty/", "moduleUrl": "https://eclipse.dev/jetty/",
"moduleVersion": "12.0.7", "moduleVersion": "12.0.9",
"moduleLicense": "Eclipse Public License - Version 2.0",
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
},
{
"moduleName": "org.eclipse.jetty:jetty-jndi",
"moduleUrl": "https://eclipse.dev/jetty/",
"moduleVersion": "12.0.7",
"moduleLicense": "Eclipse Public License - Version 2.0", "moduleLicense": "Eclipse Public License - Version 2.0",
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/" "moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
}, },
{ {
"moduleName": "org.eclipse.jetty:jetty-plus", "moduleName": "org.eclipse.jetty:jetty-plus",
"moduleUrl": "https://eclipse.dev/jetty/", "moduleUrl": "https://eclipse.dev/jetty/",
"moduleVersion": "12.0.7", "moduleVersion": "12.0.9",
"moduleLicense": "Eclipse Public License - Version 2.0", "moduleLicense": "Eclipse Public License - Version 2.0",
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/" "moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
}, },
{ {
"moduleName": "org.eclipse.jetty:jetty-security", "moduleName": "org.eclipse.jetty:jetty-security",
"moduleUrl": "https://eclipse.dev/jetty/", "moduleUrl": "https://eclipse.dev/jetty/",
"moduleVersion": "12.0.7", "moduleVersion": "12.0.9",
"moduleLicense": "Eclipse Public License - Version 2.0", "moduleLicense": "Eclipse Public License - Version 2.0",
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/" "moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
}, },
{ {
"moduleName": "org.eclipse.jetty:jetty-server", "moduleName": "org.eclipse.jetty:jetty-server",
"moduleUrl": "https://eclipse.dev/jetty/", "moduleUrl": "https://eclipse.dev/jetty/",
"moduleVersion": "12.0.7", "moduleVersion": "12.0.9",
"moduleLicense": "Eclipse Public License - Version 2.0", "moduleLicense": "Eclipse Public License - Version 2.0",
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/" "moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
}, },
{ {
"moduleName": "org.eclipse.jetty:jetty-session", "moduleName": "org.eclipse.jetty:jetty-session",
"moduleUrl": "https://eclipse.dev/jetty/", "moduleUrl": "https://eclipse.dev/jetty/",
"moduleVersion": "12.0.7", "moduleVersion": "12.0.9",
"moduleLicense": "Eclipse Public License - Version 2.0", "moduleLicense": "Eclipse Public License - Version 2.0",
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/" "moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
}, },
{ {
"moduleName": "org.eclipse.jetty:jetty-util", "moduleName": "org.eclipse.jetty:jetty-util",
"moduleUrl": "https://eclipse.dev/jetty/", "moduleUrl": "https://eclipse.dev/jetty/",
"moduleVersion": "12.0.7", "moduleVersion": "12.0.9",
"moduleLicense": "Eclipse Public License - Version 2.0", "moduleLicense": "Eclipse Public License - Version 2.0",
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/" "moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
}, },
{ {
"moduleName": "org.eclipse.jetty:jetty-xml", "moduleName": "org.eclipse.jetty:jetty-xml",
"moduleUrl": "https://eclipse.dev/jetty/", "moduleUrl": "https://eclipse.dev/jetty/",
"moduleVersion": "12.0.7", "moduleVersion": "12.0.9",
"moduleLicense": "Eclipse Public License - Version 2.0", "moduleLicense": "Eclipse Public License - Version 2.0",
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/" "moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
}, },
@@ -753,7 +790,7 @@
{ {
"moduleName": "org.hdrhistogram:HdrHistogram", "moduleName": "org.hdrhistogram:HdrHistogram",
"moduleUrl": "http://hdrhistogram.github.io/HdrHistogram/", "moduleUrl": "http://hdrhistogram.github.io/HdrHistogram/",
"moduleVersion": "2.1.12", "moduleVersion": "2.2.1",
"moduleLicense": "Public Domain, per Creative Commons CC0", "moduleLicense": "Public Domain, per Creative Commons CC0",
"moduleLicenseUrl": "http://creativecommons.org/publicdomain/zero/1.0/" "moduleLicenseUrl": "http://creativecommons.org/publicdomain/zero/1.0/"
}, },
@@ -766,8 +803,8 @@
}, },
{ {
"moduleName": "org.hibernate.orm:hibernate-core", "moduleName": "org.hibernate.orm:hibernate-core",
"moduleUrl": "https://www.hibernate.org/orm/6.4", "moduleUrl": "https://www.hibernate.org/orm/6.5",
"moduleVersion": "6.4.4.Final", "moduleVersion": "6.5.2.Final",
"moduleLicense": "GNU Library General Public License v2.1 or later", "moduleLicense": "GNU Library General Public License v2.1 or later",
"moduleLicenseUrl": "https://www.opensource.org/licenses/LGPL-2.1" "moduleLicenseUrl": "https://www.opensource.org/licenses/LGPL-2.1"
}, },
@@ -788,35 +825,35 @@
{ {
"moduleName": "org.ow2.asm:asm", "moduleName": "org.ow2.asm:asm",
"moduleUrl": "http://asm.ow2.org", "moduleUrl": "http://asm.ow2.org",
"moduleVersion": "9.6", "moduleVersion": "9.7",
"moduleLicense": "The Apache Software License, Version 2.0", "moduleLicense": "The Apache Software License, Version 2.0",
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt" "moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
}, },
{ {
"moduleName": "org.ow2.asm:asm-commons", "moduleName": "org.ow2.asm:asm-commons",
"moduleUrl": "http://asm.ow2.org", "moduleUrl": "http://asm.ow2.org",
"moduleVersion": "9.6", "moduleVersion": "9.7",
"moduleLicense": "The Apache Software License, Version 2.0", "moduleLicense": "The Apache Software License, Version 2.0",
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt" "moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
}, },
{ {
"moduleName": "org.ow2.asm:asm-tree", "moduleName": "org.ow2.asm:asm-tree",
"moduleUrl": "http://asm.ow2.org", "moduleUrl": "http://asm.ow2.org",
"moduleVersion": "9.6", "moduleVersion": "9.7",
"moduleLicense": "The Apache Software License, Version 2.0", "moduleLicense": "The Apache Software License, Version 2.0",
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt" "moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
}, },
{ {
"moduleName": "org.slf4j:jul-to-slf4j", "moduleName": "org.slf4j:jul-to-slf4j",
"moduleUrl": "http://www.slf4j.org", "moduleUrl": "http://www.slf4j.org",
"moduleVersion": "2.0.12", "moduleVersion": "2.0.13",
"moduleLicense": "MIT License", "moduleLicense": "MIT License",
"moduleLicenseUrl": "http://www.opensource.org/licenses/mit-license.php" "moduleLicenseUrl": "http://www.opensource.org/licenses/mit-license.php"
}, },
{ {
"moduleName": "org.slf4j:slf4j-api", "moduleName": "org.slf4j:slf4j-api",
"moduleUrl": "http://www.slf4j.org", "moduleUrl": "http://www.slf4j.org",
"moduleVersion": "2.0.12", "moduleVersion": "2.0.13",
"moduleLicense": "MIT License", "moduleLicense": "MIT License",
"moduleLicenseUrl": "http://www.opensource.org/licenses/mit-license.php" "moduleLicenseUrl": "http://www.opensource.org/licenses/mit-license.php"
}, },
@@ -841,266 +878,266 @@
{ {
"moduleName": "org.springframework.boot:spring-boot", "moduleName": "org.springframework.boot:spring-boot",
"moduleUrl": "https://spring.io/projects/spring-boot", "moduleUrl": "https://spring.io/projects/spring-boot",
"moduleVersion": "3.2.4", "moduleVersion": "3.3.0",
"moduleLicense": "Apache License, Version 2.0", "moduleLicense": "Apache License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
}, },
{ {
"moduleName": "org.springframework.boot:spring-boot-actuator", "moduleName": "org.springframework.boot:spring-boot-actuator",
"moduleUrl": "https://spring.io/projects/spring-boot", "moduleUrl": "https://spring.io/projects/spring-boot",
"moduleVersion": "3.2.4", "moduleVersion": "3.3.0",
"moduleLicense": "Apache License, Version 2.0", "moduleLicense": "Apache License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
}, },
{ {
"moduleName": "org.springframework.boot:spring-boot-actuator-autoconfigure", "moduleName": "org.springframework.boot:spring-boot-actuator-autoconfigure",
"moduleUrl": "https://spring.io/projects/spring-boot", "moduleUrl": "https://spring.io/projects/spring-boot",
"moduleVersion": "3.2.4", "moduleVersion": "3.3.0",
"moduleLicense": "Apache License, Version 2.0", "moduleLicense": "Apache License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
}, },
{ {
"moduleName": "org.springframework.boot:spring-boot-autoconfigure", "moduleName": "org.springframework.boot:spring-boot-autoconfigure",
"moduleUrl": "https://spring.io/projects/spring-boot", "moduleUrl": "https://spring.io/projects/spring-boot",
"moduleVersion": "3.2.4", "moduleVersion": "3.3.0",
"moduleLicense": "Apache License, Version 2.0", "moduleLicense": "Apache License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
}, },
{ {
"moduleName": "org.springframework.boot:spring-boot-devtools", "moduleName": "org.springframework.boot:spring-boot-devtools",
"moduleUrl": "https://spring.io/projects/spring-boot", "moduleUrl": "https://spring.io/projects/spring-boot",
"moduleVersion": "3.2.4", "moduleVersion": "3.3.2",
"moduleLicense": "Apache License, Version 2.0", "moduleLicense": "Apache License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
}, },
{ {
"moduleName": "org.springframework.boot:spring-boot-starter", "moduleName": "org.springframework.boot:spring-boot-starter",
"moduleUrl": "https://spring.io/projects/spring-boot", "moduleUrl": "https://spring.io/projects/spring-boot",
"moduleVersion": "3.2.4", "moduleVersion": "3.3.0",
"moduleLicense": "Apache License, Version 2.0", "moduleLicense": "Apache License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
}, },
{ {
"moduleName": "org.springframework.boot:spring-boot-starter-actuator", "moduleName": "org.springframework.boot:spring-boot-starter-actuator",
"moduleUrl": "https://spring.io/projects/spring-boot", "moduleUrl": "https://spring.io/projects/spring-boot",
"moduleVersion": "3.2.4", "moduleVersion": "3.3.2",
"moduleLicense": "Apache License, Version 2.0", "moduleLicense": "Apache License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
}, },
{ {
"moduleName": "org.springframework.boot:spring-boot-starter-aop", "moduleName": "org.springframework.boot:spring-boot-starter-aop",
"moduleUrl": "https://spring.io/projects/spring-boot", "moduleUrl": "https://spring.io/projects/spring-boot",
"moduleVersion": "3.2.4", "moduleVersion": "3.3.0",
"moduleLicense": "Apache License, Version 2.0", "moduleLicense": "Apache License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
}, },
{ {
"moduleName": "org.springframework.boot:spring-boot-starter-data-jpa", "moduleName": "org.springframework.boot:spring-boot-starter-data-jpa",
"moduleUrl": "https://spring.io/projects/spring-boot", "moduleUrl": "https://spring.io/projects/spring-boot",
"moduleVersion": "3.2.4", "moduleVersion": "3.3.2",
"moduleLicense": "Apache License, Version 2.0", "moduleLicense": "Apache License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
}, },
{ {
"moduleName": "org.springframework.boot:spring-boot-starter-jdbc", "moduleName": "org.springframework.boot:spring-boot-starter-jdbc",
"moduleUrl": "https://spring.io/projects/spring-boot", "moduleUrl": "https://spring.io/projects/spring-boot",
"moduleVersion": "3.2.4", "moduleVersion": "3.3.0",
"moduleLicense": "Apache License, Version 2.0", "moduleLicense": "Apache License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
}, },
{ {
"moduleName": "org.springframework.boot:spring-boot-starter-jetty", "moduleName": "org.springframework.boot:spring-boot-starter-jetty",
"moduleUrl": "https://spring.io/projects/spring-boot", "moduleUrl": "https://spring.io/projects/spring-boot",
"moduleVersion": "3.2.4", "moduleVersion": "3.3.2",
"moduleLicense": "Apache License, Version 2.0", "moduleLicense": "Apache License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
}, },
{ {
"moduleName": "org.springframework.boot:spring-boot-starter-json", "moduleName": "org.springframework.boot:spring-boot-starter-json",
"moduleUrl": "https://spring.io/projects/spring-boot", "moduleUrl": "https://spring.io/projects/spring-boot",
"moduleVersion": "3.2.4", "moduleVersion": "3.3.0",
"moduleLicense": "Apache License, Version 2.0", "moduleLicense": "Apache License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
}, },
{ {
"moduleName": "org.springframework.boot:spring-boot-starter-logging", "moduleName": "org.springframework.boot:spring-boot-starter-logging",
"moduleUrl": "https://spring.io/projects/spring-boot", "moduleUrl": "https://spring.io/projects/spring-boot",
"moduleVersion": "3.2.4", "moduleVersion": "3.3.0",
"moduleLicense": "Apache License, Version 2.0", "moduleLicense": "Apache License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
}, },
{ {
"moduleName": "org.springframework.boot:spring-boot-starter-oauth2-client", "moduleName": "org.springframework.boot:spring-boot-starter-oauth2-client",
"moduleUrl": "https://spring.io/projects/spring-boot", "moduleUrl": "https://spring.io/projects/spring-boot",
"moduleVersion": "3.2.4", "moduleVersion": "3.3.2",
"moduleLicense": "Apache License, Version 2.0", "moduleLicense": "Apache License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
}, },
{ {
"moduleName": "org.springframework.boot:spring-boot-starter-security", "moduleName": "org.springframework.boot:spring-boot-starter-security",
"moduleUrl": "https://spring.io/projects/spring-boot", "moduleUrl": "https://spring.io/projects/spring-boot",
"moduleVersion": "3.2.4", "moduleVersion": "3.3.2",
"moduleLicense": "Apache License, Version 2.0", "moduleLicense": "Apache License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
}, },
{ {
"moduleName": "org.springframework.boot:spring-boot-starter-thymeleaf", "moduleName": "org.springframework.boot:spring-boot-starter-thymeleaf",
"moduleUrl": "https://spring.io/projects/spring-boot", "moduleUrl": "https://spring.io/projects/spring-boot",
"moduleVersion": "3.2.4", "moduleVersion": "3.3.2",
"moduleLicense": "Apache License, Version 2.0", "moduleLicense": "Apache License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
}, },
{ {
"moduleName": "org.springframework.boot:spring-boot-starter-web", "moduleName": "org.springframework.boot:spring-boot-starter-web",
"moduleUrl": "https://spring.io/projects/spring-boot", "moduleUrl": "https://spring.io/projects/spring-boot",
"moduleVersion": "3.2.4", "moduleVersion": "3.3.2",
"moduleLicense": "Apache License, Version 2.0", "moduleLicense": "Apache License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
}, },
{ {
"moduleName": "org.springframework.data:spring-data-commons", "moduleName": "org.springframework.data:spring-data-commons",
"moduleUrl": "https://spring.io/projects/spring-data", "moduleUrl": "https://spring.io/projects/spring-data",
"moduleVersion": "3.2.4", "moduleVersion": "3.3.0",
"moduleLicense": "Apache License, Version 2.0", "moduleLicense": "Apache License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
}, },
{ {
"moduleName": "org.springframework.data:spring-data-jpa", "moduleName": "org.springframework.data:spring-data-jpa",
"moduleUrl": "https://projects.spring.io/spring-data-jpa", "moduleUrl": "https://projects.spring.io/spring-data-jpa",
"moduleVersion": "3.2.4", "moduleVersion": "3.3.0",
"moduleLicense": "Apache License, Version 2.0", "moduleLicense": "Apache License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
}, },
{ {
"moduleName": "org.springframework.security:spring-security-config", "moduleName": "org.springframework.security:spring-security-config",
"moduleUrl": "https://spring.io/projects/spring-security", "moduleUrl": "https://spring.io/projects/spring-security",
"moduleVersion": "6.2.3", "moduleVersion": "6.3.0",
"moduleLicense": "Apache License, Version 2.0", "moduleLicense": "Apache License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
}, },
{ {
"moduleName": "org.springframework.security:spring-security-core", "moduleName": "org.springframework.security:spring-security-core",
"moduleUrl": "https://spring.io/projects/spring-security", "moduleUrl": "https://spring.io/projects/spring-security",
"moduleVersion": "6.2.3", "moduleVersion": "6.3.0",
"moduleLicense": "Apache License, Version 2.0", "moduleLicense": "Apache License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
}, },
{ {
"moduleName": "org.springframework.security:spring-security-crypto", "moduleName": "org.springframework.security:spring-security-crypto",
"moduleUrl": "https://spring.io/projects/spring-security", "moduleUrl": "https://spring.io/projects/spring-security",
"moduleVersion": "6.2.3", "moduleVersion": "6.3.0",
"moduleLicense": "Apache License, Version 2.0", "moduleLicense": "Apache License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
}, },
{ {
"moduleName": "org.springframework.security:spring-security-oauth2-client", "moduleName": "org.springframework.security:spring-security-oauth2-client",
"moduleUrl": "https://spring.io/projects/spring-security", "moduleUrl": "https://spring.io/projects/spring-security",
"moduleVersion": "6.2.3", "moduleVersion": "6.3.0",
"moduleLicense": "Apache License, Version 2.0", "moduleLicense": "Apache License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
}, },
{ {
"moduleName": "org.springframework.security:spring-security-oauth2-core", "moduleName": "org.springframework.security:spring-security-oauth2-core",
"moduleUrl": "https://spring.io/projects/spring-security", "moduleUrl": "https://spring.io/projects/spring-security",
"moduleVersion": "6.2.3", "moduleVersion": "6.3.0",
"moduleLicense": "Apache License, Version 2.0", "moduleLicense": "Apache License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
}, },
{ {
"moduleName": "org.springframework.security:spring-security-oauth2-jose", "moduleName": "org.springframework.security:spring-security-oauth2-jose",
"moduleUrl": "https://spring.io/projects/spring-security", "moduleUrl": "https://spring.io/projects/spring-security",
"moduleVersion": "6.2.3", "moduleVersion": "6.3.0",
"moduleLicense": "Apache License, Version 2.0", "moduleLicense": "Apache License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
}, },
{ {
"moduleName": "org.springframework.security:spring-security-web", "moduleName": "org.springframework.security:spring-security-web",
"moduleUrl": "https://spring.io/projects/spring-security", "moduleUrl": "https://spring.io/projects/spring-security",
"moduleVersion": "6.2.3", "moduleVersion": "6.3.0",
"moduleLicense": "Apache License, Version 2.0", "moduleLicense": "Apache License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
}, },
{ {
"moduleName": "org.springframework:spring-aop", "moduleName": "org.springframework:spring-aop",
"moduleUrl": "https://github.com/spring-projects/spring-framework", "moduleUrl": "https://github.com/spring-projects/spring-framework",
"moduleVersion": "6.1.5", "moduleVersion": "6.1.8",
"moduleLicense": "Apache License, Version 2.0", "moduleLicense": "Apache License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
}, },
{ {
"moduleName": "org.springframework:spring-aspects", "moduleName": "org.springframework:spring-aspects",
"moduleUrl": "https://github.com/spring-projects/spring-framework", "moduleUrl": "https://github.com/spring-projects/spring-framework",
"moduleVersion": "6.1.5", "moduleVersion": "6.1.8",
"moduleLicense": "Apache License, Version 2.0", "moduleLicense": "Apache License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
}, },
{ {
"moduleName": "org.springframework:spring-beans", "moduleName": "org.springframework:spring-beans",
"moduleUrl": "https://github.com/spring-projects/spring-framework", "moduleUrl": "https://github.com/spring-projects/spring-framework",
"moduleVersion": "6.1.5", "moduleVersion": "6.1.8",
"moduleLicense": "Apache License, Version 2.0", "moduleLicense": "Apache License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
}, },
{ {
"moduleName": "org.springframework:spring-context", "moduleName": "org.springframework:spring-context",
"moduleUrl": "https://github.com/spring-projects/spring-framework", "moduleUrl": "https://github.com/spring-projects/spring-framework",
"moduleVersion": "6.1.5", "moduleVersion": "6.1.8",
"moduleLicense": "Apache License, Version 2.0", "moduleLicense": "Apache License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
}, },
{ {
"moduleName": "org.springframework:spring-core", "moduleName": "org.springframework:spring-core",
"moduleUrl": "https://github.com/spring-projects/spring-framework", "moduleUrl": "https://github.com/spring-projects/spring-framework",
"moduleVersion": "6.1.5", "moduleVersion": "6.1.8",
"moduleLicense": "Apache License, Version 2.0", "moduleLicense": "Apache License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
}, },
{ {
"moduleName": "org.springframework:spring-expression", "moduleName": "org.springframework:spring-expression",
"moduleUrl": "https://github.com/spring-projects/spring-framework", "moduleUrl": "https://github.com/spring-projects/spring-framework",
"moduleVersion": "6.1.5", "moduleVersion": "6.1.8",
"moduleLicense": "Apache License, Version 2.0", "moduleLicense": "Apache License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
}, },
{ {
"moduleName": "org.springframework:spring-jcl", "moduleName": "org.springframework:spring-jcl",
"moduleUrl": "https://github.com/spring-projects/spring-framework", "moduleUrl": "https://github.com/spring-projects/spring-framework",
"moduleVersion": "6.1.5", "moduleVersion": "6.1.8",
"moduleLicense": "Apache License, Version 2.0", "moduleLicense": "Apache License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
}, },
{ {
"moduleName": "org.springframework:spring-jdbc", "moduleName": "org.springframework:spring-jdbc",
"moduleUrl": "https://github.com/spring-projects/spring-framework", "moduleUrl": "https://github.com/spring-projects/spring-framework",
"moduleVersion": "6.1.5", "moduleVersion": "6.1.8",
"moduleLicense": "Apache License, Version 2.0", "moduleLicense": "Apache License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
}, },
{ {
"moduleName": "org.springframework:spring-orm", "moduleName": "org.springframework:spring-orm",
"moduleUrl": "https://github.com/spring-projects/spring-framework", "moduleUrl": "https://github.com/spring-projects/spring-framework",
"moduleVersion": "6.1.5", "moduleVersion": "6.1.8",
"moduleLicense": "Apache License, Version 2.0", "moduleLicense": "Apache License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
}, },
{ {
"moduleName": "org.springframework:spring-tx", "moduleName": "org.springframework:spring-tx",
"moduleUrl": "https://github.com/spring-projects/spring-framework", "moduleUrl": "https://github.com/spring-projects/spring-framework",
"moduleVersion": "6.1.5", "moduleVersion": "6.1.8",
"moduleLicense": "Apache License, Version 2.0", "moduleLicense": "Apache License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
}, },
{ {
"moduleName": "org.springframework:spring-web", "moduleName": "org.springframework:spring-web",
"moduleUrl": "https://github.com/spring-projects/spring-framework", "moduleUrl": "https://github.com/spring-projects/spring-framework",
"moduleVersion": "6.1.5", "moduleVersion": "6.1.8",
"moduleLicense": "Apache License, Version 2.0", "moduleLicense": "Apache License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
}, },
{ {
"moduleName": "org.springframework:spring-webmvc", "moduleName": "org.springframework:spring-webmvc",
"moduleUrl": "https://github.com/spring-projects/spring-framework", "moduleUrl": "https://github.com/spring-projects/spring-framework",
"moduleVersion": "6.1.5", "moduleVersion": "6.1.9",
"moduleLicense": "Apache License, Version 2.0", "moduleLicense": "Apache License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
}, },

View File

@@ -1,8 +1,3 @@
p {
text-align: center;
margin-top: 2em;
}
.features-container { .features-container {
display: grid; display: grid;
grid-template-columns: repeat(auto-fill, minmax(21rem, 3fr)); grid-template-columns: repeat(auto-fill, minmax(21rem, 3fr));

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 600"><g fill-rule="evenodd" stroke-width="1pt"><path fill="#a51931" d="M0 0h900v600H0z"/><path fill="#fff" d="M0 120h900v360H0z"/><path fill="#241d4f" d="M0 240h900v120H0z"/></g></svg>

After

Width:  |  Height:  |  Size: 241 B

View File

@@ -3,12 +3,12 @@
"short_name": "Stirling-PDF", "short_name": "Stirling-PDF",
"icons": [ "icons": [
{ {
"src": "/android-icon-192x192.png", "src": "/android-chrome-192x192.png",
"sizes": "192x192", "sizes": "192x192",
"type": "image/png" "type": "image/png"
}, },
{ {
"src": "/android-icon-512x512.png", "src": "/android-chrome-512x512.png",
"sizes": "512x512", "sizes": "512x512",
"type": "image/png" "type": "image/png"
} }

View File

@@ -1,17 +1,17 @@
{ {
"name": "Stirling PDF", "name": "Stirling-PDF",
"short_name": "Stirling PDF", "short_name": "Stirling-PDF",
"icons": [ "icons": [
{ {
"src": "/android-chrome-192x192.png", "src": "/android-chrome-192x192.png",
"sizes": "192x192", "sizes": "192x192",
"type": "image/png" "type": "image/png"
}, },
{ {
"src": "/android-chrome-512x512.png", "src": "/android-chrome-512x512.png",
"sizes": "512x512", "sizes": "512x512",
"type": "image/png" "type": "image/png"
} }
], ],
"theme_color": "#ffffff", "theme_color": "#ffffff",
"background_color": "#ffffff", "background_color": "#ffffff",

View File

@@ -13,9 +13,12 @@
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-9 bg-card"> <div class="col-md-9 bg-card">
<div class="tool-header">
<span class="material-symbols-rounded tool-header-icon organize">settings_account_box</span>
<span class="tool-header-text" th:text="#{account.accountSettings}">User Settings</span>
</div>
<!-- User Settings Title --> <!-- User Settings Title -->
<h2 class="text-center" th:text="#{account.accountSettings}">User Settings</h2>
<th:block th:if="${messageType}"> <th:block th:if="${messageType}">
<div class="alert alert-danger"> <div class="alert alert-danger">
<span th:text="#{${messageType}}">Default message if not found</span> <span th:text="#{${messageType}}">Default message if not found</span>
@@ -247,9 +250,9 @@
<table id="settingsTable" class="table table-bordered table-sm table-striped"> <table id="settingsTable" class="table table-bordered table-sm table-striped">
<thead> <thead>
<tr> <tr>
<th th:text="#{account.property}">Property</th> <th scope="col" th:text="#{account.property}">Property</th>
<th th:text="#{account.accountSettings}">Account Setting</th> <th scope="col" th:text="#{account.accountSettings}">Account Setting</th>
<th th:text="#{account.webBrowserSettings}">Web Browser Setting</th> <th scope="col" th:text="#{account.webBrowserSettings}">Web Browser Setting</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@@ -329,8 +332,8 @@
}); });
</script> </script>
<div class="mb-3 mt-4 text-center"> <div class="mb-3 mt-4 text-center">
<a href="logout" role="button" class="btn btn-danger" th:text="#{account.signOut}">Sign Out</a> <a th:href="@{'/logout'}" role="button" class="btn btn-danger" th:text="#{account.signOut}">Sign Out</a>
<a th:if="${role == 'ROLE_ADMIN'}" class="btn btn-info" href="addUsers" role="button" th:text="#{account.adminSettings}" target="_blank">Admin Settings</a> <a th:if="${role == 'ROLE_ADMIN'}" class="btn btn-info" th:href="@{'/addUsers'}" role="button" th:text="#{account.adminSettings}" target="_blank">Admin Settings</a>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -12,10 +12,13 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-8 bg-card"> <div class="col-md-9 bg-card">
<div class="tool-header">
<span class="material-symbols-rounded tool-header-icon organize">manage_accounts</span>
<span class="tool-header-text" th:text="#{adminUserSettings.header}">Admin User Control Settings</span>
</div>
<!-- User Settings Title --> <!-- User Settings Title -->
<h2 class="text-center" th:text="#{adminUserSettings.header}">Admin User Control Settings</h2>
<div style="background: var(--md-sys-color-outline-variant);padding: .8rem; margin: 10px 0; border-radius: 2rem; text-align: center;"> <div style="background: var(--md-sys-color-outline-variant);padding: .8rem; margin: 10px 0; border-radius: 2rem; text-align: center;">
<a href="#" data-bs-toggle="modal" data-bs-target="#addUserModal" class="btn btn-outline-info" th:title="#{adminUserSettings.addUser}"> <a href="#" data-bs-toggle="modal" data-bs-target="#addUserModal" class="btn btn-outline-info" th:title="#{adminUserSettings.addUser}">
<span class="material-symbols-rounded">person_add</span> <span class="material-symbols-rounded">person_add</span>
@@ -29,35 +32,39 @@
<div th:if="${deleteMessage}" class="alert alert-danger"> <div th:if="${deleteMessage}" class="alert alert-danger">
<span th:text="#{${deleteMessage}}">Message</span> <span th:text="#{${deleteMessage}}">Message</span>
</div> </div>
<table class="table"> <div class="bg-card mt-3 mb-3">
<thead> <table class="table table-striped table-hover">
<tr> <thead>
<th th:text="#{username}">Username</th> <tr>
<th th:text="#{adminUserSettings.roles}">Roles</th> <th scope="col">UID</th>
<th th:text="#{adminUserSettings.actions}">Actions</th> <th scope="col" th:text="#{username}">Username</th>
<th th:text="#{adminUserSettings.authenticated}">Authenticated</th> <th scope="col" th:text="#{adminUserSettings.roles}">Roles</th>
</tr> <th scope="col" th:text="#{adminUserSettings.actions}">Actions</th>
</thead> <th scope="col" th:text="#{adminUserSettings.authenticated}">Authenticated</th>
<tbody> </tr>
<tr th:each="user : ${users}"> </thead>
<td style="align-content: center;" th:text="${user.username}"></td> <tbody>
<td style="align-content: center;" th:text="#{${user.roleName}}"></td> <tr th:each="user : ${users}">
<td style="align-content: center;"> <th scope="row" style="align-content: center;" th:text="${user.id}"></th>
<form th:if="${user.username != currentUsername}" th:action="@{'/api/v1/user/admin/deleteUser/' + ${user.username}}" method="post" onsubmit="return confirmDelete()"> <td style="align-content: center;" th:text="${user.username}"></td>
<button type="submit" th:title="#{adminUserSettings.deleteUser}" class="btn btn-info"><span class="material-symbols-rounded">person_remove</span></button> <td style="align-content: center;" th:text="#{${user.roleName}}"></td>
</form> <td style="align-content: center;">
<script th:inline="javascript"> <form th:if="${user.username != currentUsername}" th:action="@{'/api/v1/user/admin/deleteUser/' + ${user.username}}" method="post" onsubmit="return confirmDelete()">
const confirm_text = /*[[#{adminUserSettings.confirmDeleteUser}]]*/ 'Should the user be deleted?'; <button type="submit" th:title="#{adminUserSettings.deleteUser}" class="btn btn-info"><span class="material-symbols-rounded">person_remove</span></button>
function confirmDelete() { </form>
return confirm(confirm_text); <a th:if="${user.username == currentUsername}" th:href="@{'/account'}" class="btn btn-outline-info"><span class="material-symbols-rounded">edit</span></a>
} </td>
</script> <td style="align-content: center;" th:text="${user.authenticationType}"></td>
<a th:if="${user.username == currentUsername}" th:href="@{'/account'}" class="btn btn-outline-info"><span class="material-symbols-rounded">edit</span></a> </tr>
</td> </tbody>
<td style="align-content: center;" th:text="${user.authenticationType}"></td> </table>
</tr> </div>
</tbody> <script th:inline="javascript">
</table> const confirm_text = /*[[#{adminUserSettings.confirmDeleteUser}]]*/ 'Should the user be deleted?';
function confirmDelete() {
return confirm(confirm_text);
}
</script>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -21,7 +21,7 @@
<span class="tool-header-text" th:text="#{autoSplitPDF.header}"></span> <span class="tool-header-text" th:text="#{autoSplitPDF.header}"></span>
</div> </div>
<form method="post" enctype="multipart/form-data" th:action="@{api/v1/misc/auto-split-pdf}"> <form method="post" enctype="multipart/form-data" th:action="@{'/api/v1/misc/auto-split-pdf'}">
<p th:text="#{autoSplitPDF.formPrompt}"></p> <p th:text="#{autoSplitPDF.formPrompt}"></p>
<div <div
th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"> th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}">
@@ -43,9 +43,9 @@
<li th:text="#{autoSplitPDF.selectText.3}"></li> <li th:text="#{autoSplitPDF.selectText.3}"></li>
<li th:text="#{autoSplitPDF.selectText.4}"></li> <li th:text="#{autoSplitPDF.selectText.4}"></li>
</ul> </ul>
<p><a th:href="@{files/Auto%20Splitter%20Divider%20(minimal).pdf}" download <p><a th:href="@{'/files/Auto%20Splitter%20Divider%20(minimal).pdf'}" download
th:text="#{autoSplitPDF.dividerDownload1}"></a></p> th:text="#{autoSplitPDF.dividerDownload1}"></a></p>
<p><a th:href="@{files/Auto%20Splitter%20Divider%20(with%20instructions).pdf}" download <p><a th:href="@{'/files/Auto%20Splitter%20Divider%20(with%20instructions).pdf'}" download
th:text="#{autoSplitPDF.dividerDownload2}"></a></p> th:text="#{autoSplitPDF.dividerDownload2}"></a></p>
</div> </div>

View File

@@ -14,7 +14,7 @@
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6"> <div class="col-md-6">
<h2 th:text="#{BookToPDF.header}"></h2> <h2 th:text="#{BookToPDF.header}"></h2>
<form method="post" enctype="multipart/form-data" th:action="@{api/v1/convert/book/pdf}"> <form method="post" enctype="multipart/form-data" th:action="@{'/api/v1/convert/book/pdf'}">
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false)}"></div> <div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false)}"></div>
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{BookToPDF.submit}"></button> <button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{BookToPDF.submit}"></button>
</form> </form>

View File

@@ -20,7 +20,7 @@
<span class="tool-header-text" th:text="#{fileToPDF.header}"></span> <span class="tool-header-text" th:text="#{fileToPDF.header}"></span>
</div> </div>
<p th:text="#{processTimeWarning}"></p> <p th:text="#{processTimeWarning}"></p>
<form method="post" enctype="multipart/form-data" th:action="@{api/v1/convert/file/pdf}"> <form method="post" enctype="multipart/form-data" th:action="@{'/api/v1/convert/file/pdf'}">
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false)}"></div> <div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false)}"></div>
<a class="btn btn-outline-primary" data-bs-toggle="collapse" href="#info" role="button" <a class="btn btn-outline-primary" data-bs-toggle="collapse" href="#info" role="button"
aria-expanded="false" aria-controls="info" th:text="#{fileToPDF.supportedFileTypesInfo}"></a> aria-expanded="false" aria-controls="info" th:text="#{fileToPDF.supportedFileTypesInfo}"></a>

View File

@@ -17,7 +17,7 @@
<span class="material-symbols-rounded tool-header-icon convert">html</span> <span class="material-symbols-rounded tool-header-icon convert">html</span>
<span class="tool-header-text" th:text="#{HTMLToPDF.header}"></span> <span class="tool-header-text" th:text="#{HTMLToPDF.header}"></span>
</div> </div>
<form method="post" enctype="multipart/form-data" th:action="@{api/v1/convert/html/pdf}"> <form method="post" enctype="multipart/form-data" th:action="@{'/api/v1/convert/html/pdf'}">
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='text/html,application/zip' )}"></div> <div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='text/html,application/zip' )}"></div>
<div class="mb-3"> <div class="mb-3">
<label for="zoom" th:text="#{HTMLToPDF.zoom}" class="form-label"></label> <label for="zoom" th:text="#{HTMLToPDF.zoom}" class="form-label"></label>

View File

@@ -17,7 +17,7 @@
<span class="material-symbols-rounded tool-header-icon image">image</span> <span class="material-symbols-rounded tool-header-icon image">image</span>
<span class="tool-header-text" th:text="#{imageToPDF.header}"></span> <span class="tool-header-text" th:text="#{imageToPDF.header}"></span>
</div> </div>
<form method="post" enctype="multipart/form-data" th:action="@{api/v1/convert/img/pdf}"> <form method="post" enctype="multipart/form-data" th:action="@{'/api/v1/convert/img/pdf'}">
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='image/*', inputText=#{imgPrompt})}"></div> <div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='image/*', inputText=#{imgPrompt})}"></div>
<div class="mb-3"> <div class="mb-3">
<label for="fitOption" th:text="#{imageToPDF.selectLabel}">Fit Options</label> <label for="fitOption" th:text="#{imageToPDF.selectLabel}">Fit Options</label>

View File

@@ -17,7 +17,7 @@
<span class="material-symbols-rounded tool-header-icon convert">markdown</span> <span class="material-symbols-rounded tool-header-icon convert">markdown</span>
<span class="tool-header-text" th:text="#{MarkdownToPDF.header}"></span> <span class="tool-header-text" th:text="#{MarkdownToPDF.header}"></span>
</div> </div>
<form method="post" enctype="multipart/form-data" th:action="@{api/v1/convert/markdown/pdf}"> <form method="post" enctype="multipart/form-data" th:action="@{'/api/v1/convert/markdown/pdf'}">
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='text/markdown')}"></div> <div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='text/markdown')}"></div>
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{MarkdownToPDF.submit}"></button> <button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{MarkdownToPDF.submit}"></button>
</form> </form>

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