mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2024-11-14 03:20:14 +01:00
Merge branch 'main' into main
This commit is contained in:
commit
fdae1c9756
28
.github/workflows/push-docker.yml
vendored
28
.github/workflows/push-docker.yml
vendored
@ -110,3 +110,31 @@ jobs:
|
|||||||
labels: ${{ steps.meta2.outputs.labels }}
|
labels: ${{ steps.meta2.outputs.labels }}
|
||||||
build-args: VERSION_TAG=${{ steps.versionNumber.outputs.versionNumber }}
|
build-args: VERSION_TAG=${{ steps.versionNumber.outputs.versionNumber }}
|
||||||
platforms: linux/amd64,linux/arm64/v8
|
platforms: linux/amd64,linux/arm64/v8
|
||||||
|
|
||||||
|
|
||||||
|
- name: Generate tags fat
|
||||||
|
id: meta3
|
||||||
|
uses: docker/metadata-action@v5
|
||||||
|
if: github.ref != 'refs/heads/main'
|
||||||
|
with:
|
||||||
|
images: |
|
||||||
|
${{ secrets.DOCKER_HUB_USERNAME }}/s-pdf
|
||||||
|
ghcr.io/${{ steps.repoowner.outputs.lowercase }}/s-pdf
|
||||||
|
tags: |
|
||||||
|
type=raw,value=${{ steps.versionNumber.outputs.versionNumber }}-fat,enable=${{ github.ref == 'refs/heads/master' }}
|
||||||
|
type=raw,value=latest-fat,enable=${{ github.ref == 'refs/heads/master' }}
|
||||||
|
|
||||||
|
- name: Build and push main Dockerfile fat
|
||||||
|
uses: docker/build-push-action@v5
|
||||||
|
if: github.ref != 'refs/heads/main'
|
||||||
|
with:
|
||||||
|
builder: ${{ steps.buildx.outputs.name }}
|
||||||
|
context: .
|
||||||
|
file: ./Dockerfile-fat
|
||||||
|
push: true
|
||||||
|
cache-from: type=gha
|
||||||
|
cache-to: type=gha,mode=max
|
||||||
|
tags: ${{ steps.meta3.outputs.tags }}
|
||||||
|
labels: ${{ steps.meta3.outputs.labels }}
|
||||||
|
build-args: VERSION_TAG=${{ steps.versionNumber.outputs.versionNumber }}
|
||||||
|
platforms: linux/amd64,linux/arm64/v8
|
||||||
|
84
Dockerfile-fat
Normal file
84
Dockerfile-fat
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
# Build the application
|
||||||
|
FROM gradle:7.6-jdk17 AS build
|
||||||
|
|
||||||
|
# Set the working directory
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Copy the entire project to the working directory
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Build the application with DOCKER_ENABLE_SECURITY=false
|
||||||
|
RUN DOCKER_ENABLE_SECURITY=true \
|
||||||
|
./gradlew clean build
|
||||||
|
|
||||||
|
# Main stage
|
||||||
|
FROM alpine:3.20.0
|
||||||
|
|
||||||
|
# Copy necessary files
|
||||||
|
COPY scripts /scripts
|
||||||
|
COPY pipeline /pipeline
|
||||||
|
COPY src/main/resources/static/fonts/*.ttf /usr/share/fonts/opentype/noto/
|
||||||
|
COPY --from=build /app/build/libs/*.jar app.jar
|
||||||
|
|
||||||
|
ARG VERSION_TAG
|
||||||
|
|
||||||
|
# Set Environment Variables
|
||||||
|
ENV DOCKER_ENABLE_SECURITY=false \
|
||||||
|
VERSION_TAG=$VERSION_TAG \
|
||||||
|
JAVA_TOOL_OPTIONS="$JAVA_TOOL_OPTIONS -XX:MaxRAMPercentage=75" \
|
||||||
|
HOME=/home/stirlingpdfuser \
|
||||||
|
PUID=1000 \
|
||||||
|
PGID=1000 \
|
||||||
|
UMASK=022 \
|
||||||
|
FAT_DOCKER=true \
|
||||||
|
INSTALL_BOOK_AND_ADVANCED_HTML_OPS=true
|
||||||
|
|
||||||
|
|
||||||
|
# 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 upgrade --no-cache -a && \
|
||||||
|
apk add --no-cache \
|
||||||
|
ca-certificates \
|
||||||
|
tzdata \
|
||||||
|
tini \
|
||||||
|
bash \
|
||||||
|
curl \
|
||||||
|
calibre@testing \
|
||||||
|
shadow \
|
||||||
|
su-exec \
|
||||||
|
openssl \
|
||||||
|
openssl-dev \
|
||||||
|
openjdk21-jre \
|
||||||
|
# Doc conversion
|
||||||
|
libreoffice \
|
||||||
|
# pdftohtml
|
||||||
|
poppler-utils \
|
||||||
|
# OCR MY PDF (unpaper for descew and other advanced featues)
|
||||||
|
ocrmypdf \
|
||||||
|
tesseract-ocr-data-eng \
|
||||||
|
font-terminus font-dejavu font-noto font-noto-cjk font-awesome font-noto-extra \
|
||||||
|
# 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 && \
|
||||||
|
mkdir -p $HOME /configs /logs /customFiles /pipeline/watchedFolders /pipeline/finishedFolders && \
|
||||||
|
fc-cache -f -v && \
|
||||||
|
chmod +x /scripts/* && \
|
||||||
|
chmod +x /scripts/init.sh && \
|
||||||
|
# User permissions
|
||||||
|
addgroup -S stirlingpdfgroup && adduser -S stirlingpdfuser -G stirlingpdfgroup && \
|
||||||
|
chown -R stirlingpdfuser:stirlingpdfgroup $HOME /scripts /usr/share/fonts/opentype/noto /configs /customFiles /pipeline && \
|
||||||
|
chown stirlingpdfuser:stirlingpdfgroup /app.jar && \
|
||||||
|
tesseract --list-langs
|
||||||
|
|
||||||
|
EXPOSE 8080/tcp
|
||||||
|
|
||||||
|
# Set user and run command
|
||||||
|
ENTRYPOINT ["tini", "--", "/scripts/init.sh"]
|
||||||
|
CMD ["java", "-Dfile.encoding=UTF-8", "-jar", "/app.jar"]
|
@ -1,46 +1,47 @@
|
|||||||
| Operation | PageOps | Convert | Security | Other | CLI | Python | OpenCV | LibreOffice | OCRmyPDF | Java | Javascript |
|
| Operation | PageOps | Convert | Security | Other | CLI | Python | OpenCV | LibreOffice | OCRmyPDF | Java | Javascript |
|
||||||
|---------------------|---------|---------|----------|-------|------|--------|--------|-------------|----------|----------|------------|
|
| ------------------- | ------- | ------- | -------- | ----- | --- | ------ | ------ | ----------- | -------- | ---- | ---------- |
|
||||||
| adjust-contrast | ✔️ | | | | | | | | | | ✔️ |
|
| adjust-contrast | ✔️ | | | | | | | | | | ✔️ |
|
||||||
| auto-split-pdf | ✔️ | | | | | | | | | ✔️ | |
|
| auto-split-pdf | ✔️ | | | | | | | | | ✔️ | |
|
||||||
| crop | ✔️ | | | | | | | | | ✔️ | |
|
| crop | ✔️ | | | | | | | | | ✔️ | |
|
||||||
| extract-page | ✔️ | | | | | | | | | ✔️ | |
|
| extract-page | ✔️ | | | | | | | | | ✔️ | |
|
||||||
| merge-pdfs | ✔️ | | | | | | | | | ✔️ | |
|
| merge-pdfs | ✔️ | | | | | | | | | ✔️ | |
|
||||||
| multi-page-layout | ✔️ | | | | | | | | | ✔️ | |
|
| multi-page-layout | ✔️ | | | | | | | | | ✔️ | |
|
||||||
| pdf-organizer | ✔️ | | | | | | | | | ✔️ | ✔️ |
|
| pdf-organizer | ✔️ | | | | | | | | | ✔️ | ✔️ |
|
||||||
| pdf-to-single-page | ✔️ | | | | | | | | | ✔️ | |
|
| pdf-to-single-page | ✔️ | | | | | | | | | ✔️ | |
|
||||||
| remove-pages | ✔️ | | | | | | | | | ✔️ | |
|
| remove-pages | ✔️ | | | | | | | | | ✔️ | |
|
||||||
| rotate-pdf | ✔️ | | | | | | | | | ✔️ | |
|
| rotate-pdf | ✔️ | | | | | | | | | ✔️ | |
|
||||||
| scale-pages | ✔️ | | | | | | | | | ✔️ | |
|
| scale-pages | ✔️ | | | | | | | | | ✔️ | |
|
||||||
| split-pdfs | ✔️ | | | | | | | | | ✔️ | |
|
| split-pdfs | ✔️ | | | | | | | | | ✔️ | |
|
||||||
| file-to-pdf | | ✔️ | | | ✔️ | | | ✔️ | | | |
|
| file-to-pdf | | ✔️ | | | ✔️ | | | ✔️ | | | |
|
||||||
| img-to-pdf | | ✔️ | | | | | | | | ✔️ | |
|
| img-to-pdf | | ✔️ | | | | | | | | ✔️ | |
|
||||||
| pdf-to-html | | ✔️ | | | ✔️ | | | ✔️ | | | |
|
| pdf-to-html | | ✔️ | | | ✔️ | | | ✔️ | | | |
|
||||||
| pdf-to-img | | ✔️ | | | | | | | | ✔️ | |
|
| pdf-to-img | | ✔️ | | | | | | | | ✔️ | |
|
||||||
| pdf-to-pdfa | | ✔️ | | | ✔️ | | | | ✔️ | | |
|
| pdf-to-pdfa | | ✔️ | | | ✔️ | | | | ✔️ | | |
|
||||||
| pdf-to-markdown | | ✔️ | | | | | | | | ✔️ | |
|
| pdf-to-markdown | | ✔️ | | | | | | | | ✔️ | |
|
||||||
| pdf-to-presentation | | ✔️ | | | ✔️ | | | ✔️ | | | |
|
| pdf-to-presentation | | ✔️ | | | ✔️ | | | ✔️ | | | |
|
||||||
| pdf-to-text | | ✔️ | | | ✔️ | | | ✔️ | | | |
|
| pdf-to-text | | ✔️ | | | ✔️ | | | ✔️ | | | |
|
||||||
| pdf-to-word | | ✔️ | | | ✔️ | | | ✔️ | | | |
|
| pdf-to-word | | ✔️ | | | ✔️ | | | ✔️ | | | |
|
||||||
| pdf-to-xml | | ✔️ | | | ✔️ | | | ✔️ | | | |
|
| pdf-to-xml | | ✔️ | | | ✔️ | | | ✔️ | | | |
|
||||||
| xlsx-to-pdf | | ✔️ | | | ✔️ | | | ✔️ | | | |
|
| xlsx-to-pdf | | ✔️ | | | ✔️ | | | ✔️ | | | |
|
||||||
| add-password | | | ✔️ | | | | | | | ✔️ | |
|
| add-password | | | ✔️ | | | | | | | ✔️ | |
|
||||||
| add-watermark | | | ✔️ | | | | | | | ✔️ | |
|
| add-watermark | | | ✔️ | | | | | | | ✔️ | |
|
||||||
| cert-sign | | | ✔️ | | | | | | | ✔️ | |
|
| cert-sign | | | ✔️ | | | | | | | ✔️ | |
|
||||||
| change-permissions | | | ✔️ | | | | | | | ✔️ | |
|
| remove-cert-sign | | | ✔️ | | | | | | | ✔️ | |
|
||||||
| remove-password | | | ✔️ | | | | | | | ✔️ | |
|
| change-permissions | | | ✔️ | | | | | | | ✔️ | |
|
||||||
| sanitize-pdf | | | ✔️ | | | | | | | ✔️ | |
|
| remove-password | | | ✔️ | | | | | | | ✔️ | |
|
||||||
| add-image | | | | ✔️ | | | | | | ✔️ | |
|
| sanitize-pdf | | | ✔️ | | | | | | | ✔️ | |
|
||||||
| add-page-numbers | | | | ✔️ | | | | | | ✔️ | |
|
| add-image | | | | ✔️ | | | | | | ✔️ | |
|
||||||
| auto-rename | | | | ✔️ | | | | | | ✔️ | |
|
| add-page-numbers | | | | ✔️ | | | | | | ✔️ | |
|
||||||
| change-metadata | | | | ✔️ | | | | | | ✔️ | |
|
| auto-rename | | | | ✔️ | | | | | | ✔️ | |
|
||||||
| compare | | | | ✔️ | | | | | | | ✔️ |
|
| change-metadata | | | | ✔️ | | | | | | ✔️ | |
|
||||||
| compress-pdf | | | | ✔️ | ✔️ | | | | ✔️ | | |
|
| compare | | | | ✔️ | | | | | | | ✔️ |
|
||||||
| extract-image-scans | | | | ✔️ | ✔️ | ✔️ | ✔️ | | | | |
|
| compress-pdf | | | | ✔️ | ✔️ | | | | ✔️ | | |
|
||||||
| extract-images | | | | ✔️ | | | | | | ✔️ | |
|
| extract-image-scans | | | | ✔️ | ✔️ | ✔️ | ✔️ | | | | |
|
||||||
| flatten | | | | ✔️ | | | | | | | ✔️ |
|
| extract-images | | | | ✔️ | | | | | | ✔️ | |
|
||||||
| get-info-on-pdf | | | | ✔️ | | | | | | ✔️ | |
|
| flatten | | | | ✔️ | | | | | | | ✔️ |
|
||||||
| ocr-pdf | | | | ✔️ | ✔️ | | | | ✔️ | | |
|
| get-info-on-pdf | | | | ✔️ | | | | | | ✔️ | |
|
||||||
| remove-blanks | | | | ✔️ | ✔️ | ✔️ | ✔️ | | | | |
|
| ocr-pdf | | | | ✔️ | ✔️ | | | | ✔️ | | |
|
||||||
| repair | | | | ✔️ | ✔️ | | | ✔️ | | | |
|
| remove-blanks | | | | ✔️ | ✔️ | ✔️ | ✔️ | | | | |
|
||||||
| show-javascript | | | | ✔️ | | | | | | | ✔️ |
|
| repair | | | | ✔️ | ✔️ | | | ✔️ | | | |
|
||||||
| sign | | | | ✔️ | | | | | | | ✔️ |
|
| show-javascript | | | | ✔️ | | | | | | | ✔️ |
|
||||||
|
| sign | | | | ✔️ | | | | | | | ✔️ |
|
58
README.md
58
README.md
@ -159,39 +159,41 @@ Please view https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToUseOCR
|
|||||||
|
|
||||||
## Supported Languages
|
## Supported Languages
|
||||||
|
|
||||||
Stirling PDF currently supports 28!
|
Stirling PDF currently supports 32!
|
||||||
|
|
||||||
| Language | Progress |
|
| Language | Progress |
|
||||||
| ------------------------------------------- | -------------------------------------- |
|
| ------------------------------------------- | -------------------------------------- |
|
||||||
| English (English) (en_GB) | ![100%](https://geps.dev/progress/100) |
|
| English (English) (en_GB) | ![100%](https://geps.dev/progress/100) |
|
||||||
| English (US) (en_US) | ![100%](https://geps.dev/progress/100) |
|
| English (US) (en_US) | ![100%](https://geps.dev/progress/100) |
|
||||||
| Arabic (العربية) (ar_AR) | ![41%](https://geps.dev/progress/41) |
|
| Arabic (العربية) (ar_AR) | ![40%](https://geps.dev/progress/40) |
|
||||||
| German (Deutsch) (de_DE) | ![100%](https://geps.dev/progress/100) |
|
| German (Deutsch) (de_DE) | ![99%](https://geps.dev/progress/99) |
|
||||||
| French (Français) (fr_FR) | ![95%](https://geps.dev/progress/95) |
|
| French (Français) (fr_FR) | ![93%](https://geps.dev/progress/93) |
|
||||||
| Spanish (Español) (es_ES) | ![96%](https://geps.dev/progress/96) |
|
| Spanish (Español) (es_ES) | ![95%](https://geps.dev/progress/95) |
|
||||||
| Simplified Chinese (简体中文) (zh_CN) | ![96%](https://geps.dev/progress/96) |
|
| Simplified Chinese (简体中文) (zh_CN) | ![95%](https://geps.dev/progress/95) |
|
||||||
| Traditional Chinese (繁體中文) (zh_TW) | ![95%](https://geps.dev/progress/95) |
|
| Traditional Chinese (繁體中文) (zh_TW) | ![94%](https://geps.dev/progress/94) |
|
||||||
| Catalan (Català) (ca_CA) | ![49%](https://geps.dev/progress/49) |
|
| Catalan (Català) (ca_CA) | ![49%](https://geps.dev/progress/49) |
|
||||||
| Italian (Italiano) (it_IT) | ![99%](https://geps.dev/progress/99) |
|
| Italian (Italiano) (it_IT) | ![98%](https://geps.dev/progress/98) |
|
||||||
| Swedish (Svenska) (sv_SE) | ![41%](https://geps.dev/progress/41) |
|
| Swedish (Svenska) (sv_SE) | ![40%](https://geps.dev/progress/40) |
|
||||||
| Polish (Polski) (pl_PL) | ![43%](https://geps.dev/progress/43) |
|
| Polish (Polski) (pl_PL) | ![42%](https://geps.dev/progress/42) |
|
||||||
| Romanian (Română) (ro_RO) | ![40%](https://geps.dev/progress/40) |
|
| Romanian (Română) (ro_RO) | ![39%](https://geps.dev/progress/39) |
|
||||||
| Korean (한국어) (ko_KR) | ![88%](https://geps.dev/progress/88) |
|
| Korean (한국어) (ko_KR) | ![87%](https://geps.dev/progress/87) |
|
||||||
| Portuguese Brazilian (Português) (pt_BR) | ![62%](https://geps.dev/progress/62) |
|
| Portuguese Brazilian (Português) (pt_BR) | ![61%](https://geps.dev/progress/61) |
|
||||||
| Russian (Русский) (ru_RU) | ![88%](https://geps.dev/progress/88) |
|
| Russian (Русский) (ru_RU) | ![87%](https://geps.dev/progress/87) |
|
||||||
| Basque (Euskara) (eu_ES) | ![64%](https://geps.dev/progress/64) |
|
| Basque (Euskara) (eu_ES) | ![63%](https://geps.dev/progress/63) |
|
||||||
| Japanese (日本語) (ja_JP) | ![88%](https://geps.dev/progress/88) |
|
| Japanese (日本語) (ja_JP) | ![87%](https://geps.dev/progress/87) |
|
||||||
| Dutch (Nederlands) (nl_NL) | ![86%](https://geps.dev/progress/86) |
|
| Dutch (Nederlands) (nl_NL) | ![85%](https://geps.dev/progress/85) |
|
||||||
| Greek (Ελληνικά) (el_GR) | ![86%](https://geps.dev/progress/86) |
|
| Greek (Ελληνικά) (el_GR) | ![85%](https://geps.dev/progress/85) |
|
||||||
| Turkish (Türkçe) (tr_TR) | ![99%](https://geps.dev/progress/99) |
|
| Turkish (Türkçe) (tr_TR) | ![97%](https://geps.dev/progress/97) |
|
||||||
| Indonesia (Bahasa Indonesia) (id_ID) | ![79%](https://geps.dev/progress/79) |
|
| Indonesia (Bahasa Indonesia) (id_ID) | ![78%](https://geps.dev/progress/78) |
|
||||||
| Hindi (हिंदी) (hi_IN) | ![80%](https://geps.dev/progress/80) |
|
| Hindi (हिंदी) (hi_IN) | ![79%](https://geps.dev/progress/79) |
|
||||||
| Hungarian (Magyar) (hu_HU) | ![79%](https://geps.dev/progress/79) |
|
| Hungarian (Magyar) (hu_HU) | ![78%](https://geps.dev/progress/78) |
|
||||||
| Bulgarian (Български) (bg_BG) | ![96%](https://geps.dev/progress/96) |
|
| Bulgarian (Български) (bg_BG) | ![98%](https://geps.dev/progress/98) |
|
||||||
| Sebian Latin alphabet (Srpski) (sr_LATN_RS) | ![81%](https://geps.dev/progress/81) |
|
| Sebian Latin alphabet (Srpski) (sr_LATN_RS) | ![80%](https://geps.dev/progress/80) |
|
||||||
| Ukrainian (Українська) (uk_UA) | ![87%](https://geps.dev/progress/87) |
|
| Ukrainian (Українська) (uk_UA) | ![86%](https://geps.dev/progress/86) |
|
||||||
| Slovakian (Slovensky) (sk_SK) | ![96%](https://geps.dev/progress/96) |
|
| Slovakian (Slovensky) (sk_SK) | ![95%](https://geps.dev/progress/95) |
|
||||||
| Czech (Česky) (cs_CZ) | ![94%](https://geps.dev/progress/94) |
|
| Czech (Česky) (cs_CZ) | ![94%](https://geps.dev/progress/94) |
|
||||||
|
| Croatian (Hrvatski) (hr_HR) | ![98%](https://geps.dev/progress/98) |
|
||||||
|
| Norwegian (Norsk) (no_NB) | ![98%](https://geps.dev/progress/98) |
|
||||||
|
|
||||||
## Contributing (creating issues, translations, fixing bugs, etc.)
|
## Contributing (creating issues, translations, fixing bugs, etc.)
|
||||||
|
|
||||||
@ -213,10 +215,10 @@ For example in the settings.yml you have
|
|||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
system:
|
system:
|
||||||
defaultLocale: 'en-US'
|
enableLogin: 'true'
|
||||||
```
|
```
|
||||||
|
|
||||||
To have this via an environment variable you would have ``SYSTEM_DEFAULTLOCALE``
|
To have this via an environment variable you would have ``SYSTEM_ENABLELOGIN``
|
||||||
|
|
||||||
The Current list of settings is
|
The Current list of settings is
|
||||||
|
|
||||||
|
@ -1,52 +1,53 @@
|
|||||||
| Technology | Ultra-Lite | Full |
|
| Technology | Ultra-Lite | Full |
|
||||||
|----------------|:----------:|:----:|
|
| ---------- | :--------: | :---: |
|
||||||
| Java | ✔️ | ✔️ |
|
| Java | ✔️ | ✔️ |
|
||||||
| JavaScript | ✔️ | ✔️ |
|
| JavaScript | ✔️ | ✔️ |
|
||||||
| Libre | | ✔️ |
|
| Libre | | ✔️ |
|
||||||
| Python | | ✔️ |
|
| Python | | ✔️ |
|
||||||
| OpenCV | | ✔️ |
|
| OpenCV | | ✔️ |
|
||||||
| OCRmyPDF | | ✔️ |
|
| OCRmyPDF | | ✔️ |
|
||||||
|
|
||||||
Operation | Ultra-Lite | Full
|
| Operation | Ultra-Lite | Full |
|
||||||
-------------------------|------------|-----
|
| ---------------------- | ---------- | ---- |
|
||||||
add-page-numbers | ✔️ | ✔️
|
| add-page-numbers | ✔️ | ✔️ |
|
||||||
add-password | ✔️ | ✔️
|
| add-password | ✔️ | ✔️ |
|
||||||
add-image | ✔️ | ✔️
|
| add-image | ✔️ | ✔️ |
|
||||||
add-watermark | ✔️ | ✔️
|
| add-watermark | ✔️ | ✔️ |
|
||||||
adjust-contrast | ✔️ | ✔️
|
| adjust-contrast | ✔️ | ✔️ |
|
||||||
auto-split-pdf | ✔️ | ✔️
|
| auto-split-pdf | ✔️ | ✔️ |
|
||||||
auto-redact | ✔️ | ✔️
|
| auto-redact | ✔️ | ✔️ |
|
||||||
auto-rename | ✔️ | ✔️
|
| auto-rename | ✔️ | ✔️ |
|
||||||
cert-sign | ✔️ | ✔️
|
| cert-sign | ✔️ | ✔️ |
|
||||||
crop | ✔️ | ✔️
|
| remove-cert-sign | ✔️ | ✔️ |
|
||||||
change-metadata | ✔️ | ✔️
|
| crop | ✔️ | ✔️ |
|
||||||
change-permissions | ✔️ | ✔️
|
| change-metadata | ✔️ | ✔️ |
|
||||||
compare | ✔️ | ✔️
|
| change-permissions | ✔️ | ✔️ |
|
||||||
extract-page | ✔️ | ✔️
|
| compare | ✔️ | ✔️ |
|
||||||
extract-images | ✔️ | ✔️
|
| extract-page | ✔️ | ✔️ |
|
||||||
flatten | ✔️ | ✔️
|
| extract-images | ✔️ | ✔️ |
|
||||||
get-info-on-pdf | ✔️ | ✔️
|
| flatten | ✔️ | ✔️ |
|
||||||
img-to-pdf | ✔️ | ✔️
|
| get-info-on-pdf | ✔️ | ✔️ |
|
||||||
markdown-to-pdf | ✔️ | ✔️
|
| img-to-pdf | ✔️ | ✔️ |
|
||||||
merge-pdfs | ✔️ | ✔️
|
| markdown-to-pdf | ✔️ | ✔️ |
|
||||||
multi-page-layout | ✔️ | ✔️
|
| merge-pdfs | ✔️ | ✔️ |
|
||||||
overlay-pdf | ✔️ | ✔️
|
| multi-page-layout | ✔️ | ✔️ |
|
||||||
pdf-organizer | ✔️ | ✔️
|
| overlay-pdf | ✔️ | ✔️ |
|
||||||
pdf-to-csv | ✔️ | ✔️
|
| pdf-organizer | ✔️ | ✔️ |
|
||||||
pdf-to-img | ✔️ | ✔️
|
| pdf-to-csv | ✔️ | ✔️ |
|
||||||
pdf-to-single-page | ✔️ | ✔️
|
| pdf-to-img | ✔️ | ✔️ |
|
||||||
remove-pages | ✔️ | ✔️
|
| pdf-to-single-page | ✔️ | ✔️ |
|
||||||
remove-password | ✔️ | ✔️
|
| remove-pages | ✔️ | ✔️ |
|
||||||
rotate-pdf | ✔️ | ✔️
|
| remove-password | ✔️ | ✔️ |
|
||||||
sanitize-pdf | ✔️ | ✔️
|
| rotate-pdf | ✔️ | ✔️ |
|
||||||
scale-pages | ✔️ | ✔️
|
| sanitize-pdf | ✔️ | ✔️ |
|
||||||
sign | ✔️ | ✔️
|
| scale-pages | ✔️ | ✔️ |
|
||||||
show-javascript | ✔️ | ✔️
|
| sign | ✔️ | ✔️ |
|
||||||
split-by-size-or-count | ✔️ | ✔️
|
| show-javascript | ✔️ | ✔️ |
|
||||||
split-pdf-by-sections | ✔️ | ✔️
|
| split-by-size-or-count | ✔️ | ✔️ |
|
||||||
split-pdfs | ✔️ | ✔️
|
| split-pdf-by-sections | ✔️ | ✔️ |
|
||||||
compress-pdf | | ✔️
|
| split-pdfs | ✔️ | ✔️ |
|
||||||
extract-image-scans | | ✔️
|
| compress-pdf | | ✔️ |
|
||||||
ocr-pdf | | ✔️
|
| extract-image-scans | | ✔️ |
|
||||||
pdf-to-pdfa | | ✔️
|
| ocr-pdf | | ✔️ |
|
||||||
remove-blanks | | ✔️
|
| pdf-to-pdfa | | ✔️ |
|
||||||
|
| remove-blanks | | ✔️ |
|
||||||
|
13
build.gradle
13
build.gradle
@ -12,7 +12,7 @@ plugins {
|
|||||||
import com.github.jk1.license.render.*
|
import com.github.jk1.license.render.*
|
||||||
|
|
||||||
group = 'stirling.software'
|
group = 'stirling.software'
|
||||||
version = '0.24.6'
|
version = '0.25.2'
|
||||||
|
|
||||||
//17 is lowest but we support and recommend 21
|
//17 is lowest but we support and recommend 21
|
||||||
sourceCompatibility = '17'
|
sourceCompatibility = '17'
|
||||||
@ -21,7 +21,6 @@ repositories {
|
|||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
licenseReport {
|
licenseReport {
|
||||||
renderers = [new JsonReportRenderer()]
|
renderers = [new JsonReportRenderer()]
|
||||||
}
|
}
|
||||||
@ -172,14 +171,14 @@ dependencies {
|
|||||||
annotationProcessor 'org.projectlombok:lombok:1.18.32'
|
annotationProcessor 'org.projectlombok:lombok:1.18.32'
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.withType(JavaCompile) {
|
tasks.withType(JavaCompile).configureEach {
|
||||||
dependsOn 'spotlessApply'
|
dependsOn 'spotlessApply'
|
||||||
}
|
}
|
||||||
compileJava {
|
compileJava {
|
||||||
options.compilerArgs << '-parameters'
|
options.compilerArgs << '-parameters'
|
||||||
}
|
}
|
||||||
|
|
||||||
task writeVersion {
|
task writeVersion {
|
||||||
def propsFile = file('src/main/resources/version.properties')
|
def propsFile = file('src/main/resources/version.properties')
|
||||||
def props = new Properties()
|
def props = new Properties()
|
||||||
props.setProperty('version', version)
|
props.setProperty('version', version)
|
||||||
@ -196,8 +195,6 @@ swaggerhubUpload {
|
|||||||
oas '3.0.0' // The version of the OpenAPI Specification you're using
|
oas '3.0.0' // The version of the OpenAPI Specification you're using
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
jar {
|
jar {
|
||||||
enabled = false
|
enabled = false
|
||||||
manifest {
|
manifest {
|
||||||
@ -211,6 +208,6 @@ tasks.named('test') {
|
|||||||
useJUnitPlatform()
|
useJUnitPlatform()
|
||||||
}
|
}
|
||||||
|
|
||||||
task printVersion {
|
task printVersion {
|
||||||
println project.version
|
println project.version
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
apiVersion: v2
|
apiVersion: v2
|
||||||
appVersion: 0.24.6
|
appVersion: 0.25.2
|
||||||
description: locally hosted web application that allows you to perform various operations
|
description: locally hosted web application that allows you to perform various operations
|
||||||
on PDF files
|
on PDF files
|
||||||
home: https://github.com/Stirling-Tools/Stirling-PDF
|
home: https://github.com/Stirling-Tools/Stirling-PDF
|
||||||
|
34
exampleYmlFiles/docker-compose-latest-fat-security.yml
Normal file
34
exampleYmlFiles/docker-compose-latest-fat-security.yml
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
version: '3.3'
|
||||||
|
services:
|
||||||
|
stirling-pdf:
|
||||||
|
container_name: Stirling-PDF-Security-Fat
|
||||||
|
image: frooodle/s-pdf:latest-fat
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
memory: 4G
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "curl -f http://localhost:8080/api/v1/info/status | grep -q 'UP' && curl -fL http://localhost:8080/ | grep -q 'Please sign in'"]
|
||||||
|
interval: 5s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 16
|
||||||
|
ports:
|
||||||
|
- 8080:8080
|
||||||
|
volumes:
|
||||||
|
- /stirling/latest/data:/usr/share/tessdata:rw
|
||||||
|
- /stirling/latest/config:/configs:rw
|
||||||
|
- /stirling/latest/logs:/logs:rw
|
||||||
|
environment:
|
||||||
|
DOCKER_ENABLE_SECURITY: "true"
|
||||||
|
SECURITY_ENABLELOGIN: "true"
|
||||||
|
PUID: 1002
|
||||||
|
PGID: 1002
|
||||||
|
UMASK: "022"
|
||||||
|
SYSTEM_DEFAULTLOCALE: en-US
|
||||||
|
UI_APPNAME: Stirling-PDF
|
||||||
|
UI_HOMEDESCRIPTION: Demo site for Stirling-PDF Latest-fat with Security
|
||||||
|
UI_APPNAMENAVBAR: Stirling-PDF Latest-fat
|
||||||
|
SYSTEM_MAXFILESIZE: "100"
|
||||||
|
METRICS_ENABLED: "true"
|
||||||
|
SYSTEM_GOOGLEVISIBILITY: "true"
|
||||||
|
restart: on-failure:5
|
@ -13,7 +13,7 @@ services:
|
|||||||
timeout: 10s
|
timeout: 10s
|
||||||
retries: 16
|
retries: 16
|
||||||
ports:
|
ports:
|
||||||
- 8080:8080
|
- "8080:8080"
|
||||||
volumes:
|
volumes:
|
||||||
- /stirling/latest/data:/usr/share/tessdata:rw
|
- /stirling/latest/data:/usr/share/tessdata:rw
|
||||||
- /stirling/latest/config:/configs:rw
|
- /stirling/latest/config:/configs:rw
|
||||||
@ -27,6 +27,8 @@ services:
|
|||||||
SECURITY_OAUTH2_CLIENTID: "<YOUR CLIENT ID>.apps.googleusercontent.com" # Client ID from your provider
|
SECURITY_OAUTH2_CLIENTID: "<YOUR CLIENT ID>.apps.googleusercontent.com" # Client ID from your provider
|
||||||
SECURITY_OAUTH2_CLIENTSECRET: "<YOUR CLIENT SECRET>" # Client Secret from your provider
|
SECURITY_OAUTH2_CLIENTSECRET: "<YOUR CLIENT SECRET>" # Client Secret from your provider
|
||||||
SECURITY_OAUTH2_SCOPES: "openid,profile,email" # Expected OAuth2 Scope
|
SECURITY_OAUTH2_SCOPES: "openid,profile,email" # Expected OAuth2 Scope
|
||||||
|
SECURITY_OAUTH2_USEASUSERNAME: "email" # Default is 'email'; custom fields can be used as the username
|
||||||
|
SECURITY_OAUTH2_PROVIDER: "google" # Set this to your OAuth provider's name, e.g., 'google' or 'keycloak'
|
||||||
PUID: 1002
|
PUID: 1002
|
||||||
PGID: 1002
|
PGID: 1002
|
||||||
UMASK: "022"
|
UMASK: "022"
|
||||||
|
@ -13,7 +13,7 @@ services:
|
|||||||
timeout: 10s
|
timeout: 10s
|
||||||
retries: 16
|
retries: 16
|
||||||
ports:
|
ports:
|
||||||
- 8080:8080
|
- "8080:8080"
|
||||||
volumes:
|
volumes:
|
||||||
- /stirling/latest/data:/usr/share/tessdata:rw
|
- /stirling/latest/data:/usr/share/tessdata:rw
|
||||||
- /stirling/latest/config:/configs:rw
|
- /stirling/latest/config:/configs:rw
|
||||||
|
@ -13,7 +13,7 @@ services:
|
|||||||
timeout: 10s
|
timeout: 10s
|
||||||
retries: 16
|
retries: 16
|
||||||
ports:
|
ports:
|
||||||
- 8080:8080
|
- "8080:8080"
|
||||||
volumes:
|
volumes:
|
||||||
- /stirling/latest/data:/usr/share/tessdata:rw
|
- /stirling/latest/data:/usr/share/tessdata:rw
|
||||||
- /stirling/latest/config:/configs:rw
|
- /stirling/latest/config:/configs:rw
|
||||||
|
@ -13,7 +13,7 @@ services:
|
|||||||
timeout: 10s
|
timeout: 10s
|
||||||
retries: 16
|
retries: 16
|
||||||
ports:
|
ports:
|
||||||
- 8080:8080
|
- "8080:8080"
|
||||||
volumes:
|
volumes:
|
||||||
- /stirling/latest/config:/configs:rw
|
- /stirling/latest/config:/configs:rw
|
||||||
- /stirling/latest/logs:/logs:rw
|
- /stirling/latest/logs:/logs:rw
|
||||||
|
@ -13,7 +13,7 @@ services:
|
|||||||
timeout: 10s
|
timeout: 10s
|
||||||
retries: 16
|
retries: 16
|
||||||
ports:
|
ports:
|
||||||
- 8080:8080
|
- "8080:8080"
|
||||||
volumes:
|
volumes:
|
||||||
- /stirling/latest/data:/usr/share/tessdata:rw
|
- /stirling/latest/data:/usr/share/tessdata:rw
|
||||||
- /stirling/latest/config:/configs:rw
|
- /stirling/latest/config:/configs:rw
|
||||||
|
@ -11,14 +11,16 @@ if [ ! -z "$PGID" ] && [ "$PGID" != "$(getent group stirlingpdfgroup | cut -d: -
|
|||||||
fi
|
fi
|
||||||
umask "$UMASK" || true
|
umask "$UMASK" || true
|
||||||
|
|
||||||
if [[ "$INSTALL_BOOK_AND_ADVANCED_HTML_OPS" == "true" ]]; then
|
if [[ "$INSTALL_BOOK_AND_ADVANCED_HTML_OPS" == "true" && "$FAT_DOCKER" != "true" ]]; then
|
||||||
apk add --no-cache calibre@testing
|
apk add --no-cache calibre@testing
|
||||||
fi
|
fi
|
||||||
|
|
||||||
/scripts/download-security-jar.sh
|
if [[ "$FAT_DOCKER" != "true" ]]; then
|
||||||
|
/scripts/download-security-jar.sh
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ -n "$LANGS" ]]; then
|
if [[ -n "$LANGS" ]]; then
|
||||||
/scripts/installFonts.sh $LANGS
|
/scripts/installFonts.sh $LANGS
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Setting permissions and ownership for necessary directories..."
|
echo "Setting permissions and ownership for necessary directories..."
|
||||||
|
@ -15,7 +15,10 @@ ignore = [
|
|||||||
|
|
||||||
[cs_CZ]
|
[cs_CZ]
|
||||||
ignore = [
|
ignore = [
|
||||||
|
'info',
|
||||||
'language.direction',
|
'language.direction',
|
||||||
|
'pipeline.header',
|
||||||
|
'text',
|
||||||
]
|
]
|
||||||
|
|
||||||
[de_DE]
|
[de_DE]
|
||||||
@ -65,6 +68,16 @@ ignore = [
|
|||||||
'language.direction',
|
'language.direction',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[hr_HR]
|
||||||
|
ignore = [
|
||||||
|
'font',
|
||||||
|
'home.pipeline.title',
|
||||||
|
'info',
|
||||||
|
'language.direction',
|
||||||
|
'pdfOrganiser.tags',
|
||||||
|
'showJS.tags',
|
||||||
|
]
|
||||||
|
|
||||||
[hu_HU]
|
[hu_HU]
|
||||||
ignore = [
|
ignore = [
|
||||||
'language.direction',
|
'language.direction',
|
||||||
@ -103,6 +116,11 @@ ignore = [
|
|||||||
'language.direction',
|
'language.direction',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[no_NB]
|
||||||
|
ignore = [
|
||||||
|
'language.direction',
|
||||||
|
]
|
||||||
|
|
||||||
[pl_PL]
|
[pl_PL]
|
||||||
ignore = [
|
ignore = [
|
||||||
'language.direction',
|
'language.direction',
|
||||||
|
@ -6,11 +6,15 @@ import java.net.Socket;
|
|||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import io.github.pixee.security.SystemCommand;
|
import io.github.pixee.security.SystemCommand;
|
||||||
|
|
||||||
public class LibreOfficeListener {
|
public class LibreOfficeListener {
|
||||||
|
|
||||||
private static final long ACTIVITY_TIMEOUT = 20 * 60 * 1000; // 20 minutes
|
private static final Logger logger = LoggerFactory.getLogger(LibreOfficeListener.class);
|
||||||
|
private static final long ACTIVITY_TIMEOUT = 20L * 60 * 1000; // 20 minutes
|
||||||
|
|
||||||
private static final LibreOfficeListener INSTANCE = new LibreOfficeListener();
|
private static final LibreOfficeListener INSTANCE = new LibreOfficeListener();
|
||||||
private static final int LISTENER_PORT = 2002;
|
private static final int LISTENER_PORT = 2002;
|
||||||
@ -27,14 +31,12 @@ public class LibreOfficeListener {
|
|||||||
private LibreOfficeListener() {}
|
private LibreOfficeListener() {}
|
||||||
|
|
||||||
private boolean isListenerRunning() {
|
private boolean isListenerRunning() {
|
||||||
try {
|
System.out.println("waiting for listener to start");
|
||||||
System.out.println("waiting for listener to start");
|
try (Socket socket = new Socket()) {
|
||||||
Socket socket = new Socket();
|
|
||||||
socket.connect(
|
socket.connect(
|
||||||
new InetSocketAddress("localhost", 2002), 1000); // Timeout after 1 second
|
new InetSocketAddress("localhost", 2002), 1000); // Timeout after 1 second
|
||||||
socket.close();
|
|
||||||
return true;
|
return true;
|
||||||
} catch (IOException e) {
|
} catch (Exception e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -63,6 +65,7 @@ public class LibreOfficeListener {
|
|||||||
try {
|
try {
|
||||||
Thread.sleep(5000); // Check for inactivity every 5 seconds
|
Thread.sleep(5000); // Check for inactivity every 5 seconds
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -80,8 +83,8 @@ public class LibreOfficeListener {
|
|||||||
try {
|
try {
|
||||||
Thread.sleep(1000);
|
Thread.sleep(1000);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
// TODO Auto-generated catch block
|
Thread.currentThread().interrupt();
|
||||||
e.printStackTrace();
|
logger.error("exception", e);
|
||||||
} // Check every 1 second
|
} // Check every 1 second
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,13 @@ package stirling.software.SPDF.config;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
@ -22,6 +26,8 @@ import stirling.software.SPDF.model.ApplicationProperties;
|
|||||||
@Lazy
|
@Lazy
|
||||||
public class AppConfig {
|
public class AppConfig {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(AppConfig.class);
|
||||||
|
|
||||||
@Autowired ApplicationProperties applicationProperties;
|
@Autowired ApplicationProperties applicationProperties;
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ -54,7 +60,7 @@ public class AppConfig {
|
|||||||
props.load(resource.getInputStream());
|
props.load(resource.getInputStream());
|
||||||
return props.getProperty("version");
|
return props.getProperty("version");
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
logger.error("exception", e);
|
||||||
}
|
}
|
||||||
return "0.0.0";
|
return "0.0.0";
|
||||||
}
|
}
|
||||||
@ -108,4 +114,26 @@ public class AppConfig {
|
|||||||
public boolean missingActivSecurity() {
|
public boolean missingActivSecurity() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean(name = "watchedFoldersDir")
|
||||||
|
public String watchedFoldersDir() {
|
||||||
|
return "./pipeline/watchedFolders/";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean(name = "finishedFoldersDir")
|
||||||
|
public String finishedFoldersDir() {
|
||||||
|
return "./pipeline/finishedFolders/";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean(name = "directoryFilter")
|
||||||
|
public Predicate<Path> processPDFOnlyFilter() {
|
||||||
|
return path -> {
|
||||||
|
if (Files.isDirectory(path)) {
|
||||||
|
return !path.toString().contains("processing");
|
||||||
|
} else {
|
||||||
|
String fileName = path.getFileName().toString();
|
||||||
|
return fileName.endsWith(".pdf");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,6 @@ import java.net.URISyntaxException;
|
|||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.springframework.context.ApplicationContextInitializer;
|
import org.springframework.context.ApplicationContextInitializer;
|
||||||
@ -45,46 +44,47 @@ public class ConfigInitializer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Path templatePath =
|
// Path templatePath =
|
||||||
Paths.get(
|
// Paths.get(
|
||||||
getClass()
|
// getClass()
|
||||||
.getClassLoader()
|
// .getClassLoader()
|
||||||
.getResource("settings.yml.template")
|
// .getResource("settings.yml.template")
|
||||||
.toURI());
|
// .toURI());
|
||||||
Path userPath = Paths.get("configs", "settings.yml");
|
// Path userPath = Paths.get("configs", "settings.yml");
|
||||||
|
//
|
||||||
List<String> templateLines = Files.readAllLines(templatePath);
|
// List<String> templateLines = Files.readAllLines(templatePath);
|
||||||
List<String> userLines =
|
// List<String> userLines =
|
||||||
Files.exists(userPath) ? Files.readAllLines(userPath) : new ArrayList<>();
|
// Files.exists(userPath) ? Files.readAllLines(userPath) : new
|
||||||
|
// ArrayList<>();
|
||||||
List<String> resultLines = new ArrayList<>();
|
//
|
||||||
int position = 0;
|
// List<String> resultLines = new ArrayList<>();
|
||||||
for (String templateLine : templateLines) {
|
// int position = 0;
|
||||||
// Check if the line is a comment
|
// for (String templateLine : templateLines) {
|
||||||
if (templateLine.trim().startsWith("#")) {
|
// // Check if the line is a comment
|
||||||
String entry = templateLine.trim().substring(1).trim();
|
// if (templateLine.trim().startsWith("#")) {
|
||||||
if (!entry.isEmpty()) {
|
// String entry = templateLine.trim().substring(1).trim();
|
||||||
// Check if this comment has been uncommented in userLines
|
// if (!entry.isEmpty()) {
|
||||||
String key = entry.split(":")[0].trim();
|
// // Check if this comment has been uncommented in userLines
|
||||||
addLine(resultLines, userLines, templateLine, key, position);
|
// String key = entry.split(":")[0].trim();
|
||||||
} else {
|
// addLine(resultLines, userLines, templateLine, key, position);
|
||||||
resultLines.add(templateLine);
|
// } else {
|
||||||
}
|
// resultLines.add(templateLine);
|
||||||
}
|
// }
|
||||||
// Check if the line is a key-value pair
|
// }
|
||||||
else if (templateLine.contains(":")) {
|
// // Check if the line is a key-value pair
|
||||||
String key = templateLine.split(":")[0].trim();
|
// else if (templateLine.contains(":")) {
|
||||||
addLine(resultLines, userLines, templateLine, key, position);
|
// String key = templateLine.split(":")[0].trim();
|
||||||
}
|
// addLine(resultLines, userLines, templateLine, key, position);
|
||||||
// Handle empty lines
|
// }
|
||||||
else if (templateLine.trim().length() == 0) {
|
// // Handle empty lines
|
||||||
resultLines.add("");
|
// else if (templateLine.trim().length() == 0) {
|
||||||
}
|
// resultLines.add("");
|
||||||
position++;
|
// }
|
||||||
}
|
// position++;
|
||||||
|
// }
|
||||||
// Write the result to the user settings file
|
//
|
||||||
Files.write(userPath, resultLines);
|
// // Write the result to the user settings file
|
||||||
|
// Files.write(userPath, resultLines);
|
||||||
}
|
}
|
||||||
|
|
||||||
Path customSettingsPath = Paths.get("configs", "custom_settings.yml");
|
Path customSettingsPath = Paths.get("configs", "custom_settings.yml");
|
||||||
|
@ -116,6 +116,7 @@ public class EndpointConfiguration {
|
|||||||
addEndpointToGroup("Security", "change-permissions");
|
addEndpointToGroup("Security", "change-permissions");
|
||||||
addEndpointToGroup("Security", "add-watermark");
|
addEndpointToGroup("Security", "add-watermark");
|
||||||
addEndpointToGroup("Security", "cert-sign");
|
addEndpointToGroup("Security", "cert-sign");
|
||||||
|
addEndpointToGroup("Security", "remove-cert-sign");
|
||||||
addEndpointToGroup("Security", "sanitize-pdf");
|
addEndpointToGroup("Security", "sanitize-pdf");
|
||||||
addEndpointToGroup("Security", "auto-redact");
|
addEndpointToGroup("Security", "auto-redact");
|
||||||
|
|
||||||
@ -200,6 +201,7 @@ public class EndpointConfiguration {
|
|||||||
addEndpointToGroup("Java", "extract-images");
|
addEndpointToGroup("Java", "extract-images");
|
||||||
addEndpointToGroup("Java", "change-metadata");
|
addEndpointToGroup("Java", "change-metadata");
|
||||||
addEndpointToGroup("Java", "cert-sign");
|
addEndpointToGroup("Java", "cert-sign");
|
||||||
|
addEndpointToGroup("Java", "remove-cert-sign");
|
||||||
addEndpointToGroup("Java", "multi-page-layout");
|
addEndpointToGroup("Java", "multi-page-layout");
|
||||||
addEndpointToGroup("Java", "scale-pages");
|
addEndpointToGroup("Java", "scale-pages");
|
||||||
addEndpointToGroup("Java", "add-page-numbers");
|
addEndpointToGroup("Java", "add-page-numbers");
|
||||||
|
@ -1,16 +1,18 @@
|
|||||||
package stirling.software.SPDF.config;
|
package stirling.software.SPDF.config;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.core.io.ResourceLoader;
|
import org.springframework.core.io.ResourceLoader;
|
||||||
import org.thymeleaf.IEngineConfiguration;
|
import org.thymeleaf.IEngineConfiguration;
|
||||||
import org.thymeleaf.templateresolver.AbstractConfigurableTemplateResolver;
|
import org.thymeleaf.templateresolver.AbstractConfigurableTemplateResolver;
|
||||||
import org.thymeleaf.templateresource.ClassLoaderTemplateResource;
|
|
||||||
import org.thymeleaf.templateresource.FileTemplateResource;
|
import org.thymeleaf.templateresource.FileTemplateResource;
|
||||||
import org.thymeleaf.templateresource.ITemplateResource;
|
import org.thymeleaf.templateresource.ITemplateResource;
|
||||||
|
|
||||||
|
import stirling.software.SPDF.model.InputStreamTemplateResource;
|
||||||
|
|
||||||
public class FileFallbackTemplateResolver extends AbstractConfigurableTemplateResolver {
|
public class FileFallbackTemplateResolver extends AbstractConfigurableTemplateResolver {
|
||||||
|
|
||||||
private final ResourceLoader resourceLoader;
|
private final ResourceLoader resourceLoader;
|
||||||
@ -40,9 +42,13 @@ public class FileFallbackTemplateResolver extends AbstractConfigurableTemplateRe
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ClassLoaderTemplateResource(
|
InputStream inputStream =
|
||||||
Thread.currentThread().getContextClassLoader(),
|
Thread.currentThread()
|
||||||
"classpath:/templates/" + resourceName,
|
.getContextClassLoader()
|
||||||
characterEncoding);
|
.getResourceAsStream("templates/" + resourceName);
|
||||||
|
if (inputStream != null) {
|
||||||
|
return new InputStreamTemplateResource(inputStream, "UTF-8");
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,6 @@ public class MetricsFilter extends OncePerRequestFilter {
|
|||||||
|| uri.startsWith("/v1/api-docs")
|
|| uri.startsWith("/v1/api-docs")
|
||||||
|| uri.endsWith("robots.txt")
|
|| uri.endsWith("robots.txt")
|
||||||
|| uri.startsWith("/images")
|
|| uri.startsWith("/images")
|
||||||
|| uri.startsWith("/images")
|
|
||||||
|| uri.endsWith(".png")
|
|| uri.endsWith(".png")
|
||||||
|| uri.endsWith(".ico")
|
|| uri.endsWith(".ico")
|
||||||
|| uri.endsWith(".css")
|
|| uri.endsWith(".css")
|
||||||
|
@ -18,6 +18,7 @@ class AppUpdateAuthService implements ShowAdminInterface {
|
|||||||
@Autowired private UserRepository userRepository;
|
@Autowired private UserRepository userRepository;
|
||||||
@Autowired private ApplicationProperties applicationProperties;
|
@Autowired private ApplicationProperties applicationProperties;
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean getShowUpdateOnlyAdmins() {
|
public boolean getShowUpdateOnlyAdmins() {
|
||||||
boolean showUpdate = applicationProperties.getSystem().getShowUpdate();
|
boolean showUpdate = applicationProperties.getSystem().getShowUpdate();
|
||||||
if (!showUpdate) {
|
if (!showUpdate) {
|
||||||
|
@ -49,10 +49,12 @@ public class CustomAuthenticationFailureHandler extends SimpleUrlAuthenticationF
|
|||||||
}
|
}
|
||||||
|
|
||||||
String username = request.getParameter("username");
|
String username = request.getParameter("username");
|
||||||
if (username != null && !isDemoUser(username)) {
|
Optional<User> optUser = userService.findByUsernameIgnoreCase(username);
|
||||||
|
|
||||||
|
if (username != null && optUser.isPresent() && !isDemoUser(optUser)) {
|
||||||
logger.info(
|
logger.info(
|
||||||
"Remaining attempts for user {}: {}",
|
"Remaining attempts for user {}: {}",
|
||||||
username,
|
optUser.get().getUsername(),
|
||||||
loginAttemptService.getRemainingAttempts(username));
|
loginAttemptService.getRemainingAttempts(username));
|
||||||
loginAttemptService.loginFailed(username);
|
loginAttemptService.loginFailed(username);
|
||||||
if (loginAttemptService.isBlocked(username)
|
if (loginAttemptService.isBlocked(username)
|
||||||
@ -70,8 +72,7 @@ public class CustomAuthenticationFailureHandler extends SimpleUrlAuthenticationF
|
|||||||
super.onAuthenticationFailure(request, response, exception);
|
super.onAuthenticationFailure(request, response, exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isDemoUser(String username) {
|
private boolean isDemoUser(Optional<User> user) {
|
||||||
Optional<User> user = userService.findByUsernameIgnoreCase(username);
|
|
||||||
return user.isPresent()
|
return user.isPresent()
|
||||||
&& user.get().getAuthorities().stream()
|
&& user.get().getAuthorities().stream()
|
||||||
.anyMatch(authority -> "ROLE_DEMO_USER".equals(authority.getAuthority()));
|
.anyMatch(authority -> "ROLE_DEMO_USER".equals(authority.getAuthority()));
|
||||||
|
@ -33,7 +33,6 @@ public class LoginAttemptService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void loginSucceeded(String key) {
|
public void loginSucceeded(String key) {
|
||||||
logger.info(key + " " + attemptsCache.mappingCount());
|
|
||||||
if (key == null || key.trim().isEmpty()) {
|
if (key == null || key.trim().isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -238,7 +238,7 @@ public class SecurityConfiguration {
|
|||||||
GoogleProvider google = client.getGoogle();
|
GoogleProvider google = client.getGoogle();
|
||||||
return google != null && google.isSettingsValid()
|
return google != null && google.isSettingsValid()
|
||||||
? Optional.of(
|
? Optional.of(
|
||||||
ClientRegistration.withRegistrationId("google")
|
ClientRegistration.withRegistrationId(google.getName())
|
||||||
.clientId(google.getClientId())
|
.clientId(google.getClientId())
|
||||||
.clientSecret(google.getClientSecret())
|
.clientSecret(google.getClientSecret())
|
||||||
.scope(google.getScopes())
|
.scope(google.getScopes())
|
||||||
@ -246,8 +246,8 @@ public class SecurityConfiguration {
|
|||||||
.tokenUri(google.getTokenuri())
|
.tokenUri(google.getTokenuri())
|
||||||
.userInfoUri(google.getUserinfouri())
|
.userInfoUri(google.getUserinfouri())
|
||||||
.userNameAttributeName(google.getUseAsUsername())
|
.userNameAttributeName(google.getUseAsUsername())
|
||||||
.clientName("Google")
|
.clientName(google.getClientName())
|
||||||
.redirectUri("{baseUrl}/login/oauth2/code/google")
|
.redirectUri("{baseUrl}/login/oauth2/code/" + google.getName())
|
||||||
.authorizationGrantType(
|
.authorizationGrantType(
|
||||||
org.springframework.security.oauth2.core
|
org.springframework.security.oauth2.core
|
||||||
.AuthorizationGrantType.AUTHORIZATION_CODE)
|
.AuthorizationGrantType.AUTHORIZATION_CODE)
|
||||||
@ -269,12 +269,12 @@ public class SecurityConfiguration {
|
|||||||
return keycloak != null && keycloak.isSettingsValid()
|
return keycloak != null && keycloak.isSettingsValid()
|
||||||
? Optional.of(
|
? Optional.of(
|
||||||
ClientRegistrations.fromIssuerLocation(keycloak.getIssuer())
|
ClientRegistrations.fromIssuerLocation(keycloak.getIssuer())
|
||||||
.registrationId("keycloak")
|
.registrationId(keycloak.getName())
|
||||||
.clientId(keycloak.getClientId())
|
.clientId(keycloak.getClientId())
|
||||||
.clientSecret(keycloak.getClientSecret())
|
.clientSecret(keycloak.getClientSecret())
|
||||||
.scope(keycloak.getScopes())
|
.scope(keycloak.getScopes())
|
||||||
.userNameAttributeName(keycloak.getUseAsUsername())
|
.userNameAttributeName(keycloak.getUseAsUsername())
|
||||||
.clientName("Keycloak")
|
.clientName(keycloak.getClientName())
|
||||||
.build())
|
.build())
|
||||||
: Optional.empty();
|
: Optional.empty();
|
||||||
}
|
}
|
||||||
@ -291,7 +291,7 @@ public class SecurityConfiguration {
|
|||||||
GithubProvider github = client.getGithub();
|
GithubProvider github = client.getGithub();
|
||||||
return github != null && github.isSettingsValid()
|
return github != null && github.isSettingsValid()
|
||||||
? Optional.of(
|
? Optional.of(
|
||||||
ClientRegistration.withRegistrationId("github")
|
ClientRegistration.withRegistrationId(github.getName())
|
||||||
.clientId(github.getClientId())
|
.clientId(github.getClientId())
|
||||||
.clientSecret(github.getClientSecret())
|
.clientSecret(github.getClientSecret())
|
||||||
.scope(github.getScopes())
|
.scope(github.getScopes())
|
||||||
@ -299,8 +299,8 @@ public class SecurityConfiguration {
|
|||||||
.tokenUri(github.getTokenuri())
|
.tokenUri(github.getTokenuri())
|
||||||
.userInfoUri(github.getUserinfouri())
|
.userInfoUri(github.getUserinfouri())
|
||||||
.userNameAttributeName(github.getUseAsUsername())
|
.userNameAttributeName(github.getUseAsUsername())
|
||||||
.clientName("GitHub")
|
.clientName(github.getClientName())
|
||||||
.redirectUri("{baseUrl}/login/oauth2/code/github")
|
.redirectUri("{baseUrl}/login/oauth2/code/" + github.getName())
|
||||||
.authorizationGrantType(
|
.authorizationGrantType(
|
||||||
org.springframework.security.oauth2.core
|
org.springframework.security.oauth2.core
|
||||||
.AuthorizationGrantType.AUTHORIZATION_CODE)
|
.AuthorizationGrantType.AUTHORIZATION_CODE)
|
||||||
|
@ -52,7 +52,7 @@ public class CustomOAuth2LogoutSuccessHandler extends SimpleUrlLogoutSuccessHand
|
|||||||
issuer = provider.getIssuer();
|
issuer = provider.getIssuer();
|
||||||
clientId = provider.getClientId();
|
clientId = provider.getClientId();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
logger.error("exception", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@ -60,13 +60,13 @@ public class CustomOAuth2LogoutSuccessHandler extends SimpleUrlLogoutSuccessHand
|
|||||||
issuer = oauth.getIssuer();
|
issuer = oauth.getIssuer();
|
||||||
clientId = oauth.getClientId();
|
clientId = oauth.getClientId();
|
||||||
}
|
}
|
||||||
|
String errorMessage = "";
|
||||||
if (request.getParameter("oauth2AuthenticationErrorWeb") != null) {
|
if (request.getParameter("oauth2AuthenticationErrorWeb") != null) {
|
||||||
param = "erroroauth=oauth2AuthenticationErrorWeb";
|
param = "erroroauth=oauth2AuthenticationErrorWeb";
|
||||||
} else if (request.getParameter("error") != null) {
|
} else if ((errorMessage = request.getParameter("error")) != null) {
|
||||||
param = "error=" + request.getParameter("error");
|
param = "error=" + sanitizeInput(errorMessage);
|
||||||
} else if (request.getParameter("erroroauth") != null) {
|
} else if ((errorMessage = request.getParameter("erroroauth")) != null) {
|
||||||
param = "erroroauth=" + request.getParameter("erroroauth");
|
param = "erroroauth=" + sanitizeInput(errorMessage);
|
||||||
} else if (request.getParameter("oauth2AutoCreateDisabled") != null) {
|
} else if (request.getParameter("oauth2AutoCreateDisabled") != null) {
|
||||||
param = "error=oauth2AutoCreateDisabled";
|
param = "error=oauth2AutoCreateDisabled";
|
||||||
}
|
}
|
||||||
@ -81,7 +81,7 @@ public class CustomOAuth2LogoutSuccessHandler extends SimpleUrlLogoutSuccessHand
|
|||||||
logger.info("Session invalidated: " + sessionId);
|
logger.info("Session invalidated: " + sessionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (registrationId) {
|
switch (registrationId.toLowerCase()) {
|
||||||
case "keycloak":
|
case "keycloak":
|
||||||
// Add Keycloak specific logout URL if needed
|
// Add Keycloak specific logout URL if needed
|
||||||
String logoutUrl =
|
String logoutUrl =
|
||||||
@ -115,4 +115,8 @@ public class CustomOAuth2LogoutSuccessHandler extends SimpleUrlLogoutSuccessHand
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String sanitizeInput(String input) {
|
||||||
|
return input.replaceAll("[^a-zA-Z0-9 ]", "");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,8 @@ import org.springframework.security.oauth2.core.oidc.user.OidcUser;
|
|||||||
import stirling.software.SPDF.config.security.LoginAttemptService;
|
import stirling.software.SPDF.config.security.LoginAttemptService;
|
||||||
import stirling.software.SPDF.config.security.UserService;
|
import stirling.software.SPDF.config.security.UserService;
|
||||||
import stirling.software.SPDF.model.ApplicationProperties;
|
import stirling.software.SPDF.model.ApplicationProperties;
|
||||||
|
import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2;
|
||||||
|
import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2.Client;
|
||||||
import stirling.software.SPDF.model.User;
|
import stirling.software.SPDF.model.User;
|
||||||
|
|
||||||
public class CustomOAuth2UserService implements OAuth2UserService<OidcUserRequest, OidcUser> {
|
public class CustomOAuth2UserService implements OAuth2UserService<OidcUserRequest, OidcUser> {
|
||||||
@ -41,11 +43,27 @@ public class CustomOAuth2UserService implements OAuth2UserService<OidcUserReques
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OidcUser loadUser(OidcUserRequest userRequest) throws OAuth2AuthenticationException {
|
public OidcUser loadUser(OidcUserRequest userRequest) throws OAuth2AuthenticationException {
|
||||||
String usernameAttribute =
|
OAUTH2 oauth2 = applicationProperties.getSecurity().getOAUTH2();
|
||||||
applicationProperties.getSecurity().getOAUTH2().getUseAsUsername();
|
String usernameAttribute = oauth2.getUseAsUsername();
|
||||||
|
if (usernameAttribute == null || usernameAttribute.trim().isEmpty()) {
|
||||||
|
Client client = oauth2.getClient();
|
||||||
|
if (client != null && client.getKeycloak() != null) {
|
||||||
|
usernameAttribute = client.getKeycloak().getUseAsUsername();
|
||||||
|
} else {
|
||||||
|
usernameAttribute = "email";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
OidcUser user = delegate.loadUser(userRequest);
|
OidcUser user = delegate.loadUser(userRequest);
|
||||||
String username = user.getUserInfo().getClaimAsString(usernameAttribute);
|
String username = user.getUserInfo().getClaimAsString(usernameAttribute);
|
||||||
|
|
||||||
|
// Check if the username claim is null or empty
|
||||||
|
if (username == null || username.trim().isEmpty()) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Claim '" + usernameAttribute + "' cannot be null or empty");
|
||||||
|
}
|
||||||
|
|
||||||
Optional<User> duser = userService.findByUsernameIgnoreCase(username);
|
Optional<User> duser = userService.findByUsernameIgnoreCase(username);
|
||||||
if (duser.isPresent()) {
|
if (duser.isPresent()) {
|
||||||
if (loginAttemptService.isBlocked(username)) {
|
if (loginAttemptService.isBlocked(username)) {
|
||||||
@ -56,13 +74,14 @@ public class CustomOAuth2UserService implements OAuth2UserService<OidcUserReques
|
|||||||
throw new IllegalArgumentException("Password must not be null");
|
throw new IllegalArgumentException("Password must not be null");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return a new OidcUser with adjusted attributes
|
// Return a new OidcUser with adjusted attributes
|
||||||
return new DefaultOidcUser(
|
return new DefaultOidcUser(
|
||||||
user.getAuthorities(),
|
user.getAuthorities(),
|
||||||
userRequest.getIdToken(),
|
userRequest.getIdToken(),
|
||||||
user.getUserInfo(),
|
user.getUserInfo(),
|
||||||
usernameAttribute);
|
usernameAttribute);
|
||||||
} catch (java.lang.IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
logger.error("Error loading OIDC user: {}", e.getMessage());
|
logger.error("Error loading OIDC user: {}", e.getMessage());
|
||||||
throw new OAuth2AuthenticationException(new OAuth2Error(e.getMessage()), e);
|
throw new OAuth2AuthenticationException(new OAuth2Error(e.getMessage()), e);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -18,6 +18,8 @@ import org.apache.pdfbox.pdmodel.PDPageContentStream.AppendMode;
|
|||||||
import org.apache.pdfbox.pdmodel.common.PDRectangle;
|
import org.apache.pdfbox.pdmodel.common.PDRectangle;
|
||||||
import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject;
|
import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject;
|
||||||
import org.apache.pdfbox.util.Matrix;
|
import org.apache.pdfbox.util.Matrix;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||||
@ -38,6 +40,9 @@ import stirling.software.SPDF.utils.WebResponseUtils;
|
|||||||
@Tag(name = "General", description = "General APIs")
|
@Tag(name = "General", description = "General APIs")
|
||||||
public class SplitPdfBySectionsController {
|
public class SplitPdfBySectionsController {
|
||||||
|
|
||||||
|
private static final Logger logger =
|
||||||
|
LoggerFactory.getLogger(SplitPdfBySectionsController.class);
|
||||||
|
|
||||||
@PostMapping(value = "/split-pdf-by-sections", consumes = "multipart/form-data")
|
@PostMapping(value = "/split-pdf-by-sections", consumes = "multipart/form-data")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Split PDF pages into smaller sections",
|
summary = "Split PDF pages into smaller sections",
|
||||||
@ -92,7 +97,7 @@ public class SplitPdfBySectionsController {
|
|||||||
if (sectionNum == horiz * verti) pageNum++;
|
if (sectionNum == horiz * verti) pageNum++;
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
logger.error("exception", e);
|
||||||
} finally {
|
} finally {
|
||||||
data = Files.readAllBytes(zipFile);
|
data = Files.readAllBytes(zipFile);
|
||||||
Files.deleteIfExists(zipFile);
|
Files.deleteIfExists(zipFile);
|
||||||
|
@ -10,6 +10,8 @@ import java.util.zip.ZipOutputStream;
|
|||||||
import org.apache.pdfbox.Loader;
|
import org.apache.pdfbox.Loader;
|
||||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||||
import org.apache.pdfbox.pdmodel.PDPage;
|
import org.apache.pdfbox.pdmodel.PDPage;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||||
@ -31,6 +33,8 @@ import stirling.software.SPDF.utils.WebResponseUtils;
|
|||||||
@Tag(name = "General", description = "General APIs")
|
@Tag(name = "General", description = "General APIs")
|
||||||
public class SplitPdfBySizeController {
|
public class SplitPdfBySizeController {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(SplitPdfBySizeController.class);
|
||||||
|
|
||||||
@PostMapping(value = "/split-by-size-or-count", consumes = "multipart/form-data")
|
@PostMapping(value = "/split-by-size-or-count", consumes = "multipart/form-data")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Auto split PDF pages into separate documents based on size or count",
|
summary = "Auto split PDF pages into separate documents based on size or count",
|
||||||
@ -66,7 +70,7 @@ public class SplitPdfBySizeController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
logger.error("exception", e);
|
||||||
} finally {
|
} finally {
|
||||||
data = Files.readAllBytes(zipFile);
|
data = Files.readAllBytes(zipFile);
|
||||||
Files.deleteIfExists(zipFile);
|
Files.deleteIfExists(zipFile);
|
||||||
|
@ -66,46 +66,46 @@ public class UserController {
|
|||||||
RedirectAttributes redirectAttributes) {
|
RedirectAttributes redirectAttributes) {
|
||||||
|
|
||||||
if (!userService.isUsernameValid(newUsername)) {
|
if (!userService.isUsernameValid(newUsername)) {
|
||||||
return new RedirectView("/account?messageType=invalidUsername");
|
return new RedirectView("/account?messageType=invalidUsername", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (principal == null) {
|
if (principal == null) {
|
||||||
return new RedirectView("/account?messageType=notAuthenticated");
|
return new RedirectView("/account?messageType=notAuthenticated", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The username MUST be unique when renaming
|
// The username MUST be unique when renaming
|
||||||
Optional<User> userOpt = userService.findByUsername(principal.getName());
|
Optional<User> userOpt = userService.findByUsername(principal.getName());
|
||||||
|
|
||||||
if (userOpt == null || userOpt.isEmpty()) {
|
if (userOpt == null || userOpt.isEmpty()) {
|
||||||
return new RedirectView("/account?messageType=userNotFound");
|
return new RedirectView("/account?messageType=userNotFound", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
User user = userOpt.get();
|
User user = userOpt.get();
|
||||||
|
|
||||||
if (user.getUsername().equals(newUsername)) {
|
if (user.getUsername().equals(newUsername)) {
|
||||||
return new RedirectView("/account?messageType=usernameExists");
|
return new RedirectView("/account?messageType=usernameExists", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!userService.isPasswordCorrect(user, currentPassword)) {
|
if (!userService.isPasswordCorrect(user, currentPassword)) {
|
||||||
return new RedirectView("/account?messageType=incorrectPassword");
|
return new RedirectView("/account?messageType=incorrectPassword", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!user.getUsername().equals(newUsername) && userService.usernameExists(newUsername)) {
|
if (!user.getUsername().equals(newUsername) && userService.usernameExists(newUsername)) {
|
||||||
return new RedirectView("/account?messageType=usernameExists");
|
return new RedirectView("/account?messageType=usernameExists", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newUsername != null && newUsername.length() > 0) {
|
if (newUsername != null && newUsername.length() > 0) {
|
||||||
try {
|
try {
|
||||||
userService.changeUsername(user, newUsername);
|
userService.changeUsername(user, newUsername);
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
return new RedirectView("/account?messageType=invalidUsername");
|
return new RedirectView("/account?messageType=invalidUsername", true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Logout using Spring's utility
|
// Logout using Spring's utility
|
||||||
new SecurityContextLogoutHandler().logout(request, response, null);
|
new SecurityContextLogoutHandler().logout(request, response, null);
|
||||||
|
|
||||||
return new RedirectView(LOGIN_MESSAGETYPE_CREDSUPDATED);
|
return new RedirectView(LOGIN_MESSAGETYPE_CREDSUPDATED, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PreAuthorize("!hasAuthority('ROLE_DEMO_USER')")
|
@PreAuthorize("!hasAuthority('ROLE_DEMO_USER')")
|
||||||
@ -118,19 +118,19 @@ public class UserController {
|
|||||||
HttpServletResponse response,
|
HttpServletResponse response,
|
||||||
RedirectAttributes redirectAttributes) {
|
RedirectAttributes redirectAttributes) {
|
||||||
if (principal == null) {
|
if (principal == null) {
|
||||||
return new RedirectView("/change-creds?messageType=notAuthenticated");
|
return new RedirectView("/change-creds?messageType=notAuthenticated", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<User> userOpt = userService.findByUsernameIgnoreCase(principal.getName());
|
Optional<User> userOpt = userService.findByUsernameIgnoreCase(principal.getName());
|
||||||
|
|
||||||
if (userOpt == null || userOpt.isEmpty()) {
|
if (userOpt == null || userOpt.isEmpty()) {
|
||||||
return new RedirectView("/change-creds?messageType=userNotFound");
|
return new RedirectView("/change-creds?messageType=userNotFound", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
User user = userOpt.get();
|
User user = userOpt.get();
|
||||||
|
|
||||||
if (!userService.isPasswordCorrect(user, currentPassword)) {
|
if (!userService.isPasswordCorrect(user, currentPassword)) {
|
||||||
return new RedirectView("/change-creds?messageType=incorrectPassword");
|
return new RedirectView("/change-creds?messageType=incorrectPassword", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
userService.changePassword(user, newPassword);
|
userService.changePassword(user, newPassword);
|
||||||
@ -138,7 +138,7 @@ public class UserController {
|
|||||||
// Logout using Spring's utility
|
// Logout using Spring's utility
|
||||||
new SecurityContextLogoutHandler().logout(request, response, null);
|
new SecurityContextLogoutHandler().logout(request, response, null);
|
||||||
|
|
||||||
return new RedirectView(LOGIN_MESSAGETYPE_CREDSUPDATED);
|
return new RedirectView(LOGIN_MESSAGETYPE_CREDSUPDATED, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PreAuthorize("!hasAuthority('ROLE_DEMO_USER')")
|
@PreAuthorize("!hasAuthority('ROLE_DEMO_USER')")
|
||||||
@ -151,19 +151,19 @@ public class UserController {
|
|||||||
HttpServletResponse response,
|
HttpServletResponse response,
|
||||||
RedirectAttributes redirectAttributes) {
|
RedirectAttributes redirectAttributes) {
|
||||||
if (principal == null) {
|
if (principal == null) {
|
||||||
return new RedirectView("/account?messageType=notAuthenticated");
|
return new RedirectView("/account?messageType=notAuthenticated", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<User> userOpt = userService.findByUsernameIgnoreCase(principal.getName());
|
Optional<User> userOpt = userService.findByUsernameIgnoreCase(principal.getName());
|
||||||
|
|
||||||
if (userOpt == null || userOpt.isEmpty()) {
|
if (userOpt == null || userOpt.isEmpty()) {
|
||||||
return new RedirectView("/account?messageType=userNotFound");
|
return new RedirectView("/account?messageType=userNotFound", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
User user = userOpt.get();
|
User user = userOpt.get();
|
||||||
|
|
||||||
if (!userService.isPasswordCorrect(user, currentPassword)) {
|
if (!userService.isPasswordCorrect(user, currentPassword)) {
|
||||||
return new RedirectView("/account?messageType=incorrectPassword");
|
return new RedirectView("/account?messageType=incorrectPassword", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
userService.changePassword(user, newPassword);
|
userService.changePassword(user, newPassword);
|
||||||
@ -171,7 +171,7 @@ public class UserController {
|
|||||||
// Logout using Spring's utility
|
// Logout using Spring's utility
|
||||||
new SecurityContextLogoutHandler().logout(request, response, null);
|
new SecurityContextLogoutHandler().logout(request, response, null);
|
||||||
|
|
||||||
return new RedirectView(LOGIN_MESSAGETYPE_CREDSUPDATED);
|
return new RedirectView(LOGIN_MESSAGETYPE_CREDSUPDATED, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PreAuthorize("!hasAuthority('ROLE_DEMO_USER')")
|
@PreAuthorize("!hasAuthority('ROLE_DEMO_USER')")
|
||||||
@ -204,7 +204,7 @@ public class UserController {
|
|||||||
boolean forceChange) {
|
boolean forceChange) {
|
||||||
|
|
||||||
if (!userService.isUsernameValid(username)) {
|
if (!userService.isUsernameValid(username)) {
|
||||||
return new RedirectView("/addUsers?messageType=invalidUsername");
|
return new RedirectView("/addUsers?messageType=invalidUsername", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<User> userOpt = userService.findByUsernameIgnoreCase(username);
|
Optional<User> userOpt = userService.findByUsernameIgnoreCase(username);
|
||||||
@ -212,26 +212,27 @@ public class UserController {
|
|||||||
if (userOpt.isPresent()) {
|
if (userOpt.isPresent()) {
|
||||||
User user = userOpt.get();
|
User user = userOpt.get();
|
||||||
if (user != null && user.getUsername().equalsIgnoreCase(username)) {
|
if (user != null && user.getUsername().equalsIgnoreCase(username)) {
|
||||||
return new RedirectView("/addUsers?messageType=usernameExists");
|
return new RedirectView("/addUsers?messageType=usernameExists", true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (userService.usernameExistsIgnoreCase(username)) {
|
if (userService.usernameExistsIgnoreCase(username)) {
|
||||||
return new RedirectView("/addUsers?messageType=usernameExists");
|
return new RedirectView("/addUsers?messageType=usernameExists", true);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
// Validate the role
|
// Validate the role
|
||||||
Role roleEnum = Role.fromString(role);
|
Role roleEnum = Role.fromString(role);
|
||||||
if (roleEnum == Role.INTERNAL_API_USER) {
|
if (roleEnum == Role.INTERNAL_API_USER) {
|
||||||
// If the role is INTERNAL_API_USER, reject the request
|
// If the role is INTERNAL_API_USER, reject the request
|
||||||
return new RedirectView("/addUsers?messageType=invalidRole");
|
return new RedirectView("/addUsers?messageType=invalidRole", true);
|
||||||
}
|
}
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
// If the role ID is not valid, redirect with an error message
|
// If the role ID is not valid, redirect with an error message
|
||||||
return new RedirectView("/addUsers?messageType=invalidRole");
|
return new RedirectView("/addUsers?messageType=invalidRole", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
userService.saveUser(username, password, role, forceChange);
|
userService.saveUser(username, password, role, forceChange);
|
||||||
return new RedirectView("/addUsers"); // Redirect to account page after adding the user
|
return new RedirectView(
|
||||||
|
"/addUsers", true); // Redirect to account page after adding the user
|
||||||
}
|
}
|
||||||
|
|
||||||
@PreAuthorize("hasRole('ROLE_ADMIN')")
|
@PreAuthorize("hasRole('ROLE_ADMIN')")
|
||||||
@ -244,33 +245,34 @@ public class UserController {
|
|||||||
Optional<User> userOpt = userService.findByUsernameIgnoreCase(username);
|
Optional<User> userOpt = userService.findByUsernameIgnoreCase(username);
|
||||||
|
|
||||||
if (!userOpt.isPresent()) {
|
if (!userOpt.isPresent()) {
|
||||||
return new RedirectView("/addUsers?messageType=userNotFound");
|
return new RedirectView("/addUsers?messageType=userNotFound", true);
|
||||||
}
|
}
|
||||||
if (!userService.usernameExistsIgnoreCase(username)) {
|
if (!userService.usernameExistsIgnoreCase(username)) {
|
||||||
return new RedirectView("/addUsers?messageType=userNotFound");
|
return new RedirectView("/addUsers?messageType=userNotFound", true);
|
||||||
}
|
}
|
||||||
// Get the currently authenticated username
|
// Get the currently authenticated username
|
||||||
String currentUsername = authentication.getName();
|
String currentUsername = authentication.getName();
|
||||||
|
|
||||||
// Check if the provided username matches the current session's username
|
// Check if the provided username matches the current session's username
|
||||||
if (currentUsername.equalsIgnoreCase(username)) {
|
if (currentUsername.equalsIgnoreCase(username)) {
|
||||||
return new RedirectView("/addUsers?messageType=downgradeCurrentUser");
|
return new RedirectView("/addUsers?messageType=downgradeCurrentUser", true);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
// Validate the role
|
// Validate the role
|
||||||
Role roleEnum = Role.fromString(role);
|
Role roleEnum = Role.fromString(role);
|
||||||
if (roleEnum == Role.INTERNAL_API_USER) {
|
if (roleEnum == Role.INTERNAL_API_USER) {
|
||||||
// If the role is INTERNAL_API_USER, reject the request
|
// If the role is INTERNAL_API_USER, reject the request
|
||||||
return new RedirectView("/addUsers?messageType=invalidRole");
|
return new RedirectView("/addUsers?messageType=invalidRole", true);
|
||||||
}
|
}
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
// If the role ID is not valid, redirect with an error message
|
// If the role ID is not valid, redirect with an error message
|
||||||
return new RedirectView("/addUsers?messageType=invalidRole");
|
return new RedirectView("/addUsers?messageType=invalidRole", true);
|
||||||
}
|
}
|
||||||
User user = userOpt.get();
|
User user = userOpt.get();
|
||||||
|
|
||||||
userService.changeRole(user, role);
|
userService.changeRole(user, role);
|
||||||
return new RedirectView("/addUsers"); // Redirect to account page after adding the user
|
return new RedirectView(
|
||||||
|
"/addUsers", true); // Redirect to account page after adding the user
|
||||||
}
|
}
|
||||||
|
|
||||||
@PreAuthorize("hasRole('ROLE_ADMIN')")
|
@PreAuthorize("hasRole('ROLE_ADMIN')")
|
||||||
@ -279,7 +281,7 @@ public class UserController {
|
|||||||
@PathVariable(name = "username") String username, Authentication authentication) {
|
@PathVariable(name = "username") String username, Authentication authentication) {
|
||||||
|
|
||||||
if (!userService.usernameExistsIgnoreCase(username)) {
|
if (!userService.usernameExistsIgnoreCase(username)) {
|
||||||
return new RedirectView("/addUsers?messageType=deleteUsernameExists");
|
return new RedirectView("/addUsers?messageType=deleteUsernameExists", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the currently authenticated username
|
// Get the currently authenticated username
|
||||||
@ -287,11 +289,11 @@ public class UserController {
|
|||||||
|
|
||||||
// Check if the provided username matches the current session's username
|
// Check if the provided username matches the current session's username
|
||||||
if (currentUsername.equalsIgnoreCase(username)) {
|
if (currentUsername.equalsIgnoreCase(username)) {
|
||||||
return new RedirectView("/addUsers?messageType=deleteCurrentUser");
|
return new RedirectView("/addUsers?messageType=deleteCurrentUser", true);
|
||||||
}
|
}
|
||||||
invalidateUserSessions(username);
|
invalidateUserSessions(username);
|
||||||
userService.deleteUser(username);
|
userService.deleteUser(username);
|
||||||
return new RedirectView("/addUsers");
|
return new RedirectView("/addUsers", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Autowired private SessionRegistry sessionRegistry;
|
@Autowired private SessionRegistry sessionRegistry;
|
||||||
|
@ -1,10 +1,22 @@
|
|||||||
package stirling.software.SPDF.controller.api.converters;
|
package stirling.software.SPDF.controller.api.converters;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.apache.pdfbox.Loader;
|
||||||
|
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||||
|
import org.apache.pdfbox.pdmodel.PDDocumentCatalog;
|
||||||
|
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
|
||||||
|
import org.apache.pdfbox.pdmodel.interactive.form.PDField;
|
||||||
|
import org.apache.pdfbox.pdmodel.interactive.form.PDSignatureField;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
@ -26,6 +38,8 @@ import stirling.software.SPDF.utils.WebResponseUtils;
|
|||||||
@Tag(name = "Convert", description = "Convert APIs")
|
@Tag(name = "Convert", description = "Convert APIs")
|
||||||
public class ConvertPDFToPDFA {
|
public class ConvertPDFToPDFA {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(ConvertPDFToPDFA.class);
|
||||||
|
|
||||||
@PostMapping(consumes = "multipart/form-data", value = "/pdf/pdfa")
|
@PostMapping(consumes = "multipart/form-data", value = "/pdf/pdfa")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Convert a PDF to a PDF/A",
|
summary = "Convert a PDF to a PDF/A",
|
||||||
@ -36,9 +50,39 @@ public class ConvertPDFToPDFA {
|
|||||||
MultipartFile inputFile = request.getFileInput();
|
MultipartFile inputFile = request.getFileInput();
|
||||||
String outputFormat = request.getOutputFormat();
|
String outputFormat = request.getOutputFormat();
|
||||||
|
|
||||||
// Save the uploaded file to a temporary location
|
// Convert MultipartFile to byte[]
|
||||||
|
byte[] pdfBytes = inputFile.getBytes();
|
||||||
|
|
||||||
|
// Load the PDF document
|
||||||
|
PDDocument document = Loader.loadPDF(pdfBytes);
|
||||||
|
|
||||||
|
// Get the document catalog
|
||||||
|
PDDocumentCatalog catalog = document.getDocumentCatalog();
|
||||||
|
|
||||||
|
// Get the AcroForm
|
||||||
|
PDAcroForm acroForm = catalog.getAcroForm();
|
||||||
|
if (acroForm != null) {
|
||||||
|
// Remove signature fields safely
|
||||||
|
List<PDField> fieldsToRemove =
|
||||||
|
acroForm.getFields().stream()
|
||||||
|
.filter(field -> field instanceof PDSignatureField)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
if (!fieldsToRemove.isEmpty()) {
|
||||||
|
acroForm.flatten(fieldsToRemove, false);
|
||||||
|
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
document.save(baos);
|
||||||
|
pdfBytes = baos.toByteArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
document.close();
|
||||||
|
|
||||||
|
// Save the uploaded (and possibly modified) file to a temporary location
|
||||||
Path tempInputFile = Files.createTempFile("input_", ".pdf");
|
Path tempInputFile = Files.createTempFile("input_", ".pdf");
|
||||||
inputFile.transferTo(tempInputFile.toFile());
|
try (OutputStream outputStream = new FileOutputStream(tempInputFile.toFile())) {
|
||||||
|
outputStream.write(pdfBytes);
|
||||||
|
}
|
||||||
|
|
||||||
// Prepare the output file path
|
// Prepare the output file path
|
||||||
Path tempOutputFile = Files.createTempFile("output_", ".pdf");
|
Path tempOutputFile = Files.createTempFile("output_", ".pdf");
|
||||||
@ -58,7 +102,7 @@ public class ConvertPDFToPDFA {
|
|||||||
.runCommandWithOutputHandling(command);
|
.runCommandWithOutputHandling(command);
|
||||||
|
|
||||||
// Read the optimized PDF file
|
// Read the optimized PDF file
|
||||||
byte[] pdfBytes = Files.readAllBytes(tempOutputFile);
|
byte[] optimizedPdfBytes = Files.readAllBytes(tempOutputFile);
|
||||||
|
|
||||||
// Clean up the temporary files
|
// Clean up the temporary files
|
||||||
Files.deleteIfExists(tempInputFile);
|
Files.deleteIfExists(tempInputFile);
|
||||||
@ -69,6 +113,6 @@ public class ConvertPDFToPDFA {
|
|||||||
Filenames.toSimpleFileName(inputFile.getOriginalFilename())
|
Filenames.toSimpleFileName(inputFile.getOriginalFilename())
|
||||||
.replaceFirst("[.][^.]+$", "")
|
.replaceFirst("[.][^.]+$", "")
|
||||||
+ "_PDFA.pdf";
|
+ "_PDFA.pdf";
|
||||||
return WebResponseUtils.bytesToWebResponse(pdfBytes, outputFilename);
|
return WebResponseUtils.bytesToWebResponse(optimizedPdfBytes, outputFilename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,8 @@ import java.util.zip.ZipOutputStream;
|
|||||||
import org.apache.pdfbox.Loader;
|
import org.apache.pdfbox.Loader;
|
||||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||||
import org.apache.pdfbox.rendering.PDFRenderer;
|
import org.apache.pdfbox.rendering.PDFRenderer;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||||
@ -43,6 +45,7 @@ import stirling.software.SPDF.utils.WebResponseUtils;
|
|||||||
@Tag(name = "Misc", description = "Miscellaneous APIs")
|
@Tag(name = "Misc", description = "Miscellaneous APIs")
|
||||||
public class AutoSplitPdfController {
|
public class AutoSplitPdfController {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(AutoSplitPdfController.class);
|
||||||
private static final String QR_CONTENT = "https://github.com/Stirling-Tools/Stirling-PDF";
|
private static final String QR_CONTENT = "https://github.com/Stirling-Tools/Stirling-PDF";
|
||||||
private static final String QR_CONTENT_OLD = "https://github.com/Frooodle/Stirling-PDF";
|
private static final String QR_CONTENT_OLD = "https://github.com/Frooodle/Stirling-PDF";
|
||||||
|
|
||||||
@ -115,7 +118,7 @@ public class AutoSplitPdfController {
|
|||||||
zipOut.closeEntry();
|
zipOut.closeEntry();
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
logger.error("exception", e);
|
||||||
} finally {
|
} finally {
|
||||||
data = Files.readAllBytes(zipFile);
|
data = Files.readAllBytes(zipFile);
|
||||||
Files.deleteIfExists(zipFile);
|
Files.deleteIfExists(zipFile);
|
||||||
|
@ -106,7 +106,7 @@ public class BlankPageController {
|
|||||||
.replaceFirst("[.][^.]+$", "")
|
.replaceFirst("[.][^.]+$", "")
|
||||||
+ "_blanksRemoved.pdf");
|
+ "_blanksRemoved.pdf");
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
logger.error("exception", e);
|
||||||
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
|
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||||
} finally {
|
} finally {
|
||||||
if (document != null) document.close();
|
if (document != null) document.close();
|
||||||
|
@ -110,8 +110,8 @@ public class FakeScanControllerWIP {
|
|||||||
private BufferedImage rotate(BufferedImage image, double rotation) {
|
private BufferedImage rotate(BufferedImage image, double rotation) {
|
||||||
|
|
||||||
double rotationRequired = Math.toRadians(rotation);
|
double rotationRequired = Math.toRadians(rotation);
|
||||||
double locationX = image.getWidth() / 2;
|
double locationX = (double) image.getWidth() / 2;
|
||||||
double locationY = image.getHeight() / 2;
|
double locationY = (double) image.getHeight() / 2;
|
||||||
AffineTransform tx =
|
AffineTransform tx =
|
||||||
AffineTransform.getRotateInstance(rotationRequired, locationX, locationY);
|
AffineTransform.getRotateInstance(rotationRequired, locationX, locationY);
|
||||||
AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BICUBIC);
|
AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BICUBIC);
|
||||||
@ -127,8 +127,8 @@ public class FakeScanControllerWIP {
|
|||||||
|
|
||||||
for (int i = -radius; i <= radius; i++) {
|
for (int i = -radius; i <= radius; i++) {
|
||||||
for (int j = -radius; j <= radius; j++) {
|
for (int j = -radius; j <= radius; j++) {
|
||||||
double xDistance = i * i;
|
double xDistance = (double) i * i;
|
||||||
double yDistance = j * j;
|
double yDistance = (double) j * j;
|
||||||
double g = Math.exp(-(xDistance + yDistance) / (2 * sigma * sigma));
|
double g = Math.exp(-(xDistance + yDistance) / (2 * sigma * sigma));
|
||||||
data[(i + radius) * size + j + radius] = (float) g;
|
data[(i + radius) * size + j + radius] = (float) g;
|
||||||
sum += g;
|
sum += g;
|
||||||
@ -137,7 +137,7 @@ public class FakeScanControllerWIP {
|
|||||||
|
|
||||||
// Normalize the kernel
|
// Normalize the kernel
|
||||||
for (int i = 0; i < data.length; i++) {
|
for (int i = 0; i < data.length; i++) {
|
||||||
data[i] /= sum;
|
if (sum != 0) data[i] /= sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
Kernel kernel = new Kernel(size, size, data);
|
Kernel kernel = new Kernel(size, size, data);
|
||||||
@ -166,7 +166,7 @@ public class FakeScanControllerWIP {
|
|||||||
0,
|
0,
|
||||||
new Color(0, 0, 0, 1f),
|
new Color(0, 0, 0, 1f),
|
||||||
0,
|
0,
|
||||||
featherRadius * 2,
|
featherRadius * 2f,
|
||||||
new Color(0, 0, 0, 0f)));
|
new Color(0, 0, 0, 0f)));
|
||||||
g2.fillRect(0, 0, width, featherRadius);
|
g2.fillRect(0, 0, width, featherRadius);
|
||||||
|
|
||||||
@ -174,7 +174,7 @@ public class FakeScanControllerWIP {
|
|||||||
g2.setPaint(
|
g2.setPaint(
|
||||||
new GradientPaint(
|
new GradientPaint(
|
||||||
0,
|
0,
|
||||||
height - featherRadius * 2,
|
height - featherRadius * 2f,
|
||||||
new Color(0, 0, 0, 0f),
|
new Color(0, 0, 0, 0f),
|
||||||
0,
|
0,
|
||||||
height,
|
height,
|
||||||
@ -187,7 +187,7 @@ public class FakeScanControllerWIP {
|
|||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
new Color(0, 0, 0, 1f),
|
new Color(0, 0, 0, 1f),
|
||||||
featherRadius * 2,
|
featherRadius * 2f,
|
||||||
0,
|
0,
|
||||||
new Color(0, 0, 0, 0f)));
|
new Color(0, 0, 0, 0f)));
|
||||||
g2.fillRect(0, 0, featherRadius, height);
|
g2.fillRect(0, 0, featherRadius, height);
|
||||||
@ -195,7 +195,7 @@ public class FakeScanControllerWIP {
|
|||||||
// Right edge
|
// Right edge
|
||||||
g2.setPaint(
|
g2.setPaint(
|
||||||
new GradientPaint(
|
new GradientPaint(
|
||||||
width - featherRadius * 2,
|
width - featherRadius * 2f,
|
||||||
0,
|
0,
|
||||||
new Color(0, 0, 0, 0f),
|
new Color(0, 0, 0, 0f),
|
||||||
width,
|
width,
|
||||||
@ -244,7 +244,7 @@ public class FakeScanControllerWIP {
|
|||||||
int y2 = y1 + random.nextInt(20) - 10;
|
int y2 = y1 + random.nextInt(20) - 10;
|
||||||
Path2D.Double hair = new Path2D.Double();
|
Path2D.Double hair = new Path2D.Double();
|
||||||
hair.moveTo(x1, y1);
|
hair.moveTo(x1, y1);
|
||||||
hair.curveTo(x1, y1, (x1 + x2) / 2, (y1 + y2) / 2, x2, y2);
|
hair.curveTo(x1, y1, (double) (x1 + x2) / 2, (double) (y1 + y2) / 2, x2, y2);
|
||||||
g2d.draw(hair);
|
g2d.draw(hair);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,6 +12,8 @@ import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
|
|||||||
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
|
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
|
||||||
import org.apache.pdfbox.rendering.ImageType;
|
import org.apache.pdfbox.rendering.ImageType;
|
||||||
import org.apache.pdfbox.rendering.PDFRenderer;
|
import org.apache.pdfbox.rendering.PDFRenderer;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
@ -33,6 +35,8 @@ import stirling.software.SPDF.utils.WebResponseUtils;
|
|||||||
@Tag(name = "Misc", description = "Miscellaneous APIs")
|
@Tag(name = "Misc", description = "Miscellaneous APIs")
|
||||||
public class FlattenController {
|
public class FlattenController {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(FlattenController.class);
|
||||||
|
|
||||||
@PostMapping(consumes = "multipart/form-data", value = "/flatten")
|
@PostMapping(consumes = "multipart/form-data", value = "/flatten")
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Flatten PDF form fields or full page",
|
summary = "Flatten PDF form fields or full page",
|
||||||
@ -73,7 +77,7 @@ public class FlattenController {
|
|||||||
contentStream.drawImage(pdImage, 0, 0, pageWidth, pageHeight);
|
contentStream.drawImage(pdImage, 0, 0, pageWidth, pageHeight);
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
logger.error("exception", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PdfUtils.setMetadataToPdf(newDocument, metadata);
|
PdfUtils.setMetadataToPdf(newDocument, metadata);
|
||||||
|
@ -11,6 +11,8 @@ import org.apache.pdfbox.Loader;
|
|||||||
import org.apache.pdfbox.cos.COSName;
|
import org.apache.pdfbox.cos.COSName;
|
||||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||||
import org.apache.pdfbox.pdmodel.PDDocumentInformation;
|
import org.apache.pdfbox.pdmodel.PDDocumentInformation;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
@ -30,6 +32,8 @@ import stirling.software.SPDF.utils.WebResponseUtils;
|
|||||||
@Tag(name = "Misc", description = "Miscellaneous APIs")
|
@Tag(name = "Misc", description = "Miscellaneous APIs")
|
||||||
public class MetadataController {
|
public class MetadataController {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(MetadataController.class);
|
||||||
|
|
||||||
private String checkUndefined(String entry) {
|
private String checkUndefined(String entry) {
|
||||||
// Check if the string is "undefined"
|
// Check if the string is "undefined"
|
||||||
if ("undefined".equals(entry)) {
|
if ("undefined".equals(entry)) {
|
||||||
@ -136,7 +140,7 @@ public class MetadataController {
|
|||||||
creationDateCal.setTime(
|
creationDateCal.setTime(
|
||||||
new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse(creationDate));
|
new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse(creationDate));
|
||||||
} catch (ParseException e) {
|
} catch (ParseException e) {
|
||||||
e.printStackTrace();
|
logger.error("exception", e);
|
||||||
}
|
}
|
||||||
info.setCreationDate(creationDateCal);
|
info.setCreationDate(creationDateCal);
|
||||||
} else {
|
} else {
|
||||||
@ -148,7 +152,7 @@ public class MetadataController {
|
|||||||
modificationDateCal.setTime(
|
modificationDateCal.setTime(
|
||||||
new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse(modificationDate));
|
new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse(modificationDate));
|
||||||
} catch (ParseException e) {
|
} catch (ParseException e) {
|
||||||
e.printStackTrace();
|
logger.error("exception", e);
|
||||||
}
|
}
|
||||||
info.setModificationDate(modificationDateCal);
|
info.setModificationDate(modificationDateCal);
|
||||||
} else {
|
} else {
|
||||||
|
@ -19,6 +19,7 @@ import java.util.stream.Stream;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
import org.springframework.core.io.ByteArrayResource;
|
import org.springframework.core.io.ByteArrayResource;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.scheduling.annotation.Scheduled;
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
@ -28,6 +29,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
|||||||
|
|
||||||
import stirling.software.SPDF.model.PipelineConfig;
|
import stirling.software.SPDF.model.PipelineConfig;
|
||||||
import stirling.software.SPDF.model.PipelineOperation;
|
import stirling.software.SPDF.model.PipelineOperation;
|
||||||
|
import stirling.software.SPDF.utils.FileMonitor;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class PipelineDirectoryProcessor {
|
public class PipelineDirectoryProcessor {
|
||||||
@ -35,11 +37,18 @@ public class PipelineDirectoryProcessor {
|
|||||||
private static final Logger logger = LoggerFactory.getLogger(PipelineDirectoryProcessor.class);
|
private static final Logger logger = LoggerFactory.getLogger(PipelineDirectoryProcessor.class);
|
||||||
@Autowired private ObjectMapper objectMapper;
|
@Autowired private ObjectMapper objectMapper;
|
||||||
@Autowired private ApiDocService apiDocService;
|
@Autowired private ApiDocService apiDocService;
|
||||||
|
|
||||||
final String watchedFoldersDir = "./pipeline/watchedFolders/";
|
|
||||||
final String finishedFoldersDir = "./pipeline/finishedFolders/";
|
|
||||||
|
|
||||||
@Autowired PipelineProcessor processor;
|
@Autowired PipelineProcessor processor;
|
||||||
|
@Autowired FileMonitor fileMonitor;
|
||||||
|
|
||||||
|
final String watchedFoldersDir;
|
||||||
|
final String finishedFoldersDir;
|
||||||
|
|
||||||
|
public PipelineDirectoryProcessor(
|
||||||
|
@Qualifier("watchedFoldersDir") String watchedFoldersDir,
|
||||||
|
@Qualifier("finishedFoldersDir") String finishedFoldersDir) {
|
||||||
|
this.watchedFoldersDir = watchedFoldersDir;
|
||||||
|
this.finishedFoldersDir = finishedFoldersDir;
|
||||||
|
}
|
||||||
|
|
||||||
@Scheduled(fixedRate = 60000)
|
@Scheduled(fixedRate = 60000)
|
||||||
public void scanFolders() {
|
public void scanFolders() {
|
||||||
@ -130,7 +139,11 @@ public class PipelineDirectoryProcessor {
|
|||||||
throws IOException {
|
throws IOException {
|
||||||
try (Stream<Path> paths = Files.list(dir)) {
|
try (Stream<Path> paths = Files.list(dir)) {
|
||||||
if ("automated".equals(operation.getParameters().get("fileInput"))) {
|
if ("automated".equals(operation.getParameters().get("fileInput"))) {
|
||||||
return paths.filter(path -> !Files.isDirectory(path) && !path.equals(jsonFile))
|
return paths.filter(
|
||||||
|
path ->
|
||||||
|
!Files.isDirectory(path)
|
||||||
|
&& !path.equals(jsonFile)
|
||||||
|
&& fileMonitor.isFileReadyForProcessing(path))
|
||||||
.map(Path::toFile)
|
.map(Path::toFile)
|
||||||
.toArray(File[]::new);
|
.toArray(File[]::new);
|
||||||
} else {
|
} else {
|
||||||
|
@ -148,7 +148,7 @@ public class CertSignController {
|
|||||||
doc.addSignature(signature, instance);
|
doc.addSignature(signature, instance);
|
||||||
doc.saveIncremental(output);
|
doc.saveIncremental(output);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
logger.error("exception", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,6 +56,8 @@ import org.apache.xmpbox.XMPMetadata;
|
|||||||
import org.apache.xmpbox.xml.DomXmpParser;
|
import org.apache.xmpbox.xml.DomXmpParser;
|
||||||
import org.apache.xmpbox.xml.XmpParsingException;
|
import org.apache.xmpbox.xml.XmpParsingException;
|
||||||
import org.apache.xmpbox.xml.XmpSerializer;
|
import org.apache.xmpbox.xml.XmpSerializer;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||||
@ -79,6 +81,8 @@ import stirling.software.SPDF.utils.WebResponseUtils;
|
|||||||
@Tag(name = "Security", description = "Security APIs")
|
@Tag(name = "Security", description = "Security APIs")
|
||||||
public class GetInfoOnPDF {
|
public class GetInfoOnPDF {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(GetInfoOnPDF.class);
|
||||||
|
|
||||||
static ObjectMapper objectMapper = new ObjectMapper();
|
static ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
|
||||||
@PostMapping(consumes = "multipart/form-data", value = "/get-info-on-pdf")
|
@PostMapping(consumes = "multipart/form-data", value = "/get-info-on-pdf")
|
||||||
@ -220,7 +224,7 @@ public class GetInfoOnPDF {
|
|||||||
javascriptArray.add(jsNode);
|
javascriptArray.add(jsNode);
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
logger.error("exception", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -253,7 +257,7 @@ public class GetInfoOnPDF {
|
|||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// TODO Auto-generated catch block
|
// TODO Auto-generated catch block
|
||||||
e.printStackTrace();
|
logger.error("exception", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isPdfACompliant = checkForStandard(pdfBoxDoc, "PDF/A");
|
boolean isPdfACompliant = checkForStandard(pdfBoxDoc, "PDF/A");
|
||||||
@ -305,7 +309,7 @@ public class GetInfoOnPDF {
|
|||||||
new XmpSerializer().serialize(xmpMeta, os, true);
|
new XmpSerializer().serialize(xmpMeta, os, true);
|
||||||
xmpString = new String(os.toByteArray(), StandardCharsets.UTF_8);
|
xmpString = new String(os.toByteArray(), StandardCharsets.UTF_8);
|
||||||
} catch (XmpParsingException | IOException e) {
|
} catch (XmpParsingException | IOException e) {
|
||||||
e.printStackTrace();
|
logger.error("exception", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -593,7 +597,7 @@ public class GetInfoOnPDF {
|
|||||||
MediaType.APPLICATION_JSON);
|
MediaType.APPLICATION_JSON);
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
logger.error("exception", e);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -691,7 +695,7 @@ public class GetInfoOnPDF {
|
|||||||
Exception
|
Exception
|
||||||
e) { // Catching general exception for brevity, ideally you'd catch specific
|
e) { // Catching general exception for brevity, ideally you'd catch specific
|
||||||
// exceptions.
|
// exceptions.
|
||||||
e.printStackTrace();
|
logger.error("exception", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -0,0 +1,81 @@
|
|||||||
|
package stirling.software.SPDF.controller.api.security;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.apache.pdfbox.Loader;
|
||||||
|
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||||
|
import org.apache.pdfbox.pdmodel.PDDocumentCatalog;
|
||||||
|
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
|
||||||
|
import org.apache.pdfbox.pdmodel.interactive.form.PDField;
|
||||||
|
import org.apache.pdfbox.pdmodel.interactive.form.PDSignatureField;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
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.PDFFile;
|
||||||
|
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/v1/security")
|
||||||
|
@Tag(name = "Security", description = "Security APIs")
|
||||||
|
public class RemoveCertSignController {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(RemoveCertSignController.class);
|
||||||
|
|
||||||
|
@PostMapping(consumes = "multipart/form-data", value = "/remove-cert-sign")
|
||||||
|
@Operation(
|
||||||
|
summary = "Remove digital signature from PDF",
|
||||||
|
description =
|
||||||
|
"This endpoint accepts a PDF file and returns the PDF file without the digital signature. Input: PDF, Output: PDF")
|
||||||
|
public ResponseEntity<byte[]> removeCertSignPDF(@ModelAttribute PDFFile request)
|
||||||
|
throws Exception {
|
||||||
|
MultipartFile pdf = request.getFileInput();
|
||||||
|
|
||||||
|
// Convert MultipartFile to byte[]
|
||||||
|
byte[] pdfBytes = pdf.getBytes();
|
||||||
|
|
||||||
|
// Create a ByteArrayOutputStream to hold the resulting PDF
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
|
||||||
|
// Load the PDF document
|
||||||
|
PDDocument document = Loader.loadPDF(pdfBytes);
|
||||||
|
|
||||||
|
// Get the document catalog
|
||||||
|
PDDocumentCatalog catalog = document.getDocumentCatalog();
|
||||||
|
|
||||||
|
// Get the AcroForm
|
||||||
|
PDAcroForm acroForm = catalog.getAcroForm();
|
||||||
|
if (acroForm != null) {
|
||||||
|
// Remove signature fields safely
|
||||||
|
List<PDField> fieldsToRemove =
|
||||||
|
acroForm.getFields().stream()
|
||||||
|
.filter(field -> field instanceof PDSignatureField)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
if (!fieldsToRemove.isEmpty()) {
|
||||||
|
acroForm.flatten(fieldsToRemove, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the modified document to the ByteArrayOutputStream
|
||||||
|
document.save(baos);
|
||||||
|
document.close();
|
||||||
|
|
||||||
|
// Return the modified PDF as a response
|
||||||
|
return WebResponseUtils.boasToWebResponse(
|
||||||
|
baos,
|
||||||
|
Filenames.toSimpleFileName(pdf.getOriginalFilename()).replaceFirst("[.][^.]+$", "")
|
||||||
|
+ "_unsigned.pdf");
|
||||||
|
}
|
||||||
|
}
|
@ -117,7 +117,6 @@ public class PDFTableStripper extends PDFTextStripper {
|
|||||||
/**
|
/**
|
||||||
* Instantiate a new PDFTableStripper object.
|
* Instantiate a new PDFTableStripper object.
|
||||||
*
|
*
|
||||||
* @param document
|
|
||||||
* @throws IOException If there is an error loading the properties.
|
* @throws IOException If there is an error loading the properties.
|
||||||
*/
|
*/
|
||||||
public PDFTableStripper() throws IOException {
|
public PDFTableStripper() throws IOException {
|
||||||
|
@ -52,23 +52,23 @@ public class AccountWebController {
|
|||||||
OAUTH2 oauth = applicationProperties.getSecurity().getOAUTH2();
|
OAUTH2 oauth = applicationProperties.getSecurity().getOAUTH2();
|
||||||
if (oauth != null) {
|
if (oauth != null) {
|
||||||
if (oauth.isSettingsValid()) {
|
if (oauth.isSettingsValid()) {
|
||||||
providerList.put("oidc", "OpenID Connect");
|
providerList.put("oidc", oauth.getProvider());
|
||||||
}
|
}
|
||||||
Client client = oauth.getClient();
|
Client client = oauth.getClient();
|
||||||
if (client != null) {
|
if (client != null) {
|
||||||
GoogleProvider google = client.getGoogle();
|
GoogleProvider google = client.getGoogle();
|
||||||
if (google.isSettingsValid()) {
|
if (google.isSettingsValid()) {
|
||||||
providerList.put("google", "Google");
|
providerList.put(google.getName(), google.getClientName());
|
||||||
}
|
}
|
||||||
|
|
||||||
GithubProvider github = client.getGithub();
|
GithubProvider github = client.getGithub();
|
||||||
if (github.isSettingsValid()) {
|
if (github.isSettingsValid()) {
|
||||||
providerList.put("github", "Github");
|
providerList.put(github.getName(), github.getClientName());
|
||||||
}
|
}
|
||||||
|
|
||||||
KeycloakProvider keycloak = client.getKeycloak();
|
KeycloakProvider keycloak = client.getKeycloak();
|
||||||
if (keycloak.isSettingsValid()) {
|
if (keycloak.isSettingsValid()) {
|
||||||
providerList.put("keycloak", "Keycloak");
|
providerList.put(keycloak.getName(), keycloak.getClientName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -129,6 +129,8 @@ public class AccountWebController {
|
|||||||
case "invalid_request":
|
case "invalid_request":
|
||||||
erroroauth = "login.oauth2invalidRequest";
|
erroroauth = "login.oauth2invalidRequest";
|
||||||
break;
|
break;
|
||||||
|
case "invalid_id_token":
|
||||||
|
erroroauth = "login.oauth2InvalidIdToken";
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -260,8 +262,7 @@ public class AccountWebController {
|
|||||||
userRepository.findByUsernameIgnoreCase(
|
userRepository.findByUsernameIgnoreCase(
|
||||||
username); // Assuming findByUsername method exists
|
username); // Assuming findByUsername method exists
|
||||||
if (!user.isPresent()) {
|
if (!user.isPresent()) {
|
||||||
// Handle error appropriately
|
return "redirect:/error";
|
||||||
return "redirect:/error"; // Example redirection in case of error
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert settings map to JSON string
|
// Convert settings map to JSON string
|
||||||
@ -271,8 +272,8 @@ public class AccountWebController {
|
|||||||
settingsJson = objectMapper.writeValueAsString(user.get().getSettings());
|
settingsJson = objectMapper.writeValueAsString(user.get().getSettings());
|
||||||
} catch (JsonProcessingException e) {
|
} catch (JsonProcessingException e) {
|
||||||
// Handle JSON conversion error
|
// Handle JSON conversion error
|
||||||
e.printStackTrace();
|
logger.error("exception", e);
|
||||||
return "redirect:/error"; // Example redirection in case of error
|
return "redirect:/error";
|
||||||
}
|
}
|
||||||
|
|
||||||
String messageType = request.getParameter("messageType");
|
String messageType = request.getParameter("messageType");
|
||||||
|
@ -15,6 +15,8 @@ import java.util.Objects;
|
|||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.core.io.ResourceLoader;
|
import org.springframework.core.io.ResourceLoader;
|
||||||
@ -33,6 +35,8 @@ import io.swagger.v3.oas.annotations.tags.Tag;
|
|||||||
@Tag(name = "General", description = "General APIs")
|
@Tag(name = "General", description = "General APIs")
|
||||||
public class GeneralWebController {
|
public class GeneralWebController {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(GeneralWebController.class);
|
||||||
|
|
||||||
@GetMapping("/pipeline")
|
@GetMapping("/pipeline")
|
||||||
@Hidden
|
@Hidden
|
||||||
public String pipelineForm(Model model) {
|
public String pipelineForm(Model model) {
|
||||||
@ -74,7 +78,7 @@ public class GeneralWebController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
logger.error("exception", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (pipelineConfigsWithNames.size() == 0) {
|
if (pipelineConfigsWithNames.size() == 0) {
|
||||||
|
@ -6,6 +6,8 @@ import java.nio.charset.StandardCharsets;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.core.io.ClassPathResource;
|
import org.springframework.core.io.ClassPathResource;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
@ -26,6 +28,8 @@ import stirling.software.SPDF.model.Dependency;
|
|||||||
@Controller
|
@Controller
|
||||||
public class HomeWebController {
|
public class HomeWebController {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(HomeWebController.class);
|
||||||
|
|
||||||
@GetMapping("/about")
|
@GetMapping("/about")
|
||||||
@Hidden
|
@Hidden
|
||||||
public String gameForm(Model model) {
|
public String gameForm(Model model) {
|
||||||
@ -46,7 +50,7 @@ public class HomeWebController {
|
|||||||
mapper.readValue(json, new TypeReference<Map<String, List<Dependency>>>() {});
|
mapper.readValue(json, new TypeReference<Map<String, List<Dependency>>>() {});
|
||||||
model.addAttribute("dependencies", data.get("dependencies"));
|
model.addAttribute("dependencies", data.get("dependencies"));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
logger.error("exception", e);
|
||||||
}
|
}
|
||||||
return "licenses";
|
return "licenses";
|
||||||
}
|
}
|
||||||
|
@ -53,6 +53,13 @@ public class SecurityWebController {
|
|||||||
return "security/cert-sign";
|
return "security/cert-sign";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/remove-cert-sign")
|
||||||
|
@Hidden
|
||||||
|
public String certUnSignForm(Model model) {
|
||||||
|
model.addAttribute("currentPage", "remove-cert-sign");
|
||||||
|
return "security/remove-cert-sign";
|
||||||
|
}
|
||||||
|
|
||||||
@GetMapping("/sanitize-pdf")
|
@GetMapping("/sanitize-pdf")
|
||||||
@Hidden
|
@Hidden
|
||||||
public String sanitizeForm(Model model) {
|
public String sanitizeForm(Model model) {
|
||||||
|
@ -356,8 +356,8 @@ public class ApplicationProperties {
|
|||||||
private KeycloakProvider keycloak = new KeycloakProvider();
|
private KeycloakProvider keycloak = new KeycloakProvider();
|
||||||
|
|
||||||
public Provider get(String registrationId) throws Exception {
|
public Provider get(String registrationId) throws Exception {
|
||||||
switch (registrationId) {
|
switch (registrationId.toLowerCase()) {
|
||||||
case "gogole":
|
case "google":
|
||||||
return getGoogle();
|
return getGoogle();
|
||||||
case "github":
|
case "github":
|
||||||
return getGithub();
|
return getGithub();
|
||||||
@ -455,6 +455,7 @@ public class ApplicationProperties {
|
|||||||
@Override
|
@Override
|
||||||
public Collection<String> getScopes() {
|
public Collection<String> getScopes() {
|
||||||
if (scopes == null || scopes.isEmpty()) {
|
if (scopes == null || scopes.isEmpty()) {
|
||||||
|
scopes = new ArrayList<>();
|
||||||
scopes.add("https://www.googleapis.com/auth/userinfo.email");
|
scopes.add("https://www.googleapis.com/auth/userinfo.email");
|
||||||
scopes.add("https://www.googleapis.com/auth/userinfo.profile");
|
scopes.add("https://www.googleapis.com/auth/userinfo.profile");
|
||||||
}
|
}
|
||||||
@ -495,6 +496,11 @@ public class ApplicationProperties {
|
|||||||
return "google";
|
return "google";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getClientName() {
|
||||||
|
return "Google";
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isSettingsValid() {
|
public boolean isSettingsValid() {
|
||||||
return super.isValid(this.getClientId(), "clientId")
|
return super.isValid(this.getClientId(), "clientId")
|
||||||
&& super.isValid(this.getClientSecret(), "clientSecret")
|
&& super.isValid(this.getClientSecret(), "clientSecret")
|
||||||
@ -553,8 +559,10 @@ public class ApplicationProperties {
|
|||||||
this.clientSecret = clientSecret;
|
this.clientSecret = clientSecret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Collection<String> getScopes() {
|
public Collection<String> getScopes() {
|
||||||
if (scopes == null || scopes.isEmpty()) {
|
if (scopes == null || scopes.isEmpty()) {
|
||||||
|
scopes = new ArrayList<>();
|
||||||
scopes.add("read:user");
|
scopes.add("read:user");
|
||||||
}
|
}
|
||||||
return scopes;
|
return scopes;
|
||||||
@ -594,6 +602,11 @@ public class ApplicationProperties {
|
|||||||
return "github";
|
return "github";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getClientName() {
|
||||||
|
return "GitHub";
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isSettingsValid() {
|
public boolean isSettingsValid() {
|
||||||
return super.isValid(this.getClientId(), "clientId")
|
return super.isValid(this.getClientId(), "clientId")
|
||||||
&& super.isValid(this.getClientSecret(), "clientSecret")
|
&& super.isValid(this.getClientSecret(), "clientSecret")
|
||||||
@ -642,13 +655,14 @@ public class ApplicationProperties {
|
|||||||
@Override
|
@Override
|
||||||
public Collection<String> getScopes() {
|
public Collection<String> getScopes() {
|
||||||
if (scopes == null || scopes.isEmpty()) {
|
if (scopes == null || scopes.isEmpty()) {
|
||||||
scopes.add("openid");
|
scopes = new ArrayList<>();
|
||||||
scopes.add("profile");
|
scopes.add("profile");
|
||||||
scopes.add("email");
|
scopes.add("email");
|
||||||
}
|
}
|
||||||
return scopes;
|
return scopes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void setScopes(String scopes) {
|
public void setScopes(String scopes) {
|
||||||
this.scopes =
|
this.scopes =
|
||||||
Arrays.stream(scopes.split(",")).map(String::trim).collect(Collectors.toList());
|
Arrays.stream(scopes.split(",")).map(String::trim).collect(Collectors.toList());
|
||||||
@ -684,6 +698,11 @@ public class ApplicationProperties {
|
|||||||
return "keycloak";
|
return "keycloak";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getClientName() {
|
||||||
|
return "Keycloak";
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isSettingsValid() {
|
public boolean isSettingsValid() {
|
||||||
return isValid(this.getIssuer(), "issuer")
|
return isValid(this.getIssuer(), "issuer")
|
||||||
&& isValid(this.getClientId(), "clientId")
|
&& isValid(this.getClientId(), "clientId")
|
||||||
|
@ -0,0 +1,45 @@
|
|||||||
|
package stirling.software.SPDF.model;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.Reader;
|
||||||
|
|
||||||
|
import org.thymeleaf.templateresource.ITemplateResource;
|
||||||
|
|
||||||
|
public class InputStreamTemplateResource implements ITemplateResource {
|
||||||
|
private InputStream inputStream;
|
||||||
|
private String characterEncoding;
|
||||||
|
|
||||||
|
public InputStreamTemplateResource(InputStream inputStream, String characterEncoding) {
|
||||||
|
this.inputStream = inputStream;
|
||||||
|
this.characterEncoding = characterEncoding;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Reader reader() throws IOException {
|
||||||
|
return new InputStreamReader(inputStream, characterEncoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ITemplateResource relative(String relativeLocation) {
|
||||||
|
// Implement logic for relative resources, if needed
|
||||||
|
throw new UnsupportedOperationException("Relative resources not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescription() {
|
||||||
|
return "InputStream resource [Stream]";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getBaseName() {
|
||||||
|
return "streamResource";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean exists() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -4,11 +4,16 @@ import java.util.Collection;
|
|||||||
|
|
||||||
public class Provider implements ProviderInterface {
|
public class Provider implements ProviderInterface {
|
||||||
private String name;
|
private String name;
|
||||||
|
private String clientName;
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getClientName() {
|
||||||
|
return clientName;
|
||||||
|
}
|
||||||
|
|
||||||
protected boolean isValid(String value, String name) {
|
protected boolean isValid(String value, String name) {
|
||||||
if (value != null && !value.trim().isEmpty()) {
|
if (value != null && !value.trim().isEmpty()) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -5,6 +5,8 @@ import java.util.List;
|
|||||||
|
|
||||||
import org.apache.pdfbox.Loader;
|
import org.apache.pdfbox.Loader;
|
||||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.Hidden;
|
import io.swagger.v3.oas.annotations.Hidden;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
@ -19,6 +21,8 @@ import stirling.software.SPDF.utils.GeneralUtils;
|
|||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
public class PDFWithPageNums extends PDFFile {
|
public class PDFWithPageNums extends PDFFile {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(PDFWithPageNums.class);
|
||||||
|
|
||||||
@Schema(
|
@Schema(
|
||||||
description =
|
description =
|
||||||
"The pages to select, Supports ranges (e.g., '1,3,5-9'), or 'all' or functions in the format 'an+b' where 'a' is the multiplier of the page number 'n', and 'b' is a constant (e.g., '2n+1', '3n', '6n-5')\"")
|
"The pages to select, Supports ranges (e.g., '1,3,5-9'), or 'all' or functions in the format 'an+b' where 'a' is the multiplier of the page number 'n', and 'b' is a constant (e.g., '2n+1', '3n', '6n-5')\"")
|
||||||
@ -31,7 +35,7 @@ public class PDFWithPageNums extends PDFFile {
|
|||||||
pageCount = Loader.loadPDF(getFileInput().getBytes()).getNumberOfPages();
|
pageCount = Loader.loadPDF(getFileInput().getBytes()).getNumberOfPages();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
// TODO Auto-generated catch block
|
// TODO Auto-generated catch block
|
||||||
e.printStackTrace();
|
logger.error("exception", e);
|
||||||
}
|
}
|
||||||
return GeneralUtils.parsePageList(pageNumbers, pageCount, zeroCount);
|
return GeneralUtils.parsePageList(pageNumbers, pageCount, zeroCount);
|
||||||
}
|
}
|
||||||
|
168
src/main/java/stirling/software/SPDF/utils/FileMonitor.java
Normal file
168
src/main/java/stirling/software/SPDF/utils/FileMonitor.java
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
package stirling.software.SPDF.utils;
|
||||||
|
|
||||||
|
import static java.nio.file.StandardWatchEventKinds.*;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.*;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class FileMonitor {
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(FileMonitor.class);
|
||||||
|
private final Map<Path, WatchKey> path2KeyMapping;
|
||||||
|
private final Set<Path> newlyDiscoveredFiles;
|
||||||
|
private final ConcurrentHashMap.KeySetView<Path, Boolean> readyForProcessingFiles;
|
||||||
|
private final WatchService watchService;
|
||||||
|
private final Predicate<Path> pathFilter;
|
||||||
|
private final Path rootDir;
|
||||||
|
private Set<Path> stagingFiles;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param rootDirectory the root directory to monitor
|
||||||
|
* @param pathFilter the filter to apply to the paths, return true if the path should be
|
||||||
|
* monitored, false otherwise
|
||||||
|
*/
|
||||||
|
@Autowired
|
||||||
|
public FileMonitor(
|
||||||
|
@Qualifier("watchedFoldersDir") String rootDirectory,
|
||||||
|
@Qualifier("directoryFilter") Predicate<Path> pathFilter)
|
||||||
|
throws IOException {
|
||||||
|
this.newlyDiscoveredFiles = new HashSet<>();
|
||||||
|
this.path2KeyMapping = new HashMap<>();
|
||||||
|
this.stagingFiles = new HashSet<>();
|
||||||
|
this.pathFilter = pathFilter;
|
||||||
|
this.readyForProcessingFiles = ConcurrentHashMap.newKeySet();
|
||||||
|
this.watchService = FileSystems.getDefault().newWatchService();
|
||||||
|
this.rootDir = Path.of(rootDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean shouldNotProcess(Path path) {
|
||||||
|
return !pathFilter.test(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void recursivelyRegisterEntry(Path dir) throws IOException {
|
||||||
|
WatchKey key = dir.register(watchService, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
|
||||||
|
path2KeyMapping.put(dir, key);
|
||||||
|
logger.info("Registered directory: {}", dir);
|
||||||
|
|
||||||
|
try (Stream<Path> directoryVisitor = Files.walk(dir, 1)) {
|
||||||
|
final Iterator<Path> iterator = directoryVisitor.iterator();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
Path path = iterator.next();
|
||||||
|
if (path.equals(dir) || shouldNotProcess(path)) continue;
|
||||||
|
|
||||||
|
if (Files.isDirectory(path)) {
|
||||||
|
recursivelyRegisterEntry(path);
|
||||||
|
} else if (Files.isRegularFile(path)) {
|
||||||
|
handleFileCreation(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Scheduled(fixedRate = 5000)
|
||||||
|
public void trackFiles() {
|
||||||
|
/*
|
||||||
|
All files observed changes in the last iteration will be considered as staging files.
|
||||||
|
If those files are not modified in current iteration, they will be considered as ready for processing.
|
||||||
|
*/
|
||||||
|
stagingFiles = new HashSet<>(newlyDiscoveredFiles);
|
||||||
|
readyForProcessingFiles.clear();
|
||||||
|
|
||||||
|
if (path2KeyMapping.isEmpty()) {
|
||||||
|
logger.warn(
|
||||||
|
"not monitoring any directory, even the root directory itself: {}", rootDir);
|
||||||
|
if (Files.exists(
|
||||||
|
rootDir)) { // if the root directory exists, re-register the root directory
|
||||||
|
try {
|
||||||
|
recursivelyRegisterEntry(rootDir);
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.error("unable to register monitoring", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WatchKey key;
|
||||||
|
while ((key = watchService.poll()) != null) {
|
||||||
|
final Path watchingDir = (Path) key.watchable();
|
||||||
|
key.pollEvents()
|
||||||
|
.forEach(
|
||||||
|
(evt) -> {
|
||||||
|
final Path path = (Path) evt.context();
|
||||||
|
final WatchEvent.Kind<?> kind = evt.kind();
|
||||||
|
if (shouldNotProcess(path)) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (Files.isDirectory(path)) {
|
||||||
|
if (kind == ENTRY_CREATE) {
|
||||||
|
handleDirectoryCreation(path);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
we don't need to handle directory deletion or modification
|
||||||
|
- directory deletion will be handled by key.reset()
|
||||||
|
- directory modification indicates a new file creation or deletion, which is handled by below
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
Path relativePathFromRoot = watchingDir.resolve(path);
|
||||||
|
if (kind == ENTRY_CREATE) {
|
||||||
|
handleFileCreation(relativePathFromRoot);
|
||||||
|
} else if (kind == ENTRY_DELETE) {
|
||||||
|
handleFileRemoval(relativePathFromRoot);
|
||||||
|
} else if (kind == ENTRY_MODIFY) {
|
||||||
|
handleFileModification(relativePathFromRoot);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("Error while processing file: {}", path, e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
boolean isKeyValid = key.reset();
|
||||||
|
if (!isKeyValid) { // key is invalid when the directory itself is no longer exists
|
||||||
|
path2KeyMapping.remove((Path) key.watchable());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
readyForProcessingFiles.addAll(stagingFiles);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleDirectoryCreation(Path dir) throws IOException {
|
||||||
|
WatchKey key = dir.register(watchService, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
|
||||||
|
path2KeyMapping.put(dir, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleFileRemoval(Path path) {
|
||||||
|
newlyDiscoveredFiles.remove(path);
|
||||||
|
stagingFiles.remove(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleFileCreation(Path path) {
|
||||||
|
newlyDiscoveredFiles.add(path);
|
||||||
|
stagingFiles.remove(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleFileModification(Path path) {
|
||||||
|
// the logic is the same
|
||||||
|
handleFileCreation(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the file is ready for processing.
|
||||||
|
*
|
||||||
|
* <p>A file is ready for processing if it is not being modified for 5000ms.
|
||||||
|
*
|
||||||
|
* @param path the path of the file
|
||||||
|
* @return true if the file is ready for processing, false otherwise
|
||||||
|
*/
|
||||||
|
public boolean isFileReadyForProcessing(Path path) {
|
||||||
|
return readyForProcessingFiles.contains(path);
|
||||||
|
}
|
||||||
|
}
|
@ -42,6 +42,7 @@ public class FileToPdf {
|
|||||||
List<String> command = new ArrayList<>();
|
List<String> command = new ArrayList<>();
|
||||||
if (!htmlFormatsInstalled) {
|
if (!htmlFormatsInstalled) {
|
||||||
command.add("weasyprint");
|
command.add("weasyprint");
|
||||||
|
command.add("-e utf-8");
|
||||||
command.add(tempInputFile.toString());
|
command.add(tempInputFile.toString());
|
||||||
command.add(tempOutputFile.toString());
|
command.add(tempOutputFile.toString());
|
||||||
|
|
||||||
@ -52,7 +53,7 @@ public class FileToPdf {
|
|||||||
command.add("--paper-size");
|
command.add("--paper-size");
|
||||||
command.add("a4");
|
command.add("a4");
|
||||||
|
|
||||||
if (request.getZoom() != 1.0) {
|
if (request != null && request.getZoom() != 1.0) {
|
||||||
// Create a temporary CSS file
|
// Create a temporary CSS file
|
||||||
File tempCssFile = Files.createTempFile("customStyle", ".css").toFile();
|
File tempCssFile = Files.createTempFile("customStyle", ".css").toFile();
|
||||||
try (FileWriter writer = new FileWriter(tempCssFile)) {
|
try (FileWriter writer = new FileWriter(tempCssFile)) {
|
||||||
|
@ -14,6 +14,8 @@ import java.nio.file.attribute.BasicFileAttributes;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import com.fathzer.soft.javaluator.DoubleEvaluator;
|
import com.fathzer.soft.javaluator.DoubleEvaluator;
|
||||||
@ -23,6 +25,8 @@ import io.github.pixee.security.Urls;
|
|||||||
|
|
||||||
public class GeneralUtils {
|
public class GeneralUtils {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(GeneralUtils.class);
|
||||||
|
|
||||||
public static File convertMultipartFileToFile(MultipartFile multipartFile) throws IOException {
|
public static File convertMultipartFileToFile(MultipartFile multipartFile) throws IOException {
|
||||||
File tempFile = Files.createTempFile("temp", null).toFile();
|
File tempFile = Files.createTempFile("temp", null).toFile();
|
||||||
try (FileOutputStream os = new FileOutputStream(tempFile)) {
|
try (FileOutputStream os = new FileOutputStream(tempFile)) {
|
||||||
@ -234,7 +238,7 @@ public class GeneralUtils {
|
|||||||
try {
|
try {
|
||||||
Files.createDirectories(folder);
|
Files.createDirectories(folder);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
logger.error("exception", e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,8 @@ import java.util.zip.ZipOutputStream;
|
|||||||
|
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
@ -24,6 +26,7 @@ import io.github.pixee.security.Filenames;
|
|||||||
import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult;
|
import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult;
|
||||||
|
|
||||||
public class PDFToFile {
|
public class PDFToFile {
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(PDFToFile.class);
|
||||||
|
|
||||||
public ResponseEntity<byte[]> processPdfToHtml(MultipartFile inputFile)
|
public ResponseEntity<byte[]> processPdfToHtml(MultipartFile inputFile)
|
||||||
throws IOException, InterruptedException {
|
throws IOException, InterruptedException {
|
||||||
@ -67,18 +70,20 @@ public class PDFToFile {
|
|||||||
// Return output files in a ZIP archive
|
// Return output files in a ZIP archive
|
||||||
fileName = pdfBaseName + "ToHtml.zip";
|
fileName = pdfBaseName + "ToHtml.zip";
|
||||||
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||||
ZipOutputStream zipOutputStream = new ZipOutputStream(byteArrayOutputStream);
|
try (ZipOutputStream zipOutputStream = new ZipOutputStream(byteArrayOutputStream)) {
|
||||||
|
for (File outputFile : outputFiles) {
|
||||||
for (File outputFile : outputFiles) {
|
ZipEntry entry = new ZipEntry(outputFile.getName());
|
||||||
ZipEntry entry = new ZipEntry(outputFile.getName());
|
zipOutputStream.putNextEntry(entry);
|
||||||
zipOutputStream.putNextEntry(entry);
|
try (FileInputStream fis = new FileInputStream(outputFile)) {
|
||||||
FileInputStream fis = new FileInputStream(outputFile);
|
IOUtils.copy(fis, zipOutputStream);
|
||||||
IOUtils.copy(fis, zipOutputStream);
|
} catch (IOException e) {
|
||||||
fis.close();
|
logger.error("Exception writing zip entry", e);
|
||||||
zipOutputStream.closeEntry();
|
}
|
||||||
|
zipOutputStream.closeEntry();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.error("Exception writing zip", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
zipOutputStream.close();
|
|
||||||
fileBytes = byteArrayOutputStream.toByteArray();
|
fileBytes = byteArrayOutputStream.toByteArray();
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
@ -160,18 +165,22 @@ public class PDFToFile {
|
|||||||
// Return output files in a ZIP archive
|
// Return output files in a ZIP archive
|
||||||
fileName = pdfBaseName + "To" + outputFormat + ".zip";
|
fileName = pdfBaseName + "To" + outputFormat + ".zip";
|
||||||
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||||
ZipOutputStream zipOutputStream = new ZipOutputStream(byteArrayOutputStream);
|
try (ZipOutputStream zipOutputStream = new ZipOutputStream(byteArrayOutputStream)) {
|
||||||
|
for (File outputFile : outputFiles) {
|
||||||
|
ZipEntry entry = new ZipEntry(outputFile.getName());
|
||||||
|
zipOutputStream.putNextEntry(entry);
|
||||||
|
try (FileInputStream fis = new FileInputStream(outputFile)) {
|
||||||
|
IOUtils.copy(fis, zipOutputStream);
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.error("Exception writing zip entry", e);
|
||||||
|
}
|
||||||
|
|
||||||
for (File outputFile : outputFiles) {
|
zipOutputStream.closeEntry();
|
||||||
ZipEntry entry = new ZipEntry(outputFile.getName());
|
}
|
||||||
zipOutputStream.putNextEntry(entry);
|
} catch (IOException e) {
|
||||||
FileInputStream fis = new FileInputStream(outputFile);
|
logger.error("Exception writing zip", e);
|
||||||
IOUtils.copy(fis, zipOutputStream);
|
|
||||||
fis.close();
|
|
||||||
zipOutputStream.closeEntry();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
zipOutputStream.close();
|
|
||||||
fileBytes = byteArrayOutputStream.toByteArray();
|
fileBytes = byteArrayOutputStream.toByteArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,7 +125,7 @@ public class ProcessExecutor {
|
|||||||
logger.warn(
|
logger.warn(
|
||||||
"Error reader thread was interrupted due to timeout.");
|
"Error reader thread was interrupted due to timeout.");
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
logger.error("exception", e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -149,7 +149,7 @@ public class ProcessExecutor {
|
|||||||
logger.warn(
|
logger.warn(
|
||||||
"Error reader thread was interrupted due to timeout.");
|
"Error reader thread was interrupted due to timeout.");
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
logger.error("exception", e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -332,6 +332,10 @@ home.certSign.title=Sign with Certificate
|
|||||||
home.certSign.desc=Signs a PDF with a Certificate/Key (PEM/P12)
|
home.certSign.desc=Signs a PDF with a Certificate/Key (PEM/P12)
|
||||||
certSign.tags=authenticate,PEM,P12,official,encrypt
|
certSign.tags=authenticate,PEM,P12,official,encrypt
|
||||||
|
|
||||||
|
home.removeCertSign.title=Remove Certificate Sign
|
||||||
|
home.removeCertSign.desc=Remove certificate signature from PDF
|
||||||
|
removeCertSign.tags=authenticate,PEM,P12,official,decrypt
|
||||||
|
|
||||||
home.pageLayout.title=Multi-Page Layout
|
home.pageLayout.title=Multi-Page Layout
|
||||||
home.pageLayout.desc=Merge multiple pages of a PDF document into a single page
|
home.pageLayout.desc=Merge multiple pages of a PDF document into a single page
|
||||||
pageLayout.tags=merge,composite,single-view,organize
|
pageLayout.tags=merge,composite,single-view,organize
|
||||||
@ -457,6 +461,7 @@ login.oauth2InvalidUserInfoResponse=Invalid User Info Response
|
|||||||
login.oauth2invalidRequest=Invalid Request
|
login.oauth2invalidRequest=Invalid Request
|
||||||
login.oauth2AccessDenied=Access Denied
|
login.oauth2AccessDenied=Access Denied
|
||||||
login.oauth2InvalidTokenResponse=Invalid Token Response
|
login.oauth2InvalidTokenResponse=Invalid Token Response
|
||||||
|
login.oauth2InvalidIdToken=Invalid Id Token
|
||||||
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
@ -654,6 +659,13 @@ certSign.name=الاسم
|
|||||||
certSign.submit=تسجيل PDF
|
certSign.submit=تسجيل PDF
|
||||||
|
|
||||||
|
|
||||||
|
#removeCertSign
|
||||||
|
removeCertSign.title=Remove Certificate Signature
|
||||||
|
removeCertSign.header=Remove the digital certificate from the PDF
|
||||||
|
removeCertSign.selectPDF=Select a PDF file:
|
||||||
|
removeCertSign.submit=Remove Signature
|
||||||
|
|
||||||
|
|
||||||
#removeBlanks
|
#removeBlanks
|
||||||
removeBlanks.title=إزالة الفراغات
|
removeBlanks.title=إزالة الفراغات
|
||||||
removeBlanks.header=إزالة الصفحات الفارغة
|
removeBlanks.header=إزالة الصفحات الفارغة
|
||||||
@ -964,6 +976,7 @@ pdfToPDFA.credit=تستخدم هذه الخدمة OCRmyPDF لتحويل PDF / A.
|
|||||||
pdfToPDFA.submit=تحويل
|
pdfToPDFA.submit=تحويل
|
||||||
pdfToPDFA.tip=Currently does not work for multiple inputs at once
|
pdfToPDFA.tip=Currently does not work for multiple inputs at once
|
||||||
pdfToPDFA.outputFormat=Output format
|
pdfToPDFA.outputFormat=Output format
|
||||||
|
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
|
||||||
|
|
||||||
|
|
||||||
#PDFToWord
|
#PDFToWord
|
||||||
|
@ -59,8 +59,8 @@ deleteCurrentUserMessage=Не може да се изтрие вписания
|
|||||||
deleteUsernameExistsMessage=Потребителското име не съществува и не може да бъде изтрито.
|
deleteUsernameExistsMessage=Потребителското име не съществува и не може да бъде изтрито.
|
||||||
downgradeCurrentUserMessage=Не може да се понижи ролята на текущия потребител
|
downgradeCurrentUserMessage=Не може да се понижи ролята на текущия потребител
|
||||||
downgradeCurrentUserLongMessage=Не може да се понижи ролята на текущия потребител. Следователно текущият потребител няма да бъде показан.
|
downgradeCurrentUserLongMessage=Не може да се понижи ролята на текущия потребител. Следователно текущият потребител няма да бъде показан.
|
||||||
userAlreadyExistsOAuthMessage=The user already exists as an OAuth2 user.
|
userAlreadyExistsOAuthMessage=Потребителят вече съществува като OAuth2 потребител.
|
||||||
userAlreadyExistsWebMessage=The user already exists as an web user.
|
userAlreadyExistsWebMessage=Потребителят вече съществува като уеб-потребител.
|
||||||
error=Грешка
|
error=Грешка
|
||||||
oops=Опаа!
|
oops=Опаа!
|
||||||
help=Помощ
|
help=Помощ
|
||||||
@ -105,18 +105,18 @@ pipelineOptions.validateButton=Валидирай
|
|||||||
#############
|
#############
|
||||||
# NAVBAR #
|
# NAVBAR #
|
||||||
#############
|
#############
|
||||||
navbar.favorite=Favorites
|
navbar.favorite=Любими
|
||||||
navbar.darkmode=Тъмна тема
|
navbar.darkmode=Тъмна тема
|
||||||
navbar.language=Languages
|
navbar.language=Езици
|
||||||
navbar.settings=Настройки
|
navbar.settings=Настройки
|
||||||
navbar.allTools=Tools
|
navbar.allTools=Инструменти
|
||||||
navbar.multiTool=Multi Tools
|
navbar.multiTool=Мулти инструменти
|
||||||
navbar.sections.organize=Organize
|
navbar.sections.organize=Организирайте
|
||||||
navbar.sections.convertTo=Convert to PDF
|
navbar.sections.convertTo=Преобразуване в PDF
|
||||||
navbar.sections.convertFrom=Convert from PDF
|
navbar.sections.convertFrom=Преобразуване от PDF
|
||||||
navbar.sections.security=Sign & Security
|
navbar.sections.security=Подписване и сигурност
|
||||||
navbar.sections.advance=Advanced
|
navbar.sections.advance=Разширено
|
||||||
navbar.sections.edit=View & Edit
|
navbar.sections.edit=Преглед и редактиране
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# SETTINGS #
|
# SETTINGS #
|
||||||
@ -185,7 +185,7 @@ adminUserSettings.internalApiUser=Вътрешен API потребител
|
|||||||
adminUserSettings.forceChange=Принудете потребителя да промени потребителското име/парола при влизане
|
adminUserSettings.forceChange=Принудете потребителя да промени потребителското име/парола при влизане
|
||||||
adminUserSettings.submit=Съхранете потребителя
|
adminUserSettings.submit=Съхранете потребителя
|
||||||
adminUserSettings.changeUserRole=Промяна на ролята на потребителя
|
adminUserSettings.changeUserRole=Промяна на ролята на потребителя
|
||||||
adminUserSettings.authenticated=Authenticated
|
adminUserSettings.authenticated=Удостоверен
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
@ -267,7 +267,7 @@ home.fileToPDF.desc=Преобразуване почти всеки файл к
|
|||||||
fileToPDF.tags=трансформация,формат,документ,изображение,слайд,текст,преобразуване,офис,документи,word,excel,powerpoint
|
fileToPDF.tags=трансформация,формат,документ,изображение,слайд,текст,преобразуване,офис,документи,word,excel,powerpoint
|
||||||
|
|
||||||
home.ocr.title=OCR / Почистващи сканирания
|
home.ocr.title=OCR / Почистващи сканирания
|
||||||
home.ocr.desc=Почистване, сканира и открива текст от изображения към PDF и го добавя отново като текст.
|
home.ocr.desc=Почиства, сканира и открива текст от изображения в PDF и го добавя отново като текст.
|
||||||
ocr.tags=разпознаване,текст,изображение,сканиране,четене,идентифициране,откриване,редактиране
|
ocr.tags=разпознаване,текст,изображение,сканиране,четене,идентифициране,откриване,редактиране
|
||||||
|
|
||||||
|
|
||||||
@ -313,7 +313,7 @@ home.flatten.desc=Премахнете всички интерактивни е
|
|||||||
flatten.tags=статичен,деактивиран,неинтерактивен,рационализиран
|
flatten.tags=статичен,деактивиран,неинтерактивен,рационализиран
|
||||||
|
|
||||||
home.repair.title=Поправи
|
home.repair.title=Поправи
|
||||||
home.repair.desc=Опитва се да поправи повреден/счупен PDF
|
home.repair.desc=Опитва се да поправи повреден PDF
|
||||||
repair.tags=поправка,възстановяване,корекция,възстановяване
|
repair.tags=поправка,възстановяване,корекция,възстановяване
|
||||||
|
|
||||||
home.removeBlanks.title=Премахване на празни страници
|
home.removeBlanks.title=Премахване на празни страници
|
||||||
@ -332,6 +332,10 @@ home.certSign.title=Подпишете със сертификат
|
|||||||
home.certSign.desc=Подписва PDF със сертификат/ключ (PEM/P12)
|
home.certSign.desc=Подписва PDF със сертификат/ключ (PEM/P12)
|
||||||
certSign.tags=удостоверяване,PEM,P12,официален,шифроване
|
certSign.tags=удостоверяване,PEM,P12,официален,шифроване
|
||||||
|
|
||||||
|
home.removeCertSign.title=Remove Certificate Sign
|
||||||
|
home.removeCertSign.desc=Remove certificate signature from PDF
|
||||||
|
removeCertSign.tags=authenticate,PEM,P12,official,decrypt
|
||||||
|
|
||||||
home.pageLayout.title=Оформление с няколко страници
|
home.pageLayout.title=Оформление с няколко страници
|
||||||
home.pageLayout.desc=Слейте няколко страници от PDF документ в една страница
|
home.pageLayout.desc=Слейте няколко страници от PDF документ в една страница
|
||||||
pageLayout.tags=сливане,комбиниран,единичен изглед,организиране
|
pageLayout.tags=сливане,комбиниран,единичен изглед,организиране
|
||||||
@ -364,7 +368,7 @@ home.autoSplitPDF.title=Автоматично разделяне на стра
|
|||||||
home.autoSplitPDF.desc=Автоматично разделяне на сканиран PDF файл с QR код за разделяне на физически сканирани страници
|
home.autoSplitPDF.desc=Автоматично разделяне на сканиран PDF файл с QR код за разделяне на физически сканирани страници
|
||||||
autoSplitPDF.tags=QR-базиран,отделен,сканиране-сегмент,организиране
|
autoSplitPDF.tags=QR-базиран,отделен,сканиране-сегмент,организиране
|
||||||
|
|
||||||
home.sanitizePdf.title=Дезинфенкцирам
|
home.sanitizePdf.title=Обеззаразяване
|
||||||
home.sanitizePdf.desc=Премахване на скриптове и други елементи от PDF файлове
|
home.sanitizePdf.desc=Премахване на скриптове и други елементи от PDF файлове
|
||||||
sanitizePdf.tags=чисти,сигурни,безопасни,премахване-заплахи
|
sanitizePdf.tags=чисти,сигурни,безопасни,премахване-заплахи
|
||||||
|
|
||||||
@ -382,8 +386,8 @@ home.MarkdownToPDF.desc=Преобразува всеки Markdown файл къ
|
|||||||
MarkdownToPDF.tags=маркиране,уеб-съдържание,трансформация,преобразуване
|
MarkdownToPDF.tags=маркиране,уеб-съдържание,трансформация,преобразуване
|
||||||
|
|
||||||
|
|
||||||
home.getPdfInfo.title=Вземете ЦЯЛАТА информация към PDF
|
home.getPdfInfo.title=Вземете ЦЯЛАТА информация от PDF
|
||||||
home.getPdfInfo.desc=Взема всяка възможна информация от PDF файлове
|
home.getPdfInfo.desc=Взима всяка възможна информация от PDF файлове
|
||||||
getPdfInfo.tags=информация,данни,статистики,статистика
|
getPdfInfo.tags=информация,данни,статистики,статистика
|
||||||
|
|
||||||
|
|
||||||
@ -405,7 +409,7 @@ home.autoRedact.title=Автоматично редактиране
|
|||||||
home.autoRedact.desc=Автоматично редактира (зачернява) текст в PDF въз основа на въведен текст
|
home.autoRedact.desc=Автоматично редактира (зачернява) текст в PDF въз основа на въведен текст
|
||||||
autoRedact.tags=Редактиране,Скриване,затъмняване,черен,маркер,скрит
|
autoRedact.tags=Редактиране,Скриване,затъмняване,черен,маркер,скрит
|
||||||
|
|
||||||
home.tableExtraxt.title=PDF to CSV
|
home.tableExtraxt.title=PDF в CSV
|
||||||
home.tableExtraxt.desc=Извлича таблици от PDF, като ги конвертира в CSV
|
home.tableExtraxt.desc=Извлича таблици от PDF, като ги конвертира в CSV
|
||||||
tableExtraxt.tags=CSV,извличане на таблица,извличане,конвертиране
|
tableExtraxt.tags=CSV,извличане на таблица,извличане,конвертиране
|
||||||
|
|
||||||
@ -452,11 +456,12 @@ login.locked=Вашият акаунт е заключен.
|
|||||||
login.signinTitle=Моля впишете се
|
login.signinTitle=Моля впишете се
|
||||||
login.ssoSignIn=Влизане чрез еднократно влизане
|
login.ssoSignIn=Влизане чрез еднократно влизане
|
||||||
login.oauth2AutoCreateDisabled=OAUTH2 Автоматично създаване на потребител е деактивирано
|
login.oauth2AutoCreateDisabled=OAUTH2 Автоматично създаване на потребител е деактивирано
|
||||||
login.oauth2RequestNotFound=Authorization request not found
|
login.oauth2RequestNotFound=Заявката за оторизация не е намерена
|
||||||
login.oauth2InvalidUserInfoResponse=Invalid User Info Response
|
login.oauth2InvalidUserInfoResponse=Невалидна информация за потребителя
|
||||||
login.oauth2invalidRequest=Invalid Request
|
login.oauth2invalidRequest=Невалидна заявка
|
||||||
login.oauth2AccessDenied=Access Denied
|
login.oauth2AccessDenied=Отказан достъп
|
||||||
login.oauth2InvalidTokenResponse=Invalid Token Response
|
login.oauth2InvalidTokenResponse=Невалиден отговор на токена
|
||||||
|
login.oauth2InvalidIdToken=Невалиден токен за идентификатор
|
||||||
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
@ -637,7 +642,7 @@ scalePages.submit=Подайте
|
|||||||
|
|
||||||
|
|
||||||
#certSign
|
#certSign
|
||||||
certSign.title=Подписване на сертификат
|
certSign.title=Подписване със сертификат
|
||||||
certSign.header=Подпишете PDF с вашия сертификат (В процес на работа)
|
certSign.header=Подпишете PDF с вашия сертификат (В процес на работа)
|
||||||
certSign.selectPDF=Изберете PDF файл за подписване:
|
certSign.selectPDF=Изберете PDF файл за подписване:
|
||||||
certSign.jksNote=Забележка: Ако вашият тип сертификат не е в списъка по-долу, моля, конвертирайте го във файл на Java Keystore (.jks) с помощта на инструмента за команден ред keytool. След това изберете опцията за .jks файл по-долу.
|
certSign.jksNote=Забележка: Ако вашият тип сертификат не е в списъка по-долу, моля, конвертирайте го във файл на Java Keystore (.jks) с помощта на инструмента за команден ред keytool. След това изберете опцията за .jks файл по-долу.
|
||||||
@ -654,6 +659,13 @@ certSign.name=Име
|
|||||||
certSign.submit=Подпишете PDF
|
certSign.submit=Подпишете PDF
|
||||||
|
|
||||||
|
|
||||||
|
#removeCertSign
|
||||||
|
removeCertSign.title=Remove Certificate Signature
|
||||||
|
removeCertSign.header=Remove the digital certificate from the PDF
|
||||||
|
removeCertSign.selectPDF=Select a PDF file:
|
||||||
|
removeCertSign.submit=Remove Signature
|
||||||
|
|
||||||
|
|
||||||
#removeBlanks
|
#removeBlanks
|
||||||
removeBlanks.title=Премахване на празни места
|
removeBlanks.title=Премахване на празни места
|
||||||
removeBlanks.header=Премахване на празни страници
|
removeBlanks.header=Премахване на празни страници
|
||||||
@ -757,7 +769,7 @@ extractImages.submit=Извличане
|
|||||||
fileToPDF.title=Файл към PDF
|
fileToPDF.title=Файл към PDF
|
||||||
fileToPDF.header=Конвертирайте всеки файл към PDF
|
fileToPDF.header=Конвертирайте всеки файл към PDF
|
||||||
fileToPDF.credit=Тази услуга използва LibreOffice и Unoconv за преобразуване на файлове.
|
fileToPDF.credit=Тази услуга използва LibreOffice и Unoconv за преобразуване на файлове.
|
||||||
fileToPDF.supportedFileTypesInfo=Supported File types
|
fileToPDF.supportedFileTypesInfo=Поддържание файлови типове
|
||||||
fileToPDF.supportedFileTypes=Поддържаните типове файлове трябва да включват по-долу, но за пълен актуализиран списък на поддържаните формати, моля, вижте документацията на LibreOffice
|
fileToPDF.supportedFileTypes=Поддържаните типове файлове трябва да включват по-долу, но за пълен актуализиран списък на поддържаните формати, моля, вижте документацията на LibreOffice
|
||||||
fileToPDF.submit=Преобразуване към PDF
|
fileToPDF.submit=Преобразуване към PDF
|
||||||
|
|
||||||
@ -766,10 +778,10 @@ fileToPDF.submit=Преобразуване към PDF
|
|||||||
compress.title=Компресиране
|
compress.title=Компресиране
|
||||||
compress.header=Компресиране на PDF
|
compress.header=Компресиране на PDF
|
||||||
compress.credit=Тази услуга използва Ghostscript за PDF компресиране/оптимизиране.
|
compress.credit=Тази услуга използва Ghostscript за PDF компресиране/оптимизиране.
|
||||||
compress.selectText.1=Ръчен режим - От 1 до 4
|
compress.selectText.1=Ръчен режим - от 1 до 4
|
||||||
compress.selectText.2=Ниво на оптимизация:
|
compress.selectText.2=Ниво на оптимизация:
|
||||||
compress.selectText.3=4 (Ужасно за текстови изображения)
|
compress.selectText.3=4 (Ужасно за текстови изображения)
|
||||||
compress.selectText.4=Автоматичен режим - Автоматично настройва качеството, за да получи PDF точен размер
|
compress.selectText.4=Автоматичен режим - Автоматично настройва качеството, за да получи PDF с точен размер
|
||||||
compress.selectText.5=Очакван PDF размер (напр. 25МБ, 10.8МБ, 25КБ)
|
compress.selectText.5=Очакван PDF размер (напр. 25МБ, 10.8МБ, 25КБ)
|
||||||
compress.submit=Компресиране
|
compress.submit=Компресиране
|
||||||
|
|
||||||
@ -810,7 +822,7 @@ pdfOrganiser.placeholder=(напр. 1,3,2 или 4-8,2,10-12 или 2n-1)
|
|||||||
#multiTool
|
#multiTool
|
||||||
multiTool.title=PDF Мулти инструмент
|
multiTool.title=PDF Мулти инструмент
|
||||||
multiTool.header=PDF Мулти инструмент
|
multiTool.header=PDF Мулти инструмент
|
||||||
multiTool.uploadPrompts=File Name
|
multiTool.uploadPrompts=Име на файл
|
||||||
|
|
||||||
#view pdf
|
#view pdf
|
||||||
viewPdf.title=Преглед на PDF
|
viewPdf.title=Преглед на PDF
|
||||||
@ -909,8 +921,8 @@ watermark.selectText.7=Непрозрачност (0% - 100%):
|
|||||||
watermark.selectText.8=Тип воден знак:
|
watermark.selectText.8=Тип воден знак:
|
||||||
watermark.selectText.9=Изображение за воден знак:
|
watermark.selectText.9=Изображение за воден знак:
|
||||||
watermark.submit=Добавяне на воден знак
|
watermark.submit=Добавяне на воден знак
|
||||||
watermark.type.1=Text
|
watermark.type.1=Текст
|
||||||
watermark.type.2=Image
|
watermark.type.2=Изображение
|
||||||
|
|
||||||
|
|
||||||
#Change permissions
|
#Change permissions
|
||||||
@ -964,6 +976,7 @@ pdfToPDFA.credit=Тази услуга използва OCRmyPDF за PDF/A пр
|
|||||||
pdfToPDFA.submit=Преобразуване
|
pdfToPDFA.submit=Преобразуване
|
||||||
pdfToPDFA.tip=В момента не работи за няколко входа наведнъж
|
pdfToPDFA.tip=В момента не работи за няколко входа наведнъж
|
||||||
pdfToPDFA.outputFormat=Изходен формат
|
pdfToPDFA.outputFormat=Изходен формат
|
||||||
|
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
|
||||||
|
|
||||||
|
|
||||||
#PDFToWord
|
#PDFToWord
|
||||||
|
@ -332,6 +332,10 @@ home.certSign.title=Signa amb Certificat
|
|||||||
home.certSign.desc=Sign PDF amb Certificate/Clau (PEM/P12)
|
home.certSign.desc=Sign PDF amb Certificate/Clau (PEM/P12)
|
||||||
certSign.tags=authentica,PEM,P12,official,encripta
|
certSign.tags=authentica,PEM,P12,official,encripta
|
||||||
|
|
||||||
|
home.removeCertSign.title=Remove Certificate Sign
|
||||||
|
home.removeCertSign.desc=Remove certificate signature from PDF
|
||||||
|
removeCertSign.tags=authenticate,PEM,P12,official,decrypt
|
||||||
|
|
||||||
home.pageLayout.title=Multi-Page Layout
|
home.pageLayout.title=Multi-Page Layout
|
||||||
home.pageLayout.desc=Merge multiple pages of a PDF document into a single page
|
home.pageLayout.desc=Merge multiple pages of a PDF document into a single page
|
||||||
pageLayout.tags=merge,composite,single-view,organize
|
pageLayout.tags=merge,composite,single-view,organize
|
||||||
@ -457,6 +461,7 @@ login.oauth2InvalidUserInfoResponse=Invalid User Info Response
|
|||||||
login.oauth2invalidRequest=Invalid Request
|
login.oauth2invalidRequest=Invalid Request
|
||||||
login.oauth2AccessDenied=Access Denied
|
login.oauth2AccessDenied=Access Denied
|
||||||
login.oauth2InvalidTokenResponse=Invalid Token Response
|
login.oauth2InvalidTokenResponse=Invalid Token Response
|
||||||
|
login.oauth2InvalidIdToken=Invalid Id Token
|
||||||
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
@ -654,6 +659,13 @@ certSign.name=Nom
|
|||||||
certSign.submit=Firma PDF
|
certSign.submit=Firma PDF
|
||||||
|
|
||||||
|
|
||||||
|
#removeCertSign
|
||||||
|
removeCertSign.title=Remove Certificate Signature
|
||||||
|
removeCertSign.header=Remove the digital certificate from the PDF
|
||||||
|
removeCertSign.selectPDF=Select a PDF file:
|
||||||
|
removeCertSign.submit=Remove Signature
|
||||||
|
|
||||||
|
|
||||||
#removeBlanks
|
#removeBlanks
|
||||||
removeBlanks.title=Elimina els espais en blanc
|
removeBlanks.title=Elimina els espais en blanc
|
||||||
removeBlanks.header=Elimina les pàgines en blanc
|
removeBlanks.header=Elimina les pàgines en blanc
|
||||||
@ -964,6 +976,7 @@ pdfToPDFA.credit=Utilitza OCRmyPDF per la conversió a PDF/A
|
|||||||
pdfToPDFA.submit=Converteix
|
pdfToPDFA.submit=Converteix
|
||||||
pdfToPDFA.tip=Currently does not work for multiple inputs at once
|
pdfToPDFA.tip=Currently does not work for multiple inputs at once
|
||||||
pdfToPDFA.outputFormat=Output format
|
pdfToPDFA.outputFormat=Output format
|
||||||
|
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
|
||||||
|
|
||||||
|
|
||||||
#PDFToWord
|
#PDFToWord
|
||||||
|
@ -26,7 +26,7 @@ bored=Nudíte se při čekání?
|
|||||||
alphabet=Abeceda
|
alphabet=Abeceda
|
||||||
downloadPdf=Stáhnout PDF
|
downloadPdf=Stáhnout PDF
|
||||||
text=Text
|
text=Text
|
||||||
font=Font
|
font=Písmo
|
||||||
selectFillter=-- Vyberte --
|
selectFillter=-- Vyberte --
|
||||||
pageNum=Číslo stránky
|
pageNum=Číslo stránky
|
||||||
sizes.small=Malé
|
sizes.small=Malé
|
||||||
@ -332,6 +332,10 @@ home.certSign.title=Podpis s certifikátem
|
|||||||
home.certSign.desc=Podpis PDF s certifikátem/klíčem (PEM/P12)
|
home.certSign.desc=Podpis PDF s certifikátem/klíčem (PEM/P12)
|
||||||
certSign.tags=autentizace,PEM,P12,oficiální,šifrování
|
certSign.tags=autentizace,PEM,P12,oficiální,šifrování
|
||||||
|
|
||||||
|
home.removeCertSign.title=Remove Certificate Sign
|
||||||
|
home.removeCertSign.desc=Remove certificate signature from PDF
|
||||||
|
removeCertSign.tags=authenticate,PEM,P12,official,decrypt
|
||||||
|
|
||||||
home.pageLayout.title=Vícestránkové rozložení
|
home.pageLayout.title=Vícestránkové rozložení
|
||||||
home.pageLayout.desc=Sloučení více stránek dokumentu PDF do jedné stránky
|
home.pageLayout.desc=Sloučení více stránek dokumentu PDF do jedné stránky
|
||||||
pageLayout.tags=sloučit,kompozitní,jedno zobrazení,organizovat
|
pageLayout.tags=sloučit,kompozitní,jedno zobrazení,organizovat
|
||||||
@ -457,6 +461,7 @@ login.oauth2InvalidUserInfoResponse=Invalid User Info Response
|
|||||||
login.oauth2invalidRequest=Invalid Request
|
login.oauth2invalidRequest=Invalid Request
|
||||||
login.oauth2AccessDenied=Access Denied
|
login.oauth2AccessDenied=Access Denied
|
||||||
login.oauth2InvalidTokenResponse=Invalid Token Response
|
login.oauth2InvalidTokenResponse=Invalid Token Response
|
||||||
|
login.oauth2InvalidIdToken=Invalid Id Token
|
||||||
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
@ -654,6 +659,13 @@ certSign.name=Název
|
|||||||
certSign.submit=Podepsat PDF
|
certSign.submit=Podepsat PDF
|
||||||
|
|
||||||
|
|
||||||
|
#removeCertSign
|
||||||
|
removeCertSign.title=Remove Certificate Signature
|
||||||
|
removeCertSign.header=Remove the digital certificate from the PDF
|
||||||
|
removeCertSign.selectPDF=Select a PDF file:
|
||||||
|
removeCertSign.submit=Remove Signature
|
||||||
|
|
||||||
|
|
||||||
#removeBlanks
|
#removeBlanks
|
||||||
removeBlanks.title=Odebrat prázdné stránky
|
removeBlanks.title=Odebrat prázdné stránky
|
||||||
removeBlanks.header=Odebrat prázdné stránky
|
removeBlanks.header=Odebrat prázdné stránky
|
||||||
@ -964,6 +976,7 @@ pdfToPDFA.credit=Tato služba používá OCRmyPDF pro konverzi do formátu PDF/A
|
|||||||
pdfToPDFA.submit=Převést
|
pdfToPDFA.submit=Převést
|
||||||
pdfToPDFA.tip=V současné době nepracuje pro více vstupů najednou
|
pdfToPDFA.tip=V současné době nepracuje pro více vstupů najednou
|
||||||
pdfToPDFA.outputFormat=Výstupní formát
|
pdfToPDFA.outputFormat=Výstupní formát
|
||||||
|
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
|
||||||
|
|
||||||
|
|
||||||
#PDFToWord
|
#PDFToWord
|
||||||
|
@ -71,7 +71,7 @@ visitGithub=GitHub-Repository besuchen
|
|||||||
donate=Spenden
|
donate=Spenden
|
||||||
color=Farbe
|
color=Farbe
|
||||||
sponsor=Sponsor
|
sponsor=Sponsor
|
||||||
info=Die Info
|
info=Informationen
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -332,6 +332,10 @@ home.certSign.title=Mit Zertifikat signieren
|
|||||||
home.certSign.desc=Ein PDF mit einem Zertifikat/Schlüssel (PEM/P12) signieren
|
home.certSign.desc=Ein PDF mit einem Zertifikat/Schlüssel (PEM/P12) signieren
|
||||||
certSign.tags=authentifizieren,pem,p12,offiziell,verschlüsseln
|
certSign.tags=authentifizieren,pem,p12,offiziell,verschlüsseln
|
||||||
|
|
||||||
|
home.removeCertSign.title=Remove Certificate Sign
|
||||||
|
home.removeCertSign.desc=Remove certificate signature from PDF
|
||||||
|
removeCertSign.tags=authenticate,PEM,P12,official,decrypt
|
||||||
|
|
||||||
home.pageLayout.title=Mehrseitiges Layout
|
home.pageLayout.title=Mehrseitiges Layout
|
||||||
home.pageLayout.desc=Mehrere Seiten eines PDF zu einer Seite zusammenführen
|
home.pageLayout.desc=Mehrere Seiten eines PDF zu einer Seite zusammenführen
|
||||||
pageLayout.tags=zusammenführen,zusammensetzen,einzelansicht,organisieren
|
pageLayout.tags=zusammenführen,zusammensetzen,einzelansicht,organisieren
|
||||||
@ -457,6 +461,7 @@ login.oauth2InvalidUserInfoResponse=Ungültige Benutzerinformationsantwort
|
|||||||
login.oauth2invalidRequest=ungültige Anfrage
|
login.oauth2invalidRequest=ungültige Anfrage
|
||||||
login.oauth2AccessDenied=Zugriff abgelehnt
|
login.oauth2AccessDenied=Zugriff abgelehnt
|
||||||
login.oauth2InvalidTokenResponse=Ungültige Token-Antwort
|
login.oauth2InvalidTokenResponse=Ungültige Token-Antwort
|
||||||
|
login.oauth2InvalidIdToken=Ungültiges ID-Token
|
||||||
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
@ -654,6 +659,13 @@ certSign.name=Name
|
|||||||
certSign.submit=PDF signieren
|
certSign.submit=PDF signieren
|
||||||
|
|
||||||
|
|
||||||
|
#removeCertSign
|
||||||
|
removeCertSign.title=Zertifikatsignatur entfernen
|
||||||
|
removeCertSign.header=Digitales Zertifikat aus dem PDF entfernen
|
||||||
|
removeCertSign.selectPDF=PDF-Datei auswählen:
|
||||||
|
removeCertSign.submit=Signatur entfernen
|
||||||
|
|
||||||
|
|
||||||
#removeBlanks
|
#removeBlanks
|
||||||
removeBlanks.title=Leere Seiten entfernen
|
removeBlanks.title=Leere Seiten entfernen
|
||||||
removeBlanks.header=Leere Seiten entfernen
|
removeBlanks.header=Leere Seiten entfernen
|
||||||
@ -964,6 +976,7 @@ pdfToPDFA.credit=Dieser Dienst verwendet OCRmyPDF für die PDF/A-Konvertierung
|
|||||||
pdfToPDFA.submit=Konvertieren
|
pdfToPDFA.submit=Konvertieren
|
||||||
pdfToPDFA.tip=Dieser Dienst kann nur einzelne Eingangsdateien verarbeiten.
|
pdfToPDFA.tip=Dieser Dienst kann nur einzelne Eingangsdateien verarbeiten.
|
||||||
pdfToPDFA.outputFormat=Ausgabeformat
|
pdfToPDFA.outputFormat=Ausgabeformat
|
||||||
|
pdfToPDFA.pdfWithDigitalSignature=Das PDF enthält eine digitale Signatur. Sie wird im nächsten Schritt entfernt.
|
||||||
|
|
||||||
|
|
||||||
#PDFToWord
|
#PDFToWord
|
||||||
|
@ -332,6 +332,10 @@ home.certSign.title=Υπογραφή με Πιστοποιητικό
|
|||||||
home.certSign.desc=Υπογραφή ενός PDF αρχείου με ένα Πιστοποιητικό/Κλειδί (PEM/P12)
|
home.certSign.desc=Υπογραφή ενός PDF αρχείου με ένα Πιστοποιητικό/Κλειδί (PEM/P12)
|
||||||
certSign.tags=authenticate,PEM,P12,official,encrypt
|
certSign.tags=authenticate,PEM,P12,official,encrypt
|
||||||
|
|
||||||
|
home.removeCertSign.title=Remove Certificate Sign
|
||||||
|
home.removeCertSign.desc=Remove certificate signature from PDF
|
||||||
|
removeCertSign.tags=authenticate,PEM,P12,official,decrypt
|
||||||
|
|
||||||
home.pageLayout.title=Διάταξη πολλών σελίδων
|
home.pageLayout.title=Διάταξη πολλών σελίδων
|
||||||
home.pageLayout.desc=Συγχώνευση πολλαπλών σελίδων ενός εγγράφου PDF σε μία μόνο σελίδα
|
home.pageLayout.desc=Συγχώνευση πολλαπλών σελίδων ενός εγγράφου PDF σε μία μόνο σελίδα
|
||||||
pageLayout.tags=merge,composite,single-view,organize
|
pageLayout.tags=merge,composite,single-view,organize
|
||||||
@ -457,6 +461,7 @@ login.oauth2InvalidUserInfoResponse=Invalid User Info Response
|
|||||||
login.oauth2invalidRequest=Invalid Request
|
login.oauth2invalidRequest=Invalid Request
|
||||||
login.oauth2AccessDenied=Access Denied
|
login.oauth2AccessDenied=Access Denied
|
||||||
login.oauth2InvalidTokenResponse=Invalid Token Response
|
login.oauth2InvalidTokenResponse=Invalid Token Response
|
||||||
|
login.oauth2InvalidIdToken=Invalid Id Token
|
||||||
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
@ -654,6 +659,13 @@ certSign.name=Όνομα
|
|||||||
certSign.submit=Υπογραφή PDF
|
certSign.submit=Υπογραφή PDF
|
||||||
|
|
||||||
|
|
||||||
|
#removeCertSign
|
||||||
|
removeCertSign.title=Remove Certificate Signature
|
||||||
|
removeCertSign.header=Remove the digital certificate from the PDF
|
||||||
|
removeCertSign.selectPDF=Select a PDF file:
|
||||||
|
removeCertSign.submit=Remove Signature
|
||||||
|
|
||||||
|
|
||||||
#removeBlanks
|
#removeBlanks
|
||||||
removeBlanks.title=Αφαίρεση Κενών
|
removeBlanks.title=Αφαίρεση Κενών
|
||||||
removeBlanks.header=Αφαίρεση Κενών Σελίδων
|
removeBlanks.header=Αφαίρεση Κενών Σελίδων
|
||||||
@ -964,6 +976,7 @@ pdfToPDFA.credit=Αυτή η υπηρεσία χρησιμοποιεί OCRmyPDF
|
|||||||
pdfToPDFA.submit=Μετατροπή
|
pdfToPDFA.submit=Μετατροπή
|
||||||
pdfToPDFA.tip=Προς το παρόν δεν λειτουργεί για πολλαπλές εισόδους ταυτόχρονα
|
pdfToPDFA.tip=Προς το παρόν δεν λειτουργεί για πολλαπλές εισόδους ταυτόχρονα
|
||||||
pdfToPDFA.outputFormat=Output format
|
pdfToPDFA.outputFormat=Output format
|
||||||
|
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
|
||||||
|
|
||||||
|
|
||||||
#PDFToWord
|
#PDFToWord
|
||||||
|
@ -332,6 +332,10 @@ home.certSign.title=Sign with Certificate
|
|||||||
home.certSign.desc=Signs a PDF with a Certificate/Key (PEM/P12)
|
home.certSign.desc=Signs a PDF with a Certificate/Key (PEM/P12)
|
||||||
certSign.tags=authenticate,PEM,P12,official,encrypt
|
certSign.tags=authenticate,PEM,P12,official,encrypt
|
||||||
|
|
||||||
|
home.removeCertSign.title=Remove Certificate Sign
|
||||||
|
home.removeCertSign.desc=Remove certificate signature from PDF
|
||||||
|
removeCertSign.tags=authenticate,PEM,P12,official,decrypt
|
||||||
|
|
||||||
home.pageLayout.title=Multi-Page Layout
|
home.pageLayout.title=Multi-Page Layout
|
||||||
home.pageLayout.desc=Merge multiple pages of a PDF document into a single page
|
home.pageLayout.desc=Merge multiple pages of a PDF document into a single page
|
||||||
pageLayout.tags=merge,composite,single-view,organize
|
pageLayout.tags=merge,composite,single-view,organize
|
||||||
@ -457,6 +461,7 @@ login.oauth2InvalidUserInfoResponse=Invalid User Info Response
|
|||||||
login.oauth2invalidRequest=Invalid Request
|
login.oauth2invalidRequest=Invalid Request
|
||||||
login.oauth2AccessDenied=Access Denied
|
login.oauth2AccessDenied=Access Denied
|
||||||
login.oauth2InvalidTokenResponse=Invalid Token Response
|
login.oauth2InvalidTokenResponse=Invalid Token Response
|
||||||
|
login.oauth2InvalidIdToken=Invalid Id Token
|
||||||
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
@ -654,6 +659,13 @@ certSign.name=Name
|
|||||||
certSign.submit=Sign PDF
|
certSign.submit=Sign PDF
|
||||||
|
|
||||||
|
|
||||||
|
#removeCertSign
|
||||||
|
removeCertSign.title=Remove Certificate Signature
|
||||||
|
removeCertSign.header=Remove the digital certificate from the PDF
|
||||||
|
removeCertSign.selectPDF=Select a PDF file:
|
||||||
|
removeCertSign.submit=Remove Signature
|
||||||
|
|
||||||
|
|
||||||
#removeBlanks
|
#removeBlanks
|
||||||
removeBlanks.title=Remove Blanks
|
removeBlanks.title=Remove Blanks
|
||||||
removeBlanks.header=Remove Blank Pages
|
removeBlanks.header=Remove Blank Pages
|
||||||
@ -964,6 +976,7 @@ pdfToPDFA.credit=This service uses OCRmyPDF for PDF/A conversion
|
|||||||
pdfToPDFA.submit=Convert
|
pdfToPDFA.submit=Convert
|
||||||
pdfToPDFA.tip=Currently does not work for multiple inputs at once
|
pdfToPDFA.tip=Currently does not work for multiple inputs at once
|
||||||
pdfToPDFA.outputFormat=Output format
|
pdfToPDFA.outputFormat=Output format
|
||||||
|
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
|
||||||
|
|
||||||
|
|
||||||
#PDFToWord
|
#PDFToWord
|
||||||
|
@ -332,6 +332,10 @@ home.certSign.title=Sign with Certificate
|
|||||||
home.certSign.desc=Signs a PDF with a Certificate/Key (PEM/P12)
|
home.certSign.desc=Signs a PDF with a Certificate/Key (PEM/P12)
|
||||||
certSign.tags=authenticate,PEM,P12,official,encrypt
|
certSign.tags=authenticate,PEM,P12,official,encrypt
|
||||||
|
|
||||||
|
home.removeCertSign.title=Remove Certificate Sign
|
||||||
|
home.removeCertSign.desc=Remove certificate signature from PDF
|
||||||
|
removeCertSign.tags=authenticate,PEM,P12,official,decrypt
|
||||||
|
|
||||||
home.pageLayout.title=Multi-Page Layout
|
home.pageLayout.title=Multi-Page Layout
|
||||||
home.pageLayout.desc=Merge multiple pages of a PDF document into a single page
|
home.pageLayout.desc=Merge multiple pages of a PDF document into a single page
|
||||||
pageLayout.tags=merge,composite,single-view,organize
|
pageLayout.tags=merge,composite,single-view,organize
|
||||||
@ -457,6 +461,7 @@ login.oauth2InvalidUserInfoResponse=Invalid User Info Response
|
|||||||
login.oauth2invalidRequest=Invalid Request
|
login.oauth2invalidRequest=Invalid Request
|
||||||
login.oauth2AccessDenied=Access Denied
|
login.oauth2AccessDenied=Access Denied
|
||||||
login.oauth2InvalidTokenResponse=Invalid Token Response
|
login.oauth2InvalidTokenResponse=Invalid Token Response
|
||||||
|
login.oauth2InvalidIdToken=Invalid Id Token
|
||||||
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
@ -654,6 +659,13 @@ certSign.name=Name
|
|||||||
certSign.submit=Sign PDF
|
certSign.submit=Sign PDF
|
||||||
|
|
||||||
|
|
||||||
|
#removeCertSign
|
||||||
|
removeCertSign.title=Remove Certificate Signature
|
||||||
|
removeCertSign.header=Remove the digital certificate from the PDF
|
||||||
|
removeCertSign.selectPDF=Select a PDF file:
|
||||||
|
removeCertSign.submit=Remove Signature
|
||||||
|
|
||||||
|
|
||||||
#removeBlanks
|
#removeBlanks
|
||||||
removeBlanks.title=Remove Blanks
|
removeBlanks.title=Remove Blanks
|
||||||
removeBlanks.header=Remove Blank Pages
|
removeBlanks.header=Remove Blank Pages
|
||||||
@ -964,6 +976,7 @@ pdfToPDFA.credit=This service uses OCRmyPDF for PDF/A conversion
|
|||||||
pdfToPDFA.submit=Convert
|
pdfToPDFA.submit=Convert
|
||||||
pdfToPDFA.tip=Currently does not work for multiple inputs at once
|
pdfToPDFA.tip=Currently does not work for multiple inputs at once
|
||||||
pdfToPDFA.outputFormat=Output format
|
pdfToPDFA.outputFormat=Output format
|
||||||
|
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
|
||||||
|
|
||||||
|
|
||||||
#PDFToWord
|
#PDFToWord
|
||||||
|
@ -332,6 +332,10 @@ home.certSign.title=Firmar con certificado
|
|||||||
home.certSign.desc=Firmar un PDF con un Certificado/Clave (PEM/P12)
|
home.certSign.desc=Firmar un PDF con un Certificado/Clave (PEM/P12)
|
||||||
certSign.tags=autentificar,PEM,P12,oficial,encriptar
|
certSign.tags=autentificar,PEM,P12,oficial,encriptar
|
||||||
|
|
||||||
|
home.removeCertSign.title=Remove Certificate Sign
|
||||||
|
home.removeCertSign.desc=Remove certificate signature from PDF
|
||||||
|
removeCertSign.tags=authenticate,PEM,P12,official,decrypt
|
||||||
|
|
||||||
home.pageLayout.title=Diseño de varias páginas
|
home.pageLayout.title=Diseño de varias páginas
|
||||||
home.pageLayout.desc=Unir varias páginas de un documento PDF en una sola página
|
home.pageLayout.desc=Unir varias páginas de un documento PDF en una sola página
|
||||||
pageLayout.tags=unir,compuesto,vista única,organizar
|
pageLayout.tags=unir,compuesto,vista única,organizar
|
||||||
@ -457,6 +461,7 @@ login.oauth2InvalidUserInfoResponse=Invalid User Info Response
|
|||||||
login.oauth2invalidRequest=Invalid Request
|
login.oauth2invalidRequest=Invalid Request
|
||||||
login.oauth2AccessDenied=Access Denied
|
login.oauth2AccessDenied=Access Denied
|
||||||
login.oauth2InvalidTokenResponse=Invalid Token Response
|
login.oauth2InvalidTokenResponse=Invalid Token Response
|
||||||
|
login.oauth2InvalidIdToken=Invalid Id Token
|
||||||
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
@ -654,6 +659,13 @@ certSign.name=Nombre
|
|||||||
certSign.submit=Firmar PDF
|
certSign.submit=Firmar PDF
|
||||||
|
|
||||||
|
|
||||||
|
#removeCertSign
|
||||||
|
removeCertSign.title=Remove Certificate Signature
|
||||||
|
removeCertSign.header=Remove the digital certificate from the PDF
|
||||||
|
removeCertSign.selectPDF=Select a PDF file:
|
||||||
|
removeCertSign.submit=Remove Signature
|
||||||
|
|
||||||
|
|
||||||
#removeBlanks
|
#removeBlanks
|
||||||
removeBlanks.title=Eliminar espacios en blanco
|
removeBlanks.title=Eliminar espacios en blanco
|
||||||
removeBlanks.header=Eliminar páginas en blanco
|
removeBlanks.header=Eliminar páginas en blanco
|
||||||
@ -964,6 +976,7 @@ pdfToPDFA.credit=Este servicio usa OCRmyPDF para la conversión a PDF/A
|
|||||||
pdfToPDFA.submit=Convertir
|
pdfToPDFA.submit=Convertir
|
||||||
pdfToPDFA.tip=Actualmente no funciona para múltiples entrada a la vez
|
pdfToPDFA.tip=Actualmente no funciona para múltiples entrada a la vez
|
||||||
pdfToPDFA.outputFormat=Output format
|
pdfToPDFA.outputFormat=Output format
|
||||||
|
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
|
||||||
|
|
||||||
|
|
||||||
#PDFToWord
|
#PDFToWord
|
||||||
|
@ -332,6 +332,10 @@ home.certSign.title=Sinatu ziurtagiriarekin
|
|||||||
home.certSign.desc=Sinatu PDF bat Ziurtagiri/Gako batekin (PEM/P12)
|
home.certSign.desc=Sinatu PDF bat Ziurtagiri/Gako batekin (PEM/P12)
|
||||||
certSign.tags=authenticate,PEM,P12,official,encrypt
|
certSign.tags=authenticate,PEM,P12,official,encrypt
|
||||||
|
|
||||||
|
home.removeCertSign.title=Remove Certificate Sign
|
||||||
|
home.removeCertSign.desc=Remove certificate signature from PDF
|
||||||
|
removeCertSign.tags=authenticate,PEM,P12,official,decrypt
|
||||||
|
|
||||||
home.pageLayout.title=Zenbait orrialderen diseinua
|
home.pageLayout.title=Zenbait orrialderen diseinua
|
||||||
home.pageLayout.desc=Elkartu orri bakar batean PDF dokumentu baten zenbait orrialde
|
home.pageLayout.desc=Elkartu orri bakar batean PDF dokumentu baten zenbait orrialde
|
||||||
pageLayout.tags=merge,composite,single-view,organize
|
pageLayout.tags=merge,composite,single-view,organize
|
||||||
@ -457,6 +461,7 @@ login.oauth2InvalidUserInfoResponse=Invalid User Info Response
|
|||||||
login.oauth2invalidRequest=Invalid Request
|
login.oauth2invalidRequest=Invalid Request
|
||||||
login.oauth2AccessDenied=Access Denied
|
login.oauth2AccessDenied=Access Denied
|
||||||
login.oauth2InvalidTokenResponse=Invalid Token Response
|
login.oauth2InvalidTokenResponse=Invalid Token Response
|
||||||
|
login.oauth2InvalidIdToken=Invalid Id Token
|
||||||
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
@ -654,6 +659,13 @@ certSign.name=Izena
|
|||||||
certSign.submit=Sinatu PDFa
|
certSign.submit=Sinatu PDFa
|
||||||
|
|
||||||
|
|
||||||
|
#removeCertSign
|
||||||
|
removeCertSign.title=Remove Certificate Signature
|
||||||
|
removeCertSign.header=Remove the digital certificate from the PDF
|
||||||
|
removeCertSign.selectPDF=Select a PDF file:
|
||||||
|
removeCertSign.submit=Remove Signature
|
||||||
|
|
||||||
|
|
||||||
#removeBlanks
|
#removeBlanks
|
||||||
removeBlanks.title=Ezabatu zuriuneak
|
removeBlanks.title=Ezabatu zuriuneak
|
||||||
removeBlanks.header=Ezabatu orrialde zuriak
|
removeBlanks.header=Ezabatu orrialde zuriak
|
||||||
@ -964,6 +976,7 @@ pdfToPDFA.credit=Zerbitzu honek OCRmyPDF erabiltzen du PDFak PDF/A bihurtzeko
|
|||||||
pdfToPDFA.submit=Bihurtu
|
pdfToPDFA.submit=Bihurtu
|
||||||
pdfToPDFA.tip=Currently does not work for multiple inputs at once
|
pdfToPDFA.tip=Currently does not work for multiple inputs at once
|
||||||
pdfToPDFA.outputFormat=Output format
|
pdfToPDFA.outputFormat=Output format
|
||||||
|
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
|
||||||
|
|
||||||
|
|
||||||
#PDFToWord
|
#PDFToWord
|
||||||
|
@ -332,6 +332,10 @@ home.certSign.title=Signer avec un certificat
|
|||||||
home.certSign.desc=Signez un PDF avec un certificat ou une clé (PEM/P12).
|
home.certSign.desc=Signez un PDF avec un certificat ou une clé (PEM/P12).
|
||||||
certSign.tags=signer,chiffrer,certificat,authenticate,PEM,P12,official,encrypt
|
certSign.tags=signer,chiffrer,certificat,authenticate,PEM,P12,official,encrypt
|
||||||
|
|
||||||
|
home.removeCertSign.title=Remove Certificate Sign
|
||||||
|
home.removeCertSign.desc=Remove certificate signature from PDF
|
||||||
|
removeCertSign.tags=authenticate,PEM,P12,official,decrypt
|
||||||
|
|
||||||
home.pageLayout.title=Fusionner des pages
|
home.pageLayout.title=Fusionner des pages
|
||||||
home.pageLayout.desc=Fusionnez plusieurs pages d’un PDF en une seule.
|
home.pageLayout.desc=Fusionnez plusieurs pages d’un PDF en une seule.
|
||||||
pageLayout.tags=fusionner,merge,composite,single-view,organize
|
pageLayout.tags=fusionner,merge,composite,single-view,organize
|
||||||
@ -457,6 +461,7 @@ login.oauth2InvalidUserInfoResponse=Invalid User Info Response
|
|||||||
login.oauth2invalidRequest=Invalid Request
|
login.oauth2invalidRequest=Invalid Request
|
||||||
login.oauth2AccessDenied=Access Denied
|
login.oauth2AccessDenied=Access Denied
|
||||||
login.oauth2InvalidTokenResponse=Invalid Token Response
|
login.oauth2InvalidTokenResponse=Invalid Token Response
|
||||||
|
login.oauth2InvalidIdToken=Invalid Id Token
|
||||||
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
@ -654,6 +659,13 @@ certSign.name=Nom
|
|||||||
certSign.submit=Signer
|
certSign.submit=Signer
|
||||||
|
|
||||||
|
|
||||||
|
#removeCertSign
|
||||||
|
removeCertSign.title=Remove Certificate Signature
|
||||||
|
removeCertSign.header=Remove the digital certificate from the PDF
|
||||||
|
removeCertSign.selectPDF=Select a PDF file:
|
||||||
|
removeCertSign.submit=Remove Signature
|
||||||
|
|
||||||
|
|
||||||
#removeBlanks
|
#removeBlanks
|
||||||
removeBlanks.title=Supprimer les pages vierges
|
removeBlanks.title=Supprimer les pages vierges
|
||||||
removeBlanks.header=Supprimer les pages vierges
|
removeBlanks.header=Supprimer les pages vierges
|
||||||
@ -964,6 +976,7 @@ pdfToPDFA.credit=Ce service utilise OCRmyPDF pour la conversion en PDF/A.
|
|||||||
pdfToPDFA.submit=Convertir
|
pdfToPDFA.submit=Convertir
|
||||||
pdfToPDFA.tip=Ne fonctionne actuellement pas pour plusieurs entrées à la fois
|
pdfToPDFA.tip=Ne fonctionne actuellement pas pour plusieurs entrées à la fois
|
||||||
pdfToPDFA.outputFormat=Format de sortie
|
pdfToPDFA.outputFormat=Format de sortie
|
||||||
|
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
|
||||||
|
|
||||||
|
|
||||||
#PDFToWord
|
#PDFToWord
|
||||||
|
@ -332,6 +332,10 @@ home.certSign.title=प्रमाणपत्र के साथ हस्त
|
|||||||
home.certSign.desc=पीडीएफ़ को प्रमाणपत्र/कुंजी (PEM/P12) के साथ हस्ताक्षरित करता है।
|
home.certSign.desc=पीडीएफ़ को प्रमाणपत्र/कुंजी (PEM/P12) के साथ हस्ताक्षरित करता है।
|
||||||
certSign.tags=प्रमाणीकरण, PEM, P12, आधिकारिक, एन्क्रिप्ट
|
certSign.tags=प्रमाणीकरण, PEM, P12, आधिकारिक, एन्क्रिप्ट
|
||||||
|
|
||||||
|
home.removeCertSign.title=Remove Certificate Sign
|
||||||
|
home.removeCertSign.desc=Remove certificate signature from PDF
|
||||||
|
removeCertSign.tags=authenticate,PEM,P12,official,decrypt
|
||||||
|
|
||||||
home.pageLayout.title=मल्टी-पेज लेआउट
|
home.pageLayout.title=मल्टी-पेज लेआउट
|
||||||
home.pageLayout.desc=पीडीएफ़ दस्तावेज़ के कई पेजों को एक ही पेज में मर्ज करता है।
|
home.pageLayout.desc=पीडीएफ़ दस्तावेज़ के कई पेजों को एक ही पेज में मर्ज करता है।
|
||||||
pageLayout.tags=मर्ज, संयोजित, एकल दृश्य, संगठित
|
pageLayout.tags=मर्ज, संयोजित, एकल दृश्य, संगठित
|
||||||
@ -457,6 +461,7 @@ login.oauth2InvalidUserInfoResponse=Invalid User Info Response
|
|||||||
login.oauth2invalidRequest=Invalid Request
|
login.oauth2invalidRequest=Invalid Request
|
||||||
login.oauth2AccessDenied=Access Denied
|
login.oauth2AccessDenied=Access Denied
|
||||||
login.oauth2InvalidTokenResponse=Invalid Token Response
|
login.oauth2InvalidTokenResponse=Invalid Token Response
|
||||||
|
login.oauth2InvalidIdToken=Invalid Id Token
|
||||||
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
@ -654,6 +659,13 @@ certSign.name=नाम
|
|||||||
certSign.submit=पीडीएफ़ पर हस्ताक्षर करें
|
certSign.submit=पीडीएफ़ पर हस्ताक्षर करें
|
||||||
|
|
||||||
|
|
||||||
|
#removeCertSign
|
||||||
|
removeCertSign.title=Remove Certificate Signature
|
||||||
|
removeCertSign.header=Remove the digital certificate from the PDF
|
||||||
|
removeCertSign.selectPDF=Select a PDF file:
|
||||||
|
removeCertSign.submit=Remove Signature
|
||||||
|
|
||||||
|
|
||||||
#removeBlanks
|
#removeBlanks
|
||||||
removeBlanks.title=खाली पेज हटाएं
|
removeBlanks.title=खाली पेज हटाएं
|
||||||
removeBlanks.header=खाली पेज हटाएं
|
removeBlanks.header=खाली पेज हटाएं
|
||||||
@ -964,6 +976,7 @@ pdfToPDFA.credit=इस सेवा में PDF/A परिवर्तन
|
|||||||
pdfToPDFA.submit=परिवर्तित करें
|
pdfToPDFA.submit=परिवर्तित करें
|
||||||
pdfToPDFA.tip=Currently does not work for multiple inputs at once
|
pdfToPDFA.tip=Currently does not work for multiple inputs at once
|
||||||
pdfToPDFA.outputFormat=Output format
|
pdfToPDFA.outputFormat=Output format
|
||||||
|
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
|
||||||
|
|
||||||
|
|
||||||
#PDFToWord
|
#PDFToWord
|
||||||
|
1093
src/main/resources/messages_hr_HR.properties
Normal file
1093
src/main/resources/messages_hr_HR.properties
Normal file
File diff suppressed because it is too large
Load Diff
@ -332,6 +332,10 @@ home.certSign.title=Aláírás Tanúsítvánnyal
|
|||||||
home.certSign.desc=PDF aláírása tanúsítvánnyal/kulccsal (PEM/P12)
|
home.certSign.desc=PDF aláírása tanúsítvánnyal/kulccsal (PEM/P12)
|
||||||
certSign.tags=hitelesítés,PEM,P12,hivatalos,segitít,álca
|
certSign.tags=hitelesítés,PEM,P12,hivatalos,segitít,álca
|
||||||
|
|
||||||
|
home.removeCertSign.title=Remove Certificate Sign
|
||||||
|
home.removeCertSign.desc=Remove certificate signature from PDF
|
||||||
|
removeCertSign.tags=authenticate,PEM,P12,official,decrypt
|
||||||
|
|
||||||
home.pageLayout.title=Több oldal elrendezése
|
home.pageLayout.title=Több oldal elrendezése
|
||||||
home.pageLayout.desc=Több oldal egyesítése egy PDF dokumentumban egyetlen oldallá
|
home.pageLayout.desc=Több oldal egyesítése egy PDF dokumentumban egyetlen oldallá
|
||||||
pageLayout.tags=egyesítés,kompozit,egy oldal,megszervez
|
pageLayout.tags=egyesítés,kompozit,egy oldal,megszervez
|
||||||
@ -457,6 +461,7 @@ login.oauth2InvalidUserInfoResponse=Invalid User Info Response
|
|||||||
login.oauth2invalidRequest=Invalid Request
|
login.oauth2invalidRequest=Invalid Request
|
||||||
login.oauth2AccessDenied=Access Denied
|
login.oauth2AccessDenied=Access Denied
|
||||||
login.oauth2InvalidTokenResponse=Invalid Token Response
|
login.oauth2InvalidTokenResponse=Invalid Token Response
|
||||||
|
login.oauth2InvalidIdToken=Invalid Id Token
|
||||||
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
@ -654,6 +659,13 @@ certSign.name=Név
|
|||||||
certSign.submit=PDF aláírása
|
certSign.submit=PDF aláírása
|
||||||
|
|
||||||
|
|
||||||
|
#removeCertSign
|
||||||
|
removeCertSign.title=Remove Certificate Signature
|
||||||
|
removeCertSign.header=Remove the digital certificate from the PDF
|
||||||
|
removeCertSign.selectPDF=Select a PDF file:
|
||||||
|
removeCertSign.submit=Remove Signature
|
||||||
|
|
||||||
|
|
||||||
#removeBlanks
|
#removeBlanks
|
||||||
removeBlanks.title=Üres oldalak eltávolítása
|
removeBlanks.title=Üres oldalak eltávolítása
|
||||||
removeBlanks.header=Üres oldalak eltávolítása
|
removeBlanks.header=Üres oldalak eltávolítása
|
||||||
@ -964,6 +976,7 @@ pdfToPDFA.credit=Ez a szolgáltatás az OCRmyPDF-t használja a PDF/A konverzió
|
|||||||
pdfToPDFA.submit=Konvertálás
|
pdfToPDFA.submit=Konvertálás
|
||||||
pdfToPDFA.tip=Currently does not work for multiple inputs at once
|
pdfToPDFA.tip=Currently does not work for multiple inputs at once
|
||||||
pdfToPDFA.outputFormat=Output format
|
pdfToPDFA.outputFormat=Output format
|
||||||
|
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
|
||||||
|
|
||||||
|
|
||||||
#PDFToWord
|
#PDFToWord
|
||||||
|
@ -332,6 +332,10 @@ home.certSign.title=Tanda tangani dengan Sertifikat
|
|||||||
home.certSign.desc=Menandatangani PDF dengan Certificate/Key (PEM/P12)
|
home.certSign.desc=Menandatangani PDF dengan Certificate/Key (PEM/P12)
|
||||||
certSign.tags=mengotentikasi, PEM, P12, resmi, mengenkripsi
|
certSign.tags=mengotentikasi, PEM, P12, resmi, mengenkripsi
|
||||||
|
|
||||||
|
home.removeCertSign.title=Remove Certificate Sign
|
||||||
|
home.removeCertSign.desc=Remove certificate signature from PDF
|
||||||
|
removeCertSign.tags=authenticate,PEM,P12,official,decrypt
|
||||||
|
|
||||||
home.pageLayout.title=Tata Letak Multi-Halaman
|
home.pageLayout.title=Tata Letak Multi-Halaman
|
||||||
home.pageLayout.desc=Menggabungkan beberapa halaman dokumen PDF menjadi satu halaman
|
home.pageLayout.desc=Menggabungkan beberapa halaman dokumen PDF menjadi satu halaman
|
||||||
pageLayout.tags=menggabungkan, komposit, tampilan tunggal, mengatur
|
pageLayout.tags=menggabungkan, komposit, tampilan tunggal, mengatur
|
||||||
@ -457,6 +461,7 @@ login.oauth2InvalidUserInfoResponse=Invalid User Info Response
|
|||||||
login.oauth2invalidRequest=Invalid Request
|
login.oauth2invalidRequest=Invalid Request
|
||||||
login.oauth2AccessDenied=Access Denied
|
login.oauth2AccessDenied=Access Denied
|
||||||
login.oauth2InvalidTokenResponse=Invalid Token Response
|
login.oauth2InvalidTokenResponse=Invalid Token Response
|
||||||
|
login.oauth2InvalidIdToken=Invalid Id Token
|
||||||
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
@ -654,6 +659,13 @@ certSign.name=Nama
|
|||||||
certSign.submit=Tanda tangani PDF
|
certSign.submit=Tanda tangani PDF
|
||||||
|
|
||||||
|
|
||||||
|
#removeCertSign
|
||||||
|
removeCertSign.title=Remove Certificate Signature
|
||||||
|
removeCertSign.header=Remove the digital certificate from the PDF
|
||||||
|
removeCertSign.selectPDF=Select a PDF file:
|
||||||
|
removeCertSign.submit=Remove Signature
|
||||||
|
|
||||||
|
|
||||||
#removeBlanks
|
#removeBlanks
|
||||||
removeBlanks.title=Hapus Halaman Kosong
|
removeBlanks.title=Hapus Halaman Kosong
|
||||||
removeBlanks.header=Remove Blank Pages
|
removeBlanks.header=Remove Blank Pages
|
||||||
@ -964,6 +976,7 @@ pdfToPDFA.credit=Layanan ini menggunakan OCRmyPDF untuk konversi PDF/A.
|
|||||||
pdfToPDFA.submit=Konversi
|
pdfToPDFA.submit=Konversi
|
||||||
pdfToPDFA.tip=Currently does not work for multiple inputs at once
|
pdfToPDFA.tip=Currently does not work for multiple inputs at once
|
||||||
pdfToPDFA.outputFormat=Output format
|
pdfToPDFA.outputFormat=Output format
|
||||||
|
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
|
||||||
|
|
||||||
|
|
||||||
#PDFToWord
|
#PDFToWord
|
||||||
|
@ -332,6 +332,10 @@ home.certSign.title=Firma con certificato
|
|||||||
home.certSign.desc=Firma un PDF con un certificato/chiave (PEM/P12)
|
home.certSign.desc=Firma un PDF con un certificato/chiave (PEM/P12)
|
||||||
certSign.tags=autenticare,PEM,P12,ufficiale,crittografare
|
certSign.tags=autenticare,PEM,P12,ufficiale,crittografare
|
||||||
|
|
||||||
|
home.removeCertSign.title=Remove Certificate Sign
|
||||||
|
home.removeCertSign.desc=Remove certificate signature from PDF
|
||||||
|
removeCertSign.tags=authenticate,PEM,P12,official,decrypt
|
||||||
|
|
||||||
home.pageLayout.title=Layout multipagina
|
home.pageLayout.title=Layout multipagina
|
||||||
home.pageLayout.desc=Unisci più pagine di un documento PDF in un'unica pagina
|
home.pageLayout.desc=Unisci più pagine di un documento PDF in un'unica pagina
|
||||||
pageLayout.tags=unire,comporre,visualizzazione singola,organizzare
|
pageLayout.tags=unire,comporre,visualizzazione singola,organizzare
|
||||||
@ -417,7 +421,7 @@ autoSizeSplitPDF.tags=pdf,diviso,documento,organizzazione
|
|||||||
|
|
||||||
home.overlay-pdfs.title=Sovrapposizione di PDF
|
home.overlay-pdfs.title=Sovrapposizione di PDF
|
||||||
home.overlay-pdfs.desc=Sovrappone i PDF sopra un altro PDF
|
home.overlay-pdfs.desc=Sovrappone i PDF sopra un altro PDF
|
||||||
overlay-pdfs.tags=Svrapponi
|
overlay-pdfs.tags=Sovrapponi
|
||||||
|
|
||||||
home.split-by-sections.title=Dividi PDF per sezioni
|
home.split-by-sections.title=Dividi PDF per sezioni
|
||||||
home.split-by-sections.desc=Dividi ciascuna pagina di un PDF in sezioni orizzontali e verticali più piccole
|
home.split-by-sections.desc=Dividi ciascuna pagina di un PDF in sezioni orizzontali e verticali più piccole
|
||||||
@ -457,6 +461,7 @@ login.oauth2InvalidUserInfoResponse=Risposta relativa alle informazioni utente n
|
|||||||
login.oauth2invalidRequest=Richiesta non valida
|
login.oauth2invalidRequest=Richiesta non valida
|
||||||
login.oauth2AccessDenied=Accesso negato
|
login.oauth2AccessDenied=Accesso negato
|
||||||
login.oauth2InvalidTokenResponse=Risposta token non valida
|
login.oauth2InvalidTokenResponse=Risposta token non valida
|
||||||
|
login.oauth2InvalidIdToken=Id Token non valido
|
||||||
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
@ -654,6 +659,13 @@ certSign.name=Nome
|
|||||||
certSign.submit=Firma PDF
|
certSign.submit=Firma PDF
|
||||||
|
|
||||||
|
|
||||||
|
#removeCertSign
|
||||||
|
removeCertSign.title=Rimuovi certificato della firma
|
||||||
|
removeCertSign.header=Rimuovere il certificato digitale dal PDF
|
||||||
|
removeCertSign.selectPDF=Seleziona un file PDF:
|
||||||
|
removeCertSign.submit=Rimuovi firma
|
||||||
|
|
||||||
|
|
||||||
#removeBlanks
|
#removeBlanks
|
||||||
removeBlanks.title=Rimuovi spazi vuoti
|
removeBlanks.title=Rimuovi spazi vuoti
|
||||||
removeBlanks.header=Rimuovi pagine vuote
|
removeBlanks.header=Rimuovi pagine vuote
|
||||||
@ -964,6 +976,7 @@ pdfToPDFA.credit=Questo servizio utilizza OCRmyPDF per la conversione in PDF/A.
|
|||||||
pdfToPDFA.submit=Converti
|
pdfToPDFA.submit=Converti
|
||||||
pdfToPDFA.tip=Attualmente non funziona per più input contemporaneamente
|
pdfToPDFA.tip=Attualmente non funziona per più input contemporaneamente
|
||||||
pdfToPDFA.outputFormat=Formato di output
|
pdfToPDFA.outputFormat=Formato di output
|
||||||
|
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
|
||||||
|
|
||||||
|
|
||||||
#PDFToWord
|
#PDFToWord
|
||||||
|
@ -332,6 +332,10 @@ home.certSign.title=証明書による署名
|
|||||||
home.certSign.desc=証明書/キーを使用してPDFに署名します。 (PEM/P12)
|
home.certSign.desc=証明書/キーを使用してPDFに署名します。 (PEM/P12)
|
||||||
certSign.tags=authenticate,PEM,P12,official,encrypt
|
certSign.tags=authenticate,PEM,P12,official,encrypt
|
||||||
|
|
||||||
|
home.removeCertSign.title=Remove Certificate Sign
|
||||||
|
home.removeCertSign.desc=Remove certificate signature from PDF
|
||||||
|
removeCertSign.tags=authenticate,PEM,P12,official,decrypt
|
||||||
|
|
||||||
home.pageLayout.title=マルチページレイアウト
|
home.pageLayout.title=マルチページレイアウト
|
||||||
home.pageLayout.desc=PDFの複数のページを1ページに結合します。
|
home.pageLayout.desc=PDFの複数のページを1ページに結合します。
|
||||||
pageLayout.tags=merge,composite,single-view,organize
|
pageLayout.tags=merge,composite,single-view,organize
|
||||||
@ -457,6 +461,7 @@ login.oauth2InvalidUserInfoResponse=Invalid User Info Response
|
|||||||
login.oauth2invalidRequest=Invalid Request
|
login.oauth2invalidRequest=Invalid Request
|
||||||
login.oauth2AccessDenied=Access Denied
|
login.oauth2AccessDenied=Access Denied
|
||||||
login.oauth2InvalidTokenResponse=Invalid Token Response
|
login.oauth2InvalidTokenResponse=Invalid Token Response
|
||||||
|
login.oauth2InvalidIdToken=Invalid Id Token
|
||||||
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
@ -654,6 +659,13 @@ certSign.name=名前
|
|||||||
certSign.submit=PDFに署名
|
certSign.submit=PDFに署名
|
||||||
|
|
||||||
|
|
||||||
|
#removeCertSign
|
||||||
|
removeCertSign.title=Remove Certificate Signature
|
||||||
|
removeCertSign.header=Remove the digital certificate from the PDF
|
||||||
|
removeCertSign.selectPDF=Select a PDF file:
|
||||||
|
removeCertSign.submit=Remove Signature
|
||||||
|
|
||||||
|
|
||||||
#removeBlanks
|
#removeBlanks
|
||||||
removeBlanks.title=空白の削除
|
removeBlanks.title=空白の削除
|
||||||
removeBlanks.header=空白ページの削除
|
removeBlanks.header=空白ページの削除
|
||||||
@ -964,6 +976,7 @@ pdfToPDFA.credit=本サービスはPDF/Aの変換にOCRmyPDFを使用してい
|
|||||||
pdfToPDFA.submit=変換
|
pdfToPDFA.submit=変換
|
||||||
pdfToPDFA.tip=現在、一度に複数の入力に対して機能しません
|
pdfToPDFA.tip=現在、一度に複数の入力に対して機能しません
|
||||||
pdfToPDFA.outputFormat=Output format
|
pdfToPDFA.outputFormat=Output format
|
||||||
|
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
|
||||||
|
|
||||||
|
|
||||||
#PDFToWord
|
#PDFToWord
|
||||||
|
@ -332,6 +332,10 @@ home.certSign.title=인증서로 서명
|
|||||||
home.certSign.desc=PDF 문서에 인증서 또는 키로 서명합니다. (PEM/P12)
|
home.certSign.desc=PDF 문서에 인증서 또는 키로 서명합니다. (PEM/P12)
|
||||||
certSign.tags=authenticate,PEM,P12,official,encrypt
|
certSign.tags=authenticate,PEM,P12,official,encrypt
|
||||||
|
|
||||||
|
home.removeCertSign.title=Remove Certificate Sign
|
||||||
|
home.removeCertSign.desc=Remove certificate signature from PDF
|
||||||
|
removeCertSign.tags=authenticate,PEM,P12,official,decrypt
|
||||||
|
|
||||||
home.pageLayout.title=다중 페이지 레이아웃
|
home.pageLayout.title=다중 페이지 레이아웃
|
||||||
home.pageLayout.desc=PDF 문서의 여러 페이지를 한 페이지로 합칩니다.
|
home.pageLayout.desc=PDF 문서의 여러 페이지를 한 페이지로 합칩니다.
|
||||||
pageLayout.tags=merge,composite,single-view,organize
|
pageLayout.tags=merge,composite,single-view,organize
|
||||||
@ -457,6 +461,7 @@ login.oauth2InvalidUserInfoResponse=Invalid User Info Response
|
|||||||
login.oauth2invalidRequest=Invalid Request
|
login.oauth2invalidRequest=Invalid Request
|
||||||
login.oauth2AccessDenied=Access Denied
|
login.oauth2AccessDenied=Access Denied
|
||||||
login.oauth2InvalidTokenResponse=Invalid Token Response
|
login.oauth2InvalidTokenResponse=Invalid Token Response
|
||||||
|
login.oauth2InvalidIdToken=Invalid Id Token
|
||||||
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
@ -654,6 +659,13 @@ certSign.name=이름
|
|||||||
certSign.submit=PDF 서명
|
certSign.submit=PDF 서명
|
||||||
|
|
||||||
|
|
||||||
|
#removeCertSign
|
||||||
|
removeCertSign.title=Remove Certificate Signature
|
||||||
|
removeCertSign.header=Remove the digital certificate from the PDF
|
||||||
|
removeCertSign.selectPDF=Select a PDF file:
|
||||||
|
removeCertSign.submit=Remove Signature
|
||||||
|
|
||||||
|
|
||||||
#removeBlanks
|
#removeBlanks
|
||||||
removeBlanks.title=빈 페이지 제거
|
removeBlanks.title=빈 페이지 제거
|
||||||
removeBlanks.header=빈 페이지 제거
|
removeBlanks.header=빈 페이지 제거
|
||||||
@ -964,6 +976,7 @@ pdfToPDFA.credit=이 서비스는 PDF/A 변환을 위해 OCRmyPDF 문서를 사
|
|||||||
pdfToPDFA.submit=변환
|
pdfToPDFA.submit=변환
|
||||||
pdfToPDFA.tip=현재 한 번에 여러 입력에 대해 작동하지 않습니다.
|
pdfToPDFA.tip=현재 한 번에 여러 입력에 대해 작동하지 않습니다.
|
||||||
pdfToPDFA.outputFormat=Output format
|
pdfToPDFA.outputFormat=Output format
|
||||||
|
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
|
||||||
|
|
||||||
|
|
||||||
#PDFToWord
|
#PDFToWord
|
||||||
|
@ -332,6 +332,10 @@ home.certSign.title=Ondertekenen met certificaat
|
|||||||
home.certSign.desc=Ondertekent een PDF met een certificaat/sleutel (PEM/P12)
|
home.certSign.desc=Ondertekent een PDF met een certificaat/sleutel (PEM/P12)
|
||||||
certSign.tags=authenticeren,PEM,P12,officieel,versleutelen
|
certSign.tags=authenticeren,PEM,P12,officieel,versleutelen
|
||||||
|
|
||||||
|
home.removeCertSign.title=Remove Certificate Sign
|
||||||
|
home.removeCertSign.desc=Remove certificate signature from PDF
|
||||||
|
removeCertSign.tags=authenticate,PEM,P12,official,decrypt
|
||||||
|
|
||||||
home.pageLayout.title=Multi-pagina indeling
|
home.pageLayout.title=Multi-pagina indeling
|
||||||
home.pageLayout.desc=Voeg meerdere pagina's van een PDF-document samen op één pagina
|
home.pageLayout.desc=Voeg meerdere pagina's van een PDF-document samen op één pagina
|
||||||
pageLayout.tags=samenvoegen,composiet,enkel-zicht,organiseren
|
pageLayout.tags=samenvoegen,composiet,enkel-zicht,organiseren
|
||||||
@ -457,6 +461,7 @@ login.oauth2InvalidUserInfoResponse=Invalid User Info Response
|
|||||||
login.oauth2invalidRequest=Invalid Request
|
login.oauth2invalidRequest=Invalid Request
|
||||||
login.oauth2AccessDenied=Access Denied
|
login.oauth2AccessDenied=Access Denied
|
||||||
login.oauth2InvalidTokenResponse=Invalid Token Response
|
login.oauth2InvalidTokenResponse=Invalid Token Response
|
||||||
|
login.oauth2InvalidIdToken=Invalid Id Token
|
||||||
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
@ -654,6 +659,13 @@ certSign.name=Naam
|
|||||||
certSign.submit=PDF ondertekenen
|
certSign.submit=PDF ondertekenen
|
||||||
|
|
||||||
|
|
||||||
|
#removeCertSign
|
||||||
|
removeCertSign.title=Remove Certificate Signature
|
||||||
|
removeCertSign.header=Remove the digital certificate from the PDF
|
||||||
|
removeCertSign.selectPDF=Select a PDF file:
|
||||||
|
removeCertSign.submit=Remove Signature
|
||||||
|
|
||||||
|
|
||||||
#removeBlanks
|
#removeBlanks
|
||||||
removeBlanks.title=Verwijder blanco's
|
removeBlanks.title=Verwijder blanco's
|
||||||
removeBlanks.header=Verwijder lege pagina's
|
removeBlanks.header=Verwijder lege pagina's
|
||||||
@ -964,6 +976,7 @@ pdfToPDFA.credit=Deze service gebruikt OCRmyPDF voor PDF/A-conversie
|
|||||||
pdfToPDFA.submit=Converteren
|
pdfToPDFA.submit=Converteren
|
||||||
pdfToPDFA.tip=Currently does not work for multiple inputs at once
|
pdfToPDFA.tip=Currently does not work for multiple inputs at once
|
||||||
pdfToPDFA.outputFormat=Output format
|
pdfToPDFA.outputFormat=Output format
|
||||||
|
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
|
||||||
|
|
||||||
|
|
||||||
#PDFToWord
|
#PDFToWord
|
||||||
|
1093
src/main/resources/messages_no_NB.properties
Normal file
1093
src/main/resources/messages_no_NB.properties
Normal file
File diff suppressed because it is too large
Load Diff
@ -332,6 +332,10 @@ home.certSign.title=Podpisz certyfikatem
|
|||||||
home.certSign.desc=Podpisz dokument PDF za pomocą certyfikatu/klucza prywatnego (PEM/P12)
|
home.certSign.desc=Podpisz dokument PDF za pomocą certyfikatu/klucza prywatnego (PEM/P12)
|
||||||
certSign.tags=authenticate,PEM,P12,official,encrypt
|
certSign.tags=authenticate,PEM,P12,official,encrypt
|
||||||
|
|
||||||
|
home.removeCertSign.title=Remove Certificate Sign
|
||||||
|
home.removeCertSign.desc=Remove certificate signature from PDF
|
||||||
|
removeCertSign.tags=authenticate,PEM,P12,official,decrypt
|
||||||
|
|
||||||
home.pageLayout.title=Układ wielu stron
|
home.pageLayout.title=Układ wielu stron
|
||||||
home.pageLayout.desc=Scal wiele stron dokumentu PDF w jedną stronę
|
home.pageLayout.desc=Scal wiele stron dokumentu PDF w jedną stronę
|
||||||
pageLayout.tags=merge,composite,single-view,organize
|
pageLayout.tags=merge,composite,single-view,organize
|
||||||
@ -457,6 +461,7 @@ login.oauth2InvalidUserInfoResponse=Invalid User Info Response
|
|||||||
login.oauth2invalidRequest=Invalid Request
|
login.oauth2invalidRequest=Invalid Request
|
||||||
login.oauth2AccessDenied=Access Denied
|
login.oauth2AccessDenied=Access Denied
|
||||||
login.oauth2InvalidTokenResponse=Invalid Token Response
|
login.oauth2InvalidTokenResponse=Invalid Token Response
|
||||||
|
login.oauth2InvalidIdToken=Invalid Id Token
|
||||||
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
@ -654,6 +659,13 @@ certSign.name=Nazwa
|
|||||||
certSign.submit=Podpisz PDF
|
certSign.submit=Podpisz PDF
|
||||||
|
|
||||||
|
|
||||||
|
#removeCertSign
|
||||||
|
removeCertSign.title=Remove Certificate Signature
|
||||||
|
removeCertSign.header=Remove the digital certificate from the PDF
|
||||||
|
removeCertSign.selectPDF=Select a PDF file:
|
||||||
|
removeCertSign.submit=Remove Signature
|
||||||
|
|
||||||
|
|
||||||
#removeBlanks
|
#removeBlanks
|
||||||
removeBlanks.title=Usuń puste
|
removeBlanks.title=Usuń puste
|
||||||
removeBlanks.header=Usuń puste strony
|
removeBlanks.header=Usuń puste strony
|
||||||
@ -964,6 +976,7 @@ pdfToPDFA.credit=Ta usługa używa OCRmyPDF do konwersji PDF/A
|
|||||||
pdfToPDFA.submit=Konwertuj
|
pdfToPDFA.submit=Konwertuj
|
||||||
pdfToPDFA.tip=Currently does not work for multiple inputs at once
|
pdfToPDFA.tip=Currently does not work for multiple inputs at once
|
||||||
pdfToPDFA.outputFormat=Output format
|
pdfToPDFA.outputFormat=Output format
|
||||||
|
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
|
||||||
|
|
||||||
|
|
||||||
#PDFToWord
|
#PDFToWord
|
||||||
|
@ -332,6 +332,10 @@ home.certSign.title=Assinar com Certificado
|
|||||||
home.certSign.desc=Assinar um PDF com um Certificado/Chave (PEM/P12)
|
home.certSign.desc=Assinar um PDF com um Certificado/Chave (PEM/P12)
|
||||||
certSign.tags=autenticar,PEM,P12,oficial,criptografar
|
certSign.tags=autenticar,PEM,P12,oficial,criptografar
|
||||||
|
|
||||||
|
home.removeCertSign.title=Remove Certificate Sign
|
||||||
|
home.removeCertSign.desc=Remove certificate signature from PDF
|
||||||
|
removeCertSign.tags=authenticate,PEM,P12,official,decrypt
|
||||||
|
|
||||||
home.pageLayout.title=Layout de Múltiplas Páginas
|
home.pageLayout.title=Layout de Múltiplas Páginas
|
||||||
home.pageLayout.desc=Mesclar várias páginas de um documento PDF em uma única página
|
home.pageLayout.desc=Mesclar várias páginas de um documento PDF em uma única página
|
||||||
pageLayout.tags=mesclar,composto,vista-única,organizar
|
pageLayout.tags=mesclar,composto,vista-única,organizar
|
||||||
@ -457,6 +461,7 @@ login.oauth2InvalidUserInfoResponse=Invalid User Info Response
|
|||||||
login.oauth2invalidRequest=Invalid Request
|
login.oauth2invalidRequest=Invalid Request
|
||||||
login.oauth2AccessDenied=Access Denied
|
login.oauth2AccessDenied=Access Denied
|
||||||
login.oauth2InvalidTokenResponse=Invalid Token Response
|
login.oauth2InvalidTokenResponse=Invalid Token Response
|
||||||
|
login.oauth2InvalidIdToken=Invalid Id Token
|
||||||
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
@ -654,6 +659,13 @@ certSign.name=Nome
|
|||||||
certSign.submit=Assinar PDF
|
certSign.submit=Assinar PDF
|
||||||
|
|
||||||
|
|
||||||
|
#removeCertSign
|
||||||
|
removeCertSign.title=Remove Certificate Signature
|
||||||
|
removeCertSign.header=Remove the digital certificate from the PDF
|
||||||
|
removeCertSign.selectPDF=Select a PDF file:
|
||||||
|
removeCertSign.submit=Remove Signature
|
||||||
|
|
||||||
|
|
||||||
#removeBlanks
|
#removeBlanks
|
||||||
removeBlanks.title=Remover Páginas em Branco
|
removeBlanks.title=Remover Páginas em Branco
|
||||||
removeBlanks.header=Remover Páginas em Branco
|
removeBlanks.header=Remover Páginas em Branco
|
||||||
@ -964,6 +976,7 @@ pdfToPDFA.credit=Este serviço usa OCRmyPDF para Conversão de PDF/A
|
|||||||
pdfToPDFA.submit=Converter
|
pdfToPDFA.submit=Converter
|
||||||
pdfToPDFA.tip=Currently does not work for multiple inputs at once
|
pdfToPDFA.tip=Currently does not work for multiple inputs at once
|
||||||
pdfToPDFA.outputFormat=Output format
|
pdfToPDFA.outputFormat=Output format
|
||||||
|
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
|
||||||
|
|
||||||
|
|
||||||
#PDFToWord
|
#PDFToWord
|
||||||
|
@ -332,6 +332,10 @@ home.certSign.title=Assinar com Certificado
|
|||||||
home.certSign.desc=Assinar um PDF com um Certificado/Chave (PEM/P12)
|
home.certSign.desc=Assinar um PDF com um Certificado/Chave (PEM/P12)
|
||||||
certSign.tags=autenticar,PEM,P12,oficial,criptografar
|
certSign.tags=autenticar,PEM,P12,oficial,criptografar
|
||||||
|
|
||||||
|
home.removeCertSign.title=Remove Certificate Sign
|
||||||
|
home.removeCertSign.desc=Remove certificate signature from PDF
|
||||||
|
removeCertSign.tags=authenticate,PEM,P12,official,decrypt
|
||||||
|
|
||||||
home.pageLayout.title=Layout de Múltiplas Páginas
|
home.pageLayout.title=Layout de Múltiplas Páginas
|
||||||
home.pageLayout.desc=Juntar várias páginas de um documento PDF em uma única página
|
home.pageLayout.desc=Juntar várias páginas de um documento PDF em uma única página
|
||||||
pageLayout.tags=juntar,composto,vista-única,organizar
|
pageLayout.tags=juntar,composto,vista-única,organizar
|
||||||
@ -457,6 +461,7 @@ login.oauth2InvalidUserInfoResponse=Invalid User Info Response
|
|||||||
login.oauth2invalidRequest=Invalid Request
|
login.oauth2invalidRequest=Invalid Request
|
||||||
login.oauth2AccessDenied=Access Denied
|
login.oauth2AccessDenied=Access Denied
|
||||||
login.oauth2InvalidTokenResponse=Invalid Token Response
|
login.oauth2InvalidTokenResponse=Invalid Token Response
|
||||||
|
login.oauth2InvalidIdToken=Invalid Id Token
|
||||||
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
@ -654,6 +659,13 @@ certSign.name=Nome
|
|||||||
certSign.submit=Assinar PDF
|
certSign.submit=Assinar PDF
|
||||||
|
|
||||||
|
|
||||||
|
#removeCertSign
|
||||||
|
removeCertSign.title=Remove Certificate Signature
|
||||||
|
removeCertSign.header=Remove the digital certificate from the PDF
|
||||||
|
removeCertSign.selectPDF=Select a PDF file:
|
||||||
|
removeCertSign.submit=Remove Signature
|
||||||
|
|
||||||
|
|
||||||
#removeBlanks
|
#removeBlanks
|
||||||
removeBlanks.title=Remover Páginas em Branco
|
removeBlanks.title=Remover Páginas em Branco
|
||||||
removeBlanks.header=Remover Páginas em Branco
|
removeBlanks.header=Remover Páginas em Branco
|
||||||
@ -964,6 +976,7 @@ pdfToPDFA.credit=Este serviço usa OCRmyPDF para Conversão de PDF/A
|
|||||||
pdfToPDFA.submit=Converter
|
pdfToPDFA.submit=Converter
|
||||||
pdfToPDFA.tip=Currently does not work for multiple inputs at once
|
pdfToPDFA.tip=Currently does not work for multiple inputs at once
|
||||||
pdfToPDFA.outputFormat=Output format
|
pdfToPDFA.outputFormat=Output format
|
||||||
|
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
|
||||||
|
|
||||||
|
|
||||||
#PDFToWord
|
#PDFToWord
|
||||||
|
@ -332,6 +332,10 @@ home.certSign.title=Semnare cu certificat
|
|||||||
home.certSign.desc=Semnează un PDF cu un certificat/cheie (PEM/P12)
|
home.certSign.desc=Semnează un PDF cu un certificat/cheie (PEM/P12)
|
||||||
certSign.tags=authenticate,PEM,P12,official,encrypt
|
certSign.tags=authenticate,PEM,P12,official,encrypt
|
||||||
|
|
||||||
|
home.removeCertSign.title=Remove Certificate Sign
|
||||||
|
home.removeCertSign.desc=Remove certificate signature from PDF
|
||||||
|
removeCertSign.tags=authenticate,PEM,P12,official,decrypt
|
||||||
|
|
||||||
home.pageLayout.title=Multi-Page Layout
|
home.pageLayout.title=Multi-Page Layout
|
||||||
home.pageLayout.desc=Merge multiple pages of a PDF document into a single page
|
home.pageLayout.desc=Merge multiple pages of a PDF document into a single page
|
||||||
pageLayout.tags=merge,composite,single-view,organize
|
pageLayout.tags=merge,composite,single-view,organize
|
||||||
@ -457,6 +461,7 @@ login.oauth2InvalidUserInfoResponse=Invalid User Info Response
|
|||||||
login.oauth2invalidRequest=Invalid Request
|
login.oauth2invalidRequest=Invalid Request
|
||||||
login.oauth2AccessDenied=Access Denied
|
login.oauth2AccessDenied=Access Denied
|
||||||
login.oauth2InvalidTokenResponse=Invalid Token Response
|
login.oauth2InvalidTokenResponse=Invalid Token Response
|
||||||
|
login.oauth2InvalidIdToken=Invalid Id Token
|
||||||
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
@ -654,6 +659,13 @@ certSign.name=Numele
|
|||||||
certSign.submit=Semnează PDF
|
certSign.submit=Semnează PDF
|
||||||
|
|
||||||
|
|
||||||
|
#removeCertSign
|
||||||
|
removeCertSign.title=Remove Certificate Signature
|
||||||
|
removeCertSign.header=Remove the digital certificate from the PDF
|
||||||
|
removeCertSign.selectPDF=Select a PDF file:
|
||||||
|
removeCertSign.submit=Remove Signature
|
||||||
|
|
||||||
|
|
||||||
#removeBlanks
|
#removeBlanks
|
||||||
removeBlanks.title=Elimină pagini goale
|
removeBlanks.title=Elimină pagini goale
|
||||||
removeBlanks.header=Elimină pagini goale
|
removeBlanks.header=Elimină pagini goale
|
||||||
@ -964,6 +976,7 @@ pdfToPDFA.credit=Acest serviciu utilizează OCRmyPDF pentru conversia în PDF/A
|
|||||||
pdfToPDFA.submit=Convert
|
pdfToPDFA.submit=Convert
|
||||||
pdfToPDFA.tip=Currently does not work for multiple inputs at once
|
pdfToPDFA.tip=Currently does not work for multiple inputs at once
|
||||||
pdfToPDFA.outputFormat=Output format
|
pdfToPDFA.outputFormat=Output format
|
||||||
|
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
|
||||||
|
|
||||||
|
|
||||||
#PDFToWord
|
#PDFToWord
|
||||||
|
@ -332,6 +332,10 @@ home.certSign.title=Подписать сертификатом
|
|||||||
home.certSign.desc=Подписать PDF сертификатом/ключом (PEM/P12)
|
home.certSign.desc=Подписать PDF сертификатом/ключом (PEM/P12)
|
||||||
certSign.tags=authenticate,PEM,P12,official,encrypt
|
certSign.tags=authenticate,PEM,P12,official,encrypt
|
||||||
|
|
||||||
|
home.removeCertSign.title=Remove Certificate Sign
|
||||||
|
home.removeCertSign.desc=Remove certificate signature from PDF
|
||||||
|
removeCertSign.tags=authenticate,PEM,P12,official,decrypt
|
||||||
|
|
||||||
home.pageLayout.title=Объединить страницы
|
home.pageLayout.title=Объединить страницы
|
||||||
home.pageLayout.desc=Объединение нескольких страниц документа PDF в одну страницу
|
home.pageLayout.desc=Объединение нескольких страниц документа PDF в одну страницу
|
||||||
pageLayout.tags=merge,composite,single-view,organize
|
pageLayout.tags=merge,composite,single-view,organize
|
||||||
@ -457,6 +461,7 @@ login.oauth2InvalidUserInfoResponse=Invalid User Info Response
|
|||||||
login.oauth2invalidRequest=Invalid Request
|
login.oauth2invalidRequest=Invalid Request
|
||||||
login.oauth2AccessDenied=Access Denied
|
login.oauth2AccessDenied=Access Denied
|
||||||
login.oauth2InvalidTokenResponse=Invalid Token Response
|
login.oauth2InvalidTokenResponse=Invalid Token Response
|
||||||
|
login.oauth2InvalidIdToken=Invalid Id Token
|
||||||
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
@ -654,6 +659,13 @@ certSign.name=Имя
|
|||||||
certSign.submit=Подписать PDF
|
certSign.submit=Подписать PDF
|
||||||
|
|
||||||
|
|
||||||
|
#removeCertSign
|
||||||
|
removeCertSign.title=Remove Certificate Signature
|
||||||
|
removeCertSign.header=Remove the digital certificate from the PDF
|
||||||
|
removeCertSign.selectPDF=Select a PDF file:
|
||||||
|
removeCertSign.submit=Remove Signature
|
||||||
|
|
||||||
|
|
||||||
#removeBlanks
|
#removeBlanks
|
||||||
removeBlanks.title=Удалить Пустые
|
removeBlanks.title=Удалить Пустые
|
||||||
removeBlanks.header=Удалить Пустые Страницы
|
removeBlanks.header=Удалить Пустые Страницы
|
||||||
@ -964,6 +976,7 @@ pdfToPDFA.credit=Этот сервис использует OCRmyPDF для пр
|
|||||||
pdfToPDFA.submit=Конвертировать
|
pdfToPDFA.submit=Конвертировать
|
||||||
pdfToPDFA.tip=Currently does not work for multiple inputs at once
|
pdfToPDFA.tip=Currently does not work for multiple inputs at once
|
||||||
pdfToPDFA.outputFormat=Output format
|
pdfToPDFA.outputFormat=Output format
|
||||||
|
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
|
||||||
|
|
||||||
|
|
||||||
#PDFToWord
|
#PDFToWord
|
||||||
|
@ -332,6 +332,10 @@ home.certSign.title=Podpísať s certifikátom
|
|||||||
home.certSign.desc=Podpísať PDF s certifikátom/kľúčom (PEM/P12)
|
home.certSign.desc=Podpísať PDF s certifikátom/kľúčom (PEM/P12)
|
||||||
certSign.tags=autentifikovať,PEM,P12,oficiálne,šifrovať
|
certSign.tags=autentifikovať,PEM,P12,oficiálne,šifrovať
|
||||||
|
|
||||||
|
home.removeCertSign.title=Remove Certificate Sign
|
||||||
|
home.removeCertSign.desc=Remove certificate signature from PDF
|
||||||
|
removeCertSign.tags=authenticate,PEM,P12,official,decrypt
|
||||||
|
|
||||||
home.pageLayout.title=Viacstranové usporiadanie
|
home.pageLayout.title=Viacstranové usporiadanie
|
||||||
home.pageLayout.desc=Zlúčte viacero stránok PDF dokumentu do jednej stránky
|
home.pageLayout.desc=Zlúčte viacero stránok PDF dokumentu do jednej stránky
|
||||||
pageLayout.tags=zlúčiť,zjednotiť,jednostranový pohľad,organizovať
|
pageLayout.tags=zlúčiť,zjednotiť,jednostranový pohľad,organizovať
|
||||||
@ -457,6 +461,7 @@ login.oauth2InvalidUserInfoResponse=Invalid User Info Response
|
|||||||
login.oauth2invalidRequest=Invalid Request
|
login.oauth2invalidRequest=Invalid Request
|
||||||
login.oauth2AccessDenied=Access Denied
|
login.oauth2AccessDenied=Access Denied
|
||||||
login.oauth2InvalidTokenResponse=Invalid Token Response
|
login.oauth2InvalidTokenResponse=Invalid Token Response
|
||||||
|
login.oauth2InvalidIdToken=Invalid Id Token
|
||||||
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
@ -654,6 +659,13 @@ certSign.name=Meno
|
|||||||
certSign.submit=Podpísať PDF
|
certSign.submit=Podpísať PDF
|
||||||
|
|
||||||
|
|
||||||
|
#removeCertSign
|
||||||
|
removeCertSign.title=Remove Certificate Signature
|
||||||
|
removeCertSign.header=Remove the digital certificate from the PDF
|
||||||
|
removeCertSign.selectPDF=Select a PDF file:
|
||||||
|
removeCertSign.submit=Remove Signature
|
||||||
|
|
||||||
|
|
||||||
#removeBlanks
|
#removeBlanks
|
||||||
removeBlanks.title=Odstrániť prázdne stránky
|
removeBlanks.title=Odstrániť prázdne stránky
|
||||||
removeBlanks.header=Odstrániť prázdne stránky
|
removeBlanks.header=Odstrániť prázdne stránky
|
||||||
@ -964,6 +976,7 @@ pdfToPDFA.credit=Táto služba používa OCRmyPDF na konverziu PDF/A
|
|||||||
pdfToPDFA.submit=Konvertovať
|
pdfToPDFA.submit=Konvertovať
|
||||||
pdfToPDFA.tip=Momentálne nefunguje pre viacero vstupov naraz
|
pdfToPDFA.tip=Momentálne nefunguje pre viacero vstupov naraz
|
||||||
pdfToPDFA.outputFormat=Výstupný formát
|
pdfToPDFA.outputFormat=Výstupný formát
|
||||||
|
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
|
||||||
|
|
||||||
|
|
||||||
#PDFToWord
|
#PDFToWord
|
||||||
|
@ -332,6 +332,10 @@ home.certSign.title=Potpis sa sertifikatom
|
|||||||
home.certSign.desc=Potpisuje PDF sa sertifikatom/ključem (PEM/P12)
|
home.certSign.desc=Potpisuje PDF sa sertifikatom/ključem (PEM/P12)
|
||||||
certSign.tags=autentifikacija,PEM,P12,zvanično,šifrovanje
|
certSign.tags=autentifikacija,PEM,P12,zvanično,šifrovanje
|
||||||
|
|
||||||
|
home.removeCertSign.title=Remove Certificate Sign
|
||||||
|
home.removeCertSign.desc=Remove certificate signature from PDF
|
||||||
|
removeCertSign.tags=authenticate,PEM,P12,official,decrypt
|
||||||
|
|
||||||
home.pageLayout.title=Višestruki prikaz stranica
|
home.pageLayout.title=Višestruki prikaz stranica
|
||||||
home.pageLayout.desc=Spaja više stranica PDF dokumenta u jednu stranicu
|
home.pageLayout.desc=Spaja više stranica PDF dokumenta u jednu stranicu
|
||||||
pageLayout.tags=spajanje,kompozit,pojedinačan-prikaz,organizacija
|
pageLayout.tags=spajanje,kompozit,pojedinačan-prikaz,organizacija
|
||||||
@ -457,6 +461,7 @@ login.oauth2InvalidUserInfoResponse=Invalid User Info Response
|
|||||||
login.oauth2invalidRequest=Invalid Request
|
login.oauth2invalidRequest=Invalid Request
|
||||||
login.oauth2AccessDenied=Access Denied
|
login.oauth2AccessDenied=Access Denied
|
||||||
login.oauth2InvalidTokenResponse=Invalid Token Response
|
login.oauth2InvalidTokenResponse=Invalid Token Response
|
||||||
|
login.oauth2InvalidIdToken=Invalid Id Token
|
||||||
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
@ -654,6 +659,13 @@ certSign.name=Ime
|
|||||||
certSign.submit=Potpiši PDF
|
certSign.submit=Potpiši PDF
|
||||||
|
|
||||||
|
|
||||||
|
#removeCertSign
|
||||||
|
removeCertSign.title=Remove Certificate Signature
|
||||||
|
removeCertSign.header=Remove the digital certificate from the PDF
|
||||||
|
removeCertSign.selectPDF=Select a PDF file:
|
||||||
|
removeCertSign.submit=Remove Signature
|
||||||
|
|
||||||
|
|
||||||
#removeBlanks
|
#removeBlanks
|
||||||
removeBlanks.title=Ukloni prazne stranice
|
removeBlanks.title=Ukloni prazne stranice
|
||||||
removeBlanks.header=Ukloni prazne stranice
|
removeBlanks.header=Ukloni prazne stranice
|
||||||
@ -964,6 +976,7 @@ pdfToPDFA.credit=Ova usluga koristi OCRmyPDF za konverziju u PDF/A format
|
|||||||
pdfToPDFA.submit=Konvertuj
|
pdfToPDFA.submit=Konvertuj
|
||||||
pdfToPDFA.tip=Currently does not work for multiple inputs at once
|
pdfToPDFA.tip=Currently does not work for multiple inputs at once
|
||||||
pdfToPDFA.outputFormat=Output format
|
pdfToPDFA.outputFormat=Output format
|
||||||
|
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
|
||||||
|
|
||||||
|
|
||||||
#PDFToWord
|
#PDFToWord
|
||||||
|
@ -332,6 +332,10 @@ home.certSign.title=Sign with Certificate
|
|||||||
home.certSign.desc=Signs a PDF with a Certificate/Key (PEM/P12)
|
home.certSign.desc=Signs a PDF with a Certificate/Key (PEM/P12)
|
||||||
certSign.tags=authenticate,PEM,P12,official,encrypt
|
certSign.tags=authenticate,PEM,P12,official,encrypt
|
||||||
|
|
||||||
|
home.removeCertSign.title=Remove Certificate Sign
|
||||||
|
home.removeCertSign.desc=Remove certificate signature from PDF
|
||||||
|
removeCertSign.tags=authenticate,PEM,P12,official,decrypt
|
||||||
|
|
||||||
home.pageLayout.title=Multi-Page Layout
|
home.pageLayout.title=Multi-Page Layout
|
||||||
home.pageLayout.desc=Merge multiple pages of a PDF document into a single page
|
home.pageLayout.desc=Merge multiple pages of a PDF document into a single page
|
||||||
pageLayout.tags=merge,composite,single-view,organize
|
pageLayout.tags=merge,composite,single-view,organize
|
||||||
@ -457,6 +461,7 @@ login.oauth2InvalidUserInfoResponse=Invalid User Info Response
|
|||||||
login.oauth2invalidRequest=Invalid Request
|
login.oauth2invalidRequest=Invalid Request
|
||||||
login.oauth2AccessDenied=Access Denied
|
login.oauth2AccessDenied=Access Denied
|
||||||
login.oauth2InvalidTokenResponse=Invalid Token Response
|
login.oauth2InvalidTokenResponse=Invalid Token Response
|
||||||
|
login.oauth2InvalidIdToken=Invalid Id Token
|
||||||
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
@ -654,6 +659,13 @@ certSign.name=Namn
|
|||||||
certSign.submit=Skriv under PDF
|
certSign.submit=Skriv under PDF
|
||||||
|
|
||||||
|
|
||||||
|
#removeCertSign
|
||||||
|
removeCertSign.title=Remove Certificate Signature
|
||||||
|
removeCertSign.header=Remove the digital certificate from the PDF
|
||||||
|
removeCertSign.selectPDF=Select a PDF file:
|
||||||
|
removeCertSign.submit=Remove Signature
|
||||||
|
|
||||||
|
|
||||||
#removeBlanks
|
#removeBlanks
|
||||||
removeBlanks.title=Ta bort tomrum
|
removeBlanks.title=Ta bort tomrum
|
||||||
removeBlanks.header=Ta bort tomma sidor
|
removeBlanks.header=Ta bort tomma sidor
|
||||||
@ -964,6 +976,7 @@ pdfToPDFA.credit=Denna tjänst använder OCRmyPDF för PDF/A-konvertering
|
|||||||
pdfToPDFA.submit=Konvertera
|
pdfToPDFA.submit=Konvertera
|
||||||
pdfToPDFA.tip=Currently does not work for multiple inputs at once
|
pdfToPDFA.tip=Currently does not work for multiple inputs at once
|
||||||
pdfToPDFA.outputFormat=Output format
|
pdfToPDFA.outputFormat=Output format
|
||||||
|
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
|
||||||
|
|
||||||
|
|
||||||
#PDFToWord
|
#PDFToWord
|
||||||
|
@ -332,6 +332,10 @@ home.certSign.title=Sertifika ile İmzala
|
|||||||
home.certSign.desc=Bir PDF'i Sertifika/Anahtar (PEM/P12) ile imzalar
|
home.certSign.desc=Bir PDF'i Sertifika/Anahtar (PEM/P12) ile imzalar
|
||||||
certSign.tags=doğrula,PEM,P12,resmi,şifrele
|
certSign.tags=doğrula,PEM,P12,resmi,şifrele
|
||||||
|
|
||||||
|
home.removeCertSign.title=Remove Certificate Sign
|
||||||
|
home.removeCertSign.desc=Remove certificate signature from PDF
|
||||||
|
removeCertSign.tags=authenticate,PEM,P12,official,decrypt
|
||||||
|
|
||||||
home.pageLayout.title=Çoklu-Sayfa Düzeni
|
home.pageLayout.title=Çoklu-Sayfa Düzeni
|
||||||
home.pageLayout.desc=Bir PDF belgesinin çoklu sayfalarını tek bir sayfada birleştirir
|
home.pageLayout.desc=Bir PDF belgesinin çoklu sayfalarını tek bir sayfada birleştirir
|
||||||
pageLayout.tags=birleştir,kompozit,tek-görünüm,düzenle
|
pageLayout.tags=birleştir,kompozit,tek-görünüm,düzenle
|
||||||
@ -457,6 +461,7 @@ login.oauth2InvalidUserInfoResponse=Invalid User Info Response
|
|||||||
login.oauth2invalidRequest=Invalid Request
|
login.oauth2invalidRequest=Invalid Request
|
||||||
login.oauth2AccessDenied=Access Denied
|
login.oauth2AccessDenied=Access Denied
|
||||||
login.oauth2InvalidTokenResponse=Invalid Token Response
|
login.oauth2InvalidTokenResponse=Invalid Token Response
|
||||||
|
login.oauth2InvalidIdToken=Invalid Id Token
|
||||||
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
@ -654,6 +659,13 @@ certSign.name=İsim
|
|||||||
certSign.submit=PDF'i İmzala
|
certSign.submit=PDF'i İmzala
|
||||||
|
|
||||||
|
|
||||||
|
#removeCertSign
|
||||||
|
removeCertSign.title=Remove Certificate Signature
|
||||||
|
removeCertSign.header=Remove the digital certificate from the PDF
|
||||||
|
removeCertSign.selectPDF=Select a PDF file:
|
||||||
|
removeCertSign.submit=Remove Signature
|
||||||
|
|
||||||
|
|
||||||
#removeBlanks
|
#removeBlanks
|
||||||
removeBlanks.title=Boşları Kaldır
|
removeBlanks.title=Boşları Kaldır
|
||||||
removeBlanks.header=Boş Sayfaları Kaldır
|
removeBlanks.header=Boş Sayfaları Kaldır
|
||||||
@ -964,6 +976,7 @@ pdfToPDFA.credit=Bu hizmet PDF/A dönüşümü için OCRmyPDF kullanır
|
|||||||
pdfToPDFA.submit=Dönüştür
|
pdfToPDFA.submit=Dönüştür
|
||||||
pdfToPDFA.tip=Şu anda aynı anda birden fazla giriş için çalışmıyor
|
pdfToPDFA.tip=Şu anda aynı anda birden fazla giriş için çalışmıyor
|
||||||
pdfToPDFA.outputFormat=Çıkış formatı
|
pdfToPDFA.outputFormat=Çıkış formatı
|
||||||
|
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
|
||||||
|
|
||||||
|
|
||||||
#PDFToWord
|
#PDFToWord
|
||||||
|
@ -332,6 +332,10 @@ home.certSign.title=Підписати сертифікатом
|
|||||||
home.certSign.desc=Підписати PDF сертифікатом/ключем (PEM/P12)
|
home.certSign.desc=Підписати PDF сертифікатом/ключем (PEM/P12)
|
||||||
certSign.tags=authenticate,PEM,P12,official,encrypt
|
certSign.tags=authenticate,PEM,P12,official,encrypt
|
||||||
|
|
||||||
|
home.removeCertSign.title=Remove Certificate Sign
|
||||||
|
home.removeCertSign.desc=Remove certificate signature from PDF
|
||||||
|
removeCertSign.tags=authenticate,PEM,P12,official,decrypt
|
||||||
|
|
||||||
home.pageLayout.title=Об'єднати сторінки
|
home.pageLayout.title=Об'єднати сторінки
|
||||||
home.pageLayout.desc=Об'єднання кількох сторінок документа PDF в одну сторінку
|
home.pageLayout.desc=Об'єднання кількох сторінок документа PDF в одну сторінку
|
||||||
pageLayout.tags=merge,composite,single-view,organize
|
pageLayout.tags=merge,composite,single-view,organize
|
||||||
@ -457,6 +461,7 @@ login.oauth2InvalidUserInfoResponse=Invalid User Info Response
|
|||||||
login.oauth2invalidRequest=Invalid Request
|
login.oauth2invalidRequest=Invalid Request
|
||||||
login.oauth2AccessDenied=Access Denied
|
login.oauth2AccessDenied=Access Denied
|
||||||
login.oauth2InvalidTokenResponse=Invalid Token Response
|
login.oauth2InvalidTokenResponse=Invalid Token Response
|
||||||
|
login.oauth2InvalidIdToken=Invalid Id Token
|
||||||
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
@ -654,6 +659,13 @@ certSign.name=Ім'я
|
|||||||
certSign.submit=Підписати PDF
|
certSign.submit=Підписати PDF
|
||||||
|
|
||||||
|
|
||||||
|
#removeCertSign
|
||||||
|
removeCertSign.title=Remove Certificate Signature
|
||||||
|
removeCertSign.header=Remove the digital certificate from the PDF
|
||||||
|
removeCertSign.selectPDF=Select a PDF file:
|
||||||
|
removeCertSign.submit=Remove Signature
|
||||||
|
|
||||||
|
|
||||||
#removeBlanks
|
#removeBlanks
|
||||||
removeBlanks.title=Видалити порожні
|
removeBlanks.title=Видалити порожні
|
||||||
removeBlanks.header=Видалити порожні сторінки
|
removeBlanks.header=Видалити порожні сторінки
|
||||||
@ -964,6 +976,7 @@ pdfToPDFA.credit=Цей сервіс використовує OCRmyPDF для п
|
|||||||
pdfToPDFA.submit=Конвертувати
|
pdfToPDFA.submit=Конвертувати
|
||||||
pdfToPDFA.tip=Наразі не працює для кількох вхідних файлів одночасно
|
pdfToPDFA.tip=Наразі не працює для кількох вхідних файлів одночасно
|
||||||
pdfToPDFA.outputFormat=Output format
|
pdfToPDFA.outputFormat=Output format
|
||||||
|
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
|
||||||
|
|
||||||
|
|
||||||
#PDFToWord
|
#PDFToWord
|
||||||
|
@ -332,6 +332,10 @@ home.certSign.title=使用证书签署
|
|||||||
home.certSign.desc=使用证书/密钥(PEM/P12)对PDF进行签署
|
home.certSign.desc=使用证书/密钥(PEM/P12)对PDF进行签署
|
||||||
certSign.tags=身份验证、PEM、P12、官方、加密
|
certSign.tags=身份验证、PEM、P12、官方、加密
|
||||||
|
|
||||||
|
home.removeCertSign.title=Remove Certificate Sign
|
||||||
|
home.removeCertSign.desc=Remove certificate signature from PDF
|
||||||
|
removeCertSign.tags=authenticate,PEM,P12,official,decrypt
|
||||||
|
|
||||||
home.pageLayout.title=多页布局
|
home.pageLayout.title=多页布局
|
||||||
home.pageLayout.desc=将PDF文档的多个页面合并成一页
|
home.pageLayout.desc=将PDF文档的多个页面合并成一页
|
||||||
pageLayout.tags=合并、组合、单视图、整理
|
pageLayout.tags=合并、组合、单视图、整理
|
||||||
@ -457,6 +461,7 @@ login.oauth2InvalidUserInfoResponse=Invalid User Info Response
|
|||||||
login.oauth2invalidRequest=Invalid Request
|
login.oauth2invalidRequest=Invalid Request
|
||||||
login.oauth2AccessDenied=Access Denied
|
login.oauth2AccessDenied=Access Denied
|
||||||
login.oauth2InvalidTokenResponse=Invalid Token Response
|
login.oauth2InvalidTokenResponse=Invalid Token Response
|
||||||
|
login.oauth2InvalidIdToken=Invalid Id Token
|
||||||
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
@ -654,6 +659,13 @@ certSign.name=名称
|
|||||||
certSign.submit=签署 PDF
|
certSign.submit=签署 PDF
|
||||||
|
|
||||||
|
|
||||||
|
#removeCertSign
|
||||||
|
removeCertSign.title=Remove Certificate Signature
|
||||||
|
removeCertSign.header=Remove the digital certificate from the PDF
|
||||||
|
removeCertSign.selectPDF=Select a PDF file:
|
||||||
|
removeCertSign.submit=Remove Signature
|
||||||
|
|
||||||
|
|
||||||
#removeBlanks
|
#removeBlanks
|
||||||
removeBlanks.title=删除空白
|
removeBlanks.title=删除空白
|
||||||
removeBlanks.header=删除空白页
|
removeBlanks.header=删除空白页
|
||||||
@ -964,6 +976,7 @@ pdfToPDFA.credit=此服务使用OCRmyPDF进行PDF/A转换
|
|||||||
pdfToPDFA.submit=转换
|
pdfToPDFA.submit=转换
|
||||||
pdfToPDFA.tip=目前不支持上传多个
|
pdfToPDFA.tip=目前不支持上传多个
|
||||||
pdfToPDFA.outputFormat=Output format
|
pdfToPDFA.outputFormat=Output format
|
||||||
|
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
|
||||||
|
|
||||||
|
|
||||||
#PDFToWord
|
#PDFToWord
|
||||||
|
@ -332,6 +332,10 @@ home.certSign.title=使用憑證簽章
|
|||||||
home.certSign.desc=使用憑證/金鑰(PEM/P12)簽章 PDF
|
home.certSign.desc=使用憑證/金鑰(PEM/P12)簽章 PDF
|
||||||
certSign.tags=驗證,PEM,P12,官方,加密
|
certSign.tags=驗證,PEM,P12,官方,加密
|
||||||
|
|
||||||
|
home.removeCertSign.title=Remove Certificate Sign
|
||||||
|
home.removeCertSign.desc=Remove certificate signature from PDF
|
||||||
|
removeCertSign.tags=authenticate,PEM,P12,official,decrypt
|
||||||
|
|
||||||
home.pageLayout.title=多頁面版面配置
|
home.pageLayout.title=多頁面版面配置
|
||||||
home.pageLayout.desc=將 PDF 檔案的多個頁面合併到單一頁面
|
home.pageLayout.desc=將 PDF 檔案的多個頁面合併到單一頁面
|
||||||
pageLayout.tags=合併,複合,單一檢視,組織
|
pageLayout.tags=合併,複合,單一檢視,組織
|
||||||
@ -457,6 +461,7 @@ login.oauth2InvalidUserInfoResponse=Invalid User Info Response
|
|||||||
login.oauth2invalidRequest=Invalid Request
|
login.oauth2invalidRequest=Invalid Request
|
||||||
login.oauth2AccessDenied=Access Denied
|
login.oauth2AccessDenied=Access Denied
|
||||||
login.oauth2InvalidTokenResponse=Invalid Token Response
|
login.oauth2InvalidTokenResponse=Invalid Token Response
|
||||||
|
login.oauth2InvalidIdToken=Invalid Id Token
|
||||||
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
@ -654,6 +659,13 @@ certSign.name=名稱
|
|||||||
certSign.submit=簽章 PDF
|
certSign.submit=簽章 PDF
|
||||||
|
|
||||||
|
|
||||||
|
#removeCertSign
|
||||||
|
removeCertSign.title=Remove Certificate Signature
|
||||||
|
removeCertSign.header=Remove the digital certificate from the PDF
|
||||||
|
removeCertSign.selectPDF=Select a PDF file:
|
||||||
|
removeCertSign.submit=Remove Signature
|
||||||
|
|
||||||
|
|
||||||
#removeBlanks
|
#removeBlanks
|
||||||
removeBlanks.title=移除空白頁面
|
removeBlanks.title=移除空白頁面
|
||||||
removeBlanks.header=移除空白頁面
|
removeBlanks.header=移除空白頁面
|
||||||
@ -964,6 +976,7 @@ pdfToPDFA.credit=此服務使用 OCRmyPDF 進行 PDF/A 轉換
|
|||||||
pdfToPDFA.submit=轉換
|
pdfToPDFA.submit=轉換
|
||||||
pdfToPDFA.tip=目前不支援上傳多個
|
pdfToPDFA.tip=目前不支援上傳多個
|
||||||
pdfToPDFA.outputFormat=Output format
|
pdfToPDFA.outputFormat=Output format
|
||||||
|
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
|
||||||
|
|
||||||
|
|
||||||
#PDFToWord
|
#PDFToWord
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
margin-bottom: 2rem;
|
margin-bottom: 2rem;
|
||||||
padding: 0.75rem 3.5rem;
|
padding: 0.75rem 3.5rem;
|
||||||
border: 0.1rem solid var(--md-sys-color-outline-variant);
|
border: 1px solid var(--md-sys-color-outline-variant);
|
||||||
border-radius: 3rem;
|
border-radius: 3rem;
|
||||||
outline-color: var(--md-sys-color-outline-variant);
|
outline-color: var(--md-sys-color-outline-variant);
|
||||||
}
|
}
|
||||||
@ -19,12 +19,12 @@
|
|||||||
.features-container {
|
.features-container {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fill, minmax(15rem, 3fr));
|
grid-template-columns: repeat(auto-fill, minmax(15rem, 3fr));
|
||||||
gap: 25px 30px;
|
gap: 30px 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.feature-card {
|
.feature-card {
|
||||||
border: 2px solid var(--md-sys-color-surface-5);
|
border: 1px solid var(--md-sys-color-surface-5);
|
||||||
border-radius: 2rem;
|
border-radius: 1.75rem;
|
||||||
padding: 1.25rem;
|
padding: 1.25rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@ -47,13 +47,13 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.feature-card .card-text {
|
.feature-card .card-text {
|
||||||
flex: 1;
|
font-size: .875rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.feature-card:hover {
|
.feature-card:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transform: scale(1.1);
|
transform: scale(1.08);
|
||||||
box-shadow: var(--md-sys-elevation-3);
|
box-shadow: var(--md-sys-elevation-2);
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-title.text-primary {
|
.card-title.text-primary {
|
||||||
@ -79,11 +79,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
#tool-text {
|
#tool-text {
|
||||||
margin: 0.5rem 0.5rem 0rem;
|
margin: 0.0rem 0 0 1.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-title {
|
.card-title {
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
|
font-size: 1.1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Only show the favorite icons when the parent card is being hovered over */
|
/* Only show the favorite icons when the parent card is being hovered over */
|
||||||
|
@ -75,7 +75,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.icon-text {
|
.icon-text {
|
||||||
margin-left: 4px;
|
margin-left: 8px;
|
||||||
margin-right: 4px;
|
margin-right: 4px;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
@ -187,8 +187,8 @@ td {
|
|||||||
.feature-card .nav-icon {
|
.feature-card .nav-icon {
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
font-size: 2rem !important;
|
font-size: 2rem !important;
|
||||||
padding: 0.5rem;
|
padding: 0.75rem;
|
||||||
border-radius: 1.25rem;
|
border-radius: 0.9rem;
|
||||||
color: var(--md-sys-color-surface);
|
color: var(--md-sys-color-surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -798,6 +798,8 @@ textarea.form-control {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.nav-link {
|
.nav-link {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
transition: none !important;
|
transition: none !important;
|
||||||
padding: 0.5rem 1rem !important;
|
padding: 0.5rem 1rem !important;
|
||||||
border: 1px transparent;
|
border: 1px transparent;
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
.material-symbols-rounded {
|
.material-symbols-rounded {
|
||||||
font-family: 'Material Symbols Rounded';
|
font-family: 'Material Symbols Rounded';
|
||||||
font-weight: normal;
|
font-weight: 300;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
|
@ -30,5 +30,5 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.no-fill {
|
.no-fill {
|
||||||
font-variation-settings: var(--md-sys-icon-fill-0);
|
/* font-variation-settings: var(--md-sys-icon-fill-0); */
|
||||||
}
|
}
|
58
src/main/resources/static/images/flags/hr.svg
Normal file
58
src/main/resources/static/images/flags/hr.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 40 KiB |
7
src/main/resources/static/images/flags/no.svg
Normal file
7
src/main/resources/static/images/flags/no.svg
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" id="flag-icons-no" viewBox="0 0 640 480">
|
||||||
|
<path fill="#ed2939" d="M0 0h640v480H0z"/>
|
||||||
|
<path fill="#fff" d="M180 0h120v480H180z"/>
|
||||||
|
<path fill="#fff" d="M0 180h640v120H0z"/>
|
||||||
|
<path fill="#002664" d="M210 0h60v480h-60z"/>
|
||||||
|
<path fill="#002664" d="M0 210h640v60H0z"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 318 B |
@ -34,7 +34,7 @@
|
|||||||
<td th:text="#{${user.roleName}}"></td>
|
<td th:text="#{${user.roleName}}"></td>
|
||||||
<td>
|
<td>
|
||||||
<form th:if="${user.username != currentUsername}" th:action="@{'/api/v1/user/admin/deleteUser/' + ${user.username}}" method="post">
|
<form th:if="${user.username != currentUsername}" th:action="@{'/api/v1/user/admin/deleteUser/' + ${user.username}}" method="post">
|
||||||
<button type="submit" th:text="#{delete}">Delete</button>
|
<button class="btn btn-danger" type="submit" th:text="#{delete}">Delete</button>
|
||||||
</form>
|
</form>
|
||||||
</td>
|
</td>
|
||||||
<td th:text="${user.authenticationType}"></td>
|
<td th:text="${user.authenticationType}"></td>
|
||||||
@ -47,7 +47,7 @@
|
|||||||
<span th:text="#{${addMessage}}">Default message if not found</span>
|
<span th:text="#{${addMessage}}">Default message if not found</span>
|
||||||
</div>
|
</div>
|
||||||
<button class="btn btn-outline-info" data-toggle="tooltip" data-placement="auto" th:title="#{adminUserSettings.usernameInfo}" th:text="#{help}">Help</button>
|
<button class="btn btn-outline-info" data-toggle="tooltip" data-placement="auto" th:title="#{adminUserSettings.usernameInfo}" th:text="#{help}">Help</button>
|
||||||
<form id="formsaveuser" action="/api/v1/user/admin/saveUser" method="post">
|
<form id="formsaveuser" th:action="@{/api/v1/user/admin/saveUser}" method="post">
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="username" th:text="#{username}">Username</label>
|
<label for="username" th:text="#{username}">Username</label>
|
||||||
<input type="text" class="form-control" name="username" id="username" th:title="#{adminUserSettings.usernameInfo}" required>
|
<input type="text" class="form-control" name="username" id="username" th:title="#{adminUserSettings.usernameInfo}" required>
|
||||||
@ -78,7 +78,7 @@
|
|||||||
<div th:if="${changeMessage}" class="alert alert-danger">
|
<div th:if="${changeMessage}" class="alert alert-danger">
|
||||||
<span th:text="#{${changeMessage}}">Default message if not found</span>
|
<span th:text="#{${changeMessage}}">Default message if not found</span>
|
||||||
</div>
|
</div>
|
||||||
<form action="/api/v1/user/admin/changeRole" method="post">
|
<form th:action="@{/api/v1/user/admin/changeRole}" method="post">
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="username" th:text="#{username}">Username</label>
|
<label for="username" th:text="#{username}">Username</label>
|
||||||
<select name="username" class="form-control" required>
|
<select name="username" class="form-control" required>
|
||||||
|
@ -21,15 +21,51 @@
|
|||||||
<form method="post" enctype="multipart/form-data" th:action="@{api/v1/convert/pdf/pdfa}">
|
<form method="post" enctype="multipart/form-data" th:action="@{api/v1/convert/pdf/pdfa}">
|
||||||
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"></div>
|
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"></div>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label th:text="#{pdfToPDFA.outputFormat}"></label>
|
<label for="outputFormat" th:text="#{pdfToPDFA.outputFormat}"></label>
|
||||||
<select class="form-control" name="outputFormat">
|
<select class="form-control" name="outputFormat" id="outputFormat">
|
||||||
<option value="pdfa-1">PDF/A-1b</option>
|
<option value="pdfa-1">PDF/A-1b</option>
|
||||||
<option value="pdfa">PDF/A-2b</option>
|
<option value="pdfa">PDF/A-2b</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<br>
|
<div id="result" class="alert-warning"></div>
|
||||||
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{pdfToPDFA.submit}"></button>
|
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{pdfToPDFA.submit}"></button>
|
||||||
</form>
|
</form>
|
||||||
|
<script th:inline="javascript">
|
||||||
|
document.getElementById('fileInput-input').addEventListener('change', async () => {
|
||||||
|
pdfjsLib.GlobalWorkerOptions.workerSrc = './pdfjs/pdf.worker.mjs';
|
||||||
|
const fileInput = document.getElementById('fileInput-input');
|
||||||
|
const resultDiv = document.getElementById('result');
|
||||||
|
|
||||||
|
const file = fileInput.files[0];
|
||||||
|
const arrayBuffer = await file.arrayBuffer();
|
||||||
|
|
||||||
|
try {
|
||||||
|
const pdf = await pdfjsLib.getDocument({ data: arrayBuffer }).promise;
|
||||||
|
|
||||||
|
let hasSignature = false;
|
||||||
|
|
||||||
|
for (let i = 1; i <= pdf.numPages; i++) {
|
||||||
|
const page = await pdf.getPage(i);
|
||||||
|
const annotations = await page.getAnnotations({ intent: 'display' });
|
||||||
|
|
||||||
|
annotations.forEach(annotation => {
|
||||||
|
console.log(annotation)
|
||||||
|
if (annotation.subtype === 'Widget' && annotation.fieldType === 'Sig') {
|
||||||
|
hasSignature = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasSignature) {
|
||||||
|
/*<![CDATA[*/
|
||||||
|
resultDiv.textContent = /*[[#{pdfToPDFA.pdfWithDigitalSignature}]]*/ "The PDF contains a digital signature. This will be removed in the next step.";
|
||||||
|
/*]]>*/
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
resultDiv.textContent = 'Error reading the PDF: ' + error.message;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
<p class="mt-3" th:text="#{pdfToPDFA.credit}"></p>
|
<p class="mt-3" th:text="#{pdfToPDFA.credit}"></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html th:lang="${#locale.language}" th:dir="#{language.direction}" th:data-language="${#locale.toString()}" xmlns:th="https://www.thymeleaf.org">
|
<html th:lang="${#locale.language}" th:dir="#{language.direction}" th:data-language="${#locale.toString()}" xmlns:th="https://www.thymeleaf.org">
|
||||||
<head>
|
<head>
|
||||||
<th:block th:insert="~{fragments/common :: head(title=#{crop.title}, header=#{crop.header})}"></th:block>
|
<th:block th:insert="~{fragments/common :: head(title=#{crop.title}, header=#{crop.header})}"></th:block>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
@ -16,7 +16,7 @@
|
|||||||
<span class="material-symbols-rounded tool-header-icon organize">crop</span>
|
<span class="material-symbols-rounded tool-header-icon organize">crop</span>
|
||||||
<span class="tool-header-text" th:text="#{crop.header}"></span>
|
<span class="tool-header-text" th:text="#{crop.header}"></span>
|
||||||
</div>
|
</div>
|
||||||
<form id="cropForm" action="/api/v1/general/crop" method="post" enctype="multipart/form-data">
|
<form id="cropForm" th:action="@{/api/v1/general/crop}" method="post" enctype="multipart/form-data">
|
||||||
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"></div>
|
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"></div>
|
||||||
<input id="x" type="hidden" name="x">
|
<input id="x" type="hidden" name="x">
|
||||||
<input id="y" type="hidden" name="y">
|
<input id="y" type="hidden" name="y">
|
||||||
@ -75,6 +75,16 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
cropForm.addEventListener('submit', function(e) {
|
||||||
|
if (xInput.value == "" && yInput.value == "" && widthInput.value == "" && heightInput.value == "") {
|
||||||
|
// Ορίστε συντεταγμένες για ολόκληρη την επιφάνεια του PDF
|
||||||
|
xInput.value = 0;
|
||||||
|
yInput.value = 0;
|
||||||
|
widthInput.value = pdfCanvas.width;
|
||||||
|
heightInput.value = pdfCanvas.height;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
overlayCanvas.addEventListener('mousedown', function(e) {
|
overlayCanvas.addEventListener('mousedown', function(e) {
|
||||||
// Clear previously drawn rectangle on the main canvas
|
// Clear previously drawn rectangle on the main canvas
|
||||||
context.clearRect(0, 0, pdfCanvas.width, pdfCanvas.height);
|
context.clearRect(0, 0, pdfCanvas.width, pdfCanvas.height);
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
<a href="https://github.com/Stirling-Tools/Stirling-PDF/issues" id="github-button" class="btn btn-primary" target="_blank" th:text="#{error.github}"></a>
|
<a href="https://github.com/Stirling-Tools/Stirling-PDF/issues" id="github-button" class="btn btn-primary" target="_blank" th:text="#{error.github}"></a>
|
||||||
<a href="https://discord.gg/Cn8pWhQRxZ" id="discord-button" class="btn btn-primary" target="_blank" th:text="#{joinDiscord}"></a>
|
<a href="https://discord.gg/Cn8pWhQRxZ" id="discord-button" class="btn btn-primary" target="_blank" th:text="#{joinDiscord}"></a>
|
||||||
</div>
|
</div>
|
||||||
<a href="/" id="home-button" class="home-button btn btn-primary" th:text="#{goHomepage}"></a>
|
<a th:href="@{/}" id="home-button" class="home-button btn btn-primary" th:text="#{goHomepage}"></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -29,4 +29,6 @@
|
|||||||
<a class="dropdown-item lang_dropdown-item" href="" data-bs-language-code="sr_LATN_RS"> <img src="images/flags/rs.svg" alt="icon" width="20" height="15"> Srpski</a>
|
<a class="dropdown-item lang_dropdown-item" href="" data-bs-language-code="sr_LATN_RS"> <img src="images/flags/rs.svg" alt="icon" width="20" height="15"> Srpski</a>
|
||||||
<a class="dropdown-item lang_dropdown-item" href="" data-bs-language-code="uk_UA"> <img src="images/flags/ua.svg" alt="icon" width="20" height="15"> Українська</a>
|
<a class="dropdown-item lang_dropdown-item" href="" data-bs-language-code="uk_UA"> <img src="images/flags/ua.svg" alt="icon" width="20" height="15"> Українська</a>
|
||||||
<a class="dropdown-item lang_dropdown-item" href="" data-bs-language-code="cs_CZ"> <img src="images/flags/cz.svg" alt="icon" width="20" height="15"> Česky</a>
|
<a class="dropdown-item lang_dropdown-item" href="" data-bs-language-code="cs_CZ"> <img src="images/flags/cz.svg" alt="icon" width="20" height="15"> Česky</a>
|
||||||
|
<a class="dropdown-item lang_dropdown-item" href="" data-bs-language-code="hr_HR"> <img src="images/flags/hr.svg" alt="icon" width="20" height="15"> Hrvatski</a>
|
||||||
|
<a class="dropdown-item lang_dropdown-item" href="" data-bs-language-code="no_NB"> <img src="images/flags/no.svg" alt="icon" width="20" height="15"> Norsk</a>
|
||||||
</th:block>
|
</th:block>
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
<script src="js/githubVersion.js"></script>
|
<script src="js/githubVersion.js"></script>
|
||||||
<nav class="navbar navbar-expand-lg">
|
<nav class="navbar navbar-expand-lg">
|
||||||
<div class="container ">
|
<div class="container ">
|
||||||
<a class="navbar-brand" href="/" style="display: flex;">
|
<a class="navbar-brand" th:href="@{/}" style="display: flex;">
|
||||||
<img class="main-icon" src="favicon.svg" alt="icon">
|
<img class="main-icon" src="favicon.svg" alt="icon">
|
||||||
<span class="icon-text" th:text="${@navBarText}"></span>
|
<span class="icon-text" th:text="${@navBarText}"></span>
|
||||||
</a>
|
</a>
|
||||||
@ -22,8 +22,7 @@
|
|||||||
<ul class="navbar-nav me-auto flex-nowrap">
|
<ul class="navbar-nav me-auto flex-nowrap">
|
||||||
|
|
||||||
<!-- All Tools -->
|
<!-- All Tools -->
|
||||||
<li class="nav-item dropdown dropdown-mega position-static"
|
<li class="nav-item dropdown dropdown-mega position-static">
|
||||||
th:classappend="${currentPage}=='remove-pages' OR ${currentPage}=='merge-pdfs' OR ${currentPage}=='split-pdfs' OR ${currentPage}=='crop' OR ${currentPage}=='adjust-contrast' OR ${currentPage}=='pdf-organizer' OR ${currentPage}=='rotate-pdf' OR ${currentPage}=='multi-page-layout' OR ${currentPage}=='scale-pages' OR ${currentPage}=='auto-split-pdf' OR ${currentPage}=='extract-page' OR ${currentPage}=='pdf-to-single-page' OR ${currentPage}=='add-password' OR ${currentPage}=='remove-password' OR ${currentPage}=='add-watermark' OR ${currentPage}=='cert-sign' OR ${currentPage}=='sanitize-pdf' OR ${currentPage}=='img-to-pdf' OR ${currentPage}=='file-to-pdf' OR ${currentPage}=='html-to-pdf' OR ${currentPage}=='url-to-pdf' OR ${currentPage}=='pdf-to-img' OR ${currentPage}=='pdf-to-word' OR ${currentPage}=='pdf-to-presentation' OR ${currentPage}=='pdf-to-text' OR ${currentPage}=='pdf-to-html' OR ${currentPage}=='pdf-to-xml' OR ${currentPage}=='pdf-to-pdfa' OR ${currentPage}=='sign' OR ${currentPage}=='repair' OR ${currentPage}=='compare' OR ${currentPage}=='show-javascript' OR ${currentPage}=='flatten' OR ${currentPage}=='remove-blanks' OR ${currentPage}=='remove-annotations' OR ${currentPage}=='extract-image-scans' OR ${currentPage}=='change-metadata' OR ${currentPage}=='add-image' OR ${currentPage}=='ocr-pdf' OR ${currentPage}=='change-permissions' OR ${currentPage}=='extract-images' OR ${currentPage}=='compress-pdf' OR ${currentPage}=='add-page-numbers' OR ${currentPage}=='auto-rename' OR ${currentPage}=='get-info-on-pdf' ? 'active' : ''">
|
|
||||||
<a class="nav-link" id="navbarDropdown-1" href="#" role="button" data-bs-toggle="dropdown"
|
<a class="nav-link" id="navbarDropdown-1" href="#" role="button" data-bs-toggle="dropdown"
|
||||||
aria-haspopup="true" aria-expanded="false">
|
aria-haspopup="true" aria-expanded="false">
|
||||||
<span class="material-symbols-rounded">
|
<span class="material-symbols-rounded">
|
||||||
@ -91,6 +90,9 @@
|
|||||||
<div
|
<div
|
||||||
th:replace="~{fragments/navbarEntry :: navbarEntry ('markdown-to-pdf', 'markdown', 'home.MarkdownToPDF.title', 'home.MarkdownToPDF.desc', 'MarkdownToPDF.tags', 'convert')}">
|
th:replace="~{fragments/navbarEntry :: navbarEntry ('markdown-to-pdf', 'markdown', 'home.MarkdownToPDF.title', 'home.MarkdownToPDF.desc', 'MarkdownToPDF.tags', 'convert')}">
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
th:replace="~{fragments/navbarEntry :: navbarEntry ('book-to-pdf', 'book', 'home.BookToPDF.title', 'home.BookToPDF.desc', 'BookToPDF.tags', 'convert')}">
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- Convert from PDF menu items -->
|
<!-- Convert from PDF menu items -->
|
||||||
<div class="col-lg-2 col-sm-6 py px-xl-1 px-2">
|
<div class="col-lg-2 col-sm-6 py px-xl-1 px-2">
|
||||||
@ -119,6 +121,9 @@
|
|||||||
<div
|
<div
|
||||||
th:replace="~{fragments/navbarEntry :: navbarEntry ('pdf-to-csv', 'csv', 'home.tableExtraxt.title', 'home.tableExtraxt.desc', 'pdfToPDFA.tags', 'convert')}">
|
th:replace="~{fragments/navbarEntry :: navbarEntry ('pdf-to-csv', 'csv', 'home.tableExtraxt.title', 'home.tableExtraxt.desc', 'pdfToPDFA.tags', 'convert')}">
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
th:replace="~{fragments/navbarEntry :: navbarEntry ('pdf-to-book', 'book', 'home.PDFToBook.title', 'home.PDFToBook.desc', 'PDFToBook.tags', 'convert')}">
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- Security menu items -->
|
<!-- Security menu items -->
|
||||||
<div class="col-lg-2 col-sm-6 py px-xl-1 px-2">
|
<div class="col-lg-2 col-sm-6 py px-xl-1 px-2">
|
||||||
@ -141,6 +146,9 @@
|
|||||||
<div
|
<div
|
||||||
th:replace="~{fragments/navbarEntry :: navbarEntry ('cert-sign', 'workspace_premium', 'home.certSign.title', 'home.certSign.desc', 'certSign.tags', 'security')}">
|
th:replace="~{fragments/navbarEntry :: navbarEntry ('cert-sign', 'workspace_premium', 'home.certSign.title', 'home.certSign.desc', 'certSign.tags', 'security')}">
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
th:replace="~{fragments/navbarEntry :: navbarEntry ('remove-cert-sign', 'remove_moderator', 'home.removeCertSign.title', 'home.removeCertSign.desc', 'removeCertSign.tags', 'security')}">
|
||||||
|
</div>
|
||||||
<div
|
<div
|
||||||
th:replace="~{fragments/navbarEntry :: navbarEntry ('sanitize-pdf', 'sanitizer', 'home.sanitizePdf.title', 'home.sanitizePdf.desc', 'sanitizePdf.tags', 'security')}">
|
th:replace="~{fragments/navbarEntry :: navbarEntry ('sanitize-pdf', 'sanitizer', 'home.sanitizePdf.title', 'home.sanitizePdf.desc', 'sanitizePdf.tags', 'security')}">
|
||||||
</div>
|
</div>
|
||||||
@ -233,7 +241,7 @@
|
|||||||
|
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="nav-item">
|
<li class="nav-item" th:if="${@endpointConfiguration.isEndpointEnabled('multi-tool')}">
|
||||||
<a class="nav-link" href="#" th:href="@{multi-tool}"
|
<a class="nav-link" href="#" th:href="@{multi-tool}"
|
||||||
th:classappend="${currentPage}=='multi-tool' ? 'active' : ''" th:title="#{home.multiTool.desc}">
|
th:classappend="${currentPage}=='multi-tool' ? 'active' : ''" th:title="#{home.multiTool.desc}">
|
||||||
<span class="material-symbols-rounded">
|
<span class="material-symbols-rounded">
|
||||||
@ -243,7 +251,7 @@
|
|||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="nav-item">
|
<li class="nav-item" th:if="${@endpointConfiguration.isEndpointEnabled('pipeline')}" >
|
||||||
<a class="nav-link" href="#" th:href="@{pipeline}"
|
<a class="nav-link" href="#" th:href="@{pipeline}"
|
||||||
th:classappend="${currentPage}=='pipeline' ? 'active' : ''" th:title="#{home.pipeline.desc}">
|
th:classappend="${currentPage}=='pipeline' ? 'active' : ''" th:title="#{home.pipeline.desc}">
|
||||||
<span class="material-symbols-rounded">
|
<span class="material-symbols-rounded">
|
||||||
@ -253,7 +261,7 @@
|
|||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="nav-item">
|
<li class="nav-item" th:if="${@endpointConfiguration.isEndpointEnabled('compress-pdf')}" >
|
||||||
<a class="nav-link" href="#" title="#{home.compressPdfs.title}" th:href="@{compress-pdf}"
|
<a class="nav-link" href="#" title="#{home.compressPdfs.title}" th:href="@{compress-pdf}"
|
||||||
th:classappend="${currentPage}=='compress-pdf' ? 'active' : ''" th:title="#{home.compressPdfs.desc}">
|
th:classappend="${currentPage}=='compress-pdf' ? 'active' : ''" th:title="#{home.compressPdfs.desc}">
|
||||||
<span class="material-symbols-rounded">
|
<span class="material-symbols-rounded">
|
||||||
|
@ -164,6 +164,9 @@
|
|||||||
<div
|
<div
|
||||||
th:replace="~{fragments/card :: card(id='cert-sign', cardTitle=#{home.certSign.title}, cardText=#{home.certSign.desc}, cardLink='cert-sign', toolIcon='workspace_premium', tags=#{certSign.tags}, toolGroup='security')}">
|
th:replace="~{fragments/card :: card(id='cert-sign', cardTitle=#{home.certSign.title}, cardText=#{home.certSign.desc}, cardLink='cert-sign', toolIcon='workspace_premium', tags=#{certSign.tags}, toolGroup='security')}">
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
th:replace="~{fragments/card :: card(id='remove-cert-sign', cardTitle=#{home.removeCertSign.title}, cardText=#{home.removeCertSign.desc}, cardLink='remove-cert-sign', toolIcon='remove_moderator', tags=#{removeCertSign.tags}, toolGroup='security')}">
|
||||||
|
</div>
|
||||||
<div
|
<div
|
||||||
th:replace="~{fragments/card :: card(id='multi-page-layout', cardTitle=#{home.pageLayout.title}, cardText=#{home.pageLayout.desc}, cardLink='multi-page-layout', toolIcon='dashboard', tags=#{pageLayout.tags}, toolGroup='organize')}">
|
th:replace="~{fragments/card :: card(id='multi-page-layout', cardTitle=#{home.pageLayout.title}, cardText=#{home.pageLayout.desc}, cardLink='multi-page-layout', toolIcon='dashboard', tags=#{pageLayout.tags}, toolGroup='organize')}">
|
||||||
</div>
|
</div>
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user