Compare commits

..

155 Commits

Author SHA1 Message Date
github-actions[bot]
d575ba8f9a 💾 Update Version (#1461)
💾 Sync Versions
> Made via sync_files.yml

Co-authored-by: GitHub Action action@github.com <GitHub Action action@github.com>
2024-06-15 00:42:11 +01:00
Anthony Stirling
accab3b5bf Update build.gradle 2024-06-15 00:41:43 +01:00
Sebastian Espei
8cbb4367ab PDF-to-Image different page formats fix (#1460)
* Improve the PDF rendering process for pages of varying sizes

This commit includes changes to handle the rendering of PDF documents with pages of different sizes. The updated code calculates the dimensions of each page upfront and assembles a final combined image that accommodates for the differing page dimensions. This approach avoids repetitive renderings of the same page sizes.

* Refactor image preparation for Pdf to Image
2024-06-14 23:39:30 +01:00
Thomas
3ede204918 Fixed a spelling mistake in French (#1459)
"en temps que" is not correct, it should be written "en tant que"
2024-06-14 19:39:25 +01:00
imgbot[bot]
32030e8d85 [ImgBot] Optimize images (#1455)
*Total -- 1,022.17kb -> 830.16kb (18.79%)

/src/main/resources/static/images/flags/ro.svg -- 3.37kb -> 0.61kb (81.88%)
/src/main/resources/static/pdfjs/images/annotation-noicon.svg -- 0.15kb -> 0.08kb (46.84%)
/src/main/resources/static/pdfjs-legacy/images/annotation-noicon.svg -- 0.15kb -> 0.08kb (46.84%)
/src/main/resources/static/pdfjs/images/annotation-paperclip.svg -- 0.54kb -> 0.33kb (39.31%)
/src/main/resources/static/pdfjs-legacy/images/annotation-paperclip.svg -- 0.54kb -> 0.33kb (39.31%)
/images/stirling-home-dark.png -- 365.99kb -> 242.29kb (33.8%)
/docs/stirling.svg -- 3.99kb -> 2.72kb (31.87%)
/src/main/resources/static/favicon.svg -- 3.99kb -> 2.72kb (31.87%)
/images/login-light.png -- 44.09kb -> 30.17kb (31.56%)
/docs/stirling-transparent.svg -- 13.68kb -> 9.37kb (31.53%)
/images/login-dark.png -- 45.22kb -> 31.00kb (31.46%)
/src/main/resources/static/pdfjs-legacy/images/annotation-note.svg -- 1.02kb -> 0.70kb (31.12%)
/src/main/resources/static/pdfjs/images/annotation-note.svg -- 1.02kb -> 0.70kb (31.12%)
/images/settings-light.png -- 63.36kb -> 43.84kb (30.8%)
/src/main/resources/static/pdfjs-legacy/images/toolbarButton-editorStamp.svg -- 0.72kb -> 0.50kb (30.52%)
/src/main/resources/static/pdfjs/images/toolbarButton-editorStamp.svg -- 0.72kb -> 0.50kb (30.52%)
/src/main/resources/static/pdfjs/images/toolBarButton-home.svg -- 1.19kb -> 0.91kb (23.4%)
/src/main/resources/static/pdfjs-legacy/images/toolBarButton-home.svg -- 1.19kb -> 0.91kb (23.4%)
/src/main/resources/static/pdfjs/images/annotation-check.svg -- 0.41kb -> 0.31kb (22.65%)
/src/main/resources/static/pdfjs-legacy/images/annotation-check.svg -- 0.41kb -> 0.31kb (22.65%)
/src/main/resources/static/pdfjs-legacy/images/annotation-newparagraph.svg -- 0.42kb -> 0.32kb (22.54%)
/src/main/resources/static/pdfjs/images/annotation-newparagraph.svg -- 0.42kb -> 0.32kb (22.54%)
/src/main/resources/static/pdfjs/images/annotation-insert.svg -- 0.40kb -> 0.31kb (22.06%)
/src/main/resources/static/pdfjs-legacy/images/annotation-insert.svg -- 0.40kb -> 0.31kb (22.06%)
/src/main/resources/static/images/flags/cz.svg -- 0.26kb -> 0.22kb (17.04%)
/src/main/resources/static/pdfjs/images/annotation-pushpin.svg -- 1.34kb -> 1.13kb (16%)
/src/main/resources/static/pdfjs-legacy/images/annotation-pushpin.svg -- 1.34kb -> 1.13kb (16%)
/src/main/resources/static/pdfjs-legacy/images/annotation-comment.svg -- 0.86kb -> 0.73kb (15.63%)
/src/main/resources/static/pdfjs/images/annotation-comment.svg -- 0.86kb -> 0.73kb (15.63%)
/src/main/resources/static/images/flags/in.svg -- 1.06kb -> 0.91kb (14.59%)
/src/main/resources/static/pdfjs-legacy/images/annotation-paragraph.svg -- 1.12kb -> 0.97kb (12.69%)
/src/main/resources/static/pdfjs/images/annotation-paragraph.svg -- 1.12kb -> 0.97kb (12.69%)
/src/main/resources/static/images/flags/kr.svg -- 1.01kb -> 0.88kb (12.61%)
/src/main/resources/static/pdfjs/images/loading-dark.svg -- 1.70kb -> 1.49kb (12.27%)
/src/main/resources/static/images/github.svg -- 2.02kb -> 1.80kb (10.69%)
/src/main/resources/static/safari-pinned-tab.svg -- 1.77kb -> 1.58kb (10.39%)
/src/main/resources/static/images/flags/jp.svg -- 0.45kb -> 0.41kb (8.82%)
/src/main/resources/static/images/flags/hu.svg -- 0.22kb -> 0.20kb (8.77%)
/src/main/resources/static/images/flags/pl.svg -- 0.21kb -> 0.20kb (8.22%)
/src/main/resources/static/images/flags/bg.svg -- 0.28kb -> 0.25kb (8.13%)
/src/main/resources/static/images/flags/ru.svg -- 0.28kb -> 0.25kb (8.13%)
/src/main/resources/static/images/flags/it.svg -- 0.28kb -> 0.26kb (7.96%)
/src/main/resources/static/images/flags/ua.svg -- 0.23kb -> 0.21kb (7.76%)
/src/main/resources/static/pdfjs-legacy/images/annotation-help.svg -- 2.12kb -> 1.96kb (7.29%)
/src/main/resources/static/pdfjs/images/annotation-help.svg -- 2.12kb -> 1.96kb (7.29%)
/src/main/resources/static/images/flags/us.svg -- 0.85kb -> 0.79kb (7.21%)
/src/main/resources/static/pdfjs/images/annotation-key.svg -- 1.42kb -> 1.33kb (6.47%)
/src/main/resources/static/pdfjs-legacy/images/annotation-key.svg -- 1.42kb -> 1.33kb (6.47%)
/src/main/resources/static/images/docker.svg -- 0.90kb -> 0.85kb (5.65%)
/src/main/resources/static/images/flags/gr.svg -- 0.85kb -> 0.80kb (5.53%)
/src/main/resources/static/images/flags/no.svg -- 0.31kb -> 0.29kb (5.35%)
/src/main/resources/static/images/flags/de.svg -- 0.21kb -> 0.19kb (5.24%)
/src/main/resources/static/images/flags/tr.svg -- 0.54kb -> 0.51kb (5.09%)
/src/main/resources/static/images/flags/pt_br.svg -- 6.34kb -> 6.03kb (4.92%)
/src/main/resources/static/images/flags/fr.svg -- 0.23kb -> 0.21kb (4.76%)
/src/main/resources/static/images/flags/nl.svg -- 0.21kb -> 0.21kb (4.55%)
/src/main/resources/static/images/flags/id.svg -- 0.17kb -> 0.17kb (4.49%)
/src/main/resources/static/pdfjs-legacy/images/loading.svg -- 1.52kb -> 1.46kb (4.04%)
/src/main/resources/static/pdfjs/images/loading.svg -- 1.52kb -> 1.46kb (4.04%)
/src/main/resources/static/images/flags/pt_pt.svg -- 8.12kb -> 7.80kb (3.91%)
/src/main/resources/static/images/flags/cn.svg -- 0.78kb -> 0.75kb (3.9%)
/src/main/resources/static/images/flags/se.svg -- 0.21kb -> 0.20kb (3.76%)
/src/main/resources/static/images/flags/gb.svg -- 0.52kb -> 0.51kb (3.18%)
/src/main/resources/static/images/flags/es-ct.svg -- 0.25kb -> 0.24kb (3.14%)
/src/main/resources/static/pdfjs/images/toolbarButton-editorHighlight.svg -- 0.89kb -> 0.86kb (2.97%)
/src/main/resources/static/pdfjs-legacy/images/toolbarButton-editorHighlight.svg -- 0.89kb -> 0.86kb (2.97%)
/src/main/resources/static/pdfjs/images/editor-toolbar-delete.svg -- 0.89kb -> 0.86kb (2.64%)
/src/main/resources/static/pdfjs-legacy/images/editor-toolbar-delete.svg -- 0.89kb -> 0.86kb (2.64%)
/src/main/resources/static/images/flags/eu.svg -- 0.59kb -> 0.57kb (2.33%)
/src/main/resources/static/images/flags/sk.svg -- 1.17kb -> 1.15kb (1.92%)
/src/main/resources/static/images/flags/es.svg -- 89.66kb -> 88.07kb (1.77%)
/src/main/resources/static/pdfjs/images/toolbarButton-editorFreeText.svg -- 0.49kb -> 0.48kb (1.61%)
/src/main/resources/static/pdfjs-legacy/images/toolbarButton-editorFreeText.svg -- 0.49kb -> 0.48kb (1.61%)
/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-lastPage.svg -- 0.25kb -> 0.25kb (1.56%)
/src/main/resources/static/pdfjs/images/secondaryToolbarButton-lastPage.svg -- 0.25kb -> 0.25kb (1.56%)
/src/main/resources/static/pdfjs/images/secondaryToolbarButton-firstPage.svg -- 0.25kb -> 0.25kb (1.54%)
/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-firstPage.svg -- 0.25kb -> 0.25kb (1.54%)
/src/main/resources/static/images/clipboard.svg -- 0.48kb -> 0.48kb (1.41%)
/src/main/resources/static/images/arrow-right-short.svg -- 0.31kb -> 0.30kb (1.27%)
/src/main/resources/static/pdfjs/images/toolbarButton-viewOutline.svg -- 0.32kb -> 0.32kb (1.2%)
/src/main/resources/static/pdfjs-legacy/images/toolbarButton-viewOutline.svg -- 0.32kb -> 0.32kb (1.2%)
/src/main/resources/static/images/flags/rs.svg -- 179.94kb -> 177.79kb (1.19%)
/src/main/resources/static/images/flags/sa.svg -- 10.04kb -> 9.93kb (1.13%)
/src/main/resources/static/pdfjs/images/secondaryToolbarButton-spreadNone.svg -- 0.39kb -> 0.38kb (1.01%)
/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-spreadNone.svg -- 0.39kb -> 0.38kb (1.01%)
/src/main/resources/static/pdfjs/images/secondaryToolbarButton-documentProperties.svg -- 0.41kb -> 0.40kb (0.96%)
/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-documentProperties.svg -- 0.41kb -> 0.40kb (0.96%)
/src/main/resources/static/images/Files.svg -- 1.32kb -> 1.31kb (0.89%)
/src/main/resources/static/rainbow.svg -- 0.45kb -> 0.44kb (0.87%)
/src/main/resources/static/pdfjs/images/altText_add.svg -- 0.90kb -> 0.89kb (0.87%)
/src/main/resources/static/pdfjs-legacy/images/altText_add.svg -- 0.90kb -> 0.89kb (0.87%)
/src/main/resources/static/pdfjs/images/toolbarButton-zoomOut.svg -- 0.46kb -> 0.46kb (0.85%)
/src/main/resources/static/pdfjs-legacy/images/toolbarButton-zoomOut.svg -- 0.46kb -> 0.46kb (0.85%)
/src/main/resources/static/pdfjs/images/toolbarButton-viewAttachments.svg -- 0.56kb -> 0.55kb (0.7%)
/src/main/resources/static/pdfjs-legacy/images/toolbarButton-viewAttachments.svg -- 0.56kb -> 0.55kb (0.7%)
/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-rotateCw.svg -- 0.56kb -> 0.56kb (0.69%)
/src/main/resources/static/pdfjs/images/secondaryToolbarButton-rotateCw.svg -- 0.56kb -> 0.56kb (0.69%)
/src/main/resources/static/pdfjs/images/findbarButton-next.svg -- 0.56kb -> 0.56kb (0.69%)
/src/main/resources/static/pdfjs-legacy/images/findbarButton-next.svg -- 0.56kb -> 0.56kb (0.69%)
/src/main/resources/static/pdfjs-legacy/images/findbarButton-previous.svg -- 0.56kb -> 0.56kb (0.69%)
/src/main/resources/static/pdfjs/images/findbarButton-previous.svg -- 0.56kb -> 0.56kb (0.69%)
/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-rotateCcw.svg -- 0.58kb -> 0.58kb (0.67%)
/src/main/resources/static/pdfjs/images/secondaryToolbarButton-rotateCcw.svg -- 0.58kb -> 0.58kb (0.67%)
/src/main/resources/static/moon.svg -- 0.58kb -> 0.58kb (0.67%)
/src/main/resources/static/pdfjs/images/toolbarButton-currentOutlineItem.svg -- 0.59kb -> 0.59kb (0.66%)
/src/main/resources/static/pdfjs-legacy/images/toolbarButton-currentOutlineItem.svg -- 0.59kb -> 0.59kb (0.66%)
/src/main/resources/static/images/flags/hr.svg -- 40.21kb -> 39.97kb (0.6%)
/src/main/resources/static/pdfjs-legacy/images/toolbarButton-viewLayers.svg -- 0.66kb -> 0.65kb (0.6%)
/src/main/resources/static/pdfjs/images/toolbarButton-viewLayers.svg -- 0.66kb -> 0.65kb (0.6%)
/src/main/resources/static/pdfjs/images/toolbarButton-presentationMode.svg -- 0.67kb -> 0.66kb (0.59%)
/src/main/resources/static/pdfjs-legacy/images/toolbarButton-menuArrow.svg -- 0.67kb -> 0.66kb (0.59%)
/src/main/resources/static/pdfjs-legacy/images/toolbarButton-presentationMode.svg -- 0.67kb -> 0.66kb (0.59%)
/src/main/resources/static/pdfjs/images/toolbarButton-menuArrow.svg -- 0.67kb -> 0.66kb (0.59%)
/src/main/resources/static/pdfjs-legacy/images/toolbarButton-pageUp.svg -- 0.67kb -> 0.66kb (0.59%)
/src/main/resources/static/pdfjs/images/toolbarButton-pageUp.svg -- 0.67kb -> 0.66kb (0.59%)
/src/main/resources/static/pdfjs/images/toolbarButton-download.svg -- 1.01kb -> 1.01kb (0.58%)
/src/main/resources/static/pdfjs-legacy/images/toolbarButton-download.svg -- 1.01kb -> 1.01kb (0.58%)
/src/main/resources/static/pdfjs-legacy/images/toolbarButton-pageDown.svg -- 0.68kb -> 0.68kb (0.57%)
/src/main/resources/static/pdfjs/images/toolbarButton-pageDown.svg -- 0.68kb -> 0.68kb (0.57%)
/src/main/resources/static/pdfjs/images/secondaryToolbarButton-spreadOdd.svg -- 0.69kb -> 0.69kb (0.56%)
/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-spreadOdd.svg -- 0.69kb -> 0.69kb (0.56%)
/src/main/resources/static/pdfjs-legacy/images/altText_done.svg -- 1.06kb -> 1.06kb (0.55%)
/src/main/resources/static/pdfjs/images/altText_done.svg -- 1.06kb -> 1.06kb (0.55%)
/src/main/resources/static/pdfjs/images/secondaryToolbarButton-scrollPage.svg -- 0.71kb -> 0.71kb (0.55%)
/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-scrollPage.svg -- 0.71kb -> 0.71kb (0.55%)
/src/main/resources/static/images/book.svg -- 0.75kb -> 0.75kb (0.52%)
/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-spreadEven.svg -- 0.76kb -> 0.75kb (0.52%)
/src/main/resources/static/pdfjs/images/secondaryToolbarButton-spreadEven.svg -- 0.76kb -> 0.75kb (0.52%)
/src/main/resources/static/pdfjs-legacy/images/gv-toolbarButton-download.svg -- 0.76kb -> 0.76kb (0.51%)
/src/main/resources/static/pdfjs/images/gv-toolbarButton-download.svg -- 0.76kb -> 0.76kb (0.51%)
/src/main/resources/static/pdfjs/images/toolbarButton-editorInk.svg -- 1.16kb -> 1.16kb (0.5%)
/src/main/resources/static/pdfjs-legacy/images/toolbarButton-editorInk.svg -- 1.16kb -> 1.16kb (0.5%)
/src/main/resources/static/sun.svg -- 0.81kb -> 0.80kb (0.48%)
/src/main/resources/static/pdfjs/images/toolbarButton-bookmark.svg -- 0.84kb -> 0.84kb (0.46%)
/src/main/resources/static/pdfjs-legacy/images/toolbarButton-bookmark.svg -- 0.84kb -> 0.84kb (0.46%)
/src/main/resources/static/images/file-earmark-pdf.svg -- 1.50kb -> 1.49kb (0.46%)
/src/main/resources/static/pdfjs/images/cursor-editorInk.svg -- 1.29kb -> 1.29kb (0.45%)
/src/main/resources/static/pdfjs-legacy/images/cursor-editorInk.svg -- 1.29kb -> 1.29kb (0.45%)
/src/main/resources/static/pdfjs/images/toolbarButton-print.svg -- 0.91kb -> 0.90kb (0.43%)
/src/main/resources/static/pdfjs-legacy/images/toolbarButton-print.svg -- 0.91kb -> 0.90kb (0.43%)
/src/main/resources/static/pdfjs/images/toolbarButton-zoomIn.svg -- 0.94kb -> 0.93kb (0.42%)
/src/main/resources/static/pdfjs-legacy/images/toolbarButton-zoomIn.svg -- 0.94kb -> 0.93kb (0.42%)
/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-scrollVertical.svg -- 0.95kb -> 0.94kb (0.41%)
/src/main/resources/static/pdfjs/images/secondaryToolbarButton-scrollVertical.svg -- 0.95kb -> 0.94kb (0.41%)
/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-scrollHorizontal.svg -- 0.95kb -> 0.94kb (0.41%)
/src/main/resources/static/pdfjs/images/secondaryToolbarButton-scrollHorizontal.svg -- 0.95kb -> 0.94kb (0.41%)
/src/main/resources/static/pdfjs/images/toolbarButton-secondaryToolbarToggle.svg -- 1.05kb -> 1.05kb (0.37%)
/src/main/resources/static/pdfjs-legacy/images/toolbarButton-secondaryToolbarToggle.svg -- 1.05kb -> 1.05kb (0.37%)
/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-selectTool.svg -- 1.06kb -> 1.06kb (0.37%)
/src/main/resources/static/pdfjs/images/secondaryToolbarButton-selectTool.svg -- 1.06kb -> 1.06kb (0.37%)
/src/main/resources/static/pdfjs/images/loading-icon.gif -- 2.49kb -> 2.48kb (0.35%)
/src/main/resources/static/pdfjs-legacy/images/loading-icon.gif -- 2.49kb -> 2.48kb (0.35%)
/src/main/resources/static/pdfjs/images/cursor-editorFreeText.svg -- 1.42kb -> 1.41kb (0.34%)
/src/main/resources/static/pdfjs-legacy/images/cursor-editorFreeText.svg -- 1.42kb -> 1.41kb (0.34%)
/src/main/resources/static/pdfjs/images/secondaryToolbarButton-scrollWrapped.svg -- 1.20kb -> 1.20kb (0.33%)
/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-scrollWrapped.svg -- 1.20kb -> 1.20kb (0.33%)
/src/main/resources/static/pdfjs/images/toolbarButton-search.svg -- 1.21kb -> 1.20kb (0.32%)
/src/main/resources/static/pdfjs-legacy/images/toolbarButton-search.svg -- 1.21kb -> 1.20kb (0.32%)
/src/main/resources/static/images/discord.svg -- 1.24kb -> 1.24kb (0.31%)
/src/main/resources/static/pdfjs/images/secondaryToolbarButton-handTool.svg -- 1.31kb -> 1.31kb (0.3%)
/src/main/resources/static/pdfjs-legacy/images/secondaryToolbarButton-handTool.svg -- 1.31kb -> 1.31kb (0.3%)
/src/main/resources/static/pdfjs-legacy/images/toolbarButton-viewThumbnail.svg -- 1.36kb -> 1.36kb (0.29%)
/src/main/resources/static/pdfjs/images/toolbarButton-viewThumbnail.svg -- 1.36kb -> 1.36kb (0.29%)
/src/main/resources/static/pdfjs/images/toolbarButton-openFile.svg -- 1.37kb -> 1.36kb (0.29%)
/src/main/resources/static/pdfjs-legacy/images/toolbarButton-openFile.svg -- 1.37kb -> 1.36kb (0.29%)
/src/main/resources/static/pdfjs-legacy/images/toolbarButton-sidebarToggle.svg -- 1.52kb -> 1.52kb (0.26%)
/src/main/resources/static/pdfjs/images/toolbarButton-sidebarToggle.svg -- 1.52kb -> 1.52kb (0.26%)
/src/main/resources/static/images/update.svg -- 0.40kb -> 0.40kb (0.24%)
/src/main/resources/static/pdfjs/images/cursor-editorFreeHighlight.svg -- 2.87kb -> 2.86kb (0.2%)
/src/main/resources/static/pdfjs-legacy/images/cursor-editorFreeHighlight.svg -- 2.87kb -> 2.86kb (0.2%)
/src/main/resources/static/pdfjs-legacy/images/cursor-editorTextHighlight.svg -- 5.28kb -> 5.27kb (0.19%)
/src/main/resources/static/pdfjs/images/cursor-editorTextHighlight.svg -- 5.28kb -> 5.27kb (0.19%)

Signed-off-by: ImgBotApp <ImgBotHelp@gmail.com>
Co-authored-by: ImgBotApp <ImgBotHelp@gmail.com>
2024-06-14 19:38:54 +01:00
tkymmm
b7d55a3f78 Update messages_ja_JP.properties (#1457)
Updated Japanese translation
2024-06-14 19:32:39 +01:00
albanobattistella
699545ddbe Update messages_it_IT.properties (#1454) 2024-06-13 21:51:39 +01:00
Pavlo K
54b3f17bf9 Add missing of Ukrainian translation to the resource file (#1448) 2024-06-13 18:14:09 +01:00
HHHHHMMMM
f2015cecbd When converting PDF to word, add parameters to speed up soffice startup (#1450)
When converting PDF to word, add parameters to speed up soffice startup
2024-06-13 18:13:38 +01:00
Sebastian Espei
f60a8d87d2 Add Odd-Even Merge operation mode (#1445)
* Add ODD_EVEN_MERGE sort type

* Add process method to merge odd and even PDF pages

* Add test cases for Odd-Even merge method

* Add Odd-Even Merge mode in PDF Organizer webpage

This also add a new translatable text message variable pdfOrganiser.mode.10 with translation for english and german

* Add ODD_EVEN_MERGE documentation to RearrangePagesRequest

* Add english translation for pdfOrganiser.mode.10

---------

Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
2024-06-12 22:21:02 +01:00
github-actions[bot]
eccebd265f 📝 Update README: Translation Progress Table (#1447)
📝 Sync README
> Made via sync_files.yml

Co-authored-by: GitHub Action action@github.com <GitHub Action action@github.com>
2024-06-12 22:15:32 +01:00
Anthony Stirling
889c9a114b survey (#1446)
* survey

* LANGS
2024-06-12 22:12:42 +01:00
github-actions[bot]
9fd561ecf6 📝 Update README: Translation Progress Table (#1431)
📝 Sync README
> Made via sync_files.yml

Co-authored-by: GitHub Action action@github.com <GitHub Action action@github.com>
2024-06-12 20:36:35 +01:00
Ludy
1e72960c5f Bugfix: missing contextPath (#1434) 2024-06-12 20:36:18 +01:00
小麥
5a50c54f29 Update messages_zh_TW.properties: Translate English sentence to Chinese (#1438)
Update messages_zh_TW.properties

Translate more sentence to zh_TW.
Fix sentence to fit the "Chinese copywriting guidelines".
2024-06-12 20:34:56 +01:00
Ludy
446bc68768 change to Pdf.js-Legacy Version 4.3.136 (#1444)
* add: PDF.js-Legacy

* change path
2024-06-12 20:33:25 +01:00
Abdulwahhab A Alzahrani
76660eb791 Update messages_ar_AR.properties (#1430)
translate to Arabic
2024-06-09 21:20:35 +01:00
github-actions[bot]
e0ce3c90de 💾 Update Version (#1429)
💾 Sync Versions
> Made via sync_files.yml

Co-authored-by: GitHub Action action@github.com <GitHub Action action@github.com>
2024-06-09 17:45:13 +01:00
Anthony Stirling
aaf94fa981 Update build.gradle 2024-06-09 17:44:31 +01:00
dependabot[bot]
d1aa56266e Bump gradle from 7.6-jdk17 to 8.0-jdk17 (#1371)
* Bump gradle from 7.6-jdk17 to 8.0-jdk17

Bumps gradle from 7.6-jdk17 to 8.0-jdk17.

---
updated-dependencies:
- dependency-name: gradle
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>

* Update Dockerfile-fat

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
2024-06-09 16:00:04 +01:00
github-actions[bot]
790d4f053d Update 3rd Party Licenses (#1428)
Signed-off-by: GitHub Action <action@github.com>
Co-authored-by: GitHub Action <action@github.com>
2024-06-09 15:56:15 +01:00
dependabot[bot]
e5b25ac8a5 Bump commons-io:commons-io from 2.15.1 to 2.16.1 (#1055)
Bumps commons-io:commons-io from 2.15.1 to 2.16.1.

---
updated-dependencies:
- dependency-name: commons-io:commons-io
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
2024-06-09 15:54:50 +01:00
Anthony Stirling
b365155e62 Update githubVersion.js 2024-06-09 15:30:20 +01:00
github-actions[bot]
f4f80a54a8 📝 Update README: Translation Progress Table (#1427)
📝 Sync README
> Made via sync_files.yml

Co-authored-by: GitHub Action action@github.com <GitHub Action action@github.com>
2024-06-09 14:20:42 +01:00
github-actions[bot]
681a8d3443 📝 Update README: Translation Progress Table (#1426)
📝 Sync README
> Made via sync_files.yml

Co-authored-by: GitHub Action action@github.com <GitHub Action action@github.com>
2024-06-09 14:05:16 +01:00
Ludy
7543f49ba4 Add: Option to remove the digital signature when merging (#1424) 2024-06-09 13:58:05 +01:00
albanobattistella
2e11b632dd Update messages_it_IT.properties (#1423) 2024-06-09 13:57:13 +01:00
Anthony Stirling
63bdc0d59e Pipeline fixes for json lists + delete func (#1425)
* init

* revert

* pipelines fixes for lists

* pipeline fixes to allow json lists

* formatting

* pipeline changes

* langs

---------

Co-authored-by: a <a>
2024-06-09 13:56:55 +01:00
Anthony Stirling
56fdf1f3a1 Feature request template (#1422)
* Create 2-feature.yml

* Update 2-feature.yml

* Update 2-feature.yml
2024-06-09 11:06:17 +01:00
Ludy
a6069c0f9e Add template for bug issues (#1419) 2024-06-09 10:45:36 +01:00
Ludy
327a44d487 Bump PDF.js from 4.3.118 to 4.3.136 (#1420)
Changelog: https://github.com/mozilla/pdf.js/releases/tag/v4.3.136
2024-06-09 10:45:25 +01:00
Ludy
7a15930453 add password validator (#1418) 2024-06-08 22:36:23 +01:00
github-actions[bot]
517e54517c 📝 Update README: Translation Progress Table (#1416)
📝 Sync README
> Made via sync_files.yml

Co-authored-by: GitHub Action action@github.com <GitHub Action action@github.com>
2024-06-08 16:07:54 +01:00
Anthony Stirling
ef59ea6fe4 Images and login context (#1417)
* init

* revert
2024-06-08 16:07:23 +01:00
imgbot[bot]
10472a6467 [ImgBot] Optimize images (#1412)
*Total -- 412.00kb -> 334.04kb (18.92%)

/images/settings.png -- 12.04kb -> 5.53kb (54.07%)
/images/stirling-home-light.png -- 118.54kb -> 81.18kb (31.51%)
/images/login-light.png -- 30.08kb -> 24.98kb (16.94%)
/images/login-dark.png -- 29.44kb -> 25.32kb (13.98%)
/images/stirling-home.jpg -- 166.42kb -> 144.85kb (12.96%)
/docs/stirling-pdf.png -- 53.00kb -> 49.69kb (6.24%)
/src/main/resources/static/pdfjs/images/loading-icon.gif -- 2.49kb -> 2.48kb (0.35%)

Signed-off-by: ImgBotApp <ImgBotHelp@gmail.com>
Co-authored-by: ImgBotApp <ImgBotHelp@gmail.com>
2024-06-08 15:55:41 +01:00
Ludy
9a9429c15c Bugfix: fixes API query, replaces password comparisons, fixes duplicate ids (#1415)
fixes API query, replaces password comparisons, fixes duplicate ids
2024-06-08 12:37:06 +01:00
github-actions[bot]
b17912d607 📝 Update README: Translation Progress Table (#1414)
📝 Sync README
> Made via sync_files.yml

Co-authored-by: GitHub Action action@github.com <GitHub Action action@github.com>
2024-06-07 22:59:41 +01:00
albanobattistella
ff315d9d96 Update messages_it_IT.properties (#1413) 2024-06-07 22:58:51 +01:00
github-actions[bot]
67f72ad17b 📝 Update README: Translation Progress Table (#1410)
📝 Sync README
> Made via sync_files.yml

Co-authored-by: GitHub Action action@github.com <GitHub Action action@github.com>
2024-06-07 22:27:58 +01:00
Ludy
8f55c38391 add: redesign addUsers.html (#1407)
Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
2024-06-07 22:27:16 +01:00
Anthony Stirling
8245d77c84 Merge pull request #1406 from SorCelien/main
New fr_FR ignore
2024-06-07 22:24:01 +01:00
Anthony Stirling
f5628f16d9 Merge branch 'main' into main 2024-06-07 22:22:32 +01:00
Anthony Stirling
47907daea0 Merge pull request #1405 from SorCelien/patch-1
fr messages: more translations
2024-06-07 22:21:55 +01:00
Anthony Stirling
664253532e Merge pull request #1404 from Ludy87/bypass_github
Add: Bypass for too many requests to the github api
2024-06-07 22:20:44 +01:00
Célien
6108b38098 Merge pull request #1 from SorCelien/patch-1
fr messages: more translations
2024-06-07 18:06:37 +02:00
Célien
a634c63176 New fr_FR ignore 2024-06-07 17:45:21 +02:00
Célien
109ed6a719 Nex fr_FR ignore 2024-06-07 17:40:33 +02:00
Célien
ac9312bd7e fr messages: more translations
mainly oauth translations
2024-06-07 17:35:36 +02:00
Ludy87
a743493cd3 Update navbar.html 2024-06-07 17:24:42 +02:00
Ludy87
c35355f01a Update githubVersion.js 2024-06-07 17:07:14 +02:00
Ludy87
ed910da288 Add: Bypass for too many requests to the github api 2024-06-07 16:54:47 +02:00
Anthony Stirling
fc0878704d Merge pull request #1385 from jimdouk/main
Enhance Test Coverage for SPDF/Utils Classes
2024-06-07 09:38:56 +01:00
Anthony Stirling
d5c71c8425 Merge pull request #1399 from Stirling-Tools/sync_version
💾 Update Version
2024-06-07 09:38:24 +01:00
GitHub Action action@github.com
afbe8f7abe 💾 Sync Versions
> Made via sync_files.yml
2024-06-07 08:37:00 +00:00
Anthony Stirling
3a97ff0e5e Update build.gradle 2024-06-07 09:36:46 +01:00
Anthony Stirling
4f5b19edfb Merge pull request #1397 from Stirling-Tools/pixeebot/drip-2024-06-07-sonar-java/avoid-implicit-public-constructor-s1118
(Sonar) Fixed finding: "Utility classes should not have public constructors"
2024-06-07 09:09:10 +01:00
pixeebot[bot]
88338b4dbc (Sonar) Fixed finding: "Utility classes should not have public constructors" 2024-06-07 07:52:26 +00:00
jimdouk
fc249661e2 Merge branch 'main' of https://github.com/jimdouk/Stirling-PDF 2024-06-07 10:38:21 +03:00
jimdouk
805848e627 Fix one test in Class ProcessExecutorTest 2024-06-07 10:38:05 +03:00
Dimitris Doukas
fdae1c9756 Merge branch 'main' into main 2024-06-07 09:21:06 +03:00
Anthony Stirling
32b3cfca41 Merge pull request #1396 from Stirling-Tools/pixeebot/drip-2024-06-07-sonar-java/add-missing-override-s1161
(Sonar) Fixed finding: "`@Override` should be used on overriding and implementing methods"
2024-06-07 06:27:02 +01:00
pixeebot[bot]
9147d364bc (Sonar) Fixed finding: "@Override should be used on overriding and implementing methods" 2024-06-07 04:38:10 +00:00
Anthony Stirling
6606850e4a fix version number 2024-06-06 22:38:22 +01:00
Anthony Stirling
7b08d98232 Merge pull request #1394 from Stirling-Tools/disableConfigUpdater
Disable config updater
2024-06-06 22:05:53 +01:00
Anthony Stirling
03150c6462 format 2024-06-06 21:59:13 +01:00
a
a3bf7baf35 Merge branch 'disableConfigUpdater' of git@github.com:Stirling-Tools/Stirling-PDF.git into disableConfigUpdater 2024-06-06 21:57:30 +01:00
Anthony Stirling
6c09bcf23c resolve #1386 2024-06-06 21:57:18 +01:00
Anthony Stirling
e11fa01d10 Merge pull request #1393 from Stirling-Tools/disableConfigUpdater
resolve admin config with custom path
2024-06-06 21:43:15 +01:00
Anthony Stirling
d60107f48b Merge branch 'main' into disableConfigUpdater 2024-06-06 21:36:04 +01:00
Anthony Stirling
0b449af9ba resolve path 2024-06-06 21:34:56 +01:00
Anthony Stirling
4c9c0207ba fancy button 2024-06-06 21:27:58 +01:00
Anthony Stirling
d36a59442f th action 2024-06-06 21:24:41 +01:00
Anthony Stirling
fd4c75279f init 2024-06-06 21:23:33 +01:00
Anthony Stirling
fd5f5025ce Merge pull request #1391 from Stirling-Tools/sync_version
💾 Update Version
2024-06-06 20:34:52 +01:00
GitHub Action action@github.com
319ecbcbc1 💾 Sync Versions
> Made via sync_files.yml
2024-06-06 19:23:20 +00:00
Anthony Stirling
04b0bcde61 Merge pull request #1388 from Stirling-Tools/disableConfigUpdater
remove settings files update for now
2024-06-06 20:23:04 +01:00
Anthony Stirling
6499b759d9 Merge pull request #1390 from Ludy87/replace_hardcoded
Enhance OAuth2 Client Registration with Dynamic Provider Details
2024-06-06 20:22:40 +01:00
Anthony Stirling
2081c4872d Merge pull request #1389 from Ludy87/fix_langues_cz_de_nb
Minor corrections in the languages
2024-06-06 20:21:05 +01:00
Ludy87
37c75971f2 Update ApplicationProperties.java 2024-06-06 21:14:34 +02:00
Ludy87
7d9edfca6d Enhance OAuth2 Client Registration with Dynamic Provider Details 2024-06-06 21:03:06 +02:00
Anthony Stirling
a40696f16e remove settings files update for now 2024-06-06 19:49:53 +01:00
Ludy87
515b5b1492 Minor corrections in the languages 2024-06-06 20:42:50 +02:00
jimdouk
5277cf2b59 Add junit tests for utils classes 2024-06-06 12:54:12 +03:00
Anthony Stirling
e824a3e7bd Update build.gradle 2024-06-05 23:18:52 +01:00
Anthony Stirling
9fd508fcc7 Update README.md 2024-06-05 23:17:38 +01:00
Anthony Stirling
a0227a4bdd Merge pull request #1382 from Stirling-Tools/tweaks
tweaks and fix for #1381
2024-06-05 22:35:22 +01:00
Anthony Stirling
87be41117f tweaks and fix for #1381 2024-06-05 21:16:22 +01:00
Anthony Stirling
3e9123fcd5 Merge pull request #1376 from arsvendg/main
Small adjustmens to language file
2024-06-05 18:28:48 +01:00
arsvendg
7e7c6a3832 Small adjustmens to language file 2024-06-05 13:21:17 +02:00
Anthony Stirling
cce31ee0f6 Merge pull request #1373 from arsvendg/main
Norwegian translation
2024-06-05 08:40:19 +01:00
arsvendg
746f341d6a Merge branch 'Stirling-Tools:main' into main 2024-06-05 09:07:11 +02:00
Anthony Stirling
f35bf120e9 Update flatten.html 2024-06-04 20:17:27 +01:00
arsvendg
1fd4ce339f Update languages.html 2024-06-04 00:05:34 +02:00
arsvendg
af736ca33a Add files via upload 2024-06-04 00:03:56 +02:00
arsvendg
0878dd10b8 Add files via upload 2024-06-04 00:03:23 +02:00
Anthony Stirling
948ddb06bc Merge pull request #1362 from Stirling-Tools/sonar
Sonar
2024-06-02 12:12:41 +01:00
Anthony Stirling
efc07522ab minor 2024-06-02 12:04:29 +01:00
Anthony Stirling
31938b662c format 2024-06-02 12:02:01 +01:00
Anthony Stirling
eb526a5d0c logging and try catch 2024-06-02 11:59:43 +01:00
Anthony Stirling
c4a620e3f5 init sonar 2024-06-02 11:42:30 +01:00
Anthony Stirling
17bf6237a2 Update push-docker.yml 2024-06-02 10:52:08 +01:00
Anthony Stirling
086daf8351 Merge pull request #1361 from Stirling-Tools/sync_version
💾 Update Version
2024-06-02 10:32:41 +01:00
GitHub Action action@github.com
2741094a8a 💾 Sync Versions
> Made via sync_files.yml
2024-06-02 09:28:30 +00:00
Anthony Stirling
b4dc766f7a Update build.gradle 2024-06-02 10:28:16 +01:00
Anthony Stirling
75e2cfb234 Merge pull request #1359 from albanobattistella/patch-29
Update messages_it_IT.properties
2024-06-01 22:32:34 +01:00
Anthony Stirling
c5f7000e72 Merge pull request #1360 from Ludy87/remove_digi_sign
new workaround for remove digital signature
2024-06-01 22:31:05 +01:00
Ludy87
ca0432e0b4 notification 2024-06-01 21:33:21 +02:00
Ludy87
5799e61385 new workaround for remove digital signature 2024-06-01 21:30:05 +02:00
albanobattistella
f2784c85d6 Update messages_it_IT.properties 2024-06-01 21:07:02 +02:00
Anthony Stirling
01a3fa8cfe Update push-docker.yml 2024-06-01 14:12:57 +01:00
Anthony Stirling
41138cb2be Merge pull request #1356 from Stirling-Tools/fatDockerAutomation
automate fat docker
2024-06-01 14:03:20 +01:00
Anthony Stirling
995de6abc3 automate fat docker 2024-06-01 13:55:28 +01:00
Anthony Stirling
36deb32f07 Merge pull request #1355 from Stirling-Tools/fatDocker
fat docker
2024-06-01 13:06:51 +01:00
Anthony Stirling
6a38c55867 remove headless due to com.sun.imageio.plugins.jpeg.JPEGImageWriter 2024-06-01 12:57:11 +01:00
Anthony Stirling
96e390c98d Merge branch 'main' into fatDocker 2024-06-01 12:41:51 +01:00
Anthony Stirling
52978ec9ad fat docker 2024-06-01 12:38:10 +01:00
Anthony Stirling
fcd4af2d09 Merge pull request #1354 from foivospro/main
Fix Error When Submitting Crop Tool Without Making a Selection
2024-06-01 12:02:18 +01:00
foiv
963c1f4874 fix the crop problem 2024-06-01 13:58:56 +03:00
Anthony Stirling
aa42806a9e Merge pull request #1352 from Ludy87/fix_admin_exe_windows
Fix: Initialization Issue and Enhance Configuration Management for Co…
2024-06-01 09:41:54 +01:00
Ludy87
19c564a6f7 Fix: Initialization Issue and Enhance Configuration Management for ConfigInitializer #1324 2024-05-31 23:51:42 +02:00
Anthony Stirling
6afbd8bd24 Update build.gradle 2024-05-31 21:04:42 +01:00
Anthony Stirling
76bfc09a44 Merge pull request #1344 from andrewdolphin/main
Update view-pdf.html
2024-05-31 20:55:22 +01:00
Anthony Stirling
6df412c576 Merge pull request #1347 from Stirling-Tools/sync_readme
📝 Update README: Translation Progress Table
2024-05-31 20:55:09 +01:00
Anthony Stirling
37bb890cb9 Merge branch 'main' into sync_readme 2024-05-31 20:54:55 +01:00
Anthony Stirling
9bd15d7ef3 Update README.md 2024-05-31 20:53:05 +01:00
Anthony Stirling
b0671943f7 Merge pull request #1345 from onyxfin/main
Croatian language Translation.
2024-05-31 20:50:30 +01:00
GitHub Action action@github.com
7cbad4df4f 📝 Sync README
> Made via sync_files.yml
2024-05-31 19:50:13 +00:00
Anthony Stirling
e27651826e Merge pull request #1346 from Ludy87/remove_cert_sign
add remove digital signature
2024-05-31 20:49:57 +01:00
onyxfin
5b0de9eac1 Update languages.html 2024-05-31 15:45:47 +02:00
onyxfin
b646d8c481 Add files via upload 2024-05-31 15:24:01 +02:00
andrewdolphin
cd2f628168 Update view-pdf.html
Remove bootstrap.css which regresses a previous issue that caused imported images to incorrectly resize.

Reintroduce "Import image" option.
2024-05-31 12:16:57 +01:00
Ludy87
aef0d32b5b add remove digital signature 2024-05-31 11:31:07 +02:00
onyxfin
e761ad8e51 Merge pull request #1 from onyxfin/onyxfin-patch-1
Add files via upload
2024-05-30 22:11:09 +02:00
onyxfin
059296d444 Add files via upload 2024-05-30 22:01:29 +02:00
Anthony Stirling
9c1de1cb10 Merge pull request #1336 from Stirling-Tools/sync_readme
📝 Update README: Translation Progress Table
2024-05-30 20:55:34 +01:00
Anthony Stirling
ebba39ce10 Merge pull request #1334 from Ludy87/fix_docker_sso
add properties Docker
2024-05-30 20:54:28 +01:00
Anthony Stirling
361b4c2db4 Merge pull request #1333 from Ludy87/fix_viewer_pdf
Fix: Can't select the Draw tool in View #1328
2024-05-30 20:54:15 +01:00
Anthony Stirling
d221654121 Merge pull request #1331 from pcanham/hotfix/typo-fix-for-google
fix: type correction around google OAUTH2 provider
2024-05-30 20:54:08 +01:00
GitHub Action action@github.com
7ac41d7863 📝 Sync README
> Made via sync_files.yml
2024-05-30 19:54:03 +00:00
Anthony Stirling
f1476d197f Merge pull request #1326 from NicolasFR/feat/utf8-mdToPdf
feat: Force UTF-8 encoding of input characters
2024-05-30 20:53:58 +01:00
Anthony Stirling
4a53195c25 Merge pull request #1322 from albanobattistella/patch-28
Update messages_it_IT.properties
2024-05-30 20:53:50 +01:00
Anthony Stirling
e2bed6f6af Merge pull request #1321 from nimdassdev/main
Update messages_bg_BG.properties
2024-05-30 20:53:45 +01:00
Anthony Stirling
5d6e23d4b7 Merge pull request #1282 from kkdlau/bugfix/1214-grab-zero-byte-pdf
#1214 Only take pdf that are good for processing
2024-05-30 20:53:21 +01:00
Ludy87
dfb8ba857f add properties Docker 2024-05-30 11:52:13 +02:00
Ludy87
1572404e6f Fix: Can't select the Draw tool in View #1328 2024-05-30 11:42:49 +02:00
Paul Canham
76dc90d587 fi: type correction around google OAUTH2 provider 2024-05-30 09:42:23 +01:00
Anthony Stirling
316b4e42af Update README.md 2024-05-29 23:36:14 +01:00
Nicolas
f61bbd312f feat: Force UTF-8 encoding of input characters 2024-05-29 22:09:09 +02:00
Danny Lau
65b9544942 #1214 Fix unable to create FileMonitor if the root directory does not exist 2024-05-29 23:03:24 +08:00
albanobattistella
7e8b86e6eb Update messages_it_IT.properties 2024-05-29 12:08:25 +02:00
IT Creativity + Art Team
2ab5bc1e18 Update messages_bg_BG.properties
Updated/improved Bulgarian language strings. Thank you.
2024-05-29 09:56:21 +03:00
Dimitris Doukas
52e9689431 Merge branch 'Stirling-Tools:main' into main 2024-05-28 11:43:21 +03:00
Danny Lau
17ef2e9b5d Merge branch 'main' into bugfix/1214-grab-zero-byte-pdf 2024-05-25 08:20:57 +08:00
Danny Lau
801dcdb463 #1214 Only take files that are good for processing 2024-05-25 00:22:01 +08:00
Dimitris Doukas
caa5525ddd Merge branch 'Stirling-Tools:main' into main 2024-05-02 15:41:23 +03:00
648 changed files with 154378 additions and 3612 deletions

2
.gitattributes vendored
View File

@@ -3,6 +3,8 @@
# Ignore all JavaScript files in a directory
src/main/resources/static/pdfjs/* linguist-vendored
src/main/resources/static/pdfjs/** linguist-vendored
src/main/resources/static/pdfjs-legacy/* linguist-vendored
src/main/resources/static/pdfjs-legacy/** linguist-vendored
src/main/resources/static/css/bootstrap-icons.css linguist-vendored
src/main/resources/static/css/bootstrap.min.css linguist-vendored
src/main/resources/static/css/fonts/* linguist-vendored

116
.github/ISSUE_TEMPLATE/1-bug.yml vendored Normal file
View File

@@ -0,0 +1,116 @@
name: Bug Report
description: File a bug report.
title: "[Bug]: "
body:
- type: markdown
attributes:
value: |
## Bug Report
Thanks for taking the time to fill out this bug report!
This issue form is for reporting bugs only. Please fill out the following sections to help us understand the issue you are facing.
- type: textarea
id: problem
validations:
required: true
attributes:
label: The Problem
description: |
Describe the issue you are experiencing here. Tell us what you were trying to do and what happened.
Provide a clear and concise description of what the problem is.
placeholder: Provide a detailed description of the issue.
- type: markdown
attributes:
value: |
## Environment
- type: input
id: version
validations:
required: true
attributes:
label: Version of Stirling-PDF
placeholder: e.g., 0.0.2
description: What version of Stirling-PDF has the issue?
- type: input
id: last-working-version
attributes:
label: Last Working Version of Stirling-PDF
placeholder: e.g., 0.0.1
description: |
If known, please provide the last version where the issue did not occur. Otherwise, leave blank.
- type: input
id: url
attributes:
label: Page Where the Problem Occurred
placeholder: e.g., http://localhost:8080/pdf/pipeline
description: |
If applicable, provide the URL where the issue occurred. Otherwise, leave blank.
- type: textarea
id: docker
attributes:
label: Docker Configuration
description: |
Enter your Docker configuration here if it is relevant to the error. Remove any personal data. Otherwise, leave the field blank.
render: txt
- type: markdown
attributes:
value: |
## Logs
- type: textarea
id: logs
attributes:
label: Relevant Log Output
description: |
Provide any log output that might help us diagnose the issue, such as error messages or stack traces.
render: txt
- type: markdown
attributes:
value: |
## Additional Information
- type: textarea
id: additional-info
attributes:
label: Additional Information
description: |
If you have any additional information that might help us understand and resolve the issue, provide it here.
- type: markdown
attributes:
value: |
## Browser Information
- type: dropdown
id: browsers
attributes:
label: Browsers Affected
description: |
If applicable, select the browsers where you are experiencing the issue. Otherwise, leave blank.
multiple: true
options:
- Firefox
- Chrome
- Safari
- Microsoft Edge
- Other
- type: checkboxes
id: terms
attributes:
label: No Duplicate of the Issue
description: |
Please confirm that you have searched for similar issues and none of them match your problem.
options:
- label: I have verified that there are no existing issues raised related to my problem.
required: true

76
.github/ISSUE_TEMPLATE/2-feature.yml vendored Normal file
View File

@@ -0,0 +1,76 @@
name: Feature Request
description: Submit a new feature request.
title: "[Feature Request]: "
body:
- type: markdown
attributes:
value: |
## Feature Request
Thank you for taking the time to suggest a new feature!
This form is for proposing features or enhancements. Please fill out the following sections to help us understand your idea or suggestion.
- type: textarea
id: feature-description
validations:
required: true
attributes:
label: Feature Description
description: |
Describe the feature you would like to see. Tell us what the feature should do and the problem it would solve.
Provide a clear and concise description of what you want to happen.
placeholder: Provide a detailed description of the desired feature.
- type: markdown
attributes:
value: |
## Motivation
- type: textarea
id: motivation
attributes:
label: Why is this feature valuable?
description: |
Explain why this feature is valuable to you or others. How would it improve the tool or process?
Describe any relevant scenarios that would benefit from this feature.
placeholder: Describe why this feature is important.
- type: markdown
attributes:
value: |
## Possible Implementation
- type: textarea
id: implementation
attributes:
label: Suggested Implementation
description: |
If you have ideas about how this feature could be implemented, describe them here.
This section is optional but can be helpful to guide initial discussions.
placeholder: Describe how this feature might be implemented.
- type: markdown
attributes:
value: |
## Additional Information
- type: textarea
id: additional-info
attributes:
label: Additional Information
description: |
If you have any additional information, comments, or resources you think would support or be relevant to your feature request, include them here.
- type: checkboxes
id: search-confirmation
attributes:
label: No Duplicate of the Feature
description: |
Please confirm that you have searched for similar features in our repository and found none that match your request.
options:
- label: I have verified that there are no existing features requests similar to my request.
required: true

5
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -0,0 +1,5 @@
blank_issues_enabled: true
contact_links:
- name: 💬 Discord Server
url: https://discord.gg/Cn8pWhQRxZ
about: You can join our Discord server for real time discussion and support

View File

@@ -110,3 +110,31 @@ jobs:
labels: ${{ steps.meta2.outputs.labels }}
build-args: VERSION_TAG=${{ steps.versionNumber.outputs.versionNumber }}
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
View File

@@ -0,0 +1,84 @@
# Build the application
FROM gradle:8.7-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"]

View File

@@ -1,46 +1,47 @@
| Operation | PageOps | Convert | Security | Other | CLI | Python | OpenCV | LibreOffice | OCRmyPDF | Java | Javascript |
|---------------------|---------|---------|----------|-------|------|--------|--------|-------------|----------|----------|------------|
| adjust-contrast | ✔️ | | | | | | | | | | ✔️ |
| auto-split-pdf | ✔️ | | | | | | | | | ✔️ | |
| crop | ✔️ | | | | | | | | | ✔️ | |
| extract-page | ✔️ | | | | | | | | | ✔️ | |
| merge-pdfs | ✔️ | | | | | | | | | ✔️ | |
| multi-page-layout | ✔️ | | | | | | | | | ✔️ | |
| pdf-organizer | ✔️ | | | | | | | | | ✔️ | ✔️ |
| pdf-to-single-page | ✔️ | | | | | | | | | ✔️ | |
| remove-pages | ✔️ | | | | | | | | | ✔️ | |
| rotate-pdf | ✔️ | | | | | | | | | ✔️ | |
| scale-pages | ✔️ | | | | | | | | | ✔️ | |
| split-pdfs | ✔️ | | | | | | | | | ✔️ | |
| file-to-pdf | | ✔️ | | | ✔️ | | | ✔️ | | | |
| img-to-pdf | | ✔️ | | | | | | | | ✔️ | |
| pdf-to-html | | ✔️ | | | ✔️ | | | ✔️ | | | |
| pdf-to-img | | ✔️ | | | | | | | | ✔️ | |
| pdf-to-pdfa | | ✔️ | | | ✔️ | | | | ✔️ | | |
| pdf-to-markdown | | ✔️ | | | | | | | | ✔️ | |
| pdf-to-presentation | | ✔️ | | | ✔️ | | | ✔️ | | | |
| pdf-to-text | | ✔️ | | | ✔️ | | | ✔️ | | | |
| pdf-to-word | | ✔️ | | | ✔️ | | | ✔️ | | | |
| pdf-to-xml | | ✔️ | | | ✔️ | | | ✔️ | | | |
| xlsx-to-pdf | | ✔️ | | | ✔️ | | | ✔️ | | | |
| add-password | | | ✔️ | | | | | | | ✔️ | |
| add-watermark | | | ✔️ | | | | | | | ✔️ | |
| cert-sign | | | ✔️ | | | | | | | ✔️ | |
| change-permissions | | | ✔️ | | | | | | | ✔️ | |
| remove-password | | | ✔️ | | | | | | | ✔️ | |
| sanitize-pdf | | | ✔️ | | | | | | | ✔️ | |
| add-image | | | | ✔️ | | | | | | ✔️ | |
| add-page-numbers | | | | ✔️ | | | | | | ✔️ | |
| auto-rename | | | | ✔️ | | | | | | ✔️ | |
| change-metadata | | | | ✔️ | | | | | | ✔️ | |
| compare | | | | ✔️ | | | | | | | ✔️ |
| compress-pdf | | | | ✔️ | ✔️ | | | | ✔️ | | |
| extract-image-scans | | | | ✔️ | ✔️ | ✔️ | ✔️ | | | | |
| extract-images | | | | ✔️ | | | | | | ✔️ | |
| flatten | | | | ✔️ | | | | | | | ✔️ |
| get-info-on-pdf | | | | ✔️ | | | | | | ✔️ | |
| ocr-pdf | | | | ✔️ | ✔️ | | | | ✔️ | | |
| remove-blanks | | | | ✔️ | ✔️ | ✔️ | ✔️ | | | | |
| repair | | | | ✔️ | ✔️ | | | ✔️ | | | |
| show-javascript | | | | ✔️ | | | | | | | ✔️ |
| sign | | | | ✔️ | | | | | | | ✔️ |
| Operation | PageOps | Convert | Security | Other | CLI | Python | OpenCV | LibreOffice | OCRmyPDF | Java | Javascript |
| ------------------- | ------- | ------- | -------- | ----- | --- | ------ | ------ | ----------- | -------- | ---- | ---------- |
| adjust-contrast | ✔️ | | | | | | | | | | ✔️ |
| auto-split-pdf | ✔️ | | | | | | | | | ✔️ | |
| crop | ✔️ | | | | | | | | | ✔️ | |
| extract-page | ✔️ | | | | | | | | | ✔️ | |
| merge-pdfs | ✔️ | | | | | | | | | ✔️ | |
| multi-page-layout | ✔️ | | | | | | | | | ✔️ | |
| pdf-organizer | ✔️ | | | | | | | | | ✔️ | ✔️ |
| pdf-to-single-page | ✔️ | | | | | | | | | ✔️ | |
| remove-pages | ✔️ | | | | | | | | | ✔️ | |
| rotate-pdf | ✔️ | | | | | | | | | ✔️ | |
| scale-pages | ✔️ | | | | | | | | | ✔️ | |
| split-pdfs | ✔️ | | | | | | | | | ✔️ | |
| file-to-pdf | | ✔️ | | | ✔️ | | | ✔️ | | | |
| img-to-pdf | | ✔️ | | | | | | | | ✔️ | |
| pdf-to-html | | ✔️ | | | ✔️ | | | ✔️ | | | |
| pdf-to-img | | ✔️ | | | | | | | | ✔️ | |
| pdf-to-pdfa | | ✔️ | | | ✔️ | | | | ✔️ | | |
| pdf-to-markdown | | ✔️ | | | | | | | | ✔️ | |
| pdf-to-presentation | | ✔️ | | | ✔️ | | | ✔️ | | | |
| pdf-to-text | | ✔️ | | | ✔️ | | | ✔️ | | | |
| pdf-to-word | | ✔️ | | | ✔️ | | | ✔️ | | | |
| pdf-to-xml | | ✔️ | | | ✔️ | | | ✔️ | | | |
| xlsx-to-pdf | | ✔️ | | | ✔️ | | | ✔️ | | | |
| add-password | | | ✔️ | | | | | | | ✔️ | |
| add-watermark | | | ✔️ | | | | | | | ✔️ | |
| cert-sign | | | ✔️ | | | | | | | ✔️ | |
| remove-cert-sign | | | ✔️ | | | | | | | ✔️ | |
| change-permissions | | | ✔️ | | | | | | | ✔️ | |
| remove-password | | | ✔️ | | | | | | | ✔️ | |
| sanitize-pdf | | | ✔️ | | | | | | | ✔️ | |
| add-image | | | | ✔️ | | | | | | ✔️ | |
| add-page-numbers | | | | ✔️ | | | | | | ✔️ | |
| auto-rename | | | | ✔️ | | | | | | ✔️ | |
| change-metadata | | | | ✔️ | | | | | | ✔️ | |
| compare | | | | ✔️ | | | | | | | ✔️ |
| compress-pdf | | | | ✔️ | ✔️ | | | | ✔️ | | |
| extract-image-scans | | | | ✔️ | ✔️ | ✔️ | ✔️ | | | | |
| extract-images | | | | ✔️ | | | | | | ✔️ | |
| flatten | | | | ✔️ | | | | | | | ✔️ |
| get-info-on-pdf | | | | ✔️ | | | | | | ✔️ | |
| ocr-pdf | | | | ✔️ | ✔️ | | | | ✔️ | | |
| remove-blanks | | | | ✔️ | ✔️ | ✔️ | ✔️ | | | | |
| repair | | | | ✔️ | ✔️ | | | ✔️ | | | |
| show-javascript | | | | ✔️ | | | | | | | ✔️ |
| sign | | | | ✔️ | | | | | | | ✔️ |

View File

@@ -159,39 +159,41 @@ Please view https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToUseOCR
## Supported Languages
Stirling PDF currently supports 28!
Stirling PDF currently supports 32!
| Language | Progress |
| ------------------------------------------- | -------------------------------------- |
| English (English) (en_GB) | ![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) |
| German (Deutsch) (de_DE) | ![100%](https://geps.dev/progress/100) |
| French (Français) (fr_FR) | ![94%](https://geps.dev/progress/94) |
| Spanish (Español) (es_ES) | ![96%](https://geps.dev/progress/96) |
| Simplified Chinese (简体中文) (zh_CN) | ![96%](https://geps.dev/progress/96) |
| Traditional Chinese (繁體中文) (zh_TW) | ![95%](https://geps.dev/progress/95) |
| Arabic (العربية) (ar_AR) | ![46%](https://geps.dev/progress/46) |
| German (Deutsch) (de_DE) | ![99%](https://geps.dev/progress/99) |
| French (Français) (fr_FR) | ![93%](https://geps.dev/progress/93) |
| Spanish (Español) (es_ES) | ![93%](https://geps.dev/progress/93) |
| Simplified Chinese (简体中文) (zh_CN) | ![94%](https://geps.dev/progress/94) |
| Traditional Chinese (繁體中文) (zh_TW) | ![98%](https://geps.dev/progress/98) |
| Catalan (Català) (ca_CA) | ![49%](https://geps.dev/progress/49) |
| Italian (Italiano) (it_IT) | ![99%](https://geps.dev/progress/99) |
| Swedish (Svenska) (sv_SE) | ![41%](https://geps.dev/progress/41) |
| Polish (Polski) (pl_PL) | ![43%](https://geps.dev/progress/43) |
| Romanian (Română) (ro_RO) | ![40%](https://geps.dev/progress/40) |
| Korean (한국어) (ko_KR) | ![88%](https://geps.dev/progress/88) |
| Portuguese Brazilian (Português) (pt_BR) | ![62%](https://geps.dev/progress/62) |
| Russian (Русский) (ru_RU) | ![88%](https://geps.dev/progress/88) |
| Basque (Euskara) (eu_ES) | ![64%](https://geps.dev/progress/64) |
| Japanese (日本語) (ja_JP) | ![88%](https://geps.dev/progress/88) |
| Dutch (Nederlands) (nl_NL) | ![86%](https://geps.dev/progress/86) |
| Greek (Ελληνικά) (el_GR) | ![86%](https://geps.dev/progress/86) |
| Turkish (Türkçe) (tr_TR) | ![98%](https://geps.dev/progress/98) |
| Indonesia (Bahasa Indonesia) (id_ID) | ![79%](https://geps.dev/progress/79) |
| Hindi (हिंदी) (hi_IN) | ![80%](https://geps.dev/progress/80) |
| Hungarian (Magyar) (hu_HU) | ![79%](https://geps.dev/progress/79) |
| Italian (Italiano) (it_IT) | ![98%](https://geps.dev/progress/98) |
| Swedish (Svenska) (sv_SE) | ![40%](https://geps.dev/progress/40) |
| Polish (Polski) (pl_PL) | ![42%](https://geps.dev/progress/42) |
| Romanian (Română) (ro_RO) | ![39%](https://geps.dev/progress/39) |
| Korean (한국어) (ko_KR) | ![86%](https://geps.dev/progress/86) |
| Portuguese Brazilian (Português) (pt_BR) | ![61%](https://geps.dev/progress/61) |
| Russian (Русский) (ru_RU) | ![86%](https://geps.dev/progress/86) |
| Basque (Euskara) (eu_ES) | ![63%](https://geps.dev/progress/63) |
| Japanese (日本語) (ja_JP) | ![86%](https://geps.dev/progress/86) |
| Dutch (Nederlands) (nl_NL) | ![83%](https://geps.dev/progress/83) |
| Greek (Ελληνικά) (el_GR) | ![84%](https://geps.dev/progress/84) |
| Turkish (Türkçe) (tr_TR) | ![96%](https://geps.dev/progress/96) |
| Indonesia (Bahasa Indonesia) (id_ID) | ![78%](https://geps.dev/progress/78) |
| Hindi (हिंदी) (hi_IN) | ![79%](https://geps.dev/progress/79) |
| Hungarian (Magyar) (hu_HU) | ![77%](https://geps.dev/progress/77) |
| Bulgarian (Български) (bg_BG) | ![96%](https://geps.dev/progress/96) |
| Sebian Latin alphabet (Srpski) (sr_LATN_RS) | ![81%](https://geps.dev/progress/81) |
| Ukrainian (Українська) (uk_UA) | ![87%](https://geps.dev/progress/87) |
| Slovakian (Slovensky) (sk_SK) | ![96%](https://geps.dev/progress/96) |
| Czech (Česky) (cs_CZ) | ![94%](https://geps.dev/progress/94) |
| Sebian Latin alphabet (Srpski) (sr_LATN_RS) | ![80%](https://geps.dev/progress/80) |
| Ukrainian (Українська) (uk_UA) | ![85%](https://geps.dev/progress/85) |
| Slovakian (Slovensky) (sk_SK) | ![93%](https://geps.dev/progress/93) |
| Czech (Česky) (cs_CZ) | ![92%](https://geps.dev/progress/92) |
| Croatian (Hrvatski) (hr_HR) | ![97%](https://geps.dev/progress/97) |
| Norwegian (Norsk) (no_NB) | ![97%](https://geps.dev/progress/97) |
## Contributing (creating issues, translations, fixing bugs, etc.)
@@ -213,10 +215,10 @@ For example in the settings.yml you have
```yaml
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

View File

@@ -1,52 +1,53 @@
| Technology | Ultra-Lite | Full |
|----------------|:----------:|:----:|
| Java | ✔️ | ✔️ |
| JavaScript | ✔️ | ✔️ |
| Libre | | ✔️ |
| Python | | ✔️ |
| OpenCV | | ✔️ |
| OCRmyPDF | | ✔️ |
| Technology | Ultra-Lite | Full |
| ---------- | :--------: | :---: |
| Java | ✔️ | ✔️ |
| JavaScript | ✔️ | ✔️ |
| Libre | | ✔️ |
| Python | | ✔️ |
| OpenCV | | ✔️ |
| OCRmyPDF | | ✔️ |
Operation | Ultra-Lite | Full
-------------------------|------------|-----
add-page-numbers | ✔️ | ✔️
add-password | ✔️ | ✔️
add-image | ✔️ | ✔️
add-watermark | ✔️ | ✔️
adjust-contrast | ✔️ | ✔️
auto-split-pdf | ✔️ | ✔️
auto-redact | ✔️ | ✔️
auto-rename | ✔️ | ✔️
cert-sign | ✔️ | ✔️
crop | ✔️ | ✔️
change-metadata | ✔️ | ✔️
change-permissions | ✔️ | ✔️
compare | ✔️ | ✔️
extract-page | ✔️ | ✔️
extract-images | ✔️ | ✔️
flatten | ✔️ | ✔️
get-info-on-pdf | ✔️ | ✔️
img-to-pdf | ✔️ | ✔️
markdown-to-pdf | ✔️ | ✔️
merge-pdfs | ✔️ | ✔️
multi-page-layout | ✔️ | ✔️
overlay-pdf | ✔️ | ✔️
pdf-organizer | ✔️ | ✔️
pdf-to-csv | ✔️ | ✔️
pdf-to-img | ✔️ | ✔️
pdf-to-single-page | ✔️ | ✔️
remove-pages | ✔️ | ✔️
remove-password | ✔️ | ✔️
rotate-pdf | ✔️ | ✔️
sanitize-pdf | ✔️ | ✔️
scale-pages | ✔️ | ✔️
sign | ✔️ | ✔️
show-javascript | ✔️ | ✔️
split-by-size-or-count | ✔️ | ✔️
split-pdf-by-sections | ✔️ | ✔️
split-pdfs | ✔️ | ✔️
compress-pdf | | ✔️
extract-image-scans | | ✔️
ocr-pdf | | ✔️
pdf-to-pdfa | | ✔️
remove-blanks | | ✔️
| Operation | Ultra-Lite | Full |
| ---------------------- | ---------- | ---- |
| add-page-numbers | ✔️ | ✔️ |
| add-password | ✔️ | ✔️ |
| add-image | ✔️ | ✔️ |
| add-watermark | ✔️ | ✔️ |
| adjust-contrast | ✔️ | ✔️ |
| auto-split-pdf | ✔️ | ✔️ |
| auto-redact | ✔️ | ✔️ |
| auto-rename | ✔️ | ✔️ |
| cert-sign | ✔️ | ✔️ |
| remove-cert-sign | ✔️ | ✔️ |
| crop | ✔️ | ✔️ |
| change-metadata | ✔️ | ✔️ |
| change-permissions | ✔️ | ✔️ |
| compare | ✔️ | ✔️ |
| extract-page | ✔️ | ✔️ |
| extract-images | ✔️ | ✔️ |
| flatten | ✔️ | ✔️ |
| get-info-on-pdf | ✔️ | ✔️ |
| img-to-pdf | ✔️ | ✔️ |
| markdown-to-pdf | ✔️ | ✔️ |
| merge-pdfs | ✔️ | ✔️ |
| multi-page-layout | ✔️ | ✔️ |
| overlay-pdf | ✔️ | ✔️ |
| pdf-organizer | ✔️ | ✔️ |
| pdf-to-csv | ✔️ | ✔️ |
| pdf-to-img | ✔️ | ✔️ |
| pdf-to-single-page | ✔️ | ✔️ |
| remove-pages | ✔️ | ✔️ |
| remove-password | ✔️ | ✔️ |
| rotate-pdf | ✔️ | ✔️ |
| sanitize-pdf | ✔️ | ✔️ |
| scale-pages | ✔️ | ✔️ |
| sign | ✔️ | ✔️ |
| show-javascript | ✔️ | ✔️ |
| split-by-size-or-count | ✔️ | ✔️ |
| split-pdf-by-sections | ✔️ | ✔️ |
| split-pdfs | ✔️ | ✔️ |
| compress-pdf | | ✔️ |
| extract-image-scans | | ✔️ |
| ocr-pdf | | ✔️ |
| pdf-to-pdfa | | ✔️ |
| remove-blanks | | ✔️ |

View File

@@ -12,7 +12,7 @@ plugins {
import com.github.jk1.license.render.*
group = 'stirling.software'
version = '0.25.0'
version = '0.26.1'
//17 is lowest but we support and recommend 21
sourceCompatibility = '17'
@@ -21,7 +21,6 @@ repositories {
mavenCentral()
}
licenseReport {
renderers = [new JsonReportRenderer()]
}
@@ -136,7 +135,7 @@ dependencies {
implementation 'com.twelvemonkeys.imageio:imageio-webp:3.10.1'
// implementation 'com.twelvemonkeys.imageio:imageio-xwd:3.10.1'
implementation 'commons-io:commons-io:2.15.1'
implementation 'commons-io:commons-io:2.16.1'
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0'
//general PDF
@@ -172,14 +171,14 @@ dependencies {
annotationProcessor 'org.projectlombok:lombok:1.18.32'
}
tasks.withType(JavaCompile) {
tasks.withType(JavaCompile).configureEach {
dependsOn 'spotlessApply'
}
compileJava {
options.compilerArgs << '-parameters'
}
task writeVersion {
task writeVersion {
def propsFile = file('src/main/resources/version.properties')
def props = new Properties()
props.setProperty('version', version)
@@ -196,8 +195,6 @@ swaggerhubUpload {
oas '3.0.0' // The version of the OpenAPI Specification you're using
}
jar {
enabled = false
manifest {
@@ -211,6 +208,6 @@ tasks.named('test') {
useJUnitPlatform()
}
task printVersion {
println project.version
task printVersion {
println project.version
}

View File

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 50 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

View File

@@ -1,110 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg
version="1.1"
id="Layer_1"
x="0px"
y="0px"
viewBox="0 0 512 512"
style="enable-background:new 0 0 512 512;"
xml:space="preserve"
sodipodi:docname="favicon.svg"
inkscape:version="1.2.2 (732a01da63, 2022-12-09)"
inkscape:export-filename="favicon.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs173">
<linearGradient
id="XMLID_5_"
gradientUnits="userSpaceOnUse"
x1="304.496"
y1="422.9102"
x2="316.036"
y2="326.2626">
<stop
offset="0"
style="stop-color:#DCF1F3"
id="stop156" />
<stop
offset="1"
style="stop-color:#C2C2C9"
id="stop158" />
</linearGradient>
</defs><sodipodi:namedview
id="namedview171"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="1.4142136"
inkscape:cx="219.91021"
inkscape:cy="232.63813"
inkscape:window-width="3840"
inkscape:window-height="2054"
inkscape:window-x="2869"
inkscape:window-y="-11"
inkscape:window-maximized="1"
inkscape:current-layer="XMLID_4_" />
<style
type="text/css"
id="style150">
.st0{fill:#FFFFFF;}
.st1{fill:#C02223;}
.st2{fill:#882425;}
.st3{fill:url(#XMLID_5_);}
.st4{fill:url(#XMLID_7_);}
</style>
<g
id="XMLID_4_">
<path
id="XMLID_131_"
class="st1"
d="M 347.01402,14.355825 98.978019,69.02261 C 73.825483,74.547445 55.942464,96.792175 55.942464,122.52628 v 315.06096 c 0,22.39012 16.719895,41.14548 38.819234,43.76251 L 224.8861,498.36042 339.48636,384.26465 455.76603,265.15425 453.73057,84.870162 C 453.43979,62.916214 433.08513,46.632491 411.71274,51.284984 l -28.78729,6.251786 0.14539,-13.666697 C 383.36162,24.678542 365.62399,10.284894 347.01402,14.355825 Z"
sodipodi:nodetypes="ccssccccccccc"
style="stroke-width:1.45391" /><path
id="XMLID_117_"
class="st2"
d="m 383.21622,57.53677 v 285.8375 L 456.05681,265.00885 454.02135,78.763767 C 453.87595,59.863016 436.28372,45.905539 417.81914,49.97647 Z"
style="stroke-width:1.45391" /><polygon
id="XMLID_18_"
class="st3"
points="234.7,422.6 368.5,387.7 393.5,262.2 "
style="fill:url(#XMLID_5_)"
transform="matrix(1.4556308,0,0,1.4548265,-116.73161,-116.45231)" />
<linearGradient
id="XMLID_7_"
gradientUnits="userSpaceOnUse"
x1="223.0838"
y1="372.7559"
x2="241.4174"
y2="114.557"
gradientTransform="matrix(1.4539039,0,0,1.4539039,-116.19976,-116.20474)">
<stop
offset="0"
style="stop-color:#DCF1F3"
id="stop163" />
<stop
offset="1"
style="stop-color:#C2C2C9"
id="stop165" />
</linearGradient>
<path
id="XMLID_6_"
class="st4"
d="m 282.89686,214.84917 c 0,0 -22.24473,-28.93269 -38.67384,-36.78377 -10.46811,-4.94327 -26.02489,-6.83335 -38.23768,-0.72695 -18.02841,9.0142 -19.91848,34.31213 -3.34397,44.34406 3.92553,2.47165 9.15959,4.50711 15.99294,6.10641 36.63838,8.43264 97.12077,25.87949 89.70587,96.10304 0,0 -4.21633,65.86185 -73.56753,73.42215 -12.2128,1.30851 -24.57098,0.43617 -36.493,-2.32625 -16.42911,-3.63476 -45.50719,-11.04967 -59.75545,-19.91849 l -2.61703,-75.16682 h 6.97875 c 0,0 13.81208,33.43978 53.06749,49.57812 7.26952,2.90781 15.26599,4.07093 22.97168,2.90781 9.74116,-1.45391 21.22699,-6.68796 25.87949,-22.53551 0,0 7.85108,-23.11707 -32.85823,-35.76604 -32.56744,-10.17733 -63.24481,-20.64543 -75.89378,-54.95757 -5.961,-16.28371 -6.97874,-34.31212 -2.90781,-51.61358 5.37944,-22.53551 20.79082,-54.23062 64.40794,-67.89732 0,0 57.28381,-15.55677 96.53922,5.52484 l -1.74468,89.70587 z"
style="fill:url(#XMLID_7_);stroke-width:1.45391" />
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" id="Layer_1" x="0" y="0" version="1.1" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512" xml:space="preserve"><defs id="defs173"><linearGradient id="XMLID_5_" x1="304.496" x2="316.036" y1="422.91" y2="326.263" gradientUnits="userSpaceOnUse"><stop offset="0" style="stop-color:#dcf1f3" id="stop156"/><stop offset="1" style="stop-color:#c2c2c9" id="stop158"/></linearGradient></defs><style id="style150" type="text/css">.st1{fill:#c02223}.st2{fill:#882425}.st3{fill:url(#XMLID_5_)}.st4{fill:url(#XMLID_7_)}</style><g id="XMLID_4_"><path id="XMLID_131_" d="M 347.01402,14.355825 98.978019,69.02261 C 73.825483,74.547445 55.942464,96.792175 55.942464,122.52628 v 315.06096 c 0,22.39012 16.719895,41.14548 38.819234,43.76251 L 224.8861,498.36042 339.48636,384.26465 455.76603,265.15425 453.73057,84.870162 C 453.43979,62.916214 433.08513,46.632491 411.71274,51.284984 l -28.78729,6.251786 0.14539,-13.666697 C 383.36162,24.678542 365.62399,10.284894 347.01402,14.355825 Z" class="st1" style="stroke-width:1.45391"/><path id="XMLID_117_" d="m 383.21622,57.53677 v 285.8375 L 456.05681,265.00885 454.02135,78.763767 C 453.87595,59.863016 436.28372,45.905539 417.81914,49.97647 Z" class="st2" style="stroke-width:1.45391"/><polygon id="XMLID_18_" points="234.7 422.6 368.5 387.7 393.5 262.2" class="st3" style="fill:url(#XMLID_5_)" transform="matrix(1.4556308,0,0,1.4548265,-116.73161,-116.45231)"/><linearGradient id="XMLID_7_" x1="223.084" x2="241.417" y1="372.756" y2="114.557" gradientTransform="matrix(1.4539039,0,0,1.4539039,-116.19976,-116.20474)" gradientUnits="userSpaceOnUse"><stop offset="0" style="stop-color:#dcf1f3" id="stop163"/><stop offset="1" style="stop-color:#c2c2c9" id="stop165"/></linearGradient><path id="XMLID_6_" d="m 282.89686,214.84917 c 0,0 -22.24473,-28.93269 -38.67384,-36.78377 -10.46811,-4.94327 -26.02489,-6.83335 -38.23768,-0.72695 -18.02841,9.0142 -19.91848,34.31213 -3.34397,44.34406 3.92553,2.47165 9.15959,4.50711 15.99294,6.10641 36.63838,8.43264 97.12077,25.87949 89.70587,96.10304 0,0 -4.21633,65.86185 -73.56753,73.42215 -12.2128,1.30851 -24.57098,0.43617 -36.493,-2.32625 -16.42911,-3.63476 -45.50719,-11.04967 -59.75545,-19.91849 l -2.61703,-75.16682 h 6.97875 c 0,0 13.81208,33.43978 53.06749,49.57812 7.26952,2.90781 15.26599,4.07093 22.97168,2.90781 9.74116,-1.45391 21.22699,-6.68796 25.87949,-22.53551 0,0 7.85108,-23.11707 -32.85823,-35.76604 -32.56744,-10.17733 -63.24481,-20.64543 -75.89378,-54.95757 -5.961,-16.28371 -6.97874,-34.31212 -2.90781,-51.61358 5.37944,-22.53551 20.79082,-54.23062 64.40794,-67.89732 0,0 57.28381,-15.55677 96.53922,5.52484 l -1.74468,89.70587 z" class="st4" style="fill:url(#XMLID_7_);stroke-width:1.45391"/></g></svg>

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

View 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

View File

@@ -13,7 +13,7 @@ services:
timeout: 10s
retries: 16
ports:
- 8080:8080
- "8080:8080"
volumes:
- /stirling/latest/data:/usr/share/tessdata: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_CLIENTSECRET: "<YOUR CLIENT SECRET>" # Client Secret from your provider
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
PGID: 1002
UMASK: "022"

View File

@@ -13,7 +13,7 @@ services:
timeout: 10s
retries: 16
ports:
- 8080:8080
- "8080:8080"
volumes:
- /stirling/latest/data:/usr/share/tessdata:rw
- /stirling/latest/config:/configs:rw

View File

@@ -13,7 +13,7 @@ services:
timeout: 10s
retries: 16
ports:
- 8080:8080
- "8080:8080"
volumes:
- /stirling/latest/data:/usr/share/tessdata:rw
- /stirling/latest/config:/configs:rw

View File

@@ -13,7 +13,7 @@ services:
timeout: 10s
retries: 16
ports:
- 8080:8080
- "8080:8080"
volumes:
- /stirling/latest/config:/configs:rw
- /stirling/latest/logs:/logs:rw

View File

@@ -13,7 +13,7 @@ services:
timeout: 10s
retries: 16
ports:
- 8080:8080
- "8080:8080"
volumes:
- /stirling/latest/data:/usr/share/tessdata:rw
- /stirling/latest/config:/configs:rw

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

BIN
images/settings-light.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 166 KiB

After

Width:  |  Height:  |  Size: 145 KiB

View File

@@ -0,0 +1,43 @@
{
"name": "OCR images",
"pipeline": [
{
"operation": "/api/v1/convert/img/pdf",
"parameters": {
"fitOption": "fillPage",
"colorType": "color",
"autoRotate": true,
"fileInput": "automated"
}
},
{
"operation": "/api/v1/general/merge-pdfs",
"parameters": {
"sortType": "orderProvided",
"fileInput": "automated"
}
},
{
"operation": "/api/v1/misc/ocr-pdf",
"parameters": {
"languages": [
"eng"
],
"sidecar": false,
"deskew": false,
"clean": false,
"cleanFinal": false,
"ocrType": "skip-text",
"ocrRenderType": "hocr",
"removeImagesAfter": false,
"fileInput": "automated"
}
}
],
"_examples": {
"outputDir": "{outputFolder}/{folderName}",
"outputFileName": "{filename}-{pipelineName}-{date}-{time}"
},
"outputDir": "{outputFolder}",
"outputFileName": "{filename}"
}

View File

@@ -11,14 +11,16 @@ if [ ! -z "$PGID" ] && [ "$PGID" != "$(getent group stirlingpdfgroup | cut -d: -
fi
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
fi
/scripts/download-security-jar.sh
if [[ "$FAT_DOCKER" != "true" ]]; then
/scripts/download-security-jar.sh
fi
if [[ -n "$LANGS" ]]; then
/scripts/installFonts.sh $LANGS
/scripts/installFonts.sh $LANGS
fi
echo "Setting permissions and ownership for necessary directories..."

View File

@@ -15,7 +15,10 @@ ignore = [
[cs_CZ]
ignore = [
'info',
'language.direction',
'pipeline.header',
'text',
]
[de_DE]
@@ -58,6 +61,7 @@ ignore = [
[fr_FR]
ignore = [
'language.direction',
'sponsor',
]
[hi_IN]
@@ -65,6 +69,16 @@ ignore = [
'language.direction',
]
[hr_HR]
ignore = [
'font',
'home.pipeline.title',
'info',
'language.direction',
'pdfOrganiser.tags',
'showJS.tags',
]
[hu_HU]
ignore = [
'language.direction',
@@ -103,6 +117,11 @@ ignore = [
'language.direction',
]
[no_NB]
ignore = [
'language.direction',
]
[pl_PL]
ignore = [
'language.direction',

View File

@@ -6,11 +6,15 @@ import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.github.pixee.security.SystemCommand;
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 int LISTENER_PORT = 2002;
@@ -27,14 +31,12 @@ public class LibreOfficeListener {
private LibreOfficeListener() {}
private boolean isListenerRunning() {
try {
System.out.println("waiting for listener to start");
Socket socket = new Socket();
System.out.println("waiting for listener to start");
try (Socket socket = new Socket()) {
socket.connect(
new InetSocketAddress("localhost", 2002), 1000); // Timeout after 1 second
socket.close();
return true;
} catch (IOException e) {
} catch (Exception e) {
return false;
}
}
@@ -63,6 +65,7 @@ public class LibreOfficeListener {
try {
Thread.sleep(5000); // Check for inactivity every 5 seconds
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
@@ -80,8 +83,8 @@ public class LibreOfficeListener {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Thread.currentThread().interrupt();
logger.error("exception", e);
} // Check every 1 second
}
}

View File

@@ -2,9 +2,13 @@ package stirling.software.SPDF.config;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
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.boot.autoconfigure.condition.ConditionalOnMissingClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@@ -22,6 +26,8 @@ import stirling.software.SPDF.model.ApplicationProperties;
@Lazy
public class AppConfig {
private static final Logger logger = LoggerFactory.getLogger(AppConfig.class);
@Autowired ApplicationProperties applicationProperties;
@Bean
@@ -54,7 +60,7 @@ public class AppConfig {
props.load(resource.getInputStream());
return props.getProperty("version");
} catch (IOException e) {
e.printStackTrace();
logger.error("exception", e);
}
return "0.0.0";
}
@@ -108,4 +114,26 @@ public class AppConfig {
public boolean missingActivSecurity() {
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");
}
};
}
}

View File

@@ -58,7 +58,8 @@ public class CleanUrlInterceptor implements HandlerInterceptor {
// Redirect to the URL with only allowed query parameters
String redirectUrl = requestURI + "?" + newQueryString;
response.sendRedirect(redirectUrl);
response.sendRedirect(request.getContextPath() + redirectUrl);
return false;
}
}

View File

@@ -7,7 +7,6 @@ import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import org.springframework.context.ApplicationContextInitializer;
@@ -45,46 +44,47 @@ public class ConfigInitializer
}
}
} else {
Path templatePath =
Paths.get(
getClass()
.getClassLoader()
.getResource("settings.yml.template")
.toURI());
Path userPath = Paths.get("configs", "settings.yml");
List<String> templateLines = Files.readAllLines(templatePath);
List<String> userLines =
Files.exists(userPath) ? Files.readAllLines(userPath) : new ArrayList<>();
List<String> resultLines = new ArrayList<>();
int position = 0;
for (String templateLine : templateLines) {
// Check if the line is a comment
if (templateLine.trim().startsWith("#")) {
String entry = templateLine.trim().substring(1).trim();
if (!entry.isEmpty()) {
// Check if this comment has been uncommented in userLines
String key = entry.split(":")[0].trim();
addLine(resultLines, userLines, templateLine, key, position);
} else {
resultLines.add(templateLine);
}
}
// Check if the line is a key-value pair
else if (templateLine.contains(":")) {
String key = templateLine.split(":")[0].trim();
addLine(resultLines, userLines, templateLine, key, position);
}
// Handle empty lines
else if (templateLine.trim().length() == 0) {
resultLines.add("");
}
position++;
}
// Write the result to the user settings file
Files.write(userPath, resultLines);
// Path templatePath =
// Paths.get(
// getClass()
// .getClassLoader()
// .getResource("settings.yml.template")
// .toURI());
// Path userPath = Paths.get("configs", "settings.yml");
//
// List<String> templateLines = Files.readAllLines(templatePath);
// List<String> userLines =
// Files.exists(userPath) ? Files.readAllLines(userPath) : new
// ArrayList<>();
//
// List<String> resultLines = new ArrayList<>();
// int position = 0;
// for (String templateLine : templateLines) {
// // Check if the line is a comment
// if (templateLine.trim().startsWith("#")) {
// String entry = templateLine.trim().substring(1).trim();
// if (!entry.isEmpty()) {
// // Check if this comment has been uncommented in userLines
// String key = entry.split(":")[0].trim();
// addLine(resultLines, userLines, templateLine, key, position);
// } else {
// resultLines.add(templateLine);
// }
// }
// // Check if the line is a key-value pair
// else if (templateLine.contains(":")) {
// String key = templateLine.split(":")[0].trim();
// addLine(resultLines, userLines, templateLine, key, position);
// }
// // Handle empty lines
// else if (templateLine.trim().length() == 0) {
// resultLines.add("");
// }
// position++;
// }
//
// // Write the result to the user settings file
// Files.write(userPath, resultLines);
}
Path customSettingsPath = Paths.get("configs", "custom_settings.yml");

View File

@@ -116,6 +116,7 @@ public class EndpointConfiguration {
addEndpointToGroup("Security", "change-permissions");
addEndpointToGroup("Security", "add-watermark");
addEndpointToGroup("Security", "cert-sign");
addEndpointToGroup("Security", "remove-cert-sign");
addEndpointToGroup("Security", "sanitize-pdf");
addEndpointToGroup("Security", "auto-redact");
@@ -200,6 +201,7 @@ public class EndpointConfiguration {
addEndpointToGroup("Java", "extract-images");
addEndpointToGroup("Java", "change-metadata");
addEndpointToGroup("Java", "cert-sign");
addEndpointToGroup("Java", "remove-cert-sign");
addEndpointToGroup("Java", "multi-page-layout");
addEndpointToGroup("Java", "scale-pages");
addEndpointToGroup("Java", "add-page-numbers");

View File

@@ -1,16 +1,18 @@
package stirling.software.SPDF.config;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.thymeleaf.IEngineConfiguration;
import org.thymeleaf.templateresolver.AbstractConfigurableTemplateResolver;
import org.thymeleaf.templateresource.ClassLoaderTemplateResource;
import org.thymeleaf.templateresource.FileTemplateResource;
import org.thymeleaf.templateresource.ITemplateResource;
import stirling.software.SPDF.model.InputStreamTemplateResource;
public class FileFallbackTemplateResolver extends AbstractConfigurableTemplateResolver {
private final ResourceLoader resourceLoader;
@@ -40,9 +42,13 @@ public class FileFallbackTemplateResolver extends AbstractConfigurableTemplateRe
}
return new ClassLoaderTemplateResource(
Thread.currentThread().getContextClassLoader(),
"classpath:/templates/" + resourceName,
characterEncoding);
InputStream inputStream =
Thread.currentThread()
.getContextClassLoader()
.getResourceAsStream("templates/" + resourceName);
if (inputStream != null) {
return new InputStreamTemplateResource(inputStream, "UTF-8");
}
return null;
}
}

View File

@@ -36,7 +36,6 @@ public class MetricsFilter extends OncePerRequestFilter {
|| uri.startsWith("/v1/api-docs")
|| uri.endsWith("robots.txt")
|| uri.startsWith("/images")
|| uri.startsWith("/images")
|| uri.endsWith(".png")
|| uri.endsWith(".ico")
|| uri.endsWith(".css")

View File

@@ -18,6 +18,7 @@ class AppUpdateAuthService implements ShowAdminInterface {
@Autowired private UserRepository userRepository;
@Autowired private ApplicationProperties applicationProperties;
@Override
public boolean getShowUpdateOnlyAdmins() {
boolean showUpdate = applicationProperties.getSystem().getShowUpdate();
if (!showUpdate) {

View File

@@ -42,36 +42,39 @@ public class CustomAuthenticationFailureHandler extends SimpleUrlAuthenticationF
String ip = request.getRemoteAddr();
logger.error("Failed login attempt from IP: {}", ip);
String contextPath = request.getContextPath();
if (exception.getClass().isAssignableFrom(InternalAuthenticationServiceException.class)
|| "Password must not be null".equalsIgnoreCase(exception.getMessage())) {
response.sendRedirect("/login?error=oauth2AuthenticationError");
response.sendRedirect(contextPath + "/login?error=oauth2AuthenticationError");
return;
}
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(
"Remaining attempts for user {}: {}",
username,
optUser.get().getUsername(),
loginAttemptService.getRemainingAttempts(username));
loginAttemptService.loginFailed(username);
if (loginAttemptService.isBlocked(username)
|| exception.getClass().isAssignableFrom(LockedException.class)) {
response.sendRedirect("/login?error=locked");
response.sendRedirect(contextPath + "/login?error=locked");
return;
}
}
if (exception.getClass().isAssignableFrom(BadCredentialsException.class)
|| exception.getClass().isAssignableFrom(UsernameNotFoundException.class)) {
response.sendRedirect("/login?error=badcredentials");
response.sendRedirect(contextPath + "/login?error=badcredentials");
return;
}
super.onAuthenticationFailure(request, response, exception);
}
private boolean isDemoUser(String username) {
Optional<User> user = userService.findByUsernameIgnoreCase(username);
private boolean isDemoUser(Optional<User> user) {
return user.isPresent()
&& user.get().getAuthorities().stream()
.anyMatch(authority -> "ROLE_DEMO_USER".equals(authority.getAuthority()));

View File

@@ -37,7 +37,8 @@ public class CustomAuthenticationSuccessHandler
: null;
if (savedRequest != null
&& !RequestUriUtils.isStaticResource(savedRequest.getRedirectUrl())) {
&& !RequestUriUtils.isStaticResource(
request.getContextPath(), savedRequest.getRedirectUrl())) {
// Redirect to the original destination
super.onAuthenticationSuccess(request, response, authentication);
} else {

View File

@@ -28,8 +28,10 @@ public class FirstLoginFilter extends OncePerRequestFilter {
throws ServletException, IOException {
String method = request.getMethod();
String requestURI = request.getRequestURI();
String contextPath = request.getContextPath();
// Check if the request is for static resources
boolean isStaticResource = RequestUriUtils.isStaticResource(requestURI);
boolean isStaticResource = RequestUriUtils.isStaticResource(contextPath, requestURI);
// If it's a static resource, just continue the filter chain and skip the logic below
if (isStaticResource) {
@@ -43,8 +45,8 @@ public class FirstLoginFilter extends OncePerRequestFilter {
if ("GET".equalsIgnoreCase(method)
&& user.isPresent()
&& user.get().isFirstLogin()
&& !"/change-creds".equals(requestURI)) {
response.sendRedirect("/change-creds");
&& !(contextPath + "/change-creds").equals(requestURI)) {
response.sendRedirect(contextPath + "/change-creds");
return;
}
}

View File

@@ -33,7 +33,8 @@ public class IPRateLimitingFilter implements Filter {
String method = httpRequest.getMethod();
String requestURI = httpRequest.getRequestURI();
// Check if the request is for static resources
boolean isStaticResource = RequestUriUtils.isStaticResource(requestURI);
boolean isStaticResource =
RequestUriUtils.isStaticResource(httpRequest.getContextPath(), requestURI);
// If it's a static resource, just continue the filter chain and skip the logic below
if (isStaticResource) {

View File

@@ -33,7 +33,6 @@ public class LoginAttemptService {
}
public void loginSucceeded(String key) {
logger.info(key + " " + attemptsCache.mappingCount());
if (key == null || key.trim().isEmpty()) {
return;
}

View File

@@ -238,7 +238,7 @@ public class SecurityConfiguration {
GoogleProvider google = client.getGoogle();
return google != null && google.isSettingsValid()
? Optional.of(
ClientRegistration.withRegistrationId("google")
ClientRegistration.withRegistrationId(google.getName())
.clientId(google.getClientId())
.clientSecret(google.getClientSecret())
.scope(google.getScopes())
@@ -246,8 +246,8 @@ public class SecurityConfiguration {
.tokenUri(google.getTokenuri())
.userInfoUri(google.getUserinfouri())
.userNameAttributeName(google.getUseAsUsername())
.clientName("Google")
.redirectUri("{baseUrl}/login/oauth2/code/google")
.clientName(google.getClientName())
.redirectUri("{baseUrl}/login/oauth2/code/" + google.getName())
.authorizationGrantType(
org.springframework.security.oauth2.core
.AuthorizationGrantType.AUTHORIZATION_CODE)
@@ -269,12 +269,12 @@ public class SecurityConfiguration {
return keycloak != null && keycloak.isSettingsValid()
? Optional.of(
ClientRegistrations.fromIssuerLocation(keycloak.getIssuer())
.registrationId("keycloak")
.registrationId(keycloak.getName())
.clientId(keycloak.getClientId())
.clientSecret(keycloak.getClientSecret())
.scope(keycloak.getScopes())
.userNameAttributeName(keycloak.getUseAsUsername())
.clientName("Keycloak")
.clientName(keycloak.getClientName())
.build())
: Optional.empty();
}
@@ -291,7 +291,7 @@ public class SecurityConfiguration {
GithubProvider github = client.getGithub();
return github != null && github.isSettingsValid()
? Optional.of(
ClientRegistration.withRegistrationId("github")
ClientRegistration.withRegistrationId(github.getName())
.clientId(github.getClientId())
.clientSecret(github.getClientSecret())
.scope(github.getScopes())
@@ -299,8 +299,8 @@ public class SecurityConfiguration {
.tokenUri(github.getTokenuri())
.userInfoUri(github.getUserinfouri())
.userNameAttributeName(github.getUseAsUsername())
.clientName("GitHub")
.redirectUri("{baseUrl}/login/oauth2/code/github")
.clientName(github.getClientName())
.redirectUri("{baseUrl}/login/oauth2/code/" + github.getName())
.authorizationGrantType(
org.springframework.security.oauth2.core
.AuthorizationGrantType.AUTHORIZATION_CODE)

View File

@@ -104,6 +104,7 @@ public class UserAuthenticationFilter extends OncePerRequestFilter {
contextPath + "/fonts/",
contextPath + "/js/",
contextPath + "/pdfjs/",
contextPath + "/pdfjs-legacy/",
contextPath + "/api/v1/info/status",
contextPath + "/site.webmanifest"
};

View File

@@ -48,13 +48,14 @@ public class CustomOAuth2AuthenticationSuccessHandler
// Get the saved request
HttpSession session = request.getSession(false);
String contextPath = request.getContextPath();
SavedRequest savedRequest =
(session != null)
? (SavedRequest) session.getAttribute("SPRING_SECURITY_SAVED_REQUEST")
: null;
if (savedRequest != null
&& !RequestUriUtils.isStaticResource(savedRequest.getRedirectUrl())) {
&& !RequestUriUtils.isStaticResource(contextPath, savedRequest.getRedirectUrl())) {
// Redirect to the original destination
super.onAuthenticationSuccess(request, response, authentication);
} else {
@@ -75,16 +76,15 @@ public class CustomOAuth2AuthenticationSuccessHandler
&& !userService.isAuthenticationTypeByUsername(
username, AuthenticationType.OAUTH2)
&& oAuth.getAutoCreateUser()) {
response.sendRedirect(
request.getContextPath() + "/logout?oauth2AuthenticationErrorWeb=true");
response.sendRedirect(contextPath + "/logout?oauth2AuthenticationErrorWeb=true");
return;
} else {
try {
userService.processOAuth2PostLogin(username, oAuth.getAutoCreateUser());
response.sendRedirect("/");
response.sendRedirect(contextPath + "/");
return;
} catch (IllegalArgumentException e) {
response.sendRedirect("/logout?invalidUsername=true");
response.sendRedirect(contextPath + "/logout?invalidUsername=true");
return;
}
}

View File

@@ -52,7 +52,7 @@ public class CustomOAuth2LogoutSuccessHandler extends SimpleUrlLogoutSuccessHand
issuer = provider.getIssuer();
clientId = provider.getClientId();
} catch (Exception e) {
e.printStackTrace();
logger.error("exception", e);
}
} else {
@@ -60,13 +60,13 @@ public class CustomOAuth2LogoutSuccessHandler extends SimpleUrlLogoutSuccessHand
issuer = oauth.getIssuer();
clientId = oauth.getClientId();
}
String errorMessage = "";
if (request.getParameter("oauth2AuthenticationErrorWeb") != null) {
param = "erroroauth=oauth2AuthenticationErrorWeb";
} else if (request.getParameter("error") != null) {
param = "error=" + request.getParameter("error");
} else if (request.getParameter("erroroauth") != null) {
param = "erroroauth=" + request.getParameter("erroroauth");
} else if ((errorMessage = request.getParameter("error")) != null) {
param = "error=" + sanitizeInput(errorMessage);
} else if ((errorMessage = request.getParameter("erroroauth")) != null) {
param = "erroroauth=" + sanitizeInput(errorMessage);
} else if (request.getParameter("oauth2AutoCreateDisabled") != null) {
param = "error=oauth2AutoCreateDisabled";
}
@@ -81,7 +81,7 @@ public class CustomOAuth2LogoutSuccessHandler extends SimpleUrlLogoutSuccessHand
logger.info("Session invalidated: " + sessionId);
}
switch (registrationId) {
switch (registrationId.toLowerCase()) {
case "keycloak":
// Add Keycloak specific logout URL if needed
String logoutUrl =
@@ -115,4 +115,8 @@ public class CustomOAuth2LogoutSuccessHandler extends SimpleUrlLogoutSuccessHand
break;
}
}
private String sanitizeInput(String input) {
return input.replaceAll("[^a-zA-Z0-9 ]", "");
}
}

View File

@@ -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.UserService;
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;
public class CustomOAuth2UserService implements OAuth2UserService<OidcUserRequest, OidcUser> {
@@ -41,11 +43,27 @@ public class CustomOAuth2UserService implements OAuth2UserService<OidcUserReques
@Override
public OidcUser loadUser(OidcUserRequest userRequest) throws OAuth2AuthenticationException {
String usernameAttribute =
applicationProperties.getSecurity().getOAUTH2().getUseAsUsername();
OAUTH2 oauth2 = applicationProperties.getSecurity().getOAUTH2();
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 {
OidcUser user = delegate.loadUser(userRequest);
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);
if (duser.isPresent()) {
if (loginAttemptService.isBlocked(username)) {
@@ -56,13 +74,14 @@ public class CustomOAuth2UserService implements OAuth2UserService<OidcUserReques
throw new IllegalArgumentException("Password must not be null");
}
}
// Return a new OidcUser with adjusted attributes
return new DefaultOidcUser(
user.getAuthorities(),
userRequest.getIdToken(),
user.getUserInfo(),
usernameAttribute);
} catch (java.lang.IllegalArgumentException e) {
} catch (IllegalArgumentException e) {
logger.error("Error loading OIDC user: {}", e.getMessage());
throw new OAuth2AuthenticationException(new OAuth2Error(e.getMessage()), e);
} catch (Exception e) {

View File

@@ -10,11 +10,16 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.pdfbox.Loader;
import org.apache.pdfbox.multipdf.PDFMergerUtility;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDDocumentCatalog;
import org.apache.pdfbox.pdmodel.PDPage;
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;
@@ -38,6 +43,7 @@ public class MergeController {
private static final Logger logger = LoggerFactory.getLogger(MergeController.class);
// Merges a list of PDDocument objects into a single PDDocument
public PDDocument mergeDocuments(List<PDDocument> documents) throws IOException {
PDDocument mergedDoc = new PDDocument();
for (PDDocument doc : documents) {
@@ -48,6 +54,7 @@ public class MergeController {
return mergedDoc;
}
// Returns a comparator for sorting MultipartFile arrays based on the given sort type
private Comparator<MultipartFile> getSortComparator(String sortType) {
switch (sortType) {
case "byFileName":
@@ -108,37 +115,78 @@ public class MergeController {
"This endpoint merges multiple PDF files into a single PDF file. The merged file will contain all pages from the input files in the order they were provided. Input:PDF Output:PDF Type:MISO")
public ResponseEntity<byte[]> mergePdfs(@ModelAttribute MergePdfsRequest form)
throws IOException {
List<File> filesToDelete = new ArrayList<File>();
List<File> filesToDelete = new ArrayList<>(); // List of temporary files to delete
ByteArrayOutputStream docOutputstream =
new ByteArrayOutputStream(); // Stream for the merged document
PDDocument mergedDocument = null;
boolean removeCertSign = form.isRemoveCertSign();
try {
MultipartFile[] files = form.getFileInput();
Arrays.sort(files, getSortComparator(form.getSortType()));
PDFMergerUtility mergedDoc = new PDFMergerUtility();
ByteArrayOutputStream docOutputstream = new ByteArrayOutputStream();
Arrays.sort(
files,
getSortComparator(
form.getSortType())); // Sort files based on the given sort type
PDFMergerUtility mergerUtility = new PDFMergerUtility();
for (MultipartFile multipartFile : files) {
File tempFile = GeneralUtils.convertMultipartFileToFile(multipartFile);
filesToDelete.add(tempFile);
mergedDoc.addSource(tempFile);
File tempFile =
GeneralUtils.convertMultipartFileToFile(
multipartFile); // Convert MultipartFile to File
filesToDelete.add(tempFile); // Add temp file to the list for later deletion
mergerUtility.addSource(tempFile); // Add source file to the merger utility
}
mergerUtility.setDestinationStream(
docOutputstream); // Set the output stream for the merged document
mergerUtility.mergeDocuments(null); // Merge the documents
byte[] mergedPdfBytes = docOutputstream.toByteArray(); // Get merged document bytes
// Load the merged PDF document
mergedDocument = Loader.loadPDF(mergedPdfBytes);
// Remove signatures if removeCertSign is true
if (removeCertSign) {
PDDocumentCatalog catalog = mergedDocument.getDocumentCatalog();
PDAcroForm acroForm = catalog.getAcroForm();
if (acroForm != null) {
List<PDField> fieldsToRemove =
acroForm.getFields().stream()
.filter(field -> field instanceof PDSignatureField)
.collect(Collectors.toList());
if (!fieldsToRemove.isEmpty()) {
acroForm.flatten(
fieldsToRemove,
false); // Flatten the fields, effectively removing them
}
}
}
mergedDoc.setDestinationFileName(
files[0].getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_merged.pdf");
mergedDoc.setDestinationStream(docOutputstream);
mergedDoc.mergeDocuments(null);
// Save the modified document to a new ByteArrayOutputStream
ByteArrayOutputStream baos = new ByteArrayOutputStream();
mergedDocument.save(baos);
String mergedFileName =
files[0].getOriginalFilename().replaceFirst("[.][^.]+$", "")
+ "_merged_unsigned.pdf";
return WebResponseUtils.bytesToWebResponse(
docOutputstream.toByteArray(), mergedDoc.getDestinationFileName());
baos.toByteArray(), mergedFileName); // Return the modified PDF
} catch (Exception ex) {
logger.error("Error in merge pdf process", ex);
throw ex;
} finally {
for (File file : filesToDelete) {
if (file != null) {
Files.deleteIfExists(file.toPath());
Files.deleteIfExists(file.toPath()); // Delete temporary files
}
}
docOutputstream.close();
if (mergedDocument != null) {
mergedDocument.close(); // Close the merged document
}
}
}
}

View File

@@ -145,6 +145,28 @@ public class RearrangePagesPDFController {
return newPageOrder;
}
/**
* Rearrange pages in a PDF file by merging odd and even pages. The first half of the pages will
* be the odd pages, and the second half will be the even pages as input. <br>
* This method is visible for testing purposes only.
*
* @param totalPages Total number of pages in the PDF file.
* @return List of page numbers in the new order. The first page is 0.
*/
List<Integer> oddEvenMerge(int totalPages) {
List<Integer> newPageOrderZeroBased = new ArrayList<>();
int numberOfOddPages = (totalPages + 1) / 2;
for (int oneBasedIndex = 1; oneBasedIndex < (numberOfOddPages + 1); oneBasedIndex++) {
newPageOrderZeroBased.add((oneBasedIndex - 1));
if (numberOfOddPages + oneBasedIndex <= totalPages) {
newPageOrderZeroBased.add((numberOfOddPages + oneBasedIndex - 1));
}
}
return newPageOrderZeroBased;
}
private List<Integer> processSortTypes(String sortTypes, int totalPages) {
try {
SortTypes mode = SortTypes.valueOf(sortTypes.toUpperCase());
@@ -159,6 +181,8 @@ public class RearrangePagesPDFController {
return sideStitchBooklet(totalPages);
case ODD_EVEN_SPLIT:
return oddEvenSplit(totalPages);
case ODD_EVEN_MERGE:
return oddEvenMerge(totalPages);
case REMOVE_FIRST:
return removeFirst(totalPages);
case REMOVE_LAST:

View File

@@ -18,6 +18,8 @@ import org.apache.pdfbox.pdmodel.PDPageContentStream.AppendMode;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject;
import org.apache.pdfbox.util.Matrix;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ModelAttribute;
@@ -38,6 +40,9 @@ import stirling.software.SPDF.utils.WebResponseUtils;
@Tag(name = "General", description = "General APIs")
public class SplitPdfBySectionsController {
private static final Logger logger =
LoggerFactory.getLogger(SplitPdfBySectionsController.class);
@PostMapping(value = "/split-pdf-by-sections", consumes = "multipart/form-data")
@Operation(
summary = "Split PDF pages into smaller sections",
@@ -92,7 +97,7 @@ public class SplitPdfBySectionsController {
if (sectionNum == horiz * verti) pageNum++;
}
} catch (Exception e) {
e.printStackTrace();
logger.error("exception", e);
} finally {
data = Files.readAllBytes(zipFile);
Files.deleteIfExists(zipFile);

View File

@@ -10,6 +10,8 @@ import java.util.zip.ZipOutputStream;
import org.apache.pdfbox.Loader;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ModelAttribute;
@@ -31,6 +33,8 @@ import stirling.software.SPDF.utils.WebResponseUtils;
@Tag(name = "General", description = "General APIs")
public class SplitPdfBySizeController {
private static final Logger logger = LoggerFactory.getLogger(SplitPdfBySizeController.class);
@PostMapping(value = "/split-by-size-or-count", consumes = "multipart/form-data")
@Operation(
summary = "Auto split PDF pages into separate documents based on size or count",
@@ -66,7 +70,7 @@ public class SplitPdfBySizeController {
}
} catch (Exception e) {
e.printStackTrace();
logger.error("exception", e);
} finally {
data = Files.readAllBytes(zipFile);
Files.deleteIfExists(zipFile);

View File

@@ -59,53 +59,53 @@ public class UserController {
@PostMapping("/change-username")
public RedirectView changeUsername(
Principal principal,
@RequestParam(name = "currentPassword") String currentPassword,
@RequestParam(name = "currentPasswordChangeUsername") String currentPassword,
@RequestParam(name = "newUsername") String newUsername,
HttpServletRequest request,
HttpServletResponse response,
RedirectAttributes redirectAttributes) {
if (!userService.isUsernameValid(newUsername)) {
return new RedirectView("/account?messageType=invalidUsername");
return new RedirectView("/account?messageType=invalidUsername", true);
}
if (principal == null) {
return new RedirectView("/account?messageType=notAuthenticated");
return new RedirectView("/account?messageType=notAuthenticated", true);
}
// The username MUST be unique when renaming
Optional<User> userOpt = userService.findByUsername(principal.getName());
if (userOpt == null || userOpt.isEmpty()) {
return new RedirectView("/account?messageType=userNotFound");
return new RedirectView("/account?messageType=userNotFound", true);
}
User user = userOpt.get();
if (user.getUsername().equals(newUsername)) {
return new RedirectView("/account?messageType=usernameExists");
return new RedirectView("/account?messageType=usernameExists", true);
}
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)) {
return new RedirectView("/account?messageType=usernameExists");
return new RedirectView("/account?messageType=usernameExists", true);
}
if (newUsername != null && newUsername.length() > 0) {
try {
userService.changeUsername(user, newUsername);
} catch (IllegalArgumentException e) {
return new RedirectView("/account?messageType=invalidUsername");
return new RedirectView("/account?messageType=invalidUsername", true);
}
}
// Logout using Spring's utility
new SecurityContextLogoutHandler().logout(request, response, null);
return new RedirectView(LOGIN_MESSAGETYPE_CREDSUPDATED);
return new RedirectView(LOGIN_MESSAGETYPE_CREDSUPDATED, true);
}
@PreAuthorize("!hasAuthority('ROLE_DEMO_USER')")
@@ -118,19 +118,19 @@ public class UserController {
HttpServletResponse response,
RedirectAttributes redirectAttributes) {
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());
if (userOpt == null || userOpt.isEmpty()) {
return new RedirectView("/change-creds?messageType=userNotFound");
return new RedirectView("/change-creds?messageType=userNotFound", true);
}
User user = userOpt.get();
if (!userService.isPasswordCorrect(user, currentPassword)) {
return new RedirectView("/change-creds?messageType=incorrectPassword");
return new RedirectView("/change-creds?messageType=incorrectPassword", true);
}
userService.changePassword(user, newPassword);
@@ -138,7 +138,7 @@ public class UserController {
// Logout using Spring's utility
new SecurityContextLogoutHandler().logout(request, response, null);
return new RedirectView(LOGIN_MESSAGETYPE_CREDSUPDATED);
return new RedirectView(LOGIN_MESSAGETYPE_CREDSUPDATED, true);
}
@PreAuthorize("!hasAuthority('ROLE_DEMO_USER')")
@@ -151,19 +151,19 @@ public class UserController {
HttpServletResponse response,
RedirectAttributes redirectAttributes) {
if (principal == null) {
return new RedirectView("/account?messageType=notAuthenticated");
return new RedirectView("/account?messageType=notAuthenticated", true);
}
Optional<User> userOpt = userService.findByUsernameIgnoreCase(principal.getName());
if (userOpt == null || userOpt.isEmpty()) {
return new RedirectView("/account?messageType=userNotFound");
return new RedirectView("/account?messageType=userNotFound", true);
}
User user = userOpt.get();
if (!userService.isPasswordCorrect(user, currentPassword)) {
return new RedirectView("/account?messageType=incorrectPassword");
return new RedirectView("/account?messageType=incorrectPassword", true);
}
userService.changePassword(user, newPassword);
@@ -171,7 +171,7 @@ public class UserController {
// Logout using Spring's utility
new SecurityContextLogoutHandler().logout(request, response, null);
return new RedirectView(LOGIN_MESSAGETYPE_CREDSUPDATED);
return new RedirectView(LOGIN_MESSAGETYPE_CREDSUPDATED, true);
}
@PreAuthorize("!hasAuthority('ROLE_DEMO_USER')")
@@ -204,7 +204,7 @@ public class UserController {
boolean forceChange) {
if (!userService.isUsernameValid(username)) {
return new RedirectView("/addUsers?messageType=invalidUsername");
return new RedirectView("/addUsers?messageType=invalidUsername", true);
}
Optional<User> userOpt = userService.findByUsernameIgnoreCase(username);
@@ -212,26 +212,27 @@ public class UserController {
if (userOpt.isPresent()) {
User user = userOpt.get();
if (user != null && user.getUsername().equalsIgnoreCase(username)) {
return new RedirectView("/addUsers?messageType=usernameExists");
return new RedirectView("/addUsers?messageType=usernameExists", true);
}
}
if (userService.usernameExistsIgnoreCase(username)) {
return new RedirectView("/addUsers?messageType=usernameExists");
return new RedirectView("/addUsers?messageType=usernameExists", true);
}
try {
// Validate the role
Role roleEnum = Role.fromString(role);
if (roleEnum == Role.INTERNAL_API_USER) {
// 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) {
// 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);
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')")
@@ -244,33 +245,34 @@ public class UserController {
Optional<User> userOpt = userService.findByUsernameIgnoreCase(username);
if (!userOpt.isPresent()) {
return new RedirectView("/addUsers?messageType=userNotFound");
return new RedirectView("/addUsers?messageType=userNotFound", true);
}
if (!userService.usernameExistsIgnoreCase(username)) {
return new RedirectView("/addUsers?messageType=userNotFound");
return new RedirectView("/addUsers?messageType=userNotFound", true);
}
// Get the currently authenticated username
String currentUsername = authentication.getName();
// Check if the provided username matches the current session's username
if (currentUsername.equalsIgnoreCase(username)) {
return new RedirectView("/addUsers?messageType=downgradeCurrentUser");
return new RedirectView("/addUsers?messageType=downgradeCurrentUser", true);
}
try {
// Validate the role
Role roleEnum = Role.fromString(role);
if (roleEnum == Role.INTERNAL_API_USER) {
// 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) {
// 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();
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')")
@@ -279,7 +281,7 @@ public class UserController {
@PathVariable(name = "username") String username, Authentication authentication) {
if (!userService.usernameExistsIgnoreCase(username)) {
return new RedirectView("/addUsers?messageType=deleteUsernameExists");
return new RedirectView("/addUsers?messageType=deleteUsernameExists", true);
}
// Get the currently authenticated username
@@ -287,11 +289,11 @@ public class UserController {
// Check if the provided username matches the current session's username
if (currentUsername.equalsIgnoreCase(username)) {
return new RedirectView("/addUsers?messageType=deleteCurrentUser");
return new RedirectView("/addUsers?messageType=deleteCurrentUser", true);
}
invalidateUserSessions(username);
userService.deleteUser(username);
return new RedirectView("/addUsers");
return new RedirectView("/addUsers", true);
}
@Autowired private SessionRegistry sessionRegistry;

View File

@@ -1,10 +1,22 @@
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.Path;
import java.util.ArrayList;
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;
@@ -26,6 +38,8 @@ import stirling.software.SPDF.utils.WebResponseUtils;
@Tag(name = "Convert", description = "Convert APIs")
public class ConvertPDFToPDFA {
private static final Logger logger = LoggerFactory.getLogger(ConvertPDFToPDFA.class);
@PostMapping(consumes = "multipart/form-data", value = "/pdf/pdfa")
@Operation(
summary = "Convert a PDF to a PDF/A",
@@ -36,9 +50,39 @@ public class ConvertPDFToPDFA {
MultipartFile inputFile = request.getFileInput();
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");
inputFile.transferTo(tempInputFile.toFile());
try (OutputStream outputStream = new FileOutputStream(tempInputFile.toFile())) {
outputStream.write(pdfBytes);
}
// Prepare the output file path
Path tempOutputFile = Files.createTempFile("output_", ".pdf");
@@ -58,7 +102,7 @@ public class ConvertPDFToPDFA {
.runCommandWithOutputHandling(command);
// Read the optimized PDF file
byte[] pdfBytes = Files.readAllBytes(tempOutputFile);
byte[] optimizedPdfBytes = Files.readAllBytes(tempOutputFile);
// Clean up the temporary files
Files.deleteIfExists(tempInputFile);
@@ -69,6 +113,6 @@ public class ConvertPDFToPDFA {
Filenames.toSimpleFileName(inputFile.getOriginalFilename())
.replaceFirst("[.][^.]+$", "")
+ "_PDFA.pdf";
return WebResponseUtils.bytesToWebResponse(pdfBytes, outputFilename);
return WebResponseUtils.bytesToWebResponse(optimizedPdfBytes, outputFilename);
}
}

View File

@@ -15,6 +15,8 @@ import java.util.zip.ZipOutputStream;
import org.apache.pdfbox.Loader;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ModelAttribute;
@@ -43,6 +45,7 @@ import stirling.software.SPDF.utils.WebResponseUtils;
@Tag(name = "Misc", description = "Miscellaneous APIs")
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_OLD = "https://github.com/Frooodle/Stirling-PDF";
@@ -115,7 +118,7 @@ public class AutoSplitPdfController {
zipOut.closeEntry();
}
} catch (Exception e) {
e.printStackTrace();
logger.error("exception", e);
} finally {
data = Files.readAllBytes(zipFile);
Files.deleteIfExists(zipFile);

View File

@@ -106,7 +106,7 @@ public class BlankPageController {
.replaceFirst("[.][^.]+$", "")
+ "_blanksRemoved.pdf");
} catch (IOException e) {
e.printStackTrace();
logger.error("exception", e);
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
} finally {
if (document != null) document.close();

View File

@@ -110,8 +110,8 @@ public class FakeScanControllerWIP {
private BufferedImage rotate(BufferedImage image, double rotation) {
double rotationRequired = Math.toRadians(rotation);
double locationX = image.getWidth() / 2;
double locationY = image.getHeight() / 2;
double locationX = (double) image.getWidth() / 2;
double locationY = (double) image.getHeight() / 2;
AffineTransform tx =
AffineTransform.getRotateInstance(rotationRequired, locationX, locationY);
AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BICUBIC);
@@ -127,8 +127,8 @@ public class FakeScanControllerWIP {
for (int i = -radius; i <= radius; i++) {
for (int j = -radius; j <= radius; j++) {
double xDistance = i * i;
double yDistance = j * j;
double xDistance = (double) i * i;
double yDistance = (double) j * j;
double g = Math.exp(-(xDistance + yDistance) / (2 * sigma * sigma));
data[(i + radius) * size + j + radius] = (float) g;
sum += g;
@@ -137,7 +137,7 @@ public class FakeScanControllerWIP {
// Normalize the kernel
for (int i = 0; i < data.length; i++) {
data[i] /= sum;
if (sum != 0) data[i] /= sum;
}
Kernel kernel = new Kernel(size, size, data);
@@ -166,7 +166,7 @@ public class FakeScanControllerWIP {
0,
new Color(0, 0, 0, 1f),
0,
featherRadius * 2,
featherRadius * 2f,
new Color(0, 0, 0, 0f)));
g2.fillRect(0, 0, width, featherRadius);
@@ -174,7 +174,7 @@ public class FakeScanControllerWIP {
g2.setPaint(
new GradientPaint(
0,
height - featherRadius * 2,
height - featherRadius * 2f,
new Color(0, 0, 0, 0f),
0,
height,
@@ -187,7 +187,7 @@ public class FakeScanControllerWIP {
0,
0,
new Color(0, 0, 0, 1f),
featherRadius * 2,
featherRadius * 2f,
0,
new Color(0, 0, 0, 0f)));
g2.fillRect(0, 0, featherRadius, height);
@@ -195,7 +195,7 @@ public class FakeScanControllerWIP {
// Right edge
g2.setPaint(
new GradientPaint(
width - featherRadius * 2,
width - featherRadius * 2f,
0,
new Color(0, 0, 0, 0f),
width,
@@ -244,7 +244,7 @@ public class FakeScanControllerWIP {
int y2 = y1 + random.nextInt(20) - 10;
Path2D.Double hair = new Path2D.Double();
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);
}

View File

@@ -12,6 +12,8 @@ import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
@@ -33,6 +35,8 @@ import stirling.software.SPDF.utils.WebResponseUtils;
@Tag(name = "Misc", description = "Miscellaneous APIs")
public class FlattenController {
private static final Logger logger = LoggerFactory.getLogger(FlattenController.class);
@PostMapping(consumes = "multipart/form-data", value = "/flatten")
@Operation(
summary = "Flatten PDF form fields or full page",
@@ -73,7 +77,7 @@ public class FlattenController {
contentStream.drawImage(pdImage, 0, 0, pageWidth, pageHeight);
}
} catch (IOException e) {
e.printStackTrace();
logger.error("exception", e);
}
}
PdfUtils.setMetadataToPdf(newDocument, metadata);

View File

@@ -11,6 +11,8 @@ import org.apache.pdfbox.Loader;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDDocumentInformation;
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;
@@ -30,6 +32,8 @@ import stirling.software.SPDF.utils.WebResponseUtils;
@Tag(name = "Misc", description = "Miscellaneous APIs")
public class MetadataController {
private static final Logger logger = LoggerFactory.getLogger(MetadataController.class);
private String checkUndefined(String entry) {
// Check if the string is "undefined"
if ("undefined".equals(entry)) {
@@ -136,7 +140,7 @@ public class MetadataController {
creationDateCal.setTime(
new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse(creationDate));
} catch (ParseException e) {
e.printStackTrace();
logger.error("exception", e);
}
info.setCreationDate(creationDateCal);
} else {
@@ -148,7 +152,7 @@ public class MetadataController {
modificationDateCal.setTime(
new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse(modificationDate));
} catch (ParseException e) {
e.printStackTrace();
logger.error("exception", e);
}
info.setModificationDate(modificationDateCal);
} else {

View File

@@ -19,6 +19,7 @@ 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.core.io.ByteArrayResource;
import org.springframework.core.io.Resource;
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.PipelineOperation;
import stirling.software.SPDF.utils.FileMonitor;
@Service
public class PipelineDirectoryProcessor {
@@ -35,11 +37,18 @@ public class PipelineDirectoryProcessor {
private static final Logger logger = LoggerFactory.getLogger(PipelineDirectoryProcessor.class);
@Autowired private ObjectMapper objectMapper;
@Autowired private ApiDocService apiDocService;
final String watchedFoldersDir = "./pipeline/watchedFolders/";
final String finishedFoldersDir = "./pipeline/finishedFolders/";
@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)
public void scanFolders() {
@@ -130,7 +139,11 @@ public class PipelineDirectoryProcessor {
throws IOException {
try (Stream<Path> paths = Files.list(dir)) {
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)
.toArray(File[]::new);
} else {

View File

@@ -105,7 +105,14 @@ public class PipelineProcessor {
body.add("fileInput", file);
for (Entry<String, Object> entry : parameters.entrySet()) {
body.add(entry.getKey(), entry.getValue());
if (entry.getValue() instanceof List) {
List<?> list = (List<?>) entry.getValue();
for (Object item : list) {
body.add(entry.getKey(), item);
}
} else {
body.add(entry.getKey(), entry.getValue());
}
}
ResponseEntity<byte[]> response = sendWebRequest(url, body);
@@ -167,7 +174,14 @@ public class PipelineProcessor {
}
for (Entry<String, Object> entry : parameters.entrySet()) {
body.add(entry.getKey(), entry.getValue());
if (entry.getValue() instanceof List) {
List<?> list = (List<?>) entry.getValue();
for (Object item : list) {
body.add(entry.getKey(), item);
}
} else {
body.add(entry.getKey(), entry.getValue());
}
}
ResponseEntity<byte[]> response = sendWebRequest(url, body);

View File

@@ -148,7 +148,7 @@ public class CertSignController {
doc.addSignature(signature, instance);
doc.saveIncremental(output);
} catch (Exception e) {
e.printStackTrace();
logger.error("exception", e);
}
}

View File

@@ -56,6 +56,8 @@ import org.apache.xmpbox.XMPMetadata;
import org.apache.xmpbox.xml.DomXmpParser;
import org.apache.xmpbox.xml.XmpParsingException;
import org.apache.xmpbox.xml.XmpSerializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ModelAttribute;
@@ -79,6 +81,8 @@ import stirling.software.SPDF.utils.WebResponseUtils;
@Tag(name = "Security", description = "Security APIs")
public class GetInfoOnPDF {
private static final Logger logger = LoggerFactory.getLogger(GetInfoOnPDF.class);
static ObjectMapper objectMapper = new ObjectMapper();
@PostMapping(consumes = "multipart/form-data", value = "/get-info-on-pdf")
@@ -220,7 +224,7 @@ public class GetInfoOnPDF {
javascriptArray.add(jsNode);
}
} catch (IOException e) {
e.printStackTrace();
logger.error("exception", e);
}
}
}
@@ -253,7 +257,7 @@ public class GetInfoOnPDF {
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
logger.error("exception", e);
}
boolean isPdfACompliant = checkForStandard(pdfBoxDoc, "PDF/A");
@@ -305,7 +309,7 @@ public class GetInfoOnPDF {
new XmpSerializer().serialize(xmpMeta, os, true);
xmpString = new String(os.toByteArray(), StandardCharsets.UTF_8);
} catch (XmpParsingException | IOException e) {
e.printStackTrace();
logger.error("exception", e);
}
}
@@ -593,7 +597,7 @@ public class GetInfoOnPDF {
MediaType.APPLICATION_JSON);
} catch (Exception e) {
e.printStackTrace();
logger.error("exception", e);
}
return null;
}
@@ -691,7 +695,7 @@ public class GetInfoOnPDF {
Exception
e) { // Catching general exception for brevity, ideally you'd catch specific
// exceptions.
e.printStackTrace();
logger.error("exception", e);
}
return false;

View File

@@ -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");
}
}

View File

@@ -117,7 +117,6 @@ public class PDFTableStripper extends PDFTextStripper {
/**
* Instantiate a new PDFTableStripper object.
*
* @param document
* @throws IOException If there is an error loading the properties.
*/
public PDFTableStripper() throws IOException {

View File

@@ -52,23 +52,23 @@ public class AccountWebController {
OAUTH2 oauth = applicationProperties.getSecurity().getOAUTH2();
if (oauth != null) {
if (oauth.isSettingsValid()) {
providerList.put("oidc", "OpenID Connect");
providerList.put("oidc", oauth.getProvider());
}
Client client = oauth.getClient();
if (client != null) {
GoogleProvider google = client.getGoogle();
if (google.isSettingsValid()) {
providerList.put("google", "Google");
providerList.put(google.getName(), google.getClientName());
}
GithubProvider github = client.getGithub();
if (github.isSettingsValid()) {
providerList.put("github", "Github");
providerList.put(github.getName(), github.getClientName());
}
KeycloakProvider keycloak = client.getKeycloak();
if (keycloak.isSettingsValid()) {
providerList.put("keycloak", "Keycloak");
providerList.put(keycloak.getName(), keycloak.getClientName());
}
}
}
@@ -262,8 +262,7 @@ public class AccountWebController {
userRepository.findByUsernameIgnoreCase(
username); // Assuming findByUsername method exists
if (!user.isPresent()) {
// Handle error appropriately
return "redirect:/error"; // Example redirection in case of error
return "redirect:/error";
}
// Convert settings map to JSON string
@@ -273,8 +272,8 @@ public class AccountWebController {
settingsJson = objectMapper.writeValueAsString(user.get().getSettings());
} catch (JsonProcessingException e) {
// Handle JSON conversion error
e.printStackTrace();
return "redirect:/error"; // Example redirection in case of error
logger.error("exception", e);
return "redirect:/error";
}
String messageType = request.getParameter("messageType");

View File

@@ -15,6 +15,8 @@ import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
@@ -33,6 +35,8 @@ import io.swagger.v3.oas.annotations.tags.Tag;
@Tag(name = "General", description = "General APIs")
public class GeneralWebController {
private static final Logger logger = LoggerFactory.getLogger(GeneralWebController.class);
@GetMapping("/pipeline")
@Hidden
public String pipelineForm(Model model) {
@@ -74,7 +78,7 @@ public class GeneralWebController {
}
} catch (IOException e) {
e.printStackTrace();
logger.error("exception", e);
}
}
if (pipelineConfigsWithNames.size() == 0) {

View File

@@ -6,6 +6,8 @@ import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
@@ -26,6 +28,8 @@ import stirling.software.SPDF.model.Dependency;
@Controller
public class HomeWebController {
private static final Logger logger = LoggerFactory.getLogger(HomeWebController.class);
@GetMapping("/about")
@Hidden
public String gameForm(Model model) {
@@ -46,7 +50,7 @@ public class HomeWebController {
mapper.readValue(json, new TypeReference<Map<String, List<Dependency>>>() {});
model.addAttribute("dependencies", data.get("dependencies"));
} catch (IOException e) {
e.printStackTrace();
logger.error("exception", e);
}
return "licenses";
}

View File

@@ -53,6 +53,13 @@ public class SecurityWebController {
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")
@Hidden
public String sanitizeForm(Model model) {

View File

@@ -356,8 +356,8 @@ public class ApplicationProperties {
private KeycloakProvider keycloak = new KeycloakProvider();
public Provider get(String registrationId) throws Exception {
switch (registrationId) {
case "gogole":
switch (registrationId.toLowerCase()) {
case "google":
return getGoogle();
case "github":
return getGithub();
@@ -455,6 +455,7 @@ public class ApplicationProperties {
@Override
public Collection<String> getScopes() {
if (scopes == null || scopes.isEmpty()) {
scopes = new ArrayList<>();
scopes.add("https://www.googleapis.com/auth/userinfo.email");
scopes.add("https://www.googleapis.com/auth/userinfo.profile");
}
@@ -495,6 +496,11 @@ public class ApplicationProperties {
return "google";
}
@Override
public String getClientName() {
return "Google";
}
public boolean isSettingsValid() {
return super.isValid(this.getClientId(), "clientId")
&& super.isValid(this.getClientSecret(), "clientSecret")
@@ -553,8 +559,10 @@ public class ApplicationProperties {
this.clientSecret = clientSecret;
}
@Override
public Collection<String> getScopes() {
if (scopes == null || scopes.isEmpty()) {
scopes = new ArrayList<>();
scopes.add("read:user");
}
return scopes;
@@ -594,6 +602,11 @@ public class ApplicationProperties {
return "github";
}
@Override
public String getClientName() {
return "GitHub";
}
public boolean isSettingsValid() {
return super.isValid(this.getClientId(), "clientId")
&& super.isValid(this.getClientSecret(), "clientSecret")
@@ -642,13 +655,14 @@ public class ApplicationProperties {
@Override
public Collection<String> getScopes() {
if (scopes == null || scopes.isEmpty()) {
scopes.add("openid");
scopes = new ArrayList<>();
scopes.add("profile");
scopes.add("email");
}
return scopes;
}
@Override
public void setScopes(String scopes) {
this.scopes =
Arrays.stream(scopes.split(",")).map(String::trim).collect(Collectors.toList());
@@ -684,6 +698,11 @@ public class ApplicationProperties {
return "keycloak";
}
@Override
public String getClientName() {
return "Keycloak";
}
public boolean isSettingsValid() {
return isValid(this.getIssuer(), "issuer")
&& isValid(this.getClientId(), "clientId")

View File

@@ -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;
}
}

View File

@@ -4,11 +4,16 @@ import java.util.Collection;
public class Provider implements ProviderInterface {
private String name;
private String clientName;
public String getName() {
return name;
}
public String getClientName() {
return clientName;
}
protected boolean isValid(String value, String name) {
if (value != null && !value.trim().isEmpty()) {
return true;

View File

@@ -6,6 +6,7 @@ public enum SortTypes {
BOOKLET_SORT,
SIDE_STITCH_BOOKLET_SORT,
ODD_EVEN_SPLIT,
ODD_EVEN_MERGE,
REMOVE_FIRST,
REMOVE_LAST,
REMOVE_FIRST_AND_LAST,

View File

@@ -5,6 +5,8 @@ import java.util.List;
import org.apache.pdfbox.Loader;
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.media.Schema;
@@ -19,6 +21,8 @@ import stirling.software.SPDF.utils.GeneralUtils;
@EqualsAndHashCode(callSuper = true)
public class PDFWithPageNums extends PDFFile {
private static final Logger logger = LoggerFactory.getLogger(PDFWithPageNums.class);
@Schema(
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')\"")
@@ -31,7 +35,7 @@ public class PDFWithPageNums extends PDFFile {
pageCount = Loader.loadPDF(getFileInput().getBytes()).getNumberOfPages();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
logger.error("exception", e);
}
return GeneralUtils.parsePageList(pageNumbers, pageCount, zeroCount);
}

View File

@@ -21,4 +21,10 @@ public class MergePdfsRequest extends MultiplePDFFiles {
},
defaultValue = "orderProvided")
private String sortType = "orderProvided";
@Schema(
description =
"Flag indicating whether to remove certification signatures from the merged PDF. If true, all certification signatures will be removed from the final merged document.",
example = "true")
private boolean isRemoveCertSign;
}

View File

@@ -19,6 +19,7 @@ public class RearrangePagesRequest extends PDFWithPageNums {
+ "DUPLEX_SORT: Sorts pages as if all fronts were scanned then all backs in reverse (1, n, 2, n-1, ...). "
+ "BOOKLET_SORT: Arranges pages for booklet printing (last, first, second, second last, ...).\n"
+ "ODD_EVEN_SPLIT: Splits and arranges pages into odd and even numbered pages.\n"
+ "ODD_EVEN_MERGE: Merges pages and organises them alternately into odd and even pages.\n"
+ "REMOVE_FIRST: Removes the first page.\n"
+ "REMOVE_LAST: Removes the last page.\n"
+ "REMOVE_FIRST_AND_LAST: Removes both the first and the last pages.\n")

View 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);
}
}

View File

@@ -42,6 +42,7 @@ public class FileToPdf {
List<String> command = new ArrayList<>();
if (!htmlFormatsInstalled) {
command.add("weasyprint");
command.add("-e utf-8");
command.add(tempInputFile.toString());
command.add(tempOutputFile.toString());
@@ -52,7 +53,7 @@ public class FileToPdf {
command.add("--paper-size");
command.add("a4");
if (request.getZoom() != 1.0) {
if (request != null && request.getZoom() != 1.0) {
// Create a temporary CSS file
File tempCssFile = Files.createTempFile("customStyle", ".css").toFile();
try (FileWriter writer = new FileWriter(tempCssFile)) {

View File

@@ -14,6 +14,8 @@ import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;
import com.fathzer.soft.javaluator.DoubleEvaluator;
@@ -23,6 +25,8 @@ import io.github.pixee.security.Urls;
public class GeneralUtils {
private static final Logger logger = LoggerFactory.getLogger(GeneralUtils.class);
public static File convertMultipartFileToFile(MultipartFile multipartFile) throws IOException {
File tempFile = Files.createTempFile("temp", null).toFile();
try (FileOutputStream os = new FileOutputStream(tempFile)) {
@@ -234,7 +238,7 @@ public class GeneralUtils {
try {
Files.createDirectories(folder);
} catch (IOException e) {
e.printStackTrace();
logger.error("exception", e);
return false;
}
}

View File

@@ -14,6 +14,8 @@ import java.util.zip.ZipOutputStream;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
@@ -24,6 +26,7 @@ import io.github.pixee.security.Filenames;
import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult;
public class PDFToFile {
private static final Logger logger = LoggerFactory.getLogger(PDFToFile.class);
public ResponseEntity<byte[]> processPdfToHtml(MultipartFile inputFile)
throws IOException, InterruptedException {
@@ -67,18 +70,20 @@ public class PDFToFile {
// Return output files in a ZIP archive
fileName = pdfBaseName + "ToHtml.zip";
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ZipOutputStream zipOutputStream = new ZipOutputStream(byteArrayOutputStream);
for (File outputFile : outputFiles) {
ZipEntry entry = new ZipEntry(outputFile.getName());
zipOutputStream.putNextEntry(entry);
FileInputStream fis = new FileInputStream(outputFile);
IOUtils.copy(fis, zipOutputStream);
fis.close();
zipOutputStream.closeEntry();
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);
}
zipOutputStream.closeEntry();
}
} catch (IOException e) {
logger.error("Exception writing zip", e);
}
zipOutputStream.close();
fileBytes = byteArrayOutputStream.toByteArray();
} finally {
@@ -135,6 +140,8 @@ public class PDFToFile {
new ArrayList<>(
Arrays.asList(
"soffice",
"--headless",
"--nologo",
"--infilter=" + libreOfficeFilter,
"--convert-to",
outputFormat,
@@ -160,18 +167,22 @@ public class PDFToFile {
// Return output files in a ZIP archive
fileName = pdfBaseName + "To" + outputFormat + ".zip";
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) {
ZipEntry entry = new ZipEntry(outputFile.getName());
zipOutputStream.putNextEntry(entry);
FileInputStream fis = new FileInputStream(outputFile);
IOUtils.copy(fis, zipOutputStream);
fis.close();
zipOutputStream.closeEntry();
zipOutputStream.closeEntry();
}
} catch (IOException e) {
logger.error("Exception writing zip", e);
}
zipOutputStream.close();
fileBytes = byteArrayOutputStream.toByteArray();
}

View File

@@ -1,27 +1,27 @@
package stirling.software.SPDF.utils;
import java.awt.Graphics;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.*;
import javax.imageio.stream.ImageOutputStream;
import org.apache.pdfbox.Loader;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.pdmodel.*;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.PDPageContentStream.AppendMode;
import org.apache.pdfbox.pdmodel.PDResources;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.graphics.PDXObject;
import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject;
@@ -245,19 +245,64 @@ public class PdfUtils {
writer.dispose();
} else {
// Combine all images into a single big image
BufferedImage image = pdfRenderer.renderImageWithDPI(0, DPI, colorType);
// Calculate the combined image dimensions
int maxWidth = 0;
int totalHeight = 0;
BufferedImage pdfSizeImage = null;
int pdfSizeImageIndex = -1;
// Using a map to store the rendered dimensions of each page size
// to avoid rendering the same page sizes multiple times
HashMap<PdfRenderSettingsKey, PdfImageDimensionValue> pageSizes =
new HashMap<>();
for (int i = 0; i < pageCount; ++i) {
PDPage page = document.getPage(i);
PDRectangle mediaBox = page.getMediaBox();
int rotation = page.getRotation();
PdfRenderSettingsKey settings =
new PdfRenderSettingsKey(
mediaBox.getWidth(), mediaBox.getHeight(), rotation);
PdfImageDimensionValue dimension = pageSizes.get(settings);
if (dimension == null) {
// Render the image to get the dimensions
pdfSizeImage = pdfRenderer.renderImageWithDPI(i, DPI, colorType);
pdfSizeImageIndex = i;
dimension =
new PdfImageDimensionValue(
pdfSizeImage.getWidth(), pdfSizeImage.getHeight());
pageSizes.put(settings, dimension);
if (pdfSizeImage.getWidth() > maxWidth) {
maxWidth = pdfSizeImage.getWidth();
}
}
totalHeight += dimension.height();
}
// Create a new BufferedImage to store the combined images
BufferedImage combined =
new BufferedImage(
image.getWidth(),
image.getHeight() * pageCount,
BufferedImage.TYPE_INT_RGB);
prepareImageForPdfToImage(maxWidth, totalHeight, imageType);
Graphics g = combined.getGraphics();
int currentHeight = 0;
BufferedImage pageImage;
// Check if the first image is the last rendered image
boolean firstImageAlreadyRendered = pdfSizeImageIndex == 0;
for (int i = 0; i < pageCount; ++i) {
if (i != 0) {
image = pdfRenderer.renderImageWithDPI(i, DPI, colorType);
if (firstImageAlreadyRendered && i == 0) {
pageImage = pdfSizeImage;
} else {
pageImage = pdfRenderer.renderImageWithDPI(i, DPI, colorType);
}
g.drawImage(image, 0, i * image.getHeight(), null);
// Calculate the x-coordinate to center the image
int x = (maxWidth - pageImage.getWidth()) / 2;
g.drawImage(pageImage, x, currentHeight, null);
currentHeight += pageImage.getHeight();
}
// Write the image to the output stream
@@ -296,6 +341,23 @@ public class PdfUtils {
}
}
private static BufferedImage prepareImageForPdfToImage(
int maxWidth, int height, String imageType) {
BufferedImage combined;
if ("png".equalsIgnoreCase(imageType)) {
combined = new BufferedImage(maxWidth, height, BufferedImage.TYPE_INT_ARGB);
} else {
combined = new BufferedImage(maxWidth, height, BufferedImage.TYPE_INT_RGB);
}
if (!"png".equalsIgnoreCase(imageType)) {
Graphics g = combined.getGraphics();
g.setColor(Color.WHITE);
g.fillRect(0, 0, combined.getWidth(), combined.getHeight());
g.dispose();
}
return combined;
}
public static byte[] imageToPdf(
MultipartFile[] files, String fitOption, boolean autoRotate, String colorType)
throws IOException {
@@ -443,4 +505,10 @@ public class PdfUtils {
pdf.getDocumentInformation().setCreationDate(pdfMetadata.getCreationDate());
pdf.getDocumentInformation().setModificationDate(Calendar.getInstance());
}
/** Key for storing the dimensions of a rendered image in a map. */
private record PdfRenderSettingsKey(float mediaBoxWidth, float mediaBoxHeight, int rotation) {}
/** Value for storing the dimensions of a rendered image in a map. */
private record PdfImageDimensionValue(int width, int height) {}
}

View File

@@ -125,7 +125,7 @@ public class ProcessExecutor {
logger.warn(
"Error reader thread was interrupted due to timeout.");
} catch (IOException e) {
e.printStackTrace();
logger.error("exception", e);
}
});
@@ -149,7 +149,7 @@ public class ProcessExecutor {
logger.warn(
"Error reader thread was interrupted due to timeout.");
} catch (IOException e) {
e.printStackTrace();
logger.error("exception", e);
}
});

View File

@@ -10,7 +10,22 @@ public class RequestUriUtils {
|| requestURI.startsWith("/images/")
|| requestURI.startsWith("/public/")
|| requestURI.startsWith("/pdfjs/")
|| requestURI.startsWith("/pdfjs-legacy/")
|| requestURI.endsWith(".svg")
|| requestURI.endsWith(".webmanifest")
|| requestURI.startsWith("/api/v1/info/status");
}
public static boolean isStaticResource(String contextPath, String requestURI) {
return requestURI.startsWith(contextPath + "/css/")
|| requestURI.startsWith(contextPath + "/fonts/")
|| requestURI.startsWith(contextPath + "/js/")
|| requestURI.startsWith(contextPath + "/images/")
|| requestURI.startsWith(contextPath + "/public/")
|| requestURI.startsWith(contextPath + "/pdfjs/")
|| requestURI.endsWith(".svg")
|| requestURI.endsWith(".webmanifest")
|| requestURI.startsWith(contextPath + "/api/v1/info/status");
}
}

View File

@@ -4,6 +4,8 @@ import jakarta.servlet.http.HttpServletRequest;
public class UrlUtils {
private UrlUtils() {}
public static String getOrigin(HttpServletRequest request) {
String scheme = request.getScheme(); // http or https
String serverName = request.getServerName(); // localhost

View File

@@ -21,7 +21,7 @@ saveToBrowser=Save to Browser
close=إغلاق
filesSelected=الملفات المحددة
noFavourites=لم تتم إضافة أي مفضلات
downloadComplete=Download Complete
downloadComplete=إكتمل التحميل
bored=الانتظار بالملل؟
alphabet=الأبجدية
downloadPdf=تنزيل PDF
@@ -29,47 +29,48 @@ text=نص
font=الخط
selectFillter=- حدد -
pageNum=رقم الصفحة
sizes.small=Small
sizes.medium=Medium
sizes.large=Large
sizes.x-large=X-Large
sizes.small=صغير
sizes.medium=وسط
sizes.large=كبير
sizes.x-large=كبير جدا
error.pdfPassword=The PDF Document is passworded and either the password was not provided or was incorrect
delete=Delete
username=Username
password=Password
welcome=Welcome
delete=حذف
username=اسم المستخدم
password=كلمة المرور
welcome=مرحبا
property=Property
black=Black
white=White
red=Red
green=Green
blue=Blue
black=أسود
white=أبيض
red=أحمر
green=أخضر
blue=أزرق
custom=Custom...
WorkInProgess=Work in progress, May not work or be buggy, Please report any problems!
poweredBy=Powered by
yes=Yes
no=No
yes=نعم
no=لا
changedCredsMessage=Credentials changed!
notAuthenticatedMessage=User not authenticated.
userNotFoundMessage=User not found.
incorrectPasswordMessage=Current password is incorrect.
usernameExistsMessage=New Username already exists.
invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=لا يمكن خفض دور المستخدم الحالي
downgradeCurrentUserLongMessage=لا يمكن تخفيض دور المستخدم الحالي. وبالتالي، لن يظهر المستخدم الحالي.
userAlreadyExistsOAuthMessage=The user already exists as an OAuth2 user.
userAlreadyExistsWebMessage=The user already exists as an web user.
error=Error
error=خطأ
oops=Oops!
help=Help
goHomepage=Go to Homepage
help=مساعدة
goHomepage=الى الصفحة الرئيسية
joinDiscord=Join our Discord server
seeDockerHub=See Docker Hub
visitGithub=Visit Github Repository
donate=Donate
color=Color
color=لون
sponsor=Sponsor
info=Info
@@ -85,6 +86,7 @@ pipeline.defaultOption=Custom
pipeline.submitButton=Submit
pipeline.help=Pipeline Help
pipeline.scanHelp=Folder Scanning Help
pipeline.deletePrompt=Are you sure you want to delete pipeline
######################
# Pipeline Options #
@@ -107,15 +109,15 @@ pipelineOptions.validateButton=Validate
#############
navbar.favorite=Favorites
navbar.darkmode=الوضع الداكن
navbar.language=Languages
navbar.language=اللغات
navbar.settings=إعدادات
navbar.allTools=Tools
navbar.allTools=أدوات
navbar.multiTool=Multi Tools
navbar.sections.organize=Organize
navbar.sections.convertTo=Convert to PDF
navbar.sections.convertTo=تحويل الى PDF
navbar.sections.convertFrom=Convert from PDF
navbar.sections.security=Sign & Security
navbar.sections.advance=Advanced
navbar.sections.advance=متقدم
navbar.sections.edit=View & Edit
#############
@@ -131,7 +133,7 @@ settings.downloadOption.2=فتح في نافذة جديدة
settings.downloadOption.3=تنزيل الملف
settings.zipThreshold=ملفات مضغوطة عند تجاوز عدد الملفات التي تم تنزيلها
settings.signOut=Sign Out
settings.accountSettings=Account Settings
settings.accountSettings=اعدادات الحساب
settings.bored.help=Enables easter egg game
settings.cacheInputs.name=Save form inputs
settings.cacheInputs.help=Enable to store previously used inputs for future runs
@@ -139,10 +141,10 @@ settings.cacheInputs.help=Enable to store previously used inputs for future runs
changeCreds.title=Change Credentials
changeCreds.header=Update Your Account Details
changeCreds.changePassword=You are using default login credentials. Please enter a new password
changeCreds.newUsername=New Username
changeCreds.oldPassword=Current Password
changeCreds.newPassword=New Password
changeCreds.confirmNewPassword=Confirm New Password
changeCreds.newUsername=مستخدم جديد
changeCreds.oldPassword=كلمة المرور الحالية
changeCreds.newPassword=كلمة المرور الجديدة
changeCreds.confirmNewPassword=تأكيد كلمة المرور الجديدة
changeCreds.submit=Submit Changes
@@ -173,6 +175,8 @@ adminUserSettings.header=Admin User Control Settings
adminUserSettings.admin=Admin
adminUserSettings.user=User
adminUserSettings.addUser=Add New User
adminUserSettings.deleteUser=Delete User
adminUserSettings.confirmDeleteUser=Should the user be deleted?
adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Roles
adminUserSettings.role=Role
@@ -332,6 +336,10 @@ home.certSign.title=Sign with Certificate
home.certSign.desc=Signs a PDF with a Certificate/Key (PEM/P12)
certSign.tags=authenticate,PEM,P12,official,encrypt
home.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.desc=Merge multiple pages of a PDF document into a single page
pageLayout.tags=merge,composite,single-view,organize
@@ -487,9 +495,9 @@ pdfToSinglePage.submit=Convert To Single Page
#pageExtracter
pageExtracter.title=Extract Pages
pageExtracter.header=Extract Pages
pageExtracter.submit=Extract
pageExtracter.title=استخراج الصفحات
pageExtracter.header=استخراج الصفحات
pageExtracter.submit=استخراج
pageExtracter.placeholder=(e.g. 1,2,8 or 4,7,12-16 or 2n-1)
@@ -497,7 +505,7 @@ pageExtracter.placeholder=(e.g. 1,2,8 or 4,7,12-16 or 2n-1)
getPdfInfo.title=Get Info on PDF
getPdfInfo.header=Get Info on PDF
getPdfInfo.submit=Get Info
getPdfInfo.downloadJson=Download JSON
getPdfInfo.downloadJson=تحميل JSON
#markdown-to-pdf
@@ -655,6 +663,13 @@ certSign.name=الاسم
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.title=إزالة الفراغات
removeBlanks.header=إزالة الصفحات الفارغة
@@ -668,7 +683,7 @@ removeBlanks.submit=إزالة الفراغات
#removeAnnotations
removeAnnotations.title=Remove Annotations
removeAnnotations.header=Remove Annotations
removeAnnotations.submit=Remove
removeAnnotations.submit=إزالة
#compare
@@ -786,8 +801,9 @@ addImage.submit=إضافة صورة
#merge
merge.title=دمج
merge.header=دمج ملفات PDF متعددة (2+)
merge.sortByName=Sort by name
merge.sortByDate=Sort by date
merge.sortByName=الترتيب حسب الإسم
merge.sortByDate=الترتيب حسب التاريخ
merge.removeCertSign=Remove digital signature in the merged file?
merge.submit=دمج
@@ -811,7 +827,7 @@ pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)
#multiTool
multiTool.title=أداة متعددة PDF
multiTool.header=أداة متعددة PDF
multiTool.uploadPrompts=File Name
multiTool.uploadPrompts=إسم الملف
#view pdf
viewPdf.title=View PDF
@@ -852,7 +868,7 @@ imageToPDF.title=صورة إلى PDF
imageToPDF.header=صورة إلى PDF
imageToPDF.submit=تحول
imageToPDF.selectLabel=Image Fit Options
imageToPDF.fillPage=Fill Page
imageToPDF.fillPage=امل الصفحة
imageToPDF.fitDocumentToImage=Fit Page to Image
imageToPDF.maintainAspectRatio=Maintain Aspect Ratios
imageToPDF.selectText.2=دوران PDF تلقائيًا
@@ -891,7 +907,7 @@ addPassword.selectText.10=منع التعديل
addPassword.selectText.11=منع تعديل التعليقات التوضيحية
addPassword.selectText.12=منع الطباعة
addPassword.selectText.13=منع طباعة تنسيقات مختلفة
addPassword.selectText.14=Owner Password
addPassword.selectText.14=كلمة مرور المالك
addPassword.selectText.15=Restricts what can be done with the document once it is opened (Not supported by all readers)
addPassword.selectText.16=Restricts the opening of the document itself
addPassword.submit=تشفير
@@ -910,8 +926,8 @@ watermark.selectText.7=التعتيم (0٪ - 100٪):
watermark.selectText.8=Watermark Type:
watermark.selectText.9=Watermark Image:
watermark.submit=إضافة علامة مائية
watermark.type.1=Text
watermark.type.2=Image
watermark.type.1=نص
watermark.type.2=صورة
#Change permissions
@@ -965,6 +981,7 @@ pdfToPDFA.credit=تستخدم هذه الخدمة OCRmyPDF لتحويل PDF / A.
pdfToPDFA.submit=تحويل
pdfToPDFA.tip=Currently does not work for multiple inputs at once
pdfToPDFA.outputFormat=Output format
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
#PDFToWord
@@ -1005,10 +1022,10 @@ PDFToXML.credit=تستخدم هذه الخدمة LibreOffice لتحويل الم
PDFToXML.submit=تحويل
#PDFToCSV
PDFToCSV.title=PDF ??? CSV
PDFToCSV.header=PDF ??? CSV
PDFToCSV.title=PDF الى CSV
PDFToCSV.header=PDF الى CSV
PDFToCSV.prompt=Choose page to extract table
PDFToCSV.submit=??????
PDFToCSV.submit=تحويل
#split-by-size-or-count
split-by-size-or-count.title=Split PDF by Size or Count
@@ -1050,11 +1067,11 @@ split-by-sections.merge=Merge Into One PDF
#printFile
printFile.title=Print File
printFile.header=Print File to Printer
printFile.selectText.1=Select File to Print
printFile.selectText.2=Enter Printer Name
printFile.submit=Print
printFile.title=طباعة ملف
printFile.header=طباعة ملف بالطابعة
printFile.selectText.1=تحديد ملف للطباعة
printFile.selectText.2=ادخل اسم الطابعة
printFile.submit=طباعة
#licenses
@@ -1065,6 +1082,15 @@ licenses.module=Module
licenses.version=Version
licenses.license=License
#survey
survey.nav=Survey
survey.title=Stirling-PDF Survey
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF!
survey.please=Please consider taking our survey!
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page)
survey.button=Take Survey
survey.dontShowAgain=Don't show again
#error
error.sorry=Sorry for the issue!

View File

@@ -55,12 +55,13 @@ userNotFoundMessage=Потребителят не е намерен
incorrectPasswordMessage=Текущата парола е неправилна.
usernameExistsMessage=Новият потребител вече съществува.
invalidUsernameMessage=Невалидно потребителско име, потребителското име може да съдържа само букви, цифри и следните специални знаци @._+- или трябва да е валиден имейл адрес.
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
deleteCurrentUserMessage=Не може да се изтрие вписания в момента потребител.
deleteUsernameExistsMessage=Потребителското име не съществува и не може да бъде изтрито.
downgradeCurrentUserMessage=Не може да се понижи ролята на текущия потребител
downgradeCurrentUserLongMessage=Не може да се понижи ролята на текущия потребител. Следователно текущият потребител няма да бъде показан.
userAlreadyExistsOAuthMessage=The user already exists as an OAuth2 user.
userAlreadyExistsWebMessage=The user already exists as an web user.
userAlreadyExistsOAuthMessage=Потребителят вече съществува като OAuth2 потребител.
userAlreadyExistsWebMessage=Потребителят вече съществува като уеб-потребител.
error=Грешка
oops=Опаа!
help=Помощ
@@ -85,6 +86,7 @@ pipeline.defaultOption=Персонализиран
pipeline.submitButton=Подайте
pipeline.help=Pipeline Помощ
pipeline.scanHelp=Помощ за сканиране на папки
pipeline.deletePrompt=Are you sure you want to delete pipeline
######################
# Pipeline Options #
@@ -105,18 +107,18 @@ pipelineOptions.validateButton=Валидирай
#############
# NAVBAR #
#############
navbar.favorite=Favorites
navbar.favorite=Любими
navbar.darkmode=Тъмна тема
navbar.language=Languages
navbar.language=Езици
navbar.settings=Настройки
navbar.allTools=Tools
navbar.multiTool=Multi Tools
navbar.sections.organize=Organize
navbar.sections.convertTo=Convert to PDF
navbar.sections.convertFrom=Convert from PDF
navbar.sections.security=Sign & Security
navbar.sections.advance=Advanced
navbar.sections.edit=View & Edit
navbar.allTools=Инструменти
navbar.multiTool=Мулти инструменти
navbar.sections.organize=Организирайте
navbar.sections.convertTo=Преобразуване в PDF
navbar.sections.convertFrom=Преобразуване от PDF
navbar.sections.security=Подписване и сигурност
navbar.sections.advance=Разширено
navbar.sections.edit=Преглед и редактиране
#############
# SETTINGS #
@@ -173,6 +175,8 @@ adminUserSettings.header=Настройки за администраторск
adminUserSettings.admin=Администратор
adminUserSettings.user=Потребител
adminUserSettings.addUser=Добавяне на нов потребител
adminUserSettings.deleteUser=Delete User
adminUserSettings.confirmDeleteUser=Should the user be deleted?
adminUserSettings.usernameInfo=Потребителското име може да съдържа само букви, цифри и следните специални символи @._+- или трябва да е валиден имейл адрес.
adminUserSettings.roles=Роли
adminUserSettings.role=Роля
@@ -185,7 +189,7 @@ adminUserSettings.internalApiUser=Вътрешен API потребител
adminUserSettings.forceChange=Принудете потребителя да промени потребителското име/парола при влизане
adminUserSettings.submit=Съхранете потребителя
adminUserSettings.changeUserRole=Промяна на ролята на потребителя
adminUserSettings.authenticated=Authenticated
adminUserSettings.authenticated=Удостоверен
#############
# HOME-PAGE #
@@ -267,7 +271,7 @@ home.fileToPDF.desc=Преобразуване почти всеки файл к
fileToPDF.tags=трансформация,формат,документ,изображение,слайд,текст,преобразуване,офис,документи,word,excel,powerpoint
home.ocr.title=OCR / Почистващи сканирания
home.ocr.desc=Почистване, сканира и открива текст от изображения към PDF и го добавя отново като текст.
home.ocr.desc=Почиства, сканира и открива текст от изображения в PDF и го добавя отново като текст.
ocr.tags=разпознаване,текст,изображение,сканиране,четене,идентифициране,откриване,редактиране
@@ -313,7 +317,7 @@ home.flatten.desc=Премахнете всички интерактивни е
flatten.tags=статичен,деактивиран,неинтерактивен,рационализиран
home.repair.title=Поправи
home.repair.desc=Опитва се да поправи повреден/счупен PDF
home.repair.desc=Опитва се да поправи повреден PDF
repair.tags=поправка,възстановяване,корекция,възстановяване
home.removeBlanks.title=Премахване на празни страници
@@ -332,6 +336,10 @@ home.certSign.title=Подпишете със сертификат
home.certSign.desc=Подписва PDF със сертификат/ключ (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.desc=Слейте няколко страници от PDF документ в една страница
pageLayout.tags=сливане,комбиниран,единичен изглед,организиране
@@ -364,7 +372,7 @@ home.autoSplitPDF.title=Автоматично разделяне на стра
home.autoSplitPDF.desc=Автоматично разделяне на сканиран PDF файл с QR код за разделяне на физически сканирани страници
autoSplitPDF.tags=QR-базиран,отделен,сканиране-сегмент,организиране
home.sanitizePdf.title=Дезинфенкцирам
home.sanitizePdf.title=Обеззаразяване
home.sanitizePdf.desc=Премахване на скриптове и други елементи от PDF файлове
sanitizePdf.tags=чисти,сигурни,безопасни,премахване-заплахи
@@ -382,8 +390,8 @@ home.MarkdownToPDF.desc=Преобразува всеки Markdown файл къ
MarkdownToPDF.tags=маркиране,уеб-съдържание,трансформация,преобразуване
home.getPdfInfo.title=Вземете ЦЯЛАТА информация към PDF
home.getPdfInfo.desc=Взема всяка възможна информация от PDF файлове
home.getPdfInfo.title=Вземете ЦЯЛАТА информация от PDF
home.getPdfInfo.desc=Взима всяка възможна информация от PDF файлове
getPdfInfo.tags=информация,данни,статистики,статистика
@@ -405,7 +413,7 @@ home.autoRedact.title=Автоматично редактиране
home.autoRedact.desc=Автоматично редактира (зачернява) текст в PDF въз основа на въведен текст
autoRedact.tags=Редактиране,Скриване,затъмняване,черен,маркер,скрит
home.tableExtraxt.title=PDF to CSV
home.tableExtraxt.title=PDF в CSV
home.tableExtraxt.desc=Извлича таблици от PDF, като ги конвертира в CSV
tableExtraxt.tags=CSV,извличане на таблица,извличане,конвертиране
@@ -452,12 +460,12 @@ login.locked=Вашият акаунт е заключен.
login.signinTitle=Моля впишете се
login.ssoSignIn=Влизане чрез еднократно влизане
login.oauth2AutoCreateDisabled=OAUTH2 Автоматично създаване на потребител е деактивирано
login.oauth2RequestNotFound=Authorization request not found
login.oauth2InvalidUserInfoResponse=Invalid User Info Response
login.oauth2invalidRequest=Invalid Request
login.oauth2AccessDenied=Access Denied
login.oauth2InvalidTokenResponse=Invalid Token Response
login.oauth2InvalidIdToken=Invalid Id Token
login.oauth2RequestNotFound=Заявката за оторизация не е намерена
login.oauth2InvalidUserInfoResponse=Невалидна информация за потребителя
login.oauth2invalidRequest=Невалидна заявка
login.oauth2AccessDenied=Отказан достъп
login.oauth2InvalidTokenResponse=Невалиден отговор на токена
login.oauth2InvalidIdToken=Невалиден токен за идентификатор
#auto-redact
@@ -638,7 +646,7 @@ scalePages.submit=Подайте
#certSign
certSign.title=Подписване на сертификат
certSign.title=Подписване със сертификат
certSign.header=Подпишете PDF с вашия сертификат (В процес на работа)
certSign.selectPDF=Изберете PDF файл за подписване:
certSign.jksNote=Забележка: Ако вашият тип сертификат не е в списъка по-долу, моля, конвертирайте го във файл на Java Keystore (.jks) с помощта на инструмента за команден ред keytool. След това изберете опцията за .jks файл по-долу.
@@ -655,6 +663,13 @@ certSign.name=Име
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.title=Премахване на празни места
removeBlanks.header=Премахване на празни страници
@@ -758,7 +773,7 @@ extractImages.submit=Извличане
fileToPDF.title=Файл към PDF
fileToPDF.header=Конвертирайте всеки файл към PDF
fileToPDF.credit=Тази услуга използва LibreOffice и Unoconv за преобразуване на файлове.
fileToPDF.supportedFileTypesInfo=Supported File types
fileToPDF.supportedFileTypesInfo=Поддържание файлови типове
fileToPDF.supportedFileTypes=Поддържаните типове файлове трябва да включват по-долу, но за пълен актуализиран списък на поддържаните формати, моля, вижте документацията на LibreOffice
fileToPDF.submit=Преобразуване към PDF
@@ -767,10 +782,10 @@ fileToPDF.submit=Преобразуване към PDF
compress.title=Компресиране
compress.header=Компресиране на PDF
compress.credit=Тази услуга използва Ghostscript за PDF компресиране/оптимизиране.
compress.selectText.1=Ръчен режим - От 1 до 4
compress.selectText.1=Ръчен режим - от 1 до 4
compress.selectText.2=Ниво на оптимизация:
compress.selectText.3=4 (Ужасно за текстови изображения)
compress.selectText.4=Автоматичен режим - Автоматично настройва качеството, за да получи PDF точен размер
compress.selectText.4=Автоматичен режим - Автоматично настройва качеството, за да получи PDF с точен размер
compress.selectText.5=Очакван PDF размер (напр. 25МБ, 10.8МБ, 25КБ)
compress.submit=Компресиране
@@ -788,6 +803,7 @@ merge.title=Обединяване
merge.header=Обединяване на множество PDF файлове (2+)
merge.sortByName=Сортиране по име
merge.sortByDate=Сортиране по дата
merge.removeCertSign=Remove digital signature in the merged file?
merge.submit=Обединяване
@@ -811,7 +827,7 @@ pdfOrganiser.placeholder=(напр. 1,3,2 или 4-8,2,10-12 или 2n-1)
#multiTool
multiTool.title=PDF Мулти инструмент
multiTool.header=PDF Мулти инструмент
multiTool.uploadPrompts=File Name
multiTool.uploadPrompts=Име на файл
#view pdf
viewPdf.title=Преглед на PDF
@@ -910,8 +926,8 @@ watermark.selectText.7=Непрозрачност (0% - 100%):
watermark.selectText.8=Тип воден знак:
watermark.selectText.9=Изображение за воден знак:
watermark.submit=Добавяне на воден знак
watermark.type.1=Text
watermark.type.2=Image
watermark.type.1=Текст
watermark.type.2=Изображение
#Change permissions
@@ -965,6 +981,7 @@ pdfToPDFA.credit=Тази услуга използва OCRmyPDF за PDF/A пр
pdfToPDFA.submit=Преобразуване
pdfToPDFA.tip=В момента не работи за няколко входа наведнъж
pdfToPDFA.outputFormat=Изходен формат
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
#PDFToWord
@@ -1065,6 +1082,15 @@ licenses.module=Модул
licenses.version=Версия
licenses.license=Лиценз
#survey
survey.nav=Survey
survey.title=Stirling-PDF Survey
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF!
survey.please=Please consider taking our survey!
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page)
survey.button=Take Survey
survey.dontShowAgain=Don't show again
#error
error.sorry=Извинете за проблема!

View File

@@ -55,6 +55,7 @@ userNotFoundMessage=User not found.
incorrectPasswordMessage=Current password is incorrect.
usernameExistsMessage=New Username already exists.
invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=No es pot reduir la funció de l'usuari actual
@@ -85,6 +86,7 @@ pipeline.defaultOption=Custom
pipeline.submitButton=Submit
pipeline.help=Pipeline Help
pipeline.scanHelp=Folder Scanning Help
pipeline.deletePrompt=Are you sure you want to delete pipeline
######################
# Pipeline Options #
@@ -173,6 +175,8 @@ adminUserSettings.header=Usuari Admin Opcions Control
adminUserSettings.admin=Admin
adminUserSettings.user=Usuari
adminUserSettings.addUser=Afegir Usuari
adminUserSettings.deleteUser=Delete User
adminUserSettings.confirmDeleteUser=Should the user be deleted?
adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Rols
adminUserSettings.role=Rol
@@ -332,6 +336,10 @@ home.certSign.title=Signa amb Certificat
home.certSign.desc=Sign PDF amb Certificate/Clau (PEM/P12)
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.desc=Merge multiple pages of a PDF document into a single page
pageLayout.tags=merge,composite,single-view,organize
@@ -655,6 +663,13 @@ certSign.name=Nom
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.title=Elimina els espais en blanc
removeBlanks.header=Elimina les pàgines en blanc
@@ -788,6 +803,7 @@ merge.title=Fusiona
merge.header=Fusiona múltiples PDFs (2+)
merge.sortByName=Sort by name
merge.sortByDate=Sort by date
merge.removeCertSign=Remove digital signature in the merged file?
merge.submit=Fusiona
@@ -965,6 +981,7 @@ pdfToPDFA.credit=Utilitza OCRmyPDF per la conversió a PDF/A
pdfToPDFA.submit=Converteix
pdfToPDFA.tip=Currently does not work for multiple inputs at once
pdfToPDFA.outputFormat=Output format
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
#PDFToWord
@@ -1065,6 +1082,15 @@ licenses.module=Module
licenses.version=Version
licenses.license=License
#survey
survey.nav=Survey
survey.title=Stirling-PDF Survey
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF!
survey.please=Please consider taking our survey!
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page)
survey.button=Take Survey
survey.dontShowAgain=Don't show again
#error
error.sorry=Sorry for the issue!

View File

@@ -1,7 +1,7 @@
###########
# Generic #
###########
# the direction that the language is written (ltr = left to right, rtl = right to left)
# the direction that the language is written (ltr=left to right, rtl = right to left)
language.direction=ltr
pdfPrompt=Vyberte PDF soubory
@@ -26,7 +26,7 @@ bored=Nudíte se při čekání?
alphabet=Abeceda
downloadPdf=Stáhnout PDF
text=Text
font=Font
font=Písmo
selectFillter=-- Vyberte --
pageNum=Číslo stránky
sizes.small=Malé
@@ -55,6 +55,7 @@ userNotFoundMessage=Uživatel nenalezen.
incorrectPasswordMessage=Současné heslo není správné.
usernameExistsMessage=Nové uživatelské jméno již existuje.
invalidUsernameMessage=Nesprávné uživatelské jméno, smí obsahovat pouze písmena, číslice a následující speciální znaky @._+- nebo musí být validní emailová adresa.
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
deleteCurrentUserMessage=Nelze smazat aktuální přihlášeného uživatele.
deleteUsernameExistsMessage=Uživatelské jméno neexistuje a nelze ho smazat.
downgradeCurrentUserMessage=Nelze snížit roli aktuálního uživatele.
@@ -85,6 +86,7 @@ pipeline.defaultOption=Vlastní
pipeline.submitButton=Odeslat
pipeline.help=Pomoc s pipeline
pipeline.scanHelp=Pomoc se skenováním adresáře
pipeline.deletePrompt=Are you sure you want to delete pipeline
######################
# Pipeline Options #
@@ -173,6 +175,8 @@ adminUserSettings.header=Admin User Control Settings
adminUserSettings.admin=Admin
adminUserSettings.user=Uživatel
adminUserSettings.addUser=Přidat Nového Uživatele
adminUserSettings.deleteUser=Delete User
adminUserSettings.confirmDeleteUser=Should the user be deleted?
adminUserSettings.usernameInfo=Uživatelské Jméno může obsahovat pouze písmena, čísla a následující speciální znaky @._+- nebo musí být správná emailová adresa.
adminUserSettings.roles=Role
adminUserSettings.role=Role
@@ -190,7 +194,7 @@ adminUserSettings.authenticated=Ověřeno
#############
# HOME-PAGE #
#############
home.desc= Vaše lokálně hostované jednotné kontaktní místo pro všechny vaše potřeby ve formátu PDF
home.desc=Vaše lokálně hostované jednotné kontaktní místo pro všechny vaše potřeby ve formátu PDF
home.searchBar=Hledej funkce...
@@ -224,7 +228,7 @@ home.pdfToImage.desc=Konvertovat PDF na obrázek. (PNG, JPEG, GIF)
pdfToImage.tags=konverze,img,jpg,obrázek,fotka
home.pdfOrganiser.title=Organizovat
home.pdfOrganiser.desc=Odebrat/Přeskupit stránky v jakémkoli pořadí
home.pdfOrganiser.desc=Odebrat/Přeskupit stránky v jakémkoli pořadí
pdfOrganiser.tags=dvojitý,sudý,lichý,seřadit,přesunout
@@ -332,6 +336,10 @@ home.certSign.title=Podpis s certifikátem
home.certSign.desc=Podpis PDF s certifikátem/klíčem (PEM/P12)
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.desc=Sloučení více stránek dokumentu PDF do jedné stránky
pageLayout.tags=sloučit,kompozitní,jedno zobrazení,organizovat
@@ -655,6 +663,13 @@ certSign.name=Název
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.title=Odebrat prázdné stránky
removeBlanks.header=Odebrat prázdné stránky
@@ -710,7 +725,7 @@ repair.submit=Opravit
#flatten
flatten.title=Zploštit
flatten.header=Zploštit PDF
flatten.flattenOnlyForms=Zploštit pouze formuláře
flatten.flattenOnlyForms=Zploštit pouze formuláře
flatten.submit=Zploštit
@@ -788,6 +803,7 @@ merge.title=Sloučit
merge.header=Sloučit více PDF (2+)
merge.sortByName=Seřadit podle názvu
merge.sortByDate=Seřadit podle data
merge.removeCertSign=Remove digital signature in the merged file?
merge.submit=Sloučit
@@ -965,6 +981,7 @@ pdfToPDFA.credit=Tato služba používá OCRmyPDF pro konverzi do formátu PDF/A
pdfToPDFA.submit=Převést
pdfToPDFA.tip=V současné době nepracuje pro více vstupů najednou
pdfToPDFA.outputFormat=Výstupní formát
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
#PDFToWord
@@ -1065,6 +1082,15 @@ licenses.module=Modul
licenses.version=Verze
licenses.license=Licence
#survey
survey.nav=Survey
survey.title=Stirling-PDF Survey
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF!
survey.please=Please consider taking our survey!
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page)
survey.button=Take Survey
survey.dontShowAgain=Don't show again
#error
error.sorry=Omlouváme se za potíže!

View File

@@ -55,6 +55,7 @@ userNotFoundMessage=Benutzer nicht gefunden.
incorrectPasswordMessage=Das Passwort ist falsch.
usernameExistsMessage=Neuer Benutzername existiert bereits.
invalidUsernameMessage=Ungültiger Benutzername. Der Benutzername darf nur Buchstaben, Zahlen und die folgenden Sonderzeichen @._+- enthalten oder muss eine gültige E-Mail-Adresse sein.
confirmPasswordErrorMessage=„Neues Passwort“ und „Neues Passwort bestätigen“ müssen übereinstimmen.
deleteCurrentUserMessage=Der aktuell angemeldete Benutzer kann nicht gelöscht werden.
deleteUsernameExistsMessage=Der Benutzername existiert nicht und kann nicht gelöscht werden.
downgradeCurrentUserMessage=Die Rolle des aktuellen Benutzers kann nicht herabgestuft werden
@@ -71,7 +72,7 @@ visitGithub=GitHub-Repository besuchen
donate=Spenden
color=Farbe
sponsor=Sponsor
info=Die Info
info=Informationen
@@ -85,6 +86,7 @@ pipeline.defaultOption=Benutzerdefiniert
pipeline.submitButton=Speichern
pipeline.help=Hilfe für Pipeline
pipeline.scanHelp=Hilfe zum Ordnerscan
pipeline.deletePrompt=Are you sure you want to delete pipeline
######################
# Pipeline Options #
@@ -173,6 +175,8 @@ adminUserSettings.header=Administrator-Benutzerkontrolle
adminUserSettings.admin=Administrator
adminUserSettings.user=Benutzer
adminUserSettings.addUser=Neuen Benutzer hinzufügen
adminUserSettings.deleteUser=Benutzer löschen
adminUserSettings.confirmDeleteUser=Soll der Benutzer gelöscht werden?
adminUserSettings.usernameInfo=Der Benutzername darf nur Buchstaben, Zahlen und die folgenden Sonderzeichen @._+- enthalten oder muss eine gültige E-Mail-Adresse sein.
adminUserSettings.roles=Rollen
adminUserSettings.role=Rolle
@@ -332,6 +336,10 @@ home.certSign.title=Mit Zertifikat signieren
home.certSign.desc=Ein PDF mit einem Zertifikat/Schlüssel (PEM/P12) signieren
certSign.tags=authentifizieren,pem,p12,offiziell,verschlüsseln
home.removeCertSign.title=Zertifikatsignatur entfernen
home.removeCertSign.desc=Zertifikatsignatur aus PDF entfernen
removeCertSign.tags=authentifizieren,PEM,P12,offiziell,entschlüsseln,decrypt
home.pageLayout.title=Mehrseitiges Layout
home.pageLayout.desc=Mehrere Seiten eines PDF zu einer Seite zusammenführen
pageLayout.tags=zusammenführen,zusammensetzen,einzelansicht,organisieren
@@ -655,6 +663,13 @@ certSign.name=Name
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.title=Leere Seiten entfernen
removeBlanks.header=Leere Seiten entfernen
@@ -788,6 +803,7 @@ merge.title=Zusammenführen
merge.header=Mehrere PDFs zusammenführen (2+)
merge.sortByName=Nach Namen sortieren
merge.sortByDate=Nach Datum sortieren
merge.removeCertSign=Digitale Signatur in der zusammengeführten Datei entfernen?
merge.submit=Zusammenführen
@@ -805,6 +821,7 @@ pdfOrganiser.mode.6=Ungerade-Gerade-Teilung
pdfOrganiser.mode.7=Erste entfernen
pdfOrganiser.mode.8=Letzte entfernen
pdfOrganiser.mode.9=Erste und letzte entfernen
pdfOrganiser.mode.10=Ungerade-Gerade-Zusammenführung
pdfOrganiser.placeholder=(z.B. 1,3,2 oder 4-8,2,10-12 oder 2n-1)
@@ -965,6 +982,7 @@ pdfToPDFA.credit=Dieser Dienst verwendet OCRmyPDF für die PDF/A-Konvertierung
pdfToPDFA.submit=Konvertieren
pdfToPDFA.tip=Dieser Dienst kann nur einzelne Eingangsdateien verarbeiten.
pdfToPDFA.outputFormat=Ausgabeformat
pdfToPDFA.pdfWithDigitalSignature=Das PDF enthält eine digitale Signatur. Sie wird im nächsten Schritt entfernt.
#PDFToWord
@@ -1065,6 +1083,15 @@ licenses.module=Modul
licenses.version=Version
licenses.license=Lizenz
#survey
survey.nav=Survey
survey.title=Stirling-PDF Survey
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF!
survey.please=Please consider taking our survey!
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page)
survey.button=Take Survey
survey.dontShowAgain=Don't show again
#error
error.sorry=Entschuldigung für das Problem!

View File

@@ -55,6 +55,7 @@ userNotFoundMessage=Ο χρήστης δεν βρέθηκε.
incorrectPasswordMessage=Ο τρέχων κωδικός πρόσβασης είναι λανθασμένος.
usernameExistsMessage=Το νέο όνομα χρήστη υπάρχει ήδη.
invalidUsernameMessage=Μη έγκυρο όνομα χρήστη, όνομα χρήστη μπορεί να περιέχει μόνο γράμματα, αριθμούς και τους ακόλουθους ειδικούς χαρακτήρες @._+- ή πρέπει να είναι έγκυρη διεύθυνση email.
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
deleteCurrentUserMessage=Δεν είναι δυνατή η διαγραφή του τρέχοντος συνδεδεμένου χρήστη.
deleteUsernameExistsMessage=Το όνομα χρήστη δεν υπάρχει και δεν μπορεί να διαγραφεί.
downgradeCurrentUserMessage=Δεν είναι δυνατή η υποβάθμιση του ρόλου του τρέχοντος χρήστη
@@ -85,6 +86,7 @@ pipeline.defaultOption=Custom
pipeline.submitButton=Υποβολή
pipeline.help=Βοήθεια για το Pipeline
pipeline.scanHelp=Βοήθεια για Σάρωση Φακέλων
pipeline.deletePrompt=Are you sure you want to delete pipeline
######################
# Pipeline Options #
@@ -173,6 +175,8 @@ adminUserSettings.header=Ρυθμίσεις ελέγχου Διαχειριστ
adminUserSettings.admin=Διαχειριστής
adminUserSettings.user=Χρήστης
adminUserSettings.addUser=Προσθήκη νέου Χρήστη
adminUserSettings.deleteUser=Delete User
adminUserSettings.confirmDeleteUser=Should the user be deleted?
adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Ρόλοι
adminUserSettings.role=Ρόλος
@@ -332,6 +336,10 @@ home.certSign.title=Υπογραφή με Πιστοποιητικό
home.certSign.desc=Υπογραφή ενός PDF αρχείου με ένα Πιστοποιητικό/Κλειδί (PEM/P12)
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.desc=Συγχώνευση πολλαπλών σελίδων ενός εγγράφου PDF σε μία μόνο σελίδα
pageLayout.tags=merge,composite,single-view,organize
@@ -655,6 +663,13 @@ certSign.name=Όνομα
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.title=Αφαίρεση Κενών
removeBlanks.header=Αφαίρεση Κενών Σελίδων
@@ -788,6 +803,7 @@ merge.title=Συγχώνευση
merge.header=Συγχώνευση πολλαπλών PDFs (2+)
merge.sortByName=Ταξινόμηση με βάση το Όνομα
merge.sortByDate=Ταξινόμηση με βάση την Ημερομηνία
merge.removeCertSign=Remove digital signature in the merged file?
merge.submit=Συγχώνευση
@@ -965,6 +981,7 @@ pdfToPDFA.credit=Αυτή η υπηρεσία χρησιμοποιεί OCRmyPDF
pdfToPDFA.submit=Μετατροπή
pdfToPDFA.tip=Προς το παρόν δεν λειτουργεί για πολλαπλές εισόδους ταυτόχρονα
pdfToPDFA.outputFormat=Output format
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
#PDFToWord
@@ -1065,6 +1082,15 @@ licenses.module=Module
licenses.version=Εκδοχή
licenses.license=Άδεια
#survey
survey.nav=Survey
survey.title=Stirling-PDF Survey
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF!
survey.please=Please consider taking our survey!
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page)
survey.button=Take Survey
survey.dontShowAgain=Don't show again
#error
error.sorry=Συγγνώμη για το ζήτημα!

View File

@@ -55,6 +55,7 @@ userNotFoundMessage=User not found.
incorrectPasswordMessage=Current password is incorrect.
usernameExistsMessage=New Username already exists.
invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=Cannot downgrade current user's role
@@ -85,6 +86,7 @@ pipeline.defaultOption=Custom
pipeline.submitButton=Submit
pipeline.help=Pipeline Help
pipeline.scanHelp=Folder Scanning Help
pipeline.deletePrompt=Are you sure you want to delete pipeline
######################
# Pipeline Options #
@@ -173,6 +175,8 @@ adminUserSettings.header=Admin User Control Settings
adminUserSettings.admin=Admin
adminUserSettings.user=User
adminUserSettings.addUser=Add New User
adminUserSettings.deleteUser=Delete User
adminUserSettings.confirmDeleteUser=Should the user be deleted?
adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Roles
adminUserSettings.role=Role
@@ -332,6 +336,10 @@ home.certSign.title=Sign with Certificate
home.certSign.desc=Signs a PDF with a Certificate/Key (PEM/P12)
certSign.tags=authenticate,PEM,P12,official,encrypt
home.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.desc=Merge multiple pages of a PDF document into a single page
pageLayout.tags=merge,composite,single-view,organize
@@ -655,6 +663,13 @@ certSign.name=Name
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.title=Remove Blanks
removeBlanks.header=Remove Blank Pages
@@ -788,6 +803,7 @@ merge.title=Merge
merge.header=Merge multiple PDFs (2+)
merge.sortByName=Sort by name
merge.sortByDate=Sort by date
merge.removeCertSign=Remove digital signature in the merged file?
merge.submit=Merge
@@ -805,6 +821,7 @@ pdfOrganiser.mode.6=Odd-Even Split
pdfOrganiser.mode.7=Remove First
pdfOrganiser.mode.8=Remove Last
pdfOrganiser.mode.9=Remove First and Last
pdfOrganiser.mode.10=Odd-Even Merge
pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)
@@ -965,6 +982,7 @@ pdfToPDFA.credit=This service uses OCRmyPDF for PDF/A conversion
pdfToPDFA.submit=Convert
pdfToPDFA.tip=Currently does not work for multiple inputs at once
pdfToPDFA.outputFormat=Output format
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
#PDFToWord
@@ -1058,12 +1076,21 @@ printFile.submit=Print
#licenses
licenses.nav=Licenses
licenses.title=3rd Party Licenses
licenses.header=3rd Party Licenses
licenses.nav=Licences
licenses.title=3rd Party Licences
licenses.header=3rd Party Licences
licenses.module=Module
licenses.version=Version
licenses.license=License
licenses.license=Licence
#survey
survey.nav=Survey
survey.title=Stirling-PDF Survey
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF!
survey.please=Please consider taking our survey!
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page)
survey.button=Take Survey
survey.dontShowAgain=Don't show again
#error

View File

@@ -55,6 +55,7 @@ userNotFoundMessage=User not found.
incorrectPasswordMessage=Current password is incorrect.
usernameExistsMessage=New Username already exists.
invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=Cannot downgrade current user's role
@@ -85,6 +86,7 @@ pipeline.defaultOption=Custom
pipeline.submitButton=Submit
pipeline.help=Pipeline Help
pipeline.scanHelp=Folder Scanning Help
pipeline.deletePrompt=Are you sure you want to delete pipeline
######################
# Pipeline Options #
@@ -173,6 +175,8 @@ adminUserSettings.header=Admin User Control Settings
adminUserSettings.admin=Admin
adminUserSettings.user=User
adminUserSettings.addUser=Add New User
adminUserSettings.deleteUser=Delete User
adminUserSettings.confirmDeleteUser=Should the user be deleted?
adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Roles
adminUserSettings.role=Role
@@ -332,6 +336,10 @@ home.certSign.title=Sign with Certificate
home.certSign.desc=Signs a PDF with a Certificate/Key (PEM/P12)
certSign.tags=authenticate,PEM,P12,official,encrypt
home.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.desc=Merge multiple pages of a PDF document into a single page
pageLayout.tags=merge,composite,single-view,organize
@@ -655,6 +663,13 @@ certSign.name=Name
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.title=Remove Blanks
removeBlanks.header=Remove Blank Pages
@@ -788,6 +803,7 @@ merge.title=Merge
merge.header=Merge multiple PDFs (2+)
merge.sortByName=Sort by name
merge.sortByDate=Sort by date
merge.removeCertSign=Remove digital signature in the merged file?
merge.submit=Merge
@@ -805,6 +821,7 @@ pdfOrganiser.mode.6=Odd-Even Split
pdfOrganiser.mode.7=Remove First
pdfOrganiser.mode.8=Remove Last
pdfOrganiser.mode.9=Remove First and Last
pdfOrganiser.mode.10=Odd-Even Merge
pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)
@@ -965,6 +982,7 @@ pdfToPDFA.credit=This service uses OCRmyPDF for PDF/A conversion
pdfToPDFA.submit=Convert
pdfToPDFA.tip=Currently does not work for multiple inputs at once
pdfToPDFA.outputFormat=Output format
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
#PDFToWord
@@ -1065,6 +1083,15 @@ licenses.module=Module
licenses.version=Version
licenses.license=License
#survey
survey.nav=Survey
survey.title=Stirling-PDF Survey
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF!
survey.please=Please consider taking our survey!
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page)
survey.button=Take Survey
survey.dontShowAgain=Don't show again
#error
error.sorry=Sorry for the issue!

View File

@@ -55,6 +55,7 @@ userNotFoundMessage=Usuario no encontrado.
incorrectPasswordMessage=La contraseña actual no es correcta.
usernameExistsMessage=El nuevo nombre de usuario está en uso.
invalidUsernameMessage=Nombre de usuario no válido, el nombre de usuario solo puede contener letras, números y los siguientes caracteres especiales @._+- o debe ser una dirección de correo electrónico válida.
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
deleteCurrentUserMessage=No puede eliminar el usuario que tiene la sesión actualmente en uso.
deleteUsernameExistsMessage=El usuario no existe y no puede eliminarse.
downgradeCurrentUserMessage=No se puede degradar el rol del usuario actual
@@ -85,6 +86,7 @@ pipeline.defaultOption=Personalizar
pipeline.submitButton=Enviar
pipeline.help=Ayuda de Canalización
pipeline.scanHelp=Ayuda de escaneado de carpetas
pipeline.deletePrompt=Are you sure you want to delete pipeline
######################
# Pipeline Options #
@@ -173,6 +175,8 @@ adminUserSettings.header=Configuración de control de usuario administrador
adminUserSettings.admin=Administrador
adminUserSettings.user=Usuario
adminUserSettings.addUser=Añadir Nuevo Usuario
adminUserSettings.deleteUser=Delete User
adminUserSettings.confirmDeleteUser=Should the user be deleted?
adminUserSettings.usernameInfo=El nombre de usuario solo puede contener letras, números y los siguientes caracteres especiales @._+- o debe ser una dirección de correo electrónico válida.
adminUserSettings.roles=Roles
adminUserSettings.role=Rol
@@ -332,6 +336,10 @@ home.certSign.title=Firmar con certificado
home.certSign.desc=Firmar un PDF con un Certificado/Clave (PEM/P12)
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.desc=Unir varias páginas de un documento PDF en una sola página
pageLayout.tags=unir,compuesto,vista única,organizar
@@ -655,6 +663,13 @@ certSign.name=Nombre
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.title=Eliminar espacios en blanco
removeBlanks.header=Eliminar páginas en blanco
@@ -788,6 +803,7 @@ merge.title=Unir
merge.header=Unir múltiples PDFs (2+)
merge.sortByName=Ordenar por nombre
merge.sortByDate=Ordenar por fecha
merge.removeCertSign=Remove digital signature in the merged file?
merge.submit=Unir
@@ -965,6 +981,7 @@ pdfToPDFA.credit=Este servicio usa OCRmyPDF para la conversión a PDF/A
pdfToPDFA.submit=Convertir
pdfToPDFA.tip=Actualmente no funciona para múltiples entrada a la vez
pdfToPDFA.outputFormat=Output format
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
#PDFToWord
@@ -1065,6 +1082,15 @@ licenses.module=Módulo
licenses.version=Versión
licenses.license=Licencia
#survey
survey.nav=Survey
survey.title=Stirling-PDF Survey
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF!
survey.please=Please consider taking our survey!
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page)
survey.button=Take Survey
survey.dontShowAgain=Don't show again
#error
error.sorry=¡Perdón por el fallo!

View File

@@ -55,6 +55,7 @@ userNotFoundMessage=User not found.
incorrectPasswordMessage=Current password is incorrect.
usernameExistsMessage=New Username already exists.
invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=Ezin da uneko erabiltzailearen rola jaitsi
@@ -85,6 +86,7 @@ pipeline.defaultOption=Custom
pipeline.submitButton=Submit
pipeline.help=Pipeline Help
pipeline.scanHelp=Folder Scanning Help
pipeline.deletePrompt=Are you sure you want to delete pipeline
######################
# Pipeline Options #
@@ -173,6 +175,8 @@ adminUserSettings.header=Admin Erabiltzailearen Ezarpenen Kontrolak
adminUserSettings.admin=Admin
adminUserSettings.user=Erabiltzaile
adminUserSettings.addUser=Erabiltzaile berria
adminUserSettings.deleteUser=Delete User
adminUserSettings.confirmDeleteUser=Should the user be deleted?
adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Rolak
adminUserSettings.role=Rol
@@ -332,6 +336,10 @@ home.certSign.title=Sinatu ziurtagiriarekin
home.certSign.desc=Sinatu PDF bat Ziurtagiri/Gako batekin (PEM/P12)
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.desc=Elkartu orri bakar batean PDF dokumentu baten zenbait orrialde
pageLayout.tags=merge,composite,single-view,organize
@@ -655,6 +663,13 @@ certSign.name=Izena
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.title=Ezabatu zuriuneak
removeBlanks.header=Ezabatu orrialde zuriak
@@ -788,6 +803,7 @@ merge.title=Elkartu
merge.header=Elkartu zenbait PDF (2+)
merge.sortByName=Sort by nameOrdenatu izenaren arabera
merge.sortByDate=Ordenatu dataren arabera
merge.removeCertSign=Remove digital signature in the merged file?
merge.submit=Elkartu
@@ -965,6 +981,7 @@ pdfToPDFA.credit=Zerbitzu honek OCRmyPDF erabiltzen du PDFak PDF/A bihurtzeko
pdfToPDFA.submit=Bihurtu
pdfToPDFA.tip=Currently does not work for multiple inputs at once
pdfToPDFA.outputFormat=Output format
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
#PDFToWord
@@ -1065,6 +1082,15 @@ licenses.module=Module
licenses.version=Version
licenses.license=License
#survey
survey.nav=Survey
survey.title=Stirling-PDF Survey
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF!
survey.please=Please consider taking our survey!
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page)
survey.button=Take Survey
survey.dontShowAgain=Don't show again
#error
error.sorry=Sorry for the issue!

View File

@@ -55,6 +55,7 @@ userNotFoundMessage=Utilisateur non trouvé.
incorrectPasswordMessage=Le mot de passe actuel est incorrect.
usernameExistsMessage=Le nouveau nom dutilisateur existe déjà.
invalidUsernameMessage=Nom dutilisateur invalide, le nom dutilisateur ne peut contenir que des lettres, des chiffres et les caractères spéciaux suivants @._+- ou doit être une adresse e-mail valide.
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
deleteCurrentUserMessage=Impossible de supprimer lutilisateur actuellement connecté.
deleteUsernameExistsMessage=Le nom dutilisateur nexiste pas et ne peut pas être supprimé.
downgradeCurrentUserMessage=Impossible de rétrograder le rôle de l'utilisateur actuel.
@@ -85,6 +86,7 @@ pipeline.defaultOption=Personnaliser
pipeline.submitButton=Soumettre
pipeline.help=Aide Pipeline
pipeline.scanHelp=Aide analyse de dossier
pipeline.deletePrompt=Are you sure you want to delete pipeline
######################
# Pipeline Options #
@@ -173,6 +175,8 @@ adminUserSettings.header=Administration des paramètres des utilisateurs
adminUserSettings.admin=Administateur
adminUserSettings.user=Utilisateur
adminUserSettings.addUser=Ajouter un utilisateur
adminUserSettings.deleteUser=Delete User
adminUserSettings.confirmDeleteUser=Should the user be deleted?
adminUserSettings.usernameInfo=Le nom d'utilisateur ne peut contenir que des lettres, des chiffres et les caractères spéciaux suivants @._+- ou doit être une adresse e-mail valide.
adminUserSettings.roles=Rôles
adminUserSettings.role=Rôle
@@ -267,7 +271,7 @@ home.fileToPDF.desc=Convertissez presque nimporte quel fichiers en PDF (DOCX,
fileToPDF.tags=convertion,transformation,format,document,image,slide,texte,conversion,office,docs,word,excel,powerpoint
home.ocr.title=OCR / Nettoyage des numérisations
home.ocr.desc=Utilisez lOCR pour analyser et détecter le texte des images dun PDF et le rajouter en temps que tel.
home.ocr.desc=Utilisez lOCR pour analyser et détecter le texte des images dun PDF et le rajouter en tant que tel.
ocr.tags=ocr,reconnaissance,texte,image,numérisation,scan,read,identify,detection,editable
@@ -332,6 +336,10 @@ home.certSign.title=Signer avec un certificat
home.certSign.desc=Signez un PDF avec un certificat ou une clé (PEM/P12).
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.desc=Fusionnez plusieurs pages dun PDF en une seule.
pageLayout.tags=fusionner,merge,composite,single-view,organize
@@ -452,12 +460,12 @@ login.locked=Votre compte a été verrouillé.
login.signinTitle=Veuillez vous connecter
login.ssoSignIn=Se connecter via l'authentification unique
login.oauth2AutoCreateDisabled=OAUTH2 Création automatique d'utilisateur désactivée
login.oauth2RequestNotFound=Authorization request not found
login.oauth2InvalidUserInfoResponse=Invalid User Info Response
login.oauth2invalidRequest=Invalid Request
login.oauth2AccessDenied=Access Denied
login.oauth2InvalidTokenResponse=Invalid Token Response
login.oauth2InvalidIdToken=Invalid Id Token
login.oauth2RequestNotFound=Demande d'autorisation introuvable
login.oauth2InvalidUserInfoResponse=Réponse contenant les informations de l'utilisateur est invalide
login.oauth2invalidRequest=Requête invalide
login.oauth2AccessDenied=Accès refusé
login.oauth2InvalidTokenResponse=Réponse contenant le jeton est invalide
login.oauth2InvalidIdToken=Jeton d'identification invalide
#auto-redact
@@ -655,6 +663,13 @@ certSign.name=Nom
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.title=Supprimer les pages vierges
removeBlanks.header=Supprimer les pages vierges
@@ -679,14 +694,14 @@ compare.document.2=Document 2
compare.submit=Comparer
#BookToPDF
BookToPDF.title=Books and Comics to PDF
BookToPDF.header=Book to PDF
BookToPDF.title=Livres et BD vers PDF
BookToPDF.header=Livre vers PDF
BookToPDF.credit=Utiliser Calibre
BookToPDF.submit=Convertir
#PDFToBook
PDFToBook.title=PDF to Book
PDFToBook.header=PDF to Book
PDFToBook.title=PDF vers Livre
PDFToBook.header=PDF vers Livre
PDFToBook.selectText.1=Format
PDFToBook.credit=Utiliser Calibre
PDFToBook.submit=Convertir
@@ -788,6 +803,7 @@ merge.title=Fusionner
merge.header=Fusionner plusieurs PDF
merge.sortByName=Trier par nom
merge.sortByDate=Trier par date
merge.removeCertSign=Remove digital signature in the merged file?
merge.submit=Fusionner
@@ -965,6 +981,7 @@ pdfToPDFA.credit=Ce service utilise OCRmyPDF pour la conversion en PDF/A.
pdfToPDFA.submit=Convertir
pdfToPDFA.tip=Ne fonctionne actuellement pas pour plusieurs entrées à la fois
pdfToPDFA.outputFormat=Format de sortie
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
#PDFToWord
@@ -1065,6 +1082,15 @@ licenses.module=Module
licenses.version=Version
licenses.license=Licence
#survey
survey.nav=Survey
survey.title=Stirling-PDF Survey
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF!
survey.please=Please consider taking our survey!
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page)
survey.button=Take Survey
survey.dontShowAgain=Don't show again
#error
error.sorry=Désolé pour ce problème !

View File

@@ -55,6 +55,7 @@ userNotFoundMessage=उपयोगकर्ता नहीं मिला।
incorrectPasswordMessage=वर्तमान पासवर्ड गलत है।
usernameExistsMessage=नया उपयोगकर्ता नाम पहले से मौजूद है।
invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=मौजूदा यूज़र की भूमिका को डाउनग्रेड नहीं किया जा सकता
@@ -85,6 +86,7 @@ pipeline.defaultOption=Custom
pipeline.submitButton=Submit
pipeline.help=Pipeline Help
pipeline.scanHelp=Folder Scanning Help
pipeline.deletePrompt=Are you sure you want to delete pipeline
######################
# Pipeline Options #
@@ -173,6 +175,8 @@ adminUserSettings.header=व्यवस्थापक उपयोगकर्
adminUserSettings.admin=व्यवस्थापक
adminUserSettings.user=उपयोगकर्ता
adminUserSettings.addUser=नया उपयोगकर्ता जोड़ें
adminUserSettings.deleteUser=Delete User
adminUserSettings.confirmDeleteUser=Should the user be deleted?
adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=रोल्स
adminUserSettings.role=रोल
@@ -332,6 +336,10 @@ home.certSign.title=प्रमाणपत्र के साथ हस्त
home.certSign.desc=पीडीएफ़ को प्रमाणपत्र/कुंजी (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.desc=पीडीएफ़ दस्तावेज़ के कई पेजों को एक ही पेज में मर्ज करता है।
pageLayout.tags=मर्ज, संयोजित, एकल दृश्य, संगठित
@@ -655,6 +663,13 @@ certSign.name=नाम
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.title=खाली पेज हटाएं
removeBlanks.header=खाली पेज हटाएं
@@ -788,6 +803,7 @@ merge.title=मर्ज
merge.header=एक से अधिक PDF एक साथ मर्ज करें (2+)
merge.sortByName=नाम से क्रमबद्ध करें
merge.sortByDate=तारीख से क्रमबद्ध करें
merge.removeCertSign=Remove digital signature in the merged file?
merge.submit=मर्ज करें
@@ -965,6 +981,7 @@ pdfToPDFA.credit=इस सेवा में PDF/A परिवर्तन
pdfToPDFA.submit=परिवर्तित करें
pdfToPDFA.tip=Currently does not work for multiple inputs at once
pdfToPDFA.outputFormat=Output format
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
#PDFToWord
@@ -1065,6 +1082,15 @@ licenses.module=Module
licenses.version=Version
licenses.license=License
#survey
survey.nav=Survey
survey.title=Stirling-PDF Survey
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF!
survey.please=Please consider taking our survey!
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page)
survey.button=Take Survey
survey.dontShowAgain=Don't show again
#error
error.sorry=Sorry for the issue!

File diff suppressed because it is too large Load Diff

View File

@@ -55,6 +55,7 @@ userNotFoundMessage=A felhasználó nem található.
incorrectPasswordMessage=A jelenlegi jelszó helytelen.
usernameExistsMessage=Az új felhasználónév már létezik.
invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=A jelenlegi felhasználó szerepkörét nem lehet visszaminősíteni
@@ -85,6 +86,7 @@ pipeline.defaultOption=Custom
pipeline.submitButton=Submit
pipeline.help=Pipeline Help
pipeline.scanHelp=Folder Scanning Help
pipeline.deletePrompt=Are you sure you want to delete pipeline
######################
# Pipeline Options #
@@ -173,6 +175,8 @@ adminUserSettings.header=Adminisztrátori Felhasználói Vezérlési Beállítá
adminUserSettings.admin=Adminisztrátor
adminUserSettings.user=Felhasználó
adminUserSettings.addUser=Új felhasználó hozzáadása
adminUserSettings.deleteUser=Delete User
adminUserSettings.confirmDeleteUser=Should the user be deleted?
adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Szerepek
adminUserSettings.role=Szerep
@@ -332,6 +336,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)
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.desc=Több oldal egyesítése egy PDF dokumentumban egyetlen oldallá
pageLayout.tags=egyesítés,kompozit,egy oldal,megszervez
@@ -655,6 +663,13 @@ certSign.name=Név
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.title=Üres oldalak eltávolítása
removeBlanks.header=Üres oldalak eltávolítása
@@ -788,6 +803,7 @@ merge.title=Összevonás
merge.header=Több PDF összevonása (2+)
merge.sortByName=Név szerinti rendezés
merge.sortByDate=Dátum szerinti rendezés
merge.removeCertSign=Remove digital signature in the merged file?
merge.submit=Összevonás
@@ -965,6 +981,7 @@ pdfToPDFA.credit=Ez a szolgáltatás az OCRmyPDF-t használja a PDF/A konverzió
pdfToPDFA.submit=Konvertálás
pdfToPDFA.tip=Currently does not work for multiple inputs at once
pdfToPDFA.outputFormat=Output format
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
#PDFToWord
@@ -1065,6 +1082,15 @@ licenses.module=Module
licenses.version=Version
licenses.license=License
#survey
survey.nav=Survey
survey.title=Stirling-PDF Survey
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF!
survey.please=Please consider taking our survey!
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page)
survey.button=Take Survey
survey.dontShowAgain=Don't show again
#error
error.sorry=Sorry for the issue!

View File

@@ -55,6 +55,7 @@ userNotFoundMessage=Pengguna tidak ditemukan.
incorrectPasswordMessage=Kata sandi saat ini salah.
usernameExistsMessage=Nama pengguna baru sudah ada.
invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=Tidak dapat menurunkan peran pengguna saat ini
@@ -85,6 +86,7 @@ pipeline.defaultOption=Custom
pipeline.submitButton=Submit
pipeline.help=Pipeline Help
pipeline.scanHelp=Folder Scanning Help
pipeline.deletePrompt=Are you sure you want to delete pipeline
######################
# Pipeline Options #
@@ -173,6 +175,8 @@ adminUserSettings.header=Pengaturan Kontrol Admin
adminUserSettings.admin=Admin
adminUserSettings.user=Pengguna
adminUserSettings.addUser=Tambahkan Pengguna Baru
adminUserSettings.deleteUser=Delete User
adminUserSettings.confirmDeleteUser=Should the user be deleted?
adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Peran
adminUserSettings.role=Peran
@@ -332,6 +336,10 @@ home.certSign.title=Tanda tangani dengan Sertifikat
home.certSign.desc=Menandatangani PDF dengan Certificate/Key (PEM/P12)
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.desc=Menggabungkan beberapa halaman dokumen PDF menjadi satu halaman
pageLayout.tags=menggabungkan, komposit, tampilan tunggal, mengatur
@@ -655,6 +663,13 @@ certSign.name=Nama
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.title=Hapus Halaman Kosong
removeBlanks.header=Remove Blank Pages
@@ -788,6 +803,7 @@ merge.title=Gabungkan
merge.header=Gabungkan beberapa PDFs (2+)
merge.sortByName=Sortir berdasarkan nama
merge.sortByDate=Sortir berdasrkan tanggal
merge.removeCertSign=Remove digital signature in the merged file?
merge.submit=Gabungkan
@@ -965,6 +981,7 @@ pdfToPDFA.credit=Layanan ini menggunakan OCRmyPDF untuk konversi PDF/A.
pdfToPDFA.submit=Konversi
pdfToPDFA.tip=Currently does not work for multiple inputs at once
pdfToPDFA.outputFormat=Output format
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
#PDFToWord
@@ -1065,6 +1082,15 @@ licenses.module=Module
licenses.version=Version
licenses.license=License
#survey
survey.nav=Survey
survey.title=Stirling-PDF Survey
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF!
survey.please=Please consider taking our survey!
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page)
survey.button=Take Survey
survey.dontShowAgain=Don't show again
#error
error.sorry=Sorry for the issue!

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