Compare commits
140 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
01f7f1f59c | ||
|
|
ff7f089f69 | ||
|
|
ca5ce905c7 | ||
|
|
0fc29de02c | ||
|
|
8509a16d6e | ||
|
|
0ed021357b | ||
|
|
58ad7a1e8a | ||
|
|
622ee29dd8 | ||
|
|
5cbb4c6223 | ||
|
|
5299859385 | ||
|
|
c57b308909 | ||
|
|
6409274f83 | ||
|
|
bc534c12a5 | ||
|
|
b58fd2022a | ||
|
|
d850d026ed | ||
|
|
83627686d4 | ||
|
|
4e7d01c72c | ||
|
|
0f8ab20db7 | ||
|
|
88cc90786d | ||
|
|
fb66717b43 | ||
|
|
1d60433fcf | ||
|
|
0f3df6e92b | ||
|
|
ca7c63c7d7 | ||
|
|
135f9611df | ||
|
|
cfaaeebd4a | ||
|
|
09a0779180 | ||
|
|
7f7d09bc85 | ||
|
|
0c454a08dc | ||
|
|
d749b63549 | ||
|
|
2053a6950d | ||
|
|
41bd801e0d | ||
|
|
cd0e1a3962 | ||
|
|
7c2f482b3b | ||
|
|
7741d60afd | ||
|
|
8aac0c0327 | ||
|
|
7c26c56210 | ||
|
|
e88a780efe | ||
|
|
363fb5dc02 | ||
|
|
39a187b6da | ||
|
|
b4cc34a522 | ||
|
|
af94ef3d49 | ||
|
|
505855a53c | ||
|
|
87ac245341 | ||
|
|
1670a09d04 | ||
|
|
620b954336 | ||
|
|
cfd51e9b84 | ||
|
|
6c797f8216 | ||
|
|
40e208152a | ||
|
|
cf7bfa62ef | ||
|
|
a1086b9a04 | ||
|
|
9bc4bbd2c8 | ||
|
|
73156012e9 | ||
|
|
91cc3d77d4 | ||
|
|
3fc55a9e9f | ||
|
|
b666aa3f26 | ||
|
|
53e7dbe12f | ||
|
|
9d8ff6856b | ||
|
|
3fb38376b0 | ||
|
|
15c73d9dd3 | ||
|
|
86f71ffb93 | ||
|
|
eb928d3369 | ||
|
|
d7307665b3 | ||
|
|
2836f0ab5a | ||
|
|
91b7f3980c | ||
|
|
5053432c2d | ||
|
|
563c612395 | ||
|
|
95dced6455 | ||
|
|
989f0bbbfb | ||
|
|
e5eec28bfd | ||
|
|
bfc402f307 | ||
|
|
35a998b934 | ||
|
|
cadc8e499d | ||
|
|
7f7ea6da9f | ||
|
|
ab9a22d8e7 | ||
|
|
cd2728105e | ||
|
|
d75e84bdff | ||
|
|
e791fee38b | ||
|
|
ad5f057733 | ||
|
|
6f325b5fdb | ||
|
|
b73aeee18d | ||
|
|
8a54035a9f | ||
|
|
af28e30e4c | ||
|
|
492513306c | ||
|
|
bc554ff4a7 | ||
|
|
b7a0d1ece8 | ||
|
|
ca384218dc | ||
|
|
e9550fd6b2 | ||
|
|
232a305d51 | ||
|
|
a6ab448eeb | ||
|
|
f9aa157c6c | ||
|
|
b7df24acaa | ||
|
|
ad4ca1b2d7 | ||
|
|
c562d197e7 | ||
|
|
83ba1899b7 | ||
|
|
3420adc7c9 | ||
|
|
fd39f28e46 | ||
|
|
710125852a | ||
|
|
e8ec208390 | ||
|
|
4584562607 | ||
|
|
2c1412a088 | ||
|
|
0a65382979 | ||
|
|
4f404f66e5 | ||
|
|
89505ada00 | ||
|
|
374a30ac5a | ||
|
|
cee4ee4128 | ||
|
|
58fc5e2ffa | ||
|
|
951ea43f8b | ||
|
|
ca16ecef24 | ||
|
|
bb025dc2a1 | ||
|
|
d797169bd0 | ||
|
|
891f9e2252 | ||
|
|
4a579c00ce | ||
|
|
9cb4d8e088 | ||
|
|
5d3ee7755a | ||
|
|
c047c46587 | ||
|
|
54f53be5b5 | ||
|
|
8bb9e5b22f | ||
|
|
379791a326 | ||
|
|
38ec68b303 | ||
|
|
a5095b04ad | ||
|
|
a27ddb40be | ||
|
|
bc36be8a5e | ||
|
|
1e35556034 | ||
|
|
882cd41d4b | ||
|
|
724fb4bf8f | ||
|
|
b07437dbfa | ||
|
|
96f05cd518 | ||
|
|
77411e94a4 | ||
|
|
0da9c62ef8 | ||
|
|
52a7885f3c | ||
|
|
f98f089d63 | ||
|
|
6b618f3abe | ||
|
|
0732ffa76e | ||
|
|
b5b4636e56 | ||
|
|
ca12d040e1 | ||
|
|
3388b9fafa | ||
|
|
954b36e14c | ||
|
|
4d43814220 | ||
|
|
f6262c82e1 | ||
|
|
21de6c6520 |
6
.github/workflows/push-docker.yml
vendored
6
.github/workflows/push-docker.yml
vendored
@@ -21,6 +21,8 @@ jobs:
|
||||
|
||||
|
||||
- uses: gradle/gradle-build-action@v2.4.2
|
||||
env:
|
||||
DOCKER_ENABLE_SECURITY: false
|
||||
with:
|
||||
gradle-version: 7.6
|
||||
arguments: clean build
|
||||
@@ -77,6 +79,8 @@ jobs:
|
||||
cache-to: type=gha,mode=max
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args:
|
||||
VERSION_TAG=${{ steps.versionNumber.outputs.versionNumber }}
|
||||
platforms: linux/amd64,linux/arm64/v8
|
||||
|
||||
|
||||
@@ -105,6 +109,8 @@ jobs:
|
||||
cache-to: type=gha,mode=max
|
||||
tags: ${{ steps.meta2.outputs.tags }}
|
||||
labels: ${{ steps.meta2.outputs.labels }}
|
||||
build-args:
|
||||
VERSION_TAG=${{ steps.versionNumber.outputs.versionNumber }}
|
||||
platforms: linux/amd64,linux/arm64/v8
|
||||
|
||||
|
||||
|
||||
22
.github/workflows/releaseArtifacts.yml
vendored
22
.github/workflows/releaseArtifacts.yml
vendored
@@ -1,10 +1,20 @@
|
||||
name: Release Artifacts
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [created]
|
||||
|
||||
jobs:
|
||||
push:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
enable_security: [true, false]
|
||||
include:
|
||||
- enable_security: true
|
||||
file_suffix: '-with-login'
|
||||
- enable_security: false
|
||||
file_suffix: ''
|
||||
steps:
|
||||
- uses: actions/checkout@v3.5.2
|
||||
|
||||
@@ -17,15 +27,17 @@ jobs:
|
||||
- name: Grant execute permission for gradlew
|
||||
run: chmod +x gradlew
|
||||
|
||||
- name: Generate jar
|
||||
- name: Generate jar (With Security=${{ matrix.enable_security }})
|
||||
run: ./gradlew clean createExe
|
||||
env:
|
||||
DOCKER_ENABLE_SECURITY: ${{ matrix.enable_security }}
|
||||
|
||||
- name: Upload binaries to release
|
||||
uses: svenstaro/upload-release-action@v2
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
file: ./build/launch4j/Stirling-PDF.exe
|
||||
asset_name: Stirling-PDF.exe
|
||||
asset_name: Stirling-PDF${{ matrix.file_suffix }}.exe
|
||||
tag: ${{ github.ref }}
|
||||
overwrite: true
|
||||
|
||||
@@ -33,13 +45,11 @@ jobs:
|
||||
id: versionNumber
|
||||
run: echo "::set-output name=versionNumber::$(./gradlew printVersion --quiet | tail -1)"
|
||||
|
||||
- name: Upload binaries to release
|
||||
- name: Upload jar binaries to release
|
||||
uses: svenstaro/upload-release-action@v2
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
file: ./build/libs/Stirling-PDF-${{ steps.versionNumber.outputs.versionNumber }}.jar
|
||||
asset_name: Stirling-PDF.jar
|
||||
asset_name: Stirling-PDF${{ matrix.file_suffix }}.jar
|
||||
tag: ${{ github.ref }}
|
||||
overwrite: true
|
||||
|
||||
|
||||
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -19,7 +19,7 @@ pipeline/
|
||||
|
||||
#### Stirling-PDF Files ###
|
||||
customFiles/
|
||||
config/
|
||||
configs/
|
||||
watchedFolders/
|
||||
|
||||
|
||||
@@ -116,7 +116,7 @@ watchedFolders/
|
||||
*.zip
|
||||
*.tar.gz
|
||||
*.rar
|
||||
|
||||
*.db
|
||||
/build
|
||||
|
||||
/.vscode
|
||||
@@ -1,6 +1,11 @@
|
||||
# Build jbig2enc in a separate stage
|
||||
FROM frooodle/stirling-pdf-base:beta4
|
||||
|
||||
ARG VERSION_TAG
|
||||
ENV VERSION_TAG=$VERSION_TAG
|
||||
|
||||
ENV DOCKER_ENABLE_SECURITY=false
|
||||
|
||||
# Create scripts folder and copy local scripts
|
||||
RUN mkdir /scripts
|
||||
COPY ./scripts/* /scripts/
|
||||
@@ -11,7 +16,7 @@ COPY src/main/resources/static/fonts/*.ttf /usr/share/fonts/opentype/noto/
|
||||
COPY src/main/resources/static/fonts/*.otf /usr/share/fonts/opentype/noto/
|
||||
RUN fc-cache -f -v
|
||||
|
||||
# Copy the application JAR file
|
||||
# Always copy the JAR
|
||||
COPY build/libs/*.jar app.jar
|
||||
|
||||
# Expose the application port
|
||||
@@ -19,8 +24,6 @@ EXPOSE 8080
|
||||
|
||||
# Set environment variables
|
||||
ENV APP_HOME_NAME="Stirling PDF"
|
||||
#ENV APP_HOME_DESCRIPTION="Personal PDF Website!"
|
||||
#ENV APP_NAVBAR_NAME="Stirling PDF"
|
||||
|
||||
# Run the application
|
||||
RUN chmod +x /scripts/init.sh
|
||||
|
||||
@@ -10,20 +10,17 @@ RUN apt-get update && \
|
||||
unoconv && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
#Install fonts
|
||||
RUN mkdir /usr/share/fonts/opentype/noto/
|
||||
COPY src/main/resources/static/fonts/*.ttf /usr/share/fonts/opentype/noto/
|
||||
COPY src/main/resources/static/fonts/*.otf /usr/share/fonts/opentype/noto/
|
||||
RUN fc-cache -f -v
|
||||
|
||||
# Copy the application JAR file
|
||||
COPY build/libs/*.jar app.jar
|
||||
|
||||
|
||||
|
||||
# Expose the application port
|
||||
EXPOSE 8080
|
||||
|
||||
# Set environment variables
|
||||
ENV GROUPS_TO_REMOVE=Python,OpenCV,OCRmyPDF
|
||||
ENV DOCKER_ENABLE_SECURITY=false
|
||||
|
||||
# Run the application
|
||||
CMD ["java", "-jar", "/app.jar"]
|
||||
|
||||
@@ -7,8 +7,11 @@ COPY build/libs/*.jar app.jar
|
||||
# Expose the application port
|
||||
EXPOSE 8080
|
||||
|
||||
|
||||
|
||||
# Set environment variables
|
||||
ENV GROUPS_TO_REMOVE=CLI
|
||||
ENV DOCKER_ENABLE_SECURITY=false
|
||||
|
||||
# Run the application
|
||||
CMD ["java", "-jar", "/app.jar"]
|
||||
|
||||
@@ -3,9 +3,11 @@
|
||||
| adjust-contrast | ✔️ | | | | | | | | | | ✔️ |
|
||||
| auto-split-pdf | ✔️ | | | | | | | | | ✔️ | |
|
||||
| crop | ✔️ | | | | | | | | | ✔️ | |
|
||||
| extract-page | ✔️ | | | | | | | | | ✔️ | |
|
||||
| merge-pdfs | ✔️ | | | | | | | | | ✔️ | |
|
||||
| multi-page-layout | ✔️ | | | | | | | | | ✔️ | |
|
||||
| pdf-organizer | ✔️ | | | | | | | | | ✔️ | ✔️ |
|
||||
| pdf-to-single-page | ✔️ | | | | | | | | | ✔️ | |
|
||||
| remove-pages | ✔️ | | | | | | | | | ✔️ | |
|
||||
| rotate-pdf | ✔️ | | | | | | | | | ✔️ | |
|
||||
| scale-pages | ✔️ | | | | | | | | | ✔️ | |
|
||||
@@ -15,6 +17,7 @@
|
||||
| pdf-to-html | | ✔️ | | | ✔️ | | | ✔️ | | | |
|
||||
| pdf-to-img | | ✔️ | | | | | | | | ✔️ | |
|
||||
| pdf-to-pdfa | | ✔️ | | | ✔️ | | | | ✔️ | | |
|
||||
| pdf-to-markdown | | ✔️ | | | | | | | | ✔️ | |
|
||||
| pdf-to-presentation | | ✔️ | | | ✔️ | | | ✔️ | | | |
|
||||
| pdf-to-text | | ✔️ | | | ✔️ | | | ✔️ | | | |
|
||||
| pdf-to-word | | ✔️ | | | ✔️ | | | ✔️ | | | |
|
||||
@@ -34,8 +37,10 @@
|
||||
| compress-pdf | | | | ✔️ | ✔️ | | | | ✔️ | | |
|
||||
| extract-image-scans | | | | ✔️ | ✔️ | ✔️ | ✔️ | | | | |
|
||||
| extract-images | | | | ✔️ | | | | | | ✔️ | |
|
||||
| flatten | | | | ✔️ | | | | | | | |
|
||||
| flatten | | | | ✔️ | | | | | | | ✔️ |
|
||||
| get-info-on-pdf | | | | ✔️ | | | | | | ✔️ | |
|
||||
| ocr-pdf | | | | ✔️ | ✔️ | | | | ✔️ | | |
|
||||
| remove-blanks | | | | ✔️ | ✔️ | ✔️ | ✔️ | | | | |
|
||||
| repair | | | | ✔️ | ✔️ | | | ✔️ | | | |
|
||||
| show-javascript | | | | ✔️ | | | | | | | ✔️ |
|
||||
| sign | | | | ✔️ | | | | | | | ✔️ |
|
||||
117
README.md
117
README.md
@@ -8,6 +8,8 @@
|
||||
[](https://www.paypal.com/paypalme/froodleplex)
|
||||
[](https://github.com/sponsors/Frooodle)
|
||||
|
||||
[](https://cloud.digitalocean.com/apps/new?repo=https://github.com/Frooodle/Stirling-PDF/tree/digitalOcean&refcode=c3210994b1af)
|
||||
|
||||
This is a powerful locally hosted web based PDF manipulation tool using docker that allows you to perform various operations on PDF files, such as splitting merging, converting, reorganizing, adding images, rotating, compressing, and more. This locally hosted web application started as a 100% ChatGPT-made application and has evolved to include a wide range of features to handle all your PDF needs.
|
||||
|
||||
Stirling PDF makes no outbound calls for any record keeping or tracking.
|
||||
@@ -80,9 +82,9 @@ Please view https://github.com/Frooodle/Stirling-PDF/blob/main/LocalRunGuide.md
|
||||
### Docker
|
||||
https://hub.docker.com/r/frooodle/s-pdf
|
||||
|
||||
Stirling PDF has 3 different versions, a Full version, Lite and ultra-Lite. 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, Lite, and ultra-Lite. 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/Frooodle/Stirling-PDF/blob/main/Version-groups.md)
|
||||
For people that dont mind about space optimisation just use latest tag.
|
||||
For people that don't mind about space optimization just use the latest tag.
|
||||

|
||||

|
||||

|
||||
@@ -92,19 +94,14 @@ Docker Run
|
||||
docker run -d \
|
||||
-p 8080:8080 \
|
||||
-v /location/of/trainingData:/usr/share/tesseract-ocr/4.00/tessdata \
|
||||
-v /location/of/extraConfigs:/configs \
|
||||
--name stirling-pdf \
|
||||
frooodle/s-pdf:latest
|
||||
|
||||
|
||||
Can also add these for customisation but are not required
|
||||
-v /location/of/extraConfigs:/configs \
|
||||
|
||||
-v /location/of/customFiles:/customFiles \
|
||||
-e APP_HOME_NAME="Stirling PDF" \
|
||||
-e APP_HOME_DESCRIPTION="Your locally hosted one-stop-shop for all your PDF needs." \
|
||||
-e APP_NAVBAR_NAME="Stirling PDF" \
|
||||
-e ALLOW_GOOGLE_VISIBILITY="true" \
|
||||
-e APP_ROOT_PATH="/" \
|
||||
-e APP_LOCALE="en_GB" \
|
||||
```
|
||||
Docker Compose
|
||||
```
|
||||
@@ -116,15 +113,8 @@ services:
|
||||
- '8080:8080'
|
||||
volumes:
|
||||
- /location/of/trainingData:/usr/share/tesseract-ocr/4.00/tessdata #Required for extra OCR languages
|
||||
# - /location/of/extraConfigs:/configs
|
||||
- /location/of/extraConfigs:/configs
|
||||
# - /location/of/customFiles:/customFiles/
|
||||
# environment:
|
||||
# APP_LOCALE: en_GB
|
||||
# APP_HOME_NAME: Stirling PDF
|
||||
# APP_HOME_DESCRIPTION: Your locally hosted one-stop-shop for all your PDF needs.
|
||||
# APP_NAVBAR_NAME: Stirling PDF
|
||||
# APP_ROOT_PATH: /
|
||||
# ALLOW_GOOGLE_VISIBILITY: true
|
||||
|
||||
```
|
||||
|
||||
@@ -156,47 +146,92 @@ https://github.com/Frooodle/Stirling-PDF/blob/main/HowToAddNewLanguage.md
|
||||
|
||||
And please create a PR to merge it back in so others can use it!
|
||||
|
||||
Also please note as i add new features i will google translate existing languages so that they dont lose support. This could mean that new features need grammer corrections as added.
|
||||
|
||||
## How to View
|
||||
1. Open a web browser and navigate to `http://localhost:8080/`
|
||||
2. Use the application by following the instructions on the website.
|
||||
|
||||
|
||||
## Customize App
|
||||
Stirling PDF allows easy customization of the visible application name.
|
||||
Simply use environment variables APP_HOME_NAME, APP_HOME_DESCRIPTION and APP_NAVBAR_NAME with Docker or Java.
|
||||
If running Java directly, you can also pass these as properties using -D arguments.
|
||||
## Customisation
|
||||
Stirling PDF allows easy customization of the app.
|
||||
Includes things like
|
||||
- Custom application name
|
||||
- Custom slogans, icons, images, and even custom HTML (via file overrides)
|
||||
|
||||
Using the same method you can also change
|
||||
|
||||
- The default language by providing APP_LOCALE with values like de-DE fr-FR or ar-AR (Note the - character not _ ) to select your default language (Will always default to English on invalid locale) Current accepted locales can be seen above in the Want to add your own language section
|
||||
- Enable/Disable search engine visiblility with ALLOW_GOOGLE_VISIBILITY with true / false values. Default disable visiblility.
|
||||
- Change root URI for Stirling-PDF ie change server.com/ to server.com/pdf-app by running APP_ROOT_PATH as pdf-app
|
||||
- Disable and remove endpoints and functionality from Stirling-PDF. Currently the endpoints ENDPOINTS_TO_REMOVE and GROUPS_TO_REMOVE can include comma seperated lists of endpoints and groups to disable as example ENDPOINTS_TO_REMOVE=img-to-pdf,remove-pages would disable both image to pdf and remove pages, GROUPS_TO_REMOVE=LibreOffice Would disable all things that use LibreOffice. You can see a list of all endpoints and groups [here](https://github.com/Frooodle/Stirling-PDF/blob/main/groups.md)
|
||||
- Change the max file size allowed through the server with the environment variable MAX_FILE_SIZE. default 2000MB
|
||||
- Customise static files such as app logo by placing files in the /customFiles/static/ directory. Example to customise app logo is placing a /customFiles/static/favicon.svg to override current SVG. This can be used to change any images/icons/css/fonts/js etc in Stirling-PDF
|
||||
There are two options for this, either using the generated settings file ``settings.yml``
|
||||
This file is located in the ``/configs`` directory and follows standard YAML formatting
|
||||
|
||||
Environment variables are also supported and would override the settings file
|
||||
For example in the settings.yml you have
|
||||
```
|
||||
system:
|
||||
defaultLocale: 'en-US'
|
||||
```
|
||||
|
||||
To have this via an environment variable you would have ``SYSTEM_DEFAULTLOCALE``
|
||||
|
||||
The Current list of settings is
|
||||
```
|
||||
security:
|
||||
enableLogin: true # set to 'true' to enable login
|
||||
csrfDisabled: true #enables/disables csrf protection
|
||||
|
||||
system:
|
||||
defaultLocale: 'en-US' # Set the default language (e.g. 'de-DE', 'fr-FR', etc)
|
||||
googlevisibility: false # 'true' to allow Google visibility, 'false' to disallow
|
||||
rootPath: / # Set the application's root URI (e.g. pdf-app for http://localhost/pdf-app)
|
||||
customstaticFilePath: '/customFiles/static/' # Directory path for custom static files
|
||||
|
||||
ui:
|
||||
homeName: # Application's visible name
|
||||
homeDescription: # Short description or tagline.
|
||||
navbarName: # Name displayed on the navigation bar
|
||||
|
||||
endpoints:
|
||||
toRemove: [] # List individual endpoints to disable (e.g. ['img-to-pdf', 'remove-pages'])
|
||||
groupsToRemove: [] # List groups of endpoints to disable (e.g. ['LibreOffice']) view groups.md for more info
|
||||
|
||||
metrics:
|
||||
enabled: true
|
||||
```
|
||||
### Extra notes
|
||||
- Endpoints. Currently, the endpoints ENDPOINTS_TO_REMOVE and GROUPS_TO_REMOVE can include comma separate lists of endpoints and groups to disable as example ENDPOINTS_TO_REMOVE=img-to-pdf,remove-pages would disable both image-to-pdf and remove pages, GROUPS_TO_REMOVE=LibreOffice Would disable all things that use LibreOffice. You can see a list of all endpoints and groups [here](https://github.com/Frooodle/Stirling-PDF/blob/main/groups.md)
|
||||
- customStaticFilePath. Customise static files such as the app logo by placing files in the /customFiles/static/ directory. An example of customising app logo is placing a /customFiles/static/favicon.svg to override current SVG. This can be used to change any images/icons/css/fonts/js etc in Stirling-PDF
|
||||
|
||||
|
||||
## API
|
||||
For those wanting to use Stirling-PDFs backend API to link with their own custom scripting to edit PDFs you can view all existing API documentation
|
||||
[here](https://app.swaggerhub.com/apis-docs/Frooodle/Stirling-PDF/) or navigate to /swagger-ui/index.html of your stirling-pdf instance for your versions documentation (Or by following the API button in your settings of Stirling-PDF)
|
||||
|
||||
|
||||
## Login authentication
|
||||
### Prerequisites:
|
||||
- User must have the folder ./configs volumed within docker so that it is retained during updates.
|
||||
- Docker uses must download the security jar version by setting ``DOCKER_ENABLE_SECURITY`` to ``true`` in environment variables.
|
||||
- Now the initial user must be generated. Navigate to your settings.yaml and configure your security settings along with the username and password (only required on the first boot to create the initial user, ignored after.). Alternatively, you can set these via the environment variables ``SECURITY_ENABLELOGIN : true`` ``SECURITY_INITIALLOGIN_USERNAME: username`` ``SECURITY_INITIALLOGIN_PASSWORD: password``
|
||||
|
||||
Once the above has been done, on restart, a new stirling-pdf-DB.mv.db will show if everything worked.
|
||||
|
||||
When you login to Stirling PDF you will be redirected to /login page to login with those credentials. After login everything should function as normal
|
||||
|
||||
To access your account settings go to Account settings in the settings cog menu (top right in navbar) This Account settings menu is also where you find your API key.
|
||||
|
||||
To add new users go to the bottom of Account settings and hit 'Admin Settings', here you can add new users. The different roles mentioned within this are for rate limiting. This is a Work in progress which will be expanding on more in future
|
||||
|
||||
For API usage you must provide a header with 'X-API-Key' and the associated API key for that user.
|
||||
|
||||
|
||||
## FAQ
|
||||
|
||||
### Q1: Can you add authentication in Stirling PDF?
|
||||
There is no Auth within Stirling PDF and there is none planned. This feature will not be added. Instead we recommended you use trusted and secure authentication software like Authentik or Authelia.
|
||||
|
||||
### Q2: What are your planned features?
|
||||
- Crop
|
||||
### Q1: What are your planned features?
|
||||
- Progress bar/Tracking
|
||||
- Full custom logic pipelines to combine multiple operations together.
|
||||
- Folder support with auto scanning to perform operations on
|
||||
- Redact sections of pages
|
||||
- Add page numbers
|
||||
- Auto rename (Renames file based on file title text)
|
||||
- URL to PDF
|
||||
- Change contrast
|
||||
- Redact text (Via UI)
|
||||
- Add Forms
|
||||
- Annotations
|
||||
- Multi page layout (Stich PDF pages together) support x rows y columns and custom page sizing
|
||||
- Fill forms mannual and automatic
|
||||
|
||||
### Q3: Why is my application downloading .htm files?
|
||||
### Q2: Why is my application downloading .htm files?
|
||||
This is a issue caused commonly by your NGINX congifuration. The default file upload size for NGINX is 1MB, you need to add the following in your Nginx sites-available file. client_max_body_size SIZE; Where "SIZE" is 50M for example for 50MB files.
|
||||
|
||||
@@ -15,6 +15,7 @@ Operation | Ultra-Lite | Lite | Full
|
||||
--------------------|------------|------|-----
|
||||
add-page-numbers | ✔️ | ✔️ | ✔️
|
||||
add-password | ✔️ | ✔️ | ✔️
|
||||
add-image | ✔️ | ✔️ | ✔️
|
||||
add-watermark | ✔️ | ✔️ | ✔️
|
||||
adjust-contrast | ✔️ | ✔️ | ✔️
|
||||
auto-split-pdf | ✔️ | ✔️ | ✔️
|
||||
@@ -24,21 +25,25 @@ crop | ✔️ | ✔️ | ✔️
|
||||
change-metadata | ✔️ | ✔️ | ✔️
|
||||
change-permissions | ✔️ | ✔️ | ✔️
|
||||
compare | ✔️ | ✔️ | ✔️
|
||||
extract-page | ✔️ | ✔️ | ✔️
|
||||
extract-images | ✔️ | ✔️ | ✔️
|
||||
flatten | ✔️ | ✔️ | ✔️
|
||||
get-info-on-pdf | ✔️ | ✔️ | ✔️
|
||||
img-to-pdf | ✔️ | ✔️ | ✔️
|
||||
markdown-to-pdf | ✔️ | ✔️ | ✔️
|
||||
merge-pdfs | ✔️ | ✔️ | ✔️
|
||||
multi-page-layout | ✔️ | ✔️ | ✔️
|
||||
pdf-organizer | ✔️ | ✔️ | ✔️
|
||||
pdf-to-img | ✔️ | ✔️ | ✔️
|
||||
pdf-to-single-page | ✔️ | ✔️ | ✔️
|
||||
remove-pages | ✔️ | ✔️ | ✔️
|
||||
remove-password | ✔️ | ✔️ | ✔️
|
||||
rotate-pdf | ✔️ | ✔️ | ✔️
|
||||
sanitize-pdf | ✔️ | ✔️ | ✔️
|
||||
scale-pages | ✔️ | ✔️ | ✔️
|
||||
sign | ✔️ | ✔️ | ✔️
|
||||
show-javascript | ✔️ | ✔️ | ✔️
|
||||
split-pdfs | ✔️ | ✔️ | ✔️
|
||||
add-image | ✔️ | ✔️ | ✔️
|
||||
file-to-pdf | | ✔️ | ✔️
|
||||
pdf-to-html | | ✔️ | ✔️
|
||||
pdf-to-presentation | | ✔️ | ✔️
|
||||
|
||||
49
build.gradle
49
build.gradle
@@ -1,20 +1,38 @@
|
||||
plugins {
|
||||
id 'java'
|
||||
id 'org.springframework.boot' version '3.1.1'
|
||||
id 'io.spring.dependency-management' version '1.1.0'
|
||||
id 'org.springframework.boot' version '3.1.2'
|
||||
id 'io.spring.dependency-management' version '1.1.2'
|
||||
id 'org.springdoc.openapi-gradle-plugin' version '1.6.0'
|
||||
id "io.swagger.swaggerhub" version "1.2.0"
|
||||
id 'edu.sc.seis.launch4j' version '3.0.3'
|
||||
}
|
||||
|
||||
group = 'stirling.software'
|
||||
version = '0.11.2'
|
||||
version = '0.13.1'
|
||||
sourceCompatibility = '17'
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
java {
|
||||
if (System.getenv('DOCKER_ENABLE_SECURITY') == 'false') {
|
||||
exclude 'stirling/software/SPDF/config/security/**'
|
||||
exclude 'stirling/software/SPDF/controller/api/UserController.java'
|
||||
exclude 'stirling/software/SPDF/controller/web/AccountWebController.java'
|
||||
exclude 'stirling/software/SPDF/model/ApiKeyAuthenticationToken.java'
|
||||
exclude 'stirling/software/SPDF/model/Authority.java'
|
||||
exclude 'stirling/software/SPDF/model/PersistentLogin.java'
|
||||
exclude 'stirling/software/SPDF/model/User.java'
|
||||
exclude 'stirling/software/SPDF/repository/**'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
openApi {
|
||||
apiDocsUrl = "http://localhost:8080/v3/api-docs"
|
||||
outputDir = file("$projectDir")
|
||||
@@ -45,9 +63,21 @@ launch4j {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'org.springframework.boot:spring-boot-starter-web:3.1.0'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf:3.1.1'
|
||||
testImplementation 'org.springframework.boot:spring-boot-starter-test:3.1.0'
|
||||
implementation 'org.yaml:snakeyaml:2.1'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-web:3.1.2'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf:3.1.2'
|
||||
|
||||
if (System.getenv('DOCKER_ENABLE_SECURITY') != 'false') {
|
||||
implementation 'org.springframework.boot:spring-boot-starter-security:3.1.2'
|
||||
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5:3.1.2.RELEASE'
|
||||
implementation "org.springframework.boot:spring-boot-starter-data-jpa"
|
||||
implementation "com.h2database:h2"
|
||||
}
|
||||
|
||||
testImplementation 'org.springframework.boot:spring-boot-starter-test:3.1.2'
|
||||
|
||||
|
||||
|
||||
// https://mvnrepository.com/artifact/org.apache.pdfbox/jbig2-imageio
|
||||
implementation group: 'org.apache.pdfbox', name: 'jbig2-imageio', version: '3.0.4'
|
||||
implementation 'commons-io:commons-io:2.13.0'
|
||||
@@ -55,14 +85,17 @@ dependencies {
|
||||
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.1.0'
|
||||
|
||||
//general PDF
|
||||
implementation 'org.apache.pdfbox:pdfbox:2.0.28'
|
||||
implementation 'org.apache.pdfbox:pdfbox:2.0.29'
|
||||
implementation 'org.bouncycastle:bcprov-jdk15on:1.70'
|
||||
implementation 'org.bouncycastle:bcpkix-jdk15on:1.70'
|
||||
implementation 'com.itextpdf:itext7-core:7.2.5'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-actuator'
|
||||
implementation 'io.micrometer:micrometer-core'
|
||||
|
||||
implementation group: 'com.google.zxing', name: 'core', version: '3.5.1'
|
||||
// https://mvnrepository.com/artifact/org.commonmark/commonmark
|
||||
implementation 'org.commonmark:commonmark:0.21.0'
|
||||
// https://mvnrepository.com/artifact/com.github.vladimir-bukhtoyarov/bucket4j-core
|
||||
implementation 'com.github.vladimir-bukhtoyarov:bucket4j-core:7.6.0'
|
||||
|
||||
developmentOnly("org.springframework.boot:spring-boot-devtools")
|
||||
|
||||
|
||||
BIN
images/login-dark.png
Normal file
BIN
images/login-dark.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 29 KiB |
BIN
images/login-light.png
Normal file
BIN
images/login-light.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 30 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 118 KiB After Width: | Height: | Size: 131 KiB |
@@ -5,5 +5,36 @@ echo "Copying original files without overwriting existing files"
|
||||
mkdir -p /usr/share/tesseract-ocr
|
||||
cp -rn /usr/share/tesseract-ocr-original/* /usr/share/tesseract-ocr
|
||||
|
||||
# Check if TESSERACT_LANGS environment variable is set and is not empty
|
||||
if [[ -n "$TESSERACT_LANGS" ]]; then
|
||||
# Convert comma-separated values to a space-separated list
|
||||
LANGS=$(echo $TESSERACT_LANGS | tr ',' ' ')
|
||||
|
||||
# Install each language pack
|
||||
for LANG in $LANGS; do
|
||||
apt-get install -y "tesseract-ocr-$LANG"
|
||||
done
|
||||
fi
|
||||
|
||||
# Check for DOCKER_ENABLE_SECURITY and download the appropriate JAR if required
|
||||
if [ "$DOCKER_ENABLE_SECURITY" = "true" ] && [ "$VERSION_TAG" != "alpha" ]; then
|
||||
if [ ! -f app-security.jar ]; then
|
||||
echo "Trying to download from: https://github.com/Frooodle/Stirling-PDF/releases/download/v$VERSION_TAG/Stirling-PDF-with-login.jar"
|
||||
curl -L -o app-security.jar https://github.com/Frooodle/Stirling-PDF/releases/download/v$VERSION_TAG/Stirling-PDF-with-login.jar
|
||||
|
||||
# If the first download attempt failed, try with the 'v' prefix
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Trying to download from: https://github.com/Frooodle/Stirling-PDF/releases/download/$VERSION_TAG/Stirling-PDF-with-login.jar"
|
||||
curl -L -o app-security.jar https://github.com/Frooodle/Stirling-PDF/releases/download/$VERSION_TAG/Stirling-PDF-with-login.jar
|
||||
fi
|
||||
|
||||
if [ $? -eq 0 ]; then # checks if curl was successful
|
||||
rm -f app.jar
|
||||
ln -s app-security.jar app.jar
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
# Run the main command
|
||||
exec "$@"
|
||||
@@ -1,20 +1,20 @@
|
||||
package stirling.software.SPDF;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import stirling.software.SPDF.config.ConfigInitializer;
|
||||
import stirling.software.SPDF.utils.GeneralUtils;
|
||||
|
||||
@SpringBootApplication
|
||||
|
||||
//@EnableScheduling
|
||||
public class SPdfApplication {
|
||||
|
||||
@@ -48,7 +48,15 @@ public class SPdfApplication {
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(SPdfApplication.class, args);
|
||||
SpringApplication app = new SpringApplication(SPdfApplication.class);
|
||||
app.addInitializers(new ConfigInitializer());
|
||||
if (Files.exists(Paths.get("configs/settings.yml"))) {
|
||||
app.setDefaultProperties(Collections.singletonMap("spring.config.additional-location", "file:configs/settings.yml"));
|
||||
} else {
|
||||
System.out.println("External configuration file 'configs/settings.yml' does not exist. Using default configuration and environment configuration instead.");
|
||||
}
|
||||
app.run(args);
|
||||
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
|
||||
@@ -1,42 +1,54 @@
|
||||
package stirling.software.SPDF.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class AppConfig {
|
||||
@Bean(name = "appName")
|
||||
public String appName() {
|
||||
String appName = System.getProperty("APP_HOME_NAME");
|
||||
if (appName == null)
|
||||
appName = System.getenv("APP_HOME_NAME");
|
||||
return (appName != null) ? appName : "Stirling PDF";
|
||||
}
|
||||
|
||||
@Bean(name = "appVersion")
|
||||
public String appVersion() {
|
||||
String version = getClass().getPackage().getImplementationVersion();
|
||||
return (version != null) ? version : "0.0.0";
|
||||
}
|
||||
|
||||
@Bean(name = "homeText")
|
||||
public String homeText() {
|
||||
String homeText = System.getProperty("APP_HOME_DESCRIPTION");
|
||||
if (homeText == null)
|
||||
homeText = System.getenv("APP_HOME_DESCRIPTION");
|
||||
return (homeText != null) ? homeText : "null";
|
||||
}
|
||||
|
||||
@Bean(name = "navBarText")
|
||||
public String navBarText() {
|
||||
String navBarText = System.getProperty("APP_NAVBAR_NAME");
|
||||
if (navBarText == null)
|
||||
navBarText = System.getenv("APP_NAVBAR_NAME");
|
||||
if (navBarText == null)
|
||||
navBarText = System.getProperty("APP_HOME_NAME");
|
||||
if (navBarText == null)
|
||||
navBarText = System.getenv("APP_HOME_NAME");
|
||||
|
||||
return (navBarText != null) ? navBarText : "Stirling PDF";
|
||||
}
|
||||
package stirling.software.SPDF.config;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import stirling.software.SPDF.model.ApplicationProperties;
|
||||
@Configuration
|
||||
public class AppConfig {
|
||||
|
||||
@Autowired
|
||||
ApplicationProperties applicationProperties;
|
||||
|
||||
@Bean(name = "loginEnabled")
|
||||
public boolean loginEnabled() {
|
||||
System.out.println(applicationProperties.toString());
|
||||
return applicationProperties.getSecurity().getEnableLogin();
|
||||
}
|
||||
|
||||
@Bean(name = "appName")
|
||||
public String appName() {
|
||||
String homeTitle = applicationProperties.getUi().getAppName();
|
||||
return (homeTitle != null) ? homeTitle : "Stirling PDF";
|
||||
}
|
||||
|
||||
@Bean(name = "appVersion")
|
||||
public String appVersion() {
|
||||
String version = getClass().getPackage().getImplementationVersion();
|
||||
return (version != null) ? version : "0.0.0";
|
||||
}
|
||||
|
||||
@Bean(name = "homeText")
|
||||
public String homeText() {
|
||||
return (applicationProperties.getUi().getHomeDescription() != null) ? applicationProperties.getUi().getHomeDescription() : "null";
|
||||
}
|
||||
|
||||
|
||||
@Bean(name = "navBarText")
|
||||
public String navBarText() {
|
||||
String defaultNavBar = applicationProperties.getUi().getAppNameNavbar() != null ? applicationProperties.getUi().getAppNameNavbar() : applicationProperties.getUi().getAppName();
|
||||
return (defaultNavBar != null) ? defaultNavBar : "Stirling PDF";
|
||||
}
|
||||
|
||||
@Bean(name = "rateLimit")
|
||||
public boolean rateLimit() {
|
||||
String appName = System.getProperty("rateLimit");
|
||||
if (appName == null)
|
||||
appName = System.getenv("rateLimit");
|
||||
System.out.println("rateLimit=" + appName);
|
||||
return (appName != null) ? Boolean.valueOf(appName) : false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package stirling.software.SPDF.config;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.LocaleResolver;
|
||||
@@ -10,9 +11,14 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
|
||||
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
|
||||
|
||||
import stirling.software.SPDF.model.ApplicationProperties;
|
||||
|
||||
@Configuration
|
||||
public class Beans implements WebMvcConfigurer {
|
||||
|
||||
|
||||
@Autowired
|
||||
ApplicationProperties applicationProperties;
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
registry.addInterceptor(localeChangeInterceptor());
|
||||
@@ -29,10 +35,9 @@ public class Beans implements WebMvcConfigurer {
|
||||
@Bean
|
||||
public LocaleResolver localeResolver() {
|
||||
SessionLocaleResolver slr = new SessionLocaleResolver();
|
||||
|
||||
String appLocaleEnv = System.getProperty("APP_LOCALE");
|
||||
if (appLocaleEnv == null)
|
||||
appLocaleEnv = System.getenv("APP_LOCALE");
|
||||
|
||||
|
||||
String appLocaleEnv = applicationProperties.getSystem().getDefaultLocale();
|
||||
Locale defaultLocale = Locale.UK; // Fallback to UK locale if environment variable is not set
|
||||
|
||||
if (appLocaleEnv != null && !appLocaleEnv.isEmpty()) {
|
||||
|
||||
@@ -1,79 +1,70 @@
|
||||
package stirling.software.SPDF.config;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
public class CleanUrlInterceptor implements HandlerInterceptor {
|
||||
|
||||
private static final List<String> ALLOWED_PARAMS = Arrays.asList("lang", "endpoint", "endpoints");
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
|
||||
throws Exception {
|
||||
String queryString = request.getQueryString();
|
||||
if (queryString != null && !queryString.isEmpty()) {
|
||||
String requestURI = request.getRequestURI();
|
||||
|
||||
Map<String, String> parameters = new HashMap<>();
|
||||
|
||||
// Keep only the allowed parameters
|
||||
String[] queryParameters = queryString.split("&");
|
||||
for (String param : queryParameters) {
|
||||
String[] keyValue = param.split("=");
|
||||
if (keyValue.length != 2) {
|
||||
continue;
|
||||
}
|
||||
if (ALLOWED_PARAMS.contains(keyValue[0])) {
|
||||
parameters.put(keyValue[0], keyValue[1]);
|
||||
}
|
||||
}
|
||||
|
||||
// If there are any parameters that are not allowed
|
||||
if (parameters.size() != queryParameters.length) {
|
||||
// Construct new query string
|
||||
StringBuilder newQueryString = new StringBuilder();
|
||||
for (Map.Entry<String, String> entry : parameters.entrySet()) {
|
||||
if (newQueryString.length() > 0) {
|
||||
newQueryString.append("&");
|
||||
}
|
||||
newQueryString.append(entry.getKey()).append("=").append(entry.getValue());
|
||||
}
|
||||
|
||||
// Redirect to the URL with only allowed query parameters
|
||||
String redirectUrl = requestURI + "?" + newQueryString;
|
||||
response.sendRedirect(redirectUrl);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
|
||||
ModelAndView modelAndView) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
|
||||
Exception ex) {
|
||||
}
|
||||
}
|
||||
package stirling.software.SPDF.config;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
public class CleanUrlInterceptor implements HandlerInterceptor {
|
||||
|
||||
private static final List<String> ALLOWED_PARAMS = Arrays.asList("lang", "endpoint", "endpoints", "logout", "error", "file");
|
||||
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
|
||||
throws Exception {
|
||||
String queryString = request.getQueryString();
|
||||
if (queryString != null && !queryString.isEmpty()) {
|
||||
String requestURI = request.getRequestURI();
|
||||
|
||||
Map<String, String> parameters = new HashMap<>();
|
||||
|
||||
// Keep only the allowed parameters
|
||||
String[] queryParameters = queryString.split("&");
|
||||
for (String param : queryParameters) {
|
||||
String[] keyValue = param.split("=");
|
||||
if (keyValue.length != 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ALLOWED_PARAMS.contains(keyValue[0])) {
|
||||
parameters.put(keyValue[0], keyValue[1]);
|
||||
}
|
||||
}
|
||||
|
||||
// If there are any parameters that are not allowed
|
||||
if (parameters.size() != queryParameters.length) {
|
||||
// Construct new query string
|
||||
StringBuilder newQueryString = new StringBuilder();
|
||||
for (Map.Entry<String, String> entry : parameters.entrySet()) {
|
||||
if (newQueryString.length() > 0) {
|
||||
newQueryString.append("&");
|
||||
}
|
||||
newQueryString.append(entry.getKey()).append("=").append(entry.getValue());
|
||||
}
|
||||
|
||||
// Redirect to the URL with only allowed query parameters
|
||||
String redirectUrl = requestURI + "?" + newQueryString;
|
||||
response.sendRedirect(redirectUrl);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
|
||||
ModelAndView modelAndView) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
|
||||
Exception ex) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package stirling.software.SPDF.config;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import org.springframework.context.ApplicationContextInitializer;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
|
||||
public class ConfigInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
|
||||
|
||||
@Override
|
||||
public void initialize(ConfigurableApplicationContext applicationContext) {
|
||||
try {
|
||||
ensureConfigExists();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Failed to initialize application configuration", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void ensureConfigExists() throws IOException {
|
||||
// Define the path to the external config directory
|
||||
Path destPath = Paths.get("configs", "settings.yml");
|
||||
|
||||
// Check if the file already exists
|
||||
if (Files.notExists(destPath)) {
|
||||
// Ensure the destination directory exists
|
||||
Files.createDirectories(destPath.getParent());
|
||||
|
||||
// Copy the resource from classpath to the external directory
|
||||
try (InputStream in = getClass().getClassLoader().getResourceAsStream("settings.yml.template")) {
|
||||
if (in != null) {
|
||||
Files.copy(in, destPath);
|
||||
} else {
|
||||
throw new FileNotFoundException("Resource file not found: settings.yml.template");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,20 +1,28 @@
|
||||
package stirling.software.SPDF.config;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import stirling.software.SPDF.model.ApplicationProperties;
|
||||
@Service
|
||||
public class EndpointConfiguration {
|
||||
private static final Logger logger = LoggerFactory.getLogger(EndpointConfiguration.class);
|
||||
private Map<String, Boolean> endpointStatuses = new ConcurrentHashMap<>();
|
||||
private Map<String, Set<String>> endpointGroups = new ConcurrentHashMap<>();
|
||||
|
||||
public EndpointConfiguration() {
|
||||
private final ApplicationProperties applicationProperties;
|
||||
|
||||
@Autowired
|
||||
public EndpointConfiguration(ApplicationProperties applicationProperties) {
|
||||
this.applicationProperties = applicationProperties;
|
||||
init();
|
||||
processEnvironmentConfigs();
|
||||
}
|
||||
@@ -71,6 +79,8 @@ public class EndpointConfiguration {
|
||||
addEndpointToGroup("PageOps", "adjust-contrast");
|
||||
addEndpointToGroup("PageOps", "crop");
|
||||
addEndpointToGroup("PageOps", "auto-split-pdf");
|
||||
addEndpointToGroup("PageOps", "extract-page");
|
||||
addEndpointToGroup("PageOps", "pdf-to-single-page");
|
||||
|
||||
// Adding endpoints to "Convert" group
|
||||
addEndpointToGroup("Convert", "pdf-to-img");
|
||||
@@ -85,6 +95,7 @@ public class EndpointConfiguration {
|
||||
addEndpointToGroup("Convert", "pdf-to-xml");
|
||||
addEndpointToGroup("Convert", "html-to-pdf");
|
||||
addEndpointToGroup("Convert", "url-to-pdf");
|
||||
addEndpointToGroup("Convert", "markdown-to-pdf");
|
||||
|
||||
// Adding endpoints to "Security" group
|
||||
addEndpointToGroup("Security", "add-password");
|
||||
@@ -94,7 +105,7 @@ public class EndpointConfiguration {
|
||||
addEndpointToGroup("Security", "cert-sign");
|
||||
addEndpointToGroup("Security", "sanitize-pdf");
|
||||
|
||||
|
||||
|
||||
// Adding endpoints to "Other" group
|
||||
addEndpointToGroup("Other", "ocr-pdf");
|
||||
addEndpointToGroup("Other", "add-image");
|
||||
@@ -109,7 +120,8 @@ public class EndpointConfiguration {
|
||||
addEndpointToGroup("Other", "compare");
|
||||
addEndpointToGroup("Other", "add-page-numbers");
|
||||
addEndpointToGroup("Other", "auto-rename");
|
||||
|
||||
addEndpointToGroup("Other", "get-info-on-pdf");
|
||||
addEndpointToGroup("Other", "show-javascript");
|
||||
|
||||
|
||||
|
||||
@@ -180,6 +192,11 @@ public class EndpointConfiguration {
|
||||
addEndpointToGroup("Java", "auto-split-pdf");
|
||||
addEndpointToGroup("Java", "sanitize-pdf");
|
||||
addEndpointToGroup("Java", "crop");
|
||||
addEndpointToGroup("Java", "get-info-on-pdf");
|
||||
addEndpointToGroup("Java", "extract-page");
|
||||
addEndpointToGroup("Java", "pdf-to-single-page");
|
||||
addEndpointToGroup("Java", "markdown-to-pdf");
|
||||
addEndpointToGroup("Java", "show-javascript");
|
||||
|
||||
//Javascript
|
||||
addEndpointToGroup("Javascript", "pdf-organizer");
|
||||
@@ -189,21 +206,19 @@ public class EndpointConfiguration {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void processEnvironmentConfigs() {
|
||||
String endpointsToRemove = System.getenv("ENDPOINTS_TO_REMOVE");
|
||||
String groupsToRemove = System.getenv("GROUPS_TO_REMOVE");
|
||||
List<String> endpointsToRemove = applicationProperties.getEndpoints().getToRemove();
|
||||
List<String> groupsToRemove = applicationProperties.getEndpoints().getGroupsToRemove();
|
||||
|
||||
if (endpointsToRemove != null) {
|
||||
String[] endpoints = endpointsToRemove.split(",");
|
||||
for (String endpoint : endpoints) {
|
||||
for (String endpoint : endpointsToRemove) {
|
||||
disableEndpoint(endpoint.trim());
|
||||
}
|
||||
}
|
||||
|
||||
if (groupsToRemove != null) {
|
||||
String[] groups = groupsToRemove.split(",");
|
||||
for (String group : groups) {
|
||||
for (String group : groupsToRemove) {
|
||||
disableGroup(group.trim());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
package stirling.software.SPDF.config;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
@Component
|
||||
public class EndpointInterceptor implements HandlerInterceptor {
|
||||
|
||||
@Autowired
|
||||
private EndpointConfiguration endpointConfiguration;
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
|
||||
throws Exception {
|
||||
String requestURI = request.getRequestURI();
|
||||
if (!endpointConfiguration.isEndpointEnabled(requestURI)) {
|
||||
response.sendError(HttpServletResponse.SC_FORBIDDEN, "This endpoint is disabled");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
package stirling.software.SPDF.config;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
@Component
|
||||
public class EndpointInterceptor implements HandlerInterceptor {
|
||||
|
||||
@Autowired
|
||||
private EndpointConfiguration endpointConfiguration;
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
|
||||
throws Exception {
|
||||
String requestURI = request.getRequestURI();
|
||||
if (!endpointConfiguration.isEndpointEnabled(requestURI)) {
|
||||
response.sendError(HttpServletResponse.SC_FORBIDDEN, "This endpoint is disabled");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,24 +1,24 @@
|
||||
package stirling.software.SPDF.config;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import io.micrometer.core.instrument.Meter;
|
||||
import io.micrometer.core.instrument.config.MeterFilter;
|
||||
import io.micrometer.core.instrument.config.MeterFilterReply;
|
||||
|
||||
@Configuration
|
||||
public class MetricsConfig {
|
||||
|
||||
@Bean
|
||||
public MeterFilter meterFilter() {
|
||||
return new MeterFilter() {
|
||||
@Override
|
||||
public MeterFilterReply accept(Meter.Id id) {
|
||||
if (id.getName().equals("http.requests")) {
|
||||
return MeterFilterReply.NEUTRAL;
|
||||
}
|
||||
return MeterFilterReply.DENY;
|
||||
}
|
||||
};
|
||||
}
|
||||
package stirling.software.SPDF.config;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import io.micrometer.core.instrument.Meter;
|
||||
import io.micrometer.core.instrument.config.MeterFilter;
|
||||
import io.micrometer.core.instrument.config.MeterFilterReply;
|
||||
|
||||
@Configuration
|
||||
public class MetricsConfig {
|
||||
|
||||
@Bean
|
||||
public MeterFilter meterFilter() {
|
||||
return new MeterFilter() {
|
||||
@Override
|
||||
public MeterFilterReply accept(Meter.Id id) {
|
||||
if (id.getName().equals("http.requests")) {
|
||||
return MeterFilterReply.NEUTRAL;
|
||||
}
|
||||
return MeterFilterReply.DENY;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,48 +1,48 @@
|
||||
package stirling.software.SPDF.config;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import io.micrometer.core.instrument.Counter;
|
||||
import io.micrometer.core.instrument.MeterRegistry;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
@Component
|
||||
public class MetricsFilter extends OncePerRequestFilter {
|
||||
|
||||
private final MeterRegistry meterRegistry;
|
||||
|
||||
@Autowired
|
||||
public MetricsFilter(MeterRegistry meterRegistry) {
|
||||
this.meterRegistry = meterRegistry;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
|
||||
throws ServletException, IOException {
|
||||
String uri = request.getRequestURI();
|
||||
|
||||
//System.out.println("uri="+uri + ", method=" + request.getMethod() );
|
||||
// Ignore static resources
|
||||
if (!(uri.startsWith("/js") || uri.startsWith("/images") || uri.endsWith(".ico") || uri.endsWith(".css") || uri.endsWith(".svg")|| uri.endsWith(".js") || uri.contains("swagger") || uri.startsWith("/api"))) {
|
||||
Counter counter = Counter.builder("http.requests")
|
||||
.tag("uri", uri)
|
||||
.tag("method", request.getMethod())
|
||||
.register(meterRegistry);
|
||||
|
||||
counter.increment();
|
||||
//System.out.println("Counted");
|
||||
}
|
||||
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
package stirling.software.SPDF.config;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import io.micrometer.core.instrument.Counter;
|
||||
import io.micrometer.core.instrument.MeterRegistry;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
@Component
|
||||
public class MetricsFilter extends OncePerRequestFilter {
|
||||
|
||||
private final MeterRegistry meterRegistry;
|
||||
|
||||
@Autowired
|
||||
public MetricsFilter(MeterRegistry meterRegistry) {
|
||||
this.meterRegistry = meterRegistry;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
|
||||
throws ServletException, IOException {
|
||||
String uri = request.getRequestURI();
|
||||
|
||||
//System.out.println("uri="+uri + ", method=" + request.getMethod() );
|
||||
// Ignore static resources
|
||||
if (!(uri.startsWith("/js") || uri.startsWith("api-docs") || uri.endsWith("robots.txt") || uri.startsWith("/images") || uri.endsWith(".png") || uri.endsWith(".ico") || uri.endsWith(".css") || uri.endsWith(".svg")|| uri.endsWith(".js") || uri.contains("swagger") || uri.startsWith("/api"))) {
|
||||
Counter counter = Counter.builder("http.requests")
|
||||
.tag("uri", uri)
|
||||
.tag("method", request.getMethod())
|
||||
.register(meterRegistry);
|
||||
|
||||
counter.increment();
|
||||
//System.out.println("Counted");
|
||||
}
|
||||
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,36 +1,36 @@
|
||||
package stirling.software.SPDF.config;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import io.swagger.v3.oas.models.Components;
|
||||
import io.swagger.v3.oas.models.OpenAPI;
|
||||
import io.swagger.v3.oas.models.info.Info;
|
||||
|
||||
@Configuration
|
||||
public class OpenApiConfig {
|
||||
|
||||
@Bean
|
||||
public OpenAPI customOpenAPI() {
|
||||
String version = getClass().getPackage().getImplementationVersion();
|
||||
if (version == null) {
|
||||
Properties props = new Properties();
|
||||
try (InputStream input = getClass().getClassLoader().getResourceAsStream("version.properties")) {
|
||||
props.load(input);
|
||||
version = props.getProperty("version");
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
version = "1.0.0"; // default version if all else fails
|
||||
}
|
||||
}
|
||||
|
||||
return new OpenAPI().components(new Components()).info(
|
||||
new Info().title("Stirling PDF API").version(version).description("API documentation for all Server-Side processing.\nPlease note some functionality might be UI only and missing from here."));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
package stirling.software.SPDF.config;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import io.swagger.v3.oas.models.Components;
|
||||
import io.swagger.v3.oas.models.OpenAPI;
|
||||
import io.swagger.v3.oas.models.info.Info;
|
||||
|
||||
@Configuration
|
||||
public class OpenApiConfig {
|
||||
|
||||
@Bean
|
||||
public OpenAPI customOpenAPI() {
|
||||
String version = getClass().getPackage().getImplementationVersion();
|
||||
if (version == null) {
|
||||
Properties props = new Properties();
|
||||
try (InputStream input = getClass().getClassLoader().getResourceAsStream("version.properties")) {
|
||||
props.load(input);
|
||||
version = props.getProperty("version");
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
version = "1.0.0"; // default version if all else fails
|
||||
}
|
||||
}
|
||||
|
||||
return new OpenAPI().components(new Components()).info(
|
||||
new Info().title("Stirling PDF API").version(version).description("API documentation for all Server-Side processing.\nPlease note some functionality might be UI only and missing from here."));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package stirling.software.SPDF.config;
|
||||
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class StartupApplicationListener implements ApplicationListener<ContextRefreshedEvent> {
|
||||
|
||||
public static LocalDateTime startTime;
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ContextRefreshedEvent event) {
|
||||
startTime = LocalDateTime.now();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
package stirling.software.SPDF.config;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
@Configuration
|
||||
public class WebMvcConfig implements WebMvcConfigurer {
|
||||
|
||||
@Autowired
|
||||
private EndpointInterceptor endpointInterceptor;
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
registry.addInterceptor(endpointInterceptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
// Handler for external static resources
|
||||
registry.addResourceHandler("/**")
|
||||
.addResourceLocations("file:customFiles/static/", "classpath:/static/")
|
||||
.setCachePeriod(0); // Optional: disable caching
|
||||
}
|
||||
}
|
||||
package stirling.software.SPDF.config;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
@Configuration
|
||||
public class WebMvcConfig implements WebMvcConfigurer {
|
||||
|
||||
@Autowired
|
||||
private EndpointInterceptor endpointInterceptor;
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
registry.addInterceptor(endpointInterceptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
// Handler for external static resources
|
||||
registry.addResourceHandler("/**")
|
||||
.addResourceLocations("file:customFiles/static/", "classpath:/static/");
|
||||
//.setCachePeriod(0); // Optional: disable caching
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package stirling.software.SPDF.config;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
|
||||
import org.springframework.core.env.PropertiesPropertySource;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.core.io.support.EncodedResource;
|
||||
import org.springframework.core.io.support.PropertySourceFactory;
|
||||
public class YamlPropertySourceFactory implements PropertySourceFactory {
|
||||
|
||||
@Override
|
||||
public PropertySource<?> createPropertySource(String name, EncodedResource encodedResource)
|
||||
throws IOException {
|
||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||
factory.setResources(encodedResource.getResource());
|
||||
|
||||
Properties properties = factory.getObject();
|
||||
|
||||
return new PropertiesPropertySource(encodedResource.getResource().getFilename(), properties);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package stirling.software.SPDF.config.security;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.security.authentication.LockedException;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
|
||||
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
public class CustomAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {
|
||||
|
||||
@Override
|
||||
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception)
|
||||
throws IOException, ServletException {
|
||||
if (exception.getClass().isAssignableFrom(BadCredentialsException.class)) {
|
||||
setDefaultFailureUrl("/login?error=badcredentials");
|
||||
} else if (exception.getClass().isAssignableFrom(LockedException.class)) {
|
||||
setDefaultFailureUrl("/login?error=locked");
|
||||
}
|
||||
super.onAuthenticationFailure(request, response, exception);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package stirling.software.SPDF.config.security;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import stirling.software.SPDF.model.Authority;
|
||||
import stirling.software.SPDF.model.User;
|
||||
import stirling.software.SPDF.repository.UserRepository;
|
||||
|
||||
@Service
|
||||
public class CustomUserDetailsService implements UserDetailsService {
|
||||
|
||||
@Autowired
|
||||
private UserRepository userRepository;
|
||||
|
||||
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
||||
User user = userRepository.findByUsername(username)
|
||||
.orElseThrow(() -> new UsernameNotFoundException("No user found with username: " + username));
|
||||
|
||||
return new org.springframework.security.core.userdetails.User(
|
||||
user.getUsername(),
|
||||
user.getPassword(),
|
||||
user.isEnabled(),
|
||||
true, true, true,
|
||||
getAuthorities(user.getAuthorities())
|
||||
);
|
||||
}
|
||||
|
||||
private Collection<? extends GrantedAuthority> getAuthorities(Set<Authority> authorities) {
|
||||
return authorities.stream()
|
||||
.map(authority -> new SimpleGrantedAuthority(authority.getAuthority()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package stirling.software.SPDF.config.security;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import stirling.software.SPDF.config.security.UserService;
|
||||
import stirling.software.SPDF.model.ApplicationProperties;
|
||||
import stirling.software.SPDF.model.Role;
|
||||
|
||||
@Component
|
||||
public class InitialSecuritySetup {
|
||||
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
@Autowired
|
||||
ApplicationProperties applicationProperties;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
if (!userService.hasUsers()) {
|
||||
String initialUsername = applicationProperties.getSecurity().getInitialLogin().getUsername();
|
||||
String initialPassword = applicationProperties.getSecurity().getInitialLogin().getPassword();
|
||||
if (initialUsername != null && initialPassword != null) {
|
||||
userService.saveUser(initialUsername, initialPassword, Role.ADMIN.getRoleId());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@PostConstruct
|
||||
public void initSecretKey() throws IOException {
|
||||
String secretKey = applicationProperties.getAutomaticallyGenerated().getKey();
|
||||
if (secretKey == null || secretKey.isEmpty()) {
|
||||
secretKey = UUID.randomUUID().toString(); // Generating a random UUID as the secret key
|
||||
saveKeyToConfig(secretKey);
|
||||
}
|
||||
}
|
||||
|
||||
private void saveKeyToConfig(String key) throws IOException {
|
||||
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
|
||||
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
|
||||
if (!keyFound) {
|
||||
lines.add("# Automatically Generated Settings (Do Not Edit Directly)");
|
||||
lines.add("AutomaticallyGenerated:");
|
||||
lines.add(" key: " + key);
|
||||
}
|
||||
|
||||
// Write back to the file
|
||||
Files.write(path, lines);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package stirling.software.SPDF.config.security;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
|
||||
import stirling.software.SPDF.repository.JPATokenRepositoryImpl;
|
||||
@Configuration
|
||||
@EnableWebSecurity()
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||
public class SecurityConfiguration {
|
||||
|
||||
@Autowired
|
||||
private UserDetailsService userDetailsService;
|
||||
|
||||
@Bean
|
||||
public PasswordEncoder passwordEncoder() {
|
||||
return new BCryptPasswordEncoder();
|
||||
}
|
||||
@Autowired
|
||||
@Lazy
|
||||
private UserService userService;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("loginEnabled")
|
||||
public boolean loginEnabledValue;
|
||||
|
||||
@Autowired
|
||||
private UserAuthenticationFilter userAuthenticationFilter;
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
http.addFilterBefore(userAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
|
||||
|
||||
if(loginEnabledValue) {
|
||||
|
||||
http.csrf(csrf -> csrf.disable());
|
||||
http
|
||||
.formLogin(formLogin -> formLogin
|
||||
.loginPage("/login")
|
||||
.defaultSuccessUrl("/")
|
||||
.failureHandler(new CustomAuthenticationFailureHandler())
|
||||
.permitAll()
|
||||
)
|
||||
.logout(logout -> logout
|
||||
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
|
||||
.logoutSuccessUrl("/login?logout=true")
|
||||
.invalidateHttpSession(true) // Invalidate session
|
||||
.deleteCookies("JSESSIONID", "remember-me")
|
||||
).rememberMe(rememberMeConfigurer -> rememberMeConfigurer // Use the configurator directly
|
||||
.key("uniqueAndSecret")
|
||||
.tokenRepository(persistentTokenRepository())
|
||||
.tokenValiditySeconds(1209600) // 2 weeks
|
||||
)
|
||||
.authorizeHttpRequests(authz -> authz
|
||||
.requestMatchers(req -> req.getRequestURI().startsWith("/login") || req.getRequestURI().endsWith(".svg") || req.getRequestURI().startsWith("/register") || req.getRequestURI().startsWith("/error") || req.getRequestURI().startsWith("/images/") || req.getRequestURI().startsWith("/public/") || req.getRequestURI().startsWith("/css/") || req.getRequestURI().startsWith("/js/"))
|
||||
.permitAll()
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
.userDetailsService(userDetailsService)
|
||||
.authenticationProvider(authenticationProvider());
|
||||
} else {
|
||||
http.csrf(csrf -> csrf.disable())
|
||||
.authorizeHttpRequests(authz -> authz
|
||||
.anyRequest().permitAll()
|
||||
);
|
||||
}
|
||||
return http.build();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Bean
|
||||
public DaoAuthenticationProvider authenticationProvider() {
|
||||
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
|
||||
authProvider.setUserDetailsService(userDetailsService);
|
||||
authProvider.setPasswordEncoder(passwordEncoder());
|
||||
return authProvider;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PersistentTokenRepository persistentTokenRepository() {
|
||||
return new JPATokenRepositoryImpl();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
package stirling.software.SPDF.config.security;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import stirling.software.SPDF.model.ApiKeyAuthenticationToken;
|
||||
@Component
|
||||
public class UserAuthenticationFilter extends OncePerRequestFilter {
|
||||
|
||||
@Autowired
|
||||
private UserDetailsService userDetailsService;
|
||||
|
||||
@Autowired
|
||||
@Lazy
|
||||
private UserService userService;
|
||||
|
||||
|
||||
@Autowired
|
||||
@Qualifier("loginEnabled")
|
||||
public boolean loginEnabledValue;
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
FilterChain filterChain) throws ServletException, IOException {
|
||||
|
||||
if (!loginEnabledValue) {
|
||||
// If login is not enabled, just pass all requests without authentication
|
||||
filterChain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
|
||||
// Check for API key in the request headers if no authentication exists
|
||||
if (authentication == null || !authentication.isAuthenticated()) {
|
||||
String apiKey = request.getHeader("X-API-Key");
|
||||
if (apiKey != null && !apiKey.trim().isEmpty()) {
|
||||
try {
|
||||
// Use API key to authenticate. This requires you to have an authentication provider for API keys.
|
||||
UserDetails userDetails = userService.loadUserByApiKey(apiKey);
|
||||
if(userDetails == null)
|
||||
{
|
||||
response.setStatus(HttpStatus.UNAUTHORIZED.value());
|
||||
response.getWriter().write("Invalid API Key.");
|
||||
return;
|
||||
}
|
||||
authentication = new ApiKeyAuthenticationToken(userDetails, apiKey, userDetails.getAuthorities());
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
} catch (AuthenticationException e) {
|
||||
// If API key authentication fails, deny the request
|
||||
response.setStatus(HttpStatus.UNAUTHORIZED.value());
|
||||
response.getWriter().write("Invalid API Key.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we still don't have any authentication, deny the request
|
||||
if (authentication == null || !authentication.isAuthenticated()) {
|
||||
String method = request.getMethod();
|
||||
if ("GET".equalsIgnoreCase(method)) {
|
||||
response.sendRedirect("/login"); // redirect to the login page
|
||||
return;
|
||||
}
|
||||
response.setStatus(HttpStatus.UNAUTHORIZED.value());
|
||||
response.getWriter().write("Authentication required. Please provide a X-API-KEY in request header.\nThis is found in Settings -> Account Settings -> API Key\nAlternativly you can disable authentication if this is unexpected");
|
||||
return;
|
||||
}
|
||||
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {
|
||||
String uri = request.getRequestURI();
|
||||
|
||||
String[] permitAllPatterns = {
|
||||
"/login",
|
||||
"/register",
|
||||
"/error",
|
||||
"/images/",
|
||||
"/public/",
|
||||
"/css/",
|
||||
"/js/"
|
||||
};
|
||||
|
||||
for (String pattern : permitAllPatterns) {
|
||||
if (uri.startsWith(pattern) || uri.endsWith(".svg")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
package stirling.software.SPDF.config.security;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.Duration;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import io.github.bucket4j.Bandwidth;
|
||||
import io.github.bucket4j.Bucket;
|
||||
import io.github.bucket4j.ConsumptionProbe;
|
||||
import io.github.bucket4j.Refill;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import stirling.software.SPDF.model.Role;
|
||||
@Component
|
||||
public class UserBasedRateLimitingFilter extends OncePerRequestFilter {
|
||||
|
||||
private final Map<String, Bucket> apiBuckets = new ConcurrentHashMap<>();
|
||||
private final Map<String, Bucket> webBuckets = new ConcurrentHashMap<>();
|
||||
|
||||
@Autowired
|
||||
private UserDetailsService userDetailsService;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("rateLimit")
|
||||
public boolean rateLimit;
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
FilterChain filterChain) throws ServletException, IOException {
|
||||
if (!rateLimit) {
|
||||
// If rateLimit is not enabled, just pass all requests without rate limiting
|
||||
filterChain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
String method = request.getMethod();
|
||||
if (!"POST".equalsIgnoreCase(method)) {
|
||||
// If the request is not a POST, just pass it through without rate limiting
|
||||
filterChain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
String identifier = null;
|
||||
|
||||
// Check for API key in the request headers
|
||||
String apiKey = request.getHeader("X-API-Key");
|
||||
if (apiKey != null && !apiKey.trim().isEmpty()) {
|
||||
identifier = "API_KEY_" + apiKey; // Prefix to distinguish between API keys and usernames
|
||||
} else {
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
if (authentication != null && authentication.isAuthenticated()) {
|
||||
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
|
||||
identifier = userDetails.getUsername();
|
||||
}
|
||||
}
|
||||
|
||||
// If neither API key nor an authenticated user is present, use IP address
|
||||
if (identifier == null) {
|
||||
identifier = request.getRemoteAddr();
|
||||
}
|
||||
|
||||
Role userRole = getRoleFromAuthentication(SecurityContextHolder.getContext().getAuthentication());
|
||||
|
||||
if (request.getHeader("X-API-Key") != null) {
|
||||
// It's an API call
|
||||
processRequest(userRole.getApiCallsPerDay(), identifier, apiBuckets, request, response, filterChain);
|
||||
} else {
|
||||
// It's a Web UI call
|
||||
processRequest(userRole.getWebCallsPerDay(), identifier, webBuckets, request, response, filterChain);
|
||||
}
|
||||
}
|
||||
|
||||
private Role getRoleFromAuthentication(Authentication authentication) {
|
||||
if (authentication != null && authentication.isAuthenticated()) {
|
||||
for (GrantedAuthority authority : authentication.getAuthorities()) {
|
||||
try {
|
||||
return Role.fromString(authority.getAuthority());
|
||||
} catch (IllegalArgumentException ex) {
|
||||
// Ignore and continue to next authority.
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new IllegalStateException("User does not have a valid role.");
|
||||
}
|
||||
|
||||
private void processRequest(int limitPerDay, String identifier, Map<String, Bucket> buckets,
|
||||
HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
|
||||
throws IOException, ServletException {
|
||||
Bucket userBucket = buckets.computeIfAbsent(identifier, k -> createUserBucket(limitPerDay));
|
||||
ConsumptionProbe probe = userBucket.tryConsumeAndReturnRemaining(1);
|
||||
|
||||
if (probe.isConsumed()) {
|
||||
response.setHeader("X-Rate-Limit-Remaining", Long.toString(probe.getRemainingTokens()));
|
||||
filterChain.doFilter(request, response);
|
||||
} else {
|
||||
long waitForRefill = probe.getNanosToWaitForRefill() / 1_000_000_000;
|
||||
response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value());
|
||||
response.setHeader("X-Rate-Limit-Retry-After-Seconds", String.valueOf(waitForRefill));
|
||||
response.getWriter().write("Rate limit exceeded for POST requests.");
|
||||
}
|
||||
}
|
||||
|
||||
private Bucket createUserBucket(int limitPerDay) {
|
||||
Bandwidth limit = Bandwidth.classic(limitPerDay, Refill.intervally(limitPerDay, Duration.ofDays(1)));
|
||||
return Bucket.builder().addLimit(limit).build();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
package stirling.software.SPDF.config.security;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import stirling.software.SPDF.model.Authority;
|
||||
import stirling.software.SPDF.model.User;
|
||||
import stirling.software.SPDF.repository.UserRepository;
|
||||
@Service
|
||||
public class UserService {
|
||||
|
||||
@Autowired
|
||||
private UserRepository userRepository;
|
||||
|
||||
@Autowired
|
||||
private PasswordEncoder passwordEncoder;
|
||||
|
||||
public Authentication getAuthentication(String apiKey) {
|
||||
User user = getUserByApiKey(apiKey);
|
||||
if (user == null) {
|
||||
throw new UsernameNotFoundException("API key is not valid");
|
||||
}
|
||||
|
||||
// Convert the user into an Authentication object
|
||||
return new UsernamePasswordAuthenticationToken(
|
||||
user, // principal (typically the user)
|
||||
null, // credentials (we don't expose the password or API key here)
|
||||
getAuthorities(user) // user's authorities (roles/permissions)
|
||||
);
|
||||
}
|
||||
|
||||
private Collection<? extends GrantedAuthority> getAuthorities(User user) {
|
||||
// Convert each Authority object into a SimpleGrantedAuthority object.
|
||||
return user.getAuthorities().stream()
|
||||
.map((Authority authority) -> new SimpleGrantedAuthority(authority.getAuthority()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
|
||||
}
|
||||
|
||||
private String generateApiKey() {
|
||||
String apiKey;
|
||||
do {
|
||||
apiKey = UUID.randomUUID().toString();
|
||||
} while (userRepository.findByApiKey(apiKey) != null); // Ensure uniqueness
|
||||
return apiKey;
|
||||
}
|
||||
|
||||
public User addApiKeyToUser(String username) {
|
||||
User user = userRepository.findByUsername(username)
|
||||
.orElseThrow(() -> new UsernameNotFoundException("User not found"));
|
||||
|
||||
user.setApiKey(generateApiKey());
|
||||
return userRepository.save(user);
|
||||
}
|
||||
|
||||
public User refreshApiKeyForUser(String username) {
|
||||
return addApiKeyToUser(username); // reuse the add API key method for refreshing
|
||||
}
|
||||
|
||||
public String getApiKeyForUser(String username) {
|
||||
User user = userRepository.findByUsername(username)
|
||||
.orElseThrow(() -> new UsernameNotFoundException("User not found"));
|
||||
return user.getApiKey();
|
||||
}
|
||||
|
||||
public boolean isValidApiKey(String apiKey) {
|
||||
return userRepository.findByApiKey(apiKey) != null;
|
||||
}
|
||||
|
||||
public User getUserByApiKey(String apiKey) {
|
||||
return userRepository.findByApiKey(apiKey);
|
||||
}
|
||||
|
||||
public UserDetails loadUserByApiKey(String apiKey) {
|
||||
User userOptional = userRepository.findByApiKey(apiKey);
|
||||
if (userOptional != null) {
|
||||
User user = userOptional;
|
||||
// Convert your User entity to a UserDetails object with authorities
|
||||
return new org.springframework.security.core.userdetails.User(
|
||||
user.getUsername(),
|
||||
user.getPassword(), // you might not need this for API key auth
|
||||
getAuthorities(user)
|
||||
);
|
||||
}
|
||||
return null; // or throw an exception
|
||||
}
|
||||
|
||||
|
||||
public boolean validateApiKeyForUser(String username, String apiKey) {
|
||||
Optional<User> userOpt = userRepository.findByUsername(username);
|
||||
return userOpt.isPresent() && userOpt.get().getApiKey().equals(apiKey);
|
||||
}
|
||||
|
||||
public void saveUser(String username, String password) {
|
||||
User user = new User();
|
||||
user.setUsername(username);
|
||||
user.setPassword(passwordEncoder.encode(password));
|
||||
user.setEnabled(true);
|
||||
userRepository.save(user);
|
||||
}
|
||||
|
||||
public void saveUser(String username, String password, String role) {
|
||||
User user = new User();
|
||||
user.setUsername(username);
|
||||
user.setPassword(passwordEncoder.encode(password));
|
||||
user.addAuthority(new Authority(role, user));
|
||||
user.setEnabled(true);
|
||||
userRepository.save(user);
|
||||
}
|
||||
|
||||
public void deleteUser(String username) {
|
||||
Optional<User> userOpt = userRepository.findByUsername(username);
|
||||
if (userOpt.isPresent()) {
|
||||
userRepository.delete(userOpt.get());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean usernameExists(String username) {
|
||||
return userRepository.findByUsername(username).isPresent();
|
||||
}
|
||||
|
||||
public boolean hasUsers() {
|
||||
return userRepository.count() > 0;
|
||||
}
|
||||
|
||||
public void updateUserSettings(String username, Map<String, String> updates) {
|
||||
Optional<User> userOpt = userRepository.findByUsername(username);
|
||||
if (userOpt.isPresent()) {
|
||||
User user = userOpt.get();
|
||||
Map<String, String> settingsMap = user.getSettings();
|
||||
|
||||
if(settingsMap == null) {
|
||||
settingsMap = new HashMap<String,String>();
|
||||
}
|
||||
settingsMap.clear();
|
||||
settingsMap.putAll(updates);
|
||||
user.setSettings(settingsMap);
|
||||
|
||||
userRepository.save(user);
|
||||
}
|
||||
}
|
||||
|
||||
public Optional<User> findByUsername(String username) {
|
||||
return userRepository.findByUsername(username);
|
||||
}
|
||||
|
||||
public void changeUsername(User user, String newUsername) {
|
||||
user.setUsername(newUsername);
|
||||
userRepository.save(user);
|
||||
}
|
||||
|
||||
public void changePassword(User user, String newPassword) {
|
||||
user.setPassword(passwordEncoder.encode(newPassword));
|
||||
userRepository.save(user);
|
||||
}
|
||||
|
||||
public boolean isPasswordCorrect(User user, String currentPassword) {
|
||||
return passwordEncoder.matches(currentPassword, user.getPassword());
|
||||
}
|
||||
}
|
||||
@@ -1,58 +1,11 @@
|
||||
package stirling.software.SPDF.controller.api;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.PDPage;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RequestPart;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import stirling.software.SPDF.utils.GeneralUtils;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
@@ -60,20 +13,13 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import com.itextpdf.kernel.geom.PageSize;
|
||||
import com.itextpdf.kernel.geom.Rectangle;
|
||||
import com.itextpdf.kernel.pdf.PdfDocument;
|
||||
import com.itextpdf.kernel.pdf.PdfPage;
|
||||
import com.itextpdf.kernel.pdf.PdfReader;
|
||||
import com.itextpdf.kernel.pdf.PdfWriter;
|
||||
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
|
||||
import com.itextpdf.kernel.pdf.canvas.parser.EventType;
|
||||
import com.itextpdf.kernel.pdf.canvas.parser.PdfCanvasProcessor;
|
||||
import com.itextpdf.kernel.pdf.canvas.parser.data.IEventData;
|
||||
import com.itextpdf.kernel.pdf.canvas.parser.data.TextRenderInfo;
|
||||
import com.itextpdf.kernel.pdf.canvas.parser.listener.IEventListener;
|
||||
import com.itextpdf.kernel.pdf.xobject.PdfFormXObject;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Hidden;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
@@ -1,22 +1,29 @@
|
||||
package stirling.software.SPDF.controller.api;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.PDPage;
|
||||
import org.apache.pdfbox.pdmodel.PDPageTree;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RequestPart;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
|
||||
@@ -26,55 +33,93 @@ public class MergeController {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(MergeController.class);
|
||||
|
||||
private PDDocument mergeDocuments(List<PDDocument> documents) throws IOException {
|
||||
// Create a new empty document
|
||||
PDDocument mergedDoc = new PDDocument();
|
||||
|
||||
// Iterate over the list of documents and add their pages to the merged document
|
||||
for (PDDocument doc : documents) {
|
||||
// Get all pages from the current document
|
||||
PDPageTree pages = doc.getPages();
|
||||
// Iterate over the pages and add them to the merged document
|
||||
for (PDPage page : pages) {
|
||||
mergedDoc.addPage(page);
|
||||
}
|
||||
|
||||
|
||||
private PDDocument mergeDocuments(List<PDDocument> documents) throws IOException {
|
||||
PDDocument mergedDoc = new PDDocument();
|
||||
for (PDDocument doc : documents) {
|
||||
for (PDPage page : doc.getPages()) {
|
||||
mergedDoc.addPage(page);
|
||||
}
|
||||
}
|
||||
return mergedDoc;
|
||||
}
|
||||
|
||||
// Return the merged document
|
||||
return mergedDoc;
|
||||
private Comparator<MultipartFile> getSortComparator(String sortType) {
|
||||
switch (sortType) {
|
||||
case "byFileName":
|
||||
return Comparator.comparing(MultipartFile::getOriginalFilename);
|
||||
case "byDateModified":
|
||||
return (file1, file2) -> {
|
||||
try {
|
||||
BasicFileAttributes attr1 = Files.readAttributes(Paths.get(file1.getOriginalFilename()), BasicFileAttributes.class);
|
||||
BasicFileAttributes attr2 = Files.readAttributes(Paths.get(file2.getOriginalFilename()), BasicFileAttributes.class);
|
||||
return attr1.lastModifiedTime().compareTo(attr2.lastModifiedTime());
|
||||
} catch (IOException e) {
|
||||
return 0; // If there's an error, treat them as equal
|
||||
}
|
||||
};
|
||||
case "byDateCreated":
|
||||
return (file1, file2) -> {
|
||||
try {
|
||||
BasicFileAttributes attr1 = Files.readAttributes(Paths.get(file1.getOriginalFilename()), BasicFileAttributes.class);
|
||||
BasicFileAttributes attr2 = Files.readAttributes(Paths.get(file2.getOriginalFilename()), BasicFileAttributes.class);
|
||||
return attr1.creationTime().compareTo(attr2.creationTime());
|
||||
} catch (IOException e) {
|
||||
return 0; // If there's an error, treat them as equal
|
||||
}
|
||||
};
|
||||
case "byPDFTitle":
|
||||
return (file1, file2) -> {
|
||||
try (PDDocument doc1 = PDDocument.load(file1.getInputStream());
|
||||
PDDocument doc2 = PDDocument.load(file2.getInputStream())) {
|
||||
String title1 = doc1.getDocumentInformation().getTitle();
|
||||
String title2 = doc2.getDocumentInformation().getTitle();
|
||||
return title1.compareTo(title2);
|
||||
} catch (IOException e) {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
case "orderProvided":
|
||||
default:
|
||||
return (file1, file2) -> 0; // Default is the order provided
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/merge-pdfs")
|
||||
@Operation(summary = "Merge multiple PDF files into one",
|
||||
description = "This endpoint merges multiple PDF files into a single PDF file. The merged file will contain all pages from the input files in the order they were provided. Input:PDF Output:PDF Type:MISO")
|
||||
public ResponseEntity<byte[]> mergePdfs(
|
||||
@RequestPart(required = true, value = "fileInput") MultipartFile[] files,
|
||||
@RequestParam(value = "sortType", defaultValue = "orderProvided")
|
||||
@Parameter(schema = @Schema(description = "The type of sorting to be applied on the input files before merging.",
|
||||
allowableValues = {
|
||||
"orderProvided",
|
||||
"byFileName",
|
||||
"byDateModified",
|
||||
"byDateCreated",
|
||||
"byPDFTitle"
|
||||
}))
|
||||
String sortType) throws IOException {
|
||||
|
||||
Arrays.sort(files, getSortComparator(sortType));
|
||||
|
||||
List<PDDocument> documents = new ArrayList<>();
|
||||
for (MultipartFile file : files) {
|
||||
try (InputStream is = file.getInputStream()) {
|
||||
documents.add(PDDocument.load(is));
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/merge-pdfs")
|
||||
@Operation(
|
||||
summary = "Merge multiple PDF files into one",
|
||||
description = "This endpoint merges multiple PDF files into a single PDF file. The merged file will contain all pages from the input files in the order they were provided. Input:PDF Output:PDF Type:MISO"
|
||||
)
|
||||
public ResponseEntity<byte[]> mergePdfs(
|
||||
@RequestPart(required = true, value = "fileInput")
|
||||
@Parameter(description = "The input PDF files to be merged into a single file", required = true)
|
||||
MultipartFile[] files) throws IOException {
|
||||
// Read the input PDF files into PDDocument objects
|
||||
List<PDDocument> documents = new ArrayList<>();
|
||||
|
||||
// Loop through the files array and read each file into a PDDocument
|
||||
for (MultipartFile file : files) {
|
||||
documents.add(PDDocument.load(file.getInputStream()));
|
||||
}
|
||||
|
||||
PDDocument mergedDoc = mergeDocuments(documents);
|
||||
|
||||
|
||||
// Return the merged PDF as a response
|
||||
try (PDDocument mergedDoc = mergeDocuments(documents)) {
|
||||
ResponseEntity<byte[]> response = WebResponseUtils.pdfDocToWebResponse(mergedDoc, files[0].getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_merged.pdf");
|
||||
|
||||
for (PDDocument doc : documents) {
|
||||
// Close the document after processing
|
||||
doc.close();
|
||||
}
|
||||
|
||||
return response;
|
||||
} finally {
|
||||
for (PDDocument doc : documents) {
|
||||
if (doc != null) {
|
||||
doc.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package stirling.software.SPDF.controller.api;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestPart;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import com.itextpdf.kernel.geom.PageSize;
|
||||
import com.itextpdf.kernel.geom.Rectangle;
|
||||
import com.itextpdf.kernel.pdf.PdfDocument;
|
||||
import com.itextpdf.kernel.pdf.PdfReader;
|
||||
import com.itextpdf.kernel.pdf.PdfWriter;
|
||||
import com.itextpdf.kernel.pdf.xobject.PdfFormXObject;
|
||||
import com.itextpdf.layout.Document;
|
||||
import com.itextpdf.layout.element.Image;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
@RestController
|
||||
@Tag(name = "General", description = "General APIs")
|
||||
public class ToSinglePageController {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ToSinglePageController.class);
|
||||
|
||||
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/pdf-to-single-page")
|
||||
@Operation(
|
||||
summary = "Convert a multi-page PDF into a single long page PDF",
|
||||
description = "This endpoint converts a multi-page PDF document into a single paged PDF document. The width of the single page will be same as the input's width, but the height will be the sum of all the pages' heights. Input:PDF Output:PDF Type:SISO"
|
||||
)
|
||||
public ResponseEntity<byte[]> pdfToSinglePage(
|
||||
@RequestPart(required = true, value = "fileInput")
|
||||
@Parameter(description = "The input multi-page PDF file to be converted into a single page", required = true)
|
||||
MultipartFile file) throws IOException {
|
||||
|
||||
PdfReader reader = new PdfReader(file.getInputStream());
|
||||
PdfDocument sourceDocument = new PdfDocument(reader);
|
||||
|
||||
float totalHeight = 0;
|
||||
float width = 0;
|
||||
|
||||
for (int i = 1; i <= sourceDocument.getNumberOfPages(); i++) {
|
||||
Rectangle pageSize = sourceDocument.getPage(i).getPageSize();
|
||||
totalHeight += pageSize.getHeight();
|
||||
if(width < pageSize.getWidth())
|
||||
width = pageSize.getWidth();
|
||||
}
|
||||
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
PdfWriter writer = new PdfWriter(baos);
|
||||
PdfDocument newDocument = new PdfDocument(writer);
|
||||
PageSize newPageSize = new PageSize(width, totalHeight);
|
||||
newDocument.addNewPage(newPageSize);
|
||||
|
||||
Document layoutDoc = new Document(newDocument);
|
||||
float yOffset = totalHeight;
|
||||
|
||||
for (int i = 1; i <= sourceDocument.getNumberOfPages(); i++) {
|
||||
PdfFormXObject pageCopy = sourceDocument.getPage(i).copyAsFormXObject(newDocument);
|
||||
Image copiedPage = new Image(pageCopy);
|
||||
copiedPage.setFixedPosition(0, yOffset - sourceDocument.getPage(i).getPageSize().getHeight());
|
||||
yOffset -= sourceDocument.getPage(i).getPageSize().getHeight();
|
||||
layoutDoc.add(copiedPage);
|
||||
}
|
||||
|
||||
layoutDoc.close();
|
||||
sourceDocument.close();
|
||||
|
||||
byte[] result = baos.toByteArray();
|
||||
return WebResponseUtils.bytesToWebResponse(result, file.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_singlePage.pdf");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
package stirling.software.SPDF.controller.api;
|
||||
|
||||
import java.security.Principal;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
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.RequestParam;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import stirling.software.SPDF.config.security.UserService;
|
||||
import stirling.software.SPDF.model.User;
|
||||
|
||||
@Controller
|
||||
public class UserController {
|
||||
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
@PostMapping("/register")
|
||||
public String register(@RequestParam String username, @RequestParam String password, Model model) {
|
||||
if(userService.usernameExists(username)) {
|
||||
model.addAttribute("error", "Username already exists");
|
||||
return "register";
|
||||
}
|
||||
|
||||
userService.saveUser(username, password);
|
||||
return "redirect:/login?registered=true";
|
||||
}
|
||||
|
||||
@PostMapping("/change-username")
|
||||
public ResponseEntity<String> changeUsername(Principal principal, @RequestParam String currentPassword, @RequestParam String newUsername, HttpServletRequest request, HttpServletResponse response) {
|
||||
if (principal == null) {
|
||||
return ResponseEntity.status(HttpStatus.FORBIDDEN).body("User not authenticated.");
|
||||
}
|
||||
|
||||
Optional<User> userOpt = userService.findByUsername(principal.getName());
|
||||
|
||||
if(userOpt == null || userOpt.isEmpty()) {
|
||||
return ResponseEntity.status(HttpStatus.NOT_FOUND).body("User not found.");
|
||||
}
|
||||
User user = userOpt.get();
|
||||
|
||||
if(!userService.isPasswordCorrect(user, currentPassword)) {
|
||||
return ResponseEntity.status(HttpStatus.FORBIDDEN).body("Current password is incorrect.");
|
||||
}
|
||||
|
||||
if(userService.usernameExists(newUsername)) {
|
||||
return ResponseEntity.status(HttpStatus.CONFLICT).body("New username already exists.");
|
||||
}
|
||||
|
||||
userService.changeUsername(user, newUsername);
|
||||
|
||||
// Logout using Spring's utility
|
||||
new SecurityContextLogoutHandler().logout(request, response, null);
|
||||
|
||||
|
||||
return ResponseEntity.ok("Username updated successfully.");
|
||||
}
|
||||
|
||||
@PostMapping("/change-password")
|
||||
public ResponseEntity<String> changePassword(Principal principal, @RequestParam String currentPassword, @RequestParam String newPassword, HttpServletRequest request, HttpServletResponse response) {
|
||||
if (principal == null) {
|
||||
return ResponseEntity.status(HttpStatus.FORBIDDEN).body("User not authenticated.");
|
||||
}
|
||||
|
||||
Optional<User> userOpt = userService.findByUsername(principal.getName());
|
||||
|
||||
if(userOpt == null || userOpt.isEmpty()) {
|
||||
return ResponseEntity.status(HttpStatus.NOT_FOUND).body("User not found.");
|
||||
}
|
||||
User user = userOpt.get();
|
||||
if(!userService.isPasswordCorrect(user, currentPassword)) {
|
||||
return ResponseEntity.status(HttpStatus.FORBIDDEN).body("Current password is incorrect.");
|
||||
}
|
||||
|
||||
userService.changePassword(user, newPassword);
|
||||
|
||||
// Logout using Spring's utility
|
||||
new SecurityContextLogoutHandler().logout(request, response, null);
|
||||
|
||||
return ResponseEntity.ok("Password updated successfully.");
|
||||
}
|
||||
|
||||
@PostMapping("/updateUserSettings")
|
||||
public String updateUserSettings(HttpServletRequest request, Principal principal) {
|
||||
Map<String, String[]> paramMap = request.getParameterMap();
|
||||
Map<String, String> updates = new HashMap<>();
|
||||
|
||||
System.out.println("Received parameter map: " + paramMap);
|
||||
|
||||
for (Map.Entry<String, String[]> entry : paramMap.entrySet()) {
|
||||
updates.put(entry.getKey(), entry.getValue()[0]);
|
||||
}
|
||||
|
||||
System.out.println("Processed updates: " + updates);
|
||||
|
||||
// Assuming you have a method in userService to update the settings for a user
|
||||
userService.updateUserSettings(principal.getName(), updates);
|
||||
|
||||
return "redirect:/account"; // Redirect to a page of your choice after updating
|
||||
}
|
||||
|
||||
@PreAuthorize("hasRole('ROLE_ADMIN')")
|
||||
@PostMapping("/admin/saveUser")
|
||||
public String saveUser(@RequestParam String username, @RequestParam String password, @RequestParam String role) {
|
||||
userService.saveUser(username, password, role);
|
||||
return "redirect:/addUsers"; // Redirect to account page after adding the user
|
||||
}
|
||||
|
||||
|
||||
@PreAuthorize("hasRole('ROLE_ADMIN')")
|
||||
@PostMapping("/admin/deleteUser/{username}")
|
||||
public String deleteUser(@PathVariable String username, Authentication authentication) {
|
||||
|
||||
// Get the currently authenticated username
|
||||
String currentUsername = authentication.getName();
|
||||
|
||||
// Check if the provided username matches the current session's username
|
||||
if (currentUsername.equals(username)) {
|
||||
throw new IllegalArgumentException("Cannot delete currently logined in user.");
|
||||
}
|
||||
|
||||
userService.deleteUser(username);
|
||||
return "redirect:/addUsers";
|
||||
}
|
||||
|
||||
@PostMapping("/get-api-key")
|
||||
public ResponseEntity<String> getApiKey(Principal principal) {
|
||||
if (principal == null) {
|
||||
return ResponseEntity.status(HttpStatus.FORBIDDEN).body("User not authenticated.");
|
||||
}
|
||||
String username = principal.getName();
|
||||
String apiKey = userService.getApiKeyForUser(username);
|
||||
if (apiKey == null) {
|
||||
return ResponseEntity.status(HttpStatus.NOT_FOUND).body("API key not found for user.");
|
||||
}
|
||||
return ResponseEntity.ok(apiKey);
|
||||
}
|
||||
|
||||
@PostMapping("/update-api-key")
|
||||
public ResponseEntity<String> updateApiKey(Principal principal) {
|
||||
if (principal == null) {
|
||||
return ResponseEntity.status(HttpStatus.FORBIDDEN).body("User not authenticated.");
|
||||
}
|
||||
String username = principal.getName();
|
||||
User user = userService.refreshApiKeyForUser(username);
|
||||
String apiKey = user.getApiKey();
|
||||
if (apiKey == null) {
|
||||
return ResponseEntity.status(HttpStatus.NOT_FOUND).body("API key not found for user.");
|
||||
}
|
||||
return ResponseEntity.ok(apiKey);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
package stirling.software.SPDF.controller.api.converters;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestPart;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.xml.sax.InputSource;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Hidden;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import stirling.software.SPDF.utils.FileToPdf;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
|
||||
@RestController
|
||||
@Tag(name = "Convert", description = "Convert APIs")
|
||||
public class ConvertEpubToPdf {
|
||||
//TODO
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/epub-to-single-pdf")
|
||||
@Hidden
|
||||
@Operation(
|
||||
summary = "Convert an EPUB file to a single PDF",
|
||||
description = "This endpoint takes an EPUB file input and converts it to a single PDF."
|
||||
)
|
||||
public ResponseEntity<byte[]> epubToSinglePdf(
|
||||
@RequestPart(required = true, value = "fileInput") MultipartFile fileInput)
|
||||
throws Exception {
|
||||
|
||||
if (fileInput == null) {
|
||||
throw new IllegalArgumentException("Please provide an EPUB file for conversion.");
|
||||
}
|
||||
|
||||
String originalFilename = fileInput.getOriginalFilename();
|
||||
if (originalFilename == null || !originalFilename.endsWith(".epub")) {
|
||||
throw new IllegalArgumentException("File must be in .epub format.");
|
||||
}
|
||||
|
||||
Map<String, byte[]> epubContents = extractEpubContent(fileInput);
|
||||
List<String> htmlFilesOrder = getHtmlFilesOrderFromOpf(epubContents);
|
||||
|
||||
List<byte[]> individualPdfs = new ArrayList<>();
|
||||
|
||||
for (String htmlFile : htmlFilesOrder) {
|
||||
byte[] htmlContent = epubContents.get(htmlFile);
|
||||
byte[] pdfBytes = FileToPdf.convertHtmlToPdf(htmlContent, htmlFile.replace(".html", ".pdf"));
|
||||
individualPdfs.add(pdfBytes);
|
||||
}
|
||||
|
||||
// Pseudo-code to merge individual PDFs into one.
|
||||
byte[] mergedPdfBytes = mergeMultiplePdfsIntoOne(individualPdfs);
|
||||
|
||||
return WebResponseUtils.bytesToWebResponse(mergedPdfBytes, originalFilename.replace(".epub", ".pdf"));
|
||||
}
|
||||
|
||||
// Assuming a pseudo-code function that merges multiple PDFs into one.
|
||||
private byte[] mergeMultiplePdfsIntoOne(List<byte[]> individualPdfs) {
|
||||
// You can use a library such as iText or PDFBox to perform the merging here.
|
||||
// Return the byte[] of the merged PDF.
|
||||
return null;
|
||||
}
|
||||
|
||||
private Map<String, byte[]> extractEpubContent(MultipartFile fileInput) throws IOException {
|
||||
Map<String, byte[]> contentMap = new HashMap<>();
|
||||
|
||||
try (ZipInputStream zis = new ZipInputStream(fileInput.getInputStream())) {
|
||||
ZipEntry zipEntry = zis.getNextEntry();
|
||||
while (zipEntry != null) {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
byte[] buffer = new byte[1024];
|
||||
int read = 0;
|
||||
while ((read = zis.read(buffer)) != -1) {
|
||||
baos.write(buffer, 0, read);
|
||||
}
|
||||
contentMap.put(zipEntry.getName(), baos.toByteArray());
|
||||
zipEntry = zis.getNextEntry();
|
||||
}
|
||||
}
|
||||
|
||||
return contentMap;
|
||||
}
|
||||
|
||||
private List<String> getHtmlFilesOrderFromOpf(Map<String, byte[]> epubContents) throws Exception {
|
||||
String opfContent = new String(epubContents.get("OEBPS/content.opf")); // Adjusting for given path
|
||||
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
|
||||
InputSource is = new InputSource(new StringReader(opfContent));
|
||||
Document doc = dBuilder.parse(is);
|
||||
|
||||
NodeList itemRefs = doc.getElementsByTagName("itemref");
|
||||
List<String> htmlFilesOrder = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < itemRefs.getLength(); i++) {
|
||||
Element itemRef = (Element) itemRefs.item(i);
|
||||
String idref = itemRef.getAttribute("idref");
|
||||
|
||||
NodeList items = doc.getElementsByTagName("item");
|
||||
for (int j = 0; j < items.getLength(); j++) {
|
||||
Element item = (Element) items.item(j);
|
||||
if (idref.equals(item.getAttribute("id"))) {
|
||||
htmlFilesOrder.add(item.getAttribute("href")); // Fetching the actual href
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return htmlFilesOrder;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,15 +1,6 @@
|
||||
package stirling.software.SPDF.controller.api.converters;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@@ -19,8 +10,7 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import stirling.software.SPDF.utils.GeneralUtils;
|
||||
import stirling.software.SPDF.utils.ProcessExecutor;
|
||||
import stirling.software.SPDF.utils.FileToPdf;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
|
||||
@RestController
|
||||
@@ -43,87 +33,17 @@ public class ConvertHtmlToPDF {
|
||||
String originalFilename = fileInput.getOriginalFilename();
|
||||
if (originalFilename == null || (!originalFilename.endsWith(".html") && !originalFilename.endsWith(".zip"))) {
|
||||
throw new IllegalArgumentException("File must be either .html or .zip format.");
|
||||
}
|
||||
Path tempOutputFile = Files.createTempFile("output_", ".pdf");
|
||||
Path tempInputFile = null;
|
||||
byte[] pdfBytes;
|
||||
try {
|
||||
if (originalFilename.endsWith(".html")) {
|
||||
tempInputFile = Files.createTempFile("input_", ".html");
|
||||
Files.write(tempInputFile, fileInput.getBytes());
|
||||
} else {
|
||||
tempInputFile = unzipAndGetMainHtml(fileInput);
|
||||
}
|
||||
|
||||
List<String> command = new ArrayList<>();
|
||||
command.add("weasyprint");
|
||||
command.add(tempInputFile.toString());
|
||||
command.add(tempOutputFile.toString());
|
||||
int returnCode = 0;
|
||||
if (originalFilename.endsWith(".zip")) {
|
||||
returnCode = ProcessExecutor.getInstance(ProcessExecutor.Processes.WEASYPRINT)
|
||||
.runCommandWithOutputHandling(command, tempInputFile.getParent().toFile());
|
||||
} else {
|
||||
|
||||
returnCode = ProcessExecutor.getInstance(ProcessExecutor.Processes.WEASYPRINT)
|
||||
.runCommandWithOutputHandling(command);
|
||||
}
|
||||
|
||||
pdfBytes = Files.readAllBytes(tempOutputFile);
|
||||
} finally {
|
||||
// Clean up temporary files
|
||||
Files.delete(tempOutputFile);
|
||||
Files.delete(tempInputFile);
|
||||
|
||||
if (originalFilename.endsWith(".zip")) {
|
||||
GeneralUtils.deleteDirectory(tempInputFile.getParent());
|
||||
}
|
||||
}
|
||||
}byte[] pdfBytes = FileToPdf.convertHtmlToPdf( fileInput.getBytes(), originalFilename);
|
||||
|
||||
String outputFilename = originalFilename.replaceFirst("[.][^.]+$", "") + ".pdf"; // Remove file extension and append .pdf
|
||||
|
||||
return WebResponseUtils.bytesToWebResponse(pdfBytes, outputFilename);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private Path unzipAndGetMainHtml(MultipartFile zipFile) throws IOException {
|
||||
Path tempDirectory = Files.createTempDirectory("unzipped_");
|
||||
try (ZipInputStream zipIn = new ZipInputStream(new ByteArrayInputStream(zipFile.getBytes()))) {
|
||||
ZipEntry entry = zipIn.getNextEntry();
|
||||
while (entry != null) {
|
||||
Path filePath = tempDirectory.resolve(entry.getName());
|
||||
if (entry.isDirectory()) {
|
||||
Files.createDirectories(filePath); // Explicitly create the directory structure
|
||||
} else {
|
||||
Files.createDirectories(filePath.getParent()); // Create parent directories if they don't exist
|
||||
Files.copy(zipIn, filePath);
|
||||
}
|
||||
zipIn.closeEntry();
|
||||
entry = zipIn.getNextEntry();
|
||||
}
|
||||
}
|
||||
|
||||
//search for the main HTML file.
|
||||
try (Stream<Path> walk = Files.walk(tempDirectory)) {
|
||||
List<Path> htmlFiles = walk.filter(file -> file.toString().endsWith(".html"))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (htmlFiles.isEmpty()) {
|
||||
throw new IOException("No HTML files found in the unzipped directory.");
|
||||
}
|
||||
|
||||
// Prioritize 'index.html' if it exists, otherwise use the first .html file
|
||||
for (Path htmlFile : htmlFiles) {
|
||||
if (htmlFile.getFileName().toString().equals("index.html")) {
|
||||
return htmlFile;
|
||||
}
|
||||
}
|
||||
|
||||
return htmlFiles.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
package stirling.software.SPDF.controller.api.converters;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.commonmark.node.Node;
|
||||
import org.commonmark.parser.Parser;
|
||||
import org.commonmark.renderer.html.HtmlRenderer;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestPart;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import stirling.software.SPDF.utils.FileToPdf;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
|
||||
@RestController
|
||||
@Tag(name = "Convert", description = "Convert APIs")
|
||||
public class ConvertMarkdownToPdf {
|
||||
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/markdown-to-pdf")
|
||||
@Operation(
|
||||
summary = "Convert a Markdown file to PDF",
|
||||
description = "This endpoint takes a Markdown file input, converts it to HTML, and then to PDF format."
|
||||
)
|
||||
public ResponseEntity<byte[]> markdownToPdf(
|
||||
@RequestPart(required = true, value = "fileInput") MultipartFile fileInput)
|
||||
throws IOException, InterruptedException {
|
||||
|
||||
if (fileInput == null) {
|
||||
throw new IllegalArgumentException("Please provide a Markdown file for conversion.");
|
||||
}
|
||||
|
||||
String originalFilename = fileInput.getOriginalFilename();
|
||||
if (originalFilename == null || !originalFilename.endsWith(".md")) {
|
||||
throw new IllegalArgumentException("File must be in .md format.");
|
||||
}
|
||||
|
||||
// Convert Markdown to HTML using CommonMark
|
||||
Parser parser = Parser.builder().build();
|
||||
Node document = parser.parse(new String(fileInput.getBytes()));
|
||||
HtmlRenderer renderer = HtmlRenderer.builder().build();
|
||||
String htmlContent = renderer.render(document);
|
||||
|
||||
byte[] pdfBytes = FileToPdf.convertHtmlToPdf(htmlContent.getBytes(), "converted.html");
|
||||
|
||||
String outputFilename = originalFilename.replaceFirst("[.][^.]+$", "") + ".pdf"; // Remove file extension and append .pdf
|
||||
return WebResponseUtils.bytesToWebResponse(pdfBytes, outputFilename);
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import stirling.software.SPDF.utils.ProcessExecutor;
|
||||
import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
|
||||
@RestController
|
||||
@@ -41,7 +42,7 @@ public class ConvertOfficeController {
|
||||
|
||||
// Run the LibreOffice command
|
||||
List<String> command = new ArrayList<>(Arrays.asList("unoconv", "-vvv", "-f", "pdf", "-o", tempOutputFile.toString(), tempInputFile.toString()));
|
||||
int returnCode = ProcessExecutor.getInstance(ProcessExecutor.Processes.LIBRE_OFFICE).runCommandWithOutputHandling(command);
|
||||
ProcessExecutorResult returnCode = ProcessExecutor.getInstance(ProcessExecutor.Processes.LIBRE_OFFICE).runCommandWithOutputHandling(command);
|
||||
|
||||
// Read the converted PDF file
|
||||
byte[] pdfBytes = Files.readAllBytes(tempOutputFile);
|
||||
@@ -62,10 +63,10 @@ public class ConvertOfficeController {
|
||||
summary = "Convert a file to a PDF using LibreOffice",
|
||||
description = "This endpoint converts a given file to a PDF using LibreOffice API Input:Any Output:PDF Type:SISO"
|
||||
)
|
||||
public ResponseEntity<byte[]> processPdfWithOCR(
|
||||
public ResponseEntity<byte[]> processFileToPDF(
|
||||
@RequestPart(required = true, value = "fileInput")
|
||||
@Parameter(
|
||||
description = "The input file to be converted to a PDF file using OCR",
|
||||
description = "The input file to be converted to a PDF file using LibreOffice",
|
||||
required = true
|
||||
)
|
||||
MultipartFile inputFile
|
||||
|
||||
@@ -16,6 +16,7 @@ import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import stirling.software.SPDF.utils.ProcessExecutor;
|
||||
import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
|
||||
@RestController
|
||||
@@ -49,7 +50,7 @@ public class ConvertPDFToPDFA {
|
||||
command.add(tempInputFile.toString());
|
||||
command.add(tempOutputFile.toString());
|
||||
|
||||
int returnCode = ProcessExecutor.getInstance(ProcessExecutor.Processes.OCR_MY_PDF).runCommandWithOutputHandling(command);
|
||||
ProcessExecutorResult returnCode = ProcessExecutor.getInstance(ProcessExecutor.Processes.OCR_MY_PDF).runCommandWithOutputHandling(command);
|
||||
|
||||
// Read the optimized PDF file
|
||||
byte[] pdfBytes = Files.readAllBytes(tempOutputFile);
|
||||
|
||||
@@ -8,15 +8,15 @@ import java.util.List;
|
||||
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestPart;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import stirling.software.SPDF.utils.GeneralUtils;
|
||||
import stirling.software.SPDF.utils.ProcessExecutor;
|
||||
import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
|
||||
@RestController
|
||||
@@ -29,7 +29,7 @@ public class ConvertWebsiteToPDF {
|
||||
description = "This endpoint fetches content from a URL and converts it to a PDF format."
|
||||
)
|
||||
public ResponseEntity<byte[]> urlToPdf(
|
||||
@RequestPart(required = true, value = "urlInput")
|
||||
@RequestParam(required = true, value = "urlInput")
|
||||
@Parameter(description = "The input URL to be converted to a PDF file", required = true)
|
||||
String URL) throws IOException, InterruptedException {
|
||||
|
||||
@@ -49,7 +49,7 @@ public class ConvertWebsiteToPDF {
|
||||
command.add(URL);
|
||||
command.add(tempOutputFile.toString());
|
||||
|
||||
int returnCode = ProcessExecutor.getInstance(ProcessExecutor.Processes.WEASYPRINT).runCommandWithOutputHandling(command);
|
||||
ProcessExecutorResult returnCode = ProcessExecutor.getInstance(ProcessExecutor.Processes.WEASYPRINT).runCommandWithOutputHandling(command);
|
||||
|
||||
// Read the optimized PDF file
|
||||
pdfBytes = Files.readAllBytes(tempOutputFile);
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
package stirling.software.SPDF.controller.api.filters;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.PDPage;
|
||||
@@ -17,11 +13,10 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import stirling.software.SPDF.utils.PdfUtils;
|
||||
import stirling.software.SPDF.utils.ProcessExecutor;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
@RestController
|
||||
@Tag(name = "Filter", description = "Filter APIs")
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
package stirling.software.SPDF.controller.api.other;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.text.PDFTextStripper;
|
||||
import org.apache.pdfbox.text.TextPosition;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
@@ -19,57 +20,7 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import stirling.software.SPDF.utils.GeneralUtils;
|
||||
import stirling.software.SPDF.utils.PdfUtils;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
import org.apache.pdfbox.pdmodel.*;
|
||||
import org.apache.pdfbox.pdmodel.common.*;
|
||||
import org.apache.pdfbox.pdmodel.PDPageContentStream.*;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.http.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import io.swagger.v3.oas.annotations.*;
|
||||
import io.swagger.v3.oas.annotations.media.*;
|
||||
import io.swagger.v3.oas.annotations.parameters.*;
|
||||
import org.apache.pdfbox.pdmodel.font.PDType1Font;
|
||||
import org.apache.pdfbox.text.TextPosition;
|
||||
import org.apache.tomcat.util.http.ResponseUtil;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import com.itextpdf.io.font.constants.StandardFonts;
|
||||
import com.itextpdf.kernel.font.PdfFont;
|
||||
import com.itextpdf.kernel.font.PdfFontFactory;
|
||||
import com.itextpdf.kernel.geom.Rectangle;
|
||||
import com.itextpdf.kernel.pdf.PdfReader;
|
||||
import com.itextpdf.kernel.pdf.PdfWriter;
|
||||
import com.itextpdf.kernel.pdf.PdfDocument;
|
||||
import com.itextpdf.kernel.pdf.PdfPage;
|
||||
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
|
||||
import com.itextpdf.layout.Canvas;
|
||||
import com.itextpdf.layout.element.Paragraph;
|
||||
import com.itextpdf.layout.properties.TextAlignment;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
import java.io.*;
|
||||
import org.apache.pdfbox.pdmodel.*;
|
||||
import org.apache.pdfbox.text.*;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import io.swagger.v3.oas.annotations.*;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
@RestController
|
||||
@Tag(name = "Other", description = "Other APIs")
|
||||
public class AutoRenameController {
|
||||
|
||||
@@ -29,9 +29,9 @@ import com.google.zxing.PlanarYUVLuminanceSource;
|
||||
import com.google.zxing.Result;
|
||||
import com.google.zxing.common.HybridBinarizer;
|
||||
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
|
||||
@RestController
|
||||
public class AutoSplitPdfController {
|
||||
|
||||
@@ -31,6 +31,7 @@ import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import stirling.software.SPDF.utils.PdfUtils;
|
||||
import stirling.software.SPDF.utils.ProcessExecutor;
|
||||
import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
|
||||
@RestController
|
||||
@@ -86,10 +87,10 @@ public class BlankPageController {
|
||||
List<String> command = new ArrayList<>(Arrays.asList("python3", System.getProperty("user.dir") + "/scripts/detect-blank-pages.py", tempFile.toString() ,"--threshold", String.valueOf(threshold), "--white_percent", String.valueOf(whitePercent)));
|
||||
|
||||
// Run CLI command
|
||||
int returnCode = ProcessExecutor.getInstance(ProcessExecutor.Processes.PYTHON_OPENCV).runCommandWithOutputHandling(command);
|
||||
ProcessExecutorResult returnCode = ProcessExecutor.getInstance(ProcessExecutor.Processes.PYTHON_OPENCV).runCommandWithOutputHandling(command);
|
||||
|
||||
// does contain data
|
||||
if (returnCode == 0) {
|
||||
if (returnCode.getRc() == 0) {
|
||||
System.out.println("page " + pageIndex + " has image which is not blank");
|
||||
pagesToKeepIndex.add(pageIndex);
|
||||
} else {
|
||||
|
||||
@@ -34,6 +34,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import stirling.software.SPDF.utils.GeneralUtils;
|
||||
import stirling.software.SPDF.utils.ProcessExecutor;
|
||||
import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
|
||||
@RestController
|
||||
@@ -116,7 +117,7 @@ public class CompressController {
|
||||
command.add("-sOutputFile=" + tempOutputFile.toString());
|
||||
command.add(tempInputFile.toString());
|
||||
|
||||
int returnCode = ProcessExecutor.getInstance(ProcessExecutor.Processes.GHOSTSCRIPT).runCommandWithOutputHandling(command);
|
||||
ProcessExecutorResult returnCode = ProcessExecutor.getInstance(ProcessExecutor.Processes.GHOSTSCRIPT).runCommandWithOutputHandling(command);
|
||||
|
||||
// Check if file size is within expected size or not auto mode so instantly finish
|
||||
long outputFileSize = Files.size(tempOutputFile);
|
||||
|
||||
@@ -33,6 +33,7 @@ import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import stirling.software.SPDF.utils.ProcessExecutor;
|
||||
import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
|
||||
@RestController
|
||||
@@ -117,7 +118,7 @@ public class ExtractImageScansController {
|
||||
|
||||
|
||||
// Run CLI command
|
||||
int returnCode = ProcessExecutor.getInstance(ProcessExecutor.Processes.PYTHON_OPENCV).runCommandWithOutputHandling(command);
|
||||
ProcessExecutorResult returnCode = ProcessExecutor.getInstance(ProcessExecutor.Processes.PYTHON_OPENCV).runCommandWithOutputHandling(command);
|
||||
|
||||
// Read the output photos in temp directory
|
||||
List<Path> tempOutputFiles = Files.list(tempDir).sorted().collect(Collectors.toList());
|
||||
|
||||
@@ -29,6 +29,7 @@ import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import stirling.software.SPDF.utils.ProcessExecutor;
|
||||
import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
|
||||
@RestController
|
||||
@@ -141,8 +142,12 @@ public class OCRController {
|
||||
command.addAll(Arrays.asList("--language", languageOption, tempInputFile.toString(), tempOutputFile.toString()));
|
||||
|
||||
// Run CLI command
|
||||
int returnCode = ProcessExecutor.getInstance(ProcessExecutor.Processes.OCR_MY_PDF).runCommandWithOutputHandling(command);
|
||||
|
||||
ProcessExecutorResult result = ProcessExecutor.getInstance(ProcessExecutor.Processes.OCR_MY_PDF).runCommandWithOutputHandling(command);
|
||||
if(result.getRc() != 0 && result.getMessages().contains("multiprocessing/synchronize.py") && result.getMessages().contains("OSError: [Errno 38] Function not implemented")) {
|
||||
command.add("--jobs");
|
||||
command.add("1");
|
||||
result = ProcessExecutor.getInstance(ProcessExecutor.Processes.OCR_MY_PDF).runCommandWithOutputHandling(command);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -153,7 +158,7 @@ public class OCRController {
|
||||
|
||||
List<String> gsCommand = Arrays.asList("gs", "-sDEVICE=pdfwrite", "-dFILTERIMAGE", "-o", tempPdfWithoutImages.toString(), tempOutputFile.toString());
|
||||
|
||||
int gsReturnCode = ProcessExecutor.getInstance(ProcessExecutor.Processes.GHOSTSCRIPT).runCommandWithOutputHandling(gsCommand);
|
||||
ProcessExecutor.getInstance(ProcessExecutor.Processes.GHOSTSCRIPT).runCommandWithOutputHandling(gsCommand);
|
||||
tempOutputFile = tempPdfWithoutImages;
|
||||
}
|
||||
// Read the OCR processed PDF file
|
||||
|
||||
@@ -1,65 +1,39 @@
|
||||
package stirling.software.SPDF.controller.api.other;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RequestPart;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import stirling.software.SPDF.utils.GeneralUtils;
|
||||
import stirling.software.SPDF.utils.PdfUtils;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
import org.apache.pdfbox.pdmodel.*;
|
||||
import org.apache.pdfbox.pdmodel.common.*;
|
||||
import org.apache.pdfbox.pdmodel.PDPageContentStream.*;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.http.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import io.swagger.v3.oas.annotations.*;
|
||||
import io.swagger.v3.oas.annotations.media.*;
|
||||
import io.swagger.v3.oas.annotations.parameters.*;
|
||||
import org.apache.pdfbox.pdmodel.font.PDType1Font;
|
||||
import org.apache.tomcat.util.http.ResponseUtil;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import com.itextpdf.io.font.constants.StandardFonts;
|
||||
import com.itextpdf.kernel.font.PdfFont;
|
||||
import com.itextpdf.kernel.font.PdfFontFactory;
|
||||
import com.itextpdf.kernel.geom.Rectangle;
|
||||
import com.itextpdf.kernel.pdf.PdfReader;
|
||||
import com.itextpdf.kernel.pdf.PdfWriter;
|
||||
import com.itextpdf.kernel.pdf.PdfDocument;
|
||||
import com.itextpdf.kernel.pdf.PdfPage;
|
||||
import com.itextpdf.kernel.pdf.PdfReader;
|
||||
import com.itextpdf.kernel.pdf.PdfWriter;
|
||||
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
|
||||
import com.itextpdf.layout.Canvas;
|
||||
import com.itextpdf.layout.element.Paragraph;
|
||||
import com.itextpdf.layout.properties.TextAlignment;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
import java.io.*;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import stirling.software.SPDF.utils.GeneralUtils;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
|
||||
@RestController
|
||||
@Tag(name = "Other", description = "Other APIs")
|
||||
@@ -116,7 +90,7 @@ public class PageNumbersController {
|
||||
Rectangle pageSize = page.getPageSize();
|
||||
PdfCanvas pdfCanvas = new PdfCanvas(page.newContentStreamAfter(), page.getResources(), pdfDoc);
|
||||
|
||||
String text = customText != null ? customText.replace("{n}", String.valueOf(pageNumber)).replace("{total}", String.valueOf(pdfDoc.getNumberOfPages())) : String.valueOf(pageNumber);
|
||||
String text = customText != null ? customText.replace("{n}", String.valueOf(pageNumber)).replace("{total}", String.valueOf(pdfDoc.getNumberOfPages())).replace("{filename}", file.getOriginalFilename().replaceFirst("[.][^.]+$", "")) : String.valueOf(pageNumber);
|
||||
|
||||
PdfFont font = PdfFontFactory.createFont(StandardFonts.HELVETICA);
|
||||
float textWidth = font.getWidth(text, fontSize);
|
||||
|
||||
@@ -18,6 +18,7 @@ import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import stirling.software.SPDF.utils.ProcessExecutor;
|
||||
import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
|
||||
@RestController
|
||||
@@ -51,7 +52,7 @@ public class RepairController {
|
||||
command.add(tempInputFile.toString());
|
||||
|
||||
|
||||
int returnCode = ProcessExecutor.getInstance(ProcessExecutor.Processes.GHOSTSCRIPT).runCommandWithOutputHandling(command);
|
||||
ProcessExecutorResult returnCode = ProcessExecutor.getInstance(ProcessExecutor.Processes.GHOSTSCRIPT).runCommandWithOutputHandling(command);
|
||||
|
||||
// Read the optimized PDF file
|
||||
byte[] pdfBytes = Files.readAllBytes(tempOutputFile);
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
package stirling.software.SPDF.controller.api.other;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestPart;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import com.itextpdf.kernel.pdf.PdfArray;
|
||||
import com.itextpdf.kernel.pdf.PdfDictionary;
|
||||
import com.itextpdf.kernel.pdf.PdfDocument;
|
||||
import com.itextpdf.kernel.pdf.PdfName;
|
||||
import com.itextpdf.kernel.pdf.PdfObject;
|
||||
import com.itextpdf.kernel.pdf.PdfReader;
|
||||
import com.itextpdf.kernel.pdf.PdfStream;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
@RestController
|
||||
@Tag(name = "Other", description = "Other APIs")
|
||||
public class ShowJavascript {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ShowJavascript.class);
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/show-javascript")
|
||||
@Operation(summary = "Extract header from PDF file", description = "This endpoint accepts a PDF file and attempts to extract its title or header based on heuristics. Input:PDF Output:PDF Type:SISO")
|
||||
public ResponseEntity<byte[]> extractHeader(
|
||||
@RequestPart(value = "fileInput") @Parameter(description = "The input PDF file from which the javascript is to be extracted.", required = true) MultipartFile inputFile)
|
||||
throws Exception {
|
||||
|
||||
try (
|
||||
PdfDocument itextDoc = new PdfDocument(new PdfReader(inputFile.getInputStream()))
|
||||
) {
|
||||
|
||||
String name = "";
|
||||
String script = "";
|
||||
String entryName = "File: "+inputFile.getOriginalFilename() + ", Script: ";
|
||||
//Javascript
|
||||
PdfDictionary namesDict = itextDoc.getCatalog().getPdfObject().getAsDictionary(PdfName.Names);
|
||||
if (namesDict != null) {
|
||||
PdfDictionary javascriptDict = namesDict.getAsDictionary(PdfName.JavaScript);
|
||||
if (javascriptDict != null) {
|
||||
|
||||
PdfArray namesArray = javascriptDict.getAsArray(PdfName.Names);
|
||||
for (int i = 0; i < namesArray.size(); i += 2) {
|
||||
if(namesArray.getAsString(i) != null)
|
||||
name = namesArray.getAsString(i).toString();
|
||||
|
||||
PdfObject jsCode = namesArray.get(i+1);
|
||||
if (jsCode instanceof PdfStream) {
|
||||
byte[] jsCodeBytes = ((PdfStream)jsCode).getBytes();
|
||||
String jsCodeStr = new String(jsCodeBytes, StandardCharsets.UTF_8);
|
||||
script = "//" + entryName + name + "\n" +jsCodeStr;
|
||||
|
||||
} else if (jsCode instanceof PdfDictionary) {
|
||||
// If the JS code is in a dictionary, you'll need to know the key to use.
|
||||
// Assuming the key is PdfName.JS:
|
||||
PdfStream jsCodeStream = ((PdfDictionary)jsCode).getAsStream(PdfName.JS);
|
||||
if (jsCodeStream != null) {
|
||||
byte[] jsCodeBytes = jsCodeStream.getBytes();
|
||||
String jsCodeStr = new String(jsCodeBytes, StandardCharsets.UTF_8);
|
||||
script = "//" + entryName + name + "\n" +jsCodeStr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if(script.equals("")) {
|
||||
script = "PDF '" +inputFile.getOriginalFilename() + "' does not contain Javascript";
|
||||
}
|
||||
return WebResponseUtils.bytesToWebResponse(script.getBytes(), name + ".js");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -3,8 +3,10 @@ package stirling.software.SPDF.controller.api.pipeline;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
@@ -20,8 +22,7 @@ import java.util.stream.Stream;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -47,6 +48,7 @@ import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import stirling.software.SPDF.model.ApplicationProperties;
|
||||
import stirling.software.SPDF.model.PipelineConfig;
|
||||
import stirling.software.SPDF.model.PipelineOperation;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
@@ -91,6 +93,10 @@ public class PipelineController {
|
||||
}
|
||||
}
|
||||
|
||||
@Autowired
|
||||
ApplicationProperties applicationProperties;
|
||||
|
||||
|
||||
private void handleDirectory(Path dir) throws Exception {
|
||||
logger.info("Handling directory: {}", dir);
|
||||
Path jsonFile = dir.resolve(jsonFileName);
|
||||
@@ -182,8 +188,7 @@ public class PipelineController {
|
||||
// {filename} {folder} {date} {tmime} {pipeline}
|
||||
String outputDir = config.getOutputDir();
|
||||
|
||||
// Check if the environment variable 'automatedOutputFolder' is set
|
||||
String outputFolder = System.getenv("automatedOutputFolder");
|
||||
String outputFolder = applicationProperties.getAutoPipeline().getOutputFolder();
|
||||
|
||||
if (outputFolder == null || outputFolder.isEmpty()) {
|
||||
// If the environment variable is not set, use the default value
|
||||
|
||||
@@ -0,0 +1,777 @@
|
||||
package stirling.software.SPDF.controller.api.security;
|
||||
|
||||
import java.io.IOException;
|
||||
import org.apache.pdfbox.pdmodel.encryption.AccessPermission;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.pdfbox.cos.COSString;
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.PDDocumentInformation;
|
||||
import org.apache.pdfbox.pdmodel.documentinterchange.logicalstructure.PDStructureElement;
|
||||
import org.apache.pdfbox.pdmodel.documentinterchange.logicalstructure.PDStructureNode;
|
||||
import org.apache.pdfbox.pdmodel.documentinterchange.logicalstructure.PDStructureTreeRoot;
|
||||
import org.apache.pdfbox.pdmodel.encryption.PDEncryption;
|
||||
import org.apache.pdfbox.text.PDFTextStripper;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestPart;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import com.itextpdf.forms.PdfAcroForm;
|
||||
import com.itextpdf.forms.fields.PdfFormField;
|
||||
import com.itextpdf.kernel.geom.Rectangle;
|
||||
import com.itextpdf.kernel.pdf.PdfArray;
|
||||
import com.itextpdf.kernel.pdf.PdfCatalog;
|
||||
import com.itextpdf.kernel.pdf.PdfDictionary;
|
||||
import com.itextpdf.kernel.pdf.PdfDocument;
|
||||
import com.itextpdf.kernel.pdf.PdfName;
|
||||
import com.itextpdf.kernel.pdf.PdfObject;
|
||||
import com.itextpdf.kernel.pdf.PdfOutline;
|
||||
import com.itextpdf.kernel.pdf.PdfReader;
|
||||
import com.itextpdf.kernel.pdf.PdfResources;
|
||||
import com.itextpdf.kernel.pdf.PdfStream;
|
||||
import com.itextpdf.kernel.pdf.PdfString;
|
||||
import com.itextpdf.kernel.pdf.annot.PdfAnnotation;
|
||||
import com.itextpdf.kernel.pdf.annot.PdfFileAttachmentAnnotation;
|
||||
import com.itextpdf.kernel.pdf.annot.PdfLinkAnnotation;
|
||||
import com.itextpdf.kernel.pdf.layer.PdfLayer;
|
||||
import com.itextpdf.kernel.pdf.layer.PdfOCProperties;
|
||||
import com.itextpdf.kernel.xmp.XMPException;
|
||||
import com.itextpdf.kernel.xmp.XMPMeta;
|
||||
import com.itextpdf.kernel.xmp.XMPMetaFactory;
|
||||
import com.itextpdf.kernel.xmp.options.SerializeOptions;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
@RestController
|
||||
@Tag(name = "Security", description = "Security APIs")
|
||||
public class GetInfoOnPDF {
|
||||
|
||||
static ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/get-info-on-pdf")
|
||||
@Operation(summary = "Summary here", description = "desc. Input:PDF Output:JSON Type:SISO")
|
||||
public ResponseEntity<byte[]> getPdfInfo(
|
||||
@RequestPart(required = true, value = "fileInput")
|
||||
@Parameter(description = "The input PDF file to get info on", required = true) MultipartFile inputFile)
|
||||
throws IOException {
|
||||
|
||||
try (
|
||||
PDDocument pdfBoxDoc = PDDocument.load(inputFile.getInputStream());
|
||||
PdfDocument itextDoc = new PdfDocument(new PdfReader(inputFile.getInputStream()))
|
||||
) {
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
ObjectNode jsonOutput = objectMapper.createObjectNode();
|
||||
|
||||
// Metadata using PDFBox
|
||||
PDDocumentInformation info = pdfBoxDoc.getDocumentInformation();
|
||||
ObjectNode metadata = objectMapper.createObjectNode();
|
||||
ObjectNode basicInfo = objectMapper.createObjectNode();
|
||||
ObjectNode docInfoNode = objectMapper.createObjectNode();
|
||||
ObjectNode compliancy = objectMapper.createObjectNode();
|
||||
ObjectNode encryption = objectMapper.createObjectNode();
|
||||
ObjectNode other = objectMapper.createObjectNode();
|
||||
|
||||
|
||||
metadata.put("Title", info.getTitle());
|
||||
metadata.put("Author", info.getAuthor());
|
||||
metadata.put("Subject", info.getSubject());
|
||||
metadata.put("Keywords", info.getKeywords());
|
||||
metadata.put("Producer", info.getProducer());
|
||||
metadata.put("Creator", info.getCreator());
|
||||
metadata.put("CreationDate", formatDate(info.getCreationDate()));
|
||||
metadata.put("ModificationDate", formatDate(info.getModificationDate()));
|
||||
jsonOutput.set("Metadata", metadata);
|
||||
|
||||
|
||||
|
||||
|
||||
// Total file size of the PDF
|
||||
long fileSizeInBytes = inputFile.getSize();
|
||||
basicInfo.put("FileSizeInBytes", fileSizeInBytes);
|
||||
|
||||
// Number of words, paragraphs, and images in the entire document
|
||||
String fullText = new PDFTextStripper().getText(pdfBoxDoc);
|
||||
String[] words = fullText.split("\\s+");
|
||||
int wordCount = words.length;
|
||||
int paragraphCount = fullText.split("\r\n|\r|\n").length;
|
||||
basicInfo.put("WordCount", wordCount);
|
||||
basicInfo.put("ParagraphCount", paragraphCount);
|
||||
// Number of characters in the entire document (including spaces and special characters)
|
||||
int charCount = fullText.length();
|
||||
basicInfo.put("CharacterCount", charCount);
|
||||
|
||||
|
||||
// Initialize the flags and types
|
||||
boolean hasCompression = false;
|
||||
String compressionType = "None";
|
||||
|
||||
// Check for object streams
|
||||
for (int i = 1; i <= itextDoc.getNumberOfPdfObjects(); i++) {
|
||||
PdfObject obj = itextDoc.getPdfObject(i);
|
||||
if (obj != null && obj.isStream() && ((PdfStream) obj).get(PdfName.Type) == PdfName.ObjStm) {
|
||||
hasCompression = true;
|
||||
compressionType = "Object Streams";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If not compressed using object streams, check for compressed Xref tables
|
||||
if (!hasCompression && itextDoc.getReader().hasRebuiltXref()) {
|
||||
hasCompression = true;
|
||||
compressionType = "Compressed Xref or Rebuilt Xref";
|
||||
}
|
||||
basicInfo.put("Compression", hasCompression);
|
||||
if(hasCompression)
|
||||
basicInfo.put("CompressionType", compressionType);
|
||||
|
||||
String language = pdfBoxDoc.getDocumentCatalog().getLanguage();
|
||||
basicInfo.put("Language", language);
|
||||
basicInfo.put("Number of pages", pdfBoxDoc.getNumberOfPages());
|
||||
|
||||
|
||||
// Page Mode using iText7
|
||||
PdfCatalog catalog = itextDoc.getCatalog();
|
||||
PdfName pageMode = catalog.getPdfObject().getAsName(PdfName.PageMode);
|
||||
|
||||
// Document Information using PDFBox
|
||||
docInfoNode.put("PDF version", pdfBoxDoc.getVersion());
|
||||
docInfoNode.put("Trapped", info.getTrapped());
|
||||
docInfoNode.put("Page Mode", getPageModeDescription(pageMode));;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
PdfAcroForm acroForm = PdfAcroForm.getAcroForm(itextDoc, false);
|
||||
ObjectNode formFieldsNode = objectMapper.createObjectNode();
|
||||
if (acroForm != null) {
|
||||
for (Map.Entry<String, PdfFormField> entry : acroForm.getFormFields().entrySet()) {
|
||||
formFieldsNode.put(entry.getKey(), entry.getValue().getValueAsString());
|
||||
}
|
||||
}
|
||||
jsonOutput.set("FormFields", formFieldsNode);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//embeed files TODO size
|
||||
ArrayNode embeddedFilesArray = objectMapper.createArrayNode();
|
||||
if(itextDoc.getCatalog().getPdfObject().getAsDictionary(PdfName.Names) != null)
|
||||
{
|
||||
PdfDictionary embeddedFiles = itextDoc.getCatalog().getPdfObject().getAsDictionary(PdfName.Names)
|
||||
.getAsDictionary(PdfName.EmbeddedFiles);
|
||||
if (embeddedFiles != null) {
|
||||
|
||||
PdfArray namesArray = embeddedFiles.getAsArray(PdfName.Names);
|
||||
if(namesArray != null) {
|
||||
for (int i = 0; i < namesArray.size(); i += 2) {
|
||||
ObjectNode embeddedFileNode = objectMapper.createObjectNode();
|
||||
embeddedFileNode.put("Name", namesArray.getAsString(i).toString());
|
||||
// Add other details if required
|
||||
embeddedFilesArray.add(embeddedFileNode);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
other.set("EmbeddedFiles", embeddedFilesArray);
|
||||
|
||||
//attachments TODO size
|
||||
ArrayNode attachmentsArray = objectMapper.createArrayNode();
|
||||
for (int pageNum = 1; pageNum <= itextDoc.getNumberOfPages(); pageNum++) {
|
||||
for (PdfAnnotation annotation : itextDoc.getPage(pageNum).getAnnotations()) {
|
||||
if (annotation instanceof PdfFileAttachmentAnnotation) {
|
||||
ObjectNode attachmentNode = objectMapper.createObjectNode();
|
||||
attachmentNode.put("Name", ((PdfFileAttachmentAnnotation) annotation).getName().toString());
|
||||
attachmentNode.put("Description", annotation.getContents().getValue());
|
||||
attachmentsArray.add(attachmentNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
other.set("Attachments", attachmentsArray);
|
||||
|
||||
//Javascript
|
||||
PdfDictionary namesDict = itextDoc.getCatalog().getPdfObject().getAsDictionary(PdfName.Names);
|
||||
ArrayNode javascriptArray = objectMapper.createArrayNode();
|
||||
if (namesDict != null) {
|
||||
PdfDictionary javascriptDict = namesDict.getAsDictionary(PdfName.JavaScript);
|
||||
if (javascriptDict != null) {
|
||||
|
||||
PdfArray namesArray = javascriptDict.getAsArray(PdfName.Names);
|
||||
for (int i = 0; i < namesArray.size(); i += 2) {
|
||||
ObjectNode jsNode = objectMapper.createObjectNode();
|
||||
if(namesArray.getAsString(i) != null)
|
||||
jsNode.put("JS Name", namesArray.getAsString(i).toString());
|
||||
|
||||
// Here we check for a PdfStream object and retrieve the JS code from it
|
||||
PdfObject jsCode = namesArray.get(i+1);
|
||||
if (jsCode instanceof PdfStream) {
|
||||
byte[] jsCodeBytes = ((PdfStream)jsCode).getBytes();
|
||||
String jsCodeStr = new String(jsCodeBytes, StandardCharsets.UTF_8);
|
||||
jsNode.put("JS Script Length", jsCodeStr.length());
|
||||
} else if (jsCode instanceof PdfDictionary) {
|
||||
// If the JS code is in a dictionary, you'll need to know the key to use.
|
||||
// Assuming the key is PdfName.JS:
|
||||
PdfStream jsCodeStream = ((PdfDictionary)jsCode).getAsStream(PdfName.JS);
|
||||
if (jsCodeStream != null) {
|
||||
byte[] jsCodeBytes = jsCodeStream.getBytes();
|
||||
String jsCodeStr = new String(jsCodeBytes, StandardCharsets.UTF_8);
|
||||
jsNode.put("JS Script Character Length", jsCodeStr.length());
|
||||
}
|
||||
}
|
||||
|
||||
javascriptArray.add(jsNode);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
other.set("JavaScript", javascriptArray);
|
||||
|
||||
//TODO size
|
||||
PdfOCProperties ocProperties = itextDoc.getCatalog().getOCProperties(false);
|
||||
ArrayNode layersArray = objectMapper.createArrayNode();
|
||||
if (ocProperties != null) {
|
||||
|
||||
for (PdfLayer layer : ocProperties.getLayers()) {
|
||||
ObjectNode layerNode = objectMapper.createObjectNode();
|
||||
layerNode.put("Name", layer.getPdfObject().getAsString(PdfName.Name).toString());
|
||||
layersArray.add(layerNode);
|
||||
}
|
||||
|
||||
}
|
||||
other.set("Layers", layersArray);
|
||||
|
||||
//TODO Security
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Digital Signatures using iText7 TODO
|
||||
|
||||
|
||||
|
||||
|
||||
PDStructureTreeRoot structureTreeRoot = pdfBoxDoc.getDocumentCatalog().getStructureTreeRoot();
|
||||
ArrayNode structureTreeArray;
|
||||
try {
|
||||
if(structureTreeRoot != null) {
|
||||
structureTreeArray = exploreStructureTree(structureTreeRoot.getKids());
|
||||
other.set("StructureTree", structureTreeArray);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
boolean isPdfACompliant = checkOutputIntent(itextDoc, "PDF/A");
|
||||
boolean isPdfXCompliant = checkOutputIntent(itextDoc, "PDF/X");
|
||||
boolean isPdfECompliant = checkForStandard(itextDoc, "PDF/E");
|
||||
boolean isPdfVTCompliant = checkForStandard(itextDoc, "PDF/VT");
|
||||
boolean isPdfUACompliant = checkForStandard(itextDoc, "PDF/UA");
|
||||
boolean isPdfBCompliant = checkForStandard(itextDoc, "PDF/B"); // If you want to check for PDF/Broadcast, though this isn't an official ISO standard.
|
||||
boolean isPdfSECCompliant = checkForStandard(itextDoc, "PDF/SEC"); // This might not be effective since PDF/SEC was under development in 2021.
|
||||
|
||||
compliancy.put("IsPDF/ACompliant", isPdfACompliant);
|
||||
compliancy.put("IsPDF/XCompliant", isPdfXCompliant);
|
||||
compliancy.put("IsPDF/ECompliant", isPdfECompliant);
|
||||
compliancy.put("IsPDF/VTCompliant", isPdfVTCompliant);
|
||||
compliancy.put("IsPDF/UACompliant", isPdfUACompliant);
|
||||
compliancy.put("IsPDF/BCompliant", isPdfBCompliant);
|
||||
compliancy.put("IsPDF/SECCompliant", isPdfSECCompliant);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
ArrayNode bookmarksArray = objectMapper.createArrayNode();
|
||||
PdfOutline root = itextDoc.getOutlines(false);
|
||||
if (root != null) {
|
||||
for (PdfOutline child : root.getAllChildren()) {
|
||||
addOutlinesToArray(child, bookmarksArray);
|
||||
}
|
||||
}
|
||||
other.set("Bookmarks/Outline/TOC", bookmarksArray);
|
||||
|
||||
byte[] xmpBytes = itextDoc.getXmpMetadata();
|
||||
String xmpString = null;
|
||||
if (xmpBytes != null) {
|
||||
try {
|
||||
XMPMeta xmpMeta = XMPMetaFactory.parseFromBuffer(xmpBytes);
|
||||
xmpString = new String(XMPMetaFactory.serializeToBuffer(xmpMeta, new SerializeOptions()));
|
||||
} catch (XMPException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
other.put("XMPMetadata", xmpString);
|
||||
|
||||
|
||||
|
||||
if (pdfBoxDoc.isEncrypted()) {
|
||||
encryption.put("IsEncrypted", true);
|
||||
|
||||
// Retrieve encryption details using getEncryption()
|
||||
PDEncryption pdfEncryption = pdfBoxDoc.getEncryption();
|
||||
encryption.put("EncryptionAlgorithm", pdfEncryption.getFilter());
|
||||
encryption.put("KeyLength", pdfEncryption.getLength());
|
||||
AccessPermission ap = pdfBoxDoc.getCurrentAccessPermission();
|
||||
if (ap != null) {
|
||||
ObjectNode permissionsNode = objectMapper.createObjectNode();
|
||||
|
||||
permissionsNode.put("CanAssembleDocument", ap.canAssembleDocument());
|
||||
permissionsNode.put("CanExtractContent", ap.canExtractContent());
|
||||
permissionsNode.put("CanExtractForAccessibility", ap.canExtractForAccessibility());
|
||||
permissionsNode.put("CanFillInForm", ap.canFillInForm());
|
||||
permissionsNode.put("CanModify", ap.canModify());
|
||||
permissionsNode.put("CanModifyAnnotations", ap.canModifyAnnotations());
|
||||
permissionsNode.put("CanPrint", ap.canPrint());
|
||||
permissionsNode.put("CanPrintDegraded", ap.canPrintDegraded());
|
||||
|
||||
encryption.set("Permissions", permissionsNode); // set the node under "Permissions"
|
||||
}
|
||||
// Add other encryption-related properties as needed
|
||||
} else {
|
||||
encryption.put("IsEncrypted", false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
ObjectNode pageInfoParent = objectMapper.createObjectNode();
|
||||
for (int pageNum = 1; pageNum <= itextDoc.getNumberOfPages(); pageNum++) {
|
||||
ObjectNode pageInfo = objectMapper.createObjectNode();
|
||||
|
||||
// Page-level Information
|
||||
Rectangle pageSize = itextDoc.getPage(pageNum).getPageSize();
|
||||
pageInfo.put("Width", pageSize.getWidth());
|
||||
pageInfo.put("Height", pageSize.getHeight());
|
||||
pageInfo.put("Rotation", itextDoc.getPage(pageNum).getRotation());
|
||||
pageInfo.put("Page Orientation", getPageOrientation(pageSize.getWidth(),pageSize.getHeight()));
|
||||
pageInfo.put("Standard Size", getPageSize(pageSize.getWidth(),pageSize.getHeight()));
|
||||
|
||||
// Boxes
|
||||
pageInfo.put("MediaBox", itextDoc.getPage(pageNum).getMediaBox().toString());
|
||||
pageInfo.put("CropBox", itextDoc.getPage(pageNum).getCropBox().toString());
|
||||
pageInfo.put("BleedBox", itextDoc.getPage(pageNum).getBleedBox().toString());
|
||||
pageInfo.put("TrimBox", itextDoc.getPage(pageNum).getTrimBox().toString());
|
||||
pageInfo.put("ArtBox", itextDoc.getPage(pageNum).getArtBox().toString());
|
||||
|
||||
// Content Extraction
|
||||
PDFTextStripper textStripper = new PDFTextStripper();
|
||||
textStripper.setStartPage(pageNum -1);
|
||||
textStripper.setEndPage(pageNum - 1);
|
||||
String pageText = textStripper.getText(pdfBoxDoc);
|
||||
|
||||
pageInfo.put("Text Characters Count", pageText.length()); //
|
||||
|
||||
// Annotations
|
||||
List<PdfAnnotation> annotations = itextDoc.getPage(pageNum).getAnnotations();
|
||||
|
||||
int subtypeCount = 0;
|
||||
int contentsCount = 0;
|
||||
|
||||
for (PdfAnnotation annotation : annotations) {
|
||||
if(annotation.getSubtype() != null) {
|
||||
subtypeCount++; // Increase subtype count
|
||||
}
|
||||
if(annotation.getContents() != null) {
|
||||
contentsCount++; // Increase contents count
|
||||
}
|
||||
}
|
||||
|
||||
ObjectNode annotationsObject = objectMapper.createObjectNode();
|
||||
annotationsObject.put("AnnotationsCount", annotations.size());
|
||||
annotationsObject.put("SubtypeCount", subtypeCount);
|
||||
annotationsObject.put("ContentsCount", contentsCount);
|
||||
pageInfo.set("Annotations", annotationsObject);
|
||||
|
||||
// Images (simplified)
|
||||
// This part is non-trivial as images can be embedded in multiple ways in a PDF.
|
||||
// Here is a basic structure to recognize image XObjects on a page.
|
||||
ArrayNode imagesArray = objectMapper.createArrayNode();
|
||||
PdfResources resources = itextDoc.getPage(pageNum).getResources();
|
||||
for (PdfName name : resources.getResourceNames()) {
|
||||
PdfObject obj = resources.getResource(name);
|
||||
if (obj instanceof PdfStream) {
|
||||
PdfStream stream = (PdfStream) obj;
|
||||
if (PdfName.Image.equals(stream.getAsName(PdfName.Subtype))) {
|
||||
ObjectNode imageNode = objectMapper.createObjectNode();
|
||||
imageNode.put("Width", stream.getAsNumber(PdfName.Width).intValue());
|
||||
imageNode.put("Height", stream.getAsNumber(PdfName.Height).intValue());
|
||||
PdfObject colorSpace = stream.get(PdfName.ColorSpace);
|
||||
if (colorSpace != null) {
|
||||
imageNode.put("ColorSpace", colorSpace.toString());
|
||||
}
|
||||
imagesArray.add(imageNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
pageInfo.set("Images", imagesArray);
|
||||
|
||||
|
||||
// Links
|
||||
ArrayNode linksArray = objectMapper.createArrayNode();
|
||||
Set<String> uniqueURIs = new HashSet<>(); // To store unique URIs
|
||||
|
||||
for (PdfAnnotation annotation : annotations) {
|
||||
if (annotation instanceof PdfLinkAnnotation) {
|
||||
PdfLinkAnnotation linkAnnotation = (PdfLinkAnnotation) annotation;
|
||||
if(linkAnnotation != null && linkAnnotation.getAction() != null) {
|
||||
String uri = linkAnnotation.getAction().toString();
|
||||
uniqueURIs.add(uri); // Add to set to ensure uniqueness
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add unique URIs to linksArray
|
||||
for (String uri : uniqueURIs) {
|
||||
ObjectNode linkNode = objectMapper.createObjectNode();
|
||||
linkNode.put("URI", uri);
|
||||
linksArray.add(linkNode);
|
||||
}
|
||||
pageInfo.set("Links", linksArray);
|
||||
|
||||
// Fonts
|
||||
ArrayNode fontsArray = objectMapper.createArrayNode();
|
||||
PdfDictionary fontDicts = resources.getResource(PdfName.Font);
|
||||
Set<String> uniqueSubtypes = new HashSet<>(); // To store unique subtypes
|
||||
|
||||
// Map to store unique fonts and their counts
|
||||
Map<String, ObjectNode> uniqueFontsMap = new HashMap<>();
|
||||
|
||||
if (fontDicts != null) {
|
||||
for (PdfName key : fontDicts.keySet()) {
|
||||
ObjectNode fontNode = objectMapper.createObjectNode(); // Create a new font node for each font
|
||||
PdfDictionary font = fontDicts.getAsDictionary(key);
|
||||
|
||||
boolean isEmbedded = font.containsKey(PdfName.FontFile) ||
|
||||
font.containsKey(PdfName.FontFile2) ||
|
||||
font.containsKey(PdfName.FontFile3);
|
||||
fontNode.put("IsEmbedded", isEmbedded);
|
||||
|
||||
if (font.containsKey(PdfName.Encoding)) {
|
||||
String encoding = font.getAsName(PdfName.Encoding).toString();
|
||||
fontNode.put("Encoding", encoding);
|
||||
}
|
||||
|
||||
if (font.getAsString(PdfName.BaseFont) != null) {
|
||||
fontNode.put("Name", font.getAsString(PdfName.BaseFont).toString());
|
||||
}
|
||||
|
||||
String subtype = null;
|
||||
if (font.containsKey(PdfName.Subtype)) {
|
||||
subtype = font.getAsName(PdfName.Subtype).toString();
|
||||
uniqueSubtypes.add(subtype); // Add to set to ensure uniqueness
|
||||
}
|
||||
fontNode.put("Subtype", subtype);
|
||||
|
||||
PdfDictionary fontDescriptor = font.getAsDictionary(PdfName.FontDescriptor);
|
||||
if (fontDescriptor != null) {
|
||||
if (fontDescriptor.containsKey(PdfName.ItalicAngle)) {
|
||||
fontNode.put("ItalicAngle", fontDescriptor.getAsNumber(PdfName.ItalicAngle).floatValue());
|
||||
}
|
||||
|
||||
if (fontDescriptor.containsKey(PdfName.Flags)) {
|
||||
int flags = fontDescriptor.getAsNumber(PdfName.Flags).intValue();
|
||||
fontNode.put("IsItalic", (flags & 64) != 0);
|
||||
fontNode.put("IsBold", (flags & 1 << 16) != 0);
|
||||
fontNode.put("IsFixedPitch", (flags & 1) != 0);
|
||||
fontNode.put("IsSerif", (flags & 2) != 0);
|
||||
fontNode.put("IsSymbolic", (flags & 4) != 0);
|
||||
fontNode.put("IsScript", (flags & 8) != 0);
|
||||
fontNode.put("IsNonsymbolic", (flags & 16) != 0);
|
||||
}
|
||||
|
||||
if (fontDescriptor.containsKey(PdfName.FontFamily)) {
|
||||
String fontFamily = fontDescriptor.getAsString(PdfName.FontFamily).toString();
|
||||
fontNode.put("FontFamily", fontFamily);
|
||||
}
|
||||
|
||||
if (fontDescriptor.containsKey(PdfName.FontStretch)) {
|
||||
String fontStretch = fontDescriptor.getAsName(PdfName.FontStretch).toString();
|
||||
fontNode.put("FontStretch", fontStretch);
|
||||
}
|
||||
|
||||
if (fontDescriptor.containsKey(PdfName.FontBBox)) {
|
||||
PdfArray bbox = fontDescriptor.getAsArray(PdfName.FontBBox);
|
||||
fontNode.put("FontBoundingBox", bbox.toString());
|
||||
}
|
||||
|
||||
if (fontDescriptor.containsKey(PdfName.FontWeight)) {
|
||||
float fontWeight = fontDescriptor.getAsNumber(PdfName.FontWeight).floatValue();
|
||||
fontNode.put("FontWeight", fontWeight);
|
||||
}
|
||||
}
|
||||
|
||||
if (font.containsKey(PdfName.ToUnicode)) {
|
||||
fontNode.put("HasToUnicodeMap", true);
|
||||
}
|
||||
|
||||
if (fontNode.size() > 0) {
|
||||
// Create a unique key for this font node based on its attributes
|
||||
String uniqueKey = fontNode.toString();
|
||||
|
||||
// Increment count if this font exists, or initialize it if new
|
||||
if (uniqueFontsMap.containsKey(uniqueKey)) {
|
||||
ObjectNode existingFontNode = uniqueFontsMap.get(uniqueKey);
|
||||
int count = existingFontNode.get("Count").asInt() + 1;
|
||||
existingFontNode.put("Count", count);
|
||||
} else {
|
||||
fontNode.put("Count", 1);
|
||||
uniqueFontsMap.put(uniqueKey, fontNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add unique font entries to fontsArray
|
||||
for (ObjectNode uniqueFontNode : uniqueFontsMap.values()) {
|
||||
fontsArray.add(uniqueFontNode);
|
||||
}
|
||||
|
||||
pageInfo.set("Fonts", fontsArray);
|
||||
|
||||
|
||||
|
||||
|
||||
// Access resources dictionary
|
||||
PdfDictionary resourcesDict = itextDoc.getPage(pageNum).getResources().getPdfObject();
|
||||
|
||||
// Color Spaces & ICC Profiles
|
||||
ArrayNode colorSpacesArray = objectMapper.createArrayNode();
|
||||
PdfDictionary colorSpaces = resourcesDict.getAsDictionary(PdfName.ColorSpace);
|
||||
if (colorSpaces != null) {
|
||||
for (PdfName name : colorSpaces.keySet()) {
|
||||
PdfObject colorSpaceObject = colorSpaces.get(name);
|
||||
if (colorSpaceObject instanceof PdfArray) {
|
||||
PdfArray colorSpaceArray = (PdfArray) colorSpaceObject;
|
||||
if (colorSpaceArray.size() > 1 && colorSpaceArray.get(0) instanceof PdfName && PdfName.ICCBased.equals(colorSpaceArray.get(0))) {
|
||||
ObjectNode iccProfileNode = objectMapper.createObjectNode();
|
||||
PdfStream iccStream = (PdfStream) colorSpaceArray.get(1);
|
||||
byte[] iccData = iccStream.getBytes();
|
||||
// TODO: Further decode and analyze the ICC data if needed
|
||||
iccProfileNode.put("ICC Profile Length", iccData.length);
|
||||
colorSpacesArray.add(iccProfileNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pageInfo.set("Color Spaces & ICC Profiles", colorSpacesArray);
|
||||
|
||||
// Other XObjects
|
||||
Map<String, Integer> xObjectCountMap = new HashMap<>(); // To store the count for each type
|
||||
PdfDictionary xObjects = resourcesDict.getAsDictionary(PdfName.XObject);
|
||||
if (xObjects != null) {
|
||||
for (PdfName name : xObjects.keySet()) {
|
||||
PdfStream xObjectStream = xObjects.getAsStream(name);
|
||||
String xObjectType = xObjectStream.getAsName(PdfName.Subtype).toString();
|
||||
|
||||
// Increment the count for this type in the map
|
||||
xObjectCountMap.put(xObjectType, xObjectCountMap.getOrDefault(xObjectType, 0) + 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Add the count map to pageInfo (or wherever you want to store it)
|
||||
ObjectNode xObjectCountNode = objectMapper.createObjectNode();
|
||||
for (Map.Entry<String, Integer> entry : xObjectCountMap.entrySet()) {
|
||||
xObjectCountNode.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
pageInfo.set("XObjectCounts", xObjectCountNode);
|
||||
|
||||
|
||||
|
||||
ArrayNode multimediaArray = objectMapper.createArrayNode();
|
||||
for (PdfAnnotation annotation : annotations) {
|
||||
if (PdfName.RichMedia.equals(annotation.getSubtype())) {
|
||||
ObjectNode multimediaNode = objectMapper.createObjectNode();
|
||||
// Extract details from the dictionary as needed
|
||||
multimediaArray.add(multimediaNode);
|
||||
}
|
||||
}
|
||||
pageInfo.set("Multimedia", multimediaArray);
|
||||
|
||||
|
||||
|
||||
pageInfoParent.set("Page " + pageNum, pageInfo);
|
||||
}
|
||||
|
||||
|
||||
jsonOutput.set("BasicInfo", basicInfo);
|
||||
jsonOutput.set("DocumentInfo", docInfoNode);
|
||||
jsonOutput.set("Compliancy", compliancy);
|
||||
jsonOutput.set("Encryption", encryption);
|
||||
jsonOutput.set("Other", other);
|
||||
jsonOutput.set("PerPageInfo", pageInfoParent);
|
||||
|
||||
|
||||
|
||||
// Save JSON to file
|
||||
String jsonString = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonOutput);
|
||||
|
||||
|
||||
|
||||
return WebResponseUtils.bytesToWebResponse(jsonString.getBytes(StandardCharsets.UTF_8), "response.json", MediaType.APPLICATION_JSON);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void addOutlinesToArray(PdfOutline outline, ArrayNode arrayNode) {
|
||||
if (outline == null) return;
|
||||
ObjectNode outlineNode = objectMapper.createObjectNode();
|
||||
outlineNode.put("Title", outline.getTitle());
|
||||
// You can add other properties if needed
|
||||
arrayNode.add(outlineNode);
|
||||
|
||||
for (PdfOutline child : outline.getAllChildren()) {
|
||||
addOutlinesToArray(child, arrayNode);
|
||||
}
|
||||
}
|
||||
public String getPageOrientation(double width, double height) {
|
||||
if (width > height) {
|
||||
return "Landscape";
|
||||
} else if (height > width) {
|
||||
return "Portrait";
|
||||
} else {
|
||||
return "Square";
|
||||
}
|
||||
}
|
||||
public String getPageSize(double width, double height) {
|
||||
// Common aspect ratios used for standard paper sizes
|
||||
double[] aspectRatios = {4.0 / 3.0, 3.0 / 2.0, Math.sqrt(2.0), 16.0 / 9.0};
|
||||
|
||||
// Check if the page matches any common aspect ratio
|
||||
for (double aspectRatio : aspectRatios) {
|
||||
if (isCloseToAspectRatio(width, height, aspectRatio)) {
|
||||
return "Standard";
|
||||
}
|
||||
}
|
||||
|
||||
// If not a standard aspect ratio, consider it as a custom size
|
||||
return "Custom";
|
||||
}
|
||||
private boolean isCloseToAspectRatio(double width, double height, double aspectRatio) {
|
||||
// Calculate the aspect ratio of the page
|
||||
double pageAspectRatio = width / height;
|
||||
|
||||
// Compare the page aspect ratio with the common aspect ratio within a threshold
|
||||
return Math.abs(pageAspectRatio - aspectRatio) <= 0.05;
|
||||
}
|
||||
|
||||
public boolean checkForStandard(PdfDocument document, String standardKeyword) {
|
||||
// Check Output Intents
|
||||
boolean foundInOutputIntents = checkOutputIntent(document, standardKeyword);
|
||||
if (foundInOutputIntents) return true;
|
||||
|
||||
// Check XMP Metadata (rudimentary)
|
||||
try {
|
||||
byte[] metadataBytes = document.getXmpMetadata();
|
||||
if (metadataBytes != null) {
|
||||
XMPMeta xmpMeta = XMPMetaFactory.parseFromBuffer(metadataBytes);
|
||||
String xmpString = xmpMeta.dumpObject();
|
||||
if (xmpString.contains(standardKeyword)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (XMPException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public boolean checkOutputIntent(PdfDocument document, String standard) {
|
||||
PdfArray outputIntents = document.getCatalog().getPdfObject().getAsArray(PdfName.OutputIntents);
|
||||
if (outputIntents != null && !outputIntents.isEmpty()) {
|
||||
for (int i = 0; i < outputIntents.size(); i++) {
|
||||
PdfDictionary outputIntentDict = outputIntents.getAsDictionary(i);
|
||||
if (outputIntentDict != null) {
|
||||
PdfString s = outputIntentDict.getAsString(PdfName.S);
|
||||
if (s != null && s.toString().contains(standard)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public ArrayNode exploreStructureTree(List<Object> nodes) {
|
||||
ArrayNode elementsArray = objectMapper.createArrayNode();
|
||||
if (nodes != null) {
|
||||
for (Object obj : nodes) {
|
||||
if (obj instanceof PDStructureNode) {
|
||||
PDStructureNode node = (PDStructureNode) obj;
|
||||
ObjectNode elementNode = objectMapper.createObjectNode();
|
||||
|
||||
if (node instanceof PDStructureElement) {
|
||||
PDStructureElement structureElement = (PDStructureElement) node;
|
||||
elementNode.put("Type", structureElement.getStructureType());
|
||||
elementNode.put("Content", getContent(structureElement));
|
||||
|
||||
// Recursively explore child elements
|
||||
ArrayNode childElements = exploreStructureTree(structureElement.getKids());
|
||||
if (childElements.size() > 0) {
|
||||
elementNode.set("Children", childElements);
|
||||
}
|
||||
}
|
||||
elementsArray.add(elementNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
return elementsArray;
|
||||
}
|
||||
|
||||
|
||||
public String getContent(PDStructureElement structureElement) {
|
||||
StringBuilder contentBuilder = new StringBuilder();
|
||||
|
||||
for (Object item : structureElement.getKids()) {
|
||||
if (item instanceof COSString) {
|
||||
COSString cosString = (COSString) item;
|
||||
contentBuilder.append(cosString.getString());
|
||||
} else if (item instanceof PDStructureElement) {
|
||||
// For simplicity, we're handling only COSString and PDStructureElement here
|
||||
// but a more comprehensive method would handle other types too
|
||||
contentBuilder.append(getContent((PDStructureElement) item));
|
||||
}
|
||||
}
|
||||
|
||||
return contentBuilder.toString();
|
||||
}
|
||||
|
||||
|
||||
private String formatDate(Calendar calendar) {
|
||||
if (calendar != null) {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
return sdf.format(calendar.getTime());
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private String getPageModeDescription(PdfName pageMode) {
|
||||
return pageMode != null ? pageMode.toString().replaceFirst("/", "") : "Unknown";
|
||||
}
|
||||
}
|
||||
@@ -52,37 +52,37 @@ public class PasswordController {
|
||||
@RequestPart(required = true, value = "fileInput")
|
||||
@Parameter(description = "The input PDF file to which the password should be added", required = true)
|
||||
MultipartFile fileInput,
|
||||
@RequestParam(defaultValue = "", name = "ownerPassword")
|
||||
@RequestParam(value = "", name = "ownerPassword", required = false, defaultValue = "")
|
||||
@Parameter(description = "The owner password to be added to the PDF file (Restricts what can be done with the document once it is opened)")
|
||||
String ownerPassword,
|
||||
@RequestParam(defaultValue = "", name = "password")
|
||||
@RequestParam( name = "password", required = false, defaultValue = "")
|
||||
@Parameter(description = "The password to be added to the PDF file (Restricts the opening of the document itself.)")
|
||||
String password,
|
||||
@RequestParam(defaultValue = "128", name = "keyLength")
|
||||
@RequestParam( name = "keyLength", required = false, defaultValue = "256")
|
||||
@Parameter(description = "The length of the encryption key", schema = @Schema(allowableValues = {"40", "128", "256"}))
|
||||
int keyLength,
|
||||
@RequestParam(defaultValue = "false", name = "canAssembleDocument")
|
||||
@RequestParam( name = "canAssembleDocument", required = false)
|
||||
@Parameter(description = "Whether the document assembly is allowed", example = "false")
|
||||
boolean canAssembleDocument,
|
||||
@RequestParam(defaultValue = "false", name = "canExtractContent")
|
||||
@RequestParam( name = "canExtractContent", required = false)
|
||||
@Parameter(description = "Whether content extraction for accessibility is allowed", example = "false")
|
||||
boolean canExtractContent,
|
||||
@RequestParam(defaultValue = "false", name = "canExtractForAccessibility")
|
||||
@RequestParam( name = "canExtractForAccessibility", required = false)
|
||||
@Parameter(description = "Whether content extraction for accessibility is allowed", example = "false")
|
||||
boolean canExtractForAccessibility,
|
||||
@RequestParam(defaultValue = "false", name = "canFillInForm")
|
||||
@RequestParam( name = "canFillInForm", required = false)
|
||||
@Parameter(description = "Whether form filling is allowed", example = "false")
|
||||
boolean canFillInForm,
|
||||
@RequestParam(defaultValue = "false", name = "canModify")
|
||||
@RequestParam( name = "canModify", required = false)
|
||||
@Parameter(description = "Whether the document modification is allowed", example = "false")
|
||||
boolean canModify,
|
||||
@RequestParam(defaultValue = "false", name = "canModifyAnnotations")
|
||||
@RequestParam( name = "canModifyAnnotations", required = false)
|
||||
@Parameter(description = "Whether modification of annotations is allowed", example = "false")
|
||||
boolean canModifyAnnotations,
|
||||
@RequestParam(defaultValue = "false", name = "canPrint")
|
||||
@RequestParam(name = "canPrint", required = false)
|
||||
@Parameter(description = "Whether printing of the document is allowed", example = "false")
|
||||
boolean canPrint,
|
||||
@RequestParam(defaultValue = "false", name = "canPrintFaithful")
|
||||
@RequestParam( name = "canPrintFaithful", required = false)
|
||||
@Parameter(description = "Whether faithful printing is allowed", example = "false")
|
||||
boolean canPrintFaithful
|
||||
) throws IOException {
|
||||
@@ -98,15 +98,15 @@ public class PasswordController {
|
||||
ap.setCanPrint(!canPrint);
|
||||
ap.setCanPrintFaithful(!canPrintFaithful);
|
||||
StandardProtectionPolicy spp = new StandardProtectionPolicy(ownerPassword, password, ap);
|
||||
|
||||
|
||||
|
||||
spp.setEncryptionKeyLength(keyLength);
|
||||
|
||||
if(!"".equals(ownerPassword) || !"".equals(password)) {
|
||||
spp.setEncryptionKeyLength(keyLength);
|
||||
}
|
||||
spp.setPermissions(ap);
|
||||
|
||||
document.protect(spp);
|
||||
|
||||
if("".equals(ownerPassword) && "".equals(password))
|
||||
return WebResponseUtils.pdfDocToWebResponse(document, fileInput.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_permissions.pdf");
|
||||
return WebResponseUtils.pdfDocToWebResponse(document, fileInput.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_passworded.pdf");
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
package stirling.software.SPDF.controller.api.security;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.PDPage;
|
||||
import org.apache.pdfbox.pdmodel.PDPageContentStream;
|
||||
import org.apache.pdfbox.pdmodel.common.PDRectangle;
|
||||
import org.apache.pdfbox.pdmodel.graphics.image.LosslessFactory;
|
||||
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
|
||||
import org.apache.pdfbox.rendering.ImageType;
|
||||
import org.apache.pdfbox.rendering.PDFRenderer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import stirling.software.SPDF.model.PDFText;
|
||||
import stirling.software.SPDF.pdf.TextFinder;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
@RestController
|
||||
@Tag(name = "Security", description = "Security APIs")
|
||||
public class RedactController {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(RedactController.class);
|
||||
|
||||
|
||||
@PostMapping(value = "/auto-redact", consumes = "multipart/form-data")
|
||||
@Operation(summary = "Redacts listOfText in a PDF document",
|
||||
description = "This operation takes an input PDF file and redacts the provided listOfText. Input:PDF, Output:PDF, Type:SISO")
|
||||
public ResponseEntity<byte[]> redactPdf(
|
||||
@Parameter(description = "The input PDF file", required = true) @RequestParam("fileInput") MultipartFile file,
|
||||
@Parameter(description = "List of listOfText to redact from the PDF", required = true, schema = @Schema(type = "string")) @RequestParam("listOfText") String listOfTextString,
|
||||
@RequestParam(value = "useRegex", required = false) boolean useRegex,
|
||||
@RequestParam(value = "wholeWordSearch", required = false) boolean wholeWordSearchBool,
|
||||
@RequestParam(value = "redactColor", required = false, defaultValue = "#000000") String colorString,
|
||||
@RequestParam(value = "customPadding", required = false) float customPadding,
|
||||
@RequestParam(value = "convertPDFToImage", required = false) boolean convertPDFToImage) throws Exception {
|
||||
|
||||
System.out.println(listOfTextString);
|
||||
String[] listOfText = listOfTextString.split("\n");
|
||||
byte[] bytes = file.getBytes();
|
||||
PDDocument document = PDDocument.load(new ByteArrayInputStream(bytes));
|
||||
|
||||
Color redactColor;
|
||||
try {
|
||||
if (!colorString.startsWith("#")) {
|
||||
colorString = "#" + colorString;
|
||||
}
|
||||
redactColor = Color.decode(colorString);
|
||||
} catch (NumberFormatException e) {
|
||||
logger.warn("Invalid color string provided. Using default color BLACK for redaction.");
|
||||
redactColor = Color.BLACK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
for (String text : listOfText) {
|
||||
text = text.trim();
|
||||
System.out.println(text);
|
||||
TextFinder textFinder = new TextFinder(text, useRegex, wholeWordSearchBool);
|
||||
List<PDFText> foundTexts = textFinder.getTextLocations(document);
|
||||
redactFoundText(document, foundTexts, customPadding,redactColor);
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (convertPDFToImage) {
|
||||
PDDocument imageDocument = new PDDocument();
|
||||
PDFRenderer pdfRenderer = new PDFRenderer(document);
|
||||
for (int page = 0; page < document.getNumberOfPages(); ++page) {
|
||||
BufferedImage bim = pdfRenderer.renderImageWithDPI(page, 300, ImageType.RGB);
|
||||
PDPage newPage = new PDPage(new PDRectangle(bim.getWidth(), bim.getHeight()));
|
||||
imageDocument.addPage(newPage);
|
||||
PDImageXObject pdImage = LosslessFactory.createFromImage(imageDocument, bim);
|
||||
PDPageContentStream contentStream = new PDPageContentStream(imageDocument, newPage);
|
||||
contentStream.drawImage(pdImage, 0, 0);
|
||||
contentStream.close();
|
||||
}
|
||||
document.close();
|
||||
document = imageDocument;
|
||||
}
|
||||
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
document.save(baos);
|
||||
document.close();
|
||||
|
||||
byte[] pdfContent = baos.toByteArray();
|
||||
return WebResponseUtils.bytesToWebResponse(pdfContent,
|
||||
file.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_redacted.pdf");
|
||||
}
|
||||
|
||||
|
||||
private void redactFoundText(PDDocument document, List<PDFText> blocks, float customPadding, Color redactColor) throws IOException {
|
||||
var allPages = document.getDocumentCatalog().getPages();
|
||||
|
||||
for (PDFText block : blocks) {
|
||||
var page = allPages.get(block.getPageIndex());
|
||||
PDPageContentStream contentStream = new PDPageContentStream(document, page, PDPageContentStream.AppendMode.APPEND, true, true);
|
||||
contentStream.setNonStrokingColor(redactColor);
|
||||
float padding = (block.getY2() - block.getY1()) * 0.3f + customPadding;
|
||||
PDRectangle pageBox = page.getBBox();
|
||||
contentStream.addRect(block.getX1(), pageBox.getHeight() - block.getY1() - padding, block.getX2() - block.getX1(), block.getY2() - block.getY1() + 2 * padding);
|
||||
contentStream.fill();
|
||||
contentStream.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,30 +1,35 @@
|
||||
package stirling.software.SPDF.controller.api.security;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.pdfbox.cos.COSDictionary;
|
||||
import org.apache.pdfbox.cos.COSName;
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.PDDocumentCatalog;
|
||||
import org.apache.pdfbox.pdmodel.PDPage;
|
||||
import org.apache.pdfbox.pdmodel.PDResources;
|
||||
import org.apache.pdfbox.pdmodel.PDPageTree;
|
||||
import org.apache.pdfbox.pdmodel.PDResources;
|
||||
import org.apache.pdfbox.pdmodel.common.PDMetadata;
|
||||
import org.apache.pdfbox.pdmodel.common.PDStream;
|
||||
import org.apache.pdfbox.pdmodel.interactive.action.*;
|
||||
import org.apache.pdfbox.pdmodel.interactive.action.PDAction;
|
||||
import org.apache.pdfbox.pdmodel.interactive.action.PDActionJavaScript;
|
||||
import org.apache.pdfbox.pdmodel.interactive.action.PDActionLaunch;
|
||||
import org.apache.pdfbox.pdmodel.interactive.action.PDActionURI;
|
||||
import org.apache.pdfbox.pdmodel.interactive.action.PDFormFieldAdditionalActions;
|
||||
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation;
|
||||
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationLink;
|
||||
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationWidget;
|
||||
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
|
||||
import org.apache.pdfbox.pdmodel.interactive.form.PDField;
|
||||
import org.apache.pdfbox.pdmodel.interactive.form.PDNonTerminalField;
|
||||
import org.apache.pdfbox.pdmodel.interactive.form.PDTerminalField;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RequestPart;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
@RestController
|
||||
public class SanitizeController {
|
||||
|
||||
@@ -35,19 +40,19 @@ public class SanitizeController {
|
||||
@RequestPart(required = true, value = "fileInput")
|
||||
@Parameter(description = "The input PDF file to be sanitized")
|
||||
MultipartFile inputFile,
|
||||
@RequestParam(name = "removeJavaScript", required = false, defaultValue = "true")
|
||||
@RequestParam(name = "removeJavaScript", required = false, defaultValue = "false")
|
||||
@Parameter(description = "Remove JavaScript actions from the PDF if set to true")
|
||||
Boolean removeJavaScript,
|
||||
@RequestParam(name = "removeEmbeddedFiles", required = false, defaultValue = "true")
|
||||
@RequestParam(name = "removeEmbeddedFiles", required = false, defaultValue = "false")
|
||||
@Parameter(description = "Remove embedded files from the PDF if set to true")
|
||||
Boolean removeEmbeddedFiles,
|
||||
@RequestParam(name = "removeMetadata", required = false, defaultValue = "true")
|
||||
@RequestParam(name = "removeMetadata", required = false, defaultValue = "false")
|
||||
@Parameter(description = "Remove metadata from the PDF if set to true")
|
||||
Boolean removeMetadata,
|
||||
@RequestParam(name = "removeLinks", required = false, defaultValue = "true")
|
||||
@RequestParam(name = "removeLinks", required = false, defaultValue = "false")
|
||||
@Parameter(description = "Remove links from the PDF if set to true")
|
||||
Boolean removeLinks,
|
||||
@RequestParam(name = "removeFonts", required = false, defaultValue = "true")
|
||||
@RequestParam(name = "removeFonts", required = false, defaultValue = "false")
|
||||
@Parameter(description = "Remove fonts from the PDF if set to true")
|
||||
Boolean removeFonts) throws IOException {
|
||||
|
||||
@@ -75,8 +80,24 @@ public class SanitizeController {
|
||||
return WebResponseUtils.pdfDocToWebResponse(document, inputFile.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_sanitized.pdf");
|
||||
}
|
||||
}
|
||||
private void sanitizeJavaScript(PDDocument document) throws IOException {
|
||||
for (PDPage page : document.getPages()) {
|
||||
private void sanitizeJavaScript(PDDocument document) throws IOException {
|
||||
// Get the root dictionary (catalog) of the PDF
|
||||
PDDocumentCatalog catalog = document.getDocumentCatalog();
|
||||
|
||||
// Get the Names dictionary
|
||||
COSDictionary namesDict = (COSDictionary) catalog.getCOSObject().getDictionaryObject(COSName.NAMES);
|
||||
|
||||
if (namesDict != null) {
|
||||
// Get the JavaScript dictionary
|
||||
COSDictionary javaScriptDict = (COSDictionary) namesDict.getDictionaryObject(COSName.getPDFName("JavaScript"));
|
||||
|
||||
if (javaScriptDict != null) {
|
||||
// Remove the JavaScript dictionary
|
||||
namesDict.removeItem(COSName.getPDFName("JavaScript"));
|
||||
}
|
||||
}
|
||||
|
||||
for (PDPage page : document.getPages()) {
|
||||
for (PDAnnotation annotation : page.getAnnotations()) {
|
||||
if (annotation instanceof PDAnnotationWidget) {
|
||||
PDAnnotationWidget widget = (PDAnnotationWidget) annotation;
|
||||
@@ -89,13 +110,28 @@ public class SanitizeController {
|
||||
PDAcroForm acroForm = document.getDocumentCatalog().getAcroForm();
|
||||
if (acroForm != null) {
|
||||
for (PDField field : acroForm.getFields()) {
|
||||
if (field.getActions().getF() instanceof PDActionJavaScript) {
|
||||
field.getActions().setF(null);
|
||||
}
|
||||
PDFormFieldAdditionalActions actions = field.getActions();
|
||||
if(actions != null) {
|
||||
if (actions.getC() instanceof PDActionJavaScript) {
|
||||
actions.setC(null);
|
||||
}
|
||||
if (actions.getF() instanceof PDActionJavaScript) {
|
||||
actions.setF(null);
|
||||
}
|
||||
if (actions.getK() instanceof PDActionJavaScript) {
|
||||
actions.setK(null);
|
||||
}
|
||||
if (actions.getV() instanceof PDActionJavaScript) {
|
||||
actions.setV(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private void sanitizeEmbeddedFiles(PDDocument document) {
|
||||
PDPageTree allPages = document.getPages();
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package stirling.software.SPDF.controller.api.security;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
@@ -32,9 +30,9 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
@RestController
|
||||
@Tag(name = "Security", description = "Security APIs")
|
||||
@@ -44,8 +42,8 @@ public class WatermarkController {
|
||||
@Operation(summary = "Add watermark to a PDF file", description = "This endpoint adds a watermark to a given PDF file. Users can specify the watermark type (text or image), rotation, opacity, width spacer, and height spacer. Input:PDF Output:PDF Type:SISO")
|
||||
public ResponseEntity<byte[]> addWatermark(
|
||||
@RequestPart(required = true, value = "fileInput") @Parameter(description = "The input PDF file to add a watermark") MultipartFile pdfFile,
|
||||
@RequestPart(required = true) @Parameter(description = "The watermark type (text or image)") String watermarkType,
|
||||
@RequestPart(required = false) @Parameter(description = "The watermark text") String watermarkText,
|
||||
@RequestParam(required = true) @Parameter(description = "The watermark type (text or image)") String watermarkType,
|
||||
@RequestParam(required = false) @Parameter(description = "The watermark text") String watermarkText,
|
||||
@RequestPart(required = false) @Parameter(description = "The watermark image") MultipartFile watermarkImage,
|
||||
|
||||
@RequestParam(defaultValue = "roman", name = "alphabet") @Parameter(description = "The selected alphabet",
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
package stirling.software.SPDF.controller.web;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.core.io.support.ResourcePatternUtils;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Hidden;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import stirling.software.SPDF.config.security.UserService;
|
||||
import stirling.software.SPDF.model.User;
|
||||
import stirling.software.SPDF.repository.UserRepository;
|
||||
@Controller
|
||||
@Tag(name = "Account Security", description = "Account Security APIs")
|
||||
public class AccountWebController {
|
||||
|
||||
|
||||
@GetMapping("/login")
|
||||
public String login(HttpServletRequest request, Model model, Authentication authentication) {
|
||||
if (authentication != null && authentication.isAuthenticated()) {
|
||||
return "redirect:/";
|
||||
}
|
||||
|
||||
if (request.getParameter("error") != null) {
|
||||
|
||||
model.addAttribute("error", request.getParameter("error"));
|
||||
}
|
||||
if (request.getParameter("logout") != null) {
|
||||
|
||||
model.addAttribute("logoutMessage", "You have been logged out.");
|
||||
}
|
||||
|
||||
return "login";
|
||||
}
|
||||
@Autowired
|
||||
private UserRepository userRepository; // Assuming you have a repository for user operations
|
||||
|
||||
|
||||
@PreAuthorize("hasRole('ROLE_ADMIN')")
|
||||
@GetMapping("/addUsers")
|
||||
public String showAddUserForm(Model model, Authentication authentication) {
|
||||
List<User> allUsers = userRepository.findAll();
|
||||
model.addAttribute("users", allUsers);
|
||||
model.addAttribute("currentUsername", authentication.getName());
|
||||
return "addUsers";
|
||||
}
|
||||
|
||||
|
||||
|
||||
@GetMapping("/account")
|
||||
public String account(HttpServletRequest request, Model model, Authentication authentication) {
|
||||
if (authentication == null || !authentication.isAuthenticated()) {
|
||||
return "redirect:/";
|
||||
}
|
||||
if (authentication != null && authentication.isAuthenticated()) {
|
||||
Object principal = authentication.getPrincipal();
|
||||
|
||||
if (principal instanceof UserDetails) {
|
||||
// Cast the principal object to UserDetails
|
||||
UserDetails userDetails = (UserDetails) principal;
|
||||
|
||||
// Retrieve username and other attributes
|
||||
String username = userDetails.getUsername();
|
||||
|
||||
// Fetch user details from the database
|
||||
Optional<User> user = userRepository.findByUsername(username); // Assuming findByUsername method exists
|
||||
if (!user.isPresent()) {
|
||||
// Handle error appropriately
|
||||
return "redirect:/error"; // Example redirection in case of error
|
||||
}
|
||||
|
||||
// Convert settings map to JSON string
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
String settingsJson;
|
||||
try {
|
||||
settingsJson = objectMapper.writeValueAsString(user.get().getSettings());
|
||||
} catch (JsonProcessingException e) {
|
||||
// Handle JSON conversion error
|
||||
e.printStackTrace();
|
||||
return "redirect:/error"; // Example redirection in case of error
|
||||
}
|
||||
|
||||
// Add attributes to the model
|
||||
model.addAttribute("username", username);
|
||||
model.addAttribute("role", user.get().getRolesAsString());
|
||||
model.addAttribute("settings", settingsJson);
|
||||
}
|
||||
} else {
|
||||
return "redirect:/";
|
||||
}
|
||||
return "account";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -25,7 +25,14 @@ public class ConverterWebController {
|
||||
model.addAttribute("currentPage", "html-to-pdf");
|
||||
return "convert/html-to-pdf";
|
||||
}
|
||||
|
||||
@GetMapping("/markdown-to-pdf")
|
||||
@Hidden
|
||||
public String convertMarkdownToPdfForm(Model model) {
|
||||
model.addAttribute("currentPage", "markdown-to-pdf");
|
||||
return "convert/markdown-to-pdf";
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/url-to-pdf")
|
||||
@Hidden
|
||||
public String convertURLToPdfForm(Model model) {
|
||||
|
||||
@@ -24,10 +24,14 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Hidden;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
|
||||
@Controller
|
||||
@Tag(name = "General", description = "General APIs")
|
||||
public class GeneralWebController {
|
||||
|
||||
|
||||
|
||||
|
||||
@GetMapping("/pipeline")
|
||||
@Hidden
|
||||
public String pipelineForm(Model model) {
|
||||
@@ -97,6 +101,20 @@ public class GeneralWebController {
|
||||
return "pdf-organizer";
|
||||
}
|
||||
|
||||
@GetMapping("/extract-page")
|
||||
@Hidden
|
||||
public String extractPages(Model model) {
|
||||
model.addAttribute("currentPage", "extract-page");
|
||||
return "extract-page";
|
||||
}
|
||||
|
||||
@GetMapping("/pdf-to-single-page")
|
||||
@Hidden
|
||||
public String pdfToSinglePage(Model model) {
|
||||
model.addAttribute("currentPage", "pdf-to-single-page");
|
||||
return "pdf-to-single-page";
|
||||
}
|
||||
|
||||
@GetMapping("/rotate-pdf")
|
||||
@Hidden
|
||||
public String rotatePdfForm(Model model) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package stirling.software.SPDF.controller.web;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
@@ -7,6 +8,7 @@ import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Hidden;
|
||||
import stirling.software.SPDF.model.ApplicationProperties;
|
||||
|
||||
@Controller
|
||||
public class HomeWebController {
|
||||
@@ -31,18 +33,16 @@ public class HomeWebController {
|
||||
return "redirect:/";
|
||||
}
|
||||
|
||||
|
||||
@Autowired
|
||||
ApplicationProperties applicationProperties;
|
||||
|
||||
|
||||
@GetMapping(value = "/robots.txt", produces = MediaType.TEXT_PLAIN_VALUE)
|
||||
@ResponseBody
|
||||
@Hidden
|
||||
public String getRobotsTxt() {
|
||||
String allowGoogleVisibility = System.getProperty("ALLOW_GOOGLE_VISIBILITY");
|
||||
if (allowGoogleVisibility == null)
|
||||
allowGoogleVisibility = System.getenv("ALLOW_GOOGLE_VISIBILITY");
|
||||
if (allowGoogleVisibility == null)
|
||||
allowGoogleVisibility = "false";
|
||||
if (Boolean.parseBoolean(allowGoogleVisibility)) {
|
||||
Boolean allowGoogle = applicationProperties.getSystem().getGooglevisibility();
|
||||
if(Boolean.TRUE.equals(allowGoogle)) {
|
||||
return "User-agent: Googlebot\nAllow: /\n\nUser-agent: *\nAllow: /";
|
||||
} else {
|
||||
return "User-agent: Googlebot\nDisallow: /\n\nUser-agent: *\nDisallow: /";
|
||||
|
||||
@@ -1,8 +1,16 @@
|
||||
package stirling.software.SPDF.controller.web;
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
@@ -14,14 +22,32 @@ import io.micrometer.core.instrument.MeterRegistry;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import stirling.software.SPDF.config.StartupApplicationListener;
|
||||
import stirling.software.SPDF.model.ApplicationProperties;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1")
|
||||
@Tag(name = "API", description = "Info APIs")
|
||||
public class MetricsController {
|
||||
|
||||
|
||||
@Autowired
|
||||
ApplicationProperties applicationProperties;
|
||||
|
||||
|
||||
private final MeterRegistry meterRegistry;
|
||||
|
||||
private boolean metricsEnabled;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
Boolean metricsEnabled = applicationProperties.getMetrics().getEnabled();
|
||||
if(metricsEnabled == null)
|
||||
metricsEnabled = true;
|
||||
this.metricsEnabled = metricsEnabled;
|
||||
}
|
||||
|
||||
public MetricsController(MeterRegistry meterRegistry) {
|
||||
this.meterRegistry = meterRegistry;
|
||||
}
|
||||
@@ -29,18 +55,25 @@ public class MetricsController {
|
||||
@GetMapping("/status")
|
||||
@Operation(summary = "Application status and version",
|
||||
description = "This endpoint returns the status of the application and its version number.")
|
||||
public Map<String, String> getStatus() {
|
||||
public ResponseEntity<?> getStatus() {
|
||||
if (!metricsEnabled) {
|
||||
return ResponseEntity.status(HttpStatus.FORBIDDEN).body("This endpoint is disabled.");
|
||||
}
|
||||
|
||||
Map<String, String> status = new HashMap<>();
|
||||
status.put("status", "UP");
|
||||
status.put("version", getClass().getPackage().getImplementationVersion());
|
||||
return status;
|
||||
return ResponseEntity.ok(status);
|
||||
}
|
||||
|
||||
@GetMapping("/loads")
|
||||
@Operation(summary = "GET request count",
|
||||
description = "This endpoint returns the total count of GET requests or the count of GET requests for a specific endpoint.")
|
||||
public Double getPageLoads(@RequestParam(required = false, name = "endpoint") @Parameter(description = "endpoint") Optional<String> endpoint) {
|
||||
try {
|
||||
public ResponseEntity<?> getPageLoads(@RequestParam(required = false, name = "endpoint") @Parameter(description = "endpoint") Optional<String> endpoint) {
|
||||
if (!metricsEnabled) {
|
||||
return ResponseEntity.status(HttpStatus.FORBIDDEN).body("This endpoint is disabled.");
|
||||
}
|
||||
try {
|
||||
|
||||
double count = 0.0;
|
||||
|
||||
@@ -68,36 +101,165 @@ public class MetricsController {
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
return ResponseEntity.ok(count);
|
||||
} catch (Exception e) {
|
||||
return -1.0;
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/loads/all")
|
||||
@Operation(summary = "GET requests count for all endpoints",
|
||||
description = "This endpoint returns the count of GET requests for each endpoint.")
|
||||
public ResponseEntity<?> getAllEndpointLoads() {
|
||||
if (!metricsEnabled) {
|
||||
return ResponseEntity.status(HttpStatus.FORBIDDEN).body("This endpoint is disabled.");
|
||||
}
|
||||
try {
|
||||
Map<String, Double> counts = new HashMap<>();
|
||||
|
||||
for (Meter meter : meterRegistry.getMeters()) {
|
||||
if (meter.getId().getName().equals("http.requests")) {
|
||||
String method = meter.getId().getTag("method");
|
||||
if (method != null && method.equals("GET")) {
|
||||
String uri = meter.getId().getTag("uri");
|
||||
if (uri != null) {
|
||||
double currentCount = counts.getOrDefault(uri, 0.0);
|
||||
if (meter instanceof Counter) {
|
||||
currentCount += ((Counter) meter).count();
|
||||
}
|
||||
counts.put(uri, currentCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<EndpointCount> results = counts.entrySet().stream()
|
||||
.map(entry -> new EndpointCount(entry.getKey(), entry.getValue()))
|
||||
.sorted(Comparator.comparing(EndpointCount::getCount).reversed())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return ResponseEntity.ok(results);
|
||||
} catch (Exception e) {
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
|
||||
}
|
||||
}
|
||||
|
||||
public class EndpointCount {
|
||||
private String endpoint;
|
||||
private double count;
|
||||
|
||||
public EndpointCount(String endpoint, double count) {
|
||||
this.endpoint = endpoint;
|
||||
this.count = count;
|
||||
}
|
||||
public String getEndpoint() {
|
||||
return endpoint;
|
||||
}
|
||||
public void setEndpoint(String endpoint) {
|
||||
this.endpoint = endpoint;
|
||||
}
|
||||
public double getCount() {
|
||||
return count;
|
||||
}
|
||||
public void setCount(double count) {
|
||||
this.count = count;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/requests")
|
||||
@Operation(summary = "POST request count",
|
||||
description = "This endpoint returns the total count of POST requests or the count of POST requests for a specific endpoint.")
|
||||
public Double getTotalRequests(@RequestParam(required = false, name = "endpoint") @Parameter(description = "endpoint") Optional<String> endpoint) {
|
||||
try {
|
||||
Counter counter;
|
||||
if (endpoint.isPresent() && !endpoint.get().isBlank()) {
|
||||
if(!endpoint.get().startsWith("/")) {
|
||||
endpoint = Optional.of("/" + endpoint.get());
|
||||
}
|
||||
|
||||
System.out.println("loads " + endpoint.get() + " vs " + meterRegistry.get("http.requests").tags("uri", endpoint.get()).toString());
|
||||
counter = meterRegistry.get("http.requests")
|
||||
.tags("method", "POST", "uri", endpoint.get()).counter();
|
||||
} else {
|
||||
counter = meterRegistry.get("http.requests")
|
||||
.tags("method", "POST").counter();
|
||||
}
|
||||
return counter.count();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return 0.0;
|
||||
public ResponseEntity<?> getTotalRequests(@RequestParam(required = false, name = "endpoint") @Parameter(description = "endpoint") Optional<String> endpoint) {
|
||||
if (!metricsEnabled) {
|
||||
return ResponseEntity.status(HttpStatus.FORBIDDEN).body("This endpoint is disabled.");
|
||||
}
|
||||
try {
|
||||
double count = 0.0;
|
||||
|
||||
for (Meter meter : meterRegistry.getMeters()) {
|
||||
if (meter.getId().getName().equals("http.requests")) {
|
||||
String method = meter.getId().getTag("method");
|
||||
if (method != null && method.equals("POST")) {
|
||||
if (endpoint.isPresent() && !endpoint.get().isBlank()) {
|
||||
if (!endpoint.get().startsWith("/")) {
|
||||
endpoint = Optional.of("/" + endpoint.get());
|
||||
}
|
||||
if (endpoint.get().equals(meter.getId().getTag("uri"))) {
|
||||
if (meter instanceof Counter) {
|
||||
count += ((Counter) meter).count();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (meter instanceof Counter) {
|
||||
count += ((Counter) meter).count();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ResponseEntity.ok(count);
|
||||
} catch (Exception e) {
|
||||
return ResponseEntity.ok(-1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/requests/all")
|
||||
@Operation(summary = "POST requests count for all endpoints",
|
||||
description = "This endpoint returns the count of POST requests for each endpoint.")
|
||||
public ResponseEntity<?> getAllPostRequests() {
|
||||
if (!metricsEnabled) {
|
||||
return ResponseEntity.status(HttpStatus.FORBIDDEN).body("This endpoint is disabled.");
|
||||
}
|
||||
try {
|
||||
Map<String, Double> counts = new HashMap<>();
|
||||
|
||||
for (Meter meter : meterRegistry.getMeters()) {
|
||||
if (meter.getId().getName().equals("http.requests")) {
|
||||
String method = meter.getId().getTag("method");
|
||||
if (method != null && method.equals("POST")) {
|
||||
String uri = meter.getId().getTag("uri");
|
||||
if (uri != null) {
|
||||
double currentCount = counts.getOrDefault(uri, 0.0);
|
||||
if (meter instanceof Counter) {
|
||||
currentCount += ((Counter) meter).count();
|
||||
}
|
||||
counts.put(uri, currentCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<EndpointCount> results = counts.entrySet().stream()
|
||||
.map(entry -> new EndpointCount(entry.getKey(), entry.getValue()))
|
||||
.sorted(Comparator.comparing(EndpointCount::getCount).reversed())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return ResponseEntity.ok(results);
|
||||
} catch (Exception e) {
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/uptime")
|
||||
public ResponseEntity<?> getUptime() {
|
||||
if (!metricsEnabled) {
|
||||
return ResponseEntity.status(HttpStatus.FORBIDDEN).body("This endpoint is disabled.");
|
||||
}
|
||||
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
Duration uptime = Duration.between(StartupApplicationListener.startTime, now);
|
||||
return ResponseEntity.ok(formatDuration(uptime));
|
||||
}
|
||||
|
||||
private String formatDuration(Duration duration) {
|
||||
long days = duration.toDays();
|
||||
long hours = duration.toHoursPart();
|
||||
long minutes = duration.toMinutesPart();
|
||||
long seconds = duration.toSecondsPart();
|
||||
return String.format("%dd %dh %dm %ds", days, hours, minutes, seconds);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,15 @@ public class OtherWebController {
|
||||
modelAndView.addObject("currentPage", "extract-image-scans");
|
||||
return modelAndView;
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/show-javascript")
|
||||
@Hidden
|
||||
public String extractJavascriptForm(Model model) {
|
||||
model.addAttribute("currentPage", "show-javascript");
|
||||
return "other/show-javascript";
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/add-page-numbers")
|
||||
@Hidden
|
||||
public String addPageNumbersForm(Model model) {
|
||||
|
||||
@@ -10,6 +10,14 @@ import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
@Controller
|
||||
@Tag(name = "Security", description = "Security APIs")
|
||||
public class SecurityWebController {
|
||||
|
||||
@GetMapping("/auto-redact")
|
||||
@Hidden
|
||||
public String autoRedactForm(Model model) {
|
||||
model.addAttribute("currentPage", "auto-redact");
|
||||
return "security/auto-redact";
|
||||
}
|
||||
|
||||
@GetMapping("/add-password")
|
||||
@Hidden
|
||||
public String addPasswordForm(Model model) {
|
||||
@@ -50,4 +58,11 @@ public class SecurityWebController {
|
||||
model.addAttribute("currentPage", "sanitize-pdf");
|
||||
return "security/sanitize-pdf";
|
||||
}
|
||||
|
||||
@GetMapping("/get-info-on-pdf")
|
||||
@Hidden
|
||||
public String getInfo(Model model) {
|
||||
model.addAttribute("currentPage", "get-info-on-pdf");
|
||||
return "security/get-info-on-pdf";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
package stirling.software.SPDF.model;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
|
||||
public class ApiKeyAuthenticationToken extends AbstractAuthenticationToken {
|
||||
|
||||
private final Object principal;
|
||||
private Object credentials;
|
||||
|
||||
public ApiKeyAuthenticationToken(String apiKey) {
|
||||
super(null);
|
||||
this.principal = null;
|
||||
this.credentials = apiKey;
|
||||
setAuthenticated(false);
|
||||
}
|
||||
|
||||
public ApiKeyAuthenticationToken(Object principal, String apiKey, Collection<? extends GrantedAuthority> authorities) {
|
||||
super(authorities);
|
||||
this.principal = principal; // principal can be a UserDetails object
|
||||
this.credentials = apiKey;
|
||||
super.setAuthenticated(true); // this authentication is trusted
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getCredentials() {
|
||||
return credentials;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getPrincipal() {
|
||||
return principal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
|
||||
if (isAuthenticated) {
|
||||
throw new IllegalArgumentException("Cannot set this token to trusted. Use constructor which takes a GrantedAuthority list instead.");
|
||||
}
|
||||
super.setAuthenticated(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void eraseCredentials() {
|
||||
super.eraseCredentials();
|
||||
credentials = null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,330 @@
|
||||
package stirling.software.SPDF.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
|
||||
import stirling.software.SPDF.config.YamlPropertySourceFactory;
|
||||
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "")
|
||||
@PropertySource(value = "file:./configs/settings.yml", factory = YamlPropertySourceFactory.class)
|
||||
public class ApplicationProperties {
|
||||
private Security security;
|
||||
private System system;
|
||||
private Ui ui;
|
||||
private Endpoints endpoints;
|
||||
private Metrics metrics;
|
||||
private AutomaticallyGenerated automaticallyGenerated;
|
||||
private AutoPipeline autoPipeline;
|
||||
|
||||
public AutoPipeline getAutoPipeline() {
|
||||
return autoPipeline != null ? autoPipeline : new AutoPipeline();
|
||||
}
|
||||
|
||||
public void setAutoPipeline(AutoPipeline autoPipeline) {
|
||||
this.autoPipeline = autoPipeline;
|
||||
}
|
||||
|
||||
public Security getSecurity() {
|
||||
return security != null ? security : new Security();
|
||||
}
|
||||
|
||||
public void setSecurity(Security security) {
|
||||
this.security = security;
|
||||
}
|
||||
|
||||
public System getSystem() {
|
||||
return system != null ? system : new System();
|
||||
}
|
||||
|
||||
public void setSystem(System system) {
|
||||
this.system = system;
|
||||
}
|
||||
|
||||
public Ui getUi() {
|
||||
return ui != null ? ui : new Ui();
|
||||
}
|
||||
|
||||
public void setUi(Ui ui) {
|
||||
this.ui = ui;
|
||||
}
|
||||
|
||||
public Endpoints getEndpoints() {
|
||||
return endpoints != null ? endpoints : new Endpoints();
|
||||
}
|
||||
|
||||
public void setEndpoints(Endpoints endpoints) {
|
||||
this.endpoints = endpoints;
|
||||
}
|
||||
|
||||
public Metrics getMetrics() {
|
||||
return metrics != null ? metrics : new Metrics();
|
||||
}
|
||||
|
||||
public void setMetrics(Metrics metrics) {
|
||||
this.metrics = metrics;
|
||||
}
|
||||
|
||||
public AutomaticallyGenerated getAutomaticallyGenerated() {
|
||||
return automaticallyGenerated != null ? automaticallyGenerated : new AutomaticallyGenerated();
|
||||
}
|
||||
|
||||
public void setAutomaticallyGenerated(AutomaticallyGenerated automaticallyGenerated) {
|
||||
this.automaticallyGenerated = automaticallyGenerated;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ApplicationProperties [security=" + security + ", system=" + system + ", ui=" + ui + ", endpoints="
|
||||
+ endpoints + ", metrics=" + metrics + ", automaticallyGenerated=" + automaticallyGenerated
|
||||
+ ", autoPipeline=" + autoPipeline + "]";
|
||||
}
|
||||
|
||||
public static class AutoPipeline {
|
||||
private String outputFolder;
|
||||
|
||||
public String getOutputFolder() {
|
||||
return outputFolder;
|
||||
}
|
||||
|
||||
public void setOutputFolder(String outputFolder) {
|
||||
this.outputFolder = outputFolder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AutoPipeline [outputFolder=" + outputFolder + "]";
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
public static class Security {
|
||||
private Boolean enableLogin;
|
||||
private InitialLogin initialLogin;
|
||||
private Boolean csrfDisabled;
|
||||
|
||||
public Boolean getEnableLogin() {
|
||||
return enableLogin;
|
||||
}
|
||||
|
||||
public void setEnableLogin(Boolean enableLogin) {
|
||||
this.enableLogin = enableLogin;
|
||||
}
|
||||
|
||||
public InitialLogin getInitialLogin() {
|
||||
return initialLogin != null ? initialLogin : new InitialLogin();
|
||||
}
|
||||
|
||||
public void setInitialLogin(InitialLogin initialLogin) {
|
||||
this.initialLogin = initialLogin;
|
||||
}
|
||||
|
||||
public Boolean getCsrfDisabled() {
|
||||
return csrfDisabled;
|
||||
}
|
||||
|
||||
public void setCsrfDisabled(Boolean csrfDisabled) {
|
||||
this.csrfDisabled = csrfDisabled;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Security [enableLogin=" + enableLogin + ", initialLogin=" + initialLogin + ", csrfDisabled="
|
||||
+ csrfDisabled + "]";
|
||||
}
|
||||
|
||||
|
||||
public static class InitialLogin {
|
||||
|
||||
private String username;
|
||||
private String password;
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "InitialLogin [username=" + username + ", password=" + (password != null && !password.isEmpty() ? "MASKED" : "NULL") + "]";
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static class System {
|
||||
private String defaultLocale;
|
||||
private Boolean googlevisibility;
|
||||
private String rootURIPath;
|
||||
private String customStaticFilePath;
|
||||
private Integer maxFileSize;
|
||||
|
||||
public String getDefaultLocale() {
|
||||
return defaultLocale;
|
||||
}
|
||||
|
||||
public void setDefaultLocale(String defaultLocale) {
|
||||
this.defaultLocale = defaultLocale;
|
||||
}
|
||||
|
||||
public Boolean getGooglevisibility() {
|
||||
return googlevisibility;
|
||||
}
|
||||
|
||||
public void setGooglevisibility(Boolean googlevisibility) {
|
||||
this.googlevisibility = googlevisibility;
|
||||
}
|
||||
|
||||
public String getRootURIPath() {
|
||||
return rootURIPath;
|
||||
}
|
||||
|
||||
public void setRootURIPath(String rootURIPath) {
|
||||
this.rootURIPath = rootURIPath;
|
||||
}
|
||||
|
||||
public String getCustomStaticFilePath() {
|
||||
return customStaticFilePath;
|
||||
}
|
||||
|
||||
public void setCustomStaticFilePath(String customStaticFilePath) {
|
||||
this.customStaticFilePath = customStaticFilePath;
|
||||
}
|
||||
|
||||
public Integer getMaxFileSize() {
|
||||
return maxFileSize;
|
||||
}
|
||||
|
||||
public void setMaxFileSize(Integer maxFileSize) {
|
||||
this.maxFileSize = maxFileSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "System [defaultLocale=" + defaultLocale + ", googlevisibility=" + googlevisibility + ", rootURIPath="
|
||||
+ rootURIPath + ", customStaticFilePath=" + customStaticFilePath + ", maxFileSize=" + maxFileSize
|
||||
+ "]";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public static class Ui {
|
||||
private String appName;
|
||||
private String homeDescription;
|
||||
private String appNameNavbar;
|
||||
|
||||
public String getAppName() {
|
||||
return appName;
|
||||
}
|
||||
|
||||
public void setAppName(String appName) {
|
||||
this.appName = appName;
|
||||
}
|
||||
|
||||
public String getHomeDescription() {
|
||||
return homeDescription;
|
||||
}
|
||||
|
||||
public void setHomeDescription(String homeDescription) {
|
||||
this.homeDescription = homeDescription;
|
||||
}
|
||||
|
||||
public String getAppNameNavbar() {
|
||||
return appNameNavbar;
|
||||
}
|
||||
|
||||
public void setAppNameNavbar(String appNameNavbar) {
|
||||
this.appNameNavbar = appNameNavbar;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "UserInterface [appName=" + appName + ", homeDescription=" + homeDescription + ", appNameNavbar=" + appNameNavbar + "]";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class Endpoints {
|
||||
private List<String> toRemove;
|
||||
private List<String> groupsToRemove;
|
||||
|
||||
public List<String> getToRemove() {
|
||||
return toRemove;
|
||||
}
|
||||
|
||||
public void setToRemove(List<String> toRemove) {
|
||||
this.toRemove = toRemove;
|
||||
}
|
||||
|
||||
public List<String> getGroupsToRemove() {
|
||||
return groupsToRemove;
|
||||
}
|
||||
|
||||
public void setGroupsToRemove(List<String> groupsToRemove) {
|
||||
this.groupsToRemove = groupsToRemove;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Endpoints [toRemove=" + toRemove + ", groupsToRemove=" + groupsToRemove + "]";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public static class Metrics {
|
||||
private Boolean enabled;
|
||||
|
||||
public Boolean getEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(Boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Metrics [enabled=" + enabled + "]";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public static class AutomaticallyGenerated {
|
||||
private String key;
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public void setKey(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AutomaticallyGenerated [key=" + (key != null && !key.isEmpty() ? "MASKED" : "NULL") + "]";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
64
src/main/java/stirling/software/SPDF/model/Authority.java
Normal file
64
src/main/java/stirling/software/SPDF/model/Authority.java
Normal file
@@ -0,0 +1,64 @@
|
||||
package stirling.software.SPDF.model;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name = "authorities")
|
||||
public class Authority {
|
||||
|
||||
public Authority() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
public Authority(String authority, User user) {
|
||||
this.authority = authority;
|
||||
this.user = user;
|
||||
user.getAuthorities().add(this);
|
||||
}
|
||||
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@Column(name = "authority")
|
||||
private String authority;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "user_id")
|
||||
private User user;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getAuthority() {
|
||||
return authority;
|
||||
}
|
||||
|
||||
public void setAuthority(String authority) {
|
||||
this.authority = authority;
|
||||
}
|
||||
|
||||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public void setUser(User user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
42
src/main/java/stirling/software/SPDF/model/PDFText.java
Normal file
42
src/main/java/stirling/software/SPDF/model/PDFText.java
Normal file
@@ -0,0 +1,42 @@
|
||||
package stirling.software.SPDF.model;
|
||||
public class PDFText {
|
||||
private final int pageIndex;
|
||||
private final float x1;
|
||||
private final float y1;
|
||||
private final float x2;
|
||||
private final float y2;
|
||||
private final String text;
|
||||
|
||||
public PDFText(int pageIndex, float x1, float y1, float x2, float y2, String text) {
|
||||
this.pageIndex = pageIndex;
|
||||
this.x1 = x1;
|
||||
this.y1 = y1;
|
||||
this.x2 = x2;
|
||||
this.y2 = y2;
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public int getPageIndex() {
|
||||
return pageIndex;
|
||||
}
|
||||
|
||||
public float getX1() {
|
||||
return x1;
|
||||
}
|
||||
|
||||
public float getY1() {
|
||||
return y1;
|
||||
}
|
||||
|
||||
public float getX2() {
|
||||
return x2;
|
||||
}
|
||||
|
||||
public float getY2() {
|
||||
return y2;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package stirling.software.SPDF.model;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name = "persistent_logins")
|
||||
public class PersistentLogin {
|
||||
|
||||
@Id
|
||||
@Column(name = "series")
|
||||
private String series;
|
||||
|
||||
@Column(name = "username", length = 64, nullable = false)
|
||||
private String username;
|
||||
|
||||
@Column(name = "token", length = 64, nullable = false)
|
||||
private String token;
|
||||
|
||||
@Column(name = "last_used", nullable = false)
|
||||
private Date lastUsed;
|
||||
|
||||
public String getSeries() {
|
||||
return series;
|
||||
}
|
||||
|
||||
public void setSeries(String series) {
|
||||
this.series = series;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getToken() {
|
||||
return token;
|
||||
}
|
||||
|
||||
public void setToken(String token) {
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
public Date getLastUsed() {
|
||||
return lastUsed;
|
||||
}
|
||||
|
||||
public void setLastUsed(Date lastUsed) {
|
||||
this.lastUsed = lastUsed;
|
||||
}
|
||||
|
||||
|
||||
// Getters, setters, etc.
|
||||
}
|
||||
50
src/main/java/stirling/software/SPDF/model/Role.java
Normal file
50
src/main/java/stirling/software/SPDF/model/Role.java
Normal file
@@ -0,0 +1,50 @@
|
||||
package stirling.software.SPDF.model;
|
||||
public enum Role {
|
||||
|
||||
// Unlimited access
|
||||
ADMIN("ROLE_ADMIN", Integer.MAX_VALUE, Integer.MAX_VALUE),
|
||||
|
||||
// Unlimited access
|
||||
USER("ROLE_USER", Integer.MAX_VALUE, Integer.MAX_VALUE),
|
||||
|
||||
// 40 API calls Per Day, 40 web calls
|
||||
LIMITED_API_USER("ROLE_LIMITED_API_USER", 40, 40),
|
||||
|
||||
// 20 API calls Per Day, 20 web calls
|
||||
EXTRA_LIMITED_API_USER("ROLE_EXTRA_LIMITED_API_USER", 20, 20),
|
||||
|
||||
// 0 API calls per day and 20 web calls
|
||||
WEB_ONLY_USER("ROLE_WEB_ONLY_USER", 0, 20);
|
||||
|
||||
private final String roleId;
|
||||
private final int apiCallsPerDay;
|
||||
private final int webCallsPerDay;
|
||||
|
||||
Role(String roleId, int apiCallsPerDay, int webCallsPerDay) {
|
||||
this.roleId = roleId;
|
||||
this.apiCallsPerDay = apiCallsPerDay;
|
||||
this.webCallsPerDay = webCallsPerDay;
|
||||
}
|
||||
|
||||
public String getRoleId() {
|
||||
return roleId;
|
||||
}
|
||||
|
||||
public int getApiCallsPerDay() {
|
||||
return apiCallsPerDay;
|
||||
}
|
||||
|
||||
public int getWebCallsPerDay() {
|
||||
return webCallsPerDay;
|
||||
}
|
||||
|
||||
public static Role fromString(String roleId) {
|
||||
for (Role role : Role.values()) {
|
||||
if (role.getRoleId().equalsIgnoreCase(roleId)) {
|
||||
return role;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("No Role defined for id: " + roleId);
|
||||
}
|
||||
|
||||
}
|
||||
124
src/main/java/stirling/software/SPDF/model/User.java
Normal file
124
src/main/java/stirling/software/SPDF/model/User.java
Normal file
@@ -0,0 +1,124 @@
|
||||
package stirling.software.SPDF.model;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import jakarta.persistence.CascadeType;
|
||||
import jakarta.persistence.CollectionTable;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.ElementCollection;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.MapKeyColumn;
|
||||
import jakarta.persistence.OneToMany;
|
||||
import jakarta.persistence.Table;
|
||||
@Entity
|
||||
@Table(name = "users")
|
||||
public class User {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "user_id")
|
||||
private Long id;
|
||||
|
||||
@Column(name = "username", unique = true)
|
||||
private String username;
|
||||
|
||||
@Column(name = "password")
|
||||
private String password;
|
||||
|
||||
@Column(name = "apiKey")
|
||||
private String apiKey;
|
||||
|
||||
@Column(name = "enabled")
|
||||
private boolean enabled;
|
||||
|
||||
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "user")
|
||||
private Set<Authority> authorities = new HashSet<>();
|
||||
|
||||
@ElementCollection
|
||||
@MapKeyColumn(name = "setting_key")
|
||||
@Column(name = "setting_value")
|
||||
@CollectionTable(name = "user_settings", joinColumns = @JoinColumn(name = "user_id"))
|
||||
private Map<String, String> settings = new HashMap<>(); // Key-value pairs of settings.
|
||||
|
||||
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getApiKey() {
|
||||
return apiKey;
|
||||
}
|
||||
|
||||
public void setApiKey(String apiKey) {
|
||||
this.apiKey = apiKey;
|
||||
}
|
||||
|
||||
public Map<String, String> getSettings() {
|
||||
return settings;
|
||||
}
|
||||
|
||||
public void setSettings(Map<String, String> settings) {
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public Set<Authority> getAuthorities() {
|
||||
return authorities;
|
||||
}
|
||||
|
||||
public void setAuthorities(Set<Authority> authorities) {
|
||||
this.authorities = authorities;
|
||||
}
|
||||
|
||||
public void addAuthorities(Set<Authority> authorities) {
|
||||
this.authorities.addAll(authorities);
|
||||
}
|
||||
public void addAuthority(Authority authorities) {
|
||||
this.authorities.add(authorities);
|
||||
}
|
||||
|
||||
public String getRolesAsString() {
|
||||
return this.authorities.stream()
|
||||
.map(Authority::getAuthority)
|
||||
.collect(Collectors.joining(", "));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
90
src/main/java/stirling/software/SPDF/pdf/TextFinder.java
Normal file
90
src/main/java/stirling/software/SPDF/pdf/TextFinder.java
Normal file
@@ -0,0 +1,90 @@
|
||||
package stirling.software.SPDF.pdf;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.text.PDFTextStripper;
|
||||
import org.apache.pdfbox.text.TextPosition;
|
||||
|
||||
import stirling.software.SPDF.model.PDFText;
|
||||
|
||||
public class TextFinder extends PDFTextStripper {
|
||||
|
||||
private final String searchText;
|
||||
private final boolean useRegex;
|
||||
private final boolean wholeWordSearch;
|
||||
private final List<PDFText> textOccurrences = new ArrayList<>();
|
||||
|
||||
public TextFinder(String searchText, boolean useRegex, boolean wholeWordSearch) throws IOException {
|
||||
this.searchText = searchText.toLowerCase();
|
||||
this.useRegex = useRegex;
|
||||
this.wholeWordSearch = wholeWordSearch;
|
||||
setSortByPosition(true);
|
||||
}
|
||||
|
||||
private List<Integer> findOccurrencesInText(String searchText, String content) {
|
||||
List<Integer> indexes = new ArrayList<>();
|
||||
Pattern pattern;
|
||||
|
||||
if (useRegex) {
|
||||
// Use regex-based search
|
||||
pattern = wholeWordSearch
|
||||
? Pattern.compile("(\\b|_|\\.)" + searchText + "(\\b|_|\\.)")
|
||||
: Pattern.compile(searchText);
|
||||
} else {
|
||||
// Use normal text search
|
||||
pattern = wholeWordSearch
|
||||
? Pattern.compile("(\\b|_|\\.)" + Pattern.quote(searchText) + "(\\b|_|\\.)")
|
||||
: Pattern.compile(Pattern.quote(searchText));
|
||||
}
|
||||
|
||||
Matcher matcher = pattern.matcher(content);
|
||||
while (matcher.find()) {
|
||||
indexes.add(matcher.start());
|
||||
}
|
||||
return indexes;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeString(String text, List<TextPosition> textPositions) {
|
||||
for (Integer index : findOccurrencesInText(searchText, text.toLowerCase())) {
|
||||
if (index + searchText.length() <= textPositions.size()) {
|
||||
// Initial values based on the first character
|
||||
TextPosition first = textPositions.get(index);
|
||||
float minX = first.getX();
|
||||
float minY = first.getY();
|
||||
float maxX = first.getX() + first.getWidth();
|
||||
float maxY = first.getY() + first.getHeight();
|
||||
|
||||
// Loop over the rest of the characters and adjust bounding box values
|
||||
for (int i = index; i < index + searchText.length(); i++) {
|
||||
TextPosition position = textPositions.get(i);
|
||||
minX = Math.min(minX, position.getX());
|
||||
minY = Math.min(minY, position.getY());
|
||||
maxX = Math.max(maxX, position.getX() + position.getWidth());
|
||||
maxY = Math.max(maxY, position.getY() + position.getHeight());
|
||||
}
|
||||
|
||||
textOccurrences.add(new PDFText(
|
||||
getCurrentPageNo() - 1,
|
||||
minX,
|
||||
minY,
|
||||
maxX,
|
||||
maxY,
|
||||
text
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<PDFText> getTextLocations(PDDocument document) throws Exception {
|
||||
this.getText(document);
|
||||
System.out.println("Found " + textOccurrences.size() + " occurrences of '" + searchText + "' in the document.");
|
||||
|
||||
return textOccurrences;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package stirling.software.SPDF.repository;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import stirling.software.SPDF.model.Authority;
|
||||
|
||||
public interface AuthorityRepository extends JpaRepository<Authority, Long> {
|
||||
//Set<Authority> findByUsername(String username);
|
||||
Set<Authority> findByUser_Username(String username);
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package stirling.software.SPDF.repository;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.web.authentication.rememberme.PersistentRememberMeToken;
|
||||
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
|
||||
|
||||
import stirling.software.SPDF.model.PersistentLogin;
|
||||
|
||||
public class JPATokenRepositoryImpl implements PersistentTokenRepository {
|
||||
|
||||
@Autowired
|
||||
private PersistentLoginRepository persistentLoginRepository;
|
||||
|
||||
@Override
|
||||
public void createNewToken(PersistentRememberMeToken token) {
|
||||
PersistentLogin newToken = new PersistentLogin();
|
||||
newToken.setSeries(token.getSeries());
|
||||
newToken.setUsername(token.getUsername());
|
||||
newToken.setToken(token.getTokenValue());
|
||||
newToken.setLastUsed(token.getDate());
|
||||
persistentLoginRepository.save(newToken);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateToken(String series, String tokenValue, Date lastUsed) {
|
||||
PersistentLogin existingToken = persistentLoginRepository.findById(series).orElse(null);
|
||||
if (existingToken != null) {
|
||||
existingToken.setToken(tokenValue);
|
||||
existingToken.setLastUsed(lastUsed);
|
||||
persistentLoginRepository.save(existingToken);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PersistentRememberMeToken getTokenForSeries(String seriesId) {
|
||||
PersistentLogin token = persistentLoginRepository.findById(seriesId).orElse(null);
|
||||
if (token != null) {
|
||||
return new PersistentRememberMeToken(token.getUsername(), token.getSeries(), token.getToken(), token.getLastUsed());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeUserTokens(String username) {
|
||||
for (PersistentLogin token : persistentLoginRepository.findAll()) {
|
||||
if (token.getUsername().equals(username)) {
|
||||
persistentLoginRepository.delete(token);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package stirling.software.SPDF.repository;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import stirling.software.SPDF.model.PersistentLogin;
|
||||
|
||||
public interface PersistentLoginRepository extends JpaRepository<PersistentLogin, String> {
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package stirling.software.SPDF.repository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import stirling.software.SPDF.model.User;
|
||||
|
||||
public interface UserRepository extends JpaRepository<User, String> {
|
||||
Optional<User> findByUsername(String username);
|
||||
User findByApiKey(String apiKey);
|
||||
}
|
||||
|
||||
95
src/main/java/stirling/software/SPDF/utils/FileToPdf.java
Normal file
95
src/main/java/stirling/software/SPDF/utils/FileToPdf.java
Normal file
@@ -0,0 +1,95 @@
|
||||
package stirling.software.SPDF.utils;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult;
|
||||
|
||||
public class FileToPdf {
|
||||
public static byte[] convertHtmlToPdf(byte[] fileBytes, String fileName) throws IOException, InterruptedException {
|
||||
|
||||
Path tempOutputFile = Files.createTempFile("output_", ".pdf");
|
||||
Path tempInputFile = null;
|
||||
byte[] pdfBytes;
|
||||
try {
|
||||
if (fileName.endsWith(".html")) {
|
||||
tempInputFile = Files.createTempFile("input_", ".html");
|
||||
Files.write(tempInputFile, fileBytes);
|
||||
} else {
|
||||
tempInputFile = unzipAndGetMainHtml(fileBytes);
|
||||
}
|
||||
|
||||
List<String> command = new ArrayList<>();
|
||||
command.add("weasyprint");
|
||||
command.add(tempInputFile.toString());
|
||||
command.add(tempOutputFile.toString());
|
||||
ProcessExecutorResult returnCode;
|
||||
if (fileName.endsWith(".zip")) {
|
||||
returnCode = ProcessExecutor.getInstance(ProcessExecutor.Processes.WEASYPRINT)
|
||||
.runCommandWithOutputHandling(command, tempInputFile.getParent().toFile());
|
||||
} else {
|
||||
|
||||
returnCode = ProcessExecutor.getInstance(ProcessExecutor.Processes.WEASYPRINT)
|
||||
.runCommandWithOutputHandling(command);
|
||||
}
|
||||
|
||||
pdfBytes = Files.readAllBytes(tempOutputFile);
|
||||
} finally {
|
||||
// Clean up temporary files
|
||||
Files.delete(tempOutputFile);
|
||||
Files.delete(tempInputFile);
|
||||
|
||||
if (fileName.endsWith(".zip")) {
|
||||
GeneralUtils.deleteDirectory(tempInputFile.getParent());
|
||||
}
|
||||
}
|
||||
|
||||
return pdfBytes;
|
||||
}
|
||||
|
||||
|
||||
private static Path unzipAndGetMainHtml(byte[] fileBytes) throws IOException {
|
||||
Path tempDirectory = Files.createTempDirectory("unzipped_");
|
||||
try (ZipInputStream zipIn = new ZipInputStream(new ByteArrayInputStream(fileBytes))) {
|
||||
ZipEntry entry = zipIn.getNextEntry();
|
||||
while (entry != null) {
|
||||
Path filePath = tempDirectory.resolve(entry.getName());
|
||||
if (entry.isDirectory()) {
|
||||
Files.createDirectories(filePath); // Explicitly create the directory structure
|
||||
} else {
|
||||
Files.createDirectories(filePath.getParent()); // Create parent directories if they don't exist
|
||||
Files.copy(zipIn, filePath);
|
||||
}
|
||||
zipIn.closeEntry();
|
||||
entry = zipIn.getNextEntry();
|
||||
}
|
||||
}
|
||||
|
||||
//search for the main HTML file.
|
||||
try (Stream<Path> walk = Files.walk(tempDirectory)) {
|
||||
List<Path> htmlFiles = walk.filter(file -> file.toString().endsWith(".html"))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (htmlFiles.isEmpty()) {
|
||||
throw new IOException("No HTML files found in the unzipped directory.");
|
||||
}
|
||||
|
||||
// Prioritize 'index.html' if it exists, otherwise use the first .html file
|
||||
for (Path htmlFile : htmlFiles) {
|
||||
if (htmlFile.getFileName().toString().equals("index.html")) {
|
||||
return htmlFile;
|
||||
}
|
||||
}
|
||||
|
||||
return htmlFiles.get(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,8 @@ import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult;
|
||||
|
||||
public class PDFToFile {
|
||||
public ResponseEntity<byte[]> processPdfToOfficeFormat(MultipartFile inputFile, String outputFormat, String libreOfficeFilter) throws IOException, InterruptedException {
|
||||
|
||||
@@ -53,7 +55,7 @@ public class PDFToFile {
|
||||
// Run the LibreOffice command
|
||||
List<String> command = new ArrayList<>(
|
||||
Arrays.asList("soffice", "--infilter=" + libreOfficeFilter, "--convert-to", outputFormat, "--outdir", tempOutputDir.toString(), tempInputFile.toString()));
|
||||
int returnCode = ProcessExecutor.getInstance(ProcessExecutor.Processes.LIBRE_OFFICE).runCommandWithOutputHandling(command);
|
||||
ProcessExecutorResult returnCode = ProcessExecutor.getInstance(ProcessExecutor.Processes.LIBRE_OFFICE).runCommandWithOutputHandling(command);
|
||||
|
||||
// Get output files
|
||||
List<File> outputFiles = Arrays.asList(tempOutputDir.toFile().listFiles());
|
||||
|
||||
@@ -32,10 +32,6 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import com.itextpdf.kernel.pdf.PdfPage;
|
||||
import com.itextpdf.kernel.pdf.canvas.parser.PdfTextExtractor;
|
||||
import com.itextpdf.kernel.pdf.canvas.parser.listener.SimpleTextExtractionStrategy;
|
||||
|
||||
import stirling.software.SPDF.pdf.ImageFinder;
|
||||
|
||||
public class PdfUtils {
|
||||
|
||||
@@ -37,11 +37,12 @@ public class ProcessExecutor {
|
||||
private ProcessExecutor(int semaphoreLimit) {
|
||||
this.semaphore = new Semaphore(semaphoreLimit);
|
||||
}
|
||||
public int runCommandWithOutputHandling(List<String> command) throws IOException, InterruptedException {
|
||||
public ProcessExecutorResult runCommandWithOutputHandling(List<String> command) throws IOException, InterruptedException {
|
||||
return runCommandWithOutputHandling(command, null);
|
||||
}
|
||||
public int runCommandWithOutputHandling(List<String> command, File workingDirectory) throws IOException, InterruptedException {
|
||||
public ProcessExecutorResult runCommandWithOutputHandling(List<String> command, File workingDirectory) throws IOException, InterruptedException {
|
||||
int exitCode = 1;
|
||||
String messages = "";
|
||||
semaphore.acquire();
|
||||
try {
|
||||
|
||||
@@ -89,14 +90,16 @@ public class ProcessExecutor {
|
||||
// Wait for the reader threads to finish
|
||||
errorReaderThread.join();
|
||||
outputReaderThread.join();
|
||||
|
||||
|
||||
if (outputLines.size() > 0) {
|
||||
String outputMessage = String.join("\n", outputLines);
|
||||
messages += outputMessage;
|
||||
System.out.println("Command output:\n" + outputMessage);
|
||||
}
|
||||
|
||||
if (errorLines.size() > 0) {
|
||||
String errorMessage = String.join("\n", errorLines);
|
||||
messages += errorMessage;
|
||||
System.out.println("Command error output:\n" + errorMessage);
|
||||
if (exitCode != 0) {
|
||||
throw new IOException("Command process failed with exit code " + exitCode + ". Error message: " + errorMessage);
|
||||
@@ -105,7 +108,28 @@ public class ProcessExecutor {
|
||||
} finally {
|
||||
semaphore.release();
|
||||
}
|
||||
return exitCode;
|
||||
return new ProcessExecutorResult(exitCode, messages);
|
||||
}
|
||||
public class ProcessExecutorResult{
|
||||
int rc;
|
||||
String messages;
|
||||
public ProcessExecutorResult(int rc, String messages) {
|
||||
this.rc = rc;
|
||||
this.messages = messages;
|
||||
}
|
||||
public int getRc() {
|
||||
return rc;
|
||||
}
|
||||
public void setRc(int rc) {
|
||||
this.rc = rc;
|
||||
}
|
||||
public String getMessages() {
|
||||
return messages;
|
||||
}
|
||||
public void setMessages(String messages) {
|
||||
this.messages = messages;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
package stirling.software.SPDF.utils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class PropertyConfigs {
|
||||
|
||||
|
||||
public static boolean getBooleanValue(List<String> keys, boolean defaultValue) {
|
||||
for (String key : keys) {
|
||||
String value = System.getProperty(key);
|
||||
if (value == null)
|
||||
value = System.getenv(key);
|
||||
|
||||
if (value != null)
|
||||
return Boolean.valueOf(value);
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public static String getStringValue(List<String> keys, String defaultValue) {
|
||||
for (String key : keys) {
|
||||
String value = System.getProperty(key);
|
||||
if (value == null)
|
||||
value = System.getenv(key);
|
||||
|
||||
if (value != null)
|
||||
return value;
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public static boolean getBooleanValue(String key, boolean defaultValue) {
|
||||
String value = System.getProperty(key);
|
||||
if (value == null)
|
||||
value = System.getenv(key);
|
||||
return (value != null) ? Boolean.valueOf(value) : defaultValue;
|
||||
}
|
||||
|
||||
public static String getStringValue(String key, String defaultValue) {
|
||||
String value = System.getProperty(key);
|
||||
if (value == null)
|
||||
value = System.getenv(key);
|
||||
return (value != null) ? value : defaultValue;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -12,6 +12,9 @@ import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import com.itextpdf.kernel.pdf.PdfDocument;
|
||||
import com.itextpdf.kernel.pdf.PdfWriter;
|
||||
|
||||
public class WebResponseUtils {
|
||||
|
||||
public static ResponseEntity<byte[]> boasToWebResponse(ByteArrayOutputStream baos, String docName) throws IOException {
|
||||
@@ -57,5 +60,19 @@ public class WebResponseUtils {
|
||||
|
||||
return boasToWebResponse(baos, docName);
|
||||
}
|
||||
|
||||
public static ResponseEntity<byte[]> pdfDocToWebResponse(PdfDocument document, String docName) throws IOException {
|
||||
|
||||
// Open Byte Array and save document to it
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
PdfWriter writer = new PdfWriter(baos);
|
||||
PdfDocument newDocument = new PdfDocument(writer);
|
||||
|
||||
document.copyPagesTo(1, document.getNumberOfPages(), newDocument);
|
||||
newDocument.close();
|
||||
|
||||
return boasToWebResponse(baos, docName);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,12 +1,5 @@
|
||||
spring.http.multipart.max-file-size=${MAX_FILE_SIZE:2000MB}
|
||||
spring.http.multipart.max-request-size=${MAX_FILE_SIZE:2000MB}
|
||||
|
||||
multipart.enabled=true
|
||||
multipart.max-file-size=${MAX_FILE_SIZE:2000MB}
|
||||
multipart.max-request-size=${MAX_FILE_SIZE:2000MB}
|
||||
|
||||
spring.servlet.multipart.max-file-size=${MAX_FILE_SIZE:2000MB}
|
||||
spring.servlet.multipart.max-request-size=${MAX_FILE_SIZE:2000MB}
|
||||
|
||||
server.forward-headers-strategy=NATIVE
|
||||
|
||||
@@ -15,18 +8,32 @@ server.error.whitelabel.enabled=false
|
||||
server.error.include-stacktrace=always
|
||||
server.error.include-exception=true
|
||||
server.error.include-message=always
|
||||
\
|
||||
|
||||
#logging.level.org.springframework.web=DEBUG
|
||||
#logging.level.org.springframework=DEBUG
|
||||
#logging.level.org.springframework.security=DEBUG
|
||||
|
||||
spring.servlet.multipart.max-file-size=2000MB
|
||||
spring.servlet.multipart.max-request-size=2000MB
|
||||
|
||||
server.servlet.session.tracking-modes=cookie
|
||||
server.servlet.context-path=${APP_ROOT_PATH:/}
|
||||
server.servlet.context-path=${SYSTEM_ROOTURIPATH:/}
|
||||
|
||||
spring.devtools.restart.enabled=true
|
||||
spring.devtools.livereload.enabled=true
|
||||
|
||||
spring.thymeleaf.encoding=UTF-8
|
||||
|
||||
server.connection-timeout=${CONNECTION_TIMEOUT:5m}
|
||||
spring.mvc.async.request-timeout=${ASYNC_CONNECTION_TIMEOUT:300000}
|
||||
server.connection-timeout=${SYSTEM_CONNECTIONTIMEOUTMINUTES:5m}
|
||||
spring.mvc.async.request-timeout=${SYSTEM_CONNECTIONTIMEOUTMILLISECONDS:300000}
|
||||
|
||||
spring.resources.static-locations=file:customFiles/static/
|
||||
#spring.thymeleaf.prefix=file:/customFiles/templates/,classpath:/templates/
|
||||
#spring.thymeleaf.cache=false
|
||||
#spring.thymeleaf.cache=false
|
||||
|
||||
spring.datasource.url=jdbc:h2:file:./configs/stirling-pdf-DB;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
|
||||
spring.datasource.driver-class-name=org.h2.Driver
|
||||
spring.datasource.username=sa
|
||||
spring.datasource.password=
|
||||
spring.h2.console.enabled=true
|
||||
spring.jpa.hibernate.ddl-auto=update
|
||||
|
||||
@@ -31,6 +31,23 @@ sizes.medium=Medium
|
||||
sizes.large=Large
|
||||
sizes.x-large=X-Large
|
||||
error.pdfPassword=The PDF Document is passworded and either the password was not provided or was incorrect
|
||||
delete=Delete
|
||||
username=Username
|
||||
password=Password
|
||||
welcome=Welcome
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
property=Property
|
||||
black=Black
|
||||
white=White
|
||||
red=Red
|
||||
green=Green
|
||||
blue=Blue
|
||||
custom=Custom...
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#############
|
||||
@@ -54,6 +71,41 @@ settings.downloadOption.1=\u0641\u062A\u062D \u0641\u064A \u0646\u0641\u0633 \u0
|
||||
settings.downloadOption.2=\u0641\u062A\u062D \u0641\u064A \u0646\u0627\u0641\u0630\u0629 \u062C\u062F\u064A\u062F\u0629
|
||||
settings.downloadOption.3=\u062A\u0646\u0632\u064A\u0644 \u0627\u0644\u0645\u0644\u0641
|
||||
settings.zipThreshold=\u0645\u0644\u0641\u0627\u062A \u0645\u0636\u063A\u0648\u0637\u0629 \u0639\u0646\u062F \u062A\u062C\u0627\u0648\u0632 \u0639\u062F\u062F \u0627\u0644\u0645\u0644\u0641\u0627\u062A \u0627\u0644\u062A\u064A \u062A\u0645 \u062A\u0646\u0632\u064A\u0644\u0647\u0627
|
||||
settings.signOut=Sign Out
|
||||
settings.accountSettings=Account Settings
|
||||
|
||||
account.title=Account Settings
|
||||
account.accountSettings=Account Settings
|
||||
account.adminSettings=Admin Settings - View and Add Users
|
||||
account.userControlSettings=User Control Settings
|
||||
account.changeUsername=Change Username
|
||||
account.changeUsername=Change Username
|
||||
account.password=Confirmation Password
|
||||
account.oldPassword=Old password
|
||||
account.newPassword=New Password
|
||||
account.changePassword=Change Password
|
||||
account.confirmNewPassword=Confirm New Password
|
||||
account.signOut=Sign Out
|
||||
account.yourApiKey=Your API Key
|
||||
account.syncTitle=Sync browser settings with Account
|
||||
account.settingsCompare=Settings Comparison:
|
||||
account.property=Property
|
||||
account.webBrowserSettings=Web Browser Setting
|
||||
account.syncToBrowser=Sync Account -> Browser
|
||||
account.syncToAccount=Sync Account <- Browser
|
||||
|
||||
|
||||
adminUserSettings.title=User Control Settings
|
||||
adminUserSettings.header=Admin User Control Settings
|
||||
adminUserSettings.admin=Admin
|
||||
adminUserSettings.user=User
|
||||
adminUserSettings.addUser=Add New User
|
||||
adminUserSettings.roles=Roles
|
||||
adminUserSettings.role=Role
|
||||
adminUserSettings.actions=Actions
|
||||
adminUserSettings.apiUser=Limited API User
|
||||
adminUserSettings.webOnlyUser=Web Only User
|
||||
adminUserSettings.submit=Save User
|
||||
|
||||
#############
|
||||
# HOME-PAGE #
|
||||
@@ -71,296 +123,264 @@ merge.tags=merge,Page operations,Back end,server side
|
||||
|
||||
home.split.title=انقسام ملفات
|
||||
home.split.desc=تقسيم ملفات PDF إلى مستندات متعددة
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
split.tags=Page operations,divide,Multi Page,cut,server side
|
||||
split.tags=Page operations,divide,Multi Page,cut,server side
|
||||
|
||||
home.rotate.title=تدوير ملفات
|
||||
home.rotate.desc=قم بتدوير ملفات PDF الخاصة بك بسهولة.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
rotate.tags=server side
|
||||
|
||||
|
||||
home.imageToPdf.title=صورة إلى PDF
|
||||
home.imageToPdf.desc=تحويل الصور (PNG ، JPEG ، GIF) إلى PDF.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
imageToPdf.tags=conversion,img,jpg,picture,photo
|
||||
|
||||
home.pdfToImage.title=تحويل PDF إلى صورة
|
||||
home.pdfToImage.desc=تحويل ملف PDF إلى صورة. (PNG ، JPEG ، GIF)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
pdfToImage.tags=conversion,img,jpg,picture,photo
|
||||
|
||||
home.pdfOrganiser.title=منظم
|
||||
home.pdfOrganiser.desc=إزالة / إعادة ترتيب الصفحات بأي ترتيب
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
pdfOrganiser.tags=duplex,even,odd,sort,move
|
||||
|
||||
|
||||
home.addImage.title=إضافة صورة إلى ملف PDF
|
||||
home.addImage.desc=إضافة صورة إلى موقع معين في PDF (العمل قيد التقدم)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
addImage.tags=img,jpg,picture,photo
|
||||
|
||||
home.watermark.title=إضافة علامة مائية
|
||||
home.watermark.desc=أضف علامة مائية مخصصة إلى مستند PDF الخاص بك.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
watermark.tags=Text,repeating,label,own,copyright,trademark,img,jpg,picture,photo
|
||||
|
||||
home.permissions.title=تغيير الأذونات
|
||||
home.permissions.desc=قم بتغيير أذونات مستند PDF الخاص بك
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
permissions.tags=read,write,edit,print
|
||||
|
||||
|
||||
home.removePages.title=إزالة الصفحات
|
||||
home.removePages.desc=حذف الصفحات غير المرغوب فيها من مستند PDF الخاص بك.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
removePages.tags=Remove pages,delete pages
|
||||
|
||||
home.addPassword.title=إضافة كلمة مرور
|
||||
home.addPassword.desc=تشفير مستند PDF الخاص بك بكلمة مرور.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
addPassword.tags=secure,security
|
||||
|
||||
home.removePassword.title=إزالة كلمة المرور
|
||||
home.removePassword.desc=إزالة الحماية بكلمة مرور من مستند PDF الخاص بك.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
removePassword.tags=secure,Decrypt,security,unpassword,delete password
|
||||
|
||||
home.compressPdfs.title=ضغط ملفات
|
||||
home.compressPdfs.desc=ضغط ملفات PDF لتقليل حجم الملف.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
compressPdfs.tags=squish,small,tiny
|
||||
|
||||
|
||||
home.changeMetadata.title=\u062A\u063A\u064A\u064A\u0631 \u0627\u0644\u0628\u064A\u0627\u0646\u0627\u062A \u0627\u0644\u0648\u0635\u0641\u064A\u0629
|
||||
home.changeMetadata.desc=\u062A\u063A\u064A\u064A\u0631 / \u0625\u0632\u0627\u0644\u0629 / \u0625\u0636\u0627\u0641\u0629 \u0628\u064A\u0627\u0646\u0627\u062A \u0623\u0648\u0644\u064A\u0629 \u0645\u0646 \u0645\u0633\u062A\u0646\u062F PDF
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
changeMetadata.tags==Title,author,date,creation,time,publisher,producer,stats
|
||||
|
||||
home.fileToPDF.title=\u062A\u062D\u0648\u064A\u0644 \u0627\u0644\u0645\u0644\u0641 \u0625\u0644\u0649 PDF
|
||||
home.fileToPDF.desc=\u062A\u062D\u0648\u064A\u0644 \u0623\u064A \u0645\u0644\u0641 \u062A\u0642\u0631\u064A\u0628\u0627 \u0625\u0644\u0649 PDF (DOCX \u0648PNG \u0648XLS \u0648PPT \u0648TXT \u0648\u0627\u0644\u0645\u0632\u064A\u062F)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
fileToPDF.tags=transformation,format,document,picture,slide,text,conversion,office,docs,word,excel,powerpoint
|
||||
|
||||
home.ocr.title=\u062A\u0634\u063A\u064A\u0644 OCR \u0639\u0644\u0649 PDF \u0648 / \u0623\u0648 \u0645\u0633\u062D \u0636\u0648\u0626\u064A
|
||||
home.ocr.desc=\u064A\u0642\u0648\u0645 \u0628\u0631\u0646\u0627\u0645\u062C \u0627\u0644\u062A\u0646\u0638\u064A\u0641 \u0628\u0645\u0633\u062D \u0648\u0627\u0643\u062A\u0634\u0627\u0641 \u0627\u0644\u0646\u0635 \u0645\u0646 \u0627\u0644\u0635\u0648\u0631 \u062F\u0627\u062E\u0644 \u0645\u0644\u0641 PDF \u0648\u064A\u0639\u064A\u062F \u0625\u0636\u0627\u0641\u062A\u0647 \u0643\u0646\u0635
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
ocr.tags=recognition,text,image,scan,read,identify,detection,editable
|
||||
|
||||
|
||||
home.extractImages.title=\u0627\u0633\u062A\u062E\u0631\u0627\u062C \u0627\u0644\u0635\u0648\u0631
|
||||
home.extractImages.desc=\u064A\u0633\u062A\u062E\u0631\u062C \u062C\u0645\u064A\u0639 \u0627\u0644\u0635\u0648\u0631 \u0645\u0646 \u0645\u0644\u0641 PDF \u0648\u064A\u062D\u0641\u0638\u0647\u0627 \u0641\u064A \u0627\u0644\u0631\u0645\u0632 \u0627\u0644\u0628\u0631\u064A\u062F\u064A
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
extractImages.tags=picture,photo,save,archive,zip,capture,grab
|
||||
|
||||
home.pdfToPDFA.title=\u062A\u062D\u0648\u064A\u0644 \u0645\u0644\u0641\u0627\u062A PDF \u0625\u0644\u0649 PDF / A
|
||||
home.pdfToPDFA.desc=\u062A\u062D\u0648\u064A\u0644 PDF \u0625\u0644\u0649 PDF / A \u0644\u0644\u062A\u062E\u0632\u064A\u0646 \u0637\u0648\u064A\u0644 \u0627\u0644\u0645\u062F\u0649
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation
|
||||
|
||||
home.PDFToWord.title=تحويل PDF إلى Word
|
||||
home.PDFToWord.desc=تحويل PDF إلى تنسيقات Word (DOC و DOCX و ODT)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
PDFToWord.tags=doc,docx,odt,word,transformation,format,conversion,office,microsoft,docfile
|
||||
|
||||
home.PDFToPresentation.title=PDF للعرض التقديمي
|
||||
home.PDFToPresentation.desc=تحويل PDF إلى تنسيقات عرض تقديمي (PPT و PPTX و ODP)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
PDFToPresentation.tags=slides,show,office,microsoft
|
||||
|
||||
home.PDFToText.title=تحويل PDF إلى نص / RTF
|
||||
home.PDFToText.desc=تحويل PDF إلى تنسيق نص أو RTF
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
PDFToText.tags=richformat,richtextformat,rich text format
|
||||
|
||||
home.PDFToHTML.title=تحويل PDF إلى HTML
|
||||
home.PDFToHTML.desc=تحويل PDF إلى تنسيق HTML
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
PDFToHTML.tags=web content,browser friendly
|
||||
|
||||
|
||||
home.PDFToXML.title=تحويل PDF إلى XML
|
||||
home.PDFToXML.desc=تحويل PDF إلى تنسيق XML
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
PDFToXML.tags=data-extraction,structured-content,interop,transformation,convert
|
||||
|
||||
home.ScannerImageSplit.title=كشف / انقسام الصور الممسوحة ضوئيًا
|
||||
home.ScannerImageSplit.desc=تقسيم عدة صور من داخل صورة / ملف PDF
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
ScannerImageSplit.tags=separate,auto-detect,scans,multi-photo,organize
|
||||
|
||||
home.sign.title=تسجيل الدخول
|
||||
home.sign.desc=إضافة التوقيع إلى PDF عن طريق الرسم أو النص أو الصورة
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
sign.tags=authorize,initials,drawn-signature,text-sign,image-signature
|
||||
|
||||
home.flatten.title=تسطيح
|
||||
home.flatten.desc=قم بإزالة كافة العناصر والنماذج التفاعلية من ملف PDF
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
flatten.tags=static,deactivate,non-interactive,streamline
|
||||
|
||||
home.repair.title=إصلاح
|
||||
home.repair.desc=يحاول إصلاح ملف PDF تالف / معطل
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
repair.tags=fix,restore,correction,recover
|
||||
|
||||
home.removeBlanks.title=إزالة الصفحات الفارغة
|
||||
home.removeBlanks.desc=يكتشف ويزيل الصفحات الفارغة من المستند
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
removeBlanks.tags=cleanup,streamline,non-content,organize
|
||||
|
||||
home.compare.title=قارن
|
||||
home.compare.desc=يقارن ويظهر الاختلافات بين 2 من مستندات PDF
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
compare.tags=differentiate,contrast,changes,analysis
|
||||
|
||||
home.certSign.title=Sign with Certificate
|
||||
home.certSign.desc=Signs a PDF with a Certificate/Key (PEM/P12)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
certSign.tags=authenticate,PEM,P12,official,encrypt
|
||||
|
||||
home.pageLayout.title=Multi-Page Layout
|
||||
home.pageLayout.desc=Merge multiple pages of a PDF document into a single page
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
pageLayout.tags=merge,composite,single-view,organize
|
||||
|
||||
home.scalePages.title=Adjust page size/scale
|
||||
home.scalePages.desc=Change the size/scale of page and/or its contents.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
scalePages.tags=resize,modify,dimension,adapt
|
||||
|
||||
home.pipeline.title=Pipeline (Advanced)
|
||||
home.pipeline.desc=Run multiple actions on PDFs by defining pipeline scripts
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
pipeline.tags=automate,sequence,scripted,batch-process
|
||||
|
||||
home.add-page-numbers.title=Add Page Numbers
|
||||
home.add-page-numbers.desc=Add Page numbers throughout a document in a set location
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
add-page-numbers.tags=paginate,label,organize,index
|
||||
|
||||
home.auto-rename.title=Auto Rename PDF File
|
||||
home.auto-rename.desc=Auto renames a PDF file based on its detected header
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
auto-rename.tags=auto-detect,header-based,organize,relabel
|
||||
|
||||
home.adjust-contrast.title=Adjust Colors/Contrast
|
||||
home.adjust-contrast.desc=Adjust Contrast, Saturation and Brightness of a PDF
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
adjust-contrast.tags=color-correction,tune,modify,enhance
|
||||
|
||||
home.crop.title=Crop PDF
|
||||
home.crop.desc=Crop a PDF to reduce its size (maintains text!)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
crop.tags=trim,shrink,edit,shape
|
||||
|
||||
home.autoSplitPDF.title=Auto Split Pages
|
||||
home.autoSplitPDF.desc=Auto Split Scanned PDF with physical scanned page splitter QR Code
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
autoSplitPDF.tags=QR-based,separate,scan-segment,organize
|
||||
|
||||
home.sanitizePdf.title=Sanitize
|
||||
home.sanitizePdf.desc=Remove scripts and other elements from PDF files
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
sanitizePdf.tags=clean,secure,safe,remove-threats
|
||||
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
home.URLToPDF.title=URL/Website To PDF
|
||||
home.URLToPDF.desc=Converts any http(s)URL to PDF
|
||||
URLToPDF.tags=web-capture,save-page,web-to-doc,archive
|
||||
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
home.HTMLToPDF.title=HTML to PDF
|
||||
home.HTMLToPDF.desc=Converts any HTML file or zip to PDF
|
||||
HTMLToPDF.tags=markup,web-content,transformation,convert
|
||||
|
||||
|
||||
home.MarkdownToPDF.title=Markdown to PDF
|
||||
home.MarkdownToPDF.desc=Converts any Markdown file to PDF
|
||||
MarkdownToPDF.tags=markup,web-content,transformation,convert
|
||||
|
||||
|
||||
home.getPdfInfo.title=Get ALL Info on PDF
|
||||
home.getPdfInfo.desc=Grabs any and all information possible on PDFs
|
||||
getPdfInfo.tags=infomation,data,stats,statistics
|
||||
|
||||
|
||||
home.extractPage.title=Extract page(s)
|
||||
home.extractPage.desc=Extracts select pages from PDF
|
||||
extractPage.tags=extract
|
||||
|
||||
|
||||
home.PdfToSinglePage.title=PDF to Single Large Page
|
||||
home.PdfToSinglePage.desc=Merges all PDF pages into one large single page
|
||||
PdfToSinglePage.tags=single page
|
||||
|
||||
|
||||
home.showJS.title=Show Javascript
|
||||
home.showJS.desc=Searches and displays any JS injected into a PDF
|
||||
showJS.tags=JS
|
||||
|
||||
home.autoRedact.title=Auto Redact
|
||||
home.autoRedact.desc=Auto Redacts(Blacks out) text in a PDF based on input text
|
||||
showJS.tags=JS
|
||||
|
||||
###########################
|
||||
# #
|
||||
# WEB PAGES #
|
||||
# #
|
||||
###########################
|
||||
#login
|
||||
login.title=Sign in
|
||||
login.signin=Sign in
|
||||
login.rememberme=Remember me
|
||||
login.invalid=Invalid username or password.
|
||||
login.locked=Your account has been locked.
|
||||
login.signinTitle=Please sign in
|
||||
|
||||
|
||||
#auto-redact
|
||||
autoRedact.title=Auto Redact
|
||||
autoRedact.header=Auto Redact
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
autoRedact.colorLabel=Colour
|
||||
autoRedact.textsToRedactLabel=Text to Redact (line-separated)
|
||||
autoRedact.textsToRedactPlaceholder=e.g. \nConfidential \nTop-Secret
|
||||
autoRedact.useRegexLabel=Use Regex
|
||||
autoRedact.wholeWordSearchLabel=Whole Word Search
|
||||
autoRedact.customPaddingLabel=Custom Extra Padding
|
||||
autoRedact.convertPDFToImageLabel=Convert PDF to PDF-Image (Used to remove text behind the box)
|
||||
autoRedact.submitButton=Submit
|
||||
|
||||
|
||||
#showJS
|
||||
showJS.title=Show Javascript
|
||||
showJS.header=Show Javascript
|
||||
showJS.downloadJS=Download Javascript
|
||||
showJS.submit=Show
|
||||
|
||||
|
||||
#pdfToSinglePage
|
||||
pdfToSinglePage.title=PDF To Single Page
|
||||
pdfToSinglePage.header=PDF To Single Page
|
||||
pdfToSinglePage.submit=Convert To Single Page
|
||||
|
||||
|
||||
#pageExtracter
|
||||
pageExtracter.title=Extract Pages
|
||||
pageExtracter.header=Extract Pages
|
||||
pageExtracter.submit=Extract
|
||||
|
||||
|
||||
#getPdfInfo
|
||||
getPdfInfo.title=Get Info on PDF
|
||||
getPdfInfo.header=Get Info on PDF
|
||||
getPdfInfo.submit=Get Info
|
||||
getPdfInfo.downloadJson=Download JSON
|
||||
|
||||
|
||||
#markdown-to-pdf
|
||||
MarkdownToPDF.title=Markdown To PDF
|
||||
MarkdownToPDF.header=Markdown To PDF
|
||||
MarkdownToPDF.submit=Convert
|
||||
MarkdownToPDF.help=Work in progress
|
||||
MarkdownToPDF.credit=Uses WeasyPrint
|
||||
|
||||
|
||||
|
||||
#url-to-pdf
|
||||
URLToPDF.title=URL To PDF
|
||||
URLToPDF.header=URL To PDF
|
||||
@@ -396,6 +416,9 @@ addPageNumbers.selectText.3=Position
|
||||
addPageNumbers.selectText.4=Starting Number
|
||||
addPageNumbers.selectText.5=Pages to Number
|
||||
addPageNumbers.selectText.6=Custom Text
|
||||
addPageNumbers.customTextDesc=Custom Text
|
||||
addPageNumbers.numberPagesDesc=Which pages to number, default 'all', also accepts 1-5 or 2,5,9 etc
|
||||
addPageNumbers.customNumberDesc=Defaults to {n}, also accepts 'Page {n} of {total}', 'Text-{n}', '{filename}-{n}
|
||||
addPageNumbers.submit=Add Page Numbers
|
||||
|
||||
|
||||
@@ -581,6 +604,8 @@ addImage.submit=إضافة صورة
|
||||
#merge
|
||||
merge.title=دمج
|
||||
merge.header=دمج ملفات PDF متعددة (2+)
|
||||
merge.sortByName=Sort by name
|
||||
merge.sortByDate=Sort by date
|
||||
merge.submit=دمج
|
||||
|
||||
|
||||
@@ -681,17 +706,11 @@ watermark.selectText.4=دوران (0-360):
|
||||
watermark.selectText.5=widthSpacer (مسافة بين كل علامة مائية أفقيًا):
|
||||
watermark.selectText.6=heightSpacer (مسافة بين كل علامة مائية عموديًا):
|
||||
watermark.selectText.7=\u0627\u0644\u062A\u0639\u062A\u064A\u0645 (0\u066A - 100\u066A):
|
||||
watermark.selectText.8=Watermark Type:
|
||||
watermark.selectText.9=Watermark Image:
|
||||
watermark.submit=إضافة علامة مائية
|
||||
|
||||
|
||||
#remove-watermark
|
||||
remove-watermark.title=\u0625\u0632\u0627\u0644\u0629 \u0627\u0644\u0639\u0644\u0627\u0645\u0629 \u0627\u0644\u0645\u0627\u0626\u064A\u0629
|
||||
remove-watermark.header=\u0625\u0632\u0627\u0644\u0629 \u0627\u0644\u0639\u0644\u0627\u0645\u0629 \u0627\u0644\u0645\u0627\u0626\u064A\u0629
|
||||
remove-watermark.selectText.1=\u062D\u062F\u062F PDF \u0644\u0625\u0632\u0627\u0644\u0629 \u0627\u0644\u0639\u0644\u0627\u0645\u0629 \u0627\u0644\u0645\u0627\u0626\u064A\u0629 \u0645\u0646:
|
||||
remove-watermark.selectText.2=\u0646\u0635 \u0627\u0644\u0639\u0644\u0627\u0645\u0629 \u0627\u0644\u0645\u0627\u0626\u064A\u0629:
|
||||
remove-watermark.submit=\u0625\u0632\u0627\u0644\u0629 \u0627\u0644\u0639\u0644\u0627\u0645\u0629 \u0627\u0644\u0645\u0627\u0626\u064A\u0629
|
||||
|
||||
|
||||
#Change permissions
|
||||
permissions.title=تغيير الأذونات
|
||||
permissions.header=تغيير الأذونات
|
||||
|
||||
@@ -31,6 +31,23 @@ sizes.medium=Medium
|
||||
sizes.large=Large
|
||||
sizes.x-large=X-Large
|
||||
error.pdfPassword=The PDF Document is passworded and either the password was not provided or was incorrect
|
||||
delete=Delete
|
||||
username=Username
|
||||
password=Password
|
||||
welcome=Welcome
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
property=Property
|
||||
black=Black
|
||||
white=White
|
||||
red=Red
|
||||
green=Green
|
||||
blue=Blue
|
||||
custom=Custom...
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#############
|
||||
@@ -54,6 +71,41 @@ settings.downloadOption.1=Obre mateixa finestra
|
||||
settings.downloadOption.2=Obre mateixa finestra
|
||||
settings.downloadOption.3=Descarrega Arxiu
|
||||
settings.zipThreshold=Comprimiu els fitxers quan el nombre de fitxers baixats superi
|
||||
settings.signOut=Sign Out
|
||||
settings.accountSettings=Account Settings
|
||||
|
||||
account.title=Account Settings
|
||||
account.accountSettings=Account Settings
|
||||
account.adminSettings=Admin Settings - View and Add Users
|
||||
account.userControlSettings=User Control Settings
|
||||
account.changeUsername=Change Username
|
||||
account.changeUsername=Change Username
|
||||
account.password=Confirmation Password
|
||||
account.oldPassword=Old password
|
||||
account.newPassword=New Password
|
||||
account.changePassword=Change Password
|
||||
account.confirmNewPassword=Confirm New Password
|
||||
account.signOut=Sign Out
|
||||
account.yourApiKey=Your API Key
|
||||
account.syncTitle=Sync browser settings with Account
|
||||
account.settingsCompare=Settings Comparison:
|
||||
account.property=Property
|
||||
account.webBrowserSettings=Web Browser Setting
|
||||
account.syncToBrowser=Sync Account -> Browser
|
||||
account.syncToAccount=Sync Account <- Browser
|
||||
|
||||
|
||||
adminUserSettings.title=User Control Settings
|
||||
adminUserSettings.header=Admin User Control Settings
|
||||
adminUserSettings.admin=Admin
|
||||
adminUserSettings.user=User
|
||||
adminUserSettings.addUser=Add New User
|
||||
adminUserSettings.roles=Roles
|
||||
adminUserSettings.role=Role
|
||||
adminUserSettings.actions=Actions
|
||||
adminUserSettings.apiUser=Limited API User
|
||||
adminUserSettings.webOnlyUser=Web Only User
|
||||
adminUserSettings.submit=Save User
|
||||
|
||||
#############
|
||||
# HOME-PAGE #
|
||||
@@ -71,296 +123,264 @@ merge.tags=merge,Page operations,Back end,server side
|
||||
|
||||
home.split.title=Divideix
|
||||
home.split.desc=Divideix PDFs en múltiples documents
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
split.tags=Page operations,divide,Multi Page,cut,server side
|
||||
split.tags=Page operations,divide,Multi Page,cut,server side
|
||||
|
||||
home.rotate.title=Rota
|
||||
home.rotate.desc=Rota els PDFs.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
rotate.tags=server side
|
||||
|
||||
|
||||
home.imageToPdf.title=Imatge a PDF
|
||||
home.imageToPdf.desc=Converteix imatge (PNG, JPEG, GIF) a PDF.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
imageToPdf.tags=conversion,img,jpg,picture,photo
|
||||
|
||||
home.pdfToImage.title=PDF a Imatge
|
||||
home.pdfToImage.desc=Converteix PDF a imatge. (PNG, JPEG, GIF)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
pdfToImage.tags=conversion,img,jpg,picture,photo
|
||||
|
||||
home.pdfOrganiser.title=Organitza
|
||||
home.pdfOrganiser.desc=Elimina/Reorganitza pàgines en qualsevol ordre
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
pdfOrganiser.tags=duplex,even,odd,sort,move
|
||||
|
||||
|
||||
home.addImage.title=Afegir imatge a PDF
|
||||
home.addImage.desc=Afegeix imatge en un PDF (En progrés)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
addImage.tags=img,jpg,picture,photo
|
||||
|
||||
home.watermark.title=Afegir Marca d'aigua
|
||||
home.watermark.desc=Afegir Marca d'aigua personalitzada en un PDF
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
watermark.tags=Text,repeating,label,own,copyright,trademark,img,jpg,picture,photo
|
||||
|
||||
home.permissions.title=Canvia permissos
|
||||
home.permissions.desc=Canvia permisos del document PDF
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
permissions.tags=read,write,edit,print
|
||||
|
||||
|
||||
home.removePages.title=Elimina
|
||||
home.removePages.desc=Elimina pàgines del document PDF.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
removePages.tags=Remove pages,delete pages
|
||||
|
||||
home.addPassword.title=Afegir Password
|
||||
home.addPassword.desc=Xifra document PDF amb password.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
addPassword.tags=secure,security
|
||||
|
||||
home.removePassword.title=Elimina Password
|
||||
home.removePassword.desc=Elimia Password de document PDF.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
removePassword.tags=secure,Decrypt,security,unpassword,delete password
|
||||
|
||||
home.compressPdfs.title=Comprimeix
|
||||
home.compressPdfs.desc=Comprimeix PDFs per reduir la mida.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
compressPdfs.tags=squish,small,tiny
|
||||
|
||||
|
||||
home.changeMetadata.title=Canvia Metadades
|
||||
home.changeMetadata.desc=Canvia/Treu/Afegeix matadades al document PDF.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
changeMetadata.tags==Title,author,date,creation,time,publisher,producer,stats
|
||||
|
||||
home.fileToPDF.title=Converteix arxiu a PDF
|
||||
home.fileToPDF.desc=Converteix qualsevol arxiu a PDF (DOCX, PNG, XLS, PPT, TXT i més)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
fileToPDF.tags=transformation,format,document,picture,slide,text,conversion,office,docs,word,excel,powerpoint
|
||||
|
||||
home.ocr.title=Executa exploracions OCR i/o neteja escanejos
|
||||
home.ocr.desc=Neteja escanejats i detecta text d'imatges dins d'un PDF i el torna a afegir com a text.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
ocr.tags=recognition,text,image,scan,read,identify,detection,editable
|
||||
|
||||
|
||||
home.extractImages.title=Extreu Imatges
|
||||
home.extractImages.desc=Extreu les Imatges del PDF i les desa a zip
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
extractImages.tags=picture,photo,save,archive,zip,capture,grab
|
||||
|
||||
home.pdfToPDFA.title=PDF a PDF/A
|
||||
home.pdfToPDFA.desc=Converteix PDF a PDF/A per desar a llarg termini.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation
|
||||
|
||||
home.PDFToWord.title=PDF a Word
|
||||
home.PDFToWord.desc=Converteix PDF a formats de Word (DOC, DOCX and ODT)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
PDFToWord.tags=doc,docx,odt,word,transformation,format,conversion,office,microsoft,docfile
|
||||
|
||||
home.PDFToPresentation.title=PDF a Presentació
|
||||
home.PDFToPresentation.desc=Convert PDF to Presentation formats (PPT, PPTX and ODP)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
PDFToPresentation.tags=slides,show,office,microsoft
|
||||
|
||||
home.PDFToText.title=PDF a Text/RTF
|
||||
home.PDFToText.desc=Converteix PDF a Text o format RTF
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
PDFToText.tags=richformat,richtextformat,rich text format
|
||||
|
||||
home.PDFToHTML.title=PDF a HTML
|
||||
home.PDFToHTML.desc=Converteix PDF a format HTML
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
PDFToHTML.tags=web content,browser friendly
|
||||
|
||||
|
||||
home.PDFToXML.title=PDF a XML
|
||||
home.PDFToXML.desc=Converteix PDF a format XML
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
PDFToXML.tags=data-extraction,structured-content,interop,transformation,convert
|
||||
|
||||
home.ScannerImageSplit.title=Detecta/Divideix fotos escanejades
|
||||
home.ScannerImageSplit.desc=Divideix múltiples fotos dins del PDF/foto
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
ScannerImageSplit.tags=separate,auto-detect,scans,multi-photo,organize
|
||||
|
||||
home.sign.title=Sign
|
||||
home.sign.desc=Afegeix signatura al PDF mitjançant dibuix, text o imatge
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
sign.tags=authorize,initials,drawn-signature,text-sign,image-signature
|
||||
|
||||
home.flatten.title=Aplanar
|
||||
home.flatten.desc=Elimineu tots els elements i formularis interactius d'un PDF
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
flatten.tags=static,deactivate,non-interactive,streamline
|
||||
|
||||
home.repair.title=Reparar
|
||||
home.repair.desc=Intenta reparar un PDF danyat o trencat
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
repair.tags=fix,restore,correction,recover
|
||||
|
||||
home.removeBlanks.title=Elimina les pàgines en blanc
|
||||
home.removeBlanks.desc=Detecta i elimina les pàgines en blanc d'un document
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
removeBlanks.tags=cleanup,streamline,non-content,organize
|
||||
|
||||
home.compare.title=Compara
|
||||
home.compare.desc=Compara i mostra les diferències entre 2 documents PDF
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
compare.tags=differentiate,contrast,changes,analysis
|
||||
|
||||
home.certSign.title=Sign with Certificate
|
||||
home.certSign.desc=Signs a PDF with a Certificate/Key (PEM/P12)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
certSign.tags=authenticate,PEM,P12,official,encrypt
|
||||
|
||||
home.pageLayout.title=Multi-Page Layout
|
||||
home.pageLayout.desc=Merge multiple pages of a PDF document into a single page
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
pageLayout.tags=merge,composite,single-view,organize
|
||||
|
||||
home.scalePages.title=Adjust page size/scale
|
||||
home.scalePages.desc=Change the size/scale of page and/or its contents.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
scalePages.tags=resize,modify,dimension,adapt
|
||||
|
||||
home.pipeline.title=Pipeline (Advanced)
|
||||
home.pipeline.desc=Run multiple actions on PDFs by defining pipeline scripts
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
pipeline.tags=automate,sequence,scripted,batch-process
|
||||
|
||||
home.add-page-numbers.title=Add Page Numbers
|
||||
home.add-page-numbers.desc=Add Page numbers throughout a document in a set location
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
add-page-numbers.tags=paginate,label,organize,index
|
||||
|
||||
home.auto-rename.title=Auto Rename PDF File
|
||||
home.auto-rename.desc=Auto renames a PDF file based on its detected header
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
auto-rename.tags=auto-detect,header-based,organize,relabel
|
||||
|
||||
home.adjust-contrast.title=Adjust Colors/Contrast
|
||||
home.adjust-contrast.desc=Adjust Contrast, Saturation and Brightness of a PDF
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
adjust-contrast.tags=color-correction,tune,modify,enhance
|
||||
|
||||
home.crop.title=Crop PDF
|
||||
home.crop.desc=Crop a PDF to reduce its size (maintains text!)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
crop.tags=trim,shrink,edit,shape
|
||||
|
||||
home.autoSplitPDF.title=Auto Split Pages
|
||||
home.autoSplitPDF.desc=Auto Split Scanned PDF with physical scanned page splitter QR Code
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
autoSplitPDF.tags=QR-based,separate,scan-segment,organize
|
||||
|
||||
home.sanitizePdf.title=Sanitize
|
||||
home.sanitizePdf.desc=Remove scripts and other elements from PDF files
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
sanitizePdf.tags=clean,secure,safe,remove-threats
|
||||
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
home.URLToPDF.title=URL/Website To PDF
|
||||
home.URLToPDF.desc=Converts any http(s)URL to PDF
|
||||
URLToPDF.tags=web-capture,save-page,web-to-doc,archive
|
||||
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
home.HTMLToPDF.title=HTML to PDF
|
||||
home.HTMLToPDF.desc=Converts any HTML file or zip to PDF
|
||||
HTMLToPDF.tags=markup,web-content,transformation,convert
|
||||
|
||||
|
||||
home.MarkdownToPDF.title=Markdown to PDF
|
||||
home.MarkdownToPDF.desc=Converts any Markdown file to PDF
|
||||
MarkdownToPDF.tags=markup,web-content,transformation,convert
|
||||
|
||||
|
||||
home.getPdfInfo.title=Get ALL Info on PDF
|
||||
home.getPdfInfo.desc=Grabs any and all information possible on PDFs
|
||||
getPdfInfo.tags=infomation,data,stats,statistics
|
||||
|
||||
|
||||
home.extractPage.title=Extract page(s)
|
||||
home.extractPage.desc=Extracts select pages from PDF
|
||||
extractPage.tags=extract
|
||||
|
||||
|
||||
home.PdfToSinglePage.title=PDF to Single Large Page
|
||||
home.PdfToSinglePage.desc=Merges all PDF pages into one large single page
|
||||
PdfToSinglePage.tags=single page
|
||||
|
||||
|
||||
home.showJS.title=Show Javascript
|
||||
home.showJS.desc=Searches and displays any JS injected into a PDF
|
||||
showJS.tags=JS
|
||||
|
||||
home.autoRedact.title=Auto Redact
|
||||
home.autoRedact.desc=Auto Redacts(Blacks out) text in a PDF based on input text
|
||||
showJS.tags=JS
|
||||
|
||||
###########################
|
||||
# #
|
||||
# WEB PAGES #
|
||||
# #
|
||||
###########################
|
||||
#login
|
||||
login.title=Sign in
|
||||
login.signin=Sign in
|
||||
login.rememberme=Remember me
|
||||
login.invalid=Invalid username or password.
|
||||
login.locked=Your account has been locked.
|
||||
login.signinTitle=Please sign in
|
||||
|
||||
|
||||
#auto-redact
|
||||
autoRedact.title=Auto Redact
|
||||
autoRedact.header=Auto Redact
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
autoRedact.colorLabel=Colour
|
||||
autoRedact.textsToRedactLabel=Text to Redact (line-separated)
|
||||
autoRedact.textsToRedactPlaceholder=e.g. \nConfidential \nTop-Secret
|
||||
autoRedact.useRegexLabel=Use Regex
|
||||
autoRedact.wholeWordSearchLabel=Whole Word Search
|
||||
autoRedact.customPaddingLabel=Custom Extra Padding
|
||||
autoRedact.convertPDFToImageLabel=Convert PDF to PDF-Image (Used to remove text behind the box)
|
||||
autoRedact.submitButton=Submit
|
||||
|
||||
|
||||
#showJS
|
||||
showJS.title=Show Javascript
|
||||
showJS.header=Show Javascript
|
||||
showJS.downloadJS=Download Javascript
|
||||
showJS.submit=Show
|
||||
|
||||
|
||||
#pdfToSinglePage
|
||||
pdfToSinglePage.title=PDF To Single Page
|
||||
pdfToSinglePage.header=PDF To Single Page
|
||||
pdfToSinglePage.submit=Convert To Single Page
|
||||
|
||||
|
||||
#pageExtracter
|
||||
pageExtracter.title=Extract Pages
|
||||
pageExtracter.header=Extract Pages
|
||||
pageExtracter.submit=Extract
|
||||
|
||||
|
||||
#getPdfInfo
|
||||
getPdfInfo.title=Get Info on PDF
|
||||
getPdfInfo.header=Get Info on PDF
|
||||
getPdfInfo.submit=Get Info
|
||||
getPdfInfo.downloadJson=Download JSON
|
||||
|
||||
|
||||
#markdown-to-pdf
|
||||
MarkdownToPDF.title=Markdown To PDF
|
||||
MarkdownToPDF.header=Markdown To PDF
|
||||
MarkdownToPDF.submit=Convert
|
||||
MarkdownToPDF.help=Work in progress
|
||||
MarkdownToPDF.credit=Uses WeasyPrint
|
||||
|
||||
|
||||
|
||||
#url-to-pdf
|
||||
URLToPDF.title=URL To PDF
|
||||
URLToPDF.header=URL To PDF
|
||||
@@ -396,6 +416,9 @@ addPageNumbers.selectText.3=Position
|
||||
addPageNumbers.selectText.4=Starting Number
|
||||
addPageNumbers.selectText.5=Pages to Number
|
||||
addPageNumbers.selectText.6=Custom Text
|
||||
addPageNumbers.customTextDesc=Custom Text
|
||||
addPageNumbers.numberPagesDesc=Which pages to number, default 'all', also accepts 1-5 or 2,5,9 etc
|
||||
addPageNumbers.customNumberDesc=Defaults to {n}, also accepts 'Page {n} of {total}', 'Text-{n}', '{filename}-{n}
|
||||
addPageNumbers.submit=Add Page Numbers
|
||||
|
||||
|
||||
@@ -581,6 +604,8 @@ addImage.submit=Afegir Imatge
|
||||
#merge
|
||||
merge.title=Fusiona
|
||||
merge.header=Fusiona múltiples PDFs (2+)
|
||||
merge.sortByName=Sort by name
|
||||
merge.sortByDate=Sort by date
|
||||
merge.submit=Fusiona
|
||||
|
||||
|
||||
@@ -681,17 +706,11 @@ watermark.selectText.4=Rotació (0-360):
|
||||
watermark.selectText.5=separació d'amplada (Espai horitzontal entre cada Marca d'Aigua):
|
||||
watermark.selectText.6=separació d'alçada (Espai vertical entre cada Marca d'Aigua):
|
||||
watermark.selectText.7=Opacitat (0% - 100%):
|
||||
watermark.selectText.8=Watermark Type:
|
||||
watermark.selectText.9=Watermark Image:
|
||||
watermark.submit=Afegir Marca d'Aigua
|
||||
|
||||
|
||||
#remove-watermark
|
||||
remove-watermark.title=Elimina Marca d'Aigua
|
||||
remove-watermark.header=Elimina Marca d'Aigua
|
||||
remove-watermark.selectText.1=Seleciona PDF per eliminar Marca d'Aigua:
|
||||
remove-watermark.selectText.2=Text de la Marca d'Aigua:
|
||||
remove-watermark.submit=Elimina Marca d'Aigua
|
||||
|
||||
|
||||
#Change permissions
|
||||
permissions.title=Canviar Permissos
|
||||
permissions.header=Canviar Permissos
|
||||
|
||||
@@ -31,6 +31,23 @@ sizes.medium=Medium
|
||||
sizes.large=Large
|
||||
sizes.x-large=X-Large
|
||||
error.pdfPassword=The PDF Document is passworded and either the password was not provided or was incorrect
|
||||
delete=Delete
|
||||
username=Username
|
||||
password=Password
|
||||
welcome=Welcome
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
property=Property
|
||||
black=Black
|
||||
white=White
|
||||
red=Red
|
||||
green=Green
|
||||
blue=Blue
|
||||
custom=Custom...
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#############
|
||||
@@ -54,6 +71,41 @@ settings.downloadOption.1=Im selben Fenster öffnen
|
||||
settings.downloadOption.2=In neuem Fenster öffnen
|
||||
settings.downloadOption.3=Datei herunterladen
|
||||
settings.zipThreshold=Dateien komprimieren, wenn die Anzahl der heruntergeladenen Dateien überschritten wird
|
||||
settings.signOut=Sign Out
|
||||
settings.accountSettings=Account Settings
|
||||
|
||||
account.title=Account Settings
|
||||
account.accountSettings=Account Settings
|
||||
account.adminSettings=Admin Settings - View and Add Users
|
||||
account.userControlSettings=User Control Settings
|
||||
account.changeUsername=Change Username
|
||||
account.changeUsername=Change Username
|
||||
account.password=Confirmation Password
|
||||
account.oldPassword=Old password
|
||||
account.newPassword=New Password
|
||||
account.changePassword=Change Password
|
||||
account.confirmNewPassword=Confirm New Password
|
||||
account.signOut=Sign Out
|
||||
account.yourApiKey=Your API Key
|
||||
account.syncTitle=Sync browser settings with Account
|
||||
account.settingsCompare=Settings Comparison:
|
||||
account.property=Property
|
||||
account.webBrowserSettings=Web Browser Setting
|
||||
account.syncToBrowser=Sync Account -> Browser
|
||||
account.syncToAccount=Sync Account <- Browser
|
||||
|
||||
|
||||
adminUserSettings.title=User Control Settings
|
||||
adminUserSettings.header=Admin User Control Settings
|
||||
adminUserSettings.admin=Admin
|
||||
adminUserSettings.user=User
|
||||
adminUserSettings.addUser=Add New User
|
||||
adminUserSettings.roles=Roles
|
||||
adminUserSettings.role=Role
|
||||
adminUserSettings.actions=Actions
|
||||
adminUserSettings.apiUser=Limited API User
|
||||
adminUserSettings.webOnlyUser=Web Only User
|
||||
adminUserSettings.submit=Save User
|
||||
|
||||
#############
|
||||
# HOME-PAGE #
|
||||
@@ -71,296 +123,264 @@ merge.tags=merge,Page operations,Back end,server side
|
||||
|
||||
home.split.title=Aufteilen
|
||||
home.split.desc=PDFs in mehrere Dokumente aufteilen.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
split.tags=Page operations,divide,Multi Page,cut,server side
|
||||
split.tags=Page operations,divide,Multi Page,cut,server side
|
||||
|
||||
home.rotate.title=Drehen
|
||||
home.rotate.desc=Drehen Sie Ihre PDFs ganz einfach.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
rotate.tags=server side
|
||||
|
||||
|
||||
home.imageToPdf.title=Bild zu PDF
|
||||
home.imageToPdf.desc=Konvertieren Sie ein Bild (PNG, JPEG, GIF) in ein PDF.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
imageToPdf.tags=conversion,img,jpg,picture,photo
|
||||
|
||||
home.pdfToImage.title=PDF zu Bild
|
||||
home.pdfToImage.desc=Konvertieren Sie ein PDF in ein Bild (PNG, JPEG, GIF).
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
pdfToImage.tags=conversion,img,jpg,picture,photo
|
||||
|
||||
home.pdfOrganiser.title=Organisieren
|
||||
home.pdfOrganiser.desc=Seiten entfernen und Seitenreihenfolge ändern.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
pdfOrganiser.tags=duplex,even,odd,sort,move
|
||||
|
||||
|
||||
home.addImage.title=Bild einfügen
|
||||
home.addImage.desc=Fügt ein Bild an eine bestimmte Stelle im PDF ein (Work in progress).
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
addImage.tags=img,jpg,picture,photo
|
||||
|
||||
home.watermark.title=Wasserzeichen hinzufügen
|
||||
home.watermark.desc=Fügen Sie ein eigenes Wasserzeichen zu Ihrem PDF hinzu.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
watermark.tags=Text,repeating,label,own,copyright,trademark,img,jpg,picture,photo
|
||||
|
||||
home.permissions.title=Berechtigungen ändern
|
||||
home.permissions.desc=Die Berechtigungen für Ihr PDF-Dokument verändern.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
permissions.tags=read,write,edit,print
|
||||
|
||||
|
||||
home.removePages.title=Entfernen
|
||||
home.removePages.desc=Ungewollte Seiten aus dem PDF entfernen.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
removePages.tags=Remove pages,delete pages
|
||||
|
||||
home.addPassword.title=Passwort hinzufügen
|
||||
home.addPassword.desc=Das PDF mit einem Passwort verschlüsseln.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
addPassword.tags=secure,security
|
||||
|
||||
home.removePassword.title=Passwort entfernen
|
||||
home.removePassword.desc=Den Passwortschutz eines PDFs entfernen.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
removePassword.tags=secure,Decrypt,security,unpassword,delete password
|
||||
|
||||
home.compressPdfs.title=Komprimieren
|
||||
home.compressPdfs.desc=PDF komprimieren um die Dateigröße zu reduzieren.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
compressPdfs.tags=squish,small,tiny
|
||||
|
||||
|
||||
home.changeMetadata.title=Metadaten ändern
|
||||
home.changeMetadata.desc=Ändern/Entfernen/Hinzufügen von Metadaten aus einem PDF-Dokument
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
changeMetadata.tags==Title,author,date,creation,time,publisher,producer,stats
|
||||
|
||||
home.fileToPDF.title=Datei in PDF konvertieren
|
||||
home.fileToPDF.desc=Konvertieren Sie nahezu jede Datei in PDF (DOCX, PNG, XLS, PPT, TXT und mehr)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
fileToPDF.tags=transformation,format,document,picture,slide,text,conversion,office,docs,word,excel,powerpoint
|
||||
|
||||
home.ocr.title=Führe OCR auf PDF- und/oder Cleanup-Scans aus
|
||||
home.ocr.desc=Cleanup scannt und erkennt Text aus Bildern in einer PDF-Datei und fügt ihn erneut als Text hinzu.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
ocr.tags=recognition,text,image,scan,read,identify,detection,editable
|
||||
|
||||
|
||||
home.extractImages.title=Bilder extrahieren
|
||||
home.extractImages.desc=Extrahiert alle Bilder aus einer PDF-Datei und speichert sie als Zip-Datei
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
extractImages.tags=picture,photo,save,archive,zip,capture,grab
|
||||
|
||||
home.pdfToPDFA.title=PDF zu PDF/A konvertieren
|
||||
home.pdfToPDFA.desc=PDF zu PDF/A für Langzeitarchivierung konvertieren
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation
|
||||
|
||||
home.PDFToWord.title=PDF zu Word
|
||||
home.PDFToWord.desc=PDF in Word-Formate konvertieren (DOC, DOCX und ODT)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
PDFToWord.tags=doc,docx,odt,word,transformation,format,conversion,office,microsoft,docfile
|
||||
|
||||
home.PDFToPresentation.title=PDF zu Präsentation
|
||||
home.PDFToPresentation.desc=PDF in Präsentationsformate konvertieren (PPT, PPTX und ODP)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
PDFToPresentation.tags=slides,show,office,microsoft
|
||||
|
||||
home.PDFToText.title=PDF in Text/RTF
|
||||
home.PDFToText.desc=PDF in Text- oder RTF-Format konvertieren
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
PDFToText.tags=richformat,richtextformat,rich text format
|
||||
|
||||
home.PDFToHTML.title=PDF in HTML
|
||||
home.PDFToHTML.desc=PDF in HTML-Format konvertieren
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
PDFToHTML.tags=web content,browser friendly
|
||||
|
||||
|
||||
home.PDFToXML.title=PDF in XML
|
||||
home.PDFToXML.desc=PDF in XML-Format konvertieren
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
PDFToXML.tags=data-extraction,structured-content,interop,transformation,convert
|
||||
|
||||
home.ScannerImageSplit.title=Gescannte Fotos erkennen/aufteilen
|
||||
home.ScannerImageSplit.desc=Teilt mehrere Fotos innerhalb eines Fotos/PDF
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
ScannerImageSplit.tags=separate,auto-detect,scans,multi-photo,organize
|
||||
|
||||
home.sign.title=Signieren
|
||||
home.sign.desc=Fügt PDF-Signaturen durch Zeichnung, Text oder Bild hinzu
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
sign.tags=authorize,initials,drawn-signature,text-sign,image-signature
|
||||
|
||||
home.flatten.title=Abflachen
|
||||
home.flatten.desc=Alle interaktiven Elemente und Formulare aus einem PDF entfernen
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
flatten.tags=static,deactivate,non-interactive,streamline
|
||||
|
||||
home.repair.title=Reparatur
|
||||
home.repair.desc=Versucht, ein beschädigtes/kaputtes PDF zu reparieren
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
repair.tags=fix,restore,correction,recover
|
||||
|
||||
home.removeBlanks.title=Leere Seiten entfernen
|
||||
home.removeBlanks.desc=Erkennt und entfernt leere Seiten aus einem Dokument
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
removeBlanks.tags=cleanup,streamline,non-content,organize
|
||||
|
||||
home.compare.title=Vergleichen
|
||||
home.compare.desc=Vergleicht und zeigt die Unterschiede zwischen zwei PDF-Dokumenten an
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
compare.tags=differentiate,contrast,changes,analysis
|
||||
|
||||
home.certSign.title=Sign with Certificate
|
||||
home.certSign.desc=Signs a PDF with a Certificate/Key (PEM/P12)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
certSign.tags=authenticate,PEM,P12,official,encrypt
|
||||
|
||||
home.pageLayout.title=Multi-Page Layout
|
||||
home.pageLayout.desc=Merge multiple pages of a PDF document into a single page
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
pageLayout.tags=merge,composite,single-view,organize
|
||||
|
||||
home.scalePages.title=Adjust page size/scale
|
||||
home.scalePages.desc=Change the size/scale of page and/or its contents.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
scalePages.tags=resize,modify,dimension,adapt
|
||||
|
||||
home.pipeline.title=Pipeline (Advanced)
|
||||
home.pipeline.desc=Run multiple actions on PDFs by defining pipeline scripts
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
pipeline.tags=automate,sequence,scripted,batch-process
|
||||
|
||||
home.add-page-numbers.title=Add Page Numbers
|
||||
home.add-page-numbers.desc=Add Page numbers throughout a document in a set location
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
add-page-numbers.tags=paginate,label,organize,index
|
||||
|
||||
home.auto-rename.title=Auto Rename PDF File
|
||||
home.auto-rename.desc=Auto renames a PDF file based on its detected header
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
auto-rename.tags=auto-detect,header-based,organize,relabel
|
||||
|
||||
home.adjust-contrast.title=Adjust Colors/Contrast
|
||||
home.adjust-contrast.desc=Adjust Contrast, Saturation and Brightness of a PDF
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
adjust-contrast.tags=color-correction,tune,modify,enhance
|
||||
|
||||
home.crop.title=Crop PDF
|
||||
home.crop.desc=Crop a PDF to reduce its size (maintains text!)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
crop.tags=trim,shrink,edit,shape
|
||||
|
||||
home.autoSplitPDF.title=Auto Split Pages
|
||||
home.autoSplitPDF.desc=Auto Split Scanned PDF with physical scanned page splitter QR Code
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
autoSplitPDF.tags=QR-based,separate,scan-segment,organize
|
||||
|
||||
home.sanitizePdf.title=Sanitize
|
||||
home.sanitizePdf.desc=Remove scripts and other elements from PDF files
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
sanitizePdf.tags=clean,secure,safe,remove-threats
|
||||
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
home.URLToPDF.title=URL/Website To PDF
|
||||
home.URLToPDF.desc=Converts any http(s)URL to PDF
|
||||
URLToPDF.tags=web-capture,save-page,web-to-doc,archive
|
||||
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
home.HTMLToPDF.title=HTML to PDF
|
||||
home.HTMLToPDF.desc=Converts any HTML file or zip to PDF
|
||||
HTMLToPDF.tags=markup,web-content,transformation,convert
|
||||
|
||||
|
||||
home.MarkdownToPDF.title=Markdown to PDF
|
||||
home.MarkdownToPDF.desc=Converts any Markdown file to PDF
|
||||
MarkdownToPDF.tags=markup,web-content,transformation,convert
|
||||
|
||||
|
||||
home.getPdfInfo.title=Get ALL Info on PDF
|
||||
home.getPdfInfo.desc=Grabs any and all information possible on PDFs
|
||||
getPdfInfo.tags=infomation,data,stats,statistics
|
||||
|
||||
|
||||
home.extractPage.title=Extract page(s)
|
||||
home.extractPage.desc=Extracts select pages from PDF
|
||||
extractPage.tags=extract
|
||||
|
||||
|
||||
home.PdfToSinglePage.title=PDF to Single Large Page
|
||||
home.PdfToSinglePage.desc=Merges all PDF pages into one large single page
|
||||
PdfToSinglePage.tags=single page
|
||||
|
||||
|
||||
home.showJS.title=Show Javascript
|
||||
home.showJS.desc=Searches and displays any JS injected into a PDF
|
||||
showJS.tags=JS
|
||||
|
||||
home.autoRedact.title=Auto Redact
|
||||
home.autoRedact.desc=Auto Redacts(Blacks out) text in a PDF based on input text
|
||||
showJS.tags=JS
|
||||
|
||||
###########################
|
||||
# #
|
||||
# WEB PAGES #
|
||||
# #
|
||||
###########################
|
||||
#login
|
||||
login.title=Sign in
|
||||
login.signin=Sign in
|
||||
login.rememberme=Remember me
|
||||
login.invalid=Invalid username or password.
|
||||
login.locked=Your account has been locked.
|
||||
login.signinTitle=Please sign in
|
||||
|
||||
|
||||
#auto-redact
|
||||
autoRedact.title=Auto Redact
|
||||
autoRedact.header=Auto Redact
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
autoRedact.colorLabel=Colour
|
||||
autoRedact.textsToRedactLabel=Text to Redact (line-separated)
|
||||
autoRedact.textsToRedactPlaceholder=e.g. \nConfidential \nTop-Secret
|
||||
autoRedact.useRegexLabel=Use Regex
|
||||
autoRedact.wholeWordSearchLabel=Whole Word Search
|
||||
autoRedact.customPaddingLabel=Custom Extra Padding
|
||||
autoRedact.convertPDFToImageLabel=Convert PDF to PDF-Image (Used to remove text behind the box)
|
||||
autoRedact.submitButton=Submit
|
||||
|
||||
|
||||
#showJS
|
||||
showJS.title=Show Javascript
|
||||
showJS.header=Show Javascript
|
||||
showJS.downloadJS=Download Javascript
|
||||
showJS.submit=Show
|
||||
|
||||
|
||||
#pdfToSinglePage
|
||||
pdfToSinglePage.title=PDF To Single Page
|
||||
pdfToSinglePage.header=PDF To Single Page
|
||||
pdfToSinglePage.submit=Convert To Single Page
|
||||
|
||||
|
||||
#pageExtracter
|
||||
pageExtracter.title=Extract Pages
|
||||
pageExtracter.header=Extract Pages
|
||||
pageExtracter.submit=Extract
|
||||
|
||||
|
||||
#getPdfInfo
|
||||
getPdfInfo.title=Get Info on PDF
|
||||
getPdfInfo.header=Get Info on PDF
|
||||
getPdfInfo.submit=Get Info
|
||||
getPdfInfo.downloadJson=Download JSON
|
||||
|
||||
|
||||
#markdown-to-pdf
|
||||
MarkdownToPDF.title=Markdown To PDF
|
||||
MarkdownToPDF.header=Markdown To PDF
|
||||
MarkdownToPDF.submit=Convert
|
||||
MarkdownToPDF.help=Work in progress
|
||||
MarkdownToPDF.credit=Uses WeasyPrint
|
||||
|
||||
|
||||
|
||||
#url-to-pdf
|
||||
URLToPDF.title=URL To PDF
|
||||
URLToPDF.header=URL To PDF
|
||||
@@ -396,6 +416,9 @@ addPageNumbers.selectText.3=Position
|
||||
addPageNumbers.selectText.4=Starting Number
|
||||
addPageNumbers.selectText.5=Pages to Number
|
||||
addPageNumbers.selectText.6=Custom Text
|
||||
addPageNumbers.customTextDesc=Custom Text
|
||||
addPageNumbers.numberPagesDesc=Which pages to number, default 'all', also accepts 1-5 or 2,5,9 etc
|
||||
addPageNumbers.customNumberDesc=Defaults to {n}, also accepts 'Page {n} of {total}', 'Text-{n}', '{filename}-{n}
|
||||
addPageNumbers.submit=Add Page Numbers
|
||||
|
||||
|
||||
@@ -581,6 +604,8 @@ addImage.submit=Bild hinzufügen
|
||||
#merge
|
||||
merge.title=Zusammenführen
|
||||
merge.header=Mehrere PDFs zusammenführen (2+)
|
||||
merge.sortByName=Sort by name
|
||||
merge.sortByDate=Sort by date
|
||||
merge.submit=Zusammenführen
|
||||
|
||||
|
||||
@@ -681,17 +706,11 @@ watermark.selectText.4=Drehung (0-360):
|
||||
watermark.selectText.5=breiteSpacer (horizontaler Abstand zwischen den einzelnen Wasserzeichen):
|
||||
watermark.selectText.6=höheSpacer (vertikaler Abstand zwischen den einzelnen Wasserzeichen):
|
||||
watermark.selectText.7=Deckkraft (0% - 100 %):
|
||||
watermark.selectText.8=Watermark Type:
|
||||
watermark.selectText.9=Watermark Image:
|
||||
watermark.submit=Wasserzeichen hinzufügen
|
||||
|
||||
|
||||
#remove-watermark
|
||||
remove-watermark.title=Wasserzeichen entfernen
|
||||
remove-watermark.header=Wasserzeichen entfernen
|
||||
remove-watermark.selectText.1=PDF auswählen, um Wasserzeichen zu entfernen von:
|
||||
remove-watermark.selectText.2=Wasserzeichentext:
|
||||
remove-watermark.submit=Wasserzeichen entfernen
|
||||
|
||||
|
||||
#Change permissions
|
||||
permissions.title=Berechtigungen ändern
|
||||
permissions.header=Berechtigungen ändern
|
||||
|
||||
@@ -31,6 +31,20 @@ sizes.medium=Medium
|
||||
sizes.large=Large
|
||||
sizes.x-large=X-Large
|
||||
error.pdfPassword=The PDF Document is passworded and either the password was not provided or was incorrect
|
||||
delete=Delete
|
||||
username=Username
|
||||
password=Password
|
||||
welcome=Welcome
|
||||
property=Property
|
||||
black=Black
|
||||
white=White
|
||||
red=Red
|
||||
green=Green
|
||||
blue=Blue
|
||||
custom=Custom...
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#############
|
||||
@@ -54,6 +68,41 @@ settings.downloadOption.1=Open in same window
|
||||
settings.downloadOption.2=Open in new window
|
||||
settings.downloadOption.3=Download file
|
||||
settings.zipThreshold=Zip files when the number of downloaded files exceeds
|
||||
settings.signOut=Sign Out
|
||||
settings.accountSettings=Account Settings
|
||||
|
||||
account.title=Account Settings
|
||||
account.accountSettings=Account Settings
|
||||
account.adminSettings=Admin Settings - View and Add Users
|
||||
account.userControlSettings=User Control Settings
|
||||
account.changeUsername=New Username
|
||||
account.changeUsername=Change Username
|
||||
account.password=Confirmation Password
|
||||
account.oldPassword=Old password
|
||||
account.newPassword=New Password
|
||||
account.changePassword=Change Password
|
||||
account.confirmNewPassword=Confirm New Password
|
||||
account.signOut=Sign Out
|
||||
account.yourApiKey=Your API Key
|
||||
account.syncTitle=Sync browser settings with Account
|
||||
account.settingsCompare=Settings Comparison:
|
||||
account.property=Property
|
||||
account.webBrowserSettings=Web Browser Setting
|
||||
account.syncToBrowser=Sync Account -> Browser
|
||||
account.syncToAccount=Sync Account <- Browser
|
||||
|
||||
|
||||
adminUserSettings.title=User Control Settings
|
||||
adminUserSettings.header=Admin User Control Settings
|
||||
adminUserSettings.admin=Admin
|
||||
adminUserSettings.user=User
|
||||
adminUserSettings.addUser=Add New User
|
||||
adminUserSettings.roles=Roles
|
||||
adminUserSettings.role=Role
|
||||
adminUserSettings.actions=Actions
|
||||
adminUserSettings.apiUser=Limited API User
|
||||
adminUserSettings.webOnlyUser=Web Only User
|
||||
adminUserSettings.submit=Save User
|
||||
|
||||
#############
|
||||
# HOME-PAGE #
|
||||
@@ -236,11 +285,96 @@ home.HTMLToPDF.desc=Converts any HTML file or zip to PDF
|
||||
HTMLToPDF.tags=markup,web-content,transformation,convert
|
||||
|
||||
|
||||
home.MarkdownToPDF.title=Markdown to PDF
|
||||
home.MarkdownToPDF.desc=Converts any Markdown file to PDF
|
||||
MarkdownToPDF.tags=markup,web-content,transformation,convert
|
||||
|
||||
|
||||
home.getPdfInfo.title=Get ALL Info on PDF
|
||||
home.getPdfInfo.desc=Grabs any and all information possible on PDFs
|
||||
getPdfInfo.tags=infomation,data,stats,statistics
|
||||
|
||||
|
||||
home.extractPage.title=Extract page(s)
|
||||
home.extractPage.desc=Extracts select pages from PDF
|
||||
extractPage.tags=extract
|
||||
|
||||
|
||||
home.PdfToSinglePage.title=PDF to Single Large Page
|
||||
home.PdfToSinglePage.desc=Merges all PDF pages into one large single page
|
||||
PdfToSinglePage.tags=single page
|
||||
|
||||
|
||||
home.showJS.title=Show Javascript
|
||||
home.showJS.desc=Searches and displays any JS injected into a PDF
|
||||
showJS.tags=JS
|
||||
|
||||
home.autoRedact.title=Auto Redact
|
||||
home.autoRedact.desc=Auto Redacts(Blacks out) text in a PDF based on input text
|
||||
showJS.tags=Redact,Hide,black out,black,marker,hidden
|
||||
|
||||
###########################
|
||||
# #
|
||||
# WEB PAGES #
|
||||
# #
|
||||
###########################
|
||||
#login
|
||||
login.title=Sign in
|
||||
login.signin=Sign in
|
||||
login.rememberme=Remember me
|
||||
login.invalid=Invalid username or password.
|
||||
login.locked=Your account has been locked.
|
||||
login.signinTitle=Please sign in
|
||||
|
||||
|
||||
#auto-redact
|
||||
autoRedact.title=Auto Redact
|
||||
autoRedact.header=Auto Redact
|
||||
autoRedact.colorLabel=Colour
|
||||
autoRedact.textsToRedactLabel=Text to Redact (line-separated)
|
||||
autoRedact.textsToRedactPlaceholder=e.g. \nConfidential \nTop-Secret
|
||||
autoRedact.useRegexLabel=Use Regex
|
||||
autoRedact.wholeWordSearchLabel=Whole Word Search
|
||||
autoRedact.customPaddingLabel=Custom Extra Padding
|
||||
autoRedact.convertPDFToImageLabel=Convert PDF to PDF-Image (Used to remove text behind the box)
|
||||
autoRedact.submitButton=Submit
|
||||
|
||||
|
||||
#showJS
|
||||
showJS.title=Show Javascript
|
||||
showJS.header=Show Javascript
|
||||
showJS.downloadJS=Download Javascript
|
||||
showJS.submit=Show
|
||||
|
||||
|
||||
#pdfToSinglePage
|
||||
pdfToSinglePage.title=PDF To Single Page
|
||||
pdfToSinglePage.header=PDF To Single Page
|
||||
pdfToSinglePage.submit=Convert To Single Page
|
||||
|
||||
|
||||
#pageExtracter
|
||||
pageExtracter.title=Extract Pages
|
||||
pageExtracter.header=Extract Pages
|
||||
pageExtracter.submit=Extract
|
||||
|
||||
|
||||
#getPdfInfo
|
||||
getPdfInfo.title=Get Info on PDF
|
||||
getPdfInfo.header=Get Info on PDF
|
||||
getPdfInfo.submit=Get Info
|
||||
getPdfInfo.downloadJson=Download JSON
|
||||
|
||||
|
||||
#markdown-to-pdf
|
||||
MarkdownToPDF.title=Markdown To PDF
|
||||
MarkdownToPDF.header=Markdown To PDF
|
||||
MarkdownToPDF.submit=Convert
|
||||
MarkdownToPDF.help=Work in progress
|
||||
MarkdownToPDF.credit=Uses WeasyPrint
|
||||
|
||||
|
||||
|
||||
#url-to-pdf
|
||||
URLToPDF.title=URL To PDF
|
||||
URLToPDF.header=URL To PDF
|
||||
@@ -276,6 +410,9 @@ addPageNumbers.selectText.3=Position
|
||||
addPageNumbers.selectText.4=Starting Number
|
||||
addPageNumbers.selectText.5=Pages to Number
|
||||
addPageNumbers.selectText.6=Custom Text
|
||||
addPageNumbers.customTextDesc=Custom Text
|
||||
addPageNumbers.numberPagesDesc=Which pages to number, default 'all', also accepts 1-5 or 2,5,9 etc
|
||||
addPageNumbers.customNumberDesc=Defaults to {n}, also accepts 'Page {n} of {total}', 'Text-{n}', '{filename}-{n}
|
||||
addPageNumbers.submit=Add Page Numbers
|
||||
|
||||
|
||||
@@ -353,10 +490,10 @@ certSign.submit=Sign PDF
|
||||
#removeBlanks
|
||||
removeBlanks.title=Remove Blanks
|
||||
removeBlanks.header=Remove Blank Pages
|
||||
removeBlanks.threshold=Threshold:
|
||||
removeBlanks.thresholdDesc=Threshold for determining how white a white pixel must be
|
||||
removeBlanks.threshold=Pixel Whiteness Threshold:
|
||||
removeBlanks.thresholdDesc=Threshold for determining how white a white pixel must be to be classed as 'White'. 0 = Black, 255 pure white.
|
||||
removeBlanks.whitePercent=White Percent (%):
|
||||
removeBlanks.whitePercentDesc=Percent of page that must be white to be removed
|
||||
removeBlanks.whitePercentDesc=Percent of page that must be 'white' pixels to be removed
|
||||
removeBlanks.submit=Remove Blanks
|
||||
|
||||
|
||||
@@ -461,6 +598,8 @@ addImage.submit=Add image
|
||||
#merge
|
||||
merge.title=Merge
|
||||
merge.header=Merge multiple PDFs (2+)
|
||||
merge.sortByName=Sort by name
|
||||
merge.sortByDate=Sort by date
|
||||
merge.submit=Merge
|
||||
|
||||
|
||||
@@ -519,9 +658,9 @@ imageToPDF.selectText.5=Convert to separate PDFs
|
||||
pdfToImage.title=PDF to Image
|
||||
pdfToImage.header=PDF to Image
|
||||
pdfToImage.selectText=Image Format
|
||||
pdfToImage.singleOrMultiple=Image result type
|
||||
pdfToImage.single=Single Big Image
|
||||
pdfToImage.multi=Multiple Images
|
||||
pdfToImage.singleOrMultiple=Page to Image result type
|
||||
pdfToImage.single=Single Big Image Combing all pages
|
||||
pdfToImage.multi=Multiple Images, one image per page
|
||||
pdfToImage.colorType=Colour type
|
||||
pdfToImage.color=Colour
|
||||
pdfToImage.grey=Greyscale
|
||||
@@ -561,17 +700,11 @@ watermark.selectText.4=Rotation (0-360):
|
||||
watermark.selectText.5=widthSpacer (Space between each watermark horizontally):
|
||||
watermark.selectText.6=heightSpacer (Space between each watermark vertically):
|
||||
watermark.selectText.7=Opacity (0% - 100%):
|
||||
watermark.selectText.8=Watermark Type:
|
||||
watermark.selectText.9=Watermark Image:
|
||||
watermark.submit=Add Watermark
|
||||
|
||||
|
||||
#remove-watermark
|
||||
remove-watermark.title=Remove Watermark
|
||||
remove-watermark.header=Remove Watermark
|
||||
remove-watermark.selectText.1=Select PDF to remove watermark from:
|
||||
remove-watermark.selectText.2=Watermark Text:
|
||||
remove-watermark.submit=Remove Watermark
|
||||
|
||||
|
||||
#Change permissions
|
||||
permissions.title=Change Permissions
|
||||
permissions.header=Change Permissions
|
||||
|
||||
808
src/main/resources/messages_en_US.properties
Normal file
808
src/main/resources/messages_en_US.properties
Normal file
@@ -0,0 +1,808 @@
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl = right to left)
|
||||
language.direction=ltr
|
||||
|
||||
pdfPrompt=Select PDF(s)
|
||||
multiPdfPrompt=Select PDFs (2+)
|
||||
multiPdfDropPrompt=Select (or drag & drop) all PDFs you require
|
||||
imgPrompt=Select Image(s)
|
||||
genericSubmit=Submit
|
||||
processTimeWarning=Warning: This process can take up to a minute depending on file-size
|
||||
pageOrderPrompt=Custom Page Order (Enter a comma-separated list of page numbers or Functions like 2n+1) :
|
||||
goToPage=Go
|
||||
true=True
|
||||
false=False
|
||||
unknown=Unknown
|
||||
save=Save
|
||||
close=Close
|
||||
filesSelected=files selected
|
||||
noFavourites=No favorites added
|
||||
bored=Bored Waiting?
|
||||
alphabet=Alphabet
|
||||
downloadPdf=Download PDF
|
||||
text=Text
|
||||
font=Font
|
||||
selectFillter=-- Select --
|
||||
pageNum=Page Number
|
||||
sizes.small=Small
|
||||
sizes.medium=Medium
|
||||
sizes.large=Large
|
||||
sizes.x-large=X-Large
|
||||
error.pdfPassword=The PDF Document is passworded and either the password was not provided or was incorrect
|
||||
delete=Delete
|
||||
username=Username
|
||||
password=Password
|
||||
welcome=Welcome
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
property=Property
|
||||
black=Black
|
||||
white=White
|
||||
red=Red
|
||||
green=Green
|
||||
blue=Blue
|
||||
custom=Custom...
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#############
|
||||
# NAVBAR #
|
||||
#############
|
||||
navbar.convert=Convert
|
||||
navbar.security=Security
|
||||
navbar.other=Other
|
||||
navbar.darkmode=Dark Mode
|
||||
navbar.pageOps=Page Operations
|
||||
navbar.settings=Settings
|
||||
|
||||
#############
|
||||
# SETTINGS #
|
||||
#############
|
||||
settings.title=Settings
|
||||
settings.update=Update available
|
||||
settings.appVersion=App Version:
|
||||
settings.downloadOption.title=Choose download option (For single file non zip downloads):
|
||||
settings.downloadOption.1=Open in same window
|
||||
settings.downloadOption.2=Open in new window
|
||||
settings.downloadOption.3=Download file
|
||||
settings.zipThreshold=Zip files when the number of downloaded files exceeds
|
||||
settings.signOut=Sign Out
|
||||
settings.accountSettings=Account Settings
|
||||
|
||||
account.title=Account Settings
|
||||
account.accountSettings=Account Settings
|
||||
account.adminSettings=Admin Settings - View and Add Users
|
||||
account.userControlSettings=User Control Settings
|
||||
account.changeUsername=Change Username
|
||||
account.changeUsername=Change Username
|
||||
account.password=Confirmation Password
|
||||
account.oldPassword=Old password
|
||||
account.newPassword=New Password
|
||||
account.changePassword=Change Password
|
||||
account.confirmNewPassword=Confirm New Password
|
||||
account.signOut=Sign Out
|
||||
account.yourApiKey=Your API Key
|
||||
account.syncTitle=Sync browser settings with Account
|
||||
account.settingsCompare=Settings Comparison:
|
||||
account.property=Property
|
||||
account.webBrowserSettings=Web Browser Setting
|
||||
account.syncToBrowser=Sync Account -> Browser
|
||||
account.syncToAccount=Sync Account <- Browser
|
||||
|
||||
|
||||
adminUserSettings.title=User Control Settings
|
||||
adminUserSettings.header=Admin User Control Settings
|
||||
adminUserSettings.admin=Admin
|
||||
adminUserSettings.user=User
|
||||
adminUserSettings.addUser=Add New User
|
||||
adminUserSettings.roles=Roles
|
||||
adminUserSettings.role=Role
|
||||
adminUserSettings.actions=Actions
|
||||
adminUserSettings.apiUser=Limited API User
|
||||
adminUserSettings.webOnlyUser=Web Only User
|
||||
adminUserSettings.submit=Save User
|
||||
|
||||
#############
|
||||
# HOME-PAGE #
|
||||
#############
|
||||
home.desc=Your locally hosted one-stop-shop for all your PDF needs.
|
||||
|
||||
|
||||
home.multiTool.title=PDF Multi Tool
|
||||
home.multiTool.desc=Merge, Rotate, Rearrange, and Remove pages
|
||||
multiTool.tags=Multi Tool,Multi operation,UI,click drag,front end,client side,interactive,intractable,move
|
||||
|
||||
home.merge.title=Merge
|
||||
home.merge.desc=Easily merge multiple PDFs into one.
|
||||
merge.tags=merge,Page operations,Back end,server side
|
||||
|
||||
home.split.title=Split
|
||||
home.split.desc=Split PDFs into multiple documents
|
||||
split.tags=Page operations,divide,Multi Page,cut,server side
|
||||
|
||||
home.rotate.title=Rotate
|
||||
home.rotate.desc=Easily rotate your PDFs.
|
||||
rotate.tags=server side
|
||||
|
||||
|
||||
home.imageToPdf.title=Image to PDF
|
||||
home.imageToPdf.desc=Convert a image (PNG, JPEG, GIF) to PDF.
|
||||
imageToPdf.tags=conversion,img,jpg,picture,photo
|
||||
|
||||
home.pdfToImage.title=PDF to Image
|
||||
home.pdfToImage.desc=Convert a PDF to a image. (PNG, JPEG, GIF)
|
||||
pdfToImage.tags=conversion,img,jpg,picture,photo
|
||||
|
||||
home.pdfOrganiser.title=Organize
|
||||
home.pdfOrganiser.desc=Remove/Rearrange pages in any order
|
||||
pdfOrganiser.tags=duplex,even,odd,sort,move
|
||||
|
||||
|
||||
home.addImage.title=Add image
|
||||
home.addImage.desc=Adds a image onto a set location on the PDF
|
||||
addImage.tags=img,jpg,picture,photo
|
||||
|
||||
home.watermark.title=Add Watermark
|
||||
home.watermark.desc=Add a custom watermark to your PDF document.
|
||||
watermark.tags=Text,repeating,label,own,copyright,trademark,img,jpg,picture,photo
|
||||
|
||||
home.permissions.title=Change Permissions
|
||||
home.permissions.desc=Change the permissions of your PDF document
|
||||
permissions.tags=read,write,edit,print
|
||||
|
||||
|
||||
home.removePages.title=Remove
|
||||
home.removePages.desc=Delete unwanted pages from your PDF document.
|
||||
removePages.tags=Remove pages,delete pages
|
||||
|
||||
home.addPassword.title=Add Password
|
||||
home.addPassword.desc=Encrypt your PDF document with a password.
|
||||
addPassword.tags=secure,security
|
||||
|
||||
home.removePassword.title=Remove Password
|
||||
home.removePassword.desc=Remove password protection from your PDF document.
|
||||
removePassword.tags=secure,Decrypt,security,unpassword,delete password
|
||||
|
||||
home.compressPdfs.title=Compress
|
||||
home.compressPdfs.desc=Compress PDFs to reduce their file size.
|
||||
compressPdfs.tags=squish,small,tiny
|
||||
|
||||
|
||||
home.changeMetadata.title=Change Metadata
|
||||
home.changeMetadata.desc=Change/Remove/Add metadata from a PDF document
|
||||
changeMetadata.tags==Title,author,date,creation,time,publisher,producer,stats
|
||||
|
||||
home.fileToPDF.title=Convert file to PDF
|
||||
home.fileToPDF.desc=Convert nearly any file to PDF (DOCX, PNG, XLS, PPT, TXT and more)
|
||||
fileToPDF.tags=transformation,format,document,picture,slide,text,conversion,office,docs,word,excel,powerpoint
|
||||
|
||||
home.ocr.title=OCR / Cleanup scans
|
||||
home.ocr.desc=Cleanup scans and detects text from images within a PDF and re-adds it as text.
|
||||
ocr.tags=recognition,text,image,scan,read,identify,detection,editable
|
||||
|
||||
|
||||
home.extractImages.title=Extract Images
|
||||
home.extractImages.desc=Extracts all images from a PDF and saves them to zip
|
||||
extractImages.tags=picture,photo,save,archive,zip,capture,grab
|
||||
|
||||
home.pdfToPDFA.title=PDF to PDF/A
|
||||
home.pdfToPDFA.desc=Convert PDF to PDF/A for long-term storage
|
||||
pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation
|
||||
|
||||
home.PDFToWord.title=PDF to Word
|
||||
home.PDFToWord.desc=Convert PDF to Word formats (DOC, DOCX and ODT)
|
||||
PDFToWord.tags=doc,docx,odt,word,transformation,format,conversion,office,microsoft,docfile
|
||||
|
||||
home.PDFToPresentation.title=PDF to Presentation
|
||||
home.PDFToPresentation.desc=Convert PDF to Presentation formats (PPT, PPTX and ODP)
|
||||
PDFToPresentation.tags=slides,show,office,microsoft
|
||||
|
||||
home.PDFToText.title=PDF to RTF (Text)
|
||||
home.PDFToText.desc=Convert PDF to Text or RTF format
|
||||
PDFToText.tags=richformat,richtextformat,rich text format
|
||||
|
||||
home.PDFToHTML.title=PDF to HTML
|
||||
home.PDFToHTML.desc=Convert PDF to HTML format
|
||||
PDFToHTML.tags=web content,browser friendly
|
||||
|
||||
|
||||
home.PDFToXML.title=PDF to XML
|
||||
home.PDFToXML.desc=Convert PDF to XML format
|
||||
PDFToXML.tags=data-extraction,structured-content,interop,transformation,convert
|
||||
|
||||
home.ScannerImageSplit.title=Detect/Split Scanned photos
|
||||
home.ScannerImageSplit.desc=Splits multiple photos from within a photo/PDF
|
||||
ScannerImageSplit.tags=separate,auto-detect,scans,multi-photo,organize
|
||||
|
||||
home.sign.title=Sign
|
||||
home.sign.desc=Adds signature to PDF by drawing, text or image
|
||||
sign.tags=authorize,initials,drawn-signature,text-sign,image-signature
|
||||
|
||||
home.flatten.title=Flatten
|
||||
home.flatten.desc=Remove all interactive elements and forms from a PDF
|
||||
flatten.tags=static,deactivate,non-interactive,streamline
|
||||
|
||||
home.repair.title=Repair
|
||||
home.repair.desc=Tries to repair a corrupt/broken PDF
|
||||
repair.tags=fix,restore,correction,recover
|
||||
|
||||
home.removeBlanks.title=Remove Blank pages
|
||||
home.removeBlanks.desc=Detects and removes blank pages from a document
|
||||
removeBlanks.tags=cleanup,streamline,non-content,organize
|
||||
|
||||
home.compare.title=Compare
|
||||
home.compare.desc=Compares and shows the differences between 2 PDF Documents
|
||||
compare.tags=differentiate,contrast,changes,analysis
|
||||
|
||||
home.certSign.title=Sign with Certificate
|
||||
home.certSign.desc=Signs a PDF with a Certificate/Key (PEM/P12)
|
||||
certSign.tags=authenticate,PEM,P12,official,encrypt
|
||||
|
||||
home.pageLayout.title=Multi-Page Layout
|
||||
home.pageLayout.desc=Merge multiple pages of a PDF document into a single page
|
||||
pageLayout.tags=merge,composite,single-view,organize
|
||||
|
||||
home.scalePages.title=Adjust page size/scale
|
||||
home.scalePages.desc=Change the size/scale of a page and/or its contents.
|
||||
scalePages.tags=resize,modify,dimension,adapt
|
||||
|
||||
home.pipeline.title=Pipeline (Advanced)
|
||||
home.pipeline.desc=Run multiple actions on PDFs by defining pipeline scripts
|
||||
pipeline.tags=automate,sequence,scripted,batch-process
|
||||
|
||||
home.add-page-numbers.title=Add Page Numbers
|
||||
home.add-page-numbers.desc=Add Page numbers throughout a document in a set location
|
||||
add-page-numbers.tags=paginate,label,organize,index
|
||||
|
||||
home.auto-rename.title=Auto Rename PDF File
|
||||
home.auto-rename.desc=Auto renames a PDF file based on its detected header
|
||||
auto-rename.tags=auto-detect,header-based,organize,relabel
|
||||
|
||||
home.adjust-contrast.title=Adjust Colors/Contrast
|
||||
home.adjust-contrast.desc=Adjust Contrast, Saturation and Brightness of a PDF
|
||||
adjust-contrast.tags=color-correction,tune,modify,enhance
|
||||
|
||||
home.crop.title=Crop PDF
|
||||
home.crop.desc=Crop a PDF to reduce its size (maintains text!)
|
||||
crop.tags=trim,shrink,edit,shape
|
||||
|
||||
home.autoSplitPDF.title=Auto Split Pages
|
||||
home.autoSplitPDF.desc=Auto Split Scanned PDF with physical scanned page splitter QR Code
|
||||
autoSplitPDF.tags=QR-based,separate,scan-segment,organize
|
||||
|
||||
home.sanitizePdf.title=Sanitize
|
||||
home.sanitizePdf.desc=Remove scripts and other elements from PDF files
|
||||
sanitizePdf.tags=clean,secure,safe,remove-threats
|
||||
|
||||
home.URLToPDF.title=URL/Website To PDF
|
||||
home.URLToPDF.desc=Converts any http(s)URL to PDF
|
||||
URLToPDF.tags=web-capture,save-page,web-to-doc,archive
|
||||
|
||||
home.HTMLToPDF.title=HTML to PDF
|
||||
home.HTMLToPDF.desc=Converts any HTML file or zip to PDF
|
||||
HTMLToPDF.tags=markup,web-content,transformation,convert
|
||||
|
||||
|
||||
home.MarkdownToPDF.title=Markdown to PDF
|
||||
home.MarkdownToPDF.desc=Converts any Markdown file to PDF
|
||||
MarkdownToPDF.tags=markup,web-content,transformation,convert
|
||||
|
||||
|
||||
home.getPdfInfo.title=Get ALL Info on PDF
|
||||
home.getPdfInfo.desc=Grabs any and all information possible on PDFs
|
||||
getPdfInfo.tags=infomation,data,stats,statistics
|
||||
|
||||
|
||||
home.extractPage.title=Extract page(s)
|
||||
home.extractPage.desc=Extracts select pages from PDF
|
||||
extractPage.tags=extract
|
||||
|
||||
|
||||
home.PdfToSinglePage.title=PDF to Single Large Page
|
||||
home.PdfToSinglePage.desc=Merges all PDF pages into one large single page
|
||||
PdfToSinglePage.tags=single page
|
||||
|
||||
|
||||
home.showJS.title=Show Javascript
|
||||
home.showJS.desc=Searches and displays any JS injected into a PDF
|
||||
showJS.tags=JS
|
||||
|
||||
home.autoRedact.title=Auto Redact
|
||||
home.autoRedact.desc=Auto Redacts(Blacks out) text in a PDF based on input text
|
||||
showJS.tags=JS
|
||||
|
||||
###########################
|
||||
# #
|
||||
# WEB PAGES #
|
||||
# #
|
||||
###########################
|
||||
#login
|
||||
login.title=Sign in
|
||||
login.signin=Sign in
|
||||
login.rememberme=Remember me
|
||||
login.invalid=Invalid username or password.
|
||||
login.locked=Your account has been locked.
|
||||
login.signinTitle=Please sign in
|
||||
|
||||
|
||||
#auto-redact
|
||||
autoRedact.title=Auto Redact
|
||||
autoRedact.header=Auto Redact
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
autoRedact.colorLabel=Color
|
||||
autoRedact.textsToRedactLabel=Text to Redact (line-separated)
|
||||
autoRedact.textsToRedactPlaceholder=e.g. \nConfidential \nTop-Secret
|
||||
autoRedact.useRegexLabel=Use Regex
|
||||
autoRedact.wholeWordSearchLabel=Whole Word Search
|
||||
autoRedact.customPaddingLabel=Custom Extra Padding
|
||||
autoRedact.convertPDFToImageLabel=Convert PDF to PDF-Image (Used to remove text behind the box)
|
||||
autoRedact.submitButton=Submit
|
||||
|
||||
|
||||
#showJS
|
||||
showJS.title=Show Javascript
|
||||
showJS.header=Show Javascript
|
||||
showJS.downloadJS=Download Javascript
|
||||
showJS.submit=Show
|
||||
|
||||
|
||||
#pdfToSinglePage
|
||||
pdfToSinglePage.title=PDF To Single Page
|
||||
pdfToSinglePage.header=PDF To Single Page
|
||||
pdfToSinglePage.submit=Convert To Single Page
|
||||
|
||||
|
||||
#pageExtracter
|
||||
pageExtracter.title=Extract Pages
|
||||
pageExtracter.header=Extract Pages
|
||||
pageExtracter.submit=Extract
|
||||
|
||||
|
||||
#getPdfInfo
|
||||
getPdfInfo.title=Get Info on PDF
|
||||
getPdfInfo.header=Get Info on PDF
|
||||
getPdfInfo.submit=Get Info
|
||||
getPdfInfo.downloadJson=Download JSON
|
||||
|
||||
|
||||
#markdown-to-pdf
|
||||
MarkdownToPDF.title=Markdown To PDF
|
||||
MarkdownToPDF.header=Markdown To PDF
|
||||
MarkdownToPDF.submit=Convert
|
||||
MarkdownToPDF.help=Work in progress
|
||||
MarkdownToPDF.credit=Uses WeasyPrint
|
||||
|
||||
|
||||
|
||||
#url-to-pdf
|
||||
URLToPDF.title=URL To PDF
|
||||
URLToPDF.header=URL To PDF
|
||||
URLToPDF.submit=Convert
|
||||
URLToPDF.credit=Uses WeasyPrint
|
||||
|
||||
|
||||
#html-to-pdf
|
||||
HTMLToPDF.title=HTML To PDF
|
||||
HTMLToPDF.header=HTML To PDF
|
||||
HTMLToPDF.help=Accepts HTML files and ZIPs containing html/css/images etc required
|
||||
HTMLToPDF.submit=Convert
|
||||
HTMLToPDF.credit=Uses WeasyPrint
|
||||
|
||||
|
||||
#sanitizePDF
|
||||
sanitizePDF.title=Sanitize PDF
|
||||
sanitizePDF.header=Sanitize a PDF file
|
||||
sanitizePDF.selectText.1=Remove JavaScript actions
|
||||
sanitizePDF.selectText.2=Remove embedded files
|
||||
sanitizePDF.selectText.3=Remove metadata
|
||||
sanitizePDF.selectText.4=Remove links
|
||||
sanitizePDF.selectText.5=Remove fonts
|
||||
sanitizePDF.submit=Sanitize PDF
|
||||
|
||||
|
||||
#addPageNumbers
|
||||
addPageNumbers.title=Add Page Numbers
|
||||
addPageNumbers.header=Add Page Numbers
|
||||
addPageNumbers.selectText.1=Select PDF file:
|
||||
addPageNumbers.selectText.2=Margin Size
|
||||
addPageNumbers.selectText.3=Position
|
||||
addPageNumbers.selectText.4=Starting Number
|
||||
addPageNumbers.selectText.5=Pages to Number
|
||||
addPageNumbers.selectText.6=Custom Text
|
||||
addPageNumbers.customTextDesc=Custom Text
|
||||
addPageNumbers.numberPagesDesc=Which pages to number, default 'all', also accepts 1-5 or 2,5,9 etc
|
||||
addPageNumbers.customNumberDesc=Defaults to {n}, also accepts 'Page {n} of {total}', 'Text-{n}', '{filename}-{n}
|
||||
addPageNumbers.submit=Add Page Numbers
|
||||
|
||||
|
||||
#auto-rename
|
||||
auto-rename.title=Auto Rename
|
||||
auto-rename.header=Auto Rename PDF
|
||||
auto-rename.submit=Auto Rename
|
||||
|
||||
|
||||
#adjustContrast
|
||||
adjustContrast.title=Adjust Contrast
|
||||
adjustContrast.header=Adjust Contrast
|
||||
adjustContrast.contrast=Contrast:
|
||||
adjustContrast.brightness=Brightness:
|
||||
adjustContrast.saturation=Saturation:
|
||||
adjustContrast.download=Download
|
||||
|
||||
|
||||
#crop
|
||||
crop.title=Crop
|
||||
crop.header=Crop Image
|
||||
crop.submit=Submit
|
||||
|
||||
|
||||
#autoSplitPDF
|
||||
autoSplitPDF.title=Auto Split PDF
|
||||
autoSplitPDF.header=Auto Split PDF
|
||||
autoSplitPDF.description=Print, Insert, Scan, upload, and let us auto-separate your documents. No manual work sorting needed.
|
||||
autoSplitPDF.selectText.1=Print out some divider sheets from below (Black and white is fine).
|
||||
autoSplitPDF.selectText.2=Scan all your documents at once by inserting the divider sheet between them.
|
||||
autoSplitPDF.selectText.3=Upload the single large scanned PDF file and let Stirling PDF handle the rest.
|
||||
autoSplitPDF.selectText.4=Divider pages are automatically detected and removed, guaranteeing a neat final document.
|
||||
autoSplitPDF.formPrompt=Submit PDF containing Stirling-PDF Page dividers:
|
||||
autoSplitPDF.duplexMode=Duplex Mode (Front and back scanning)
|
||||
autoSplitPDF.dividerDownload1=Download 'Auto Splitter Divider (minimal).pdf'
|
||||
autoSplitPDF.dividerDownload2=Download 'Auto Splitter Divider (with instructions).pdf'
|
||||
autoSplitPDF.submit=Submit
|
||||
|
||||
|
||||
#pipeline
|
||||
pipeline.title=Pipeline
|
||||
|
||||
|
||||
#pageLayout
|
||||
pageLayout.title=Multi Page Layout
|
||||
pageLayout.header=Multi Page Layout
|
||||
pageLayout.pagesPerSheet=Pages per sheet:
|
||||
pageLayout.submit=Submit
|
||||
|
||||
|
||||
#scalePages
|
||||
scalePages.title=Adjust page-scale
|
||||
scalePages.header=Adjust page-scale
|
||||
scalePages.pageSize=Size of a page of the document.
|
||||
scalePages.scaleFactor=Zoom level (crop) of a page.
|
||||
scalePages.submit=Submit
|
||||
|
||||
|
||||
#certSign
|
||||
certSign.title=Certificate Signing
|
||||
certSign.header=Sign a PDF with your certificate (Work in progress)
|
||||
certSign.selectPDF=Select a PDF File for Signing:
|
||||
certSign.selectKey=Select Your Private Key File (PKCS#8 format, could be .pem or .der):
|
||||
certSign.selectCert=Select Your Certificate File (X.509 format, could be .pem or .der):
|
||||
certSign.selectP12=Select Your PKCS#12 Keystore File (.p12 or .pfx) (Optional, If provided, it should contain your private key and certificate):
|
||||
certSign.certType=Certificate Type
|
||||
certSign.password=Enter Your Keystore or Private Key Password (If Any):
|
||||
certSign.showSig=Show Signature
|
||||
certSign.reason=Reason
|
||||
certSign.location=Location
|
||||
certSign.name=Name
|
||||
certSign.submit=Sign PDF
|
||||
|
||||
|
||||
#removeBlanks
|
||||
removeBlanks.title=Remove Blanks
|
||||
removeBlanks.header=Remove Blank Pages
|
||||
removeBlanks.threshold=Pixel Whiteness Threshold:
|
||||
removeBlanks.thresholdDesc=Threshold for determining how white a white pixel must be to be classed as 'White'. 0 = Black, 255 pure white.
|
||||
removeBlanks.whitePercent=White Percent (%):
|
||||
removeBlanks.whitePercentDesc=Percent of page that must be 'white' pixels to be removed
|
||||
removeBlanks.submit=Remove Blanks
|
||||
|
||||
|
||||
#compare
|
||||
compare.title=Compare
|
||||
compare.header=Compare PDFs
|
||||
compare.document.1=Document 1
|
||||
compare.document.2=Document 2
|
||||
compare.submit=Compare
|
||||
|
||||
|
||||
#sign
|
||||
sign.title=Sign
|
||||
sign.header=Sign PDFs
|
||||
sign.upload=Upload Image
|
||||
sign.draw=Draw Signature
|
||||
sign.text=Text Input
|
||||
sign.clear=Clear
|
||||
sign.add=Add
|
||||
|
||||
|
||||
#repair
|
||||
repair.title=Repair
|
||||
repair.header=Repair PDFs
|
||||
repair.submit=Repair
|
||||
|
||||
|
||||
#flatten
|
||||
flatten.title=Flatten
|
||||
flatten.header=Flatten PDFs
|
||||
flatten.submit=Flatten
|
||||
|
||||
|
||||
#ScannerImageSplit
|
||||
ScannerImageSplit.selectText.1=Angle Threshold:
|
||||
ScannerImageSplit.selectText.2=Sets the minimum absolute angle required for the image to be rotated (default: 10).
|
||||
ScannerImageSplit.selectText.3=Tolerance:
|
||||
ScannerImageSplit.selectText.4=Determines the range of color variation around the estimated background color (default: 30).
|
||||
ScannerImageSplit.selectText.5=Minimum Area:
|
||||
ScannerImageSplit.selectText.6=Sets the minimum area threshold for a photo (default: 10000).
|
||||
ScannerImageSplit.selectText.7=Minimum Contour Area:
|
||||
ScannerImageSplit.selectText.8=Sets the minimum contour area threshold for a photo
|
||||
ScannerImageSplit.selectText.9=Border Size:
|
||||
ScannerImageSplit.selectText.10=Sets the size of the border added and removed to prevent white borders in the output (default: 1).
|
||||
|
||||
|
||||
#OCR
|
||||
ocr.title=OCR / Scan Cleanup
|
||||
ocr.header=Cleanup Scans / OCR (Optical Character Recognition)
|
||||
ocr.selectText.1=Select languages that are to be detected within the PDF (Ones listed are the ones currently detected):
|
||||
ocr.selectText.2=Produce text file containing OCR text alongside the OCR'ed PDF
|
||||
ocr.selectText.3=Correct pages were scanned at a skewed angle by rotating them back into place
|
||||
ocr.selectText.4=Clean page so its less likely that OCR will find text in background noise. (No output change)
|
||||
ocr.selectText.5=Clean page so its less likely that OCR will find text in background noise, maintains cleanup in output.
|
||||
ocr.selectText.6=Ignores pages that have interactive text on them, only OCRs pages that are images
|
||||
ocr.selectText.7=Force OCR, will OCR Every page removing all original text elements
|
||||
ocr.selectText.8=Normal (Will error if PDF contains text)
|
||||
ocr.selectText.9=Additional Settings
|
||||
ocr.selectText.10=OCR Mode
|
||||
ocr.selectText.11=Remove images after OCR (Removes ALL images, only useful if part of conversion step)
|
||||
ocr.selectText.12=Render Type (Advanced)
|
||||
ocr.help=Please read this documentation on how to use this for other languages and/or use not in docker
|
||||
ocr.credit=This service uses OCRmyPDF and Tesseract for OCR.
|
||||
ocr.submit=Process PDF with OCR
|
||||
|
||||
|
||||
#extractImages
|
||||
extractImages.title=Extract Images
|
||||
extractImages.header=Extract Images
|
||||
extractImages.selectText=Select image format to convert extracted images to
|
||||
extractImages.submit=Extract
|
||||
|
||||
|
||||
#File to PDF
|
||||
fileToPDF.title=File to PDF
|
||||
fileToPDF.header=Convert any file to PDF
|
||||
fileToPDF.credit=This service uses LibreOffice and Unoconv for file conversion.
|
||||
fileToPDF.supportedFileTypes=Supported file types should include the below however for a full updated list of supported formats, please refer to the LibreOffice documentation
|
||||
fileToPDF.submit=Convert to PDF
|
||||
|
||||
|
||||
#compress
|
||||
compress.title=Compress
|
||||
compress.header=Compress PDF
|
||||
compress.credit=This service uses Ghostscript for PDF Compress/Optimisation.
|
||||
compress.selectText.1=Manual Mode - From 1 to 4
|
||||
compress.selectText.2=Optimization level:
|
||||
compress.selectText.3=4 (Terrible for text images)
|
||||
compress.selectText.4=Auto mode - Auto adjusts quality to get PDF to exact size
|
||||
compress.selectText.5=Expected PDF Size (e.g. 25MB, 10.8MB, 25KB)
|
||||
compress.submit=Compress
|
||||
|
||||
|
||||
#Add image
|
||||
addImage.title=Add Image
|
||||
addImage.header=Add image to PDF
|
||||
addImage.everyPage=Every Page?
|
||||
addImage.upload=Add image
|
||||
addImage.submit=Add image
|
||||
|
||||
|
||||
#merge
|
||||
merge.title=Merge
|
||||
merge.header=Merge multiple PDFs (2+)
|
||||
merge.sortByName=Sort by name
|
||||
merge.sortByDate=Sort by date
|
||||
merge.submit=Merge
|
||||
|
||||
|
||||
#pdfOrganiser
|
||||
pdfOrganiser.title=Page Organizer
|
||||
pdfOrganiser.header=PDF Page Organizer
|
||||
pdfOrganiser.submit=Rearrange Pages
|
||||
|
||||
|
||||
#multiTool
|
||||
multiTool.title=PDF Multi Tool
|
||||
multiTool.header=PDF Multi Tool
|
||||
|
||||
|
||||
#pageRemover
|
||||
pageRemover.title=Page Remover
|
||||
pageRemover.header=PDF Page remover
|
||||
pageRemover.pagesToDelete=Pages to delete (Enter a comma-separated list of page numbers) :
|
||||
pageRemover.submit=Delete Pages
|
||||
|
||||
|
||||
#rotate
|
||||
rotate.title=Rotate PDF
|
||||
rotate.header=Rotate PDF
|
||||
rotate.selectAngle=Select rotation angle (in multiples of 90 degrees):
|
||||
rotate.submit=Rotate
|
||||
|
||||
|
||||
#merge
|
||||
split.title=Split PDF
|
||||
split.header=Split PDF
|
||||
split.desc.1=The numbers you select are the page number you wish to do a split on
|
||||
split.desc.2=As such selecting 1,3,7-8 would split a 10 page document into 6 separate PDFS with:
|
||||
split.desc.3=Document #1: Page 1
|
||||
split.desc.4=Document #2: Page 2 and 3
|
||||
split.desc.5=Document #3: Page 4, 5 and 6
|
||||
split.desc.6=Document #4: Page 7
|
||||
split.desc.7=Document #5: Page 8
|
||||
split.desc.8=Document #6: Page 9 and 10
|
||||
split.splitPages=Enter pages to split on:
|
||||
split.submit=Split
|
||||
|
||||
|
||||
#merge
|
||||
imageToPDF.title=Image to PDF
|
||||
imageToPDF.header=Image to PDF
|
||||
imageToPDF.submit=Convert
|
||||
imageToPDF.selectText.1=Stretch to fit
|
||||
imageToPDF.selectText.2=Auto rotate PDF
|
||||
imageToPDF.selectText.3=Multi file logic (Only enabled if working with multiple images)
|
||||
imageToPDF.selectText.4=Merge into single PDF
|
||||
imageToPDF.selectText.5=Convert to separate PDFs
|
||||
|
||||
|
||||
#pdfToImage
|
||||
pdfToImage.title=PDF to Image
|
||||
pdfToImage.header=PDF to Image
|
||||
pdfToImage.selectText=Image Format
|
||||
pdfToImage.singleOrMultiple=Image result type
|
||||
pdfToImage.single=Single Big Image
|
||||
pdfToImage.multi=Multiple Images
|
||||
pdfToImage.colorType=Color type
|
||||
pdfToImage.color=Color
|
||||
pdfToImage.grey=Grayscale
|
||||
pdfToImage.blackwhite=Black and White (May lose data!)
|
||||
pdfToImage.submit=Convert
|
||||
|
||||
|
||||
#addPassword
|
||||
addPassword.title=Add Password
|
||||
addPassword.header=Add password (Encrypt)
|
||||
addPassword.selectText.1=Select PDF to encrypt
|
||||
addPassword.selectText.2=User Password
|
||||
addPassword.selectText.3=Encryption Key Length
|
||||
addPassword.selectText.4=Higher values are stronger, but lower values have better compatibility.
|
||||
addPassword.selectText.5=Permissions to set (Recommended to be used along with Owner password)
|
||||
addPassword.selectText.6=Prevent assembly of document
|
||||
addPassword.selectText.7=Prevent content extraction
|
||||
addPassword.selectText.8=Prevent extraction for accessibility
|
||||
addPassword.selectText.9=Prevent filling in form
|
||||
addPassword.selectText.10=Prevent modification
|
||||
addPassword.selectText.11=Prevent annotation modification
|
||||
addPassword.selectText.12=Prevent printing
|
||||
addPassword.selectText.13=Prevent printing different formats
|
||||
addPassword.selectText.14=Owner Password
|
||||
addPassword.selectText.15=Restricts what can be done with the document once it is opened (Not supported by all readers)
|
||||
addPassword.selectText.16=Restricts the opening of the document itself
|
||||
addPassword.submit=Encrypt
|
||||
|
||||
|
||||
#watermark
|
||||
watermark.title=Add Watermark
|
||||
watermark.header=Add Watermark
|
||||
watermark.selectText.1=Select PDF to add watermark to:
|
||||
watermark.selectText.2=Watermark Text:
|
||||
watermark.selectText.3=Font Size:
|
||||
watermark.selectText.4=Rotation (0-360):
|
||||
watermark.selectText.5=widthSpacer (Space between each watermark horizontally):
|
||||
watermark.selectText.6=heightSpacer (Space between each watermark vertically):
|
||||
watermark.selectText.7=Opacity (0% - 100%):
|
||||
watermark.selectText.8=Watermark Type:
|
||||
watermark.selectText.9=Watermark Image:
|
||||
watermark.submit=Add Watermark
|
||||
|
||||
|
||||
#Change permissions
|
||||
permissions.title=Change Permissions
|
||||
permissions.header=Change Permissions
|
||||
permissions.warning=Warning to have these permissions be unchangeable it is recommended to set them with a password via the add-password page
|
||||
permissions.selectText.1=Select PDF to change permissions
|
||||
permissions.selectText.2=Permissions to set
|
||||
permissions.selectText.3=Prevent assembly of document
|
||||
permissions.selectText.4=Prevent content extraction
|
||||
permissions.selectText.5=Prevent extraction for accessibility
|
||||
permissions.selectText.6=Prevent filling in form
|
||||
permissions.selectText.7=Prevent modification
|
||||
permissions.selectText.8=Prevent annotation modification
|
||||
permissions.selectText.9=Prevent printing
|
||||
permissions.selectText.10=Prevent printing different formats
|
||||
permissions.submit=Change
|
||||
|
||||
|
||||
#remove password
|
||||
removePassword.title=Remove password
|
||||
removePassword.header=Remove password (Decrypt)
|
||||
removePassword.selectText.1=Select PDF to Decrypt
|
||||
removePassword.selectText.2=Password
|
||||
removePassword.submit=Remove
|
||||
|
||||
|
||||
#changeMetadata
|
||||
changeMetadata.title=Title:
|
||||
changeMetadata.header=Change Metadata
|
||||
changeMetadata.selectText.1=Please edit the variables you wish to change
|
||||
changeMetadata.selectText.2=Delete all metadata
|
||||
changeMetadata.selectText.3=Show Custom Metadata:
|
||||
changeMetadata.author=Author:
|
||||
changeMetadata.creationDate=Creation Date (yyyy/MM/dd HH:mm:ss):
|
||||
changeMetadata.creator=Creator:
|
||||
changeMetadata.keywords=Keywords:
|
||||
changeMetadata.modDate=Modification Date (yyyy/MM/dd HH:mm:ss):
|
||||
changeMetadata.producer=Producer:
|
||||
changeMetadata.subject=Subject:
|
||||
changeMetadata.title=Title:
|
||||
changeMetadata.trapped=Trapped:
|
||||
changeMetadata.selectText.4=Other Metadata:
|
||||
changeMetadata.selectText.5=Add Custom Metadata Entry
|
||||
changeMetadata.submit=Change
|
||||
|
||||
|
||||
#xlsToPdf
|
||||
xlsToPdf.title=Excel to PDF
|
||||
xlsToPdf.header=Excel to PDF
|
||||
xlsToPdf.selectText.1=Select XLS or XLSX Excel sheet to convert
|
||||
xlsToPdf.convert=convert
|
||||
|
||||
|
||||
#pdfToPDFA
|
||||
pdfToPDFA.title=PDF To PDF/A
|
||||
pdfToPDFA.header=PDF To PDF/A
|
||||
pdfToPDFA.credit=This service uses OCRmyPDF for PDF/A conversion
|
||||
pdfToPDFA.submit=Convert
|
||||
|
||||
|
||||
#PDFToWord
|
||||
PDFToWord.title=PDF to Word
|
||||
PDFToWord.header=PDF to Word
|
||||
PDFToWord.selectText.1=Output file format
|
||||
PDFToWord.credit=This service uses LibreOffice for file conversion.
|
||||
PDFToWord.submit=Convert
|
||||
|
||||
|
||||
#PDFToPresentation
|
||||
PDFToPresentation.title=PDF to Presentation
|
||||
PDFToPresentation.header=PDF to Presentation
|
||||
PDFToPresentation.selectText.1=Output file format
|
||||
PDFToPresentation.credit=This service uses LibreOffice for file conversion.
|
||||
PDFToPresentation.submit=Convert
|
||||
|
||||
|
||||
#PDFToText
|
||||
PDFToText.title=PDF to RTF (Text)
|
||||
PDFToText.header=PDF to RTF (Text)
|
||||
PDFToText.selectText.1=Output file format
|
||||
PDFToText.credit=This service uses LibreOffice for file conversion.
|
||||
PDFToText.submit=Convert
|
||||
|
||||
|
||||
#PDFToHTML
|
||||
PDFToHTML.title=PDF to HTML
|
||||
PDFToHTML.header=PDF to HTML
|
||||
PDFToHTML.credit=This service uses LibreOffice for file conversion.
|
||||
PDFToHTML.submit=Convert
|
||||
|
||||
|
||||
#PDFToXML
|
||||
PDFToXML.title=PDF to XML
|
||||
PDFToXML.header=PDF to XML
|
||||
PDFToXML.credit=This service uses LibreOffice for file conversion.
|
||||
PDFToXML.submit=Convert
|
||||
@@ -6,7 +6,7 @@ language.direction=ltr
|
||||
|
||||
pdfPrompt=Seleccionar PDF(s)
|
||||
multiPdfPrompt=Seleccionar PDFs (2+)
|
||||
multiPdfDropPrompt=Selecciona (o arrastra y suelta) todos los PDFs que quieras
|
||||
multiPdfDropPrompt=Seleccione (o arrastre y suelte) todos los PDFs que quiera
|
||||
imgPrompt=Seleccionar Imagen(es)
|
||||
genericSubmit=Enviar
|
||||
processTimeWarning=Advertencia: este proceso puede tardar hasta un minuto dependiendo del tamaño del archivo
|
||||
@@ -19,18 +19,35 @@ save=Guardar
|
||||
close=Cerrar
|
||||
filesSelected=archivos seleccionados
|
||||
noFavourites=No se agregaron favoritos
|
||||
bored=¿Aburrido de esperar?
|
||||
bored=¿Cansado de esperar?
|
||||
alphabet=Alfabeto
|
||||
downloadPdf=Descargar PDF
|
||||
text=Texto
|
||||
font=Fuente
|
||||
selectFillter=-- Select --
|
||||
selectFillter=-- Seleccionar --
|
||||
pageNum=Número de página
|
||||
sizes.small=Small
|
||||
sizes.medium=Medium
|
||||
sizes.large=Large
|
||||
sizes.x-large=X-Large
|
||||
sizes.small=Paqueño
|
||||
sizes.medium=Mediano
|
||||
sizes.large=Grande
|
||||
sizes.x-large=Extra grande
|
||||
error.pdfPassword=El documento PDF está protegido con contraseña y no se ha proporcionado o es incorrecta
|
||||
delete=Delete
|
||||
username=Username
|
||||
password=Password
|
||||
welcome=Welcome
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
property=Property
|
||||
black=Black
|
||||
white=White
|
||||
red=Red
|
||||
green=Green
|
||||
blue=Blue
|
||||
custom=Custom...
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#############
|
||||
@@ -54,385 +71,391 @@ settings.downloadOption.1=Abrir en la misma ventana
|
||||
settings.downloadOption.2=Abrir en una nueva ventana
|
||||
settings.downloadOption.3=Descargar el fichero
|
||||
settings.zipThreshold=Ficheros ZIP cuando excede el número de ficheros descargados
|
||||
settings.signOut=Sign Out
|
||||
settings.accountSettings=Account Settings
|
||||
|
||||
account.title=Account Settings
|
||||
account.accountSettings=Account Settings
|
||||
account.adminSettings=Admin Settings - View and Add Users
|
||||
account.userControlSettings=User Control Settings
|
||||
account.changeUsername=Change Username
|
||||
account.changeUsername=Change Username
|
||||
account.password=Confirmation Password
|
||||
account.oldPassword=Old password
|
||||
account.newPassword=New Password
|
||||
account.changePassword=Change Password
|
||||
account.confirmNewPassword=Confirm New Password
|
||||
account.signOut=Sign Out
|
||||
account.yourApiKey=Your API Key
|
||||
account.syncTitle=Sync browser settings with Account
|
||||
account.settingsCompare=Settings Comparison:
|
||||
account.property=Property
|
||||
account.webBrowserSettings=Web Browser Setting
|
||||
account.syncToBrowser=Sync Account -> Browser
|
||||
account.syncToAccount=Sync Account <- Browser
|
||||
|
||||
|
||||
adminUserSettings.title=User Control Settings
|
||||
adminUserSettings.header=Admin User Control Settings
|
||||
adminUserSettings.admin=Admin
|
||||
adminUserSettings.user=User
|
||||
adminUserSettings.addUser=Add New User
|
||||
adminUserSettings.roles=Roles
|
||||
adminUserSettings.role=Role
|
||||
adminUserSettings.actions=Actions
|
||||
adminUserSettings.apiUser=Limited API User
|
||||
adminUserSettings.webOnlyUser=Web Only User
|
||||
adminUserSettings.submit=Save User
|
||||
|
||||
#############
|
||||
# HOME-PAGE #
|
||||
#############
|
||||
home.desc=Tu ventanilla única autohospedada para todas tus necesidades PDF
|
||||
home.desc=Su ventanilla única autohospedada para todas tus necesidades PDF
|
||||
|
||||
|
||||
home.multiTool.title=Multi-herramienta PDF
|
||||
home.multiTool.desc=Combinar, rotar, reorganizar y eliminar páginas
|
||||
multiTool.tags=Multi Tool,Multi operation,UI,click drag,front end,client side
|
||||
multiTool.tags=Multi-herramienta,Multi-operación,Interfaz de usuario,Arrastrar con un click,front end,lado del client
|
||||
|
||||
home.merge.title=Unir
|
||||
home.merge.desc=Unir fácilmente múltiples PDFs en uno
|
||||
merge.tags=merge,Page operations,Back end,server side
|
||||
merge.tags=Unir,Operaciones de página,Back end,lado del servidor
|
||||
|
||||
home.split.title=Dividir
|
||||
home.split.desc=Dividir PDFs en múltiples documentos
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
split.tags=Page operations,divide,Multi Page,cut,server side
|
||||
split.tags=Operaciones de página,dividir,Multi-página,cortar,lado del servidor
|
||||
|
||||
home.rotate.title=Rotar
|
||||
home.rotate.desc=Rotar fácilmente tus PDFs
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
rotate.tags=server side
|
||||
home.rotate.desc=Rotar fácilmente sus PDFs
|
||||
rotate.tags=lado del servidor
|
||||
|
||||
|
||||
home.imageToPdf.title=Imagen a PDF
|
||||
home.imageToPdf.desc=Convertir una imagen (PNG, JPEG, GIF) a PDF
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
imageToPdf.tags=conversion,img,jpg,picture,photo
|
||||
imageToPdf.tags=conversión,img,jpg,imagen,fotografía
|
||||
|
||||
home.pdfToImage.title=PDF a Imagen
|
||||
home.pdfToImage.desc=Convertir un PDF a una imagen (PNG, JPEG, GIF)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
pdfToImage.tags=conversion,img,jpg,picture,photo
|
||||
pdfToImage.tags=conversión,img,jpg,imagen,fotografía
|
||||
|
||||
home.pdfOrganiser.title=Organizador
|
||||
home.pdfOrganiser.desc=Eliminar/Reorganizar páginas en cualquier orden
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
pdfOrganiser.tags=duplex,even,odd,sort,move
|
||||
pdfOrganiser.tags=doble cara,pares,impares,ordenar,mover
|
||||
|
||||
|
||||
home.addImage.title=Agregar imagen al PDF
|
||||
home.addImage.desc=Agregar una imagen en una ubicación establecida en el PDF (trabajo en progreso)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
addImage.tags=img,jpg,picture,photo
|
||||
home.addImage.desc=Agregar una imagen en una ubicación establecida en el PDF (en desarrollo)
|
||||
addImage.tags=img,jpg,imagen,fotografía
|
||||
|
||||
home.watermark.title=Añadir marca de agua
|
||||
home.watermark.desc=Añadir una marca de agua predefinida al documento PDF
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
watermark.tags=Text,repeating,label,own,copyright,trademark,img,jpg,picture,photo
|
||||
watermark.tags=Texto,repetir,etiquetar,propietario,copyight,marca comercial,img,jpg,imagen,fotografía
|
||||
|
||||
home.permissions.title=Cambiar permisos
|
||||
home.permissions.desc=Cambiar los permisos del documento PDF
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
permissions.tags=read,write,edit,print
|
||||
permissions.tags=leer,escribir,editar,imprimir
|
||||
|
||||
|
||||
home.removePages.title=Eliminar
|
||||
home.removePages.desc=Eliminar páginas no deseadas del documento PDF
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
removePages.tags=Remove pages,delete pages
|
||||
removePages.tags=Borrar páginas,eliminar páginas
|
||||
|
||||
home.addPassword.title=Añadir contraseña
|
||||
home.addPassword.desc=Encriptar el documento PDF con una contraseña
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
addPassword.tags=secure,security
|
||||
addPassword.tags=seguro,seguridad
|
||||
|
||||
home.removePassword.title=Eliminar contraseña
|
||||
home.removePassword.desc=Eliminar la contraseña del documento PDF
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
removePassword.tags=secure,Decrypt,security,unpassword,delete password
|
||||
removePassword.tags=seguro,Desencriptar,seguridad,quitar contraseña,eliminar contraseña
|
||||
|
||||
home.compressPdfs.title=Comprimir
|
||||
home.compressPdfs.desc=Comprimir PDFs para reducir el tamaño del fichero
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
compressPdfs.tags=squish,small,tiny
|
||||
compressPdfs.tags=aplastar,pequeño,diminuto
|
||||
|
||||
|
||||
home.changeMetadata.title=Cambiar metadatos
|
||||
home.changeMetadata.desc=Cambiar/Eliminar/Añadir metadatos al documento PDF
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
changeMetadata.tags==Title,author,date,creation,time,publisher,producer,stats
|
||||
changeMetadata.tags==Título,autor,fecha,creación,hora,editorial,productor,estadísticas
|
||||
|
||||
home.fileToPDF.title=Convertir fichero a PDF
|
||||
home.fileToPDF.desc=Convertir casi cualquier archivo a PDF (DOCX, PNG, XLS, PPT, TXT y más)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
fileToPDF.tags=transformation,format,document,picture,slide,text,conversion,office,docs,word,excel,powerpoint
|
||||
fileToPDF.tags=transformación,formato,documento,imagen,diapositiva,texto,conversión,office,docs,word,excel,powerpoint
|
||||
|
||||
home.ocr.title=Ejecutar OCR en PDF y/o escaneos de limpieza
|
||||
home.ocr.desc=Escaneos de limpieza y detectar texto de imágenes dentro de un PDF y volver a agregarlo como texto
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
ocr.tags=recognition,text,image,scan,read,identify,detection,editable
|
||||
home.ocr.title=Ejecutar OCR en PDF y/o tareas de limpieza
|
||||
home.ocr.desc=Tareas de limpieza y detectar texto en imágenes dentro de un PDF y volver a incrustarlo como texto
|
||||
ocr.tags=reconocimiento,texto,imagen,escanear,leer,identificar,detección,editable
|
||||
|
||||
|
||||
home.extractImages.title=Extraer imágenes
|
||||
home.extractImages.desc=Extraer todas las imágenes de un PDF y guardarlas en ZIP
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
extractImages.tags=picture,photo,save,archive,zip,capture,grab
|
||||
extractImages.tags=imagen,fotografía,guardar,archivo,zip,capturar,coger
|
||||
|
||||
home.pdfToPDFA.title=Convertir PDF a PDF/A
|
||||
home.pdfToPDFA.desc=Convertir PDF a PDF/A para almacenamiento a largo plazo
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation
|
||||
pdfToPDFA.tags=archivo,largo plazo,estándar,conversión,almacewnamiento,conservación
|
||||
|
||||
home.PDFToWord.title=PDF a Word
|
||||
home.PDFToWord.desc=Convertir formatos PDF a Word (DOC, DOCX y ODT)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
PDFToWord.tags=doc,docx,odt,word,transformation,format,conversion,office,microsoft,docfile
|
||||
PDFToWord.tags=doc,docx,odt,word,transformación,formato,conversión,office,microsoft,archivo del documento
|
||||
|
||||
home.PDFToPresentation.title=PDF a presentación
|
||||
home.PDFToPresentation.desc=Convertir PDF a formatos de presentación (PPT, PPTX y ODP)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
PDFToPresentation.tags=slides,show,office,microsoft
|
||||
PDFToPresentation.tags=diapositivas,mostrar,office,microsoft
|
||||
|
||||
home.PDFToText.title=PDF a TXT o RTF
|
||||
home.PDFToText.desc=Convertir PDF a formato TXT o RTF
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
PDFToText.tags=richformat,richtextformat,rich text format
|
||||
PDFToText.tags=formato enriquecido,formato de texto enriquecido,formato de texto enriquecido
|
||||
|
||||
home.PDFToHTML.title=PDF a HTML
|
||||
home.PDFToHTML.desc=Convertir PDF a formato HTML
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
PDFToHTML.tags=web content,browser friendly
|
||||
PDFToHTML.tags=contenido web,amigable para navegador
|
||||
|
||||
|
||||
home.PDFToXML.title=PDF a XML
|
||||
home.PDFToXML.desc=Convertir PDF a formato XML
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
PDFToXML.tags=data-extraction,structured-content,interop,transformation,convert
|
||||
PDFToXML.tags=extracción de datos,contenido estructurado,interopersabilidad,transformación,convertir
|
||||
|
||||
home.ScannerImageSplit.title=Detectar/Dividir fotos escaneadas
|
||||
home.ScannerImageSplit.desc=Dividir varias fotos dentro de una foto/PDF
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
ScannerImageSplit.tags=separate,auto-detect,scans,multi-photo,organize
|
||||
ScannerImageSplit.tags=separar,auto-detectar,escaneos,multi-foto,organizar
|
||||
|
||||
home.sign.title=Firmar
|
||||
home.sign.desc=Añadir firma a PDF mediante dibujo, texto o imagen
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
sign.tags=authorize,initials,drawn-signature,text-sign,image-signature
|
||||
sign.tags=autorizar,iniciales,firma manuscrita,texto de firma,imagen de firma
|
||||
|
||||
home.flatten.title=Aplanar
|
||||
home.flatten.desc=Eliminar todos los elementos y formularios interactivos de un PDF
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
flatten.tags=static,deactivate,non-interactive,streamline
|
||||
flatten.tags=estática,desactivar,no interactiva,etiqueta dinámica
|
||||
|
||||
home.repair.title=Reparar
|
||||
home.repair.desc=Intentar reparar un PDF corrupto/roto
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
repair.tags=fix,restore,correction,recover
|
||||
repair.tags=reparar,restaurar,corregir,recuperar
|
||||
|
||||
home.removeBlanks.title=Eliminar páginas en blanco
|
||||
home.removeBlanks.desc=Detectar y eliminar páginas en blanco de un documento
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
removeBlanks.tags=cleanup,streamline,non-content,organize
|
||||
removeBlanks.tags=limpieza,dinámica,sin contenido,organizar
|
||||
|
||||
home.compare.title=Comparar
|
||||
home.compare.desc=Comparar y mostrar las diferencias entre 2 documentos PDF
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
compare.tags=differentiate,contrast,changes,analysis
|
||||
compare.tags=diferenciar,contrastar,cambios,análisis
|
||||
|
||||
home.certSign.title=Firmar con certificado
|
||||
home.certSign.desc=Firmar un PDF con un Certificado/Clave (PEM/P12)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
certSign.tags=authenticate,PEM,P12,official,encrypt
|
||||
certSign.tags=autentificar,PEM,P12,oficial,encriptar
|
||||
|
||||
home.pageLayout.title=Diseño de varias páginas
|
||||
home.pageLayout.desc=Unir varias páginas de un documento PDF en una sola página
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
pageLayout.tags=merge,composite,single-view,organize
|
||||
pageLayout.tags=unir,compuesto,vista única,organizar
|
||||
|
||||
home.scalePages.title=Escalar/ajustar tamaño de página
|
||||
home.scalePages.desc=Escalar/cambiar el tamaño de una pagina y/o su contenido
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
scalePages.tags=resize,modify,dimension,adapt
|
||||
scalePages.tags=cambiar tamaño,modificar,dimensionar,adaptar
|
||||
|
||||
home.pipeline.title=Pipeline (Advanced)
|
||||
home.pipeline.desc=Run multiple actions on PDFs by defining pipeline scripts
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
pipeline.tags=automate,sequence,scripted,batch-process
|
||||
home.pipeline.title=Secuencia (Avanzado)
|
||||
home.pipeline.desc=Ejecutar varias tareas a PDFs definiendo una secuencia de comandos
|
||||
pipeline.tags=automatizar,secuencia,con script,proceso por lotes
|
||||
|
||||
home.add-page-numbers.title=Add Page Numbers
|
||||
home.add-page-numbers.desc=Add Page numbers throughout a document in a set location
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
add-page-numbers.tags=paginate,label,organize,index
|
||||
home.add-page-numbers.title=Aádir números de página
|
||||
home.add-page-numbers.desc=Aádir números de página en un documento en una ubicación concreta
|
||||
add-page-numbers.tags=paginar,etiquetar,organizar,indexar
|
||||
|
||||
home.auto-rename.title=Auto Rename PDF File
|
||||
home.auto-rename.desc=Auto renames a PDF file based on its detected header
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
auto-rename.tags=auto-detect,header-based,organize,relabel
|
||||
home.auto-rename.title=Auto renombrar archivo PDF
|
||||
home.auto-rename.desc=Auto renormbrar un archivo PDF según su encabezamiento detecetado
|
||||
auto-rename.tags=auto-detectar,basado en el encabezamiento,organizar,re-etiquetar
|
||||
|
||||
home.adjust-contrast.title=Adjust Colors/Contrast
|
||||
home.adjust-contrast.desc=Adjust Contrast, Saturation and Brightness of a PDF
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
adjust-contrast.tags=color-correction,tune,modify,enhance
|
||||
home.adjust-contrast.title=Ajustar Color/Contraste
|
||||
home.adjust-contrast.desc=Ajustar Contraste, Saturación y Brillo de un PDF
|
||||
adjust-contrast.tags=corrección de color,sintonizar color,modificar,mejorar
|
||||
|
||||
home.crop.title=Crop PDF
|
||||
home.crop.desc=Crop a PDF to reduce its size (maintains text!)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
crop.tags=trim,shrink,edit,shape
|
||||
home.crop.title=Recortar PDF
|
||||
home.crop.desc=Recortar un PDF para reducir su tamaño (¡conservando el texto!)
|
||||
crop.tags=recortar,contraer,editar,forma
|
||||
|
||||
home.autoSplitPDF.title=Auto Split Pages
|
||||
home.autoSplitPDF.desc=Auto Split Scanned PDF with physical scanned page splitter QR Code
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
autoSplitPDF.tags=QR-based,separate,scan-segment,organize
|
||||
home.autoSplitPDF.title=Auto Dividir Páginas
|
||||
home.autoSplitPDF.desc=Auto Dividir PDF escaneado con código QR divsor de página escaneada físicamente
|
||||
autoSplitPDF.tags=Marcado por QR,separar,segmento de escaneo,organizar
|
||||
|
||||
home.sanitizePdf.title=Sanitize
|
||||
home.sanitizePdf.desc=Remove scripts and other elements from PDF files
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
sanitizePdf.tags=clean,secure,safe,remove-threats
|
||||
home.sanitizePdf.title=Desinfectar
|
||||
home.sanitizePdf.desc=Eliminar scripts y otros elementos de los archivos PDF
|
||||
sanitizePdf.tags=limpiar,asegurar,seguro,quitar amenazas
|
||||
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
home.URLToPDF.title=URL/Website To PDF
|
||||
home.URLToPDF.desc=Converts any http(s)URL to PDF
|
||||
URLToPDF.tags=web-capture,save-page,web-to-doc,archive
|
||||
home.URLToPDF.title=URL/Página web a PDF
|
||||
home.URLToPDF.desc=Convierte cualquier dirección http(s) a PDF
|
||||
URLToPDF.tags=captura web,guardar página,web-a-doc,archivo
|
||||
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
home.HTMLToPDF.title=HTML to PDF
|
||||
home.HTMLToPDF.desc=Converts any HTML file or zip to PDF
|
||||
HTMLToPDF.tags=markup,web-content,transformation,convert
|
||||
home.HTMLToPDF.title=HTML a PDF
|
||||
home.HTMLToPDF.desc=Convierte cualquier archivo HTML o ZIP a PDF
|
||||
HTMLToPDF.tags=margen,contenido web,transformación,convertir
|
||||
|
||||
|
||||
home.MarkdownToPDF.title=Markdown to PDF
|
||||
home.MarkdownToPDF.desc=Converts any Markdown file to PDF
|
||||
MarkdownToPDF.tags=markup,web-content,transformation,convert
|
||||
|
||||
|
||||
home.getPdfInfo.title=Get ALL Info on PDF
|
||||
home.getPdfInfo.desc=Grabs any and all information possible on PDFs
|
||||
getPdfInfo.tags=infomation,data,stats,statistics
|
||||
|
||||
|
||||
home.extractPage.title=Extract page(s)
|
||||
home.extractPage.desc=Extracts select pages from PDF
|
||||
extractPage.tags=extract
|
||||
|
||||
|
||||
home.PdfToSinglePage.title=PDF to Single Large Page
|
||||
home.PdfToSinglePage.desc=Merges all PDF pages into one large single page
|
||||
PdfToSinglePage.tags=single page
|
||||
|
||||
|
||||
home.showJS.title=Show Javascript
|
||||
home.showJS.desc=Searches and displays any JS injected into a PDF
|
||||
showJS.tags=JS
|
||||
|
||||
home.autoRedact.title=Auto Redact
|
||||
home.autoRedact.desc=Auto Redacts(Blacks out) text in a PDF based on input text
|
||||
showJS.tags=JS
|
||||
|
||||
###########################
|
||||
# #
|
||||
# WEB PAGES #
|
||||
# #
|
||||
###########################
|
||||
#login
|
||||
login.title=Sign in
|
||||
login.signin=Sign in
|
||||
login.rememberme=Remember me
|
||||
login.invalid=Invalid username or password.
|
||||
login.locked=Your account has been locked.
|
||||
login.signinTitle=Please sign in
|
||||
|
||||
|
||||
#auto-redact
|
||||
autoRedact.title=Auto Redact
|
||||
autoRedact.header=Auto Redact
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
autoRedact.colorLabel=Colour
|
||||
autoRedact.textsToRedactLabel=Text to Redact (line-separated)
|
||||
autoRedact.textsToRedactPlaceholder=e.g. \nConfidential \nTop-Secret
|
||||
autoRedact.useRegexLabel=Use Regex
|
||||
autoRedact.wholeWordSearchLabel=Whole Word Search
|
||||
autoRedact.customPaddingLabel=Custom Extra Padding
|
||||
autoRedact.convertPDFToImageLabel=Convert PDF to PDF-Image (Used to remove text behind the box)
|
||||
autoRedact.submitButton=Submit
|
||||
|
||||
|
||||
#showJS
|
||||
showJS.title=Show Javascript
|
||||
showJS.header=Show Javascript
|
||||
showJS.downloadJS=Download Javascript
|
||||
showJS.submit=Show
|
||||
|
||||
|
||||
#pdfToSinglePage
|
||||
pdfToSinglePage.title=PDF To Single Page
|
||||
pdfToSinglePage.header=PDF To Single Page
|
||||
pdfToSinglePage.submit=Convert To Single Page
|
||||
|
||||
|
||||
#pageExtracter
|
||||
pageExtracter.title=Extract Pages
|
||||
pageExtracter.header=Extract Pages
|
||||
pageExtracter.submit=Extract
|
||||
|
||||
|
||||
#getPdfInfo
|
||||
getPdfInfo.title=Get Info on PDF
|
||||
getPdfInfo.header=Get Info on PDF
|
||||
getPdfInfo.submit=Get Info
|
||||
getPdfInfo.downloadJson=Download JSON
|
||||
|
||||
|
||||
#markdown-to-pdf
|
||||
MarkdownToPDF.title=Markdown To PDF
|
||||
MarkdownToPDF.header=Markdown To PDF
|
||||
MarkdownToPDF.submit=Convert
|
||||
MarkdownToPDF.help=Work in progress
|
||||
MarkdownToPDF.credit=Uses WeasyPrint
|
||||
|
||||
|
||||
|
||||
#url-to-pdf
|
||||
URLToPDF.title=URL To PDF
|
||||
URLToPDF.header=URL To PDF
|
||||
URLToPDF.submit=Convert
|
||||
URLToPDF.credit=Uses WeasyPrint
|
||||
URLToPDF.title=URL a PDF
|
||||
URLToPDF.header=URL a PDF
|
||||
URLToPDF.submit=Convertir
|
||||
URLToPDF.credit=Utiliza WeasyPrint
|
||||
|
||||
|
||||
#html-to-pdf
|
||||
HTMLToPDF.title=HTML To PDF
|
||||
HTMLToPDF.header=HTML To PDF
|
||||
HTMLToPDF.help=Accepts HTML files and ZIPs containing html/css/images etc required
|
||||
HTMLToPDF.submit=Convert
|
||||
HTMLToPDF.credit=Uses WeasyPrint
|
||||
HTMLToPDF.title=HTML a PDF
|
||||
HTMLToPDF.header=HTML a PDF
|
||||
HTMLToPDF.help=Acepta archivos HTML y ZIPs conteniendo los html/css/imágenes etc requeridas
|
||||
HTMLToPDF.submit=Convertir
|
||||
HTMLToPDF.credit=Utiliza WeasyPrint
|
||||
|
||||
|
||||
#sanitizePDF
|
||||
sanitizePDF.title=Sanitize PDF
|
||||
sanitizePDF.header=Sanitize a PDF file
|
||||
sanitizePDF.selectText.1=Remove JavaScript actions
|
||||
sanitizePDF.selectText.2=Remove embedded files
|
||||
sanitizePDF.selectText.3=Remove metadata
|
||||
sanitizePDF.selectText.4=Remove links
|
||||
sanitizePDF.selectText.5=Remove fonts
|
||||
sanitizePDF.submit=Sanitize PDF
|
||||
sanitizePDF.title=Desinfectar archivo PDF
|
||||
sanitizePDF.header=Desinfectar un archivo PDF
|
||||
sanitizePDF.selectText.1=Eliminar acciones JavaScript
|
||||
sanitizePDF.selectText.2=Eliminar archivos incrustados
|
||||
sanitizePDF.selectText.3=Eliminar metadatos
|
||||
sanitizePDF.selectText.4=Eliminar enlaces
|
||||
sanitizePDF.selectText.5=Eliminar fuentes
|
||||
sanitizePDF.submit=Desinfectar PDF
|
||||
|
||||
|
||||
#addPageNumbers
|
||||
addPageNumbers.title=Add Page Numbers
|
||||
addPageNumbers.header=Add Page Numbers
|
||||
addPageNumbers.selectText.1=Select PDF file:
|
||||
addPageNumbers.selectText.2=Margin Size
|
||||
addPageNumbers.selectText.3=Position
|
||||
addPageNumbers.selectText.4=Starting Number
|
||||
addPageNumbers.selectText.5=Pages to Number
|
||||
addPageNumbers.selectText.6=Custom Text
|
||||
addPageNumbers.submit=Add Page Numbers
|
||||
addPageNumbers.title=Añadir Números de Página
|
||||
addPageNumbers.header=Añadir Números de Página
|
||||
addPageNumbers.selectText.1=Seleccionar archivo PDF:
|
||||
addPageNumbers.selectText.2=Tamaño del margen
|
||||
addPageNumbers.selectText.3=Posición
|
||||
addPageNumbers.selectText.4=Número de inicio
|
||||
addPageNumbers.selectText.5=Páginas a numerar
|
||||
addPageNumbers.selectText.6=Texto personalizado
|
||||
addPageNumbers.customTextDesc=Custom Text
|
||||
addPageNumbers.numberPagesDesc=Which pages to number, default 'all', also accepts 1-5 or 2,5,9 etc
|
||||
addPageNumbers.customNumberDesc=Defaults to {n}, also accepts 'Page {n} of {total}', 'Text-{n}', '{filename}-{n}
|
||||
addPageNumbers.submit=Añadir Números de Página
|
||||
|
||||
|
||||
#auto-rename
|
||||
auto-rename.title=Auto Rename
|
||||
auto-rename.header=Auto Rename PDF
|
||||
auto-rename.submit=Auto Rename
|
||||
auto-rename.title=Auto Renombrar
|
||||
auto-rename.header=Auto Renombrar PDF
|
||||
auto-rename.submit=Auto Renombrar
|
||||
|
||||
|
||||
#adjustContrast
|
||||
adjustContrast.title=Adjust Contrast
|
||||
adjustContrast.header=Adjust Contrast
|
||||
adjustContrast.contrast=Contrast:
|
||||
adjustContrast.brightness=Brightness:
|
||||
adjustContrast.saturation=Saturation:
|
||||
adjustContrast.download=Download
|
||||
adjustContrast.title=Ajustar Contraste
|
||||
adjustContrast.header=Ajustar Contraste
|
||||
adjustContrast.contrast=Contraste:
|
||||
adjustContrast.brightness=Brillo:
|
||||
adjustContrast.saturation=Saturación:
|
||||
adjustContrast.download=Descargar
|
||||
|
||||
|
||||
#crop
|
||||
crop.title=Crop
|
||||
crop.header=Crop Image
|
||||
crop.submit=Submit
|
||||
crop.title=Recortar
|
||||
crop.header=Recortar Imagen
|
||||
crop.submit=Entregar
|
||||
|
||||
|
||||
#autoSplitPDF
|
||||
autoSplitPDF.title=Auto Split PDF
|
||||
autoSplitPDF.header=Auto Split PDF
|
||||
autoSplitPDF.description=Print, Insert, Scan, upload, and let us auto-separate your documents. No manual work sorting needed.
|
||||
autoSplitPDF.selectText.1=Print out some divider sheets from below (Black and white is fine).
|
||||
autoSplitPDF.selectText.2=Scan all your documents at once by inserting the divider sheet between them.
|
||||
autoSplitPDF.selectText.3=Upload the single large scanned PDF file and let Stirling PDF handle the rest.
|
||||
autoSplitPDF.selectText.4=Divider pages are automatically detected and removed, guaranteeing a neat final document.
|
||||
autoSplitPDF.formPrompt=Submit PDF containing Stirling-PDF Page dividers:
|
||||
autoSplitPDF.duplexMode=Duplex Mode (Front and back scanning)
|
||||
autoSplitPDF.dividerDownload1=Download 'Auto Splitter Divider (minimal).pdf'
|
||||
autoSplitPDF.dividerDownload2=Download 'Auto Splitter Divider (with instructions).pdf'
|
||||
autoSplitPDF.submit=Submit
|
||||
autoSplitPDF.title=Auto Dividir PDF
|
||||
autoSplitPDF.header=Auto Dividir PDF
|
||||
autoSplitPDF.description=Imprimir, Insertar, Escanear, cargar, y déjenos sepsrar automáticamente sus documentos. No se necesita clasificación manual.
|
||||
autoSplitPDF.selectText.1=Imprimir algunas hojas divisorias desde la parte inferior (Blanco y negro está bien).
|
||||
autoSplitPDF.selectText.2=Escanee todos sus documentos a la vez insertando la hoja divisoria entre ellos.
|
||||
autoSplitPDF.selectText.3=Cargue un único archivo PDF escaneado de gran tamaño y deje que Stirling PDF se encargue del resto.
|
||||
autoSplitPDF.selectText.4=Las páginas divisorias son automáticamente detectadas y eliminadas, garantizando un buen documento final.
|
||||
autoSplitPDF.formPrompt=Entregar PDF conteniendo divisores de página de Stirling-PDF:
|
||||
autoSplitPDF.duplexMode=Modo Dúplex (Escaneado de ambas caras)
|
||||
autoSplitPDF.dividerDownload1=Descargar 'Auto Splitter Divider (mínima).pdf'
|
||||
autoSplitPDF.dividerDownload2=Descargar 'Auto Splitter Divider (con instrucciones).pdf'
|
||||
autoSplitPDF.submit=Entregar
|
||||
|
||||
|
||||
#pipeline
|
||||
@@ -456,13 +479,13 @@ scalePages.submit=Entregar
|
||||
|
||||
#certSign
|
||||
certSign.title=Firma de certificado
|
||||
certSign.header=Firmar un PDF con su certificado (Trabajo en progreso)
|
||||
certSign.header=Firmar un PDF con su certificado (en desarrollo)
|
||||
certSign.selectPDF=Seleccione un archivo PDF para firmar:
|
||||
certSign.selectKey=Seleccione su archivo de clave privada (formato PKCS#8, podría ser .pem o .der):
|
||||
certSign.selectCert=Seleccione su archivo de certificado (formato X.509, podría ser .pem o .der):
|
||||
certSign.selectP12=Seleccione su archivo de almacén de claves PKCS#12 (.p12 o .pfx) (Opcional, si se proporciona, debe contener su clave privada y certificado):
|
||||
certSign.certType=Tipo de certificado
|
||||
certSign.password=Ingrese su almacén de claves o contraseña de clave privada (si corresponde):
|
||||
certSign.password=Introduzca su almacén de claves o contraseña de clave privada (si corresponde):
|
||||
certSign.showSig=Mostrar firma
|
||||
certSign.reason=Razón
|
||||
certSign.location=Ubicación
|
||||
@@ -581,6 +604,8 @@ addImage.submit=Añadir imagen
|
||||
#merge
|
||||
merge.title=Unir
|
||||
merge.header=Unir múltiples PDFs (2+)
|
||||
merge.sortByName=Sort by name
|
||||
merge.sortByDate=Sort by date
|
||||
merge.submit=Unir
|
||||
|
||||
|
||||
@@ -681,17 +706,11 @@ watermark.selectText.4=Rotación (0-360):
|
||||
watermark.selectText.5=Ancho (Espacio entre cada marca de agua horizontalmente):
|
||||
watermark.selectText.6=Alto (Espacio entre cada marca de agua verticalmente):
|
||||
watermark.selectText.7=Opacidad (0% - 100%):
|
||||
watermark.selectText.8=Watermark Type:
|
||||
watermark.selectText.9=Watermark Image:
|
||||
watermark.submit=Añadir marca de agua
|
||||
|
||||
|
||||
#remove-watermark
|
||||
remove-watermark.title=Eliminar marca de agua
|
||||
remove-watermark.header=Eliminar marca de agua
|
||||
remove-watermark.selectText.1=Seleccionar PDF para eliminar la marca de agua:
|
||||
remove-watermark.selectText.2=Texto de la marca de agua:
|
||||
remove-watermark.submit=Eliminar marca de agua
|
||||
|
||||
|
||||
#Change permissions
|
||||
permissions.title=Cambiar permisos
|
||||
permissions.header=Cambiar permisos
|
||||
|
||||
@@ -31,6 +31,23 @@ sizes.medium=Medium
|
||||
sizes.large=Large
|
||||
sizes.x-large=X-Large
|
||||
error.pdfPassword=PDF dokumentua pasahitzarekin babestuta dago eta pasahitza ez da sartu edo akastuna da
|
||||
delete=Delete
|
||||
username=Username
|
||||
password=Password
|
||||
welcome=Welcome
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
property=Property
|
||||
black=Black
|
||||
white=White
|
||||
red=Red
|
||||
green=Green
|
||||
blue=Blue
|
||||
custom=Custom...
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#############
|
||||
@@ -54,6 +71,41 @@ settings.downloadOption.1=Ireki leiho berean
|
||||
settings.downloadOption.2=Ireki leiho berrian
|
||||
settings.downloadOption.3=Deskargatu fitxategia
|
||||
settings.zipThreshold=ZIP fitxategiak deskargatutako fitxategi kopurua gainditzen denean
|
||||
settings.signOut=Sign Out
|
||||
settings.accountSettings=Account Settings
|
||||
|
||||
account.title=Account Settings
|
||||
account.accountSettings=Account Settings
|
||||
account.adminSettings=Admin Settings - View and Add Users
|
||||
account.userControlSettings=User Control Settings
|
||||
account.changeUsername=Change Username
|
||||
account.changeUsername=Change Username
|
||||
account.password=Confirmation Password
|
||||
account.oldPassword=Old password
|
||||
account.newPassword=New Password
|
||||
account.changePassword=Change Password
|
||||
account.confirmNewPassword=Confirm New Password
|
||||
account.signOut=Sign Out
|
||||
account.yourApiKey=Your API Key
|
||||
account.syncTitle=Sync browser settings with Account
|
||||
account.settingsCompare=Settings Comparison:
|
||||
account.property=Property
|
||||
account.webBrowserSettings=Web Browser Setting
|
||||
account.syncToBrowser=Sync Account -> Browser
|
||||
account.syncToAccount=Sync Account <- Browser
|
||||
|
||||
|
||||
adminUserSettings.title=User Control Settings
|
||||
adminUserSettings.header=Admin User Control Settings
|
||||
adminUserSettings.admin=Admin
|
||||
adminUserSettings.user=User
|
||||
adminUserSettings.addUser=Add New User
|
||||
adminUserSettings.roles=Roles
|
||||
adminUserSettings.role=Role
|
||||
adminUserSettings.actions=Actions
|
||||
adminUserSettings.apiUser=Limited API User
|
||||
adminUserSettings.webOnlyUser=Web Only User
|
||||
adminUserSettings.submit=Save User
|
||||
|
||||
#############
|
||||
# HOME-PAGE #
|
||||
@@ -71,296 +123,264 @@ merge.tags=merge,Page operations,Back end,server side
|
||||
|
||||
home.split.title=Zatitu
|
||||
home.split.desc=Zatitu PDFak zenbait dokumentutan
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
split.tags=Page operations,divide,Multi Page,cut,server side
|
||||
split.tags=Page operations,divide,Multi Page,cut,server side
|
||||
|
||||
home.rotate.title=Biratu
|
||||
home.rotate.desc=Biratu PDFak modu errazean
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
rotate.tags=server side
|
||||
|
||||
|
||||
home.imageToPdf.title=Irudia PDF bihurtu
|
||||
home.imageToPdf.desc=Irudi bat(PNG, JPEG, GIF)PDF bihurtu
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
imageToPdf.tags=conversion,img,jpg,picture,photo
|
||||
|
||||
home.pdfToImage.title=PDFa irudi bihurtu
|
||||
home.pdfToImage.desc=PDF bat irudi (PNG, JPEG, GIF) bihurtu
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
pdfToImage.tags=conversion,img,jpg,picture,photo
|
||||
|
||||
home.pdfOrganiser.title=Antolatzailea
|
||||
home.pdfOrganiser.desc=Ezabatu/Berrantolatu orrialdeak edozein ordenatan
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
pdfOrganiser.tags=duplex,even,odd,sort,move
|
||||
|
||||
|
||||
home.addImage.title=Gehitu irudia PDFari
|
||||
home.addImage.desc=Gehitu irudi bat PDFan ezarritako kokaleku batean (lanean)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
addImage.tags=img,jpg,picture,photo
|
||||
|
||||
home.watermark.title=Gehitu ur-marka
|
||||
home.watermark.desc=Gehitu aurrez zehaztutako ur-marka bat PFD dokumentuari
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
watermark.tags=Text,repeating,label,own,copyright,trademark,img,jpg,picture,photo
|
||||
|
||||
home.permissions.title=Aldatu baimenak
|
||||
home.permissions.desc=Aldatu PDF dokumentuaren baimenak
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
permissions.tags=read,write,edit,print
|
||||
|
||||
|
||||
home.removePages.title=Ezabatu
|
||||
home.removePages.desc=Ezabatu nahi ez dituzun orrialdeak PDF dokumentutik
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
removePages.tags=Remove pages,delete pages
|
||||
|
||||
home.addPassword.title=Gehitu pasahitza
|
||||
home.addPassword.desc=Enkriptatu PDF dokumentua pasahitz batekin
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
addPassword.tags=secure,security
|
||||
|
||||
home.removePassword.title=Ezabatu pasahitza
|
||||
home.removePassword.desc=Ezabatu pasahitza PDF dokumentutik
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
removePassword.tags=secure,Decrypt,security,unpassword,delete password
|
||||
|
||||
home.compressPdfs.title=Konprimatu
|
||||
home.compressPdfs.desc=Konprimatu PDFak fitxategiaren tamaina murrizteko
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
compressPdfs.tags=squish,small,tiny
|
||||
|
||||
|
||||
home.changeMetadata.title=Aldatu metadatuak
|
||||
home.changeMetadata.desc=Aldatu/Ezabatu/Gehitu metadatuak PDF dokumentuari
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
changeMetadata.tags==Title,author,date,creation,time,publisher,producer,stats
|
||||
|
||||
home.fileToPDF.title=Fitxategia PDF bihurtu
|
||||
home.fileToPDF.desc=PDF bihurtu ia edozein fitxategi (DOCX, PNG, XLS, PPT, TXT eta gehiago)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
fileToPDF.tags=transformation,format,document,picture,slide,text,conversion,office,docs,word,excel,powerpoint
|
||||
|
||||
home.ocr.title=OCR exekutatu PDFan eta/edo garbiketa-eskaneatzeak
|
||||
home.ocr.desc=Garbiketa-eskaneatzeak eta irudi-testuak detektatu PDF baten barruan eta berriz ere gehitu testu gisa
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
ocr.tags=recognition,text,image,scan,read,identify,detection,editable
|
||||
|
||||
|
||||
home.extractImages.title=Atera irudiak
|
||||
home.extractImages.desc=Atera irudi guztiak PDF batetik eta ZIPen gorde
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
extractImages.tags=picture,photo,save,archive,zip,capture,grab
|
||||
|
||||
home.pdfToPDFA.title=PDFa PDF/A bihurtu
|
||||
home.pdfToPDFA.desc=PDFa PDF/A bihurtu luzaro biltegiratzeko
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation
|
||||
|
||||
home.PDFToWord.title=PDFa Word Bihurtu
|
||||
home.PDFToWord.desc=PDF formatuak Word bihurtu (DOC, DOCX y ODT)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
PDFToWord.tags=doc,docx,odt,word,transformation,format,conversion,office,microsoft,docfile
|
||||
|
||||
home.PDFToPresentation.title=PDFa aurkezpen bihurtu
|
||||
home.PDFToPresentation.desc=PDFa aurkezpen formatu bihurtu (PPT, PPTX y ODP)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
PDFToPresentation.tags=slides,show,office,microsoft
|
||||
|
||||
home.PDFToText.title=PDFa TXT edo RTF bihurtu
|
||||
home.PDFToText.desc=PDFa TXT edo RTF formatu bihurtu
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
PDFToText.tags=richformat,richtextformat,rich text format
|
||||
|
||||
home.PDFToHTML.title=PDFa HTML bihurtu
|
||||
home.PDFToHTML.desc=PDFa HTML formatu bihurtu
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
PDFToHTML.tags=web content,browser friendly
|
||||
|
||||
|
||||
home.PDFToXML.title=PDFa XML bihurtu
|
||||
home.PDFToXML.desc=PDFa XML formatu bihurtu
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
PDFToXML.tags=data-extraction,structured-content,interop,transformation,convert
|
||||
|
||||
home.ScannerImageSplit.title=Detektatu/Zatitu argazki eskaneatuak
|
||||
home.ScannerImageSplit.desc=Hainbat argazki zatitu argazki/PDF baten barruan
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
ScannerImageSplit.tags=separate,auto-detect,scans,multi-photo,organize
|
||||
|
||||
home.sign.title=Sinatu
|
||||
home.sign.desc=Gehitu sinadura PDFari marrazki, testu edo irudi bidez
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
sign.tags=authorize,initials,drawn-signature,text-sign,image-signature
|
||||
|
||||
home.flatten.title=Lautu
|
||||
home.flatten.desc=PDF batetik elementu eta inprimaki interaktibo guztiak ezabatu
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
flatten.tags=static,deactivate,non-interactive,streamline
|
||||
|
||||
home.repair.title=Konpondu
|
||||
home.repair.desc=Saiatu PDF hondatu/kaltetu bat konpontzen
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
repair.tags=fix,restore,correction,recover
|
||||
|
||||
home.removeBlanks.title=Ezabatu orrialde zuriak
|
||||
home.removeBlanks.desc=Detektatu orrialde zuriak eta dokumentutik ezabatu
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
removeBlanks.tags=cleanup,streamline,non-content,organize
|
||||
|
||||
home.compare.title=Konparatu
|
||||
home.compare.desc=Konparatu eta erakutsi 2 PDF dokumenturen aldeak
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
compare.tags=differentiate,contrast,changes,analysis
|
||||
|
||||
home.certSign.title=Sinatu ziurtagiriarekin
|
||||
home.certSign.desc=Sinatu PDF bat Ziurtagiri/Gako batekin (PEM/P12)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
certSign.tags=authenticate,PEM,P12,official,encrypt
|
||||
|
||||
home.pageLayout.title=Zenbait orrialderen diseinua
|
||||
home.pageLayout.desc=Elkartu orri bakar batean PDF dokumentu baten zenbait orrialde
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
pageLayout.tags=merge,composite,single-view,organize
|
||||
|
||||
home.scalePages.title=Eskalatu/Doitu orrialdearen tamaina
|
||||
home.scalePages.desc=Eskalatu/Aldatu orrialde baten tamaina eta/edo edukia
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
scalePages.tags=resize,modify,dimension,adapt
|
||||
|
||||
home.pipeline.title=Pipeline (Advanced)
|
||||
home.pipeline.desc=Run multiple actions on PDFs by defining pipeline scripts
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
pipeline.tags=automate,sequence,scripted,batch-process
|
||||
|
||||
home.add-page-numbers.title=Add Page Numbers
|
||||
home.add-page-numbers.desc=Add Page numbers throughout a document in a set location
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
add-page-numbers.tags=paginate,label,organize,index
|
||||
|
||||
home.auto-rename.title=Auto Rename PDF File
|
||||
home.auto-rename.desc=Auto renames a PDF file based on its detected header
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
auto-rename.tags=auto-detect,header-based,organize,relabel
|
||||
|
||||
home.adjust-contrast.title=Adjust Colors/Contrast
|
||||
home.adjust-contrast.desc=Adjust Contrast, Saturation and Brightness of a PDF
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
adjust-contrast.tags=color-correction,tune,modify,enhance
|
||||
|
||||
home.crop.title=Crop PDF
|
||||
home.crop.desc=Crop a PDF to reduce its size (maintains text!)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
crop.tags=trim,shrink,edit,shape
|
||||
|
||||
home.autoSplitPDF.title=Auto Split Pages
|
||||
home.autoSplitPDF.desc=Auto Split Scanned PDF with physical scanned page splitter QR Code
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
autoSplitPDF.tags=QR-based,separate,scan-segment,organize
|
||||
|
||||
home.sanitizePdf.title=Sanitize
|
||||
home.sanitizePdf.desc=Remove scripts and other elements from PDF files
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
sanitizePdf.tags=clean,secure,safe,remove-threats
|
||||
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
home.URLToPDF.title=URL/Website To PDF
|
||||
home.URLToPDF.desc=Converts any http(s)URL to PDF
|
||||
URLToPDF.tags=web-capture,save-page,web-to-doc,archive
|
||||
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
home.HTMLToPDF.title=HTML to PDF
|
||||
home.HTMLToPDF.desc=Converts any HTML file or zip to PDF
|
||||
HTMLToPDF.tags=markup,web-content,transformation,convert
|
||||
|
||||
|
||||
home.MarkdownToPDF.title=Markdown to PDF
|
||||
home.MarkdownToPDF.desc=Converts any Markdown file to PDF
|
||||
MarkdownToPDF.tags=markup,web-content,transformation,convert
|
||||
|
||||
|
||||
home.getPdfInfo.title=Get ALL Info on PDF
|
||||
home.getPdfInfo.desc=Grabs any and all information possible on PDFs
|
||||
getPdfInfo.tags=infomation,data,stats,statistics
|
||||
|
||||
|
||||
home.extractPage.title=Extract page(s)
|
||||
home.extractPage.desc=Extracts select pages from PDF
|
||||
extractPage.tags=extract
|
||||
|
||||
|
||||
home.PdfToSinglePage.title=PDF to Single Large Page
|
||||
home.PdfToSinglePage.desc=Merges all PDF pages into one large single page
|
||||
PdfToSinglePage.tags=single page
|
||||
|
||||
|
||||
home.showJS.title=Show Javascript
|
||||
home.showJS.desc=Searches and displays any JS injected into a PDF
|
||||
showJS.tags=JS
|
||||
|
||||
home.autoRedact.title=Auto Redact
|
||||
home.autoRedact.desc=Auto Redacts(Blacks out) text in a PDF based on input text
|
||||
showJS.tags=JS
|
||||
|
||||
###########################
|
||||
# #
|
||||
# WEB PAGES #
|
||||
# #
|
||||
###########################
|
||||
#login
|
||||
login.title=Sign in
|
||||
login.signin=Sign in
|
||||
login.rememberme=Remember me
|
||||
login.invalid=Invalid username or password.
|
||||
login.locked=Your account has been locked.
|
||||
login.signinTitle=Please sign in
|
||||
|
||||
|
||||
#auto-redact
|
||||
autoRedact.title=Auto Redact
|
||||
autoRedact.header=Auto Redact
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
autoRedact.colorLabel=Colour
|
||||
autoRedact.textsToRedactLabel=Text to Redact (line-separated)
|
||||
autoRedact.textsToRedactPlaceholder=e.g. \nConfidential \nTop-Secret
|
||||
autoRedact.useRegexLabel=Use Regex
|
||||
autoRedact.wholeWordSearchLabel=Whole Word Search
|
||||
autoRedact.customPaddingLabel=Custom Extra Padding
|
||||
autoRedact.convertPDFToImageLabel=Convert PDF to PDF-Image (Used to remove text behind the box)
|
||||
autoRedact.submitButton=Submit
|
||||
|
||||
|
||||
#showJS
|
||||
showJS.title=Show Javascript
|
||||
showJS.header=Show Javascript
|
||||
showJS.downloadJS=Download Javascript
|
||||
showJS.submit=Show
|
||||
|
||||
|
||||
#pdfToSinglePage
|
||||
pdfToSinglePage.title=PDF To Single Page
|
||||
pdfToSinglePage.header=PDF To Single Page
|
||||
pdfToSinglePage.submit=Convert To Single Page
|
||||
|
||||
|
||||
#pageExtracter
|
||||
pageExtracter.title=Extract Pages
|
||||
pageExtracter.header=Extract Pages
|
||||
pageExtracter.submit=Extract
|
||||
|
||||
|
||||
#getPdfInfo
|
||||
getPdfInfo.title=Get Info on PDF
|
||||
getPdfInfo.header=Get Info on PDF
|
||||
getPdfInfo.submit=Get Info
|
||||
getPdfInfo.downloadJson=Download JSON
|
||||
|
||||
|
||||
#markdown-to-pdf
|
||||
MarkdownToPDF.title=Markdown To PDF
|
||||
MarkdownToPDF.header=Markdown To PDF
|
||||
MarkdownToPDF.submit=Convert
|
||||
MarkdownToPDF.help=Work in progress
|
||||
MarkdownToPDF.credit=Uses WeasyPrint
|
||||
|
||||
|
||||
|
||||
#url-to-pdf
|
||||
URLToPDF.title=URL To PDF
|
||||
URLToPDF.header=URL To PDF
|
||||
@@ -396,6 +416,9 @@ addPageNumbers.selectText.3=Position
|
||||
addPageNumbers.selectText.4=Starting Number
|
||||
addPageNumbers.selectText.5=Pages to Number
|
||||
addPageNumbers.selectText.6=Custom Text
|
||||
addPageNumbers.customTextDesc=Custom Text
|
||||
addPageNumbers.numberPagesDesc=Which pages to number, default 'all', also accepts 1-5 or 2,5,9 etc
|
||||
addPageNumbers.customNumberDesc=Defaults to {n}, also accepts 'Page {n} of {total}', 'Text-{n}', '{filename}-{n}
|
||||
addPageNumbers.submit=Add Page Numbers
|
||||
|
||||
|
||||
@@ -581,6 +604,8 @@ addImage.submit=Gehitu irudia
|
||||
#merge
|
||||
merge.title=Elkartu
|
||||
merge.header=Elkartu zenbait PDF (2+)
|
||||
merge.sortByName=Sort by name
|
||||
merge.sortByDate=Sort by date
|
||||
merge.submit=Elkartu
|
||||
|
||||
|
||||
@@ -681,17 +706,11 @@ watermark.selectText.4=Errotazioa (0-360):
|
||||
watermark.selectText.5=Zabalera (ur-marka bakoitzaren arteko espazioa horizontalean):
|
||||
watermark.selectText.6=Altuera (ur-marka bakoitzaren arteko espazioa bertikalean):
|
||||
watermark.selectText.7=Opakutasuna (0% - 100%):
|
||||
watermark.selectText.8=Watermark Type:
|
||||
watermark.selectText.9=Watermark Image:
|
||||
watermark.submit=Gehitu ur-marka
|
||||
|
||||
|
||||
#remove-watermark
|
||||
remove-watermark.title=Ezabatu ur-marka
|
||||
remove-watermark.header=Ezabatu ur-marka
|
||||
remove-watermark.selectText.1=Hautatu PDFa ur-marka ezabatzeko:
|
||||
remove-watermark.selectText.2=Ur-markaren testua:
|
||||
remove-watermark.submit=Ezabatu ur-marka
|
||||
|
||||
|
||||
#Change permissions
|
||||
permissions.title=Aldatu baimenak
|
||||
permissions.header=Aldatu baimenak
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -31,6 +31,23 @@ sizes.medium=Medium
|
||||
sizes.large=Large
|
||||
sizes.x-large=X-Large
|
||||
error.pdfPassword=The PDF Document is passworded and either the password was not provided or was incorrect
|
||||
delete=Delete
|
||||
username=Username
|
||||
password=Password
|
||||
welcome=Welcome
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
property=Property
|
||||
black=Black
|
||||
white=White
|
||||
red=Red
|
||||
green=Green
|
||||
blue=Blue
|
||||
custom=Custom...
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#############
|
||||
@@ -54,6 +71,41 @@ settings.downloadOption.1=Apri in questa finestra
|
||||
settings.downloadOption.2=Apri in una nuova finestra
|
||||
settings.downloadOption.3=Scarica file
|
||||
settings.zipThreshold=Comprimi file in .zip quando il numero di download supera
|
||||
settings.signOut=Sign Out
|
||||
settings.accountSettings=Account Settings
|
||||
|
||||
account.title=Account Settings
|
||||
account.accountSettings=Account Settings
|
||||
account.adminSettings=Admin Settings - View and Add Users
|
||||
account.userControlSettings=User Control Settings
|
||||
account.changeUsername=Change Username
|
||||
account.changeUsername=Change Username
|
||||
account.password=Confirmation Password
|
||||
account.oldPassword=Old password
|
||||
account.newPassword=New Password
|
||||
account.changePassword=Change Password
|
||||
account.confirmNewPassword=Confirm New Password
|
||||
account.signOut=Sign Out
|
||||
account.yourApiKey=Your API Key
|
||||
account.syncTitle=Sync browser settings with Account
|
||||
account.settingsCompare=Settings Comparison:
|
||||
account.property=Property
|
||||
account.webBrowserSettings=Web Browser Setting
|
||||
account.syncToBrowser=Sync Account -> Browser
|
||||
account.syncToAccount=Sync Account <- Browser
|
||||
|
||||
|
||||
adminUserSettings.title=User Control Settings
|
||||
adminUserSettings.header=Admin User Control Settings
|
||||
adminUserSettings.admin=Admin
|
||||
adminUserSettings.user=User
|
||||
adminUserSettings.addUser=Add New User
|
||||
adminUserSettings.roles=Roles
|
||||
adminUserSettings.role=Role
|
||||
adminUserSettings.actions=Actions
|
||||
adminUserSettings.apiUser=Limited API User
|
||||
adminUserSettings.webOnlyUser=Web Only User
|
||||
adminUserSettings.submit=Save User
|
||||
|
||||
#############
|
||||
# HOME-PAGE #
|
||||
@@ -71,296 +123,264 @@ merge.tags=merge,Page operations,Back end,server side
|
||||
|
||||
home.split.title=Dividi
|
||||
home.split.desc=Dividi un singolo PDF in più documenti.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
split.tags=Page operations,divide,Multi Page,cut,server side
|
||||
split.tags=Page operations,divide,Multi Page,cut,server side
|
||||
|
||||
home.rotate.title=Ruota
|
||||
home.rotate.desc=Ruota un PDF.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
rotate.tags=server side
|
||||
|
||||
|
||||
home.imageToPdf.title=Da immagine a PDF
|
||||
home.imageToPdf.desc=Converti un'immagine (PNG, JPEG, GIF) in PDF.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
imageToPdf.tags=conversion,img,jpg,picture,photo
|
||||
|
||||
home.pdfToImage.title=Da PDF a immagine
|
||||
home.pdfToImage.desc=Converti un PDF in un'immagine. (PNG, JPEG, GIF)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
pdfToImage.tags=conversion,img,jpg,picture,photo
|
||||
|
||||
home.pdfOrganiser.title=Organizza
|
||||
home.pdfOrganiser.desc=Rimuovi/Riordina le pagine in qualsiasi ordine.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
pdfOrganiser.tags=duplex,even,odd,sort,move
|
||||
|
||||
|
||||
home.addImage.title=Aggiungi Immagine
|
||||
home.addImage.desc=Aggiungi un'immagine in un punto specifico del PDF (Work in progress)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
addImage.tags=img,jpg,picture,photo
|
||||
|
||||
home.watermark.title=Aggiungi Filigrana
|
||||
home.watermark.desc=Aggiungi una filigrana al tuo PDF.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
watermark.tags=Text,repeating,label,own,copyright,trademark,img,jpg,picture,photo
|
||||
|
||||
home.permissions.title=Cambia Permessi
|
||||
home.permissions.desc=Cambia i permessi del tuo PDF.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
permissions.tags=read,write,edit,print
|
||||
|
||||
|
||||
home.removePages.title=Rimuovi
|
||||
home.removePages.desc=Elimina alcune pagine dal PDF.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
removePages.tags=Remove pages,delete pages
|
||||
|
||||
home.addPassword.title=Aggiungi Password
|
||||
home.addPassword.desc=Crittografa il tuo PDF con una password.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
addPassword.tags=secure,security
|
||||
|
||||
home.removePassword.title=Rimuovi Password
|
||||
home.removePassword.desc=Rimuovi la password dal tuo PDF.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
removePassword.tags=secure,Decrypt,security,unpassword,delete password
|
||||
|
||||
home.compressPdfs.title=Comprimi
|
||||
home.compressPdfs.desc=Comprimi PDF per ridurne le dimensioni.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
compressPdfs.tags=squish,small,tiny
|
||||
|
||||
|
||||
home.changeMetadata.title=Modifica Proprietà
|
||||
home.changeMetadata.desc=Modifica/Aggiungi/Rimuovi le proprietà di un documento PDF.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
changeMetadata.tags==Title,author,date,creation,time,publisher,producer,stats
|
||||
|
||||
home.fileToPDF.title=Converti file in PDF
|
||||
home.fileToPDF.desc=Converti quasi ogni file in PDF (DOCX, PNG, XLS, PPT, TXT e altro)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
fileToPDF.tags=transformation,format,document,picture,slide,text,conversion,office,docs,word,excel,powerpoint
|
||||
|
||||
home.ocr.title=OCR / Pulisci scansioni
|
||||
home.ocr.desc=Pulisci scansioni ed estrai testo da immagini, convertendo le immagini in testo puro.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
ocr.tags=recognition,text,image,scan,read,identify,detection,editable
|
||||
|
||||
|
||||
home.extractImages.title=Estrai immagini
|
||||
home.extractImages.desc=Estrai tutte le immagini da un PDF e salvale come zip.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
extractImages.tags=picture,photo,save,archive,zip,capture,grab
|
||||
|
||||
home.pdfToPDFA.title=Converti in PDF/A
|
||||
home.pdfToPDFA.desc=Converti un PDF nel formato PDF/A per archiviazione a lungo termine.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation
|
||||
|
||||
home.PDFToWord.title=Da PDF a Word
|
||||
home.PDFToWord.desc=Converti un PDF nei formati Word (DOC, DOCX e ODT)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
PDFToWord.tags=doc,docx,odt,word,transformation,format,conversion,office,microsoft,docfile
|
||||
|
||||
home.PDFToPresentation.title=Da PDF a presentazioni
|
||||
home.PDFToPresentation.desc=Converti un PDF in presentazioni (PPT, PPTX and ODP)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
PDFToPresentation.tags=slides,show,office,microsoft
|
||||
|
||||
home.PDFToText.title=Da PDF a testo/RTF
|
||||
home.PDFToText.desc=Converti un PDF in testo o RTF.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
PDFToText.tags=richformat,richtextformat,rich text format
|
||||
|
||||
home.PDFToHTML.title=Da PDF ad HTML
|
||||
home.PDFToHTML.desc=Converti un PDF in HTML.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
PDFToHTML.tags=web content,browser friendly
|
||||
|
||||
|
||||
home.PDFToXML.title=Da PDF a XML
|
||||
home.PDFToXML.desc=Converti un PDF in XML.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
PDFToXML.tags=data-extraction,structured-content,interop,transformation,convert
|
||||
|
||||
home.ScannerImageSplit.title=Trova/Dividi foto scansionate
|
||||
home.ScannerImageSplit.desc=Estrai più foto da una singola foto o PDF.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
ScannerImageSplit.tags=separate,auto-detect,scans,multi-photo,organize
|
||||
|
||||
home.sign.title=Firma
|
||||
home.sign.desc=Aggiungi una firma al PDF da disegno, testo o immagine.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
sign.tags=authorize,initials,drawn-signature,text-sign,image-signature
|
||||
|
||||
home.flatten.title=Appiattisci
|
||||
home.flatten.desc=Rimuovi tutti gli elementi interattivi e moduli da un PDF.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
flatten.tags=static,deactivate,non-interactive,streamline
|
||||
|
||||
home.repair.title=Ripara
|
||||
home.repair.desc=Prova a riparare un PDF corrotto.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
repair.tags=fix,restore,correction,recover
|
||||
|
||||
home.removeBlanks.title=Rimuovi pagine vuote
|
||||
home.removeBlanks.desc=Trova e rimuovi pagine vuote da un PDF.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
removeBlanks.tags=cleanup,streamline,non-content,organize
|
||||
|
||||
home.compare.title=Compara
|
||||
home.compare.desc=Vedi e compara le differenze tra due PDF.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
compare.tags=differentiate,contrast,changes,analysis
|
||||
|
||||
home.certSign.title=Sign with Certificate
|
||||
home.certSign.desc=Signs a PDF with a Certificate/Key (PEM/P12)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
certSign.tags=authenticate,PEM,P12,official,encrypt
|
||||
|
||||
home.pageLayout.title=Multi-Page Layout
|
||||
home.pageLayout.desc=Merge multiple pages of a PDF document into a single page
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
pageLayout.tags=merge,composite,single-view,organize
|
||||
|
||||
home.scalePages.title=Adjust page size/scale
|
||||
home.scalePages.desc=Change the size/scale of page and/or its contents.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
scalePages.tags=resize,modify,dimension,adapt
|
||||
|
||||
home.pipeline.title=Pipeline (Advanced)
|
||||
home.pipeline.desc=Run multiple actions on PDFs by defining pipeline scripts
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
pipeline.tags=automate,sequence,scripted,batch-process
|
||||
|
||||
home.add-page-numbers.title=Add Page Numbers
|
||||
home.add-page-numbers.desc=Add Page numbers throughout a document in a set location
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
add-page-numbers.tags=paginate,label,organize,index
|
||||
|
||||
home.auto-rename.title=Auto Rename PDF File
|
||||
home.auto-rename.desc=Auto renames a PDF file based on its detected header
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
auto-rename.tags=auto-detect,header-based,organize,relabel
|
||||
|
||||
home.adjust-contrast.title=Adjust Colors/Contrast
|
||||
home.adjust-contrast.desc=Adjust Contrast, Saturation and Brightness of a PDF
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
adjust-contrast.tags=color-correction,tune,modify,enhance
|
||||
|
||||
home.crop.title=Crop PDF
|
||||
home.crop.desc=Crop a PDF to reduce its size (maintains text!)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
crop.tags=trim,shrink,edit,shape
|
||||
|
||||
home.autoSplitPDF.title=Auto Split Pages
|
||||
home.autoSplitPDF.desc=Auto Split Scanned PDF with physical scanned page splitter QR Code
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
autoSplitPDF.tags=QR-based,separate,scan-segment,organize
|
||||
|
||||
home.sanitizePdf.title=Sanitize
|
||||
home.sanitizePdf.desc=Remove scripts and other elements from PDF files
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
sanitizePdf.tags=clean,secure,safe,remove-threats
|
||||
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
home.URLToPDF.title=URL/Website To PDF
|
||||
home.URLToPDF.desc=Converts any http(s)URL to PDF
|
||||
URLToPDF.tags=web-capture,save-page,web-to-doc,archive
|
||||
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
home.HTMLToPDF.title=HTML to PDF
|
||||
home.HTMLToPDF.desc=Converts any HTML file or zip to PDF
|
||||
HTMLToPDF.tags=markup,web-content,transformation,convert
|
||||
|
||||
|
||||
home.MarkdownToPDF.title=Markdown to PDF
|
||||
home.MarkdownToPDF.desc=Converts any Markdown file to PDF
|
||||
MarkdownToPDF.tags=markup,web-content,transformation,convert
|
||||
|
||||
|
||||
home.getPdfInfo.title=Get ALL Info on PDF
|
||||
home.getPdfInfo.desc=Grabs any and all information possible on PDFs
|
||||
getPdfInfo.tags=infomation,data,stats,statistics
|
||||
|
||||
|
||||
home.extractPage.title=Extract page(s)
|
||||
home.extractPage.desc=Extracts select pages from PDF
|
||||
extractPage.tags=extract
|
||||
|
||||
|
||||
home.PdfToSinglePage.title=PDF to Single Large Page
|
||||
home.PdfToSinglePage.desc=Merges all PDF pages into one large single page
|
||||
PdfToSinglePage.tags=single page
|
||||
|
||||
|
||||
home.showJS.title=Show Javascript
|
||||
home.showJS.desc=Searches and displays any JS injected into a PDF
|
||||
showJS.tags=JS
|
||||
|
||||
home.autoRedact.title=Auto Redact
|
||||
home.autoRedact.desc=Auto Redacts(Blacks out) text in a PDF based on input text
|
||||
showJS.tags=JS
|
||||
|
||||
###########################
|
||||
# #
|
||||
# WEB PAGES #
|
||||
# #
|
||||
###########################
|
||||
#login
|
||||
login.title=Sign in
|
||||
login.signin=Sign in
|
||||
login.rememberme=Remember me
|
||||
login.invalid=Invalid username or password.
|
||||
login.locked=Your account has been locked.
|
||||
login.signinTitle=Please sign in
|
||||
|
||||
|
||||
#auto-redact
|
||||
autoRedact.title=Auto Redact
|
||||
autoRedact.header=Auto Redact
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
autoRedact.colorLabel=Colour
|
||||
autoRedact.textsToRedactLabel=Text to Redact (line-separated)
|
||||
autoRedact.textsToRedactPlaceholder=e.g. \nConfidential \nTop-Secret
|
||||
autoRedact.useRegexLabel=Use Regex
|
||||
autoRedact.wholeWordSearchLabel=Whole Word Search
|
||||
autoRedact.customPaddingLabel=Custom Extra Padding
|
||||
autoRedact.convertPDFToImageLabel=Convert PDF to PDF-Image (Used to remove text behind the box)
|
||||
autoRedact.submitButton=Submit
|
||||
|
||||
|
||||
#showJS
|
||||
showJS.title=Show Javascript
|
||||
showJS.header=Show Javascript
|
||||
showJS.downloadJS=Download Javascript
|
||||
showJS.submit=Show
|
||||
|
||||
|
||||
#pdfToSinglePage
|
||||
pdfToSinglePage.title=PDF To Single Page
|
||||
pdfToSinglePage.header=PDF To Single Page
|
||||
pdfToSinglePage.submit=Convert To Single Page
|
||||
|
||||
|
||||
#pageExtracter
|
||||
pageExtracter.title=Extract Pages
|
||||
pageExtracter.header=Extract Pages
|
||||
pageExtracter.submit=Extract
|
||||
|
||||
|
||||
#getPdfInfo
|
||||
getPdfInfo.title=Get Info on PDF
|
||||
getPdfInfo.header=Get Info on PDF
|
||||
getPdfInfo.submit=Get Info
|
||||
getPdfInfo.downloadJson=Download JSON
|
||||
|
||||
|
||||
#markdown-to-pdf
|
||||
MarkdownToPDF.title=Markdown To PDF
|
||||
MarkdownToPDF.header=Markdown To PDF
|
||||
MarkdownToPDF.submit=Convert
|
||||
MarkdownToPDF.help=Work in progress
|
||||
MarkdownToPDF.credit=Uses WeasyPrint
|
||||
|
||||
|
||||
|
||||
#url-to-pdf
|
||||
URLToPDF.title=URL To PDF
|
||||
URLToPDF.header=URL To PDF
|
||||
@@ -396,6 +416,9 @@ addPageNumbers.selectText.3=Position
|
||||
addPageNumbers.selectText.4=Starting Number
|
||||
addPageNumbers.selectText.5=Pages to Number
|
||||
addPageNumbers.selectText.6=Custom Text
|
||||
addPageNumbers.customTextDesc=Custom Text
|
||||
addPageNumbers.numberPagesDesc=Which pages to number, default 'all', also accepts 1-5 or 2,5,9 etc
|
||||
addPageNumbers.customNumberDesc=Defaults to {n}, also accepts 'Page {n} of {total}', 'Text-{n}', '{filename}-{n}
|
||||
addPageNumbers.submit=Add Page Numbers
|
||||
|
||||
|
||||
@@ -581,6 +604,8 @@ addImage.submit=Aggiungi immagine
|
||||
#merge
|
||||
merge.title=Unisci
|
||||
merge.header=Unisci 2 o più PDF
|
||||
merge.sortByName=Sort by name
|
||||
merge.sortByDate=Sort by date
|
||||
merge.submit=Unisci
|
||||
|
||||
|
||||
@@ -681,17 +706,11 @@ watermark.selectText.4=Rotazione (0-360):
|
||||
watermark.selectText.5=spazio orizzontale (tra ogni filigrana):
|
||||
watermark.selectText.6=spazio verticale (tra ogni filigrana):
|
||||
watermark.selectText.7=Opacità (0% - 100%):
|
||||
watermark.selectText.8=Watermark Type:
|
||||
watermark.selectText.9=Watermark Image:
|
||||
watermark.submit=Aggiungi Filigrana
|
||||
|
||||
|
||||
#remove-watermark
|
||||
remove-watermark.title=Rimuovi Filigrana
|
||||
remove-watermark.header=Rimuovi filigrana
|
||||
remove-watermark.selectText.1=Seleziona PDF da cui rimuovere la filigrana:
|
||||
remove-watermark.selectText.2=Testo:
|
||||
remove-watermark.submit=Rimuovi Filigrana
|
||||
|
||||
|
||||
#Change permissions
|
||||
permissions.title=Cambia Permessi
|
||||
permissions.header=Cambia permessi
|
||||
|
||||
@@ -26,14 +26,28 @@ text=テキスト
|
||||
font=フォント
|
||||
selectFillter=-- 選択 --
|
||||
pageNum=ページ番号
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
sizes.small=Small
|
||||
sizes.medium=Medium
|
||||
sizes.large=Large
|
||||
sizes.x-large=X-Large
|
||||
error.pdfPassword=PDFにパスワードが設定されてますが、パスワードが入力されてないか間違ってます。
|
||||
delete=Delete
|
||||
username=Username
|
||||
password=Password
|
||||
welcome=Welcome
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
property=Property
|
||||
black=Black
|
||||
white=White
|
||||
red=Red
|
||||
green=Green
|
||||
blue=Blue
|
||||
custom=Custom...
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#############
|
||||
@@ -57,6 +71,41 @@ settings.downloadOption.1=同じウィンドウで開く
|
||||
settings.downloadOption.2=新しいウィンドウで開く
|
||||
settings.downloadOption.3=ファイルをダウンロード
|
||||
settings.zipThreshold=このファイル数を超えたときにファイルを圧縮する
|
||||
settings.signOut=Sign Out
|
||||
settings.accountSettings=Account Settings
|
||||
|
||||
account.title=Account Settings
|
||||
account.accountSettings=Account Settings
|
||||
account.adminSettings=Admin Settings - View and Add Users
|
||||
account.userControlSettings=User Control Settings
|
||||
account.changeUsername=Change Username
|
||||
account.changeUsername=Change Username
|
||||
account.password=Confirmation Password
|
||||
account.oldPassword=Old password
|
||||
account.newPassword=New Password
|
||||
account.changePassword=Change Password
|
||||
account.confirmNewPassword=Confirm New Password
|
||||
account.signOut=Sign Out
|
||||
account.yourApiKey=Your API Key
|
||||
account.syncTitle=Sync browser settings with Account
|
||||
account.settingsCompare=Settings Comparison:
|
||||
account.property=Property
|
||||
account.webBrowserSettings=Web Browser Setting
|
||||
account.syncToBrowser=Sync Account -> Browser
|
||||
account.syncToAccount=Sync Account <- Browser
|
||||
|
||||
|
||||
adminUserSettings.title=User Control Settings
|
||||
adminUserSettings.header=Admin User Control Settings
|
||||
adminUserSettings.admin=Admin
|
||||
adminUserSettings.user=User
|
||||
adminUserSettings.addUser=Add New User
|
||||
adminUserSettings.roles=Roles
|
||||
adminUserSettings.role=Role
|
||||
adminUserSettings.actions=Actions
|
||||
adminUserSettings.apiUser=Limited API User
|
||||
adminUserSettings.webOnlyUser=Web Only User
|
||||
adminUserSettings.submit=Save User
|
||||
|
||||
#############
|
||||
# HOME-PAGE #
|
||||
@@ -66,314 +115,273 @@ home.desc=PDFのあらゆるニーズに対応するローカルホスティン
|
||||
|
||||
home.multiTool.title=PDFマルチツール
|
||||
home.multiTool.desc=ページの結合、回転、並べ替え、削除します。
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
multiTool.tags=Multi Tool,Multi operation,UI,click drag,front end,client side,interactive,intractable,move
|
||||
|
||||
home.merge.title=結合
|
||||
home.merge.desc=複数のPDFを1つに結合します。
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
merge.tags=merge,Page operations,Back end,server side
|
||||
|
||||
home.split.title=分割
|
||||
home.split.desc=PDFを複数のドキュメントに分割します。
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
split.tags=Page operations,divide,Multi Page,cut,server side
|
||||
split.tags=Page operations,divide,Multi Page,cut,server side
|
||||
|
||||
home.rotate.title=回転
|
||||
home.rotate.desc=PDFを回転します。
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
rotate.tags=server side
|
||||
|
||||
|
||||
home.imageToPdf.title=画像をPDFに変換
|
||||
home.imageToPdf.desc=画像 (PNG, JPEG, GIF) をPDFに変換します。
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
imageToPdf.tags=conversion,img,jpg,picture,photo
|
||||
|
||||
home.pdfToImage.title=PDFを画像に変換
|
||||
home.pdfToImage.desc=PDFを画像 (PNG, JPEG, GIF) に変換します。
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
pdfToImage.tags=conversion,img,jpg,picture,photo
|
||||
|
||||
home.pdfOrganiser.title=整理
|
||||
home.pdfOrganiser.desc=ページの削除/並べ替えします。
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
pdfOrganiser.tags=duplex,even,odd,sort,move
|
||||
|
||||
|
||||
home.addImage.title=画像の追加
|
||||
home.addImage.desc=PDF上の任意の場所に画像を追加します。
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
addImage.tags=img,jpg,picture,photo
|
||||
|
||||
home.watermark.title=透かしの追加
|
||||
home.watermark.desc=PDFに独自の透かしを追加します。
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
watermark.tags=Text,repeating,label,own,copyright,trademark,img,jpg,picture,photo
|
||||
|
||||
home.permissions.title=権限の変更
|
||||
home.permissions.desc=PDFの権限を変更します。
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
permissions.tags=read,write,edit,print
|
||||
|
||||
|
||||
home.removePages.title=削除
|
||||
home.removePages.desc=PDFから不要なページを削除します。
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
removePages.tags=Remove pages,delete pages
|
||||
|
||||
home.addPassword.title=パスワードの追加
|
||||
home.addPassword.desc=PDFをパスワードで暗号化します。
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
addPassword.tags=secure,security
|
||||
|
||||
home.removePassword.title=パスワードの削除
|
||||
home.removePassword.desc=PDFからパスワードの削除します。
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
removePassword.tags=secure,Decrypt,security,unpassword,delete password
|
||||
|
||||
home.compressPdfs.title=圧縮
|
||||
home.compressPdfs.desc=PDFを圧縮してファイルサイズを小さくします。
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
compressPdfs.tags=squish,small,tiny
|
||||
|
||||
|
||||
home.changeMetadata.title=メタデータの変更
|
||||
home.changeMetadata.desc=PDFのメタデータを変更/削除/追加します。
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
changeMetadata.tags==Title,author,date,creation,time,publisher,producer,stats
|
||||
|
||||
home.fileToPDF.title=ファイルをPDFに変換
|
||||
home.fileToPDF.desc=ほぼすべてのファイルをPDFに変換します。 (DOCX, PNG, XLS, PPT, TXTなど)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
fileToPDF.tags=transformation,format,document,picture,slide,text,conversion,office,docs,word,excel,powerpoint
|
||||
|
||||
home.ocr.title=OCR / クリーンアップ
|
||||
home.ocr.desc=クリーンアップはPDF内の画像からテキストを検出してテキストとして再追加します。
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
ocr.tags=recognition,text,image,scan,read,identify,detection,editable
|
||||
|
||||
|
||||
home.extractImages.title=画像の抽出
|
||||
home.extractImages.desc=PDFからすべての画像を抽出してzipで保存します。
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
extractImages.tags=picture,photo,save,archive,zip,capture,grab
|
||||
|
||||
home.pdfToPDFA.title=PDFをPDF/Aに変換
|
||||
home.pdfToPDFA.desc=長期保存のためにPDFをPDF/Aに変換。
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation
|
||||
|
||||
home.PDFToWord.title=PDFをWordに変換
|
||||
home.PDFToWord.desc=PDFをWord形式に変換します。 (DOC, DOCX および ODT)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
PDFToWord.tags=doc,docx,odt,word,transformation,format,conversion,office,microsoft,docfile
|
||||
|
||||
home.PDFToPresentation.title=PDFをプレゼンテーションに変換
|
||||
home.PDFToPresentation.desc=PDFをプレゼンテーション形式に変換します。 (PPT, PPTX および ODP)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
PDFToPresentation.tags=slides,show,office,microsoft
|
||||
|
||||
home.PDFToText.title=PDFをText/RTFに変換
|
||||
home.PDFToText.desc=PDFをTextまたはRTF形式に変換します。
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
PDFToText.tags=richformat,richtextformat,rich text format
|
||||
|
||||
home.PDFToHTML.title=PDFをHTMLに変換
|
||||
home.PDFToHTML.desc=PDFをHTML形式に変換します。
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
PDFToHTML.tags=web content,browser friendly
|
||||
|
||||
|
||||
home.PDFToXML.title=PDFをXMLに変換
|
||||
home.PDFToXML.desc=PDFをXML形式に変換します。
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
PDFToXML.tags=data-extraction,structured-content,interop,transformation,convert
|
||||
|
||||
home.ScannerImageSplit.title=スキャンされた画像の検出/分割
|
||||
home.ScannerImageSplit.desc=1枚の画像/PDFから複数の写真を分割します。
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
ScannerImageSplit.tags=separate,auto-detect,scans,multi-photo,organize
|
||||
|
||||
home.sign.title=署名
|
||||
home.sign.desc=手書き、テキストまたは画像によってPDFに署名を追加します。
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
sign.tags=authorize,initials,drawn-signature,text-sign,image-signature
|
||||
|
||||
home.flatten.title=平坦化
|
||||
home.flatten.desc=PDFからインタラクティブな要素とフォームをすべて削除します。
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
flatten.tags=static,deactivate,non-interactive,streamline
|
||||
|
||||
home.repair.title=修復
|
||||
home.repair.desc=破損したPDFの修復を試みます。
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
repair.tags=fix,restore,correction,recover
|
||||
|
||||
home.removeBlanks.title=空白ページの削除
|
||||
home.removeBlanks.desc=ドキュメントから空白ページを検出して削除します。
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
removeBlanks.tags=cleanup,streamline,non-content,organize
|
||||
|
||||
home.compare.title=比較
|
||||
home.compare.desc=2つのPDFを比較して表示します。
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
compare.tags=differentiate,contrast,changes,analysis
|
||||
|
||||
home.certSign.title=証明書による署名
|
||||
home.certSign.desc=証明書/キーを使用してPDFに署名します。 (PEM/P12)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
certSign.tags=authenticate,PEM,P12,official,encrypt
|
||||
|
||||
home.pageLayout.title=マルチページレイアウト
|
||||
home.pageLayout.desc=PDFの複数のページを1ページに結合します。
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
pageLayout.tags=merge,composite,single-view,organize
|
||||
|
||||
home.scalePages.title=ページの縮尺の調整
|
||||
home.scalePages.desc=ページやコンテンツの縮尺を変更します。
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
scalePages.tags=resize,modify,dimension,adapt
|
||||
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
home.pipeline.title=Pipeline (Advanced)
|
||||
home.pipeline.desc=Run multiple actions on PDFs by defining pipeline scripts
|
||||
pipeline.tags=automate,sequence,scripted,batch-process
|
||||
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
home.add-page-numbers.title=Add Page Numbers
|
||||
home.add-page-numbers.desc=Add Page numbers throughout a document in a set location
|
||||
add-page-numbers.tags=paginate,label,organize,index
|
||||
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
home.auto-rename.title=Auto Rename PDF File
|
||||
home.auto-rename.desc=Auto renames a PDF file based on its detected header
|
||||
home.auto-rename.desc=Auto renames a PDF file based on its detected header
|
||||
auto-rename.tags=auto-detect,header-based,organize,relabel
|
||||
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
home.adjust-contrast.title=Adjust Colors/Contrast
|
||||
home.adjust-contrast.desc=Adjust Contrast, Saturation and Brightness of a PDF
|
||||
adjust-contrast.tags=color-correction,tune,modify,enhance
|
||||
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
home.crop.title=Crop PDF
|
||||
home.crop.desc=Crop a PDF to reduce its size (maintains text!)
|
||||
crop.tags=trim,shrink,edit,shape
|
||||
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
home.autoSplitPDF.title=Auto Split Pages
|
||||
home.autoSplitPDF.desc=Auto Split Scanned PDF with physical scanned page splitter QR Code
|
||||
autoSplitPDF.tags=QR-based,separate,scan-segment,organize
|
||||
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
home.sanitizePdf.title=Sanitize
|
||||
home.sanitizePdf.desc=Remove scripts and other elements from PDF files
|
||||
sanitizePdf.tags=clean,secure,safe,remove-threats
|
||||
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
home.URLToPDF.title=URL/Website To PDF
|
||||
home.URLToPDF.desc=Converts any http(s)URL to PDF
|
||||
URLToPDF.tags=web-capture,save-page,web-to-doc,archive
|
||||
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
home.HTMLToPDF.title=HTML to PDF
|
||||
home.HTMLToPDF.desc=Converts any HTML file or zip to PDF
|
||||
HTMLToPDF.tags=markup,web-content,transformation,convert
|
||||
|
||||
|
||||
home.MarkdownToPDF.title=Markdown to PDF
|
||||
home.MarkdownToPDF.desc=Converts any Markdown file to PDF
|
||||
MarkdownToPDF.tags=markup,web-content,transformation,convert
|
||||
|
||||
|
||||
home.getPdfInfo.title=Get ALL Info on PDF
|
||||
home.getPdfInfo.desc=Grabs any and all information possible on PDFs
|
||||
getPdfInfo.tags=infomation,data,stats,statistics
|
||||
|
||||
|
||||
home.extractPage.title=Extract page(s)
|
||||
home.extractPage.desc=Extracts select pages from PDF
|
||||
extractPage.tags=extract
|
||||
|
||||
|
||||
home.PdfToSinglePage.title=PDF to Single Large Page
|
||||
home.PdfToSinglePage.desc=Merges all PDF pages into one large single page
|
||||
PdfToSinglePage.tags=single page
|
||||
|
||||
|
||||
home.showJS.title=Show Javascript
|
||||
home.showJS.desc=Searches and displays any JS injected into a PDF
|
||||
showJS.tags=JS
|
||||
|
||||
home.autoRedact.title=Auto Redact
|
||||
home.autoRedact.desc=Auto Redacts(Blacks out) text in a PDF based on input text
|
||||
showJS.tags=JS
|
||||
|
||||
###########################
|
||||
# #
|
||||
# WEB PAGES #
|
||||
# #
|
||||
###########################
|
||||
#url-to-pdf
|
||||
#login
|
||||
login.title=Sign in
|
||||
login.signin=Sign in
|
||||
login.rememberme=Remember me
|
||||
login.invalid=Invalid username or password.
|
||||
login.locked=Your account has been locked.
|
||||
login.signinTitle=Please sign in
|
||||
|
||||
|
||||
#auto-redact
|
||||
autoRedact.title=Auto Redact
|
||||
autoRedact.header=Auto Redact
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
autoRedact.colorLabel=Colour
|
||||
autoRedact.textsToRedactLabel=Text to Redact (line-separated)
|
||||
autoRedact.textsToRedactPlaceholder=e.g. \nConfidential \nTop-Secret
|
||||
autoRedact.useRegexLabel=Use Regex
|
||||
autoRedact.wholeWordSearchLabel=Whole Word Search
|
||||
autoRedact.customPaddingLabel=Custom Extra Padding
|
||||
autoRedact.convertPDFToImageLabel=Convert PDF to PDF-Image (Used to remove text behind the box)
|
||||
autoRedact.submitButton=Submit
|
||||
|
||||
|
||||
#showJS
|
||||
showJS.title=Show Javascript
|
||||
showJS.header=Show Javascript
|
||||
showJS.downloadJS=Download Javascript
|
||||
showJS.submit=Show
|
||||
|
||||
|
||||
#pdfToSinglePage
|
||||
pdfToSinglePage.title=PDF To Single Page
|
||||
pdfToSinglePage.header=PDF To Single Page
|
||||
pdfToSinglePage.submit=Convert To Single Page
|
||||
|
||||
|
||||
#pageExtracter
|
||||
pageExtracter.title=Extract Pages
|
||||
pageExtracter.header=Extract Pages
|
||||
pageExtracter.submit=Extract
|
||||
|
||||
|
||||
#getPdfInfo
|
||||
getPdfInfo.title=Get Info on PDF
|
||||
getPdfInfo.header=Get Info on PDF
|
||||
getPdfInfo.submit=Get Info
|
||||
getPdfInfo.downloadJson=Download JSON
|
||||
|
||||
|
||||
#markdown-to-pdf
|
||||
MarkdownToPDF.title=Markdown To PDF
|
||||
MarkdownToPDF.header=Markdown To PDF
|
||||
MarkdownToPDF.submit=Convert
|
||||
MarkdownToPDF.help=Work in progress
|
||||
MarkdownToPDF.credit=Uses WeasyPrint
|
||||
|
||||
|
||||
|
||||
#url-to-pdf
|
||||
URLToPDF.title=URL To PDF
|
||||
URLToPDF.header=URL To PDF
|
||||
URLToPDF.submit=Convert
|
||||
@@ -381,9 +389,6 @@ URLToPDF.credit=Uses WeasyPrint
|
||||
|
||||
|
||||
#html-to-pdf
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
HTMLToPDF.title=HTML To PDF
|
||||
HTMLToPDF.header=HTML To PDF
|
||||
HTMLToPDF.help=Accepts HTML files and ZIPs containing html/css/images etc required
|
||||
@@ -392,9 +397,6 @@ HTMLToPDF.credit=Uses WeasyPrint
|
||||
|
||||
|
||||
#sanitizePDF
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
sanitizePDF.title=Sanitize PDF
|
||||
sanitizePDF.header=Sanitize a PDF file
|
||||
sanitizePDF.selectText.1=Remove JavaScript actions
|
||||
@@ -406,9 +408,6 @@ sanitizePDF.submit=Sanitize PDF
|
||||
|
||||
|
||||
#addPageNumbers
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
addPageNumbers.title=Add Page Numbers
|
||||
addPageNumbers.header=Add Page Numbers
|
||||
addPageNumbers.selectText.1=Select PDF file:
|
||||
@@ -417,22 +416,19 @@ addPageNumbers.selectText.3=Position
|
||||
addPageNumbers.selectText.4=Starting Number
|
||||
addPageNumbers.selectText.5=Pages to Number
|
||||
addPageNumbers.selectText.6=Custom Text
|
||||
addPageNumbers.customTextDesc=Custom Text
|
||||
addPageNumbers.numberPagesDesc=Which pages to number, default 'all', also accepts 1-5 or 2,5,9 etc
|
||||
addPageNumbers.customNumberDesc=Defaults to {n}, also accepts 'Page {n} of {total}', 'Text-{n}', '{filename}-{n}
|
||||
addPageNumbers.submit=Add Page Numbers
|
||||
|
||||
|
||||
#auto-rename
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
auto-rename.title=Auto Rename
|
||||
auto-rename.header=Auto Rename PDF
|
||||
auto-rename.submit=Auto Rename
|
||||
|
||||
|
||||
#adjustContrast
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
adjustContrast.title=Adjust Contrast
|
||||
adjustContrast.header=Adjust Contrast
|
||||
adjustContrast.contrast=Contrast:
|
||||
@@ -442,18 +438,12 @@ adjustContrast.download=Download
|
||||
|
||||
|
||||
#crop
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
crop.title=Crop
|
||||
crop.header=Crop Image
|
||||
crop.submit=Submit
|
||||
|
||||
|
||||
#autoSplitPDF
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
autoSplitPDF.title=Auto Split PDF
|
||||
autoSplitPDF.header=Auto Split PDF
|
||||
autoSplitPDF.description=Print, Insert, Scan, upload, and let us auto-separate your documents. No manual work sorting needed.
|
||||
@@ -469,9 +459,6 @@ autoSplitPDF.submit=Submit
|
||||
|
||||
|
||||
#pipeline
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
pipeline.title=Pipeline
|
||||
|
||||
|
||||
@@ -617,6 +604,8 @@ addImage.submit=画像の追加
|
||||
#merge
|
||||
merge.title=結合
|
||||
merge.header=複数のPDFを結合 (2ファイル以上)
|
||||
merge.sortByName=Sort by name
|
||||
merge.sortByDate=Sort by date
|
||||
merge.submit=結合
|
||||
|
||||
|
||||
@@ -717,17 +706,11 @@ watermark.selectText.4=回転 (0-360):
|
||||
watermark.selectText.5=幅スペース (各透かし間の水平方向のスペース):
|
||||
watermark.selectText.6=高さスペース (各透かし間の垂直方向のスペース):
|
||||
watermark.selectText.7=不透明度 (0% - 100%):
|
||||
watermark.selectText.8=Watermark Type:
|
||||
watermark.selectText.9=Watermark Image:
|
||||
watermark.submit=透かしを追加
|
||||
|
||||
|
||||
#remove-watermark
|
||||
remove-watermark.title=透かしの削除
|
||||
remove-watermark.header=透かしの削除
|
||||
remove-watermark.selectText.1=透かしを削除するPDFを選択:
|
||||
remove-watermark.selectText.2=透かしのテキスト:
|
||||
remove-watermark.submit=透かしを削除
|
||||
|
||||
|
||||
#Change permissions
|
||||
permissions.title=権限の変更
|
||||
permissions.header=権限の変更
|
||||
|
||||
@@ -31,6 +31,23 @@ sizes.medium=Medium
|
||||
sizes.large=Large
|
||||
sizes.x-large=X-Large
|
||||
error.pdfPassword=The PDF Document is passworded and either the password was not provided or was incorrect
|
||||
delete=Delete
|
||||
username=Username
|
||||
password=Password
|
||||
welcome=Welcome
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
property=Property
|
||||
black=Black
|
||||
white=White
|
||||
red=Red
|
||||
green=Green
|
||||
blue=Blue
|
||||
custom=Custom...
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#############
|
||||
@@ -54,6 +71,41 @@ settings.downloadOption.1=현재 창에서 열기
|
||||
settings.downloadOption.2=새 창에서 열기
|
||||
settings.downloadOption.3=다운로드
|
||||
settings.zipThreshold=다운로드한 파일 수가 초과된 경우 파일 압축하기
|
||||
settings.signOut=Sign Out
|
||||
settings.accountSettings=Account Settings
|
||||
|
||||
account.title=Account Settings
|
||||
account.accountSettings=Account Settings
|
||||
account.adminSettings=Admin Settings - View and Add Users
|
||||
account.userControlSettings=User Control Settings
|
||||
account.changeUsername=Change Username
|
||||
account.changeUsername=Change Username
|
||||
account.password=Confirmation Password
|
||||
account.oldPassword=Old password
|
||||
account.newPassword=New Password
|
||||
account.changePassword=Change Password
|
||||
account.confirmNewPassword=Confirm New Password
|
||||
account.signOut=Sign Out
|
||||
account.yourApiKey=Your API Key
|
||||
account.syncTitle=Sync browser settings with Account
|
||||
account.settingsCompare=Settings Comparison:
|
||||
account.property=Property
|
||||
account.webBrowserSettings=Web Browser Setting
|
||||
account.syncToBrowser=Sync Account -> Browser
|
||||
account.syncToAccount=Sync Account <- Browser
|
||||
|
||||
|
||||
adminUserSettings.title=User Control Settings
|
||||
adminUserSettings.header=Admin User Control Settings
|
||||
adminUserSettings.admin=Admin
|
||||
adminUserSettings.user=User
|
||||
adminUserSettings.addUser=Add New User
|
||||
adminUserSettings.roles=Roles
|
||||
adminUserSettings.role=Role
|
||||
adminUserSettings.actions=Actions
|
||||
adminUserSettings.apiUser=Limited API User
|
||||
adminUserSettings.webOnlyUser=Web Only User
|
||||
adminUserSettings.submit=Save User
|
||||
|
||||
#############
|
||||
# HOME-PAGE #
|
||||
@@ -71,296 +123,264 @@ merge.tags=merge,Page operations,Back end,server side
|
||||
|
||||
home.split.title=분할
|
||||
home.split.desc=PDF를 여러 개의 문서로 분할하세요.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
split.tags=Page operations,divide,Multi Page,cut,server side
|
||||
split.tags=Page operations,divide,Multi Page,cut,server side
|
||||
|
||||
home.rotate.title=회전
|
||||
home.rotate.desc=PDF를 쉽게 회전하세요.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
rotate.tags=server side
|
||||
|
||||
|
||||
home.imageToPdf.title=Image to PDF
|
||||
home.imageToPdf.desc=이미지(PNG, JPEG, GIF)를 PDF로 변환하세요.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
imageToPdf.tags=conversion,img,jpg,picture,photo
|
||||
|
||||
home.pdfToImage.title=PDF to Image
|
||||
home.pdfToImage.desc=PDF를 이미지(PNG, JPEG, GIF)로 변환하세요.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
pdfToImage.tags=conversion,img,jpg,picture,photo
|
||||
|
||||
home.pdfOrganiser.title=정렬
|
||||
home.pdfOrganiser.desc=페이지를 원하는 순서대로 제거/재배열하세요.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
pdfOrganiser.tags=duplex,even,odd,sort,move
|
||||
|
||||
|
||||
home.addImage.title=사진 추가
|
||||
home.addImage.desc=PDF의 설정된 위치에 이미지를 추가하세요.(개발 중)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
addImage.tags=img,jpg,picture,photo
|
||||
|
||||
home.watermark.title=워터마크 추가
|
||||
home.watermark.desc=PDF 문서에 사용자 지정 워터마크를 추가하세요.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
watermark.tags=Text,repeating,label,own,copyright,trademark,img,jpg,picture,photo
|
||||
|
||||
home.permissions.title=권한 변경
|
||||
home.permissions.desc=PDF 문서의 권한을 변경하세요.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
permissions.tags=read,write,edit,print
|
||||
|
||||
|
||||
home.removePages.title=제거
|
||||
home.removePages.desc=PDF 문서에서 원치 않는 페이지를 제거하세요.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
removePages.tags=Remove pages,delete pages
|
||||
|
||||
home.addPassword.title=비밀번호 추가
|
||||
home.addPassword.desc=PDF 문서를 비밀번호로 암호화하세요.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
addPassword.tags=secure,security
|
||||
|
||||
home.removePassword.title=비밀번호 제거
|
||||
home.removePassword.desc=PDF 문서에서 비밀번호를 제거하세요.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
removePassword.tags=secure,Decrypt,security,unpassword,delete password
|
||||
|
||||
home.compressPdfs.title=압축
|
||||
home.compressPdfs.desc=파일 크기를 줄이기 위해 PDF 문서를 압축하세요.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
compressPdfs.tags=squish,small,tiny
|
||||
|
||||
|
||||
home.changeMetadata.title=메타데이터 변경
|
||||
home.changeMetadata.desc=PDF 문서의 메타데이터를 수정/제거/추가하세요.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
changeMetadata.tags==Title,author,date,creation,time,publisher,producer,stats
|
||||
|
||||
home.fileToPDF.title=파일을 PDF로 변환
|
||||
home.fileToPDF.desc=거의 모든 파일을 PDF로 변환하세요(DOCX, PNG, XLS, PPT, TXT 등)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
fileToPDF.tags=transformation,format,document,picture,slide,text,conversion,office,docs,word,excel,powerpoint
|
||||
|
||||
home.ocr.title=OCR / 깔끔하게 스캔
|
||||
home.ocr.desc=깔끔하게 스캔하고 PDF 내의 이미지에서 텍스트를 감지하여 텍스트로 다시 추가합니다.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
ocr.tags=recognition,text,image,scan,read,identify,detection,editable
|
||||
|
||||
|
||||
home.extractImages.title=이미지 추출
|
||||
home.extractImages.desc=PDF에서 모든 이미지를 추출하여 zip으로 저장합니다.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
extractImages.tags=picture,photo,save,archive,zip,capture,grab
|
||||
|
||||
home.pdfToPDFA.title=PDF to PDF/A
|
||||
home.pdfToPDFA.desc=장기 보관을 위해 PDF를 PDF/A 문서로 변환하세요.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation
|
||||
|
||||
home.PDFToWord.title=PDF to Word
|
||||
home.PDFToWord.desc=PDF를 Word 형식으로 변환하세요. (DOC, DOCX, ODT)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
PDFToWord.tags=doc,docx,odt,word,transformation,format,conversion,office,microsoft,docfile
|
||||
|
||||
home.PDFToPresentation.title=PDF to 프리젠테이션
|
||||
home.PDFToPresentation.desc=PDF를 프리젠테이션 형식으로 변환하세요. (PPT, PPTX, ODP)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
PDFToPresentation.tags=slides,show,office,microsoft
|
||||
|
||||
home.PDFToText.title=PDF to 텍스트/RTF
|
||||
home.PDFToText.desc=PDF를 텍스트 또는 RTF 형식으로 변환하세요.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
PDFToText.tags=richformat,richtextformat,rich text format
|
||||
|
||||
home.PDFToHTML.title=PDF to HTML
|
||||
home.PDFToHTML.desc=PDF를 HTML 형식으로 변환하세요.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
PDFToHTML.tags=web content,browser friendly
|
||||
|
||||
|
||||
home.PDFToXML.title=PDF to XML
|
||||
home.PDFToXML.desc=PDF를 XML 형식으로 변환하세요.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
PDFToXML.tags=data-extraction,structured-content,interop,transformation,convert
|
||||
|
||||
home.ScannerImageSplit.title=스캔한 사진 감지/분할
|
||||
home.ScannerImageSplit.desc=사진/PDF 내에서 여러 장의 사진을 분할합니다.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
ScannerImageSplit.tags=separate,auto-detect,scans,multi-photo,organize
|
||||
|
||||
home.sign.title=서명
|
||||
home.sign.desc=PDF에 그림, 텍스트, 이미지로 서명을 추가합니다.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
sign.tags=authorize,initials,drawn-signature,text-sign,image-signature
|
||||
|
||||
home.flatten.title=합치기
|
||||
home.flatten.desc=PDF에서 모든 인터랙션 요소와 양식을 제거하세요.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
flatten.tags=static,deactivate,non-interactive,streamline
|
||||
|
||||
home.repair.title=복구
|
||||
home.repair.desc=손상된 PDF의 복구를 시도합니다.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
repair.tags=fix,restore,correction,recover
|
||||
|
||||
home.removeBlanks.title=빈 페이지 제거
|
||||
home.removeBlanks.desc=문서에서 빈 페이지를 감지하고 제거합니다.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
removeBlanks.tags=cleanup,streamline,non-content,organize
|
||||
|
||||
home.compare.title=비교
|
||||
home.compare.desc=2개의 PDF 문서를 비교하고 차이를 표시합니다.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
compare.tags=differentiate,contrast,changes,analysis
|
||||
|
||||
home.certSign.title=인증서로 서명
|
||||
home.certSign.desc=PDF에 인증서/키로 서명합니다. (PEM/P12)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
certSign.tags=authenticate,PEM,P12,official,encrypt
|
||||
|
||||
home.pageLayout.title=Multi-Page Layout
|
||||
home.pageLayout.desc=Merge multiple pages of a PDF document into a single page
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
pageLayout.tags=merge,composite,single-view,organize
|
||||
|
||||
home.scalePages.title=Adjust page size/scale
|
||||
home.scalePages.desc=Change the size/scale of page and/or its contents.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
scalePages.tags=resize,modify,dimension,adapt
|
||||
|
||||
home.pipeline.title=Pipeline (Advanced)
|
||||
home.pipeline.desc=Run multiple actions on PDFs by defining pipeline scripts
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
pipeline.tags=automate,sequence,scripted,batch-process
|
||||
|
||||
home.add-page-numbers.title=Add Page Numbers
|
||||
home.add-page-numbers.desc=Add Page numbers throughout a document in a set location
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
add-page-numbers.tags=paginate,label,organize,index
|
||||
|
||||
home.auto-rename.title=Auto Rename PDF File
|
||||
home.auto-rename.desc=Auto renames a PDF file based on its detected header
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
auto-rename.tags=auto-detect,header-based,organize,relabel
|
||||
|
||||
home.adjust-contrast.title=Adjust Colors/Contrast
|
||||
home.adjust-contrast.desc=Adjust Contrast, Saturation and Brightness of a PDF
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
adjust-contrast.tags=color-correction,tune,modify,enhance
|
||||
|
||||
home.crop.title=Crop PDF
|
||||
home.crop.desc=Crop a PDF to reduce its size (maintains text!)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
crop.tags=trim,shrink,edit,shape
|
||||
|
||||
home.autoSplitPDF.title=Auto Split Pages
|
||||
home.autoSplitPDF.desc=Auto Split Scanned PDF with physical scanned page splitter QR Code
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
autoSplitPDF.tags=QR-based,separate,scan-segment,organize
|
||||
|
||||
home.sanitizePdf.title=Sanitize
|
||||
home.sanitizePdf.desc=Remove scripts and other elements from PDF files
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
sanitizePdf.tags=clean,secure,safe,remove-threats
|
||||
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
home.URLToPDF.title=URL/Website To PDF
|
||||
home.URLToPDF.desc=Converts any http(s)URL to PDF
|
||||
URLToPDF.tags=web-capture,save-page,web-to-doc,archive
|
||||
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
home.HTMLToPDF.title=HTML to PDF
|
||||
home.HTMLToPDF.desc=Converts any HTML file or zip to PDF
|
||||
HTMLToPDF.tags=markup,web-content,transformation,convert
|
||||
|
||||
|
||||
home.MarkdownToPDF.title=Markdown to PDF
|
||||
home.MarkdownToPDF.desc=Converts any Markdown file to PDF
|
||||
MarkdownToPDF.tags=markup,web-content,transformation,convert
|
||||
|
||||
|
||||
home.getPdfInfo.title=Get ALL Info on PDF
|
||||
home.getPdfInfo.desc=Grabs any and all information possible on PDFs
|
||||
getPdfInfo.tags=infomation,data,stats,statistics
|
||||
|
||||
|
||||
home.extractPage.title=Extract page(s)
|
||||
home.extractPage.desc=Extracts select pages from PDF
|
||||
extractPage.tags=extract
|
||||
|
||||
|
||||
home.PdfToSinglePage.title=PDF to Single Large Page
|
||||
home.PdfToSinglePage.desc=Merges all PDF pages into one large single page
|
||||
PdfToSinglePage.tags=single page
|
||||
|
||||
|
||||
home.showJS.title=Show Javascript
|
||||
home.showJS.desc=Searches and displays any JS injected into a PDF
|
||||
showJS.tags=JS
|
||||
|
||||
home.autoRedact.title=Auto Redact
|
||||
home.autoRedact.desc=Auto Redacts(Blacks out) text in a PDF based on input text
|
||||
showJS.tags=JS
|
||||
|
||||
###########################
|
||||
# #
|
||||
# WEB PAGES #
|
||||
# #
|
||||
###########################
|
||||
#login
|
||||
login.title=Sign in
|
||||
login.signin=Sign in
|
||||
login.rememberme=Remember me
|
||||
login.invalid=Invalid username or password.
|
||||
login.locked=Your account has been locked.
|
||||
login.signinTitle=Please sign in
|
||||
|
||||
|
||||
#auto-redact
|
||||
autoRedact.title=Auto Redact
|
||||
autoRedact.header=Auto Redact
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
autoRedact.colorLabel=Colour
|
||||
autoRedact.textsToRedactLabel=Text to Redact (line-separated)
|
||||
autoRedact.textsToRedactPlaceholder=e.g. \nConfidential \nTop-Secret
|
||||
autoRedact.useRegexLabel=Use Regex
|
||||
autoRedact.wholeWordSearchLabel=Whole Word Search
|
||||
autoRedact.customPaddingLabel=Custom Extra Padding
|
||||
autoRedact.convertPDFToImageLabel=Convert PDF to PDF-Image (Used to remove text behind the box)
|
||||
autoRedact.submitButton=Submit
|
||||
|
||||
|
||||
#showJS
|
||||
showJS.title=Show Javascript
|
||||
showJS.header=Show Javascript
|
||||
showJS.downloadJS=Download Javascript
|
||||
showJS.submit=Show
|
||||
|
||||
|
||||
#pdfToSinglePage
|
||||
pdfToSinglePage.title=PDF To Single Page
|
||||
pdfToSinglePage.header=PDF To Single Page
|
||||
pdfToSinglePage.submit=Convert To Single Page
|
||||
|
||||
|
||||
#pageExtracter
|
||||
pageExtracter.title=Extract Pages
|
||||
pageExtracter.header=Extract Pages
|
||||
pageExtracter.submit=Extract
|
||||
|
||||
|
||||
#getPdfInfo
|
||||
getPdfInfo.title=Get Info on PDF
|
||||
getPdfInfo.header=Get Info on PDF
|
||||
getPdfInfo.submit=Get Info
|
||||
getPdfInfo.downloadJson=Download JSON
|
||||
|
||||
|
||||
#markdown-to-pdf
|
||||
MarkdownToPDF.title=Markdown To PDF
|
||||
MarkdownToPDF.header=Markdown To PDF
|
||||
MarkdownToPDF.submit=Convert
|
||||
MarkdownToPDF.help=Work in progress
|
||||
MarkdownToPDF.credit=Uses WeasyPrint
|
||||
|
||||
|
||||
|
||||
#url-to-pdf
|
||||
URLToPDF.title=URL To PDF
|
||||
URLToPDF.header=URL To PDF
|
||||
@@ -396,6 +416,9 @@ addPageNumbers.selectText.3=Position
|
||||
addPageNumbers.selectText.4=Starting Number
|
||||
addPageNumbers.selectText.5=Pages to Number
|
||||
addPageNumbers.selectText.6=Custom Text
|
||||
addPageNumbers.customTextDesc=Custom Text
|
||||
addPageNumbers.numberPagesDesc=Which pages to number, default 'all', also accepts 1-5 or 2,5,9 etc
|
||||
addPageNumbers.customNumberDesc=Defaults to {n}, also accepts 'Page {n} of {total}', 'Text-{n}', '{filename}-{n}
|
||||
addPageNumbers.submit=Add Page Numbers
|
||||
|
||||
|
||||
@@ -581,6 +604,8 @@ addImage.submit=이미지 추가
|
||||
#merge
|
||||
merge.title=병합
|
||||
merge.header=여러 개의 PDF 병합 (2개 이상)
|
||||
merge.sortByName=Sort by name
|
||||
merge.sortByDate=Sort by date
|
||||
merge.submit=병합
|
||||
|
||||
|
||||
@@ -681,17 +706,11 @@ watermark.selectText.4=회전 각도 (0-360):
|
||||
watermark.selectText.5=가로 간격 (각 워터마크 사이의 가로 공간):
|
||||
watermark.selectText.6=세로 간격 (각 워터마크 사이의 세로 공간):
|
||||
watermark.selectText.7=투명도 (0% - 100%):
|
||||
watermark.selectText.8=Watermark Type:
|
||||
watermark.selectText.9=Watermark Image:
|
||||
watermark.submit=워터마크 추가
|
||||
|
||||
|
||||
#remove-watermark
|
||||
remove-watermark.title=워터마크 제거
|
||||
remove-watermark.header=워터마크 제거
|
||||
remove-watermark.selectText.1=워터마크를 제거할 PDF 선택:
|
||||
remove-watermark.selectText.2=워터마크 텍스트:
|
||||
remove-watermark.submit=워터마크 제거
|
||||
|
||||
|
||||
#Change permissions
|
||||
permissions.title=권한 변경
|
||||
permissions.header=권한 변경
|
||||
|
||||
808
src/main/resources/messages_nl_NL.properties
Normal file
808
src/main/resources/messages_nl_NL.properties
Normal file
@@ -0,0 +1,808 @@
|
||||
###########
|
||||
# Generic #
|
||||
###########
|
||||
# the direction that the language is written (ltr=left to right, rtl = right to left)
|
||||
language.direction=ltr
|
||||
|
||||
pdfPrompt=Selecteer PDF(s)
|
||||
multiPdfPrompt=Selecteer PDFs (2+)
|
||||
multiPdfDropPrompt=Selecteer (of sleep & zet neer) alle PDFs die je nodig hebt
|
||||
imgPrompt=Selecteer afbeelding(en)
|
||||
genericSubmit=Indienen
|
||||
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) :
|
||||
goToPage=Ga
|
||||
true=Waar
|
||||
false=Onwaar
|
||||
unknown=Onbekend
|
||||
save=Opslaan
|
||||
close=Sluiten
|
||||
filesSelected=Bestanden geselecteerd
|
||||
noFavourites=Geen favorieten toegevoegd
|
||||
bored=Verveeld met wachten?
|
||||
alphabet=Alfabet
|
||||
downloadPdf=Download PDF
|
||||
text=Tekst
|
||||
font=Lettertype
|
||||
selectFillter=-- Selecteer --
|
||||
pageNum=Paginanummer
|
||||
sizes.small=Klein
|
||||
sizes.medium=Medium
|
||||
sizes.large=Groot
|
||||
sizes.x-large=Extra Groot
|
||||
error.pdfPassword=Het PDF document is beveiligd met een wachtwoord en het wachtwoord is niet ingevoerd of was onjuist
|
||||
delete=Verwijderen
|
||||
username=Gebruikersnaam
|
||||
password=Wachtwoord
|
||||
welcome=Welkom
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
property=Property
|
||||
black=Black
|
||||
white=White
|
||||
red=Red
|
||||
green=Green
|
||||
blue=Blue
|
||||
custom=Custom...
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#############
|
||||
# NAVBAR #
|
||||
#############
|
||||
navbar.convert=Converteren
|
||||
navbar.security=Beveiliging
|
||||
navbar.other=Overige
|
||||
navbar.darkmode=Donkere modus
|
||||
navbar.pageOps=Pagina operaties
|
||||
navbar.settings=Instellingen
|
||||
|
||||
#############
|
||||
# SETTINGS #
|
||||
#############
|
||||
settings.title=Instellingen
|
||||
settings.update=Update beschikbaar
|
||||
settings.appVersion=App versie:
|
||||
settings.downloadOption.title=Kies download optie (Voor enkelvoudige bestanddownloads zonder zip):
|
||||
settings.downloadOption.1=Open in hetzelfde venster
|
||||
settings.downloadOption.2=Open in nieuw venster
|
||||
settings.downloadOption.3=Download bestand
|
||||
settings.zipThreshold=Zip bestanden wanneer het aantal gedownloade bestanden overschrijdt
|
||||
settings.signOut=Uitloggen
|
||||
settings.accountSettings=Account instellingen
|
||||
|
||||
account.title=Account instellingen
|
||||
account.accountSettings=Account instellingen
|
||||
account.adminSettings=Beheerdersinstellingen - Gebruikers bekijken en toevoegen
|
||||
account.userControlSettings=Gebruikerscontrole instellingen
|
||||
account.changeUsername=Wijzig gebruikersnaam
|
||||
account.changeUsername=Wijzig gebruikersnaam
|
||||
account.password=Bevestigingswachtwoord
|
||||
account.oldPassword=Oud wachtwoord
|
||||
account.newPassword=Nieuw wachtwoord
|
||||
account.changePassword=Wijzig wachtwoord
|
||||
account.confirmNewPassword=Bevestig nieuw wachtwoord
|
||||
account.signOut=Uitloggen
|
||||
account.yourApiKey=Jouw API sleutel
|
||||
account.syncTitle=Synchroniseer browserinstellingen met account
|
||||
account.settingsCompare=Instellingen vergelijking:
|
||||
account.property=Eigenschap
|
||||
account.webBrowserSettings=Web Browser instelling
|
||||
account.syncToBrowser=Synchroniseer account -> browser
|
||||
account.syncToAccount=Synchroniseer account <- browser
|
||||
|
||||
|
||||
adminUserSettings.title=Gebruikerscontrole instellingen
|
||||
adminUserSettings.header=Beheer Gebruikerscontrole instellingen
|
||||
adminUserSettings.admin=Beheerder
|
||||
adminUserSettings.user=Gebruiker
|
||||
adminUserSettings.addUser=Voeg nieuwe gebruiker toe
|
||||
adminUserSettings.roles=Rollen
|
||||
adminUserSettings.role=Rol
|
||||
adminUserSettings.actions=Acties
|
||||
adminUserSettings.apiUser=Beperkte API gebruiker
|
||||
adminUserSettings.webOnlyUser=Alleen web gebruiker
|
||||
adminUserSettings.submit=Sla gebruiker op
|
||||
|
||||
#############
|
||||
# HOME-PAGE #
|
||||
#############
|
||||
home.desc=Jouw lokaal gehoste one-stop-shop voor al je PDF-behoeften.
|
||||
|
||||
|
||||
home.multiTool.title=PDF Multitool
|
||||
home.multiTool.desc=Samenvoegen, draaien, herschikken en pagina''s verwijderen
|
||||
multiTool.tags=Multitool,Multi bewerking,UI,klik sleep,voorkant,clientzijde,interactief,beweegbaar,verplaats
|
||||
|
||||
home.merge.title=Samenvoegen
|
||||
home.merge.desc=Voeg eenvoudig meerdere PDF''s samen tot één.
|
||||
merge.tags=samenvoegen,Pagina operaties,Serverkant
|
||||
|
||||
home.split.title=Splitsen
|
||||
home.split.desc=Splits PDF''s in meerdere documenten
|
||||
split.tags=Pagina operaties,verdelen,meerdere pagina''s,knippen,serverzijde
|
||||
|
||||
home.rotate.title=Roteren
|
||||
home.rotate.desc=Roteer eenvoudig je PDF''s.
|
||||
rotate.tags=serverzijde
|
||||
|
||||
|
||||
home.imageToPdf.title=Afbeelding naar PDF
|
||||
home.imageToPdf.desc=Converteer een afbeelding (PNG, JPEG, GIF) naar PDF.
|
||||
imageToPdf.tags=conversie,img,jpg,foto
|
||||
|
||||
home.pdfToImage.title=PDF naar Afbeelding
|
||||
home.pdfToImage.desc=Converteer een PDF naar een afbeelding. (PNG, JPEG, GIF)
|
||||
pdfToImage.tags=conversie,img,jpg,foto
|
||||
|
||||
home.pdfOrganiser.title=Organiseren
|
||||
home.pdfOrganiser.desc=Verwijder/Herschik pagina''s in een volgorde naar keus
|
||||
pdfOrganiser.tags=duplex,even oneven,sorteren,verplaatsen
|
||||
|
||||
|
||||
home.addImage.title=Afbeelding toevoegen
|
||||
home.addImage.desc=Voegt een afbeelding toe op een specifieke locatie in de PDF
|
||||
addImage.tags=img,jpg,foto
|
||||
|
||||
home.watermark.title=Watermerk toevoegen
|
||||
home.watermark.desc=Voeg een aangepast watermerk toe aan je PDF-document.
|
||||
watermark.tags=Tekst,herhalend,label,eigen,copyright,handelsmerk,img,jpg,foto
|
||||
|
||||
home.permissions.title=Permissies wijzigen
|
||||
home.permissions.desc=Wijzig de permissies van je PDF-document
|
||||
permissions.tags=lezen,schrijven,bewerken,printen
|
||||
|
||||
|
||||
home.removePages.title=Verwijderen
|
||||
home.removePages.desc=Verwijder ongewenste pagina''s uit je PDF-document.
|
||||
removePages.tags=Pagina''s verwijderen
|
||||
|
||||
home.addPassword.title=Wachtwoord toevoegen
|
||||
home.addPassword.desc=Versleutel je PDF-document met een wachtwoord.
|
||||
addPassword.tags=veilig,beveiliging
|
||||
|
||||
home.removePassword.title=Wachtwoord verwijderen
|
||||
home.removePassword.desc=Verwijder wachtwoordbeveiliging van je PDF-document.
|
||||
removePassword.tags=veilig,Decrypteren,beveiliging,wachtwoord verwijderen
|
||||
|
||||
home.compressPdfs.title=Comprimeren
|
||||
home.compressPdfs.desc=Comprimeer PDFs om hun bestandsgrootte te verkleinen.
|
||||
compressPdfs.tags=comprimeren,klein
|
||||
|
||||
|
||||
home.changeMetadata.title=Metadata wijzigen
|
||||
home.changeMetadata.desc=Wijzig/Verwijder/Voeg metadata toe van een PDF-document
|
||||
changeMetadata.tags=Titel,auteur,datum,creatie,tijd,uitgever,producent,statistieken
|
||||
|
||||
home.fileToPDF.title=Bestand naar PDF converteren
|
||||
home.fileToPDF.desc=Converteer bijna ieder bestand naar PDF (DOCX, PNG, XLS, PPT, TXT en meer)
|
||||
fileToPDF.tags=transformatie,formaat,document,foto,slide,tekst,conversie,kantoor,docs,word,excel,powerpoint
|
||||
|
||||
home.ocr.title=OCR / Scans opruimen
|
||||
home.ocr.desc=Ruim scans op, detecteert tekst van afbeeldingen in een PDF en voegt deze opnieuw toe als tekst.
|
||||
ocr.tags=herkenning,tekst,afbeelding,scan,lezen,identificeren,detectie,bewerkbaar
|
||||
|
||||
|
||||
home.extractImages.title=Afbeeldingen extraheren
|
||||
home.extractImages.desc=Extraheert alle afbeeldingen uit een PDF en slaat ze op in een zip
|
||||
extractImages.tags=foto,opslaan,archief,zip,vastleggen,plukken
|
||||
|
||||
home.pdfToPDFA.title=PDF naar PDF/A
|
||||
home.pdfToPDFA.desc=Converteer PDF naar PDF/A voor langdurige opslag
|
||||
pdfToPDFA.tags=archief,langdurig,standaard,conversie,opslag,bewaring
|
||||
|
||||
home.PDFToWord.title=PDF naar Word
|
||||
home.PDFToWord.desc=Converteer PDF naar Word-formaten (DOC, DOCX en ODT)
|
||||
PDFToWord.tags=doc,docx,odt,word,transformatie,formaat,conversie,kantoor,microsoft,docfile
|
||||
|
||||
home.PDFToPresentation.title=PDF naar Presentatie
|
||||
home.PDFToPresentation.desc=Converteer PDF naar Presentatie formaten (PPT, PPTX en ODP)
|
||||
PDFToPresentation.tags=slides,show,kantoor,microsoft
|
||||
|
||||
home.PDFToText.title=PDF naar RTF (Tekst)
|
||||
home.PDFToText.desc=Converteer PDF naar Tekst of RTF formaat
|
||||
PDFToText.tags=rijkformaat
|
||||
|
||||
home.PDFToHTML.title=PDF naar HTML
|
||||
home.PDFToHTML.desc=Converteer PDF naar HTML formaat
|
||||
PDFToHTML.tags=webinhoud,browser vriendelijk
|
||||
|
||||
|
||||
home.PDFToXML.title=PDF naar XML
|
||||
home.PDFToXML.desc=Converteer PDF naar XML formaat
|
||||
PDFToXML.tags=data-extractie,gestructureerd,code
|
||||
|
||||
home.ScannerImageSplit.title=Detecteer/Split gescande foto''s
|
||||
home.ScannerImageSplit.desc=Splits meerdere foto''s van binnen een foto/PDF
|
||||
ScannerImageSplit.tags=scheiden,auto-detecteren,scans,meer-foto,organiseren
|
||||
|
||||
home.sign.title=Ondertekenen
|
||||
home.sign.desc=Voegt handtekening toe aan PDF via tekenen, tekst of afbeelding
|
||||
sign.tags=autoriseren,initialen,getekende-handtekening,tekst-handtekening,afbeelding-handtekening
|
||||
|
||||
home.flatten.title=Platdrukken
|
||||
home.flatten.desc=Verwijder alle interactieve elementen en formulieren uit een PDF
|
||||
flatten.tags=statisch,deactiveren,niet-interactief,stroomlijnen
|
||||
|
||||
home.repair.title=Repareren
|
||||
home.repair.desc=Probeert een corrupt/beschadigd PDF te herstellen
|
||||
repair.tags=repareren,herstellen,correctie,terughalen
|
||||
|
||||
home.removeBlanks.title=Verwijder lege pagina''s
|
||||
home.removeBlanks.desc=Detecteert en verwijdert lege pagina''s uit een document
|
||||
removeBlanks.tags=opruimen,stroomlijnen,geen-inhoud,organiseren
|
||||
|
||||
home.compare.title=Vergelijken
|
||||
home.compare.desc=Vergelijkt en toont de verschillen tussen 2 PDF-documenten
|
||||
compare.tags=onderscheiden,contrasteren,veranderingen,analyse
|
||||
|
||||
home.certSign.title=Ondertekenen met certificaat
|
||||
home.certSign.desc=Ondertekent een PDF met een certificaat/sleutel (PEM/P12)
|
||||
certSign.tags=authenticeren,PEM,P12,officieel,versleutelen
|
||||
|
||||
home.pageLayout.title=Multi-pagina indeling
|
||||
home.pageLayout.desc=Voeg meerdere pagina''s van een PDF-document samen op één pagina
|
||||
pageLayout.tags=samenvoegen,composiet,enkel-zicht,organiseren
|
||||
|
||||
home.scalePages.title=Aanpassen paginaformaat/schaal
|
||||
home.scalePages.desc=Wijzig de grootte/schaal van een pagina en/of de inhoud ervan.
|
||||
scalePages.tags=resize,aanpassen,dimensie,aanpassen
|
||||
|
||||
home.pipeline.title=Pijplijn (Geavanceerd)
|
||||
home.pipeline.desc=Voer meerdere acties uit op PDF''s door pipelinescripts te definiëren
|
||||
pipeline.tags=automatiseren,volgorde,gescrript,batch-verwerking
|
||||
|
||||
home.add-page-numbers.title=Paginanummers toevoegen
|
||||
home.add-page-numbers.desc=Voeg paginanummers toe binnen het volledige document op een vastgestelde locatie
|
||||
add-page-numbers.tags=pagineren,labelen,organiseren,indexeren
|
||||
|
||||
home.auto-rename.title=Automatisch hernoemen PDF-bestand
|
||||
home.auto-rename.desc=Hernoemt automatisch een PDF-bestand op basis van de gedetecteerde header
|
||||
auto-rename.tags=auto-detecteren,op-header-gebaseerd,organiseren,herlabelen
|
||||
|
||||
home.adjust-contrast.title=Kleuren/Contrast aanpassen
|
||||
home.adjust-contrast.desc=Pas Contrast, Verzadiging en Helderheid van een PDF aan
|
||||
adjust-contrast.tags=kleur-correctie,afstemmen,aanpassen,verbeteren
|
||||
|
||||
home.crop.title=PDF bijsnijden
|
||||
home.crop.desc=Snijd een PDF bij om de grootte te verkleinen (behoudt tekst!)
|
||||
crop.tags=trimmen,verkleinen,bewerken,vorm
|
||||
|
||||
home.autoSplitPDF.title=Automatisch splitsen pagina''s
|
||||
home.autoSplitPDF.desc=Automatisch splitsen van gescande PDF met fysieke gescande paginasplitter QR-code
|
||||
autoSplitPDF.tags=QR-gebaseerd,scheiden,scan-segment,organiseren
|
||||
|
||||
home.sanitizePdf.title=Opschonen
|
||||
home.sanitizePdf.desc=Verwijder scripts en andere elementen uit PDF-bestanden
|
||||
sanitizePdf.tags=schoonmaken,veilig,veilig,bedreigingen verwijderen
|
||||
|
||||
home.URLToPDF.title=URL/Website naar PDF
|
||||
home.URLToPDF.desc=Zet http(s)URL om naar PDF
|
||||
URLToPDF.tags=web-capture,pagina opslaan,web-naar-doc,archief
|
||||
|
||||
home.HTMLToPDF.title=HTML naar PDF
|
||||
home.HTMLToPDF.desc=Zet HTML-bestand of zip om naar PDF
|
||||
HTMLToPDF.tags=markup,web-inhoud,transformatie,omzetten
|
||||
|
||||
|
||||
home.MarkdownToPDF.title=Markdown naar PDF
|
||||
home.MarkdownToPDF.desc=Zet Markdown-bestand om naar PDF
|
||||
MarkdownToPDF.tags=markup,web-inhoud,transformatie,omzetten
|
||||
|
||||
|
||||
home.getPdfInfo.title=Haal ALLE informatie op over PDF
|
||||
home.getPdfInfo.desc=Haalt alle mogelijke informatie op van PDF''s
|
||||
getPdfInfo.tags=informatie,data,statistieken
|
||||
|
||||
|
||||
home.extractPage.title=Pagina(''s) extraheren
|
||||
home.extractPage.desc=Extraheert geselecteerde pagina''s uit PDF
|
||||
extractPage.tags=extraheren
|
||||
|
||||
|
||||
home.PdfToSinglePage.title=PDF naar één grote pagina
|
||||
home.PdfToSinglePage.desc=Voegt alle PDF-pagina''s samen tot één grote pagina
|
||||
PdfToSinglePage.tags=één pagina
|
||||
|
||||
|
||||
home.showJS.title=Toon Javascript
|
||||
home.showJS.desc=Zoekt en toont ieder script dat in een PDF is geïnjecteerd
|
||||
showJS.tags=JS
|
||||
|
||||
home.autoRedact.title=Auto Redact
|
||||
home.autoRedact.desc=Auto Redacts(Blacks out) text in a PDF based on input text
|
||||
showJS.tags=JS
|
||||
|
||||
###########################
|
||||
# #
|
||||
# WEB PAGES #
|
||||
# #
|
||||
###########################
|
||||
#login
|
||||
login.title=Sign in
|
||||
login.signin=Sign in
|
||||
login.rememberme=Remember me
|
||||
login.invalid=Invalid username or password.
|
||||
login.locked=Your account has been locked.
|
||||
login.signinTitle=Please sign in
|
||||
|
||||
|
||||
#auto-redact
|
||||
autoRedact.title=Auto Redact
|
||||
autoRedact.header=Auto Redact
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
autoRedact.colorLabel=Colour
|
||||
autoRedact.textsToRedactLabel=Text to Redact (line-separated)
|
||||
autoRedact.textsToRedactPlaceholder=e.g. \nConfidential \nTop-Secret
|
||||
autoRedact.useRegexLabel=Use Regex
|
||||
autoRedact.wholeWordSearchLabel=Whole Word Search
|
||||
autoRedact.customPaddingLabel=Custom Extra Padding
|
||||
autoRedact.convertPDFToImageLabel=Convert PDF to PDF-Image (Used to remove text behind the box)
|
||||
autoRedact.submitButton=Submit
|
||||
|
||||
|
||||
#showJS
|
||||
showJS.title=Toon Javascript
|
||||
showJS.header=Toon Javascript
|
||||
showJS.downloadJS=Download Javascript
|
||||
showJS.submit=Toon
|
||||
|
||||
|
||||
#pdfToSinglePage
|
||||
pdfToSinglePage.title=PDF naar enkele pagina
|
||||
pdfToSinglePage.header=PDF naar enkele pagina
|
||||
pdfToSinglePage.submit=Converteren naar enkele pagina
|
||||
|
||||
|
||||
#pageExtracter
|
||||
pageExtracter.title=Pagina''s extraheren
|
||||
pageExtracter.header=Pagina''s extraheren
|
||||
pageExtracter.submit=Extraheren
|
||||
|
||||
|
||||
#getPdfInfo
|
||||
getPdfInfo.title=Informatie over PDF ophalen
|
||||
getPdfInfo.header=Informatie over PDF ophalen
|
||||
getPdfInfo.submit=Haal informatie op
|
||||
getPdfInfo.downloadJson=Download JSON
|
||||
|
||||
|
||||
#markdown-to-pdf
|
||||
MarkdownToPDF.title=Markdown naar PDF
|
||||
MarkdownToPDF.header=Markdown naar PDF
|
||||
MarkdownToPDF.submit=Converteren
|
||||
MarkdownToPDF.help=in ontwikkeling
|
||||
MarkdownToPDF.credit=Gebruikt WeasyPrint
|
||||
|
||||
|
||||
|
||||
#url-to-pdf
|
||||
URLToPDF.title=URL naar PDF
|
||||
URLToPDF.header=URL naar PDF
|
||||
URLToPDF.submit=Converteren
|
||||
URLToPDF.credit=Gebruikt WeasyPrint
|
||||
|
||||
|
||||
#html-to-pdf
|
||||
HTMLToPDF.title=HTML naar PDF
|
||||
HTMLToPDF.header=HTML naar PDF
|
||||
HTMLToPDF.help=Accepteert HTML-bestanden en ZIP''s die html/css/afbeeldingen etc. bevatten
|
||||
HTMLToPDF.submit=Converteren
|
||||
HTMLToPDF.credit=Gebruikt WeasyPrint
|
||||
|
||||
|
||||
#sanitizePDF
|
||||
sanitizePDF.title=PDF opschonen
|
||||
sanitizePDF.header=Een PDF-bestand opschonen
|
||||
sanitizePDF.selectText.1=Verwijder Javascript-acties
|
||||
sanitizePDF.selectText.2=Verwijder ingebedde bestanden
|
||||
sanitizePDF.selectText.3=Verwijder metadata
|
||||
sanitizePDF.selectText.4=Verwijder links
|
||||
sanitizePDF.selectText.5=Verwijder lettertypen
|
||||
sanitizePDF.submit=PDF opschonen
|
||||
|
||||
|
||||
#addPageNumbers
|
||||
addPageNumbers.title=Paginanummers toevoegen
|
||||
addPageNumbers.header=Paginanummers toevoegen
|
||||
addPageNumbers.selectText.1=Selecteer PDF-bestand:
|
||||
addPageNumbers.selectText.2=Margegrootte
|
||||
addPageNumbers.selectText.3=Positie
|
||||
addPageNumbers.selectText.4=Startnummer
|
||||
addPageNumbers.selectText.5=Pagina''s om te nummeren
|
||||
addPageNumbers.selectText.6=Aangepaste tekst
|
||||
addPageNumbers.customTextDesc=Custom Text
|
||||
addPageNumbers.numberPagesDesc=Which pages to number, default 'all', also accepts 1-5 or 2,5,9 etc
|
||||
addPageNumbers.customNumberDesc=Defaults to {n}, also accepts 'Page {n} of {total}', 'Text-{n}', '{filename}-{n}
|
||||
addPageNumbers.submit=Paginanummers toevoegen
|
||||
|
||||
|
||||
#auto-rename
|
||||
auto-rename.title=Automatisch hernoemen
|
||||
auto-rename.header=PDF automatisch hernoemen
|
||||
auto-rename.submit=Automatisch hernoemen
|
||||
|
||||
|
||||
#adjustContrast
|
||||
adjustContrast.title=Contrast aanpassen
|
||||
adjustContrast.header=Contrast aanpassen
|
||||
adjustContrast.contrast=Contrast:
|
||||
adjustContrast.brightness=Helderheid:
|
||||
adjustContrast.saturation=Verzadiging:
|
||||
adjustContrast.download=Downloaden
|
||||
|
||||
|
||||
#crop
|
||||
crop.title=Bijwerken
|
||||
crop.header=Afbeelding bijwerken
|
||||
crop.submit=Indienen
|
||||
|
||||
|
||||
#autoSplitPDF
|
||||
autoSplitPDF.title=PDF automatisch splitsen
|
||||
autoSplitPDF.header=PDF automatisch splitsen
|
||||
autoSplitPDF.description=Print, Voeg in, Scan, upload, en laat ons je documenten automatisch scheiden. Geen handmatig sorteerwerk nodig.
|
||||
autoSplitPDF.selectText.1=Print enkele scheidingsbladen van hieronder (Zwart-wit is prima).
|
||||
autoSplitPDF.selectText.2=Scan al je documenten tegelijk door het scheidingsblad ertussen te plaatsen.
|
||||
autoSplitPDF.selectText.3=Upload het enkele grote gescande PDF-bestand en laat Stirling PDF de rest afhandelen.
|
||||
autoSplitPDF.selectText.4=Scheidingspagina''s worden automatisch gedetecteerd en verwijderd, wat een net einddocument garandeert.
|
||||
autoSplitPDF.formPrompt=Dien PDF in met Stirling-PDF Pagina-scheiders:
|
||||
autoSplitPDF.duplexMode=Duplex Modus (voor- en achterkant scannen)
|
||||
autoSplitPDF.dividerDownload1=Download 'Auto Splitter Divider (minimal).pdf'
|
||||
autoSplitPDF.dividerDownload2=Download 'Auto Splitter Divider (with instructions).pdf'
|
||||
autoSplitPDF.submit=Indienen
|
||||
|
||||
|
||||
#pipeline
|
||||
pipeline.title=Pijplijn
|
||||
|
||||
|
||||
#pageLayout
|
||||
pageLayout.title=Meerdere pagina indeling
|
||||
pageLayout.header=Meerdere pagina indeling
|
||||
pageLayout.pagesPerSheet=Pagina''s per vel:
|
||||
pageLayout.submit=Indienen
|
||||
|
||||
|
||||
#scalePages
|
||||
scalePages.title=Pagina-schaal aanpassen
|
||||
scalePages.header=Pagina-schaal aanpassen
|
||||
scalePages.pageSize=Grootte van een pagina van het document.
|
||||
scalePages.scaleFactor=Zoomniveau (uitsnede) van een pagina.
|
||||
scalePages.submit=Indienen
|
||||
|
||||
|
||||
#certSign
|
||||
certSign.title=Certificaat ondertekening
|
||||
certSign.header=Onderteken een PDF met je certificaat (in ontwikkeling)
|
||||
certSign.selectPDF=Selecteer een PDF-bestand voor ondertekening:
|
||||
certSign.selectKey=Selecteer je privésleutelbestand (PKCS#8 formaat, kan .pem of .der zijn):
|
||||
certSign.selectCert=Selecteer je certificaatbestand (X.509 formaat, kan .pem of .der zijn):
|
||||
certSign.selectP12=Selecteer je PKCS#12 Sleutelopslagbestand (.p12 of .pfx) (Optioneel, indien verstrekt, moet het je privésleutel en certificaat bevatten):
|
||||
certSign.certType=Certificaattype
|
||||
certSign.password=Voer je sleutelopslag of privésleutel wachtwoord in (indien van toepassing):
|
||||
certSign.showSig=Toon handtekening
|
||||
certSign.reason=Reden
|
||||
certSign.location=Locatie
|
||||
certSign.name=Naam
|
||||
certSign.submit=PDF ondertekenen
|
||||
|
||||
|
||||
#removeBlanks
|
||||
removeBlanks.title=Verwijder blanco''s
|
||||
removeBlanks.header=Verwijder lege pagina''s
|
||||
removeBlanks.threshold=Pixel witheid drempel:
|
||||
removeBlanks.thresholdDesc=Drempel voor het bepalen hoe wit een witte pixel moet zijn om als ''Wit'' te worden geclassificeerd. 0 = Zwart, 255 zuiver wit.
|
||||
removeBlanks.whitePercent=Wit percentage (%):
|
||||
removeBlanks.whitePercentDesc=Percentage van de pagina dat ''witte'' pixels moet zijn om verwijderd te worden
|
||||
removeBlanks.submit=Blanco''s verwijderen
|
||||
|
||||
|
||||
#compare
|
||||
compare.title=Vergelijken
|
||||
compare.header=PDF''s vergelijken
|
||||
compare.document.1=Document 1
|
||||
compare.document.2=Document 2
|
||||
compare.submit=Vergelijken
|
||||
|
||||
|
||||
#sign
|
||||
sign.title=Ondertekenen
|
||||
sign.header=PDF''s ondertekenen
|
||||
sign.upload=Upload afbeelding
|
||||
sign.draw=Handtekening tekenen
|
||||
sign.text=Tekstinvoer
|
||||
sign.clear=Wissen
|
||||
sign.add=Toevoegen
|
||||
|
||||
|
||||
#repair
|
||||
repair.title=Repareren
|
||||
repair.header=PDF''s repareren
|
||||
repair.submit=Repareren
|
||||
|
||||
|
||||
#flatten
|
||||
flatten.title=Afvlakken
|
||||
flatten.header=PDF''s afvlakken
|
||||
flatten.submit=Afvlakken
|
||||
|
||||
|
||||
#ScannerImageSplit
|
||||
ScannerImageSplit.selectText.1=Hoek drempel:
|
||||
ScannerImageSplit.selectText.2=Stelt de minimale absolute hoek in die nodig is om de afbeelding te roteren (standaard: 10).
|
||||
ScannerImageSplit.selectText.3=Tolerantie:
|
||||
ScannerImageSplit.selectText.4=Bepaalt het bereik van kleurvariatie rond de geschatte achtergrondkleur (standaard: 30).
|
||||
ScannerImageSplit.selectText.5=Minimum oppervlakte:
|
||||
ScannerImageSplit.selectText.6=Stelt de minimale oppervlakte drempel in voor een foto (standaard: 10000).
|
||||
ScannerImageSplit.selectText.7=Minimum contour oppervlakte:
|
||||
ScannerImageSplit.selectText.8=Stelt de minimale contour oppervlakte drempel in voor een foto
|
||||
ScannerImageSplit.selectText.9=Randgrootte:
|
||||
ScannerImageSplit.selectText.10=Stelt de grootte van de toegevoegde en verwijderde rand in om witte randen in de uitvoer te voorkomen (standaard: 1).
|
||||
|
||||
|
||||
#OCR
|
||||
ocr.title=OCR / Scan opruimen
|
||||
ocr.header=Scans opruimen / OCR (Optical Character Recognition)
|
||||
ocr.selectText.1=Selecteer talen die binnen de PDF gedetecteerd moeten worden (De vermelde zijn de momenteel gedetecteerde):
|
||||
ocr.selectText.2=Produceer tekstbestand met OCR-tekst naast de OCR''d PDF
|
||||
ocr.selectText.3=Corrigeer pagina''s die onder een scheve hoek zijn gescand door ze terug te draaien
|
||||
ocr.selectText.4=Maak de pagina schoon, zodat het minder waarschijnlijk is dat OCR tekst in achtergrondruis vindt. (Geen uitvoerverandering)
|
||||
ocr.selectText.5=Maak de pagina schoon zodat OCR waarschijnlijk geen tekst in achtergrondruis vindt, behoudt opruiming in uitvoer.
|
||||
ocr.selectText.6=Negeert pagina''s met interactieve tekst, OCR''s alleen pagina''s die afbeeldingen zijn
|
||||
ocr.selectText.7=Forceer OCR, zal elke pagina OCR''en en alle originele tekstelementen verwijderen
|
||||
ocr.selectText.8=Normaal (Zal een fout geven als de PDF tekst bevat)
|
||||
ocr.selectText.9=Aanvullende instellingen
|
||||
ocr.selectText.10=OCR-modus
|
||||
ocr.selectText.11=Verwijder afbeeldingen na OCR (Verwijdert ALLE afbeeldingen, alleen nuttig als onderdeel van conversiestap)
|
||||
ocr.selectText.12=Render Type (Geavanceerd)
|
||||
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.submit=Verwerk PDF met OCR
|
||||
|
||||
|
||||
#extractImages
|
||||
extractImages.title=Afbeeldingen extraheren
|
||||
extractImages.header=Afbeeldingen extraheren
|
||||
extractImages.selectText=Selecteer het beeldformaat voor geëxtraheerde afbeeldingen
|
||||
extractImages.submit=Extraheer
|
||||
|
||||
|
||||
#File to PDF
|
||||
fileToPDF.title=Bestand naar PDF
|
||||
fileToPDF.header=Zet elk bestand om naar PDF
|
||||
fileToPDF.credit=Deze service gebruikt LibreOffice en Unoconv voor bestandsconversie.
|
||||
fileToPDF.supportedFileTypes=Ondersteunde bestandstypen zijn hieronder opgenomen, maar raadpleeg voor een volledige lijst met ondersteunde formaten de LibreOffice-documentatie
|
||||
fileToPDF.submit=Omzetten naar PDF
|
||||
|
||||
|
||||
#compress
|
||||
compress.title=Comprimeren
|
||||
compress.header=PDF comprimeren
|
||||
compress.credit=Deze functie gebruikt Ghostscript voor PDF Compressie/Optimalisatie.
|
||||
compress.selectText.1=Handmatige modus - Van 1 tot 4
|
||||
compress.selectText.2=Optimalisatieniveau:
|
||||
compress.selectText.3=4 (Verschrikkelijk voor tekstafbeeldingen)
|
||||
compress.selectText.4=Automatische modus - Past kwaliteit automatisch aan om PDF naar exacte grootte te krijgen
|
||||
compress.selectText.5=Verwachte PDF-grootte (bijv. 25MB, 10.8MB, 25KB)
|
||||
compress.submit=Comprimeren
|
||||
|
||||
|
||||
#Add image
|
||||
addImage.title=Afbeelding toevoegen
|
||||
addImage.header=Afbeelding aan PDF toevoegen
|
||||
addImage.everyPage=Elke pagina?
|
||||
addImage.upload=Afbeelding toevoegen
|
||||
addImage.submit=Afbeelding toevoegen
|
||||
|
||||
|
||||
#merge
|
||||
merge.title=Samenvoegen
|
||||
merge.header=Meerdere PDF''s samenvoegen (2+)
|
||||
merge.sortByName=Sorteer op naam
|
||||
merge.sortByDate=Sorteer op datum
|
||||
merge.submit=Samenvoegen
|
||||
|
||||
|
||||
#pdfOrganiser
|
||||
pdfOrganiser.title=Pagina organisator
|
||||
pdfOrganiser.header=PDF pagina organisator
|
||||
pdfOrganiser.submit=Pagina''s herschikken
|
||||
|
||||
|
||||
#multiTool
|
||||
multiTool.title=PDF Multitool
|
||||
multiTool.header=PDF Multitool
|
||||
|
||||
|
||||
#pageRemover
|
||||
pageRemover.title=Pagina verwijderaar
|
||||
pageRemover.header=PDF pagina verwijderaar
|
||||
pageRemover.pagesToDelete=Te verwijderen pagina''s (Voer een door komma''s gescheiden lijst met paginanummers in):
|
||||
pageRemover.submit=Pagina''s verwijderen
|
||||
|
||||
|
||||
#rotate
|
||||
rotate.title=PDF roteren
|
||||
rotate.header=PDF roteren
|
||||
rotate.selectAngle=Selecteer rotatiehoek (in veelvouden van 90 graden):
|
||||
rotate.submit=Roteren
|
||||
|
||||
|
||||
#merge
|
||||
split.title=PDF splitsen
|
||||
split.header=PDF splitsen
|
||||
split.desc.1=De nummers die je kiest zijn de paginanummers waarop je een splitsing wilt uitvoeren
|
||||
split.desc.2=Als zodanig selecteren van 1,3,7-8 zou een 10 pagina''s tellend document splitsen in 6 aparte PDF''s met:
|
||||
split.desc.3=Document #1: Pagina 1
|
||||
split.desc.4=Document #2: Pagina 2 en 3
|
||||
split.desc.5=Document #3: Pagina 4, 5 en 6
|
||||
split.desc.6=Document #4: Pagina 7
|
||||
split.desc.7=Document #5: Pagina 8
|
||||
split.desc.8=Document #6: Pagina 9 en 10
|
||||
split.splitPages=Voer pagina''s in om op te splitsen:
|
||||
split.submit=Splitsen
|
||||
|
||||
|
||||
#merge
|
||||
imageToPDF.title=Afbeelding naar PDF
|
||||
imageToPDF.header=Afbeelding naar PDF
|
||||
imageToPDF.submit=Omzetten
|
||||
imageToPDF.selectText.1=Uitrekken om te passen
|
||||
imageToPDF.selectText.2=PDF automatisch draaien
|
||||
imageToPDF.selectText.3=Meervoudige bestandslogica (Alleen ingeschakeld bij werken met meerdere afbeeldingen)
|
||||
imageToPDF.selectText.4=Voeg samen in één PDF
|
||||
imageToPDF.selectText.5=Zet om naar afzonderlijke PDF''s
|
||||
|
||||
|
||||
#pdfToImage
|
||||
pdfToImage.title=PDF naar afbeelding
|
||||
pdfToImage.header=PDF naar afbeelding
|
||||
pdfToImage.selectText=Afbeeldingsformaat
|
||||
pdfToImage.singleOrMultiple=Resultaattype van pagina naar afbeelding
|
||||
pdfToImage.single=Eén grote afbeelding die alle pagina''s combineert
|
||||
pdfToImage.multi=Meerdere afbeeldingen, één afbeelding per pagina
|
||||
pdfToImage.colorType=Kleurtype
|
||||
pdfToImage.color=Kleur
|
||||
pdfToImage.grey=Grijstinten
|
||||
pdfToImage.blackwhite=Zwart en wit (kan data verliezen!)
|
||||
pdfToImage.submit=Omzetten
|
||||
|
||||
|
||||
#addPassword
|
||||
addPassword.title=Wachtwoord toevoegen
|
||||
addPassword.header=Wachtwoord toevoegen (Versleutelen)
|
||||
addPassword.selectText.1=Selecteer PDF om te versleutelen
|
||||
addPassword.selectText.2=Gebruikerswachtwoord
|
||||
addPassword.selectText.3=Versleutelingssleutellengte
|
||||
addPassword.selectText.4=Hogere waarden zijn sterker, maar lagere waarden hebben een betere compatibiliteit.
|
||||
addPassword.selectText.5=In te stellen rechten (Aanbevolen om te gebruiken samen met eigenaarswachtwoord)
|
||||
addPassword.selectText.6=Voorkomen van documentassemblage
|
||||
addPassword.selectText.7=Voorkomen van inhoudsextractie
|
||||
addPassword.selectText.8=Voorkomen van extractie voor toegankelijkheid
|
||||
addPassword.selectText.9=Voorkomen van invullen van formulier
|
||||
addPassword.selectText.10=Voorkomen van wijziging
|
||||
addPassword.selectText.11=Voorkomen van annotatiewijziging
|
||||
addPassword.selectText.12=Voorkomen van afdrukken
|
||||
addPassword.selectText.13=Voorkomen van afdrukken in verschillende formaten
|
||||
addPassword.selectText.14=Eigenaarswachtwoord
|
||||
addPassword.selectText.15=Beperkt wat gedaan kan worden met het document nadat het is geopend (Niet ondersteund door alle lezers)
|
||||
addPassword.selectText.16=Beperkt het openen van het document zelf
|
||||
addPassword.submit=Versleutelen
|
||||
|
||||
|
||||
#watermark
|
||||
watermark.title=Watermerk toevoegen
|
||||
watermark.header=Watermerk toevoegen
|
||||
watermark.selectText.1=Selecteer PDF om watermerk toe te voegen:
|
||||
watermark.selectText.2=Watermerk tekst:
|
||||
watermark.selectText.3=Tekengrootte:
|
||||
watermark.selectText.4=Rotatie (0-360):
|
||||
watermark.selectText.5=breedteSpacer (Ruimte tussen elk watermerk horizontaal):
|
||||
watermark.selectText.6=hoogteSpacer (Ruimte tussen elk watermerk verticaal):
|
||||
watermark.selectText.7=Transparantie (0% - 100%):
|
||||
watermark.selectText.8=Type watermerk:
|
||||
watermark.selectText.9=Watermerk afbeelding:
|
||||
watermark.submit=Watermerk toevoegen
|
||||
|
||||
|
||||
#Change permissions
|
||||
permissions.title=Rechten wijzigen
|
||||
permissions.header=Rechten wijzigen
|
||||
permissions.warning=Let op: om deze rechten onveranderlijk te maken, wordt aanbevolen om ze met een wachtwoord in te stellen via de add-password pagina.
|
||||
permissions.selectText.1=Selecteer PDF om rechten te wijzigen
|
||||
permissions.selectText.2=In te stellen rechten
|
||||
permissions.selectText.3=Voorkom samenvoegen van document
|
||||
permissions.selectText.4=Voorkom inhoudsextractie
|
||||
permissions.selectText.5=Voorkom extractie voor toegankelijkheid
|
||||
permissions.selectText.6=Voorkom invullen van formulier
|
||||
permissions.selectText.7=Voorkom wijziging
|
||||
permissions.selectText.8=Voorkom annotatie wijziging
|
||||
permissions.selectText.9=Voorkom afdrukken
|
||||
permissions.selectText.10=Voorkom afdrukken in verschillende formaten
|
||||
permissions.submit=Wijzigen
|
||||
|
||||
|
||||
#remove password
|
||||
removePassword.title=Wachtwoord verwijderen
|
||||
removePassword.header=Wachtwoord verwijderen (Decrypteren)
|
||||
removePassword.selectText.1=Selecteer PDF om te decrypteren
|
||||
removePassword.selectText.2=Wachtwoord
|
||||
removePassword.submit=Verwijderen
|
||||
|
||||
|
||||
#changeMetadata
|
||||
changeMetadata.title=Titel:
|
||||
changeMetadata.header=Metadata wijzigen
|
||||
changeMetadata.selectText.1=Pas de variabelen aan die je wilt wijzigen
|
||||
changeMetadata.selectText.2=Verwijder alle metadata
|
||||
changeMetadata.selectText.3=Toon aangepaste metadata:
|
||||
changeMetadata.author=Auteur:
|
||||
changeMetadata.creationDate=Aanmaakdatum (yyyy/MM/dd HH:mm:ss):
|
||||
changeMetadata.creator=Maker:
|
||||
changeMetadata.keywords=Trefwoorden:
|
||||
changeMetadata.modDate=Wijzigingsdatum (yyyy/MM/dd HH:mm:ss):
|
||||
changeMetadata.producer=Producent:
|
||||
changeMetadata.subject=Onderwerp:
|
||||
changeMetadata.title=Titel:
|
||||
changeMetadata.trapped=Vastgezet:
|
||||
changeMetadata.selectText.4=Overige metadata:
|
||||
changeMetadata.selectText.5=Voeg aangepaste metadata-invoer toe
|
||||
changeMetadata.submit=Wijzigen
|
||||
|
||||
|
||||
#xlsToPdf
|
||||
xlsToPdf.title=Excel naar PDF
|
||||
xlsToPdf.header=Excel naar PDF
|
||||
xlsToPdf.selectText.1=Selecteer XLS of XLSX Excel-blad om te converteren
|
||||
xlsToPdf.convert=Converteren
|
||||
|
||||
|
||||
#pdfToPDFA
|
||||
pdfToPDFA.title=PDF naar PDF/A
|
||||
pdfToPDFA.header=PDF naar PDF/A
|
||||
pdfToPDFA.credit=Deze service gebruikt OCRmyPDF voor PDF/A-conversie
|
||||
pdfToPDFA.submit=Converteren
|
||||
|
||||
|
||||
#PDFToWord
|
||||
PDFToWord.title=PDF naar Word
|
||||
PDFToWord.header=PDF naar Word
|
||||
PDFToWord.selectText.1=Uitvoerbestandsformaat
|
||||
PDFToWord.credit=Deze service gebruikt LibreOffice voor bestandsconversie.
|
||||
PDFToWord.submit=Converteren
|
||||
|
||||
|
||||
#PDFToPresentation
|
||||
PDFToPresentation.title=PDF naar Presentatie
|
||||
PDFToPresentation.header=PDF naar Presentatie
|
||||
PDFToPresentation.selectText.1=Uitvoerbestandsformaat
|
||||
PDFToPresentation.credit=Deze service gebruikt LibreOffice voor bestandsconversie.
|
||||
PDFToPresentation.submit=Converteren
|
||||
|
||||
|
||||
#PDFToText
|
||||
PDFToText.title=PDF naar RTF (Tekst)
|
||||
PDFToText.header=PDF naar RTF (Tekst)
|
||||
PDFToText.selectText.1=Uitvoerbestandsformaat
|
||||
PDFToText.credit=Deze service gebruikt LibreOffice voor bestandsconversie.
|
||||
PDFToText.submit=Converteren
|
||||
|
||||
|
||||
#PDFToHTML
|
||||
PDFToHTML.title=PDF naar HTML
|
||||
PDFToHTML.header=PDF naar HTML
|
||||
PDFToHTML.credit=Deze service gebruikt LibreOffice voor bestandsconversie.
|
||||
PDFToHTML.submit=Converteren
|
||||
|
||||
|
||||
#PDFToXML
|
||||
PDFToXML.title=PDF naar XML
|
||||
PDFToXML.header=PDF naar XML
|
||||
PDFToXML.credit=Deze service gebruikt LibreOffice voor bestandsconversie.
|
||||
PDFToXML.submit=Converteren
|
||||
@@ -31,6 +31,23 @@ sizes.medium=Medium
|
||||
sizes.large=Large
|
||||
sizes.x-large=X-Large
|
||||
error.pdfPassword=Dokument PDF jest zabezpieczony hasłem, musisz podać prawidłowe hasło.
|
||||
delete=Delete
|
||||
username=Username
|
||||
password=Password
|
||||
welcome=Welcome
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
property=Property
|
||||
black=Black
|
||||
white=White
|
||||
red=Red
|
||||
green=Green
|
||||
blue=Blue
|
||||
custom=Custom...
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#############
|
||||
@@ -54,6 +71,41 @@ settings.downloadOption.1=Otwórz w tym samym oknie
|
||||
settings.downloadOption.2=Otwórz w nowym oknie
|
||||
settings.downloadOption.3=Pobierz plik
|
||||
settings.zipThreshold=Spakuj pliki, gdy liczba pobranych plików przekroczy
|
||||
settings.signOut=Sign Out
|
||||
settings.accountSettings=Account Settings
|
||||
|
||||
account.title=Account Settings
|
||||
account.accountSettings=Account Settings
|
||||
account.adminSettings=Admin Settings - View and Add Users
|
||||
account.userControlSettings=User Control Settings
|
||||
account.changeUsername=Change Username
|
||||
account.changeUsername=Change Username
|
||||
account.password=Confirmation Password
|
||||
account.oldPassword=Old password
|
||||
account.newPassword=New Password
|
||||
account.changePassword=Change Password
|
||||
account.confirmNewPassword=Confirm New Password
|
||||
account.signOut=Sign Out
|
||||
account.yourApiKey=Your API Key
|
||||
account.syncTitle=Sync browser settings with Account
|
||||
account.settingsCompare=Settings Comparison:
|
||||
account.property=Property
|
||||
account.webBrowserSettings=Web Browser Setting
|
||||
account.syncToBrowser=Sync Account -> Browser
|
||||
account.syncToAccount=Sync Account <- Browser
|
||||
|
||||
|
||||
adminUserSettings.title=User Control Settings
|
||||
adminUserSettings.header=Admin User Control Settings
|
||||
adminUserSettings.admin=Admin
|
||||
adminUserSettings.user=User
|
||||
adminUserSettings.addUser=Add New User
|
||||
adminUserSettings.roles=Roles
|
||||
adminUserSettings.role=Role
|
||||
adminUserSettings.actions=Actions
|
||||
adminUserSettings.apiUser=Limited API User
|
||||
adminUserSettings.webOnlyUser=Web Only User
|
||||
adminUserSettings.submit=Save User
|
||||
|
||||
#############
|
||||
# HOME-PAGE #
|
||||
@@ -71,296 +123,264 @@ merge.tags=merge,Page operations,Back end,server side
|
||||
|
||||
home.split.title=Podziel
|
||||
home.split.desc=Podziel dokument PDF na wiele dokumentów
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
split.tags=Page operations,divide,Multi Page,cut,server side
|
||||
split.tags=Page operations,divide,Multi Page,cut,server side
|
||||
|
||||
home.rotate.title=Obróć
|
||||
home.rotate.desc=Łatwo obracaj dokumenty PDF.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
rotate.tags=server side
|
||||
|
||||
|
||||
home.imageToPdf.title=Obraz na PDF
|
||||
home.imageToPdf.desc=Konwertuj obraz (PNG, JPEG, GIF) do dokumentu PDF.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
imageToPdf.tags=conversion,img,jpg,picture,photo
|
||||
|
||||
home.pdfToImage.title=PDF na Obraz
|
||||
home.pdfToImage.desc=Konwertuj plik PDF na obraz (PNG, JPEG, GIF).
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
pdfToImage.tags=conversion,img,jpg,picture,photo
|
||||
|
||||
home.pdfOrganiser.title=Uporządkuj
|
||||
home.pdfOrganiser.desc=Usuń/Zmień kolejność stron w dowolnej kolejności
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
pdfOrganiser.tags=duplex,even,odd,sort,move
|
||||
|
||||
|
||||
home.addImage.title=Dodaj obraz
|
||||
home.addImage.desc=Dodaje obraz w wybranym miejscu w dokumencie PDF (moduł w budowie)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
addImage.tags=img,jpg,picture,photo
|
||||
|
||||
home.watermark.title=Dodaj znak wodny
|
||||
home.watermark.desc=Dodaj niestandardowy znak wodny do dokumentu PDF.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
watermark.tags=Text,repeating,label,own,copyright,trademark,img,jpg,picture,photo
|
||||
|
||||
home.permissions.title=Zmień uprawnienia
|
||||
home.permissions.desc=Zmień uprawnienia dokumentu PDF
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
permissions.tags=read,write,edit,print
|
||||
|
||||
|
||||
home.removePages.title=Usuń
|
||||
home.removePages.desc=Usuń niechciane strony z dokumentu PDF.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
removePages.tags=Remove pages,delete pages
|
||||
|
||||
home.addPassword.title=Dodaj hasło
|
||||
home.addPassword.desc=Zaszyfruj dokument PDF za pomocą hasła.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
addPassword.tags=secure,security
|
||||
|
||||
home.removePassword.title=Usuń hasło
|
||||
home.removePassword.desc=Usuń ochronę hasłem z dokumentu PDF.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
removePassword.tags=secure,Decrypt,security,unpassword,delete password
|
||||
|
||||
home.compressPdfs.title=Kompresuj
|
||||
home.compressPdfs.desc=Kompresuj dokumenty PDF, aby zmniejszyć ich rozmiar.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
compressPdfs.tags=squish,small,tiny
|
||||
|
||||
|
||||
home.changeMetadata.title=Zmień metadane
|
||||
home.changeMetadata.desc=Zmień/Usuń/Dodaj metadane w dokumencie PDF
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
changeMetadata.tags==Title,author,date,creation,time,publisher,producer,stats
|
||||
|
||||
home.fileToPDF.title=Konwertuj plik do PDF
|
||||
home.fileToPDF.desc=Konwertuj dowolny plik do dokumentu PDF (DOCX, PNG, XLS, PPT, TXT i więcej)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
fileToPDF.tags=transformation,format,document,picture,slide,text,conversion,office,docs,word,excel,powerpoint
|
||||
|
||||
home.ocr.title=OCR / Zamiana na tekst
|
||||
home.ocr.desc=OCR skanuje i wykrywa tekst z obrazów w dokumencie PDF i zamienia go na tekst.
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
ocr.tags=recognition,text,image,scan,read,identify,detection,editable
|
||||
|
||||
|
||||
home.extractImages.title=Wyodrębnij obrazy
|
||||
home.extractImages.desc=Wyodrębnia wszystkie obrazy z dokumentu PDF i zapisuje je w wybranym formacie
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
extractImages.tags=picture,photo,save,archive,zip,capture,grab
|
||||
|
||||
home.pdfToPDFA.title=PDF na PDF/A
|
||||
home.pdfToPDFA.desc=Konwertuj dokument PDF na PDF/A w celu długoterminowego przechowywania
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation
|
||||
|
||||
home.PDFToWord.title=PDF na Word
|
||||
home.PDFToWord.desc=Konwertuj dokument PDF na formaty Word (DOC, DOCX i ODT)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
PDFToWord.tags=doc,docx,odt,word,transformation,format,conversion,office,microsoft,docfile
|
||||
|
||||
home.PDFToPresentation.title=PDF na Prezentację
|
||||
home.PDFToPresentation.desc=Konwertuj dokument PDF na formaty prezentacji (PPT, PPTX i ODP)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
PDFToPresentation.tags=slides,show,office,microsoft
|
||||
|
||||
home.PDFToText.title=PDF na Tekst/RTF
|
||||
home.PDFToText.desc=Konwertuj dokument PDF na tekst lub format RTF
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
PDFToText.tags=richformat,richtextformat,rich text format
|
||||
|
||||
home.PDFToHTML.title=PDF na HTML
|
||||
home.PDFToHTML.desc=Konwertuj dokument PDF na format HTML
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
PDFToHTML.tags=web content,browser friendly
|
||||
|
||||
|
||||
home.PDFToXML.title=PDF na XML
|
||||
home.PDFToXML.desc=Konwertuj dokument PDF na format XML
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
PDFToXML.tags=data-extraction,structured-content,interop,transformation,convert
|
||||
|
||||
home.ScannerImageSplit.title=Wykryj/Podziel zeskanowane zdjęcia
|
||||
home.ScannerImageSplit.desc=Podziel na wiele zdjęć z jednego zdjęcia/PDF
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
ScannerImageSplit.tags=separate,auto-detect,scans,multi-photo,organize
|
||||
|
||||
home.sign.title=Podpis
|
||||
home.sign.desc=Dodaje podpis do dokument PDF za pomocą rysunku, tekstu lub obrazu
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
sign.tags=authorize,initials,drawn-signature,text-sign,image-signature
|
||||
|
||||
home.flatten.title=Spłaszcz
|
||||
home.flatten.desc=Usuń wszystkie interaktywne elementy i formularze z dokumentu PDF
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
flatten.tags=static,deactivate,non-interactive,streamline
|
||||
|
||||
home.repair.title=Napraw
|
||||
home.repair.desc=Spróbuj naprawić uszkodzony dokument PDF
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
repair.tags=fix,restore,correction,recover
|
||||
|
||||
home.removeBlanks.title=Usuń puste strony
|
||||
home.removeBlanks.desc=Wykrywa i usuwa puste strony z dokumentu PDF
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
removeBlanks.tags=cleanup,streamline,non-content,organize
|
||||
|
||||
home.compare.title=Porównaj
|
||||
home.compare.desc=Porównuje i pokazuje różnice między dwoma dokumentami PDF
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
compare.tags=differentiate,contrast,changes,analysis
|
||||
|
||||
home.certSign.title=Podpisz certyfikatem
|
||||
home.certSign.desc=Podpisz dokument PDF za pomocą certyfikatu/klucza prywatnego (PEM/P12)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
certSign.tags=authenticate,PEM,P12,official,encrypt
|
||||
|
||||
home.pageLayout.title=Układ wielu stron
|
||||
home.pageLayout.desc=Scal wiele stron dokumentu PDF w jedną stronę
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
pageLayout.tags=merge,composite,single-view,organize
|
||||
|
||||
home.scalePages.title=Dopasuj rozmiar stron
|
||||
home.scalePages.desc=Dopasuj rozmiar stron wybranego dokumentu PDF
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
scalePages.tags=resize,modify,dimension,adapt
|
||||
|
||||
home.pipeline.title=Pipeline (Advanced)
|
||||
home.pipeline.desc=Run multiple actions on PDFs by defining pipeline scripts
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
pipeline.tags=automate,sequence,scripted,batch-process
|
||||
|
||||
home.add-page-numbers.title=Add Page Numbers
|
||||
home.add-page-numbers.desc=Add Page numbers throughout a document in a set location
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
add-page-numbers.tags=paginate,label,organize,index
|
||||
|
||||
home.auto-rename.title=Auto Rename PDF File
|
||||
home.auto-rename.desc=Auto renames a PDF file based on its detected header
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
auto-rename.tags=auto-detect,header-based,organize,relabel
|
||||
|
||||
home.adjust-contrast.title=Adjust Colors/Contrast
|
||||
home.adjust-contrast.desc=Adjust Contrast, Saturation and Brightness of a PDF
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
adjust-contrast.tags=color-correction,tune,modify,enhance
|
||||
|
||||
home.crop.title=Crop PDF
|
||||
home.crop.desc=Crop a PDF to reduce its size (maintains text!)
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
crop.tags=trim,shrink,edit,shape
|
||||
|
||||
home.autoSplitPDF.title=Auto Split Pages
|
||||
home.autoSplitPDF.desc=Auto Split Scanned PDF with physical scanned page splitter QR Code
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
autoSplitPDF.tags=QR-based,separate,scan-segment,organize
|
||||
|
||||
home.sanitizePdf.title=Sanitize
|
||||
home.sanitizePdf.desc=Remove scripts and other elements from PDF files
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
sanitizePdf.tags=clean,secure,safe,remove-threats
|
||||
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
home.URLToPDF.title=URL/Website To PDF
|
||||
home.URLToPDF.desc=Converts any http(s)URL to PDF
|
||||
URLToPDF.tags=web-capture,save-page,web-to-doc,archive
|
||||
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
home.HTMLToPDF.title=HTML to PDF
|
||||
home.HTMLToPDF.desc=Converts any HTML file or zip to PDF
|
||||
HTMLToPDF.tags=markup,web-content,transformation,convert
|
||||
|
||||
|
||||
home.MarkdownToPDF.title=Markdown to PDF
|
||||
home.MarkdownToPDF.desc=Converts any Markdown file to PDF
|
||||
MarkdownToPDF.tags=markup,web-content,transformation,convert
|
||||
|
||||
|
||||
home.getPdfInfo.title=Get ALL Info on PDF
|
||||
home.getPdfInfo.desc=Grabs any and all information possible on PDFs
|
||||
getPdfInfo.tags=infomation,data,stats,statistics
|
||||
|
||||
|
||||
home.extractPage.title=Extract page(s)
|
||||
home.extractPage.desc=Extracts select pages from PDF
|
||||
extractPage.tags=extract
|
||||
|
||||
|
||||
home.PdfToSinglePage.title=PDF to Single Large Page
|
||||
home.PdfToSinglePage.desc=Merges all PDF pages into one large single page
|
||||
PdfToSinglePage.tags=single page
|
||||
|
||||
|
||||
home.showJS.title=Show Javascript
|
||||
home.showJS.desc=Searches and displays any JS injected into a PDF
|
||||
showJS.tags=JS
|
||||
|
||||
home.autoRedact.title=Auto Redact
|
||||
home.autoRedact.desc=Auto Redacts(Blacks out) text in a PDF based on input text
|
||||
showJS.tags=JS
|
||||
|
||||
###########################
|
||||
# #
|
||||
# WEB PAGES #
|
||||
# #
|
||||
###########################
|
||||
#login
|
||||
login.title=Sign in
|
||||
login.signin=Sign in
|
||||
login.rememberme=Remember me
|
||||
login.invalid=Invalid username or password.
|
||||
login.locked=Your account has been locked.
|
||||
login.signinTitle=Please sign in
|
||||
|
||||
|
||||
#auto-redact
|
||||
autoRedact.title=Auto Redact
|
||||
autoRedact.header=Auto Redact
|
||||
##########################
|
||||
### TODO: Translate ###
|
||||
##########################
|
||||
autoRedact.colorLabel=Colour
|
||||
autoRedact.textsToRedactLabel=Text to Redact (line-separated)
|
||||
autoRedact.textsToRedactPlaceholder=e.g. \nConfidential \nTop-Secret
|
||||
autoRedact.useRegexLabel=Use Regex
|
||||
autoRedact.wholeWordSearchLabel=Whole Word Search
|
||||
autoRedact.customPaddingLabel=Custom Extra Padding
|
||||
autoRedact.convertPDFToImageLabel=Convert PDF to PDF-Image (Used to remove text behind the box)
|
||||
autoRedact.submitButton=Submit
|
||||
|
||||
|
||||
#showJS
|
||||
showJS.title=Show Javascript
|
||||
showJS.header=Show Javascript
|
||||
showJS.downloadJS=Download Javascript
|
||||
showJS.submit=Show
|
||||
|
||||
|
||||
#pdfToSinglePage
|
||||
pdfToSinglePage.title=PDF To Single Page
|
||||
pdfToSinglePage.header=PDF To Single Page
|
||||
pdfToSinglePage.submit=Convert To Single Page
|
||||
|
||||
|
||||
#pageExtracter
|
||||
pageExtracter.title=Extract Pages
|
||||
pageExtracter.header=Extract Pages
|
||||
pageExtracter.submit=Extract
|
||||
|
||||
|
||||
#getPdfInfo
|
||||
getPdfInfo.title=Get Info on PDF
|
||||
getPdfInfo.header=Get Info on PDF
|
||||
getPdfInfo.submit=Get Info
|
||||
getPdfInfo.downloadJson=Download JSON
|
||||
|
||||
|
||||
#markdown-to-pdf
|
||||
MarkdownToPDF.title=Markdown To PDF
|
||||
MarkdownToPDF.header=Markdown To PDF
|
||||
MarkdownToPDF.submit=Convert
|
||||
MarkdownToPDF.help=Work in progress
|
||||
MarkdownToPDF.credit=Uses WeasyPrint
|
||||
|
||||
|
||||
|
||||
#url-to-pdf
|
||||
URLToPDF.title=URL To PDF
|
||||
URLToPDF.header=URL To PDF
|
||||
@@ -396,6 +416,9 @@ addPageNumbers.selectText.3=Position
|
||||
addPageNumbers.selectText.4=Starting Number
|
||||
addPageNumbers.selectText.5=Pages to Number
|
||||
addPageNumbers.selectText.6=Custom Text
|
||||
addPageNumbers.customTextDesc=Custom Text
|
||||
addPageNumbers.numberPagesDesc=Which pages to number, default 'all', also accepts 1-5 or 2,5,9 etc
|
||||
addPageNumbers.customNumberDesc=Defaults to {n}, also accepts 'Page {n} of {total}', 'Text-{n}', '{filename}-{n}
|
||||
addPageNumbers.submit=Add Page Numbers
|
||||
|
||||
|
||||
@@ -581,6 +604,8 @@ addImage.submit=Dodaj obraz
|
||||
#merge
|
||||
merge.title=Połącz
|
||||
merge.header=Połącz wiele dokumentów PDF (2+)
|
||||
merge.sortByName=Sort by name
|
||||
merge.sortByDate=Sort by date
|
||||
merge.submit=Połącz
|
||||
|
||||
|
||||
@@ -681,17 +706,11 @@ watermark.selectText.4=Obrót (0-360):
|
||||
watermark.selectText.5=Odstęp w poziomie (odstęp między każdym znakiem wodnym w poziomie):
|
||||
watermark.selectText.6=Odstęp w pionie (odstęp między każdym znakiem wodnym w pionie):
|
||||
watermark.selectText.7=Nieprzezroczystość (0% - 100%):
|
||||
watermark.selectText.8=Watermark Type:
|
||||
watermark.selectText.9=Watermark Image:
|
||||
watermark.submit=Dodaj znak wodny
|
||||
|
||||
|
||||
#remove-watermark
|
||||
remove-watermark.title=Usuń znak wodny
|
||||
remove-watermark.header=Usuń znak wodny
|
||||
remove-watermark.selectText.1=Wybierz dokument PDF, aby usunąć znak wodny z:
|
||||
remove-watermark.selectText.2=Treść zanku wodnego:
|
||||
remove-watermark.submit=Usuń znak wodny
|
||||
|
||||
|
||||
#Change permissions
|
||||
permissions.title=Zmień uprawnienia
|
||||
permissions.header=Zmień uprawnienia
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user