Compare commits

..

83 Commits

Author SHA1 Message Date
Anthony Stirling
625275124a fix for #818 2024-02-18 15:47:19 +00:00
Anthony Stirling
c96ebccae4 Download message for game 2024-02-18 13:30:56 +00:00
Anthony Stirling
20cb460a7e controls and sizing bounds 2024-02-18 09:45:50 +00:00
Anthony Stirling
3a62d19979 game const 2024-02-18 09:21:30 +00:00
Ludy
51ad741744 Fix 746 (#825)
* Fix: #746

* formatting
2024-02-18 07:40:30 +00:00
Anthony Stirling
673f005fe6 Game fixes and ocr docs (#824) 2024-02-17 23:23:07 +00:00
Ludy
8d9f0361d0 Fix Serbia Language (#822)
* Fix Serbia Language

* Rename messages_sr_Latn_RS.properties to messages_sr_LATN_RS.properties

* Update languages.html

* Update README.md
2024-02-17 19:56:56 +00:00
Anthony Stirling
56e3ec1219 Update HowToUseOCR.md 2024-02-17 19:28:32 +00:00
dependabot[bot]
a0acafcefc Bump org.springframework:spring-webmvc from 6.1.2 to 6.1.3 (#713)
Bumps [org.springframework:spring-webmvc](https://github.com/spring-projects/spring-framework) from 6.1.2 to 6.1.3.
- [Release notes](https://github.com/spring-projects/spring-framework/releases)
- [Commits](https://github.com/spring-projects/spring-framework/compare/v6.1.2...v6.1.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-17 13:24:38 +00:00
dependabot[bot]
918f5954b7 Bump io.micrometer:micrometer-core from 1.12.2 to 1.12.3 (#806)
Bumps [io.micrometer:micrometer-core](https://github.com/micrometer-metrics/micrometer) from 1.12.2 to 1.12.3.
- [Release notes](https://github.com/micrometer-metrics/micrometer/releases)
- [Commits](https://github.com/micrometer-metrics/micrometer/compare/v1.12.2...v1.12.3)

---
updated-dependencies:
- dependency-name: io.micrometer:micrometer-core
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-17 13:23:10 +00:00
albanobattistella
148dcdaee7 Update messages_it_IT.properties (#816) 2024-02-17 13:22:15 +00:00
Anthony Stirling
a5f0777892 Update ConfigInitializer.java for auto settings removal 2024-02-17 13:10:00 +00:00
Ludy
010426d488 Document (#803)
* Update HowToAddNewLanguage.md

* Update HowToUseOCR.md

* Update LocalRunGuide.md

* Update README.md

* Update LocalRunGuide.md

* Update README.md

---------

Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
2024-02-16 22:42:56 +00:00
Aliarev
6fc9c7be90 Update french translation (#814) 2024-02-16 22:24:26 +00:00
Sherif Metwally
094fde9801 Update-helm-chart (#815)
* upgrade app in helm chart to 0.20.2

* update and correct UI env variable names in chart values.yaml
2024-02-16 22:23:11 +00:00
Ludy
e4a76e96af HTML, CSS, JS and JAVA corrections (#810)
* CSS corrections

* HTML corrections

* JS corrections

* JAVA corrections

* remove tab

* CSS corrections 2

* JS corrections 2

* back to the roots

* max-linie 127

* add slash hr|br

* return bootstrap-icons.css

* return bootstrap-icons.min.css

* return bootstrap.min.css

* Update bootstrap-icons.css

* Update bootstrap-icons.min.css

* Update bootstrap-icons.min.css

* Update bootstrap.min.css

* CSS corrections

* HTML corrections

* JS corrections

* JAVA corrections

* remove tab

* CSS corrections 2

* JS corrections 2

* back to the roots

* max-linie 127

* add slash hr|br

* return bootstrap-icons.css

* Update bootstrap-icons.css

* Bootstrap CSS

* Update prism.css
2024-02-16 21:49:06 +00:00
Anthony Stirling
68f582bcb9 Merge pull request #811 from NeilJared/main
Update messages_es_ES.properties
2024-02-14 21:27:59 +00:00
NeilJared
639aed7120 Update messages_es_ES.properties
Updated es_ES translation
2024-02-14 12:22:47 +01:00
NeilJared
994bb4d1d2 Update messages_es_ES.properties
Minor bug fixes: es_ES translation
2024-02-14 11:57:34 +01:00
Anthony Stirling
80b11a55fa Merge pull request #804 from Ludy87/missing_pageSelectionPrompt
add missing propertie pageSelectionPrompt
2024-02-11 22:43:08 +00:00
Ludy87
3cfb554623 missing propertie pageSelectionPrompt 2024-02-11 21:10:04 +01:00
Eric
e84f9c5946 Merge pull request #796 from Ludy87/languages
Languages
2024-02-11 14:41:15 -05:00
Ludy87
17cc31d6e7 add placeholder translation 2024-02-11 14:32:34 -05:00
Ludy87
0c6e10a6dd add separator 2024-02-11 14:32:34 -05:00
Ludy87
297c57631f remove dublicate -> change showJS.tags to autoRedact.tags 2024-02-11 14:32:34 -05:00
Ludy87
bd4e252bb6 added missing strings 2024-02-11 14:32:33 -05:00
Ludy87
0ce34c70bc Update messages_de_DE.properties 2024-02-11 14:32:33 -05:00
Ludy87
4df75cfba1 Update messages_de_DE.properties 2024-02-11 14:32:33 -05:00
Ludy87
2aa435bcfb double spaces removed 2024-02-11 14:32:33 -05:00
Ludy87
0a4a9e6947 Removed unnecessary characters and added DE missing strings 2024-02-11 14:32:32 -05:00
Anthony Stirling
d5860d0b55 Update PdfToTextOrRTFRequest.java 2024-02-11 18:47:43 +00:00
Eric
6a487ce514 Merge pull request #802 from Stirling-Tools/normalize_files
refactor: normalize all files (strip trailing whitespace + convert CRLF to LF)
2024-02-11 13:11:37 -05:00
sbplat
4f3b85e66b refactor: normalize files that contained both CRLF and LF 2024-02-11 12:14:21 -05:00
sbplat
370cd97e05 misc: update .git-blame-ignore-revs to ignore normalize files commit in blame 2024-02-11 11:54:03 -05:00
sbplat
55d4fda01b refactor: normalize files 2024-02-11 11:47:00 -05:00
Anthony Stirling
3dd0471e22 Merge pull request #799 from Stirling-Tools/icon
Icon changes!
2024-02-10 16:40:00 +00:00
Anthony Stirling
5a4efa81a7 more icon changes 2024-02-10 16:22:59 +00:00
Anthony Stirling
ea59c12b27 icon changes 2024-02-10 16:17:47 +00:00
Anthony Stirling
9600f91dda bigger icons 2024-02-10 16:11:45 +00:00
Anthony Stirling
a9f93b014a icon change 2024-02-10 15:56:41 +00:00
Anthony Stirling
bf62e389f7 Merge branch 'main' of git@github.com:Frooodle/Stirling-PDF.git into
main
2024-02-10 14:55:53 +00:00
Anthony Stirling
26af6b5636 cleanups formatting 2024-02-10 14:52:59 +00:00
Anthony Stirling
0fabfea56d page adjusts for stamp 2024-02-10 14:52:27 +00:00
Anthony Stirling
7a9417a62f Merge pull request #794 from mannam11/fixed-stamptool-wrong-filename-generaion-#757
fixed wrong filename generation through stamp tool #757
2024-02-10 11:21:19 +00:00
Anthony Stirling
eb45005baa Merge branch 'main' into fixed-stamptool-wrong-filename-generaion-#757 2024-02-10 11:20:21 +00:00
Anthony Stirling
a4f923eb3a Update StampController.java 2024-02-10 11:19:22 +00:00
Anthony Stirling
e1c3561997 version bump and expose ports 2024-02-10 10:29:17 +00:00
mannam11
bf8b902100 Merge branch 'main' into fixed-stamptool-wrong-filename-generaion-#757 2024-02-10 15:57:38 +05:30
Anthony Stirling
8a5883501a Merge pull request #797 from Stirling-Tools/fixes
Fixes for docker changes plus others
2024-02-10 00:33:49 +00:00
Anthony Stirling
fd8f3ce019 Merge pull request #798 from Stirling-Tools/pixeebot/fixes
Hardening suggestions for Stirling-PDF / fixes
2024-02-10 00:33:33 +00:00
Anthony Stirling
6f72096953 more fixes 2024-02-10 00:21:00 +00:00
Anthony Stirling
5a52e3d6dd other changes 2024-02-10 00:08:54 +00:00
pixeebot[bot]
23672cd18d Modernize and secure temp file creation 2024-02-10 00:08:18 +00:00
pixeebot[bot]
68c0941666 Sanitized user-provided file names in HTTP multipart uploads 2024-02-10 00:08:18 +00:00
Anthony Stirling
96e399a617 changing html and book labels 2024-02-10 00:00:07 +00:00
Anthony Stirling
22343e507d fixes 2024-02-09 23:45:18 +00:00
Anthony Stirling
8a143d139c Merge remote-tracking branch 'origin/main' into fixes 2024-02-09 23:30:25 +00:00
Anthony Stirling
15ad46fe1c book htmk 2024-02-09 23:24:25 +00:00
Anthony Stirling
2473f0d034 Update build.gradle 2024-02-09 23:22:16 +00:00
Anthony Stirling
f211eefc85 Merge pull request #624 from Zoey2936/main
switch images to alpine
2024-02-09 23:22:07 +00:00
mannam
9da88b7652 fixed wrong filename generation through stamp tool #757 2024-02-09 19:35:34 +05:30
Anthony Stirling
729c8006d2 Merge pull request #789 from mannam11/fixed_remove_pages_exception#761
Fixed remove pages un-handled exception with space in input #761
2024-02-08 17:25:17 +00:00
Anthony Stirling
0d5b790443 Merge branch 'main' into fixed_remove_pages_exception#761 2024-02-08 17:19:30 +00:00
Anthony Stirling
aa16035137 Merge pull request #787 from Stirling-Tools/fix_stamp_margins
fix: use the same margins for x and y in the stamp feature
2024-02-08 17:18:31 +00:00
mannam
41686883ee Fixed remove pages un-handled exception with space in input #761 2024-02-08 21:03:57 +05:30
Eric
2e0790c893 Merge pull request #788 from Stirling-Tools/pixeebot/fix_stamp_margins
Hardening suggestions for Stirling-PDF / fix_stamp_margins
2024-02-07 21:52:21 -05:00
pixeebot[bot]
4e937a6024 Sanitized user-provided file names in HTTP multipart uploads 2024-02-08 02:46:39 +00:00
sbplat
4af58118c9 fix: use the same margins for x and y in the stamp feature 2024-02-07 21:40:33 -05:00
Zoey
aa2ad33c1d fix libreoffice install 2024-02-07 06:15:32 +01:00
Anthony Stirling
c7005bc07f Merge pull request #780 from NeilJared/main
Updated es_ES translation (100% completed)
2024-02-06 09:40:30 +00:00
NeilJared
3f932ebec9 Update messages_es_ES.properties
Updated es_ES translation (100%)
2024-02-06 10:03:55 +01:00
Stirling-PDF-Bot
296f265391 Update 3rd Party Licenses 2024-02-06 08:39:13 +00:00
Anthony Stirling
ca8519cb10 Merge remote-tracking branch 'origin/main' into fixes 2024-02-06 00:01:15 +00:00
Anthony Stirling
734d76a3b5 test 2024-02-06 00:00:49 +00:00
Anthony Stirling
f5a39ed514 Merge pull request #776 from michelheusschen/fix/dutch-small-corrections
fix: small corrections for Dutch language
2024-02-04 18:53:04 +00:00
Michel Heusschen
96f4e5eac7 fix: small corrections for Dutch language 2024-02-04 18:08:55 +01:00
Zoey
d190ae0cf3 add @testing (3/3) 2024-01-31 21:02:22 +01:00
Zoey
bb08a63296 add @testing (2/3) 2024-01-31 21:02:22 +01:00
Zoey
3debc1b0df add @testing (1/3) 2024-01-31 21:02:22 +01:00
Zoey
e560028097 Update Dockerfile-lite 2024-01-31 21:02:22 +01:00
Zoey
5afcbdbc8b use patched libreoffice version 2024-01-31 21:02:22 +01:00
Zoey
aaaf3ffe34 fix some things 2024-01-31 21:02:22 +01:00
Zoey
b043e666ae switch images to alpine
Signed-off-by: Zoey <zoey@z0ey.de>
2024-01-31 21:02:22 +01:00
289 changed files with 24084 additions and 24748 deletions

View File

@@ -1,2 +1,5 @@
# Formatting
5f771b785130154ed47952635b7acef371ffe0ec
5f771b785130154ed47952635b7acef371ffe0ec
# Normalize files
55d4fda01b2f39f5b7d7b4fda5214bd7ff0fd5dd

View File

@@ -3,7 +3,7 @@ name: Push Docker Image with VersionNumber
on:
workflow_dispatch:
push:
branches:
branches:
- master
- main
permissions:
@@ -15,13 +15,13 @@ jobs:
steps:
- uses: actions/checkout@v3.5.2
- name: Set up JDK 17
uses: actions/setup-java@v3.11.0
with:
java-version: '17'
distribution: 'temurin'
- uses: gradle/gradle-build-action@v2.4.2
env:
@@ -32,11 +32,11 @@ jobs:
- name: Make Gradle wrapper executable
run: chmod +x gradlew
- name: Get version number
id: versionNumber
run: echo "::set-output name=versionNumber::$(./gradlew printVersion --quiet | tail -1)"
- name: Login to Docker Hub
uses: docker/login-action@v2.1.0
with:
@@ -53,7 +53,7 @@ jobs:
- name: Convert repository owner to lowercase
id: repoowner
run: echo "::set-output name=lowercase::$(echo ${{ github.repository_owner }} | awk '{print tolower($0)}')"
- name: Generate tags
id: meta
uses: docker/metadata-action@v4.4.0
@@ -82,7 +82,7 @@ jobs:
cache-to: type=gha,mode=max
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-args:
build-args:
VERSION_TAG=${{ steps.versionNumber.outputs.versionNumber }}
platforms: linux/amd64,linux/arm64/v8
@@ -99,7 +99,7 @@ jobs:
tags: |
type=raw,value=${{ steps.versionNumber.outputs.versionNumber }}-ultra-lite,enable=${{ github.ref == 'refs/heads/master' }}
type=raw,value=latest-ultra-lite,enable=${{ github.ref == 'refs/heads/master' }}
- name: Build and push Dockerfile-ultra-lite
uses: docker/build-push-action@v4.0.0
@@ -112,7 +112,7 @@ jobs:
cache-to: type=gha,mode=max
tags: ${{ steps.meta2.outputs.tags }}
labels: ${{ steps.meta2.outputs.labels }}
build-args:
build-args:
VERSION_TAG=${{ steps.versionNumber.outputs.versionNumber }}
platforms: linux/amd64,linux/arm64/v8
@@ -129,7 +129,7 @@ jobs:
tags: |
type=raw,value=${{ steps.versionNumber.outputs.versionNumber }}-lite,enable=${{ github.ref == 'refs/heads/master' }}
type=raw,value=latest-lite,enable=${{ github.ref == 'refs/heads/master' }}
- name: Build and push Dockerfile-lite
uses: docker/build-push-action@v4.0.0
@@ -142,7 +142,7 @@ jobs:
cache-to: type=gha,mode=max
tags: ${{ steps.meta3.outputs.tags }}
labels: ${{ steps.meta3.outputs.labels }}
build-args:
build-args:
VERSION_TAG=${{ steps.versionNumber.outputs.versionNumber }}
platforms: linux/amd64,linux/arm64/v8
- name: Build and Push Helm Chart

View File

@@ -1,7 +1,7 @@
name: Release Artifacts
on:
release:
on:
release:
types: [created]
permissions:
contents: write
@@ -19,13 +19,13 @@ jobs:
file_suffix: ''
steps:
- uses: actions/checkout@v3.5.2
- name: Set up JDK 17
uses: actions/setup-java@v3.11.0
with:
java-version: '17'
distribution: 'temurin'
- name: Grant execute permission for gradlew
run: chmod +x gradlew
@@ -42,11 +42,11 @@ jobs:
asset_name: Stirling-PDF${{ matrix.file_suffix }}.exe
tag: ${{ github.ref }}
overwrite: true
- name: Get version number
id: versionNumber
run: echo "::set-output name=versionNumber::$(./gradlew printVersion --quiet | tail -1)"
- name: Upload jar binaries to release
uses: svenstaro/upload-release-action@v2
with:

View File

@@ -3,7 +3,7 @@ name: Update Swagger
on:
workflow_dispatch:
push:
branches:
branches:
- master
jobs:
push:
@@ -12,13 +12,13 @@ jobs:
steps:
- uses: actions/checkout@v3.5.2
- name: Set up JDK 17
uses: actions/setup-java@v3.11.0
with:
java-version: '17'
distribution: 'temurin'
- name: Grant execute permission for gradlew
run: chmod +x gradlew

View File

@@ -30,7 +30,7 @@ jobs:
- name: Run Docker Compose Tests
run: |
chmod +x ./gradlew
- name: Get version number
id: versionNumber
run: echo "::set-output name=versionNumber::$(./gradlew printVersion --quiet | tail -1)"

252
.gitignore vendored
View File

@@ -1,127 +1,127 @@
### Eclipse ###
.metadata
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.settings/
.loadpath
.recommenders
.classpath
.project
version.properties
pipeline/watchedFolders/
pipeline/finishedFolders/
#### Stirling-PDF Files ###
customFiles/
configs/
watchedFolders/
# Gradle
.gradle
.lock
# External tool builders
.externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# PyDev specific (Python IDE for Eclipse)
*.pydevproject
# CDT-specific (C/C++ Development Tooling)
.cproject
# CDT- autotools
.autotools
# Java annotation processor (APT)
.factorypath
# PDT-specific (PHP Development Tools)
.buildpath
# sbteclipse plugin
.target
# Tern plugin
.tern-project
# TeXlipse plugin
.texlipse
# STS (Spring Tool Suite)
.springBeans
# Code Recommenders
.recommenders/
# Annotation Processing
.apt_generated/
.apt_generated_test/
# Scala IDE specific (Scala & Java development for Eclipse)
.cache-main
.scala_dependencies
.worksheet
# Uncomment this line if you wish to ignore the project description file.
# Typically, this file would be tracked if it contains build/dependency configurations:
#.project
### Eclipse Patch ###
# Spring Boot Tooling
.sts4-cache/
### Git ###
# Created by git for backups. To disable backups in Git:
# $ git config --global mergetool.keepBackup false
*.orig
# Created by git when using merge tools for conflicts
*.BACKUP.*
*.BASE.*
*.LOCAL.*
*.REMOTE.*
*_BACKUP_*.txt
*_BASE_*.txt
*_LOCAL_*.txt
*_REMOTE_*.txt
### Java ###
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
*.db
/build
/.vscode
/.idea
# Ignore Mac DS_Store files
.DS_Store
### Eclipse ###
.metadata
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.settings/
.loadpath
.recommenders
.classpath
.project
version.properties
pipeline/watchedFolders/
pipeline/finishedFolders/
#### Stirling-PDF Files ###
customFiles/
configs/
watchedFolders/
# Gradle
.gradle
.lock
# External tool builders
.externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# PyDev specific (Python IDE for Eclipse)
*.pydevproject
# CDT-specific (C/C++ Development Tooling)
.cproject
# CDT- autotools
.autotools
# Java annotation processor (APT)
.factorypath
# PDT-specific (PHP Development Tools)
.buildpath
# sbteclipse plugin
.target
# Tern plugin
.tern-project
# TeXlipse plugin
.texlipse
# STS (Spring Tool Suite)
.springBeans
# Code Recommenders
.recommenders/
# Annotation Processing
.apt_generated/
.apt_generated_test/
# Scala IDE specific (Scala & Java development for Eclipse)
.cache-main
.scala_dependencies
.worksheet
# Uncomment this line if you wish to ignore the project description file.
# Typically, this file would be tracked if it contains build/dependency configurations:
#.project
### Eclipse Patch ###
# Spring Boot Tooling
.sts4-cache/
### Git ###
# Created by git for backups. To disable backups in Git:
# $ git config --global mergetool.keepBackup false
*.orig
# Created by git when using merge tools for conflicts
*.BACKUP.*
*.BASE.*
*.LOCAL.*
*.REMOTE.*
*_BACKUP_*.txt
*_BASE_*.txt
*_LOCAL_*.txt
*_REMOTE_*.txt
### Java ###
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
*.db
/build
/.vscode
/.idea
# Ignore Mac DS_Store files
.DS_Store
**/.DS_Store

View File

@@ -1,47 +1,69 @@
# Use the base image
FROM frooodle/stirling-pdf-base:version8
ARG VERSION_TAG
# Set Environment Variables
ENV DOCKER_ENABLE_SECURITY=false \
HOME=/home/stirlingpdfuser \
VERSION_TAG=$VERSION_TAG \
JAVA_TOOL_OPTIONS="$JAVA_TOOL_OPTIONS -XX:MaxRAMPercentage=75"
# PUID=1000 \
# PGID=1000 \
# UMASK=022 \
# Create user and group
##RUN groupadd -g $PGID stirlingpdfgroup && \
## useradd -u $PUID -g stirlingpdfgroup -s /bin/sh stirlingpdfuser && \
## mkdir -p $HOME && chown stirlingpdfuser:stirlingpdfgroup $HOME
# Set up necessary directories and permissions
RUN mkdir -p /scripts /usr/share/fonts/opentype/noto /usr/share/tesseract-ocr /configs /logs /customFiles /pipeline /pipeline/defaultWebUIConfigs /pipeline/watchedFolders /pipeline/finishedFolders
##&& \
## chown -R stirlingpdfuser:stirlingpdfgroup /scripts /usr/share/fonts/opentype/noto /usr/share/tesseract-ocr /configs /customFiles && \
## chown -R stirlingpdfuser:stirlingpdfgroup /usr/share/tesseract-ocr-original
# Copy necessary files
COPY ./scripts/* /scripts/
COPY ./pipeline/ /pipeline/
COPY src/main/resources/static/fonts/*.ttf /usr/share/fonts/opentype/noto/
COPY src/main/resources/static/fonts/*.otf /usr/share/fonts/opentype/noto/
COPY build/libs/*.jar app.jar
# Set font cache and permissions
RUN fc-cache -f -v && chmod +x /scripts/*
##&& \
## chown stirlingpdfuser:stirlingpdfgroup /app.jar && \
## chmod +x /scripts/init.sh
# Expose necessary ports
EXPOSE 8080
# Set user and run command
##USER stirlingpdfuser
ENTRYPOINT ["/scripts/init.sh"]
CMD ["java", "-Dfile.encoding=UTF-8", "-jar", "/app.jar"]
# Main stage
FROM alpine:3.19.1
# JDK for app
RUN echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /etc/apk/repositories && \
echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/community" | tee -a /etc/apk/repositories && \
echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/testing" | tee -a /etc/apk/repositories && \
apk add --no-cache \
ca-certificates \
tzdata \
tini \
bash \
curl \
openjdk17-jre \
# Doc conversion
libreoffice@testing \
# OCR MY PDF (unpaper for descew and other advanced featues)
ocrmypdf \
tesseract-ocr-data-eng \
# CV
py3-opencv \
# python3/pip
python3 && \
wget https://bootstrap.pypa.io/get-pip.py -qO - | python3 - --break-system-packages --no-cache-dir --upgrade && \
# uno unoconv and HTML
pip install --break-system-packages --no-cache-dir --upgrade unoconv WeasyPrint && \
mv /usr/share/tessdata /usr/share/tessdata-original
ARG VERSION_TAG
# Set Environment Variables
ENV DOCKER_ENABLE_SECURITY=false \
HOME=/home/stirlingpdfuser \
VERSION_TAG=$VERSION_TAG \
JAVA_TOOL_OPTIONS="$JAVA_TOOL_OPTIONS -XX:MaxRAMPercentage=75"
# PUID=1000 \
# PGID=1000 \
# UMASK=022 \
# Copy necessary files
COPY scripts /scripts
COPY pipeline /pipeline
COPY src/main/resources/static/fonts/*.ttf /usr/share/fonts/opentype/noto
COPY src/main/resources/static/fonts/*.otf /usr/share/fonts/opentype/noto
COPY build/libs/*.jar app.jar
# Create user and group
##RUN groupadd -g $PGID stirlingpdfgroup && \
## useradd -u $PUID -g stirlingpdfgroup -s /bin/sh stirlingpdfuser && \
## mkdir -p $HOME && chown stirlingpdfuser:stirlingpdfgroup $HOME && \
# Set up necessary directories and permissions
RUN mkdir -p /configs /logs /customFiles /pipeline/watchedFolders /pipeline/finishedFolders && \
##&& \
## chown -R stirlingpdfuser:stirlingpdfgroup /scripts /usr/share/fonts/opentype/noto /usr/share/tesseract-ocr /configs /customFiles && \
## chown -R stirlingpdfuser:stirlingpdfgroup /usr/share/tesseract-ocr-original && \
# Set font cache and permissions
fc-cache -f -v && \
chmod +x /scripts/*
## chown stirlingpdfuser:stirlingpdfgroup /app.jar && \
## chmod +x /scripts/init.sh
EXPOSE 8080
# Set user and run command
##USER stirlingpdfuser
ENTRYPOINT ["tini", "--", "/scripts/init.sh"]
CMD ["java", "-Dfile.encoding=UTF-8", "-jar", "/app.jar"]

View File

@@ -1,65 +1,61 @@
# Build jbig2enc in a separate stage
FROM bellsoft/liberica-openjdk-debian:17
# use alpine
FROM alpine:3.19.1
ARG VERSION_TAG
RUN apt-get update && \
apt-get install -y --no-install-recommends \
libreoffice-core \
libreoffice-common \
libreoffice-writer \
libreoffice-calc \
libreoffice-impress \
unoconv && \
rm -rf /var/lib/apt/lists/*
# Set Environment Variables
ENV DOCKER_ENABLE_SECURITY=false \
HOME=/home/stirlingpdfuser \
VERSION_TAG=$VERSION_TAG \
JAVA_TOOL_OPTIONS="$JAVA_TOOL_OPTIONS -XX:MaxRAMPercentage=75"
# PUID=1000 \
# PUID=1000 \
# PGID=1000 \
# UMASK=022 \
# Copy necessary files
COPY scripts/download-security-jar.sh /scripts/download-security-jar.sh
COPY scripts/init-without-ocr.sh /scripts/init-without-ocr.sh
COPY pipeline /pipeline
COPY src/main/resources/static/fonts/*.ttf /usr/share/fonts/opentype/noto
COPY src/main/resources/static/fonts/*.otf /usr/share/fonts/opentype/noto
COPY build/libs/*.jar app.jar
RUN echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /etc/apk/repositories && \
echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/community" | tee -a /etc/apk/repositories && \
echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/testing" | tee -a /etc/apk/repositories && \
apk add --no-cache \
ca-certificates \
tzdata \
tini \
bash \
curl \
openjdk17-jre \
# Doc conversion
libreoffice@testing \
# python and pip
python3 && \
wget https://bootstrap.pypa.io/get-pip.py -qO - | python3 - --break-system-packages --no-cache-dir --upgrade && \
# uno unoconv and HTML
pip install --break-system-packages --no-cache-dir --upgrade unoconv WeasyPrint && \
# Create user and group
#RUN groupadd -g $PGID stirlingpdfgroup && \
# useradd -u $PUID -g stirlingpdfgroup -s /bin/sh stirlingpdfuser && \
# mkdir -p $HOME && chown stirlingpdfuser:stirlingpdfgroup $HOME
# Set up necessary directories and permissions
RUN mkdir -p /scripts /usr/share/fonts/opentype/noto /configs /customFiles /logs /pipeline /pipeline/defaultWebUIConfigs /pipeline/watchedFolders /pipeline/finishedFolders
mkdir -p /configs /logs /customFiles /pipeline/watchedFolders /pipeline/finishedFolders && \
# chown -R stirlingpdfuser:stirlingpdfgroup /usr/share/fonts/opentype/noto /configs /customFiles
# Copy necessary files
COPY ./scripts/download-security-jar.sh /scripts/download-security-jar.sh
COPY ./scripts/init-without-ocr.sh /scripts/init-without-ocr.sh
COPY ./pipeline/ /pipeline/
COPY src/main/resources/static/fonts/*.ttf /usr/share/fonts/opentype/noto/
COPY src/main/resources/static/fonts/*.otf /usr/share/fonts/opentype/noto/
COPY build/libs/*.jar app.jar
# Set font cache and permissions
RUN fc-cache -f -v && \
chmod +x /scripts/init-without-ocr.sh && \
chmod +x /scripts/download-security-jar.sh
fc-cache -f -v && \
chmod +x /scripts/*.sh
# chown stirlingpdfuser:stirlingpdfgroup /app.jar
# Expose the application port
EXPOSE 8080
# Set environment variables
ENV ENDPOINTS_GROUPS_TO_REMOVE=Python,OpenCV,OCRmyPDF
ENV ENDPOINTS_GROUPS_TO_REMOVE=OpenCV,OCRmyPDF
ENV DOCKER_ENABLE_SECURITY=false
EXPOSE 8080
# Run the application
#USER stirlingpdfuser
ENTRYPOINT ["/scripts/init-without-ocr.sh"]
ENTRYPOINT ["tini", "--", "/scripts/init-without-ocr.sh"]
CMD ["java", "-Dfile.encoding=UTF-8", "-jar", "/app.jar"]

View File

@@ -1,5 +1,5 @@
# Build jbig2enc in a separate stage
FROM bellsoft/liberica-openjdk-alpine:17
# use alpine
FROM alpine:3.19.1
ARG VERSION_TAG
@@ -8,39 +8,44 @@ ENV DOCKER_ENABLE_SECURITY=false \
HOME=/home/stirlingpdfuser \
VERSION_TAG=$VERSION_TAG \
JAVA_TOOL_OPTIONS="$JAVA_TOOL_OPTIONS -XX:MaxRAMPercentage=75"
# PUID=1000 \
# PUID=1000 \
# PGID=1000 \
# UMASK=022 \
# Copy necessary files
COPY scripts/download-security-jar.sh /scripts/download-security-jar.sh
COPY scripts/init-without-ocr.sh /scripts/init-without-ocr.sh
COPY pipeline /pipeline
COPY build/libs/*.jar app.jar
# Create user and group using Alpine's addgroup and adduser
#RUN addgroup -g $PGID stirlingpdfgroup && \
# adduser -u $PUID -G stirlingpdfgroup -s /bin/sh -D stirlingpdfuser && \
# mkdir -p $HOME && chown stirlingpdfuser:stirlingpdfgroup $HOME
# Set up necessary directories and permissions
#RUN mkdir -p /scripts /configs /customFiles && \
# chown -R stirlingpdfuser:stirlingpdfgroup /scripts /configs /customFiles /logs /pipeline /pipeline/defaultWebUIConfigs /pipeline/watchedFolders /pipeline/finishedFolders
RUN mkdir -p /scripts /usr/share/fonts/opentype/noto /configs /customFiles
COPY ./scripts/download-security-jar.sh /scripts/download-security-jar.sh
COPY ./scripts/init-without-ocr.sh /scripts/init-without-ocr.sh
COPY ./pipeline/ /pipeline/
COPY build/libs/*.jar app.jar
# chown -R stirlingpdfuser:stirlingpdfgroup /scripts /configs /customFiles /logs /pipeline /pipeline/defaultWebUIConfigs /pipeline/watchedFolders /pipeline/finishedFolders
RUN mkdir /configs /logs /customFiles && \
# Set font cache and permissions
#RUN chown stirlingpdfuser:stirlingpdfgroup /app.jar
RUN chmod +x /scripts/init-without-ocr.sh && \
chmod +x /scripts/download-security-jar.sh && \
apk add --no-cache curl
# Expose the application port
EXPOSE 8080
chmod +x /scripts/*.sh && \
apk add --no-cache \
ca-certificates \
tzdata \
tini \
bash \
curl \
openjdk17-jre && \
echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /etc/apk/repositories && \
echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/community" | tee -a /etc/apk/repositories && \
echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/testing" | tee -a /etc/apk/repositories
# Set environment variables
ENV ENDPOINTS_GROUPS_TO_REMOVE=CLI
ENTRYPOINT ["/scripts/init-without-ocr.sh"]
EXPOSE 8080
ENTRYPOINT ["tini", "--", "/scripts/init-without-ocr.sh"]
# Run the application
CMD ["java", "-Dfile.encoding=UTF-8", "-jar", "/app.jar"]

View File

@@ -1,43 +0,0 @@
# Main stage
FROM ubuntu:latest AS base
# JDK for app
RUN apt-get update && \
apt-get install -y --no-install-recommends \
openjdk-17-jre && \
rm -rf /var/lib/apt/lists/*
# Doc conversion
RUN apt-get update && \
apt-get install -y --no-install-recommends \
libreoffice-core \
libreoffice-common \
libreoffice-writer \
libreoffice-calc \
libreoffice-impress \
python3-uno \
curl \
unoconv && \
rm -rf /var/lib/apt/lists/*
# OCR MY PDF (unpaper for descew and other advanced featues)
RUN apt-get update && apt-get install -y --no-install-recommends software-properties-common gnupg2 && \
add-apt-repository ppa:alex-p/tesseract-ocr5 && apt install -y --no-install-recommends tesseract-ocr && \
apt-get update && \
apt-get install -y --no-install-recommends \
ghostscript \
python3-pip \
ocrmypdf \
unpaper && \
rm -rf /var/lib/apt/lists/* && \
mv /usr/share/tesseract-ocr /usr/share/tesseract-ocr-original && \
pip install --no-cache-dir --upgrade pip && \
pip install --no-cache-dir --upgrade ocrmypdf && \
pip install --no-cache-dir --upgrade pillow==10.0.1 reportlab==3.6.13 wheel==0.38.1 setuptools==65.5.1 pyjwt==2.4.0 cryptography==39.0.1
#CV and HTML
RUN pip install --no-cache-dir opencv-python-headless WeasyPrint

View File

@@ -1,46 +1,46 @@
| Operation | PageOps | Convert | Security | Other | CLI | Python | OpenCV | LibreOffice | OCRmyPDF | Java | Javascript |
|---------------------|---------|---------|----------|-------|------|--------|--------|-------------|----------|----------|------------|
| 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 | ✔️ | | | | | | | | | ✔️ | |
| split-pdfs | ✔️ | | | | | | | | | ✔️ | |
| file-to-pdf | | ✔️ | | | ✔️ | | | ✔️ | | | |
| img-to-pdf | | ✔️ | | | | | | | | ✔️ | |
| pdf-to-html | | ✔️ | | | ✔️ | | | ✔️ | | | |
| pdf-to-img | | ✔️ | | | | | | | | ✔️ | |
| pdf-to-pdfa | | ✔️ | | | ✔️ | | | | ✔️ | | |
| pdf-to-markdown | | ✔️ | | | | | | | | ✔️ | |
| pdf-to-presentation | | ✔️ | | | ✔️ | | | ✔️ | | | |
| pdf-to-text | | ✔️ | | | ✔️ | | | ✔️ | | | |
| pdf-to-word | | ✔️ | | | ✔️ | | | ✔️ | | | |
| pdf-to-xml | | ✔️ | | | ✔️ | | | ✔️ | | | |
| xlsx-to-pdf | | ✔️ | | | ✔️ | | | ✔️ | | | |
| add-password | | | ✔️ | | | | | | | ✔️ | |
| add-watermark | | | ✔️ | | | | | | | ✔️ | |
| cert-sign | | | ✔️ | | | | | | | ✔️ | |
| change-permissions | | | ✔️ | | | | | | | ✔️ | |
| remove-password | | | ✔️ | | | | | | | ✔️ | |
| sanitize-pdf | | | ✔️ | | | | | | | ✔️ | |
| add-image | | | | ✔️ | | | | | | ✔️ | |
| add-page-numbers | | | | ✔️ | | | | | | ✔️ | |
| auto-rename | | | | ✔️ | | | | | | ✔️ | |
| change-metadata | | | | ✔️ | | | | | | ✔️ | |
| compare | | | | ✔️ | | | | | | | ✔️ |
| compress-pdf | | | | ✔️ | ✔️ | | | | ✔️ | | |
| extract-image-scans | | | | ✔️ | ✔️ | ✔️ | ✔️ | | | | |
| extract-images | | | | ✔️ | | | | | | ✔️ | |
| flatten | | | | ✔️ | | | | | | | ✔️ |
| get-info-on-pdf | | | | ✔️ | | | | | | ✔️ | |
| ocr-pdf | | | | ✔️ | ✔️ | | | | ✔️ | | |
| remove-blanks | | | | ✔️ | ✔️ | ✔️ | ✔️ | | | | |
| repair | | | | ✔️ | ✔️ | | | ✔️ | | | |
| show-javascript | | | | ✔️ | | | | | | | ✔️ |
| Operation | PageOps | Convert | Security | Other | CLI | Python | OpenCV | LibreOffice | OCRmyPDF | Java | Javascript |
|---------------------|---------|---------|----------|-------|------|--------|--------|-------------|----------|----------|------------|
| 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 | ✔️ | | | | | | | | | ✔️ | |
| split-pdfs | ✔️ | | | | | | | | | ✔️ | |
| file-to-pdf | | ✔️ | | | ✔️ | | | ✔️ | | | |
| img-to-pdf | | ✔️ | | | | | | | | ✔️ | |
| pdf-to-html | | ✔️ | | | ✔️ | | | ✔️ | | | |
| pdf-to-img | | ✔️ | | | | | | | | ✔️ | |
| pdf-to-pdfa | | ✔️ | | | ✔️ | | | | ✔️ | | |
| pdf-to-markdown | | ✔️ | | | | | | | | ✔️ | |
| pdf-to-presentation | | ✔️ | | | ✔️ | | | ✔️ | | | |
| pdf-to-text | | ✔️ | | | ✔️ | | | ✔️ | | | |
| pdf-to-word | | ✔️ | | | ✔️ | | | ✔️ | | | |
| pdf-to-xml | | ✔️ | | | ✔️ | | | ✔️ | | | |
| xlsx-to-pdf | | ✔️ | | | ✔️ | | | ✔️ | | | |
| add-password | | | ✔️ | | | | | | | ✔️ | |
| add-watermark | | | ✔️ | | | | | | | ✔️ | |
| cert-sign | | | ✔️ | | | | | | | ✔️ | |
| change-permissions | | | ✔️ | | | | | | | ✔️ | |
| remove-password | | | ✔️ | | | | | | | ✔️ | |
| sanitize-pdf | | | ✔️ | | | | | | | ✔️ | |
| add-image | | | | ✔️ | | | | | | ✔️ | |
| add-page-numbers | | | | ✔️ | | | | | | ✔️ | |
| auto-rename | | | | ✔️ | | | | | | ✔️ | |
| change-metadata | | | | ✔️ | | | | | | ✔️ | |
| compare | | | | ✔️ | | | | | | | ✔️ |
| compress-pdf | | | | ✔️ | ✔️ | | | | ✔️ | | |
| extract-image-scans | | | | ✔️ | ✔️ | ✔️ | ✔️ | | | | |
| extract-images | | | | ✔️ | | | | | | ✔️ | |
| flatten | | | | ✔️ | | | | | | | ✔️ |
| get-info-on-pdf | | | | ✔️ | | | | | | ✔️ | |
| ocr-pdf | | | | ✔️ | ✔️ | | | | ✔️ | | |
| remove-blanks | | | | ✔️ | ✔️ | ✔️ | ✔️ | | | | |
| repair | | | | ✔️ | ✔️ | | | ✔️ | | | |
| show-javascript | | | | ✔️ | | | | | | | ✔️ |
| sign | | | | ✔️ | | | | | | | ✔️ |

View File

@@ -9,13 +9,13 @@ Fork Stirling-PDF and make a new branch out of Main
Then add reference to the language in the navbar by adding a new language entry to the dropdown
https://github.com/Stirling-Tools/Stirling-PDF/blob/main/src/main/resources/templates/fragments/languages.html
and add a flag svg file to
and add a flag svg file to
https://github.com/Stirling-Tools/Stirling-PDF/tree/main/src/main/resources/static/images/flags
Any SVG flags are fine, i got most of mine from [here](https://flagicons.lipis.dev/)
If your language isnt represented by a flag just find whichever closely matches it, such as for Arabic i chose Saudi Arabia
If your language isn't represented by a flag just find whichever closely matches it, such as for Arabic i chose Saudi Arabia
For example to add Polish you would add
For example to add Polish you would add
```html
<a class="dropdown-item lang_dropdown-item" href="" data-language-code="pl_PL">
<img src="images/flags/pl.svg" alt="icon" width="20" height="15"> Polski
@@ -23,7 +23,7 @@ For example to add Polish you would add
```
The data-language-code is the code used to reference the file in the next step.
Start by copying the existing english property file
Start by copying the existing english property file
[https://github.com/Stirling-Tools/Stirling-PDF/blob/main/src/main/resources/messages_en_GB.properties](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/src/main/resources/messages_en_GB.properties)
@@ -32,7 +32,7 @@ Copy and rename it to messages_{your data-language-code here}.properties, in the
Then simply translate all property entries within that file and make a PR into main for others to use!
If you do not have a java IDE i am happy to verify the changes worked once you raise PR (but wont be able to verify the translations themselves)
If you do not have a java IDE i am happy to verify the changes worked once you raise PR (but won't be able to verify the translations themselves)

View File

@@ -2,12 +2,12 @@
This document provides instructions on how to add additional language packs for the OCR tab in Stirling-PDF, both inside and outside of Docker.
## My OCR used to work and now doesnt!
Please update your tesseract docker volume path version from 4.00 to 5
## My OCR used to work and now doesn't!
The paths have changed for the tessadata locations on new docker images, please use ``/usr/share/tessdata`` (Others should still work for backwards compatability but might not)
## How does the OCR Work
Stirling-PDF uses [OCRmyPDF](https://github.com/ocrmypdf/OCRmyPDF) which in turn uses tesseract for its text recognition.
All credit goes to them for this awesome work!
All credit goes to them for this awesome work!
## Language Packs
@@ -21,13 +21,13 @@ Depending on your requirements, you can choose the appropriate language pack for
### Installing Language Packs
1. Download the desired language pack(s) by selecting the `.traineddata` file(s) for the language(s) you need.
2. Place the `.traineddata` files in the Tesseract tessdata directory: `/usr/share/tesseract-ocr/5/tessdata` (Debian) or `/usr/share/tesseract/tessdata` (Fedora)
2. Place the `.traineddata` files in the Tesseract tessdata directory: `/usr/share/tessdata`
# DO NOT REMOVE EXISTING ENG.TRAINEDDATA, IT'S REQUIRED.
#### Docker
If you are using Docker, you need to expose the Tesseract tessdata directory as a volume in order to use the additional language packs.
If you are using Docker, you need to expose the Tesseract tessdata directory as a volume in order to use the additional language packs.
#### Docker Compose
Modify your `docker-compose.yml` file to include the following volume configuration:
@@ -37,14 +37,14 @@ services:
your_service_name:
image: your_docker_image_name
volumes:
- /location/of/trainingData:/usr/share/tesseract-ocr/5/tessdata
- /location/of/trainingData:/usr/share/tessdata
```
#### Docker run
Add the following to your existing docker run command
```bash
-v /location/of/trainingData:/usr/share/tesseract-ocr/5/tessdata
-v /location/of/trainingData:/usr/share/tessdata
```
#### Non-Docker

88
Jenkinsfile vendored
View File

@@ -1,45 +1,45 @@
pipeline {
agent any
stages {
stage('Build') {
steps {
sh 'chmod 755 gradlew'
sh './gradlew build'
}
}
stage('Docker Build') {
steps {
script {
def appVersion = sh(returnStdout: true, script: './gradlew printVersion -q').trim()
def image = "frooodle/s-pdf:$appVersion"
sh "docker build -t $image ."
}
}
}
stage('Docker Push') {
steps {
script {
def appVersion = sh(returnStdout: true, script: './gradlew printVersion -q').trim()
def image = "frooodle/s-pdf:$appVersion"
withCredentials([string(credentialsId: 'docker_hub_access_token', variable: 'DOCKER_HUB_ACCESS_TOKEN')]) {
sh "docker login --username frooodle --password $DOCKER_HUB_ACCESS_TOKEN"
sh "docker push $image"
}
}
}
}
stage('Helm Push') {
steps {
script {
//TODO: Read chartVersion from Chart.yaml
def chartVersion = '1.0.0'
withCredentials([string(credentialsId: 'docker_hub_access_token', variable: 'DOCKER_HUB_ACCESS_TOKEN')]) {
sh "docker login --username frooodle --password $DOCKER_HUB_ACCESS_TOKEN"
sh "helm package chart/stirling-pdf"
sh "helm push stirling-pdf-chart-1.0.0.tgz oci://registry-1.docker.io/frooodle"
}
}
}
}
}
pipeline {
agent any
stages {
stage('Build') {
steps {
sh 'chmod 755 gradlew'
sh './gradlew build'
}
}
stage('Docker Build') {
steps {
script {
def appVersion = sh(returnStdout: true, script: './gradlew printVersion -q').trim()
def image = "frooodle/s-pdf:$appVersion"
sh "docker build -t $image ."
}
}
}
stage('Docker Push') {
steps {
script {
def appVersion = sh(returnStdout: true, script: './gradlew printVersion -q').trim()
def image = "frooodle/s-pdf:$appVersion"
withCredentials([string(credentialsId: 'docker_hub_access_token', variable: 'DOCKER_HUB_ACCESS_TOKEN')]) {
sh "docker login --username frooodle --password $DOCKER_HUB_ACCESS_TOKEN"
sh "docker push $image"
}
}
}
}
stage('Helm Push') {
steps {
script {
//TODO: Read chartVersion from Chart.yaml
def chartVersion = '1.0.0'
withCredentials([string(credentialsId: 'docker_hub_access_token', variable: 'DOCKER_HUB_ACCESS_TOKEN')]) {
sh "docker login --username frooodle --password $DOCKER_HUB_ACCESS_TOKEN"
sh "helm package chart/stirling-pdf"
sh "helm push stirling-pdf-chart-1.0.0.tgz oci://registry-1.docker.io/frooodle"
}
}
}
}
}
}

View File

@@ -45,7 +45,7 @@ sudo apt-get update
sudo apt-get install -y git automake autoconf libtool libleptonica-dev pkg-config zlib1g-dev make g++ java-17-openjdk python3 python3-pip
```
For Fedora-based systems use this command:
For Fedora-based systems use this command:
```bash
sudo dnf install -y git automake autoconf libtool leptonica-devel pkg-config zlib-devel make gcc-c++ java-17-openjdk python3 python3-pip
@@ -65,7 +65,7 @@ sudo make install
```
### Step 3: Install Additional Software
Next we need to install LibreOffice for conversions, ocrmypdf for OCR, and opencv for patern recognition functionality.
Next we need to install LibreOffice for conversions, ocrmypdf for OCR, and opencv for pattern recognition functionality.
Install the following software:
@@ -95,14 +95,14 @@ For Debian-based systems, you can use the following command:
```bash
sudo apt-get install -y libreoffice-writer libreoffice-calc libreoffice-impress unpaper ocrmypdf
pip3 install uno opencv-python-headless unoconv pngquant WeasyPrint
pip3 install uno opencv-python-headless unoconv pngquant WeasyPrint
```
For Fedora:
```bash
sudo dnf install -y libreoffice-writer libreoffice-calc libreoffice-impress unpaper ocrmypdf
pip3 install uno opencv-python-headless unoconv pngquant WeasyPrint
pip3 install uno opencv-python-headless unoconv pngquant WeasyPrint
```
### Step 4: Clone and Build Stirling-PDF
@@ -139,8 +139,8 @@ Easiest is to use the langpacks provided by your repositories. Skip the other st
Manual:
1. Download the desired language pack(s) by selecting the `.traineddata` file(s) for the language(s) you need.
2. Place the `.traineddata` files in the Tesseract tessdata directory: `/usr/share/tesseract-ocr/5/tessdata`
3.
2. Place the `.traineddata` files in the Tesseract tessdata directory: `/usr/share/tessdata`
3.
Please view [OCRmyPDF install guide](https://ocrmypdf.readthedocs.io/en/latest/installation.html) for more info.
**IMPORTANT:** DO NOT REMOVE EXISTING `eng.traineddata`, IT'S REQUIRED.
@@ -264,10 +264,10 @@ sudo systemctl restart stirlingpdf.service
Remember to set the necessary environment variables before running the project if you want to customize the application the list can be seen in the main readme.
You can do this in the terminal by using the `export` command or -D arguements to java -jar command:
You can do this in the terminal by using the `export` command or -D argument to java -jar command:
```bash
export APP_HOME_NAME="Stirling PDF"
or
-DAPP_HOME_NAME="Stirling PDF"
-DAPP_HOME_NAME="Stirling PDF"
```

View File

@@ -6,7 +6,7 @@
[![Docker Image Version (tag latest semver)](https://img.shields.io/docker/v/frooodle/s-pdf/latest)](https://github.com/Stirling-Tools/Stirling-PDF/)
[![GitHub Repo stars](https://img.shields.io/github/stars/stirling-tools/stirling-pdf?style=social)](https://github.com/Stirling-Tools/stirling-pdf)
[![Paypal Donate](https://img.shields.io/badge/Paypal%20Donate-yellow?style=flat&logo=paypal)](https://www.paypal.com/paypalme/froodleplex)
[![Github Sponser](https://img.shields.io/badge/Github%20Sponsor-yellow?style=flat&logo=github)](https://github.com/sponsors/Frooodle)
[![Github Sponsor](https://img.shields.io/badge/Github%20Sponsor-yellow?style=flat&logo=github)](https://github.com/sponsors/Frooodle)
[![Deploy to DO](https://www.deploytodo.com/do-btn-blue.svg)](https://cloud.digitalocean.com/apps/new?repo=https://github.com/Stirling-Tools/Stirling-PDF/tree/digitalOcean&refcode=c3210994b1af)
@@ -110,7 +110,7 @@ Docker Run
```bash
docker run -d \
-p 8080:8080 \
-v /location/of/trainingData:/usr/share/tesseract-ocr/5/tessdata \
-v /location/of/trainingData:/usr/share/tessdata \
-v /location/of/extraConfigs:/configs \
-v /location/of/logs:/logs \
-e DOCKER_ENABLE_SECURITY=false \
@@ -131,7 +131,7 @@ services:
ports:
- '8080:8080'
volumes:
- /location/of/trainingData:/usr/share/tesseract-ocr/5/tessdata #Required for extra OCR languages
- /location/of/trainingData:/usr/share/tessdata #Required for extra OCR languages
- /location/of/extraConfigs:/configs
# - /location/of/customFiles:/customFiles/
# - /location/of/logs:/logs/
@@ -172,7 +172,7 @@ Stirling PDF currently supports 26!
- Hindi (हिंदी) (hi_IN)
- Hungarian (Magyar) (hu_HU)
- Bulgarian (Български) (bg_BG)
- Sebian Latin alphabet (Srpski) (sr-Latn-RS)
- Sebian Latin alphabet (Srpski) (sr_LATN_RS)
## Contributing (creating issues, translations, fixing bugs, etc.)
@@ -262,7 +262,7 @@ For API usage you must provide a header with 'X-API-Key' and the associated API
- Redact text (Via UI not just automated way)
- Add Forms
- Multi page layout (Stich PDF pages together) support x rows y columns and custom page sizing
- Fill forms mannual and automatic
- Fill forms manually or automatically
### Q2: Why is my application downloading .htm files?
This is an issue caused commonly by your NGINX configuration. 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.

View File

@@ -1,64 +1,64 @@
|Technology | Ultra-Lite | Lite | Full |
|----------------|:----------:|:----:|:----:|
| Java | ✔️ | ✔️ | ✔️ |
| JavaScript | ✔️ | ✔️ | ✔️ |
| Libre | | ✔️ | ✔️ |
| Python | | | ✔️ |
| OpenCV | | | ✔️ |
| OCRmyPDF | | | ✔️ |
Operation | Ultra-Lite | Lite | Full
--------------------|------------|------|-----
add-page-numbers | ✔️ | ✔️ | ✔️
add-password | ✔️ | ✔️ | ✔️
add-image | ✔️ | ✔️ | ✔️
add-watermark | ✔️ | ✔️ | ✔️
adjust-contrast | ✔️ | ✔️ | ✔️
auto-split-pdf | ✔️ | ✔️ | ✔️
auto-redact | ✔️ | ✔️ | ✔️
auto-rename | ✔️ | ✔️ | ✔️
cert-sign | ✔️ | ✔️ | ✔️
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 | ✔️ | ✔️ | ✔️
overlay-pdf | ✔️ | ✔️ | ✔️
pdf-organizer | ✔️ | ✔️ | ✔️
pdf-to-csv | ✔️ | ✔️ | ✔️
pdf-to-img | ✔️ | ✔️ | ✔️
pdf-to-single-page | ✔️ | ✔️ | ✔️
remove-pages | ✔️ | ✔️ | ✔️
remove-password | ✔️ | ✔️ | ✔️
rotate-pdf | ✔️ | ✔️ | ✔️
sanitize-pdf | ✔️ | ✔️ | ✔️
scale-pages | ✔️ | ✔️ | ✔️
sign | ✔️ | ✔️ | ✔️
show-javascript | ✔️ | ✔️ | ✔️
split-by-size-or-count | ✔️ | ✔️ | ✔️
split-pdf-by-sections | ✔️ | ✔️ | ✔️
split-pdfs | ✔️ | ✔️ | ✔️
file-to-pdf | | ✔️ | ✔️
pdf-to-html | | ✔️ | ✔️
pdf-to-presentation | | ✔️ | ✔️
pdf-to-text | | ✔️ | ✔️
pdf-to-word | | ✔️ | ✔️
pdf-to-xml | | ✔️ | ✔️
repair | | ✔️ | ✔️
xlsx-to-pdf | | ✔️ | ✔️
compress-pdf | | | ✔️
extract-image-scans | | | ✔️
ocr-pdf | | | ✔️
pdf-to-pdfa | | | ✔️
remove-blanks | | | ✔️
|Technology | Ultra-Lite | Lite | Full |
|----------------|:----------:|:----:|:----:|
| Java | ✔️ | ✔️ | ✔️ |
| JavaScript | ✔️ | ✔️ | ✔️ |
| Libre | | ✔️ | ✔️ |
| Python | | | ✔️ |
| OpenCV | | | ✔️ |
| OCRmyPDF | | | ✔️ |
Operation | Ultra-Lite | Lite | Full
--------------------|------------|------|-----
add-page-numbers | ✔️ | ✔️ | ✔️
add-password | ✔️ | ✔️ | ✔️
add-image | ✔️ | ✔️ | ✔️
add-watermark | ✔️ | ✔️ | ✔️
adjust-contrast | ✔️ | ✔️ | ✔️
auto-split-pdf | ✔️ | ✔️ | ✔️
auto-redact | ✔️ | ✔️ | ✔️
auto-rename | ✔️ | ✔️ | ✔️
cert-sign | ✔️ | ✔️ | ✔️
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 | ✔️ | ✔️ | ✔️
overlay-pdf | ✔️ | ✔️ | ✔️
pdf-organizer | ✔️ | ✔️ | ✔️
pdf-to-csv | ✔️ | ✔️ | ✔️
pdf-to-img | ✔️ | ✔️ | ✔️
pdf-to-single-page | ✔️ | ✔️ | ✔️
remove-pages | ✔️ | ✔️ | ✔️
remove-password | ✔️ | ✔️ | ✔️
rotate-pdf | ✔️ | ✔️ | ✔️
sanitize-pdf | ✔️ | ✔️ | ✔️
scale-pages | ✔️ | ✔️ | ✔️
sign | ✔️ | ✔️ | ✔️
show-javascript | ✔️ | ✔️ | ✔️
split-by-size-or-count | ✔️ | ✔️ | ✔️
split-pdf-by-sections | ✔️ | ✔️ | ✔️
split-pdfs | ✔️ | ✔️ | ✔️
file-to-pdf | | ✔️ | ✔️
pdf-to-html | | ✔️ | ✔️
pdf-to-presentation | | ✔️ | ✔️
pdf-to-text | | ✔️ | ✔️
pdf-to-word | | ✔️ | ✔️
pdf-to-xml | | ✔️ | ✔️
repair | | ✔️ | ✔️
xlsx-to-pdf | | ✔️ | ✔️
compress-pdf | | | ✔️
extract-image-scans | | | ✔️
ocr-pdf | | | ✔️
pdf-to-pdfa | | | ✔️
remove-blanks | | | ✔️

View File

@@ -12,7 +12,7 @@ plugins {
import com.github.jk1.license.render.*
group = 'stirling.software'
version = '0.20.2'
version = '0.21.0'
sourceCompatibility = '17'
repositories {
@@ -89,10 +89,10 @@ dependencies {
//security updates
implementation 'ch.qos.logback:logback-classic:1.4.14'
implementation 'ch.qos.logback:logback-core:1.4.14'
implementation 'org.springframework:spring-webmvc:6.1.2'
implementation 'org.springframework:spring-webmvc:6.1.3'
implementation("io.github.pixee:java-security-toolkit:1.1.2")
implementation 'org.yaml:snakeyaml:2.2'
implementation 'org.springframework.boot:spring-boot-starter-web:3.2.2'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf:3.2.2'
@@ -101,7 +101,7 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-security:3.2.2'
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5:3.1.2.RELEASE'
implementation "org.springframework.boot:spring-boot-starter-data-jpa:3.2.2"
//2.2.x requires rebuild of DB file.. need migration path
implementation "com.h2database:h2:2.1.214"
}
@@ -138,19 +138,19 @@ dependencies {
implementation ('com.opencsv:opencsv:5.9') {
exclude group: 'commons-logging', module: 'commons-logging'
}
implementation ('org.apache.pdfbox:pdfbox:3.0.1'){
exclude group: 'commons-logging', module: 'commons-logging'
}
implementation ('org.apache.pdfbox:xmpbox:3.0.1'){
exclude group: 'commons-logging', module: 'commons-logging'
}
implementation 'org.bouncycastle:bcprov-jdk18on:1.77'
implementation 'org.bouncycastle:bcpkix-jdk18on:1.77'
implementation 'org.springframework.boot:spring-boot-starter-actuator:3.2.2'
implementation 'io.micrometer:micrometer-core:1.12.2'
implementation 'io.micrometer:micrometer-core:1.12.3'
implementation group: 'com.google.zxing', name: 'core', version: '3.5.2'
// https://mvnrepository.com/artifact/org.commonmark/commonmark
implementation 'org.commonmark:commonmark:0.21.0'

View File

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

View File

@@ -43,6 +43,6 @@ spec:
name: http
{{- end }}
protocol: TCP
selector:
{{- include "stirlingpdf.selectorLabels" . | nindent 4 }}

View File

@@ -16,11 +16,11 @@ commonLabels: {}
# team_name: dev
envs: []
# - name: PP_HOME_NAME
# - name: UI_APP_NAME
# value: "Stirling PDF"
# - name: APP_HOME_DESCRIPTION
# - name: UI_HOME_DESCRIPTION
# value: "Your locally hosted one-stop-shop for all your PDF needs."
# - name: APP_NAVBAR_NAME
# - name: UI_APP_NAVBAR_NAME
# value: "Stirling PDF"
# - name: ALLOW_GOOGLE_VISIBILITY
# value: "true"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 8.7 KiB

View File

@@ -1,310 +1,110 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg
width="99.537987mm"
height="95.209366mm"
viewBox="0 0 99.537987 95.209366"
version="1.1"
id="svg745"
id="Layer_1"
x="0px"
y="0px"
viewBox="0 0 512 512"
style="enable-background:new 0 0 512 512;"
xml:space="preserve"
inkscape:version="1.2.1 (9c6d41e4, 2022-07-14)"
sodipodi:docname="stirling.svg"
inkscape:export-filename="stirling.png"
inkscape:export-xdpi="80"
inkscape:export-ydpi="80"
sodipodi:docname="favicon.svg"
inkscape:version="1.2.2 (732a01da63, 2022-12-09)"
inkscape:export-filename="favicon.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
id="namedview747"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="0.914906"
inkscape:cx="184.17193"
inkscape:cy="509.88845"
inkscape:window-width="2293"
inkscape:window-height="1387"
inkscape:window-x="122"
inkscape:window-y="25"
inkscape:window-maximized="0"
inkscape:current-layer="svg745" /><defs
id="defs742"><linearGradient
inkscape:collect="always"
id="linearGradient72198"><stop
style="stop-color:#ccd6d7;stop-opacity:1;"
offset="0"
id="stop72194" /><stop
style="stop-color:#0f3a3f;stop-opacity:1;"
offset="1"
id="stop72196" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient71928"><stop
style="stop-color:#4b0005;stop-opacity:1;"
offset="0"
id="stop71924" /><stop
style="stop-color:#8f000c;stop-opacity:1;"
offset="1"
id="stop71926" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient71920"><stop
style="stop-color:#4b0005;stop-opacity:1;"
offset="0"
id="stop71916" /><stop
style="stop-color:#8f000c;stop-opacity:1;"
offset="1"
id="stop71918" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient69598"><stop
style="stop-color:#6a0007;stop-opacity:1;"
offset="0"
id="stop69594" /><stop
style="stop-color:#b8000f;stop-opacity:1;"
offset="1"
id="stop69596" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient46361"><stop
style="stop-color:#f7f6f8;stop-opacity:1;"
offset="0"
id="stop46359" /><stop
style="stop-color:#b7b7b5;stop-opacity:1;"
offset="1"
id="stop46357" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient40554"><stop
style="stop-color:#f4f2f4;stop-opacity:1;"
offset="0"
id="stop40550" /><stop
style="stop-color:#57767b;stop-opacity:1;"
offset="1"
id="stop40552" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient39095"><stop
style="stop-color:#285459;stop-opacity:1;"
offset="0"
id="stop39093" /><stop
style="stop-color:#a6b6af;stop-opacity:1;"
offset="1"
id="stop39091" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient36672"><stop
style="stop-color:#da453f;stop-opacity:1;"
offset="0"
id="stop36668" /><stop
style="stop-color:#a60008;stop-opacity:1;"
offset="1"
id="stop36670" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient19524"><stop
style="stop-color:#3a4b4f;stop-opacity:1;"
offset="0"
id="stop19522" /><stop
style="stop-color:#617979;stop-opacity:0.97461927;"
offset="1"
id="stop19520" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient17996"><stop
style="stop-color:#401016;stop-opacity:1;"
offset="0"
id="stop17994" /><stop
style="stop-color:#761f19;stop-opacity:1;"
offset="1"
id="stop17992" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient15569"><stop
style="stop-color:#8ea8ad;stop-opacity:1;"
offset="0"
id="stop15565" /><stop
style="stop-color:#e9e7eb;stop-opacity:1;"
offset="1"
id="stop15567" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient15557"><stop
style="stop-color:#9b0e11;stop-opacity:1;"
offset="0"
id="stop15553" /><stop
style="stop-color:#370707;stop-opacity:1;"
offset="1"
id="stop15555" /></linearGradient><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient15557"
id="linearGradient15559"
x1="120.06672"
y1="63.25761"
x2="135.16347"
y2="78.078682"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient15569"
id="linearGradient15571"
x1="127.97037"
y1="101.66144"
x2="133.88971"
y2="104.77026"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient17996"
id="linearGradient17998"
x1="117.9284"
y1="86.055084"
x2="130.67392"
y2="76.945541"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient19524"
id="linearGradient19528"
x1="130.98172"
y1="82.402977"
x2="135.72115"
y2="86.45166"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient36672"
id="linearGradient36674"
x1="63.797714"
y1="74.81752"
x2="96.636673"
y2="120.29293"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient39095"
id="linearGradient39097"
x1="120.54506"
y1="124.76902"
x2="128.04152"
y2="126.0704"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient40554"
id="linearGradient40556"
x1="113.84585"
y1="114.04285"
x2="119.65858"
y2="128.50244"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient46361"
id="linearGradient46363"
x1="73.993439"
y1="114.13906"
x2="94.845322"
y2="71.247383"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient69598"
id="linearGradient69600"
x1="95.854446"
y1="114.66749"
x2="103.77842"
y2="120.1887"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient71920"
id="linearGradient71922"
x1="98.580376"
y1="87.186958"
x2="118.09738"
y2="101.19449"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient71928"
id="linearGradient71930"
x1="78.278267"
y1="97.433273"
x2="92.313202"
y2="104.33479"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient72198"
id="linearGradient72200"
x1="125.76636"
y1="138.46817"
x2="123.3327"
y2="126.03291"
gradientUnits="userSpaceOnUse" /></defs><g
inkscape:groupmode="layer"
id="layer4"
inkscape:label="background"
style="display:inline"
sodipodi:insensitive="true"
transform="translate(-51.420144,-44.470286)"><rect
style="display:inline;fill:#ccd6d7;fill-opacity:1;stroke:none;stroke-width:4.13755;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:3.2"
id="rect72067"
width="99.481979"
height="94.999512"
x="51.476147"
y="44.680138" /></g><g
inkscape:groupmode="layer"
id="layer5"
inkscape:label="shadow"
style="display:inline"
sodipodi:insensitive="true"
transform="translate(-51.420144,-44.470286)"><path
style="display:inline;fill:url(#linearGradient72200);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 84.146049,134.73858 c 0,0 11.721038,2.48294 17.938661,2.91673 6.21763,0.43378 14.75251,0.59994 22.41237,-0.43379 8.01008,-1.081 13.19907,-2.22733 14.50043,-2.66112 1.30136,-0.43379 4.00784,-1.24297 4.15244,-2.25514 0.1446,-1.01217 -3.4703,-2.74733 -6.21763,-3.32571 -2.74732,-0.57838 -12.72444,-1.44596 -14.89337,-1.44596 -2.16894,0 -37.892901,7.20499 -37.892901,7.20499 z"
id="path72192"
sodipodi:nodetypes="cssssssc" /></g><g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Origami"
style="display:inline"
sodipodi:insensitive="true"
transform="translate(-51.420144,-44.470286)"><path
style="display:inline;fill:url(#linearGradient40556);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 84.460552,134.86721 35.165798,-6.85679 16.15467,-42.7383 z"
id="path960"
sodipodi:nodetypes="cccc" /><path
style="fill:url(#linearGradient15571);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 135.71493,85.428056 0.3984,45.049024 -9.66213,-20.46173 z"
id="path964"
sodipodi:nodetypes="cccc" /><path
style="display:inline;fill:url(#linearGradient39097);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 119.60518,128.00293 16.5337,2.48693 -9.68769,-20.5512 z"
id="path966"
sodipodi:nodetypes="cccc" /><path
style="display:inline;fill:url(#linearGradient15559);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 118.42209,57.022622 12.70423,-2.766809 -0.0785,25.087175 -12.43878,-13.376518 z"
id="path968"
sodipodi:nodetypes="ccccc" /><path
style="display:inline;fill:url(#linearGradient19528);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 135.72114,85.386768 -4.84219,-6.459493 0.0305,11.126604 z"
id="path970"
sodipodi:nodetypes="cccc" /><path
style="display:inline;fill:url(#linearGradient17998);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 119.10273,65.682415 11.96883,13.44935 -0.0899,10.819868 -11.88577,11.430427 z"
id="path972"
sodipodi:nodetypes="ccccc" /><path
style="display:inline;fill:url(#linearGradient36674);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 62.145635,130.15618 62.043392,65.435258 c 0,0 0.179321,-2.778132 1.89516,-4.036097 1.874923,-1.374597 4.341768,-1.894096 4.341768,-1.894096 l 50.91788,-11.349167 -0.0113,53.144272 -34.733274,33.56547 z"
id="path958"
sodipodi:nodetypes="ccsccccc" /></g><g
inkscape:groupmode="layer"
id="layer3"
inkscape:label="Letter"
style="display:inline"
sodipodi:insensitive="true"
transform="translate(-51.420144,-44.470286)"><path
style="display:inline;fill:url(#linearGradient69600);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 94.780881,91.406803 16.870379,17.074877 -23.723345,23.00249 -18.122131,-17.99816 5.497473,-2.80607 18.404054,-0.0511 2.35163,-8.23071 z"
id="path54894"
sodipodi:nodetypes="cccccccc" /><path
style="display:inline;fill:url(#linearGradient71930);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 72.440405,92.224764 16.15467,15.745686 4.089788,-6.79927 z"
id="path54892" /><path
style="display:inline;fill:url(#linearGradient71922);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 95.138739,84.965385 1.124691,-14.109776 22.92453,22.286787 0.008,8.164604 -3.28863,3.16649 z"
id="path54890"
sodipodi:nodetypes="cccccc"
inkscape:label="path54890" /><path
style="display:inline;fill:url(#linearGradient46363);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 95.138739,84.965385 h 1.226936 l -0.05112,-14.109776 c 0,0 -5.776827,-3.220709 -12.167126,-2.40275 -6.390296,0.817957 -8.151582,2.1248 -10.58233,4.396523 -1.90229,1.777838 -2.913974,3.527446 -3.987546,7.157132 -0.512646,1.733226 -0.281963,5.988892 0.613471,8.537436 0.664591,1.891528 2.453873,4.294281 4.958868,6.134686 2.662335,1.956002 8.281825,3.527443 8.281825,3.527443 0,0 5.134614,1.887351 5.572338,4.294281 0.308137,1.69437 -0.102243,3.22071 -1.635914,4.95887 -1.258314,1.42609 -3.62969,1.99377 -6.288054,1.07357 -2.658364,-0.92021 -6.139514,-3.85065 -7.106009,-4.90775 -0.817958,-0.89464 -2.820665,-3.06173 -2.890231,-4.294021 -0.01209,-0.214205 -1.229505,-0.0963 -1.229505,-0.0963 l -0.0723,14.256941 5.879073,2.24938 c 0,0 5.214483,1.78929 8.946415,1.43143 3.731934,-0.35786 7.617235,-0.51122 11.604778,-5.16336 3.987542,-4.65213 3.680812,-12.831715 2.147141,-15.899056 -1.533673,-3.067344 -3.561212,-6.138812 -10.480087,-8.281826 -5.776829,-1.789283 -7.872846,-3.01622 -8.128458,-4.396524 -0.255611,-1.380305 0.0091,-4.253646 2.760607,-5.214481 3.220711,-1.124693 5.623462,-0.05112 7.05489,1.12469 1.431425,1.175817 5.572339,5.623462 5.572339,5.623462 z"
id="path46355"
sodipodi:nodetypes="cccssssscssssscccssssssscc" /></g></svg>
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs173">
<linearGradient
id="XMLID_5_"
gradientUnits="userSpaceOnUse"
x1="304.496"
y1="422.9102"
x2="316.036"
y2="326.2626">
<stop
offset="0"
style="stop-color:#DCF1F3"
id="stop156" />
<stop
offset="1"
style="stop-color:#C2C2C9"
id="stop158" />
</linearGradient>
</defs><sodipodi:namedview
id="namedview171"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="1.4142136"
inkscape:cx="219.91021"
inkscape:cy="232.63813"
inkscape:window-width="3840"
inkscape:window-height="2054"
inkscape:window-x="2869"
inkscape:window-y="-11"
inkscape:window-maximized="1"
inkscape:current-layer="XMLID_4_" />
<style
type="text/css"
id="style150">
.st0{fill:#FFFFFF;}
.st1{fill:#C02223;}
.st2{fill:#882425;}
.st3{fill:url(#XMLID_5_);}
.st4{fill:url(#XMLID_7_);}
</style>
<g
id="XMLID_4_">
<path
id="XMLID_131_"
class="st1"
d="M 347.01402,14.355825 98.978019,69.02261 C 73.825483,74.547445 55.942464,96.792175 55.942464,122.52628 v 315.06096 c 0,22.39012 16.719895,41.14548 38.819234,43.76251 L 224.8861,498.36042 339.48636,384.26465 455.76603,265.15425 453.73057,84.870162 C 453.43979,62.916214 433.08513,46.632491 411.71274,51.284984 l -28.78729,6.251786 0.14539,-13.666697 C 383.36162,24.678542 365.62399,10.284894 347.01402,14.355825 Z"
sodipodi:nodetypes="ccssccccccccc"
style="stroke-width:1.45391" /><path
id="XMLID_117_"
class="st2"
d="m 383.21622,57.53677 v 285.8375 L 456.05681,265.00885 454.02135,78.763767 C 453.87595,59.863016 436.28372,45.905539 417.81914,49.97647 Z"
style="stroke-width:1.45391" /><polygon
id="XMLID_18_"
class="st3"
points="234.7,422.6 368.5,387.7 393.5,262.2 "
style="fill:url(#XMLID_5_)"
transform="matrix(1.4556308,0,0,1.4548265,-116.73161,-116.45231)" />
<linearGradient
id="XMLID_7_"
gradientUnits="userSpaceOnUse"
x1="223.0838"
y1="372.7559"
x2="241.4174"
y2="114.557"
gradientTransform="matrix(1.4539039,0,0,1.4539039,-116.19976,-116.20474)">
<stop
offset="0"
style="stop-color:#DCF1F3"
id="stop163" />
<stop
offset="1"
style="stop-color:#C2C2C9"
id="stop165" />
</linearGradient>
<path
id="XMLID_6_"
class="st4"
d="m 282.89686,214.84917 c 0,0 -22.24473,-28.93269 -38.67384,-36.78377 -10.46811,-4.94327 -26.02489,-6.83335 -38.23768,-0.72695 -18.02841,9.0142 -19.91848,34.31213 -3.34397,44.34406 3.92553,2.47165 9.15959,4.50711 15.99294,6.10641 36.63838,8.43264 97.12077,25.87949 89.70587,96.10304 0,0 -4.21633,65.86185 -73.56753,73.42215 -12.2128,1.30851 -24.57098,0.43617 -36.493,-2.32625 -16.42911,-3.63476 -45.50719,-11.04967 -59.75545,-19.91849 l -2.61703,-75.16682 h 6.97875 c 0,0 13.81208,33.43978 53.06749,49.57812 7.26952,2.90781 15.26599,4.07093 22.97168,2.90781 9.74116,-1.45391 21.22699,-6.68796 25.87949,-22.53551 0,0 7.85108,-23.11707 -32.85823,-35.76604 -32.56744,-10.17733 -63.24481,-20.64543 -75.89378,-54.95757 -5.961,-16.28371 -6.97874,-34.31212 -2.90781,-51.61358 5.37944,-22.53551 20.79082,-54.23062 64.40794,-67.89732 0,0 57.28381,-15.55677 96.53922,5.52484 l -1.74468,89.70587 z"
style="fill:url(#XMLID_7_);stroke-width:1.45391" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

@@ -15,7 +15,7 @@ services:
ports:
- 8080:8080
volumes:
- /stirling/latest/data:/usr/share/tesseract-ocr/5/tessdata:rw
- /stirling/latest/data:/usr/share/tessdata:rw
- /stirling/latest/config:/configs:rw
- /stirling/latest/logs:/logs:rw
environment:

View File

@@ -15,7 +15,7 @@ services:
ports:
- 8080:8080
volumes:
- /stirling/latest/data:/usr/share/tesseract-ocr/5/tessdata:rw
- /stirling/latest/data:/usr/share/tessdata:rw
- /stirling/latest/config:/configs:rw
- /stirling/latest/logs:/logs:rw
environment:

View File

@@ -15,7 +15,7 @@ services:
ports:
- 8080:8080
volumes:
- /stirling/latest/data:/usr/share/tesseract-ocr/5/tessdata:rw
- /stirling/latest/data:/usr/share/tessdata:rw
- /stirling/latest/config:/configs:rw
- /stirling/latest/logs:/logs:rw
environment:

View File

@@ -15,7 +15,7 @@ services:
ports:
- 8080:8080
volumes:
- /stirling/latest/data:/usr/share/tesseract-ocr/5/tessdata:rw
- /stirling/latest/data:/usr/share/tessdata:rw
- /stirling/latest/config:/configs:rw
- /stirling/latest/logs:/logs:rw
environment:

182
gradlew.bat vendored
View File

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

View File

@@ -1,37 +0,0 @@
import cv2
import sys
import argparse
import numpy as np
def is_blank_image(image_path, threshold=10, white_percent=99, white_value=255, blur_size=5):
image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
if image is None:
print(f"Error: Unable to read the image file: {image_path}")
return False
# Apply Gaussian blur to reduce noise
blurred_image = cv2.GaussianBlur(image, (blur_size, blur_size), 0)
_, thresholded_image = cv2.threshold(blurred_image, white_value - threshold, white_value, cv2.THRESH_BINARY)
# Calculate the percentage of white pixels in the thresholded image
white_pixels = np.sum(thresholded_image == white_value)
white_pixel_percentage = (white_pixels / thresholded_image.size) * 100
print(f"Page has white pixel percent of {white_pixel_percentage}")
return white_pixel_percentage >= white_percent
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Detect if an image is considered blank or not.')
parser.add_argument('image_path', help='The path to the image file.')
parser.add_argument('-t', '--threshold', type=int, default=10, help='Threshold for determining white pixels. The default value is 10.')
parser.add_argument('-w', '--white_percent', type=float, default=99, help='The percentage of white pixels for an image to be considered blank. The default value is 99.')
args = parser.parse_args()
blank = is_blank_image(args.image_path, args.threshold, args.white_percent)
# Return code 1: The image is considered blank.
# Return code 0: The image is not considered blank.
sys.exit(int(blank))

View File

@@ -4,7 +4,7 @@ if [ "$DOCKER_ENABLE_SECURITY" = "true" ] && [ "$VERSION_TAG" != "alpha" ]; then
if [ ! -f app-security.jar ]; then
echo "Trying to download from: https://github.com/Stirling-Tools/Stirling-PDF/releases/download/v$VERSION_TAG/Stirling-PDF-with-login.jar"
curl -L -o app-security.jar https://github.com/Stirling-Tools/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/Stirling-Tools/Stirling-PDF/releases/download/$VERSION_TAG/Stirling-PDF-with-login.jar"

View File

@@ -2,11 +2,15 @@
# Copy the original tesseract-ocr files to the volume directory without overwriting existing files
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
mkdir -p /usr/share/tessdata
cp -rn /usr/share/tessdata-original/* /usr/share/tessdata
if [ -d /usr/share/tesseract-ocr/4.00/tessdata ]; then
cp -r /usr/share/tesseract-ocr/4.00/tessdata/* /usr/share/tesseract-ocr/5/tessdata/ || true;
if [ -d /usr/share/tesseract-ocr/4.00/tessdata ]; then
cp -r /usr/share/tesseract-ocr/4.00/tessdata/* /usr/share/tessdata || true;
fi
if [ -d /usr/share/tesseract-ocr/5/tessdata ]; then
cp -r /usr/share/tesseract-ocr/5/tessdata/* /usr/share/tessdata || true;
fi
# Check if TESSERACT_LANGS environment variable is set and is not empty
@@ -23,4 +27,4 @@ fi
/scripts/download-security-jar.sh
# Run the main command
exec "$@"
exec "$@"

View File

@@ -2,7 +2,7 @@ import argparse
import sys
import cv2
import numpy as np
import os
import os
def find_photo_boundaries(image, background_color, tolerance=30, min_area=10000, min_contour_area=500):
mask = cv2.inRange(image, background_color - tolerance, background_color + tolerance)
@@ -49,9 +49,9 @@ def auto_rotate(image, angle_threshold=1):
angles = []
for rho, theta in lines[:, 0]:
angles.append((theta * 180) / np.pi - 90)
angle = np.median(angles)
if abs(angle) < angle_threshold:
return image
@@ -65,16 +65,16 @@ def auto_rotate(image, angle_threshold=1):
def crop_borders(image, border_color, tolerance=30):
mask = cv2.inRange(image, border_color - tolerance, border_color + tolerance)
contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if len(contours) == 0:
return image
largest_contour = max(contours, key=cv2.contourArea)
x, y, w, h = cv2.boundingRect(largest_contour)
return image[y:y+h, x:x+w]
def split_photos(input_file, output_directory, tolerance=30, min_area=10000, min_contour_area=500, angle_threshold=10, border_size=0):
image = cv2.imread(input_file)
background_color = estimate_background_color(image)
@@ -110,7 +110,7 @@ if __name__ == "__main__":
parser.add_argument("--min_contour_area", type=int, default=500, help="Sets the minimum contour area threshold for a photo (default: 500).")
parser.add_argument("--angle_threshold", type=int, default=10, help="Sets the minimum absolute angle required for the image to be rotated (default: 10).")
parser.add_argument("--border_size", type=int, default=0, help="Sets the size of the border added and removed to prevent white borders in the output (default: 0).")
args = parser.parse_args()
split_photos(args.input_file, args.output_directory, tolerance=args.tolerance, min_area=args.min_area, min_contour_area=args.min_contour_area, angle_threshold=args.angle_threshold, border_size=args.border_size)

View File

@@ -1,12 +1,13 @@
package stirling.software.SPDF;
import io.github.pixee.security.SystemCommand;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import io.github.pixee.security.SystemCommand;
public class LibreOfficeListener {
private static final long ACTIVITY_TIMEOUT = 20 * 60 * 1000; // 20 minutes

View File

@@ -1,6 +1,5 @@
package stirling.software.SPDF;
import io.github.pixee.security.SystemCommand;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Collections;
@@ -11,6 +10,8 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.core.env.Environment;
import org.springframework.scheduling.annotation.EnableScheduling;
import io.github.pixee.security.SystemCommand;
import jakarta.annotation.PostConstruct;
import stirling.software.SPDF.config.ConfigInitializer;
import stirling.software.SPDF.utils.GeneralUtils;

View File

@@ -77,16 +77,11 @@ public class AppConfig {
return Files.exists(Paths.get("/.dockerenv"));
}
@Bean(name = "bookFormatsInstalled")
public boolean bookFormatsInstalled() {
return applicationProperties.getSystem().getCustomApplications().isInstallBookFormats();
}
@Bean(name = "htmlFormatsInstalled")
public boolean htmlFormatsInstalled() {
@Bean(name = "bookAndHtmlFormatsInstalled")
public boolean bookAndHtmlFormatsInstalled() {
return applicationProperties
.getSystem()
.getCustomApplications()
.isInstallAdvancedHtmlToPDF();
.isInstallBookAndHtmlFormats();
}
}

View File

@@ -79,6 +79,16 @@ public class ConfigInitializer
return parts.length > 0 ? parts[0].trim().replace("#", "").trim() : "";
};
Function<String, Integer> getIndentationLevel =
line -> {
int count = 0;
for (char ch : line.toCharArray()) {
if (ch == ' ') count++;
else break;
}
return count;
};
Set<String> userKeys = userLines.stream().map(extractKey).collect(Collectors.toSet());
for (String line : templateLines) {
@@ -134,10 +144,77 @@ public class ConfigInitializer
.map(extractKey)
.anyMatch(templateKey -> templateKey.equalsIgnoreCase(userKey));
if (!isPresentInTemplate && !isCommented.apply(userLine)) {
mergedLines.add(userLine);
if (!childOfTemplateEntry(
isCommented,
extractKey,
getIndentationLevel,
userLines,
userLine,
templateLines)) {
// check if userLine is a child of a entry within templateLines or not, if child
// of parent in templateLines then dont add to mergedLines, if anything else
// then add
mergedLines.add(userLine);
}
}
}
Files.write(outputPath, mergedLines, StandardCharsets.UTF_8);
}
// New method to check if a userLine is a child of an entry in templateLines
boolean childOfTemplateEntry(
Function<String, Boolean> isCommented,
Function<String, String> extractKey,
Function<String, Integer> getIndentationLevel,
List<String> userLines,
String userLine,
List<String> templateLines) {
String userKey = extractKey.apply(userLine).trim();
int userIndentation = getIndentationLevel.apply(userLine);
// Start by assuming the line is not a child of an entry in templateLines
boolean isChild = false;
// Iterate backwards through userLines from the current line to find any parent
for (int i = userLines.indexOf(userLine) - 1; i >= 0; i--) {
String potentialParentLine = userLines.get(i);
int parentIndentation = getIndentationLevel.apply(potentialParentLine);
// Check if we've reached a potential parent based on indentation
if (parentIndentation < userIndentation) {
String parentKey = extractKey.apply(potentialParentLine).trim();
// Now, check if this potential parent or any of its parents exist in templateLines
boolean parentExistsInTemplate =
templateLines.stream()
.filter(line -> !isCommented.apply(line)) // Skip commented lines
.anyMatch(
templateLine -> {
String templateKey =
extractKey.apply(templateLine).trim();
return parentKey.equalsIgnoreCase(templateKey);
});
if (!parentExistsInTemplate) {
// If the parent does not exist in template, check the next level parent
userIndentation =
parentIndentation; // Update userIndentation to the parent's indentation
// for next iteration
if (parentIndentation == 0) {
// If we've reached the top-level parent and it's not in template, the
// original line is considered not a child
isChild = false;
break;
}
} else {
// If any parent exists in template, the original line is considered a child
isChild = true;
break;
}
}
}
return isChild; // Return true if the line is not a child of any entry in templateLines
}
}

View File

@@ -16,7 +16,7 @@ import org.springframework.stereotype.Service;
import stirling.software.SPDF.model.ApplicationProperties;
@Service
@DependsOn({"bookFormatsInstalled"})
@DependsOn({"bookAndHtmlFormatsInstalled"})
public class EndpointConfiguration {
private static final Logger logger = LoggerFactory.getLogger(EndpointConfiguration.class);
private Map<String, Boolean> endpointStatuses = new ConcurrentHashMap<>();
@@ -24,14 +24,14 @@ public class EndpointConfiguration {
private final ApplicationProperties applicationProperties;
private boolean bookFormatsInstalled;
private boolean bookAndHtmlFormatsInstalled;
@Autowired
public EndpointConfiguration(
ApplicationProperties applicationProperties,
@Qualifier("bookFormatsInstalled") boolean bookFormatsInstalled) {
@Qualifier("bookAndHtmlFormatsInstalled") boolean bookAndHtmlFormatsInstalled) {
this.applicationProperties = applicationProperties;
this.bookFormatsInstalled = bookFormatsInstalled;
this.bookAndHtmlFormatsInstalled = bookAndHtmlFormatsInstalled;
init();
processEnvironmentConfigs();
}
@@ -140,7 +140,6 @@ public class EndpointConfiguration {
// CLI
addEndpointToGroup("CLI", "compress-pdf");
addEndpointToGroup("CLI", "extract-image-scans");
addEndpointToGroup("CLI", "remove-blanks");
addEndpointToGroup("CLI", "repair");
addEndpointToGroup("CLI", "pdf-to-pdfa");
addEndpointToGroup("CLI", "file-to-pdf");
@@ -218,6 +217,7 @@ public class EndpointConfiguration {
addEndpointToGroup("Java", "split-by-size-or-count");
addEndpointToGroup("Java", "overlay-pdf");
addEndpointToGroup("Java", "split-pdf-by-sections");
addEndpointToGroup("Java", "remove-blanks");
// Javascript
addEndpointToGroup("Javascript", "pdf-organizer");
@@ -229,7 +229,7 @@ public class EndpointConfiguration {
private void processEnvironmentConfigs() {
List<String> endpointsToRemove = applicationProperties.getEndpoints().getToRemove();
List<String> groupsToRemove = applicationProperties.getEndpoints().getGroupsToRemove();
if (!bookFormatsInstalled) {
if (!bookAndHtmlFormatsInstalled) {
groupsToRemove.add("Calibre");
}
if (endpointsToRemove != null) {

View File

@@ -26,12 +26,8 @@ public class PostStartupProcesses {
private boolean runningInDocker;
@Autowired
@Qualifier("bookFormatsInstalled")
private boolean bookFormatsInstalled;
@Autowired
@Qualifier("htmlFormatsInstalled")
private boolean htmlFormatsInstalled;
@Qualifier("bookAndHtmlFormatsInstalled")
private boolean bookAndHtmlFormatsInstalled;
private static final Logger logger = LoggerFactory.getLogger(PostStartupProcesses.class);
@@ -39,34 +35,11 @@ public class PostStartupProcesses {
public void runInstallCommandBasedOnEnvironment() throws IOException, InterruptedException {
List<List<String>> commands = new ArrayList<>();
// Checking for DOCKER_INSTALL_BOOK_FORMATS environment variable
if (bookFormatsInstalled) {
if (bookAndHtmlFormatsInstalled) {
List<String> tmpList = new ArrayList<>();
// Set up the timezone configuration commands
tmpList.addAll(
Arrays.asList(
"sh",
"-c",
"echo 'tzdata tzdata/Areas select Europe' | debconf-set-selections; "
+ "echo 'tzdata tzdata/Zones/Europe select Berlin' | debconf-set-selections"));
commands.add(tmpList);
// Install calibre with DEBIAN_FRONTEND set to noninteractive
tmpList = new ArrayList<>();
tmpList.addAll(
Arrays.asList(
"sh",
"-c",
"DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends calibre"));
commands.add(tmpList);
}
// Checking for DOCKER_INSTALL_HTML_FORMATS environment variable
if (htmlFormatsInstalled) {
List<String> tmpList = new ArrayList<>();
// Add -y flag for automatic yes to prompts and --no-install-recommends to reduce size
tmpList.addAll(
Arrays.asList(
"apt-get", "install", "wkhtmltopdf", "-y", "--no-install-recommends"));
tmpList.addAll(Arrays.asList("apk add --no-cache calibre"));
commands.add(tmpList);
}
@@ -74,8 +47,6 @@ public class PostStartupProcesses {
// Run the command
if (runningInDocker) {
List<String> tmpList = new ArrayList<>();
tmpList.addAll(Arrays.asList("apt-get", "update"));
commands.add(0, tmpList);
for (List<String> list : commands) {
ProcessExecutorResult returnCode =

View File

@@ -9,6 +9,9 @@ import org.springframework.security.authentication.dao.DaoAuthenticationProvider
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@@ -44,6 +47,11 @@ public class SecurityConfiguration {
@Autowired private FirstLoginFilter firstLoginFilter;
@Bean
public SessionRegistry sessionRegistry() {
return new SessionRegistryImpl();
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.addFilterBefore(userAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
@@ -53,6 +61,14 @@ public class SecurityConfiguration {
http.csrf(csrf -> csrf.disable());
http.addFilterBefore(rateLimitingFilter(), UsernamePasswordAuthenticationFilter.class);
http.addFilterAfter(firstLoginFilter, UsernamePasswordAuthenticationFilter.class);
http.sessionManagement(
sessionManagement ->
sessionManagement
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.maximumSessions(3)
.maxSessionsPreventsLogin(true)
.sessionRegistry(sessionRegistry())
.expiredUrl("/login?logout=true"));
http.formLogin(
formLogin ->
formLogin

View File

@@ -1,6 +1,5 @@
package stirling.software.SPDF.controller.api;
import io.github.pixee.security.Filenames;
import java.awt.Color;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@@ -22,6 +21,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -137,6 +137,7 @@ public class MultiPageLayoutController {
byte[] result = baos.toByteArray();
return WebResponseUtils.bytesToWebResponse(
result,
Filenames.toSimpleFileName(file.getOriginalFilename()).replaceFirst("[.][^.]+$", "") + "_layoutChanged.pdf");
Filenames.toSimpleFileName(file.getOriginalFilename()).replaceFirst("[.][^.]+$", "")
+ "_layoutChanged.pdf");
}
}

View File

@@ -1,6 +1,5 @@
package stirling.software.SPDF.controller.api;
import io.github.pixee.security.Filenames;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
@@ -21,6 +20,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -77,7 +77,8 @@ public class PdfOverlayController {
overlay.overlay(overlayGuide).save(outputStream);
byte[] data = outputStream.toByteArray();
String outputFilename =
Filenames.toSimpleFileName(baseFile.getOriginalFilename()).replaceFirst("[.][^.]+$", "")
Filenames.toSimpleFileName(baseFile.getOriginalFilename())
.replaceFirst("[.][^.]+$", "")
+ "_overlayed.pdf"; // Remove file extension and append .pdf
return WebResponseUtils.bytesToWebResponse(

View File

@@ -1,6 +1,5 @@
package stirling.software.SPDF.controller.api;
import io.github.pixee.security.Filenames;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@@ -17,6 +16,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -58,7 +58,9 @@ public class RearrangePagesPDFController {
}
return WebResponseUtils.pdfDocToWebResponse(
document,
Filenames.toSimpleFileName(pdfFile.getOriginalFilename()).replaceFirst("[.][^.]+$", "") + "_removed_pages.pdf");
Filenames.toSimpleFileName(pdfFile.getOriginalFilename())
.replaceFirst("[.][^.]+$", "")
+ "_removed_pages.pdf");
}
private List<Integer> removeFirst(int totalPages) {
@@ -212,7 +214,8 @@ public class RearrangePagesPDFController {
return WebResponseUtils.pdfDocToWebResponse(
document,
Filenames.toSimpleFileName(pdfFile.getOriginalFilename()).replaceFirst("[.][^.]+$", "")
Filenames.toSimpleFileName(pdfFile.getOriginalFilename())
.replaceFirst("[.][^.]+$", "")
+ "_rearranged.pdf");
} catch (IOException e) {
logger.error("Failed rearranging documents", e);

View File

@@ -1,6 +1,5 @@
package stirling.software.SPDF.controller.api;
import io.github.pixee.security.Filenames;
import java.io.IOException;
import org.apache.pdfbox.Loader;
@@ -16,6 +15,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -50,6 +50,8 @@ public class RotationController {
return WebResponseUtils.pdfDocToWebResponse(
document,
Filenames.toSimpleFileName(pdfFile.getOriginalFilename()).replaceFirst("[.][^.]+$", "") + "_rotated.pdf");
Filenames.toSimpleFileName(pdfFile.getOriginalFilename())
.replaceFirst("[.][^.]+$", "")
+ "_rotated.pdf");
}
}

View File

@@ -1,6 +1,5 @@
package stirling.software.SPDF.controller.api;
import io.github.pixee.security.Filenames;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashMap;
@@ -23,6 +22,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -113,6 +113,7 @@ public class ScalePagesController {
return WebResponseUtils.bytesToWebResponse(
baos.toByteArray(),
Filenames.toSimpleFileName(file.getOriginalFilename()).replaceFirst("[.][^.]+$", "") + "_scaled.pdf");
Filenames.toSimpleFileName(file.getOriginalFilename()).replaceFirst("[.][^.]+$", "")
+ "_scaled.pdf");
}
}

View File

@@ -1,6 +1,5 @@
package stirling.software.SPDF.controller.api;
import io.github.pixee.security.Filenames;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.file.Files;
@@ -24,6 +23,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -50,7 +50,7 @@ public class SplitPDFController {
PDDocument document = Loader.loadPDF(file.getBytes());
List<Integer> pageNumbers = request.getPageNumbersList(document);
List<Integer> pageNumbers = request.getPageNumbersList(document, true);
if (!pageNumbers.contains(document.getNumberOfPages() - 1))
pageNumbers.add(document.getNumberOfPages() - 1);
logger.info(
@@ -84,7 +84,9 @@ public class SplitPDFController {
Path zipFile = Files.createTempFile("split_documents", ".zip");
String filename = Filenames.toSimpleFileName(file.getOriginalFilename()).replaceFirst("[.][^.]+$", "");
String filename =
Filenames.toSimpleFileName(file.getOriginalFilename())
.replaceFirst("[.][^.]+$", "");
try (ZipOutputStream zipOut = new ZipOutputStream(Files.newOutputStream(zipFile))) {
// loop through the split documents and write them to the zip file
for (int i = 0; i < splitDocumentsBoas.size(); i++) {

View File

@@ -1,6 +1,5 @@
package stirling.software.SPDF.controller.api;
import io.github.pixee.security.Filenames;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.file.Files;
@@ -27,6 +26,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -65,7 +65,9 @@ public class SplitPdfBySectionsController {
sourceDocument.close();
Path zipFile = Files.createTempFile("split_documents", ".zip");
String filename = Filenames.toSimpleFileName(file.getOriginalFilename()).replaceFirst("[.][^.]+$", "");
String filename =
Filenames.toSimpleFileName(file.getOriginalFilename())
.replaceFirst("[.][^.]+$", "");
byte[] data;
try (ZipOutputStream zipOut = new ZipOutputStream(Files.newOutputStream(zipFile))) {

View File

@@ -1,6 +1,5 @@
package stirling.software.SPDF.controller.api;
import io.github.pixee.security.Filenames;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.file.Files;
@@ -21,6 +20,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -121,7 +121,9 @@ public class SplitPdfBySizeController {
sourceDocument.close();
Path zipFile = Files.createTempFile("split_documents", ".zip");
String filename = Filenames.toSimpleFileName(file.getOriginalFilename()).replaceFirst("[.][^.]+$", "");
String filename =
Filenames.toSimpleFileName(file.getOriginalFilename())
.replaceFirst("[.][^.]+$", "");
byte[] data;
try (ZipOutputStream zipOut = new ZipOutputStream(Files.newOutputStream(zipFile))) {

View File

@@ -10,6 +10,9 @@ 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.core.session.SessionInformation;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
@@ -228,11 +231,27 @@ public class UserController {
if (currentUsername.equals(username)) {
throw new IllegalArgumentException("Cannot delete currently logined in user.");
}
invalidateUserSessions(username);
userService.deleteUser(username);
return "redirect:/addUsers";
}
@Autowired private SessionRegistry sessionRegistry;
private void invalidateUserSessions(String username) {
for (Object principal : sessionRegistry.getAllPrincipals()) {
if (principal instanceof UserDetails) {
UserDetails userDetails = (UserDetails) principal;
if (userDetails.getUsername().equals(username)) {
for (SessionInformation session :
sessionRegistry.getAllSessions(principal, false)) {
session.expireNow();
}
}
}
}
}
@PreAuthorize("!hasAuthority('ROLE_DEMO_USER')")
@PostMapping("/get-api-key")
public ResponseEntity<String> getApiKey(Principal principal) {

View File

@@ -1,6 +1,5 @@
package stirling.software.SPDF.controller.api.converters;
import io.github.pixee.security.Filenames;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.ResponseEntity;
@@ -10,6 +9,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -23,21 +23,21 @@ import stirling.software.SPDF.utils.WebResponseUtils;
public class ConvertBookToPDFController {
@Autowired
@Qualifier("bookFormatsInstalled")
private boolean bookFormatsInstalled;
@Qualifier("bookAndHtmlFormatsInstalled")
private boolean bookAndHtmlFormatsInstalled;
@PostMapping(consumes = "multipart/form-data", value = "/book/pdf")
@Operation(
summary =
"Convert a BOOK/comic (*.epub | *.mobi | *.azw3 | *.fb2 | *.txt | *.docx) to PDF",
description =
"(Requires bookFormatsInstalled flag and Calibre installed) This endpoint takes an BOOK/comic (*.epub | *.mobi | *.azw3 | *.fb2 | *.txt | *.docx) input and converts it to PDF format.")
"(Requires bookAndHtmlFormatsInstalled flag and Calibre installed) This endpoint takes an BOOK/comic (*.epub | *.mobi | *.azw3 | *.fb2 | *.txt | *.docx) input and converts it to PDF format.")
public ResponseEntity<byte[]> HtmlToPdf(@ModelAttribute GeneralFile request) throws Exception {
MultipartFile fileInput = request.getFileInput();
if (!bookFormatsInstalled) {
if (!bookAndHtmlFormatsInstalled) {
throw new IllegalArgumentException(
"bookFormatsInstalled flag is False, this functionality is not avaiable");
"bookAndHtmlFormatsInstalled flag is False, this functionality is not avaiable");
}
if (fileInput == null) {

View File

@@ -1,6 +1,5 @@
package stirling.software.SPDF.controller.api.converters;
import io.github.pixee.security.Filenames;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.ResponseEntity;
@@ -10,6 +9,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -23,8 +23,8 @@ import stirling.software.SPDF.utils.WebResponseUtils;
public class ConvertHtmlToPDF {
@Autowired
@Qualifier("htmlFormatsInstalled")
private boolean htmlFormatsInstalled;
@Qualifier("bookAndHtmlFormatsInstalled")
private boolean bookAndHtmlFormatsInstalled;
@PostMapping(consumes = "multipart/form-data", value = "/html/pdf")
@Operation(
@@ -47,7 +47,10 @@ public class ConvertHtmlToPDF {
}
byte[] pdfBytes =
FileToPdf.convertHtmlToPdf(
request, fileInput.getBytes(), originalFilename, htmlFormatsInstalled);
request,
fileInput.getBytes(),
originalFilename,
bookAndHtmlFormatsInstalled);
String outputFilename =
originalFilename.replaceFirst("[.][^.]+$", "")

View File

@@ -1,6 +1,5 @@
package stirling.software.SPDF.controller.api.converters;
import io.github.pixee.security.Filenames;
import java.io.IOException;
import java.net.URLConnection;
@@ -19,6 +18,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -57,7 +57,9 @@ public class ConvertImgPDFController {
// returns bytes for image
boolean singleImage = "single".equals(singleOrMultiple);
byte[] result = null;
String filename = Filenames.toSimpleFileName(file.getOriginalFilename()).replaceFirst("[.][^.]+$", "");
String filename =
Filenames.toSimpleFileName(file.getOriginalFilename())
.replaceFirst("[.][^.]+$", "");
try {
result =
PdfUtils.convertFromPdf(

View File

@@ -1,6 +1,5 @@
package stirling.software.SPDF.controller.api.converters;
import io.github.pixee.security.Filenames;
import java.util.List;
import java.util.Map;
@@ -20,6 +19,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -33,8 +33,8 @@ import stirling.software.SPDF.utils.WebResponseUtils;
public class ConvertMarkdownToPdf {
@Autowired
@Qualifier("htmlFormatsInstalled")
private boolean htmlFormatsInstalled;
@Qualifier("bookAndHtmlFormatsInstalled")
private boolean bookAndHtmlFormatsInstalled;
@PostMapping(consumes = "multipart/form-data", value = "/markdown/pdf")
@Operation(
@@ -69,7 +69,10 @@ public class ConvertMarkdownToPdf {
byte[] pdfBytes =
FileToPdf.convertHtmlToPdf(
null, htmlContent.getBytes(), "converted.html", htmlFormatsInstalled);
null,
htmlContent.getBytes(),
"converted.html",
bookAndHtmlFormatsInstalled);
String outputFilename =
originalFilename.replaceFirst("[.][^.]+$", "")

View File

@@ -1,6 +1,5 @@
package stirling.software.SPDF.controller.api.converters;
import io.github.pixee.security.Filenames;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -17,6 +16,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -90,7 +90,8 @@ public class ConvertOfficeController {
byte[] pdfByteArray = convertToPdf(inputFile);
return WebResponseUtils.bytesToWebResponse(
pdfByteArray,
Filenames.toSimpleFileName(inputFile.getOriginalFilename()).replaceFirst("[.][^.]+$", "")
Filenames.toSimpleFileName(inputFile.getOriginalFilename())
.replaceFirst("[.][^.]+$", "")
+ "_convertedToPDF.pdf");
}
}

View File

@@ -1,6 +1,5 @@
package stirling.software.SPDF.controller.api.converters;
import io.github.pixee.security.Filenames;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
@@ -16,6 +15,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -30,22 +30,22 @@ import stirling.software.SPDF.utils.WebResponseUtils;
public class ConvertPDFToBookController {
@Autowired
@Qualifier("bookFormatsInstalled")
private boolean bookFormatsInstalled;
@Qualifier("bookAndHtmlFormatsInstalled")
private boolean bookAndHtmlFormatsInstalled;
@PostMapping(consumes = "multipart/form-data", value = "/pdf/book")
@Operation(
summary =
"Convert a PDF to a Book/comic (*.epub | *.mobi | *.azw3 | *.fb2 | *.txt | *.docx .. (others to include by chatgpt) to PDF",
description =
"(Requires bookFormatsInstalled flag and Calibre installed) This endpoint Convert a PDF to a Book/comic (*.epub | *.mobi | *.azw3 | *.fb2 | *.txt | *.docx .. (others to include by chatgpt) to PDF")
"(Requires bookAndHtmlFormatsInstalled flag and Calibre installed) This endpoint Convert a PDF to a Book/comic (*.epub | *.mobi | *.azw3 | *.fb2 | *.txt | *.docx .. (others to include by chatgpt) to PDF")
public ResponseEntity<byte[]> HtmlToPdf(@ModelAttribute PdfToBookRequest request)
throws Exception {
MultipartFile fileInput = request.getFileInput();
if (!bookFormatsInstalled) {
if (!bookAndHtmlFormatsInstalled) {
throw new IllegalArgumentException(
"bookFormatsInstalled flag is False, this functionality is not avaiable");
"bookAndHtmlFormatsInstalled flag is False, this functionality is not avaiable");
}
if (fileInput == null) {
@@ -93,7 +93,8 @@ public class ConvertPDFToBookController {
}
String outputFilename =
Filenames.toSimpleFileName(fileInput.getOriginalFilename()).replaceFirst("[.][^.]+$", "")
Filenames.toSimpleFileName(fileInput.getOriginalFilename())
.replaceFirst("[.][^.]+$", "")
+ "."
+ outputFormat; // Remove file extension and append .pdf

View File

@@ -2,6 +2,10 @@ package stirling.software.SPDF.controller.api.converters;
import java.io.IOException;
import org.apache.pdfbox.Loader;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
@@ -9,6 +13,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -17,6 +22,7 @@ import stirling.software.SPDF.model.api.converters.PdfToPresentationRequest;
import stirling.software.SPDF.model.api.converters.PdfToTextOrRTFRequest;
import stirling.software.SPDF.model.api.converters.PdfToWordRequest;
import stirling.software.SPDF.utils.PDFToFile;
import stirling.software.SPDF.utils.WebResponseUtils;
@RestController
@RequestMapping("/api/v1/convert")
@@ -59,9 +65,21 @@ public class ConvertPDFToOffice {
throws IOException, InterruptedException {
MultipartFile inputFile = request.getFileInput();
String outputFormat = request.getOutputFormat();
PDFToFile pdfToFile = new PDFToFile();
return pdfToFile.processPdfToOfficeFormat(inputFile, outputFormat, "writer_pdf_import");
if ("txt".equals(request.getOutputFormat())) {
try (PDDocument document = Loader.loadPDF(inputFile.getBytes())) {
PDFTextStripper stripper = new PDFTextStripper();
String text = stripper.getText(document);
return WebResponseUtils.bytesToWebResponse(
text.getBytes(),
Filenames.toSimpleFileName(inputFile.getOriginalFilename())
.replaceFirst("[.][^.]+$", "")
+ ".txt",
MediaType.TEXT_PLAIN);
}
} else {
PDFToFile pdfToFile = new PDFToFile();
return pdfToFile.processPdfToOfficeFormat(inputFile, outputFormat, "writer_pdf_import");
}
}
@PostMapping(consumes = "multipart/form-data", value = "/pdf/word")

View File

@@ -1,6 +1,5 @@
package stirling.software.SPDF.controller.api.converters;
import io.github.pixee.security.Filenames;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
@@ -13,6 +12,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -64,7 +64,9 @@ public class ConvertPDFToPDFA {
// Return the optimized PDF as a response
String outputFilename =
Filenames.toSimpleFileName(inputFile.getOriginalFilename()).replaceFirst("[.][^.]+$", "") + "_PDFA.pdf";
Filenames.toSimpleFileName(inputFile.getOriginalFilename())
.replaceFirst("[.][^.]+$", "")
+ "_PDFA.pdf";
return WebResponseUtils.bytesToWebResponse(pdfBytes, outputFilename);
}
}

View File

@@ -29,8 +29,8 @@ import stirling.software.SPDF.utils.WebResponseUtils;
public class ConvertWebsiteToPDF {
@Autowired
@Qualifier("htmlFormatsInstalled")
private boolean htmlFormatsInstalled;
@Qualifier("bookAndHtmlFormatsInstalled")
private boolean bookAndHtmlFormatsInstalled;
@PostMapping(consumes = "multipart/form-data", value = "/url/pdf")
@Operation(
@@ -53,7 +53,7 @@ public class ConvertWebsiteToPDF {
// Prepare the OCRmyPDF command
List<String> command = new ArrayList<>();
if (!htmlFormatsInstalled) {
if (!bookAndHtmlFormatsInstalled) {
command.add("weasyprint");
} else {
command.add("wkhtmltopdf");

View File

@@ -1,6 +1,5 @@
package stirling.software.SPDF.controller.api.filters;
import io.github.pixee.security.Filenames;
import java.io.IOException;
import org.apache.pdfbox.Loader;
@@ -14,6 +13,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;

View File

@@ -1,6 +1,5 @@
package stirling.software.SPDF.controller.api.misc;
import io.github.pixee.security.Filenames;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
@@ -19,6 +18,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -134,7 +134,8 @@ public class AutoRenameController {
return WebResponseUtils.pdfDocToWebResponse(document, header + ".pdf");
} else {
logger.info("File has no good title to be found");
return WebResponseUtils.pdfDocToWebResponse(document, Filenames.toSimpleFileName(file.getOriginalFilename()));
return WebResponseUtils.pdfDocToWebResponse(
document, Filenames.toSimpleFileName(file.getOriginalFilename()));
}
}
}

View File

@@ -1,6 +1,5 @@
package stirling.software.SPDF.controller.api.misc;
import io.github.pixee.security.Filenames;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.awt.image.DataBufferInt;
@@ -32,6 +31,7 @@ import com.google.zxing.PlanarYUVLuminanceSource;
import com.google.zxing.Result;
import com.google.zxing.common.HybridBinarizer;
import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -98,7 +98,9 @@ public class AutoSplitPdfController {
document.close();
Path zipFile = Files.createTempFile("split_documents", ".zip");
String filename = Filenames.toSimpleFileName(file.getOriginalFilename()).replaceFirst("[.][^.]+$", "");
String filename =
Filenames.toSimpleFileName(file.getOriginalFilename())
.replaceFirst("[.][^.]+$", "");
byte[] data;
try (ZipOutputStream zipOut = new ZipOutputStream(Files.newOutputStream(zipFile))) {

View File

@@ -1,25 +1,21 @@
package stirling.software.SPDF.controller.api.misc;
import io.github.pixee.security.Filenames;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import javax.imageio.ImageIO;
import org.apache.pdfbox.Loader;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageTree;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.apache.pdfbox.text.PDFTextStripper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ModelAttribute;
@@ -28,12 +24,12 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import stirling.software.SPDF.model.api.misc.RemoveBlankPagesRequest;
import stirling.software.SPDF.utils.PdfUtils;
import stirling.software.SPDF.utils.ProcessExecutor;
import stirling.software.SPDF.utils.WebResponseUtils;
@RestController
@@ -41,6 +37,8 @@ import stirling.software.SPDF.utils.WebResponseUtils;
@Tag(name = "Misc", description = "Miscellaneous APIs")
public class BlankPageController {
private static final Logger logger = LoggerFactory.getLogger(BlankPageController.class);
@PostMapping(consumes = "multipart/form-data", value = "/remove-blanks")
@Operation(
summary = "Remove blank pages from a PDF file",
@@ -63,63 +61,35 @@ public class BlankPageController {
PDFRenderer pdfRenderer = new PDFRenderer(document);
for (PDPage page : pages) {
System.out.println("checking page " + pageIndex);
logger.info("checking page " + pageIndex);
textStripper.setStartPage(pageIndex + 1);
textStripper.setEndPage(pageIndex + 1);
String pageText = textStripper.getText(document);
boolean hasText = !pageText.trim().isEmpty();
Boolean blank = false;
if (hasText) {
pagesToKeepIndex.add(pageIndex);
System.out.println("page " + pageIndex + " has text");
logger.info("page " + pageIndex + " has text, not blank");
blank = false;
} else {
boolean hasImages = PdfUtils.hasImagesOnPage(page);
if (hasImages) {
System.out.println("page " + pageIndex + " has image");
Path tempFile = Files.createTempFile("image_", ".png");
logger.info("page " + pageIndex + " has image, running blank detection");
// Render image and save as temp file
BufferedImage image = pdfRenderer.renderImageWithDPI(pageIndex, 300);
ImageIO.write(image, "png", tempFile.toFile());
List<String> command =
new ArrayList<>(
Arrays.asList(
"python",
System.getProperty("user.dir")
+ "/scripts/detect-blank-pages.py",
tempFile.toString(),
"--threshold",
String.valueOf(threshold),
"--white_percent",
String.valueOf(whitePercent)));
Boolean blank = false;
// Run CLI command
try {
ProcessExecutor.getInstance(ProcessExecutor.Processes.PYTHON_OPENCV)
.runCommandWithOutputHandling(command);
} catch (IOException e) {
// From detect-blank-pages.py
// Return code 1: The image is considered blank.
// Return code 0: The image is not considered blank.
// Since the process returned with a failure code, it should be blank.
blank = true;
}
if (blank) {
System.out.println("Skipping, Image was blank for page #" + pageIndex);
} else {
System.out.println(
"page " + pageIndex + " has image which is not blank");
pagesToKeepIndex.add(pageIndex);
}
BufferedImage image = pdfRenderer.renderImageWithDPI(pageIndex, 30);
blank = isBlankImage(image, threshold, whitePercent, threshold);
}
}
if (blank) {
logger.info("Skipping, Image was blank for page #" + pageIndex);
} else {
logger.info("page " + pageIndex + " has image which is not blank");
pagesToKeepIndex.add(pageIndex);
}
pageIndex++;
}
System.out.print("pagesToKeep=" + pagesToKeepIndex.size());
// Remove pages not present in pagesToKeepIndex
List<Integer> pageIndices =
IntStream.range(0, pages.getCount()).boxed().collect(Collectors.toList());
@@ -132,7 +102,8 @@ public class BlankPageController {
return WebResponseUtils.pdfDocToWebResponse(
document,
Filenames.toSimpleFileName(inputFile.getOriginalFilename()).replaceFirst("[.][^.]+$", "")
Filenames.toSimpleFileName(inputFile.getOriginalFilename())
.replaceFirst("[.][^.]+$", "")
+ "_blanksRemoved.pdf");
} catch (IOException e) {
e.printStackTrace();
@@ -141,4 +112,30 @@ public class BlankPageController {
if (document != null) document.close();
}
}
public static boolean isBlankImage(
BufferedImage image, int threshold, double whitePercent, int blurSize) {
if (image == null) {
logger.info("Error: Image is null");
return false;
}
// Convert to binary image based on the threshold
int whitePixels = 0;
int totalPixels = image.getWidth() * image.getHeight();
for (int i = 0; i < image.getHeight(); i++) {
for (int j = 0; j < image.getWidth(); j++) {
int color = image.getRGB(j, i) & 0xFF;
if (color >= 255 - threshold) {
whitePixels++;
}
}
}
double whitePixelPercentage = (whitePixels / (double) totalPixels) * 100;
logger.info(String.format("Page has white pixel percent of %.2f%%", whitePixelPercentage));
return whitePixelPercentage >= whitePercent;
}
}

View File

@@ -1,6 +1,5 @@
package stirling.software.SPDF.controller.api.misc;
import io.github.pixee.security.Filenames;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
@@ -30,6 +29,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -265,7 +265,9 @@ public class CompressController {
// Return the optimized PDF as a response
String outputFilename =
Filenames.toSimpleFileName(inputFile.getOriginalFilename()).replaceFirst("[.][^.]+$", "") + "_Optimized.pdf";
Filenames.toSimpleFileName(inputFile.getOriginalFilename())
.replaceFirst("[.][^.]+$", "")
+ "_Optimized.pdf";
return WebResponseUtils.bytesToWebResponse(pdfBytes, outputFilename);
}
}

View File

@@ -1,6 +1,5 @@
package stirling.software.SPDF.controller.api.misc;
import io.github.pixee.security.Filenames;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
@@ -30,6 +29,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -67,7 +67,9 @@ public class ExtractImagesController {
zos.setLevel(Deflater.BEST_COMPRESSION);
int imageIndex = 1;
String filename = Filenames.toSimpleFileName(file.getOriginalFilename()).replaceFirst("[.][^.]+$", "");
String filename =
Filenames.toSimpleFileName(file.getOriginalFilename())
.replaceFirst("[.][^.]+$", "");
int pageNum = 0;
Set<Integer> processedImages = new HashSet<>();
// Iterate over each page

View File

@@ -1,6 +1,5 @@
package stirling.software.SPDF.controller.api.misc;
import io.github.pixee.security.Filenames;
import java.awt.Color;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
@@ -34,6 +33,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Hidden;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -142,7 +142,9 @@ public class FakeScanControllerWIP {
// Return the optimized PDF as a response
String outputFilename =
Filenames.toSimpleFileName(inputFile.getOriginalFilename()).replaceFirst("[.][^.]+$", "") + "_scanned.pdf";
Filenames.toSimpleFileName(inputFile.getOriginalFilename())
.replaceFirst("[.][^.]+$", "")
+ "_scanned.pdf";
return WebResponseUtils.boasToWebResponse(baos, outputFilename);
}
}

View File

@@ -1,6 +1,5 @@
package stirling.software.SPDF.controller.api.misc;
import io.github.pixee.security.Filenames;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
@@ -19,6 +18,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -165,6 +165,8 @@ public class MetadataController {
document.setDocumentInformation(info);
return WebResponseUtils.pdfDocToWebResponse(
document,
Filenames.toSimpleFileName(pdfFile.getOriginalFilename()).replaceFirst("[.][^.]+$", "") + "_metadata.pdf");
Filenames.toSimpleFileName(pdfFile.getOriginalFilename())
.replaceFirst("[.][^.]+$", "")
+ "_metadata.pdf");
}
}

View File

@@ -1,6 +1,5 @@
package stirling.software.SPDF.controller.api.misc;
import io.github.pixee.security.Filenames;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
@@ -25,6 +24,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -41,7 +41,7 @@ public class OCRController {
private static final Logger logger = LoggerFactory.getLogger(OCRController.class);
public List<String> getAvailableTesseractLanguages() {
String tessdataDir = "/usr/share/tesseract-ocr/5/tessdata";
String tessdataDir = "/usr/share/tessdata";
File[] files = new File(tessdataDir).listFiles();
if (files == null) {
return Collections.emptyList();
@@ -183,12 +183,16 @@ public class OCRController {
// Return the OCR processed PDF as a response
String outputFilename =
Filenames.toSimpleFileName(inputFile.getOriginalFilename()).replaceFirst("[.][^.]+$", "") + "_OCR.pdf";
Filenames.toSimpleFileName(inputFile.getOriginalFilename())
.replaceFirst("[.][^.]+$", "")
+ "_OCR.pdf";
if (sidecar != null && sidecar) {
// Create a zip file containing both the PDF and the text file
String outputZipFilename =
Filenames.toSimpleFileName(inputFile.getOriginalFilename()).replaceFirst("[.][^.]+$", "") + "_OCR.zip";
Filenames.toSimpleFileName(inputFile.getOriginalFilename())
.replaceFirst("[.][^.]+$", "")
+ "_OCR.zip";
Path tempZipFile = Files.createTempFile("output_", ".zip");
try (ZipOutputStream zipOut =

View File

@@ -1,6 +1,5 @@
package stirling.software.SPDF.controller.api.misc;
import io.github.pixee.security.Filenames;
import java.io.IOException;
import org.slf4j.Logger;
@@ -13,6 +12,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -45,7 +45,9 @@ public class OverlayImageController {
return WebResponseUtils.bytesToWebResponse(
result,
Filenames.toSimpleFileName(pdfFile.getOriginalFilename()).replaceFirst("[.][^.]+$", "") + "_overlayed.pdf");
Filenames.toSimpleFileName(pdfFile.getOriginalFilename())
.replaceFirst("[.][^.]+$", "")
+ "_overlayed.pdf");
} catch (IOException e) {
logger.error("Failed to add image to PDF", e);
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);

View File

@@ -1,6 +1,5 @@
package stirling.software.SPDF.controller.api.misc;
import io.github.pixee.security.Filenames;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.List;
@@ -22,6 +21,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -146,7 +146,8 @@ public class PageNumbersController {
return WebResponseUtils.bytesToWebResponse(
baos.toByteArray(),
Filenames.toSimpleFileName(file.getOriginalFilename()).replaceFirst("[.][^.]+$", "") + "_numbersAdded.pdf",
Filenames.toSimpleFileName(file.getOriginalFilename()).replaceFirst("[.][^.]+$", "")
+ "_numbersAdded.pdf",
MediaType.APPLICATION_PDF);
}
}

View File

@@ -1,6 +1,5 @@
package stirling.software.SPDF.controller.api.misc;
import io.github.pixee.security.Filenames;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -16,6 +15,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -66,7 +66,9 @@ public class RepairController {
// Return the optimized PDF as a response
String outputFilename =
Filenames.toSimpleFileName(inputFile.getOriginalFilename()).replaceFirst("[.][^.]+$", "") + "_repaired.pdf";
Filenames.toSimpleFileName(inputFile.getOriginalFilename())
.replaceFirst("[.][^.]+$", "")
+ "_repaired.pdf";
return WebResponseUtils.bytesToWebResponse(pdfBytes, outputFilename);
}
}

View File

@@ -1,6 +1,5 @@
package stirling.software.SPDF.controller.api.misc;
import io.github.pixee.security.Filenames;
import java.nio.charset.StandardCharsets;
import java.util.Map;
@@ -17,6 +16,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -55,7 +55,8 @@ public class ShowJavascript {
script +=
"// File: "
+ Filenames.toSimpleFileName(inputFile.getOriginalFilename())
+ Filenames.toSimpleFileName(
inputFile.getOriginalFilename())
+ ", Script: "
+ name
+ "\n"
@@ -67,12 +68,14 @@ public class ShowJavascript {
if (script.isEmpty()) {
script =
"PDF '" + inputFile.getOriginalFilename() + "' does not contain Javascript";
"PDF '"
+ Filenames.toSimpleFileName(inputFile.getOriginalFilename())
+ "' does not contain Javascript";
}
return WebResponseUtils.bytesToWebResponse(
script.getBytes(StandardCharsets.UTF_8),
inputFile.getOriginalFilename() + ".js");
Filenames.toSimpleFileName(inputFile.getOriginalFilename()) + ".js");
}
}
}

View File

@@ -1,6 +1,5 @@
package stirling.software.SPDF.controller.api.misc;
import io.github.pixee.security.Filenames;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
@@ -8,6 +7,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.List;
import javax.imageio.ImageIO;
@@ -33,6 +33,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -48,13 +49,13 @@ public class StampController {
@Operation(
summary = "Add stamp to a PDF file",
description =
"This endpoint adds a stamp 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")
"This endpoint adds a stamp to a given PDF file. Users can specify the stamp type (text or image), rotation, opacity, width spacer, and height spacer. Input:PDF Output:PDF Type:SISO")
public ResponseEntity<byte[]> addStamp(@ModelAttribute AddStampRequest request)
throws IOException, Exception {
MultipartFile pdfFile = request.getFileInput();
String watermarkType = request.getStampType();
String watermarkText = request.getStampText();
MultipartFile watermarkImage = request.getStampImage();
String stampType = request.getStampType();
String stampText = request.getStampText();
MultipartFile stampImage = request.getStampImage();
String alphabet = request.getAlphabet();
float fontSize = request.getFontSize();
float rotation = request.getRotation();
@@ -65,6 +66,7 @@ public class StampController {
String customColor = request.getCustomColor();
float marginFactor;
switch (request.getCustomMargin().toLowerCase()) {
case "small":
marginFactor = 0.02f;
@@ -78,7 +80,6 @@ public class StampController {
case "x-large":
marginFactor = 0.075f;
break;
default:
marginFactor = 0.035f;
break;
@@ -87,54 +88,64 @@ public class StampController {
// Load the input PDF
PDDocument document = Loader.loadPDF(pdfFile.getBytes());
for (PDPage page : document.getPages()) {
PDPageContentStream contentStream =
new PDPageContentStream(
document, page, PDPageContentStream.AppendMode.APPEND, true, true);
List<Integer> pageNumbers = request.getPageNumbersList(document, false);
PDExtendedGraphicsState graphicsState = new PDExtendedGraphicsState();
graphicsState.setNonStrokingAlphaConstant(opacity);
contentStream.setGraphicsStateParameters(graphicsState);
for (int pageIndex : pageNumbers) {
int zeroBasedIndex = pageIndex - 1;
if (zeroBasedIndex >= 0 && zeroBasedIndex < document.getNumberOfPages()) {
PDPage page = document.getPage(zeroBasedIndex);
PDRectangle pageSize = page.getMediaBox();
float margin = marginFactor * (pageSize.getWidth() + pageSize.getHeight()) / 2;
if ("text".equalsIgnoreCase(watermarkType)) {
addTextStamp(
contentStream,
watermarkText,
document,
page,
rotation,
position,
fontSize,
alphabet,
overrideX,
overrideY,
marginFactor,
customColor);
} else if ("image".equalsIgnoreCase(watermarkType)) {
addImageStamp(
contentStream,
watermarkImage,
document,
page,
rotation,
position,
fontSize,
overrideX,
overrideY,
marginFactor);
PDPageContentStream contentStream =
new PDPageContentStream(
document, page, PDPageContentStream.AppendMode.APPEND, true, true);
PDExtendedGraphicsState graphicsState = new PDExtendedGraphicsState();
graphicsState.setNonStrokingAlphaConstant(opacity);
contentStream.setGraphicsStateParameters(graphicsState);
if ("text".equalsIgnoreCase(stampType)) {
addTextStamp(
contentStream,
stampText,
document,
page,
rotation,
position,
fontSize,
alphabet,
overrideX,
overrideY,
margin,
customColor);
} else if ("image".equalsIgnoreCase(stampType)) {
addImageStamp(
contentStream,
stampImage,
document,
page,
rotation,
position,
fontSize,
overrideX,
overrideY,
margin);
}
contentStream.close();
}
contentStream.close();
}
return WebResponseUtils.pdfDocToWebResponse(
document,
Filenames.toSimpleFileName(pdfFile.getOriginalFilename()).replaceFirst("[.][^.]+$", "") + "_watermarked.pdf");
Filenames.toSimpleFileName(pdfFile.getOriginalFilename())
.replaceFirst("[.][^.]+$", "")
+ "_stamped.pdf");
}
private void addTextStamp(
PDPageContentStream contentStream,
String watermarkText,
String stampText,
PDDocument document,
PDPage page,
float rotation,
@@ -143,7 +154,7 @@ public class StampController {
String alphabet,
float overrideX, // X override
float overrideY,
float marginFactor,
float margin,
String colorString) // Y override
throws IOException {
String resourceDir = "";
@@ -203,27 +214,21 @@ public class StampController {
x = overrideX;
y = overrideY;
} else {
x =
calculatePositionX(
pageSize,
position,
fontSize,
font,
fontSize,
watermarkText,
marginFactor);
y = calculatePositionY(pageSize, position, fontSize, marginFactor);
x = calculatePositionX(pageSize, position, fontSize, font, fontSize, stampText, margin);
y =
calculatePositionY(
pageSize, position, calculateTextCapHeight(font, fontSize), margin);
}
contentStream.beginText();
contentStream.setTextMatrix(Matrix.getRotateInstance(Math.toRadians(rotation), x, y));
contentStream.showText(watermarkText);
contentStream.showText(stampText);
contentStream.endText();
}
private void addImageStamp(
PDPageContentStream contentStream,
MultipartFile watermarkImage,
MultipartFile stampImage,
PDDocument document,
PDPage page,
float rotation,
@@ -231,11 +236,11 @@ public class StampController {
float fontSize,
float overrideX,
float overrideY,
float marginFactor)
float margin)
throws IOException {
// Load the watermark image
BufferedImage image = ImageIO.read(watermarkImage.getInputStream());
// Load the stamp image
BufferedImage image = ImageIO.read(stampImage.getInputStream());
// Compute width based on original aspect ratio
float aspectRatio = (float) image.getWidth() / (float) image.getHeight();
@@ -257,10 +262,8 @@ public class StampController {
x = overrideX;
y = overrideY;
} else {
x =
calculatePositionX(
pageSize, position, desiredPhysicalWidth, null, 0, null, marginFactor);
y = calculatePositionY(pageSize, position, fontSize, marginFactor);
x = calculatePositionX(pageSize, position, desiredPhysicalWidth, null, 0, null, margin);
y = calculatePositionY(pageSize, position, fontSize, margin);
}
contentStream.saveGraphicsState();
@@ -277,17 +280,31 @@ public class StampController {
PDFont font,
float fontSize,
String text,
float marginFactor)
float margin)
throws IOException {
float actualWidth =
(text != null) ? calculateTextWidth(text, font, fontSize) : contentWidth;
switch (position % 3) {
case 1: // Left
return pageSize.getLowerLeftX() + marginFactor * pageSize.getWidth();
return pageSize.getLowerLeftX() + margin;
case 2: // Center
return (pageSize.getWidth() - actualWidth) / 2;
case 0: // Right
return pageSize.getUpperRightX() - actualWidth - marginFactor * pageSize.getWidth();
return pageSize.getUpperRightX() - actualWidth - margin;
default:
return 0;
}
}
private float calculatePositionY(
PDRectangle pageSize, int position, float height, float margin) {
switch ((position - 1) / 3) {
case 0: // Top
return pageSize.getUpperRightY() - height - margin;
case 1: // Middle
return (pageSize.getHeight() - height) / 2;
case 2: // Bottom
return pageSize.getLowerLeftY() + margin;
default:
return 0;
}
@@ -297,17 +314,7 @@ public class StampController {
return font.getStringWidth(text) / 1000 * fontSize;
}
private float calculatePositionY(
PDRectangle pageSize, int position, float height, float marginFactor) {
switch ((position - 1) / 3) {
case 0: // Top
return pageSize.getUpperRightY() - height - marginFactor * pageSize.getHeight();
case 1: // Middle
return (pageSize.getHeight() - height) / 2;
case 2: // Bottom
return pageSize.getLowerLeftY() + marginFactor * pageSize.getHeight();
default:
return 0;
}
private float calculateTextCapHeight(PDFont font, float fontSize) {
return font.getFontDescriptor().getCapHeight() / 1000 * fontSize;
}
}

View File

@@ -1,7 +1,5 @@
package stirling.software.SPDF.controller.api.pipeline;
import io.github.pixee.security.Filenames;
import io.github.pixee.security.ZipSecurity;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
@@ -38,6 +36,9 @@ import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import io.github.pixee.security.Filenames;
import io.github.pixee.security.ZipSecurity;
import jakarta.servlet.ServletContext;
import stirling.software.SPDF.SPdfApplication;
import stirling.software.SPDF.model.PipelineConfig;

View File

@@ -1,6 +1,5 @@
package stirling.software.SPDF.controller.api.security;
import io.github.pixee.security.Filenames;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@@ -43,6 +42,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -124,7 +124,9 @@ public class CertSignController {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
sign(pdf.getBytes(), baos, createSignature, name, location, reason);
return WebResponseUtils.boasToWebResponse(
baos, Filenames.toSimpleFileName(pdf.getOriginalFilename()).replaceFirst("[.][^.]+$", "") + "_signed.pdf");
baos,
Filenames.toSimpleFileName(pdf.getOriginalFilename()).replaceFirst("[.][^.]+$", "")
+ "_signed.pdf");
}
private static void sign(

View File

@@ -1,6 +1,5 @@
package stirling.software.SPDF.controller.api.security;
import io.github.pixee.security.Filenames;
import java.io.IOException;
import org.apache.pdfbox.Loader;
@@ -16,6 +15,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -44,7 +44,8 @@ public class PasswordController {
document.setAllSecurityToBeRemoved(true);
return WebResponseUtils.pdfDocToWebResponse(
document,
Filenames.toSimpleFileName(fileInput.getOriginalFilename()).replaceFirst("[.][^.]+$", "")
Filenames.toSimpleFileName(fileInput.getOriginalFilename())
.replaceFirst("[.][^.]+$", "")
+ "_password_removed.pdf");
}
@@ -89,10 +90,13 @@ public class PasswordController {
if ("".equals(ownerPassword) && "".equals(password))
return WebResponseUtils.pdfDocToWebResponse(
document,
Filenames.toSimpleFileName(fileInput.getOriginalFilename()).replaceFirst("[.][^.]+$", "")
Filenames.toSimpleFileName(fileInput.getOriginalFilename())
.replaceFirst("[.][^.]+$", "")
+ "_permissions.pdf");
return WebResponseUtils.pdfDocToWebResponse(
document,
Filenames.toSimpleFileName(fileInput.getOriginalFilename()).replaceFirst("[.][^.]+$", "") + "_passworded.pdf");
Filenames.toSimpleFileName(fileInput.getOriginalFilename())
.replaceFirst("[.][^.]+$", "")
+ "_passworded.pdf");
}
}

View File

@@ -1,6 +1,5 @@
package stirling.software.SPDF.controller.api.security;
import io.github.pixee.security.Filenames;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
@@ -26,6 +25,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -105,7 +105,8 @@ public class RedactController {
byte[] pdfContent = baos.toByteArray();
return WebResponseUtils.bytesToWebResponse(
pdfContent,
Filenames.toSimpleFileName(file.getOriginalFilename()).replaceFirst("[.][^.]+$", "") + "_redacted.pdf");
Filenames.toSimpleFileName(file.getOriginalFilename()).replaceFirst("[.][^.]+$", "")
+ "_redacted.pdf");
}
private void redactFoundText(

View File

@@ -1,6 +1,5 @@
package stirling.software.SPDF.controller.api.security;
import io.github.pixee.security.Filenames;
import java.io.IOException;
import org.apache.pdfbox.Loader;
@@ -29,6 +28,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -77,7 +77,8 @@ public class SanitizeController {
return WebResponseUtils.pdfDocToWebResponse(
document,
Filenames.toSimpleFileName(inputFile.getOriginalFilename()).replaceFirst("[.][^.]+$", "")
Filenames.toSimpleFileName(inputFile.getOriginalFilename())
.replaceFirst("[.][^.]+$", "")
+ "_sanitized.pdf");
}
}

View File

@@ -1,6 +1,5 @@
package stirling.software.SPDF.controller.api.security;
import io.github.pixee.security.Filenames;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
@@ -32,6 +31,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -106,7 +106,9 @@ public class WatermarkController {
return WebResponseUtils.pdfDocToWebResponse(
document,
Filenames.toSimpleFileName(pdfFile.getOriginalFilename()).replaceFirst("[.][^.]+$", "") + "_watermarked.pdf");
Filenames.toSimpleFileName(pdfFile.getOriginalFilename())
.replaceFirst("[.][^.]+$", "")
+ "_watermarked.pdf");
}
private void addTextWatermark(

View File

@@ -33,6 +33,8 @@ public class AccountWebController {
return "redirect:/";
}
model.addAttribute("currentPage", "login");
if (request.getParameter("error") != null) {
model.addAttribute("error", request.getParameter("error"));
@@ -112,6 +114,7 @@ public class AccountWebController {
model.addAttribute("role", user.get().getRolesAsString());
model.addAttribute("settings", settingsJson);
model.addAttribute("changeCredsFlag", user.get().isFirstLogin());
model.addAttribute("currentPage", "account");
}
} else {
return "redirect:/";

View File

@@ -13,7 +13,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
@Tag(name = "Convert", description = "Convert APIs")
public class ConverterWebController {
@ConditionalOnExpression("#{bookFormatsInstalled}")
@ConditionalOnExpression("#{bookAndHtmlFormatsInstalled}")
@GetMapping("/book-to-pdf")
@Hidden
public String convertBookToPdfForm(Model model) {
@@ -21,7 +21,7 @@ public class ConverterWebController {
return "convert/book-to-pdf";
}
@ConditionalOnExpression("#{bookFormatsInstalled}")
@ConditionalOnExpression("#{bookAndHtmlFormatsInstalled}")
@GetMapping("/pdf-to-book")
@Hidden
public String convertPdfToBookForm(Model model) {

View File

@@ -82,7 +82,7 @@ public class OtherWebController {
}
public List<String> getAvailableTesseractLanguages() {
String tessdataDir = "/usr/share/tesseract-ocr/5/tessdata";
String tessdataDir = "/usr/share/tessdata";
File[] files = new File(tessdataDir).listFiles();
if (files == null) {
return Collections.emptyList();

View File

@@ -290,31 +290,20 @@ public class ApplicationProperties {
}
public static class CustomApplications {
private boolean installBookFormats;
private boolean installAdvancedHtmlToPDF;
private boolean installBookAndHtmlFormats;
public boolean isInstallBookFormats() {
return installBookFormats;
public boolean isInstallBookAndHtmlFormats() {
return installBookAndHtmlFormats;
}
public void setInstallBookFormats(boolean installBookFormats) {
this.installBookFormats = installBookFormats;
}
public boolean isInstallAdvancedHtmlToPDF() {
return installAdvancedHtmlToPDF;
}
public void setInstallAdvancedHtmlToPDF(boolean installAdvancedHtmlToPDF) {
this.installAdvancedHtmlToPDF = installAdvancedHtmlToPDF;
public void setInstallBookAndHtmlFormats(boolean installBookAndHtmlFormats) {
this.installBookAndHtmlFormats = installBookAndHtmlFormats;
}
@Override
public String toString() {
return "CustomApplications [installBookFormats="
+ installBookFormats
+ ", installAdvancedHtmlToPDF="
+ installAdvancedHtmlToPDF
return "CustomApplications [installBookAndHtmlFormats="
+ installBookAndHtmlFormats
+ "]";
}
}

View File

@@ -25,7 +25,7 @@ public class PDFWithPageNums extends PDFFile {
private String pageNumbers;
@Hidden
public List<Integer> getPageNumbersList() {
public List<Integer> getPageNumbersList(boolean zeroCount) {
int pageCount = 0;
try {
pageCount = Loader.loadPDF(getFileInput().getBytes()).getNumberOfPages();
@@ -33,13 +33,13 @@ public class PDFWithPageNums extends PDFFile {
// TODO Auto-generated catch block
e.printStackTrace();
}
return GeneralUtils.parsePageString(pageNumbers, pageCount);
return GeneralUtils.parsePageString(pageNumbers, pageCount, zeroCount);
}
@Hidden
public List<Integer> getPageNumbersList(PDDocument doc) {
public List<Integer> getPageNumbersList(PDDocument doc, boolean zeroCount) {
int pageCount = 0;
pageCount = doc.getNumberOfPages();
return GeneralUtils.parsePageString(pageNumbers, pageCount);
return GeneralUtils.parsePageString(pageNumbers, pageCount, zeroCount);
}
}

View File

@@ -14,39 +14,4 @@ public class HTMLToPdfRequest extends PDFFile {
description = "Zoom level for displaying the website. Default is '1'.",
defaultValue = "1")
private float zoom;
@Schema(description = "Width of the page in centimeters.")
private Float pageWidth;
@Schema(description = "Height of the page in centimeters.")
private Float pageHeight;
@Schema(description = "Top margin of the page in millimeters.")
private Float marginTop;
@Schema(description = "Bottom margin of the page in millimeters.")
private Float marginBottom;
@Schema(description = "Left margin of the page in millimeters.")
private Float marginLeft;
@Schema(description = "Right margin of the page in millimeters.")
private Float marginRight;
@Schema(
description = "Enable or disable rendering of website background.",
allowableValues = {"Yes", "No"})
private String printBackground;
@Schema(
description =
"Enable or disable the default header. The default header includes the name of the page on the left and the page number on the right.",
allowableValues = {"Yes", "No"})
private String defaultHeader;
@Schema(
description = "Change the CSS media type of the page. Defaults to 'print'.",
allowableValues = {"none", "print", "screen"},
defaultValue = "print")
private String cssMediaType;
}

View File

@@ -12,6 +12,6 @@ public class PdfToTextOrRTFRequest extends PDFFile {
@Schema(
description = "The output Text or RTF format",
allowableValues = {"rtf", "txt:Text"})
allowableValues = {"rtf", "txt"})
private String outputFormat;
}

View File

@@ -6,11 +6,11 @@ import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import stirling.software.SPDF.model.api.PDFFile;
import stirling.software.SPDF.model.api.PDFWithPageNums;
@Data
@EqualsAndHashCode(callSuper = true)
public class AddStampRequest extends PDFFile {
public class AddStampRequest extends PDFWithPageNums {
@Schema(
description = "The stamp type (text or image)",

View File

@@ -1,9 +1,9 @@
package stirling.software.SPDF.utils;
import io.github.pixee.security.ZipSecurity;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
@@ -13,6 +13,8 @@ import java.util.stream.Stream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import io.github.pixee.security.ZipSecurity;
import stirling.software.SPDF.model.api.converters.HTMLToPdfRequest;
import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult;
@@ -33,95 +35,40 @@ public class FileToPdf {
tempInputFile = Files.createTempFile("input_", ".html");
Files.write(tempInputFile, fileBytes);
} else {
tempInputFile = unzipAndGetMainHtml(fileBytes);
tempInputFile = Files.createTempFile("input_", ".zip");
Files.write(tempInputFile, fileBytes);
}
List<String> command = new ArrayList<>();
if (!htmlFormatsInstalled) {
command.add("weasyprint");
} else {
command.add("wkhtmltopdf");
command.add("--enable-local-file-access");
command.add("--load-error-handling");
command.add("ignore");
command.add("--load-media-error-handling");
command.add("ignore");
command.add("--zoom");
command.add(String.valueOf(request.getZoom()));
command.add(tempInputFile.toString());
command.add(tempOutputFile.toString());
} else {
command.add("ebook-convert");
command.add(tempInputFile.toString());
command.add(tempOutputFile.toString());
command.add("--paper-size");
command.add("a4");
// if custom zoom add zoom style direct to html
// https://github.com/wkhtmltopdf/wkhtmltopdf/issues/4900
if (request.getZoom() != 1.0) {
String htmlContent = new String(Files.readAllBytes(tempInputFile));
String zoomStyle = "<style>body { zoom: " + request.getZoom() + "; }</style>";
// Check for <head> tag, add style tag to associated tag
if (htmlContent.contains("<head>")) {
htmlContent = htmlContent.replace("<head>", "<head>" + zoomStyle);
} else if (htmlContent.contains("<html>")) {
// If no <head> tag, but <html> tag exists
htmlContent = htmlContent.replace("<html>", "<html>" + zoomStyle);
} else {
// If neither <head> nor <html> tags exist
htmlContent = zoomStyle + htmlContent;
// Create a temporary CSS file
File tempCssFile = Files.createTempFile("customStyle", ".css").toFile();
try (FileWriter writer = new FileWriter(tempCssFile)) {
// Write the CSS rule to the file
writer.write("body { zoom: " + request.getZoom() + "; }");
}
// rewrite new html to file
Files.write(tempInputFile, htmlContent.getBytes(StandardCharsets.UTF_8));
}
if (request.getPageWidth() != null) {
command.add("--page-width");
command.add(request.getPageWidth() + "cm");
}
if (request.getPageHeight() != null) {
command.add("--page-height");
command.add(request.getPageHeight() + "cm");
}
if (request.getMarginTop() != null) {
command.add("--margin-top");
command.add(request.getMarginTop() + "mm");
}
// Repeat similar pattern for marginBottom, marginLeft, marginRight
if ("Yes".equalsIgnoreCase(request.getPrintBackground())) {
command.add("--background");
} else {
command.add("--no-background");
}
if ("Yes".equalsIgnoreCase(request.getDefaultHeader())) {
command.add("--default-header");
}
if ("print".equalsIgnoreCase(request.getCssMediaType())) {
command.add("--print-media-type");
} else if ("screen".equalsIgnoreCase(request.getCssMediaType())) {
command.add("--no-print-media-type");
command.add("--extra-css");
command.add(tempCssFile.getAbsolutePath());
}
}
command.add(tempInputFile.toString());
command.add(tempOutputFile.toString());
ProcessExecutorResult returnCode;
if (fileName.endsWith(".zip")) {
if (htmlFormatsInstalled) {
// command.add(1, "--allow");
// command.add(2, tempInputFile.getParent().toString());
}
returnCode =
ProcessExecutor.getInstance(ProcessExecutor.Processes.WEASYPRINT)
.runCommandWithOutputHandling(
command, tempInputFile.getParent().toFile());
} else {
returnCode =
ProcessExecutor.getInstance(ProcessExecutor.Processes.WEASYPRINT)
.runCommandWithOutputHandling(command);
}
returnCode =
ProcessExecutor.getInstance(ProcessExecutor.Processes.WEASYPRINT)
.runCommandWithOutputHandling(command);
pdfBytes = Files.readAllBytes(tempOutputFile);
} catch (IOException e) {
@@ -134,10 +81,6 @@ public class FileToPdf {
// Clean up temporary files
Files.delete(tempOutputFile);
Files.delete(tempInputFile);
if (fileName.endsWith(".zip")) {
GeneralUtils.deleteDirectory(tempInputFile.getParent());
}
}
return pdfBytes;
@@ -145,7 +88,8 @@ public class FileToPdf {
private static Path unzipAndGetMainHtml(byte[] fileBytes) throws IOException {
Path tempDirectory = Files.createTempDirectory("unzipped_");
try (ZipInputStream zipIn = ZipSecurity.createHardenedInputStream(new ByteArrayInputStream(fileBytes))) {
try (ZipInputStream zipIn =
ZipSecurity.createHardenedInputStream(new ByteArrayInputStream(fileBytes))) {
ZipEntry entry = zipIn.getNextEntry();
while (entry != null) {
Path filePath = tempDirectory.resolve(entry.getName());

View File

@@ -1,13 +1,10 @@
package stirling.software.SPDF.utils;
import io.github.pixee.security.HostValidator;
import io.github.pixee.security.Urls;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -15,10 +12,14 @@ import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.springframework.web.multipart.MultipartFile;
import io.github.pixee.security.HostValidator;
import io.github.pixee.security.Urls;
public class GeneralUtils {
public static File convertMultipartFileToFile(MultipartFile multipartFile) throws IOException {
@@ -59,7 +60,8 @@ public class GeneralUtils {
public static boolean isValidURL(String urlStr) {
try {
Urls.create(urlStr, Urls.HTTP_PROTOCOLS, HostValidator.DENY_COMMON_INFRASTRUCTURE_TARGETS);
Urls.create(
urlStr, Urls.HTTP_PROTOCOLS, HostValidator.DENY_COMMON_INFRASTRUCTURE_TARGETS);
return true;
} catch (MalformedURLException e) {
return false;
@@ -114,17 +116,36 @@ public class GeneralUtils {
}
public static List<Integer> parsePageString(String pageOrder, int totalPages) {
return parsePageList(pageOrder.split(","), totalPages);
return parsePageString(pageOrder, totalPages, false);
}
public static List<Integer> parsePageString(
String pageOrder, int totalPages, boolean isOneBased) {
if (pageOrder == null || pageOrder.isEmpty()) {
return Collections.singletonList(1);
}
if (pageOrder.matches("\\d+")) {
// Convert the single number string to an integer and return it in a list
return Collections.singletonList(Integer.parseInt(pageOrder));
}
return parsePageList(pageOrder.split(","), totalPages, isOneBased);
}
public static List<Integer> parsePageList(String[] pageOrderArr, int totalPages) {
return parsePageList(pageOrderArr, totalPages, false);
}
public static List<Integer> parsePageList(
String[] pageOrderArr, int totalPages, boolean isOneBased) {
List<Integer> newPageOrder = new ArrayList<>();
int adjustmentFactor = isOneBased ? 1 : 0;
// loop through the page order array
for (String element : pageOrderArr) {
if ("all".equalsIgnoreCase(element)) {
for (int i = 0; i < totalPages; i++) {
newPageOrder.add(i);
newPageOrder.add(i + adjustmentFactor);
}
// As all pages are already added, no need to check further
break;
@@ -155,7 +176,7 @@ public class GeneralUtils {
pageNum += constantExists ? constant : 0;
if (pageNum <= totalPages && pageNum > 0) {
newPageOrder.add(pageNum - 1);
newPageOrder.add(pageNum - adjustmentFactor);
}
}
} else if (element.contains("-")) {
@@ -170,11 +191,11 @@ public class GeneralUtils {
// loop through the range of pages
for (int j = start; j <= end; j++) {
// print the current index
newPageOrder.add(j - 1);
newPageOrder.add(j - adjustmentFactor);
}
} else {
// if the element is a single page
newPageOrder.add(Integer.parseInt(element) - 1);
newPageOrder.add(Integer.parseInt(element) - adjustmentFactor);
}
}

View File

@@ -1,6 +1,5 @@
package stirling.software.SPDF.utils;
import io.github.pixee.security.Filenames;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
@@ -21,6 +20,8 @@ import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.multipart.MultipartFile;
import io.github.pixee.security.Filenames;
import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult;
public class PDFToFile {

View File

@@ -1,6 +1,5 @@
package stirling.software.SPDF.utils;
import io.github.pixee.security.Filenames;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
@@ -38,6 +37,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;
import io.github.pixee.security.Filenames;
public class PdfUtils {
private static final Logger logger = LoggerFactory.getLogger(PdfUtils.class);

View File

@@ -1,6 +1,5 @@
package stirling.software.SPDF.utils;
import io.github.pixee.security.BoundedLineReader;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
@@ -17,6 +16,8 @@ import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.github.pixee.security.BoundedLineReader;
public class ProcessExecutor {
private static final Logger logger = LoggerFactory.getLogger(ProcessExecutor.class);
@@ -110,7 +111,10 @@ public class ProcessExecutor {
process.getErrorStream(),
StandardCharsets.UTF_8))) {
String line;
while ((line = BoundedLineReader.readLine(errorReader, 5_000_000)) != null) {
while ((line =
BoundedLineReader.readLine(
errorReader, 5_000_000))
!= null) {
errorLines.add(line);
if (liveUpdates) logger.info(line);
}
@@ -131,7 +135,10 @@ public class ProcessExecutor {
process.getInputStream(),
StandardCharsets.UTF_8))) {
String line;
while ((line = BoundedLineReader.readLine(outputReader, 5_000_000)) != null) {
while ((line =
BoundedLineReader.readLine(
outputReader, 5_000_000))
!= null) {
outputLines.add(line);
if (liveUpdates) logger.info(line);
}

View File

@@ -1,6 +1,5 @@
package stirling.software.SPDF.utils;
import io.github.pixee.security.Filenames;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URLEncoder;
@@ -13,6 +12,8 @@ import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.multipart.MultipartFile;
import io.github.pixee.security.Filenames;
public class WebResponseUtils {
public static ResponseEntity<byte[]> boasToWebResponse(

View File

@@ -22,7 +22,7 @@ server.servlet.context-path=${SYSTEM_ROOTURIPATH:/}
spring.devtools.restart.enabled=true
spring.devtools.livereload.enabled=true
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.encoding=UTF-8
server.connection-timeout=${SYSTEM_CONNECTIONTIMEOUTMINUTES:5m}
spring.mvc.async.request-timeout=${SYSTEM_CONNECTIONTIMEOUTMILLISECONDS:300000}

View File

@@ -1,6 +1,6 @@
____ _____ ___ ____ _ ___ _ _ ____ ____ ____ _____
____ _____ ___ ____ _ ___ _ _ ____ ____ ____ _____
/ ___|_ _|_ _| _ \| | |_ _| \ | |/ ___| | _ \| _ \| ___|
\___ \ | | | || |_) | | | || \| | | _ _____| |_) | | | | |_
___) || | | || _ <| |___ | || |\ | |_| |_____| __/| |_| | _|
|____/ |_| |___|_| \_\_____|___|_| \_|\____| |_| |____/|_|
\___ \ | | | || |_) | | | || \| | | _ _____| |_) | | | | |_
___) || | | || _ <| |___ | || |\ | |_| |_____| __/| |_| | _|
|____/ |_| |___|_| \_\_____|___|_| \_|\____| |_| |____/|_|
Powered by Spring Boot ${spring-boot.version}

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
###########
###########
# Generic #
###########
# the direction that the language is written (ltr=left to right, rtl = right to left)
@@ -11,6 +11,7 @@ imgPrompt=Изберете изображение(я)
genericSubmit=Подайте
processTimeWarning=Предупреждение: Този процес може да отнеме до минута в зависимост от размера на файла
pageOrderPrompt=Персонализиран ред на страниците (Въведете разделен със запетаи списък с номера на страници или функции като 2n+1):
pageSelectionPrompt=Custom Page Selection (Enter a comma-separated list of page numbers 1,5,6 or Functions like 2n+1) :
goToPage=Давай
true=Вярно
false=Невярно
@@ -19,6 +20,7 @@ save=Съхранете
close=Затворете
filesSelected=избрани файлове
noFavourites=Няма добавени любими
downloadComplete=Download Complete
bored=Отекчени сте да чакате?
alphabet=Азбука
downloadPdf=Изтеглете PDF
@@ -42,7 +44,7 @@ red=Червено
green=Зелено
blue=Синьо
custom=Персонализиране...
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
WorkInProgess=Work in progress, May not work or be buggy, Please report any problems!
poweredBy=Powered by
yes=Yes
no=No
@@ -120,7 +122,7 @@ account.accountSettings=Настройки на акаунта
account.adminSettings=Настройки на администратора - Преглед и добавяне на потребители
account.userControlSettings=Настройки за потребителски контрол
account.changeUsername=Промени потребител
account.changeUsername=Промени потребител
account.newUsername=Ново потребителско име
account.password=Парола за потвърждение
account.oldPassword=Стара парола
account.newPassword=Нова парола
@@ -362,11 +364,11 @@ PdfToSinglePage.tags=единична страница
home.showJS.title=Показване на Javascript
home.showJS.desc=Търси и показва всеки JS, инжектиран в PDF
showJS.tags=Редактиране,Скриване,затъмняване,черен,маркер,скрит
showJS.tags=JS
home.autoRedact.title=Автоматично редактиране
home.autoRedact.desc=Автоматично редактира (зачернява) текст в PDF въз основа на въведен текст
showJS.tags=Редактиране,Скриване,затъмняване,черен,маркер,скрит
autoRedact.tags=Редактиране,Скриване,затъмняване,черен,маркер,скрит
home.tableExtraxt.title=PDF to CSV
home.tableExtraxt.desc=Extracts Tables from a PDF converting it to CSV
@@ -410,7 +412,7 @@ autoRedact.title=Автоматично редактиране
autoRedact.header=Автоматично редактиране
autoRedact.colorLabel=Цвят
autoRedact.textsToRedactLabel=Текст за редактиране (разделен с редове)
autoRedact.textsToRedactPlaceholder=например: \nПоверително \nСтрого секретно
autoRedact.textsToRedactPlaceholder=например: \nПоверително \nСтрого секретно
autoRedact.useRegexLabel=Използване на Regex
autoRedact.wholeWordSearchLabel=Търсене на цялата дума
autoRedact.customPaddingLabel=Персонализирана допълнителна подложка
@@ -497,7 +499,8 @@ AddStampRequest.overrideY=Override Y Coordinate
AddStampRequest.customMargin=Custom Margin
AddStampRequest.customColor=Custom Text Color
AddStampRequest.submit=Submit
#sanitizePDF
sanitizePDF.title=Дезинфектирай PDF
sanitizePDF.header=Дезинфектира PDF файл
@@ -656,7 +659,7 @@ ScannerImageSplit.selectText.8=Задава минималния праг на
ScannerImageSplit.selectText.9=Размер на рамката:
ScannerImageSplit.selectText.10=Задава размера на добавената и премахната граница, за да предотврати бели граници към изхода (по подразбиране: 1).
#OCR
ocr.title=OCR / Почистване на сканиране
ocr.header=Почистващи сканирания / OCR (оптично разпознаване на знаци)
@@ -775,8 +778,8 @@ imageToPDF.selectText.2=Автоматично завъртане на PDF
imageToPDF.selectText.3=Файлова логика с много (Активирано само ако работите с множество изображения)
imageToPDF.selectText.4=Сливане към един PDF
imageToPDF.selectText.5=Преобразуване към отделни PDF файлове
#pdfToImage
pdfToImage.title=PDF към Изображение
pdfToImage.header=PDF към Изображение
@@ -866,7 +869,6 @@ changeMetadata.keywords=Ключови думи:
changeMetadata.modDate=Дата на промяна (гггг/ММ/дд ЧЧ:мм:сс):
changeMetadata.producer=Продуцент:
changeMetadata.subject=Тема:
changeMetadata.title=Заглавие:
changeMetadata.trapped=В капан:
changeMetadata.selectText.4=Други метаданни:
changeMetadata.selectText.5=Добавяне на персонализиране метаданни

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
###########
###########
# Generic #
###########
# the direction that the language is written (ltr=left to right, rtl = right to left)
@@ -11,6 +11,7 @@ imgPrompt=\u0395\u03C0\u03B9\u03BB\u03BF\u03B3\u03AE \u0395\u03B9\u03BA\u03CC\u0
genericSubmit=\u03A5\u03C0\u03BF\u03B2\u03BF\u03BB\u03AE
processTimeWarning=\u03A0\u03C1\u03BF\u03C3\u03BF\u03C7\u03AE: \u0391\u03C5\u03C4\u03AE \u03B7 \u03B4\u03B9\u03B1\u03B4\u03B9\u03BA\u03B1\u03C3\u03AF\u03B1 \u03BC\u03C0\u03BF\u03C1\u03B5\u03AF \u03BD\u03B1 \u03B4\u03B9\u03B1\u03C1\u03BA\u03AD\u03C3\u03B5\u03B9 \u03AD\u03C9\u03C2 \u03BA\u03B1\u03B9 \u03AD\u03BD\u03B1 \u03BB\u03B5\u03C0\u03C4\u03CC \u03B1\u03BD\u03AC\u03BB\u03BF\u03B3\u03B1 \u03BC\u03B5 \u03C4\u03BF \u03BC\u03AD\u03B3\u03B5\u03B8\u03BF\u03C2 \u03C4\u03BF\u03C5 \u03B1\u03C1\u03C7\u03B5\u03AF\u03BF\u03C5
pageOrderPrompt=\u03A0\u03C1\u03BF\u03C3\u03B1\u03C1\u03BC\u03BF\u03C3\u03BC\u03AD\u03BD\u03B7 \u03A3\u03B5\u03B9\u03C1\u03AC \u03A3\u03B5\u03BB\u03AF\u03B4\u03B1\u03C2 (\u03A0\u03C1\u03BF\u03C3\u03B8\u03AD\u03C3\u03C4\u03B5 \u03BC\u03AF\u03B1 \u03BB\u03AF\u03C3\u03C4\u03B5 \u03B1\u03C0\u03BF \u03B1\u03C1\u03B9\u03B8\u03BC\u03BF\u03CD\u03C2 \u03C3\u03B5\u03BB\u03B9\u03B4\u03CE\u03BD, \u03C7\u03C9\u03C1\u03B9\u03C3\u03BC\u03AD\u03BD\u03B5\u03C2 \u03BC\u03B5 \u03BA\u03CC\u03BC\u03BC\u03B1 \u03AE \u03C3\u03C5\u03BD\u03B1\u03C1\u03C4\u03AE\u03C3\u03B5\u03B9\u03C2 \u03CC\u03C0\u03C9\u03C2 2n+1) :
pageSelectionPrompt=Custom Page Selection (Enter a comma-separated list of page numbers 1,5,6 or Functions like 2n+1) :
goToPage=Go
true=\u0391\u03BB\u03B7\u03B8\u03AD\u03C2
false=\u039B\u03B1\u03BD\u03B8\u03B1\u03C3\u03BC\u03AD\u03BD\u03BF
@@ -19,6 +20,7 @@ save=\u0391\u03C0\u03BF\u03B8\u03AE\u03BA\u03B5\u03C5\u03C3\u03B7
close=\u039A\u03BB\u03B5\u03AF\u03C3\u03B9\u03BC\u03BF
filesSelected=\u03B1\u03C1\u03C7\u03B5\u03AF\u03B1 \u03C0\u03BF\u03C5 \u03B5\u03C0\u03B9\u03BB\u03AD\u03C7\u03B8\u03B7\u03BA\u03B1\u03BD
noFavourites=\u039A\u03B1\u03BD\u03AD\u03BD\u03B1 \u03B1\u03B3\u03B1\u03C0\u03AE\u03BC\u03B5\u03BD\u03BF \u03B4\u03B5\u03BD \u03AD\u03C7\u03B5\u03B9 \u03C0\u03C1\u03BF\u03C3\u03C4\u03B5\u03B8\u03B5\u03AF
downloadComplete=Download Complete
bored=\u0392\u03B1\u03C1\u03B9\u03AD\u03C3\u03C4\u03B5 \u03BD\u03B1 \u03C0\u03B5\u03C1\u03B9\u03BC\u03AD\u03BD\u03B5\u03C4\u03B5;
alphabet=\u0391\u03BB\u03C6\u03AC\u03B2\u03B7\u03C4\u03BF
downloadPdf=\u039A\u03B1\u03C4\u03AD\u03B2\u03B1\u03C3\u03BC\u03B1 \u03C4\u03BF\u03C5 PDF
@@ -42,7 +44,7 @@ red=\u039A\u03CC\u03BA\u03BA\u03B9\u03BD\u03BF
green=\u03A0\u03C1\u03AC\u03C3\u03B9\u03BD\u03BF
blue=\u039C\u03C0\u03BB\u03AD
custom=\u03A0\u03C1\u03BF\u03C3\u03B1\u03C1\u03BC\u03BF\u03B3\u03AE...
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
WorkInProgess=Work in progress, May not work or be buggy, Please report any problems!
poweredBy=Powered by
yes=Yes
no=No
@@ -120,7 +122,7 @@ account.accountSettings=\u03A1\u03C5\u03B8\u03BC\u03AF\u03C3\u03B5\u03B9\u03C2 \
account.adminSettings=\u03A1\u03C5\u03B8\u03BC\u03AF\u03C3\u03B5\u03B9\u03C2 \u0394\u03B9\u03B1\u03C7\u03B5\u03B9\u03C1\u03B9\u03C3\u03C4\u03AE - \u03A0\u03C1\u03BF\u03B2\u03BF\u03BB\u03AE \u03BA\u03B1\u03B9 \u03C0\u03C1\u03BF\u03C3\u03B8\u03AE\u03BA\u03B7 \u03C7\u03C1\u03B7\u03C3\u03C4\u03CE\u03BD
account.userControlSettings=\u03A1\u03C5\u03B8\u03BC\u03AF\u03C3\u03B5\u03B9\u03C2 \u03A7\u03B5\u03B9\u03C1\u03B9\u03C3\u03BC\u03BF\u03CD \u03A7\u03C1\u03B7\u03C3\u03C4\u03CE\u03BD
account.changeUsername=\u0391\u03BB\u03BB\u03B1\u03B3\u03AE \u039F\u03BD\u03CC\u03BC\u03B1\u03C4\u03BF\u03C2 \u03A7\u03C1\u03AE\u03C3\u03C4\u03B7
account.changeUsername=\u0391\u03BB\u03BB\u03B1\u03B3\u03AE \u039F\u03BD\u03CC\u03BC\u03B1\u03C4\u03BF\u03C2 \u03A7\u03C1\u03AE\u03C3\u03C4\u03B7
account.newUsername=\u039d\u03ad\u03bf \u038c\u03bd\u03bf\u03bc\u03b1 \u03a7\u03c1\u03ae\u03c3\u03c4\u03b7
account.password=\u0395\u03C0\u03B9\u03B2\u03B5\u03B2\u03B1\u03AF\u03C9\u03C3\u03B7 \u039A\u03C9\u03B4\u03B9\u03BA\u03BF\u03CD \u03A0\u03C1\u03CC\u03C3\u03B2\u03B1\u03C3\u03B7\u03C2
account.oldPassword=\u03A0\u03B1\u03BB\u03B9\u03CC\u03C2 \u039A\u03C9\u03B4\u03B9\u03BA\u03CC\u03C2 \u03A0\u03C1\u03CC\u03C3\u03B2\u03B1\u03C3\u03B7\u03C2
account.newPassword=\u039D\u03AD\u03BF\u03C2 \u039A\u03C9\u03B4\u03B9\u03BA\u03CC\u03C2 \u03A0\u03C1\u03CC\u03C3\u03B2\u03B1\u03C3\u03B7\u03C2
@@ -362,11 +364,11 @@ PdfToSinglePage.tags=single page
home.showJS.title=\u0395\u03BC\u03C6\u03AC\u03BD\u03B9\u03C3\u03B7 Javascript
home.showJS.desc=\u0391\u03BD\u03B6\u03AE\u03C4\u03B7\u03C3\u03B7 \u03BA\u03B1\u03B9 \u03B5\u03BC\u03C6\u03AC\u03BD\u03B9\u03C3\u03B7 \u03BA\u03CE\u03B4\u03B9\u03BA\u03B1 Javascript \u03C0\u03BF\u03C5 \u03B5\u03AF\u03BD\u03B1\u03B9 \u03B5\u03BD\u03C3\u03C9\u03BC\u03B1\u03C4\u03C9\u03BC\u03AD\u03BD\u03BF \u03BC\u03AD\u03C3\u03B1 \u03C3\u03B5 \u03AD\u03BD\u03B1 PDF
showJS.tags=Redact,Hide,black out,black,marker,hidden
showJS.tags=JS
home.autoRedact.title=\u0391\u03C5\u03C4\u03CC\u03BC\u03B1\u03C4\u03BF \u039C\u03B1\u03CD\u03C1\u03B9\u03C3\u03BC\u03B1 \u039A\u03B5\u03B9\u03BC\u03AD\u03BD\u03BF\u03C5
home.autoRedact.desc=\u0391\u03C5\u03C4\u03CC\u03BC\u03B1\u03C4\u03B7 \u03B5\u03C0\u03B5\u03BE\u03B5\u03C1\u03B3\u03B1\u03C3\u03AF\u03B1 (\u039C\u03B1\u03CD\u03C1\u03B9\u03C3\u03BC\u03B1) \u03BA\u03B5\u03AF\u03BC\u03B5\u03BD\u03BF\u03C5 \u03C3\u03B5 PDF \u03BC\u03B5 \u03B2\u03AC\u03C3\u03B7 \u03C4\u03BF \u03BA\u03B5\u03AF\u03BC\u03B5\u03BD\u03BF \u03B5\u03B9\u03C3\u03B1\u03B3\u03C9\u03B3\u03AE\u03C2
showJS.tags=Redact,Hide,black out,black,marker,hidden
autoRedact.tags=Redact,Hide,black out,black,marker,hidden
home.tableExtraxt.title=PDF to CSV
home.tableExtraxt.desc=Extracts Tables from a PDF converting it to CSV
@@ -410,7 +412,7 @@ autoRedact.title=\u0391\u03C5\u03C4\u03CC\u03BC\u03B1\u03C4\u03BF \u039C\u03B1\u
autoRedact.header=\u0391\u03C5\u03C4\u03CC\u03BC\u03B1\u03C4\u03BF \u039C\u03B1\u03CD\u03C1\u03B9\u03C3\u03BC\u03B1 \u039A\u03B5\u03B9\u03BC\u03AD\u03BD\u03BF\u03C5
autoRedact.colorLabel=\u03A7\u03C1\u03CE\u03BC\u03B1
autoRedact.textsToRedactLabel=\u039A\u03B5\u03AF\u03BC\u03B5\u03BD\u03BF \u03B3\u03B9\u03B1 \u03BC\u03B1\u03CD\u03C1\u03B9\u03C3\u03BC\u03B1 (\u03B4\u03B9\u03B1\u03C7\u03C9\u03C1\u03B9\u03C3\u03BC\u03AD\u03BD\u03BF \u03C3\u03B5 \u03B3\u03C1\u03B1\u03BC\u03BC\u03AD\u03C2)
autoRedact.textsToRedactPlaceholder=\u03C0.\u03C7. \n\u0395\u03BC\u03C0\u03B9\u03C3\u03C4\u03B5\u03C5\u03C4\u03B9\u03BA\u03CC \n\u0391\u03BA\u03C1\u03CE\u03C2 \u03B1\u03C0\u03CC\u03C1\u03C1\u03B7\u03C4\u03BF
autoRedact.textsToRedactPlaceholder=\u03C0.\u03C7. \n\u0395\u03BC\u03C0\u03B9\u03C3\u03C4\u03B5\u03C5\u03C4\u03B9\u03BA\u03CC \n\u0391\u03BA\u03C1\u03CE\u03C2 \u03B1\u03C0\u03CC\u03C1\u03C1\u03B7\u03C4\u03BF
autoRedact.useRegexLabel=\u03A7\u03C1\u03AE\u03C3\u03B7 Regex
autoRedact.wholeWordSearchLabel=\u0391\u03BD\u03B1\u03B6\u03AE\u03C4\u03B7\u03C3\u03B7 \u03BF\u03BB\u03CC\u03BA\u03BB\u03B7\u03C1\u03B7\u03C2 \u03C4\u03B7\u03C2 \u03BB\u03AD\u03BE\u03B7\u03C2
autoRedact.customPaddingLabel=Custom Extra Padding
@@ -497,7 +499,8 @@ AddStampRequest.overrideY=Override Y Coordinate
AddStampRequest.customMargin=Custom Margin
AddStampRequest.customColor=Custom Text Color
AddStampRequest.submit=Submit
#sanitizePDF
sanitizePDF.title=\u0391\u03C0\u03BF\u03BB\u03CD\u03BC\u03B1\u03BD\u03C3\u03B7 PDF
sanitizePDF.header=\u0391\u03C0\u03BF\u03BB\u03CD\u03BC\u03B1\u03BD\u03C3\u03B7 \u03B5\u03BD\u03CC\u03C2 PDF \u03B1\u03C1\u03C7\u03B5\u03AF\u03BF\u03C5
@@ -656,7 +659,7 @@ ScannerImageSplit.selectText.8=\u03A1\u03C5\u03B8\u03BC\u03AF\u03B6\u03B5\u03B9
ScannerImageSplit.selectText.9=\u039C\u03AD\u03B3\u03B5\u03B8\u03BF\u03C2 \u03C0\u03B5\u03C1\u03B9\u03B3\u03C1\u03AC\u03BC\u03BC\u03B1\u03C4\u03BF\u03C2:
ScannerImageSplit.selectText.10=\u039F\u03C1\u03AF\u03B6\u03B5\u03B9 \u03C4\u03BF \u03BC\u03AD\u03B3\u03B5\u03B8\u03BF\u03C2 \u03C4\u03BF\u03C5 \u03C0\u03B5\u03C1\u03B9\u03B3\u03C1\u03AC\u03BC\u03BC\u03B1\u03C4\u03BF\u03C2 \u03C0\u03BF\u03C5 \u03C0\u03C1\u03BF\u03C3\u03C4\u03AF\u03B8\u03B5\u03C4\u03B1\u03B9 \u03BA\u03B1\u03B9 \u03B1\u03C6\u03B1\u03B9\u03C1\u03B5\u03AF\u03C4\u03B1\u03B9 \u03B3\u03B9\u03B1 \u03BD\u03B1 \u03B1\u03C0\u03BF\u03C4\u03C1\u03AD\u03C0\u03BF\u03BD\u03C4\u03B1\u03B9 \u03BB\u03B5\u03C5\u03BA\u03AC \u03C0\u03B5\u03C1\u03B9\u03B3\u03C1\u03AC\u03BC\u03BC\u03B1\u03C4\u03B1 \u03C3\u03C4\u03B7\u03BD \u03AD\u03BE\u03BF\u03B4\u03BF (\u03C0\u03C1\u03BF\u03B5\u03C0\u03B9\u03BB\u03BF\u03B3\u03AE: 1).
#OCR
ocr.title=\u039F\u03C0\u03C4\u03B9\u03BA\u03AE \u03B1\u03BD\u03B1\u03B3\u03BD\u03CE\u03C1\u03B9\u03C3\u03B7 \u03C7\u03B1\u03C1\u03B1\u03BA\u03C4\u03AE\u03C1\u03C9\u03BD (OCR) / \u03A3\u03B1\u03C1\u03CE\u03C3\u03B5\u03B9\u03C2 Cleanup
ocr.header=\u03A3\u03B1\u03C1\u03CE\u03C3\u03B5\u03B9\u03C2 Cleanup / OCR (Optical Character Recognition - \u039F\u03C0\u03C4\u03B9\u03BA\u03AE \u03B1\u03BD\u03B1\u03B3\u03BD\u03CE\u03C1\u03B9\u03C3\u03B7 \u03C7\u03B1\u03C1\u03B1\u03BA\u03C4\u03AE\u03C1\u03C9\u03BD)
@@ -775,8 +778,8 @@ imageToPDF.selectText.2=\u0391\u03C5\u03C4\u03CC\u03BC\u03B1\u03C4\u03B7 \u03C0\
imageToPDF.selectText.3=\u039B\u03BF\u03B3\u03B9\u03BA\u03AE \u03C0\u03BF\u03BB\u03BB\u03CE\u03BD \u03B1\u03C1\u03C7\u03B5\u03AF\u03C9\u03BD (\u0395\u03BD\u03B5\u03C1\u03B3\u03BF\u03C0\u03BF\u03B9\u03B5\u03AF\u03C4\u03B1\u03B9 \u03BC\u03CC\u03BD\u03BF \u03B5\u03AC\u03BD \u03B5\u03C1\u03B3\u03AC\u03B6\u03B5\u03C3\u03C4\u03B5 \u03BC\u03B5 \u03C0\u03BF\u03BB\u03BB\u03AD\u03C2 \u03B5\u03B9\u03BA\u03CC\u03BD\u03B5\u03C2)
imageToPDF.selectText.4=\u03A3\u03C5\u03B3\u03C7\u03CE\u03BD\u03B5\u03C5\u03C3\u03B7 \u03C3\u03B5 \u03AD\u03BD\u03B1 PDF
imageToPDF.selectText.5=\u039C\u03B5\u03C4\u03B1\u03C4\u03C1\u03BF\u03C0\u03AE \u03C3\u03B5 \u03BE\u03B5\u03C7\u03C9\u03C1\u03B9\u03C3\u03C4\u03AC \u03B1\u03C1\u03C7\u03B5\u03AF\u03B1 PDF
#pdfToImage
pdfToImage.title=PDF \u03C3\u03B5 \u0395\u03B9\u03BA\u03CC\u03BD\u03B1
pdfToImage.header=PDF \u03C3\u03B5 \u0395\u03B9\u03BA\u03CC\u03BD\u03B1
@@ -866,7 +869,6 @@ changeMetadata.keywords=\u039B\u03AD\u03BE\u03B5\u03B9\u03C2-\u03BA\u03BB\u03B5\
changeMetadata.modDate=\u0397\u03BC\u03B5\u03C1\u03BF\u03BC\u03B7\u03BD\u03AF\u03B1 \u03A4\u03C1\u03BF\u03C0\u03BF\u03C0\u03BF\u03AF\u03B7\u03C3\u03B7\u03C2 (yyyy/MM/dd HH:mm:ss):
changeMetadata.producer=\u03A0\u03B1\u03C1\u03B1\u03B3\u03C9\u03B3\u03CC\u03C2:
changeMetadata.subject=\u0398\u03AD\u03BC\u03B1:
changeMetadata.title=\u03A4\u03AF\u03C4\u03BB\u03BF\u03C2:
changeMetadata.trapped=Trapped:
changeMetadata.selectText.4=\u0386\u03BB\u03BB\u03B1 \u03BC\u03B5\u03C4\u03B1\u03B4\u03B5\u03B4\u03BF\u03BC\u03AD\u03BD\u03B1:
changeMetadata.selectText.5=\u03A0\u03C1\u03BF\u03C3\u03B8\u03AE\u03BA\u03B7 \u03B5\u03B3\u03B3\u03C1\u03B1\u03C6\u03AE\u03C2 \u03C0\u03C1\u03BF\u03C3\u03B1\u03C1\u03BC\u03BF\u03C3\u03BC\u03AD\u03BD\u03C9\u03BD \u03BC\u03B5\u03C4\u03B1\u03B4\u03B5\u03B4\u03BF\u03BC\u03AD\u03BD\u03C9\u03BD

View File

@@ -1,4 +1,4 @@
###########
###########
# Generic #
###########
# the direction that the language is written (ltr = left to right, rtl = right to left)
@@ -11,6 +11,7 @@ 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) :
pageSelectionPrompt=Custom Page Selection (Enter a comma-separated list of page numbers 1,5,6 or Functions like 2n+1) :
goToPage=Go
true=True
false=False
@@ -19,13 +20,14 @@ save=Save
close=Close
filesSelected=files selected
noFavourites=No favourites added
downloadComplete=Download Complete
bored=Bored Waiting?
alphabet=Alphabet
downloadPdf=Download PDF
text=Text
font=Font
selectFillter=-- Select --
pageNum=Page Number
pageNum=Page Number
sizes.small=Small
sizes.medium=Medium
sizes.large=Large
@@ -42,7 +44,7 @@ red=Red
green=Green
blue=Blue
custom=Custom...
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
WorkInProgess=Work in progress, May not work or be buggy, Please report any problems!
poweredBy=Powered by
yes=Yes
no=No
@@ -119,8 +121,8 @@ 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.newUsername=New Username
account.password=Confirmation Password
account.oldPassword=Old password
account.newPassword=New Password
@@ -171,7 +173,7 @@ 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
split.tags=Page operations,divide,Multi Page,cut,server side
home.rotate.title=Rotate
home.rotate.desc=Easily rotate your PDFs.
@@ -312,7 +314,7 @@ home.add-page-numbers.desc=Add Page numbers throughout a document in a set locat
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
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
@@ -366,7 +368,7 @@ 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
autoRedact.tags=Redact,Hide,black out,black,marker,hidden
home.tableExtraxt.title=PDF to CSV
home.tableExtraxt.desc=Extracts Tables from a PDF converting it to CSV
@@ -410,7 +412,7 @@ 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.textsToRedactPlaceholder=e.g. \nConfidential \nTop-Secret
autoRedact.useRegexLabel=Use Regex
autoRedact.wholeWordSearchLabel=Whole Word Search
autoRedact.customPaddingLabel=Custom Extra Padding
@@ -497,7 +499,8 @@ AddStampRequest.overrideY=Override Y Coordinate
AddStampRequest.customMargin=Custom Margin
AddStampRequest.customColor=Custom Text Color
AddStampRequest.submit=Submit
#sanitizePDF
sanitizePDF.title=Sanitize PDF
sanitizePDF.header=Sanitize a PDF file
@@ -583,18 +586,18 @@ 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.selectPDF=Select a PDF File for Signing:
certSign.jksNote=Note: If your certificate type is not listed below, please convert it to a Java Keystore (.jks) file using the keytool command line tool. Then, choose the .jks file option below.
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.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.selectJKS=Select Your Java Keystore File (.jks or .keystore):
certSign.certType=Certificate Type
certSign.password=Enter Your Keystore or Private Key Password (If Any):
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.name=Name
certSign.submit=Sign PDF
@@ -656,7 +659,7 @@ ScannerImageSplit.selectText.8=Sets the minimum contour area threshold for a pho
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)
@@ -700,7 +703,7 @@ 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.selectText.5=Expected PDF Size (e.g. 25MB, 10.8MB, 25KB)
compress.submit=Compress
@@ -775,8 +778,8 @@ 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
@@ -866,7 +869,6 @@ 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

View File

@@ -1,4 +1,4 @@
###########
###########
# Generic #
###########
# the direction that the language is written (ltr=left to right, rtl = right to left)
@@ -11,6 +11,7 @@ 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) :
pageSelectionPrompt=Custom Page Selection (Enter a comma-separated list of page numbers 1,5,6 or Functions like 2n+1) :
goToPage=Go
true=True
false=False
@@ -19,6 +20,7 @@ save=Save
close=Close
filesSelected=files selected
noFavourites=No favorites added
downloadComplete=Download Complete
bored=Bored Waiting?
alphabet=Alphabet
downloadPdf=Download PDF
@@ -42,7 +44,7 @@ red=Red
green=Green
blue=Blue
custom=Custom...
WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems!
WorkInProgess=Work in progress, May not work or be buggy, Please report any problems!
poweredBy=Powered by
yes=Yes
no=No
@@ -120,7 +122,7 @@ 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.newUsername=New Username
account.password=Confirmation Password
account.oldPassword=Old password
account.newPassword=New Password
@@ -366,7 +368,7 @@ 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
autoRedact.tags=Redact,Hide,black out,black,marker,hidden
home.tableExtraxt.title=PDF to CSV
home.tableExtraxt.desc=Extracts Tables from a PDF converting it to CSV
@@ -410,7 +412,7 @@ autoRedact.title=Auto Redact
autoRedact.header=Auto Redact
autoRedact.colorLabel=Color
autoRedact.textsToRedactLabel=Text to Redact (line-separated)
autoRedact.textsToRedactPlaceholder=e.g. \nConfidential \nTop-Secret
autoRedact.textsToRedactPlaceholder=e.g. \nConfidential \nTop-Secret
autoRedact.useRegexLabel=Use Regex
autoRedact.wholeWordSearchLabel=Whole Word Search
autoRedact.customPaddingLabel=Custom Extra Padding
@@ -497,7 +499,8 @@ AddStampRequest.overrideY=Override Y Coordinate
AddStampRequest.customMargin=Custom Margin
AddStampRequest.customColor=Custom Text Color
AddStampRequest.submit=Submit
#sanitizePDF
sanitizePDF.title=Sanitize PDF
sanitizePDF.header=Sanitize a PDF file
@@ -656,7 +659,7 @@ ScannerImageSplit.selectText.8=Sets the minimum contour area threshold for a pho
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)
@@ -775,8 +778,8 @@ 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
@@ -866,7 +869,6 @@ 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

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