1
0
mirror of https://github.com/Stirling-Tools/Stirling-PDF.git synced 2024-11-11 02:10:11 +01:00

Merge branch 'main' into dependabot/gradle/io.micrometer-micrometer-core-1.13.0

This commit is contained in:
Anthony Stirling 2024-06-09 15:39:57 +01:00 committed by GitHub
commit 5e3511a5b2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
86 changed files with 1811 additions and 649 deletions

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

@ -167,31 +167,31 @@ Stirling PDF currently supports 32!
| English (US) (en_US) | ![100%](https://geps.dev/progress/100) | | English (US) (en_US) | ![100%](https://geps.dev/progress/100) |
| Arabic (العربية) (ar_AR) | ![40%](https://geps.dev/progress/40) | | Arabic (العربية) (ar_AR) | ![40%](https://geps.dev/progress/40) |
| German (Deutsch) (de_DE) | ![99%](https://geps.dev/progress/99) | | German (Deutsch) (de_DE) | ![99%](https://geps.dev/progress/99) |
| French (Français) (fr_FR) | ![93%](https://geps.dev/progress/93) | | French (Français) (fr_FR) | ![94%](https://geps.dev/progress/94) |
| Spanish (Español) (es_ES) | ![95%](https://geps.dev/progress/95) | | Spanish (Español) (es_ES) | ![94%](https://geps.dev/progress/94) |
| Simplified Chinese (简体中文) (zh_CN) | ![95%](https://geps.dev/progress/95) | | Simplified Chinese (简体中文) (zh_CN) | ![95%](https://geps.dev/progress/95) |
| Traditional Chinese (繁體中文) (zh_TW) | ![94%](https://geps.dev/progress/94) | | Traditional Chinese (繁體中文) (zh_TW) | ![94%](https://geps.dev/progress/94) |
| Catalan (Català) (ca_CA) | ![49%](https://geps.dev/progress/49) | | Catalan (Català) (ca_CA) | ![49%](https://geps.dev/progress/49) |
| Italian (Italiano) (it_IT) | ![98%](https://geps.dev/progress/98) | | Italian (Italiano) (it_IT) | ![99%](https://geps.dev/progress/99) |
| Swedish (Svenska) (sv_SE) | ![40%](https://geps.dev/progress/40) | | Swedish (Svenska) (sv_SE) | ![40%](https://geps.dev/progress/40) |
| Polish (Polski) (pl_PL) | ![42%](https://geps.dev/progress/42) | | Polish (Polski) (pl_PL) | ![42%](https://geps.dev/progress/42) |
| Romanian (Română) (ro_RO) | ![39%](https://geps.dev/progress/39) | | Romanian (Română) (ro_RO) | ![39%](https://geps.dev/progress/39) |
| Korean (한국어) (ko_KR) | ![87%](https://geps.dev/progress/87) | | Korean (한국어) (ko_KR) | ![87%](https://geps.dev/progress/87) |
| Portuguese Brazilian (Português) (pt_BR) | ![61%](https://geps.dev/progress/61) | | Portuguese Brazilian (Português) (pt_BR) | ![61%](https://geps.dev/progress/61) |
| Russian (Русский) (ru_RU) | ![87%](https://geps.dev/progress/87) | | Russian (Русский) (ru_RU) | ![86%](https://geps.dev/progress/86) |
| Basque (Euskara) (eu_ES) | ![63%](https://geps.dev/progress/63) | | Basque (Euskara) (eu_ES) | ![63%](https://geps.dev/progress/63) |
| Japanese (日本語) (ja_JP) | ![87%](https://geps.dev/progress/87) | | Japanese (日本語) (ja_JP) | ![87%](https://geps.dev/progress/87) |
| Dutch (Nederlands) (nl_NL) | ![85%](https://geps.dev/progress/85) | | Dutch (Nederlands) (nl_NL) | ![84%](https://geps.dev/progress/84) |
| Greek (Ελληνικά) (el_GR) | ![85%](https://geps.dev/progress/85) | | Greek (Ελληνικά) (el_GR) | ![85%](https://geps.dev/progress/85) |
| Turkish (Türkçe) (tr_TR) | ![97%](https://geps.dev/progress/97) | | Turkish (Türkçe) (tr_TR) | ![97%](https://geps.dev/progress/97) |
| Indonesia (Bahasa Indonesia) (id_ID) | ![78%](https://geps.dev/progress/78) | | Indonesia (Bahasa Indonesia) (id_ID) | ![78%](https://geps.dev/progress/78) |
| Hindi (हिंदी) (hi_IN) | ![79%](https://geps.dev/progress/79) | | Hindi (हिंदी) (hi_IN) | ![79%](https://geps.dev/progress/79) |
| Hungarian (Magyar) (hu_HU) | ![78%](https://geps.dev/progress/78) | | Hungarian (Magyar) (hu_HU) | ![77%](https://geps.dev/progress/77) |
| Bulgarian (Български) (bg_BG) | ![98%](https://geps.dev/progress/98) | | Bulgarian (Български) (bg_BG) | ![97%](https://geps.dev/progress/97) |
| Sebian Latin alphabet (Srpski) (sr_LATN_RS) | ![80%](https://geps.dev/progress/80) | | Sebian Latin alphabet (Srpski) (sr_LATN_RS) | ![80%](https://geps.dev/progress/80) |
| Ukrainian (Українська) (uk_UA) | ![86%](https://geps.dev/progress/86) | | Ukrainian (Українська) (uk_UA) | ![86%](https://geps.dev/progress/86) |
| Slovakian (Slovensky) (sk_SK) | ![95%](https://geps.dev/progress/95) | | Slovakian (Slovensky) (sk_SK) | ![94%](https://geps.dev/progress/94) |
| Czech (Česky) (cs_CZ) | ![94%](https://geps.dev/progress/94) | | Czech (Česky) (cs_CZ) | ![93%](https://geps.dev/progress/93) |
| Croatian (Hrvatski) (hr_HR) | ![98%](https://geps.dev/progress/98) | | Croatian (Hrvatski) (hr_HR) | ![98%](https://geps.dev/progress/98) |
| Norwegian (Norsk) (no_NB) | ![98%](https://geps.dev/progress/98) | | Norwegian (Norsk) (no_NB) | ![98%](https://geps.dev/progress/98) |

View File

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 50 KiB

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: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 44 KiB

BIN
images/settings-light.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 366 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

@ -61,6 +61,7 @@ ignore = [
[fr_FR] [fr_FR]
ignore = [ ignore = [
'language.direction', 'language.direction',
'sponsor',
] ]
[hi_IN] [hi_IN]

View File

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

View File

@ -42,9 +42,11 @@ public class CustomAuthenticationFailureHandler extends SimpleUrlAuthenticationF
String ip = request.getRemoteAddr(); String ip = request.getRemoteAddr();
logger.error("Failed login attempt from IP: {}", ip); logger.error("Failed login attempt from IP: {}", ip);
String contextPath = request.getContextPath();
if (exception.getClass().isAssignableFrom(InternalAuthenticationServiceException.class) if (exception.getClass().isAssignableFrom(InternalAuthenticationServiceException.class)
|| "Password must not be null".equalsIgnoreCase(exception.getMessage())) { || "Password must not be null".equalsIgnoreCase(exception.getMessage())) {
response.sendRedirect("/login?error=oauth2AuthenticationError"); response.sendRedirect(contextPath + "/login?error=oauth2AuthenticationError");
return; return;
} }
@ -59,13 +61,13 @@ public class CustomAuthenticationFailureHandler extends SimpleUrlAuthenticationF
loginAttemptService.loginFailed(username); loginAttemptService.loginFailed(username);
if (loginAttemptService.isBlocked(username) if (loginAttemptService.isBlocked(username)
|| exception.getClass().isAssignableFrom(LockedException.class)) { || exception.getClass().isAssignableFrom(LockedException.class)) {
response.sendRedirect("/login?error=locked"); response.sendRedirect(contextPath + "/login?error=locked");
return; return;
} }
} }
if (exception.getClass().isAssignableFrom(BadCredentialsException.class) if (exception.getClass().isAssignableFrom(BadCredentialsException.class)
|| exception.getClass().isAssignableFrom(UsernameNotFoundException.class)) { || exception.getClass().isAssignableFrom(UsernameNotFoundException.class)) {
response.sendRedirect("/login?error=badcredentials"); response.sendRedirect(contextPath + "/login?error=badcredentials");
return; return;
} }

View File

@ -44,7 +44,7 @@ public class FirstLoginFilter extends OncePerRequestFilter {
&& user.isPresent() && user.isPresent()
&& user.get().isFirstLogin() && user.get().isFirstLogin()
&& !"/change-creds".equals(requestURI)) { && !"/change-creds".equals(requestURI)) {
response.sendRedirect("/change-creds"); response.sendRedirect(request.getContextPath() + "/change-creds");
return; return;
} }
} }

View File

@ -10,11 +10,16 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Comparator; import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import org.apache.pdfbox.Loader; import org.apache.pdfbox.Loader;
import org.apache.pdfbox.multipdf.PDFMergerUtility; import org.apache.pdfbox.multipdf.PDFMergerUtility;
import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDDocumentCatalog;
import org.apache.pdfbox.pdmodel.PDPage; 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.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
@ -38,6 +43,7 @@ public class MergeController {
private static final Logger logger = LoggerFactory.getLogger(MergeController.class); 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 { public PDDocument mergeDocuments(List<PDDocument> documents) throws IOException {
PDDocument mergedDoc = new PDDocument(); PDDocument mergedDoc = new PDDocument();
for (PDDocument doc : documents) { for (PDDocument doc : documents) {
@ -48,6 +54,7 @@ public class MergeController {
return mergedDoc; return mergedDoc;
} }
// Returns a comparator for sorting MultipartFile arrays based on the given sort type
private Comparator<MultipartFile> getSortComparator(String sortType) { private Comparator<MultipartFile> getSortComparator(String sortType) {
switch (sortType) { switch (sortType) {
case "byFileName": 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") "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) public ResponseEntity<byte[]> mergePdfs(@ModelAttribute MergePdfsRequest form)
throws IOException { 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 { try {
MultipartFile[] files = form.getFileInput(); MultipartFile[] files = form.getFileInput();
Arrays.sort(files, getSortComparator(form.getSortType())); Arrays.sort(
files,
PDFMergerUtility mergedDoc = new PDFMergerUtility(); getSortComparator(
ByteArrayOutputStream docOutputstream = new ByteArrayOutputStream(); form.getSortType())); // Sort files based on the given sort type
PDFMergerUtility mergerUtility = new PDFMergerUtility();
for (MultipartFile multipartFile : files) { for (MultipartFile multipartFile : files) {
File tempFile = GeneralUtils.convertMultipartFileToFile(multipartFile); File tempFile =
filesToDelete.add(tempFile); GeneralUtils.convertMultipartFileToFile(
mergedDoc.addSource(tempFile); 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( // Save the modified document to a new ByteArrayOutputStream
files[0].getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_merged.pdf"); ByteArrayOutputStream baos = new ByteArrayOutputStream();
mergedDoc.setDestinationStream(docOutputstream); mergedDocument.save(baos);
mergedDoc.mergeDocuments(null);
String mergedFileName =
files[0].getOriginalFilename().replaceFirst("[.][^.]+$", "")
+ "_merged_unsigned.pdf";
return WebResponseUtils.bytesToWebResponse( return WebResponseUtils.bytesToWebResponse(
docOutputstream.toByteArray(), mergedDoc.getDestinationFileName()); baos.toByteArray(), mergedFileName); // Return the modified PDF
} catch (Exception ex) { } catch (Exception ex) {
logger.error("Error in merge pdf process", ex); logger.error("Error in merge pdf process", ex);
throw ex; throw ex;
} finally { } finally {
for (File file : filesToDelete) { for (File file : filesToDelete) {
if (file != null) { 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

@ -105,7 +105,14 @@ public class PipelineProcessor {
body.add("fileInput", file); body.add("fileInput", file);
for (Entry<String, Object> entry : parameters.entrySet()) { 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); ResponseEntity<byte[]> response = sendWebRequest(url, body);
@ -167,7 +174,14 @@ public class PipelineProcessor {
} }
for (Entry<String, Object> entry : parameters.entrySet()) { 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); ResponseEntity<byte[]> response = sendWebRequest(url, body);

View File

@ -21,4 +21,10 @@ public class MergePdfsRequest extends MultiplePDFFiles {
}, },
defaultValue = "orderProvided") defaultValue = "orderProvided")
private String sortType = "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

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

View File

@ -55,6 +55,7 @@ userNotFoundMessage=User not found.
incorrectPasswordMessage=Current password is incorrect. incorrectPasswordMessage=Current password is incorrect.
usernameExistsMessage=New Username already exists. 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. 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. deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted. deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=لا يمكن خفض دور المستخدم الحالي downgradeCurrentUserMessage=لا يمكن خفض دور المستخدم الحالي
@ -85,6 +86,7 @@ pipeline.defaultOption=Custom
pipeline.submitButton=Submit pipeline.submitButton=Submit
pipeline.help=Pipeline Help pipeline.help=Pipeline Help
pipeline.scanHelp=Folder Scanning Help pipeline.scanHelp=Folder Scanning Help
pipeline.deletePrompt=Are you sure you want to delete pipeline
###################### ######################
# Pipeline Options # # Pipeline Options #
@ -173,6 +175,8 @@ adminUserSettings.header=Admin User Control Settings
adminUserSettings.admin=Admin adminUserSettings.admin=Admin
adminUserSettings.user=User adminUserSettings.user=User
adminUserSettings.addUser=Add New 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.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Roles adminUserSettings.roles=Roles
adminUserSettings.role=Role adminUserSettings.role=Role
@ -799,6 +803,7 @@ merge.title=دمج
merge.header=دمج ملفات PDF متعددة (2+) merge.header=دمج ملفات PDF متعددة (2+)
merge.sortByName=Sort by name merge.sortByName=Sort by name
merge.sortByDate=Sort by date merge.sortByDate=Sort by date
merge.removeCertSign=Remove digital signature in the merged file?
merge.submit=دمج merge.submit=دمج

View File

@ -55,6 +55,7 @@ userNotFoundMessage=Потребителят не е намерен
incorrectPasswordMessage=Текущата парола е неправилна. incorrectPasswordMessage=Текущата парола е неправилна.
usernameExistsMessage=Новият потребител вече съществува. usernameExistsMessage=Новият потребител вече съществува.
invalidUsernameMessage=Невалидно потребителско име, потребителското име може да съдържа само букви, цифри и следните специални знаци @._+- или трябва да е валиден имейл адрес. invalidUsernameMessage=Невалидно потребителско име, потребителското име може да съдържа само букви, цифри и следните специални знаци @._+- или трябва да е валиден имейл адрес.
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
deleteCurrentUserMessage=Не може да се изтрие вписания в момента потребител. deleteCurrentUserMessage=Не може да се изтрие вписания в момента потребител.
deleteUsernameExistsMessage=Потребителското име не съществува и не може да бъде изтрито. deleteUsernameExistsMessage=Потребителското име не съществува и не може да бъде изтрито.
downgradeCurrentUserMessage=Не може да се понижи ролята на текущия потребител downgradeCurrentUserMessage=Не може да се понижи ролята на текущия потребител
@ -85,6 +86,7 @@ pipeline.defaultOption=Персонализиран
pipeline.submitButton=Подайте pipeline.submitButton=Подайте
pipeline.help=Pipeline Помощ pipeline.help=Pipeline Помощ
pipeline.scanHelp=Помощ за сканиране на папки pipeline.scanHelp=Помощ за сканиране на папки
pipeline.deletePrompt=Are you sure you want to delete pipeline
###################### ######################
# Pipeline Options # # Pipeline Options #
@ -173,6 +175,8 @@ adminUserSettings.header=Настройки за администраторск
adminUserSettings.admin=Администратор adminUserSettings.admin=Администратор
adminUserSettings.user=Потребител adminUserSettings.user=Потребител
adminUserSettings.addUser=Добавяне на нов потребител adminUserSettings.addUser=Добавяне на нов потребител
adminUserSettings.deleteUser=Delete User
adminUserSettings.confirmDeleteUser=Should the user be deleted?
adminUserSettings.usernameInfo=Потребителското име може да съдържа само букви, цифри и следните специални символи @._+- или трябва да е валиден имейл адрес. adminUserSettings.usernameInfo=Потребителското име може да съдържа само букви, цифри и следните специални символи @._+- или трябва да е валиден имейл адрес.
adminUserSettings.roles=Роли adminUserSettings.roles=Роли
adminUserSettings.role=Роля adminUserSettings.role=Роля
@ -799,6 +803,7 @@ merge.title=Обединяване
merge.header=Обединяване на множество PDF файлове (2+) merge.header=Обединяване на множество PDF файлове (2+)
merge.sortByName=Сортиране по име merge.sortByName=Сортиране по име
merge.sortByDate=Сортиране по дата merge.sortByDate=Сортиране по дата
merge.removeCertSign=Remove digital signature in the merged file?
merge.submit=Обединяване merge.submit=Обединяване

View File

@ -55,6 +55,7 @@ userNotFoundMessage=User not found.
incorrectPasswordMessage=Current password is incorrect. incorrectPasswordMessage=Current password is incorrect.
usernameExistsMessage=New Username already exists. 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. 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. deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted. deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=No es pot reduir la funció de l'usuari actual downgradeCurrentUserMessage=No es pot reduir la funció de l'usuari actual
@ -85,6 +86,7 @@ pipeline.defaultOption=Custom
pipeline.submitButton=Submit pipeline.submitButton=Submit
pipeline.help=Pipeline Help pipeline.help=Pipeline Help
pipeline.scanHelp=Folder Scanning Help pipeline.scanHelp=Folder Scanning Help
pipeline.deletePrompt=Are you sure you want to delete pipeline
###################### ######################
# Pipeline Options # # Pipeline Options #
@ -173,6 +175,8 @@ adminUserSettings.header=Usuari Admin Opcions Control
adminUserSettings.admin=Admin adminUserSettings.admin=Admin
adminUserSettings.user=Usuari adminUserSettings.user=Usuari
adminUserSettings.addUser=Afegir 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.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Rols adminUserSettings.roles=Rols
adminUserSettings.role=Rol adminUserSettings.role=Rol
@ -799,6 +803,7 @@ merge.title=Fusiona
merge.header=Fusiona múltiples PDFs (2+) merge.header=Fusiona múltiples PDFs (2+)
merge.sortByName=Sort by name merge.sortByName=Sort by name
merge.sortByDate=Sort by date merge.sortByDate=Sort by date
merge.removeCertSign=Remove digital signature in the merged file?
merge.submit=Fusiona merge.submit=Fusiona

View File

@ -1,7 +1,7 @@
########### ###########
# Generic # # 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 language.direction=ltr
pdfPrompt=Vyberte PDF soubory pdfPrompt=Vyberte PDF soubory
@ -55,6 +55,7 @@ userNotFoundMessage=Uživatel nenalezen.
incorrectPasswordMessage=Současné heslo není správné. incorrectPasswordMessage=Současné heslo není správné.
usernameExistsMessage=Nové uživatelské jméno již existuje. 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. 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. deleteCurrentUserMessage=Nelze smazat aktuální přihlášeného uživatele.
deleteUsernameExistsMessage=Uživatelské jméno neexistuje a nelze ho smazat. deleteUsernameExistsMessage=Uživatelské jméno neexistuje a nelze ho smazat.
downgradeCurrentUserMessage=Nelze snížit roli aktuálního uživatele. downgradeCurrentUserMessage=Nelze snížit roli aktuálního uživatele.
@ -85,6 +86,7 @@ pipeline.defaultOption=Vlastní
pipeline.submitButton=Odeslat pipeline.submitButton=Odeslat
pipeline.help=Pomoc s pipeline pipeline.help=Pomoc s pipeline
pipeline.scanHelp=Pomoc se skenováním adresáře pipeline.scanHelp=Pomoc se skenováním adresáře
pipeline.deletePrompt=Are you sure you want to delete pipeline
###################### ######################
# Pipeline Options # # Pipeline Options #
@ -173,6 +175,8 @@ adminUserSettings.header=Admin User Control Settings
adminUserSettings.admin=Admin adminUserSettings.admin=Admin
adminUserSettings.user=Uživatel adminUserSettings.user=Uživatel
adminUserSettings.addUser=Přidat Nového Uživatele 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.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.roles=Role
adminUserSettings.role=Role adminUserSettings.role=Role
@ -190,7 +194,7 @@ adminUserSettings.authenticated=Ověřeno
############# #############
# HOME-PAGE # # 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... home.searchBar=Hledej funkce...
@ -799,6 +803,7 @@ merge.title=Sloučit
merge.header=Sloučit více PDF (2+) merge.header=Sloučit více PDF (2+)
merge.sortByName=Seřadit podle názvu merge.sortByName=Seřadit podle názvu
merge.sortByDate=Seřadit podle data merge.sortByDate=Seřadit podle data
merge.removeCertSign=Remove digital signature in the merged file?
merge.submit=Sloučit merge.submit=Sloučit

View File

@ -55,6 +55,7 @@ userNotFoundMessage=Benutzer nicht gefunden.
incorrectPasswordMessage=Das Passwort ist falsch. incorrectPasswordMessage=Das Passwort ist falsch.
usernameExistsMessage=Neuer Benutzername existiert bereits. 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. 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. deleteCurrentUserMessage=Der aktuell angemeldete Benutzer kann nicht gelöscht werden.
deleteUsernameExistsMessage=Der Benutzername existiert nicht und 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 downgradeCurrentUserMessage=Die Rolle des aktuellen Benutzers kann nicht herabgestuft werden
@ -85,6 +86,7 @@ pipeline.defaultOption=Benutzerdefiniert
pipeline.submitButton=Speichern pipeline.submitButton=Speichern
pipeline.help=Hilfe für Pipeline pipeline.help=Hilfe für Pipeline
pipeline.scanHelp=Hilfe zum Ordnerscan pipeline.scanHelp=Hilfe zum Ordnerscan
pipeline.deletePrompt=Are you sure you want to delete pipeline
###################### ######################
# Pipeline Options # # Pipeline Options #
@ -173,6 +175,8 @@ adminUserSettings.header=Administrator-Benutzerkontrolle
adminUserSettings.admin=Administrator adminUserSettings.admin=Administrator
adminUserSettings.user=Benutzer adminUserSettings.user=Benutzer
adminUserSettings.addUser=Neuen Benutzer hinzufügen 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.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.roles=Rollen
adminUserSettings.role=Rolle adminUserSettings.role=Rolle
@ -332,9 +336,9 @@ home.certSign.title=Mit Zertifikat signieren
home.certSign.desc=Ein PDF mit einem Zertifikat/Schlüssel (PEM/P12) signieren home.certSign.desc=Ein PDF mit einem Zertifikat/Schlüssel (PEM/P12) signieren
certSign.tags=authentifizieren,pem,p12,offiziell,verschlüsseln certSign.tags=authentifizieren,pem,p12,offiziell,verschlüsseln
home.removeCertSign.title=Remove Certificate Sign home.removeCertSign.title=Zertifikatsignatur entfernen
home.removeCertSign.desc=Remove certificate signature from PDF home.removeCertSign.desc=Zertifikatsignatur aus PDF entfernen
removeCertSign.tags=authenticate,PEM,P12,official,decrypt removeCertSign.tags=authentifizieren,PEM,P12,offiziell,entschlüsseln,decrypt
home.pageLayout.title=Mehrseitiges Layout home.pageLayout.title=Mehrseitiges Layout
home.pageLayout.desc=Mehrere Seiten eines PDF zu einer Seite zusammenführen home.pageLayout.desc=Mehrere Seiten eines PDF zu einer Seite zusammenführen
@ -799,6 +803,7 @@ merge.title=Zusammenführen
merge.header=Mehrere PDFs zusammenführen (2+) merge.header=Mehrere PDFs zusammenführen (2+)
merge.sortByName=Nach Namen sortieren merge.sortByName=Nach Namen sortieren
merge.sortByDate=Nach Datum sortieren merge.sortByDate=Nach Datum sortieren
merge.removeCertSign=Digitale Signatur in der zusammengeführten Datei entfernen?
merge.submit=Zusammenführen merge.submit=Zusammenführen

View File

@ -55,6 +55,7 @@ userNotFoundMessage=Ο χρήστης δεν βρέθηκε.
incorrectPasswordMessage=Ο τρέχων κωδικός πρόσβασης είναι λανθασμένος. incorrectPasswordMessage=Ο τρέχων κωδικός πρόσβασης είναι λανθασμένος.
usernameExistsMessage=Το νέο όνομα χρήστη υπάρχει ήδη. usernameExistsMessage=Το νέο όνομα χρήστη υπάρχει ήδη.
invalidUsernameMessage=Μη έγκυρο όνομα χρήστη, όνομα χρήστη μπορεί να περιέχει μόνο γράμματα, αριθμούς και τους ακόλουθους ειδικούς χαρακτήρες @._+- ή πρέπει να είναι έγκυρη διεύθυνση email. invalidUsernameMessage=Μη έγκυρο όνομα χρήστη, όνομα χρήστη μπορεί να περιέχει μόνο γράμματα, αριθμούς και τους ακόλουθους ειδικούς χαρακτήρες @._+- ή πρέπει να είναι έγκυρη διεύθυνση email.
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
deleteCurrentUserMessage=Δεν είναι δυνατή η διαγραφή του τρέχοντος συνδεδεμένου χρήστη. deleteCurrentUserMessage=Δεν είναι δυνατή η διαγραφή του τρέχοντος συνδεδεμένου χρήστη.
deleteUsernameExistsMessage=Το όνομα χρήστη δεν υπάρχει και δεν μπορεί να διαγραφεί. deleteUsernameExistsMessage=Το όνομα χρήστη δεν υπάρχει και δεν μπορεί να διαγραφεί.
downgradeCurrentUserMessage=Δεν είναι δυνατή η υποβάθμιση του ρόλου του τρέχοντος χρήστη downgradeCurrentUserMessage=Δεν είναι δυνατή η υποβάθμιση του ρόλου του τρέχοντος χρήστη
@ -85,6 +86,7 @@ pipeline.defaultOption=Custom
pipeline.submitButton=Υποβολή pipeline.submitButton=Υποβολή
pipeline.help=Βοήθεια για το Pipeline pipeline.help=Βοήθεια για το Pipeline
pipeline.scanHelp=Βοήθεια για Σάρωση Φακέλων pipeline.scanHelp=Βοήθεια για Σάρωση Φακέλων
pipeline.deletePrompt=Are you sure you want to delete pipeline
###################### ######################
# Pipeline Options # # Pipeline Options #
@ -173,6 +175,8 @@ adminUserSettings.header=Ρυθμίσεις ελέγχου Διαχειριστ
adminUserSettings.admin=Διαχειριστής adminUserSettings.admin=Διαχειριστής
adminUserSettings.user=Χρήστης adminUserSettings.user=Χρήστης
adminUserSettings.addUser=Προσθήκη νέου Χρήστη 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.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Ρόλοι adminUserSettings.roles=Ρόλοι
adminUserSettings.role=Ρόλος adminUserSettings.role=Ρόλος
@ -799,6 +803,7 @@ merge.title=Συγχώνευση
merge.header=Συγχώνευση πολλαπλών PDFs (2+) merge.header=Συγχώνευση πολλαπλών PDFs (2+)
merge.sortByName=Ταξινόμηση με βάση το Όνομα merge.sortByName=Ταξινόμηση με βάση το Όνομα
merge.sortByDate=Ταξινόμηση με βάση την Ημερομηνία merge.sortByDate=Ταξινόμηση με βάση την Ημερομηνία
merge.removeCertSign=Remove digital signature in the merged file?
merge.submit=Συγχώνευση merge.submit=Συγχώνευση

View File

@ -55,6 +55,7 @@ userNotFoundMessage=User not found.
incorrectPasswordMessage=Current password is incorrect. incorrectPasswordMessage=Current password is incorrect.
usernameExistsMessage=New Username already exists. 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. 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. deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted. deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=Cannot downgrade current user's role downgradeCurrentUserMessage=Cannot downgrade current user's role
@ -85,6 +86,7 @@ pipeline.defaultOption=Custom
pipeline.submitButton=Submit pipeline.submitButton=Submit
pipeline.help=Pipeline Help pipeline.help=Pipeline Help
pipeline.scanHelp=Folder Scanning Help pipeline.scanHelp=Folder Scanning Help
pipeline.deletePrompt=Are you sure you want to delete pipeline
###################### ######################
# Pipeline Options # # Pipeline Options #
@ -173,6 +175,8 @@ adminUserSettings.header=Admin User Control Settings
adminUserSettings.admin=Admin adminUserSettings.admin=Admin
adminUserSettings.user=User adminUserSettings.user=User
adminUserSettings.addUser=Add New 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.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Roles adminUserSettings.roles=Roles
adminUserSettings.role=Role adminUserSettings.role=Role
@ -799,6 +803,7 @@ merge.title=Merge
merge.header=Merge multiple PDFs (2+) merge.header=Merge multiple PDFs (2+)
merge.sortByName=Sort by name merge.sortByName=Sort by name
merge.sortByDate=Sort by date merge.sortByDate=Sort by date
merge.removeCertSign=Remove digital signature in the merged file?
merge.submit=Merge merge.submit=Merge

View File

@ -55,6 +55,7 @@ userNotFoundMessage=User not found.
incorrectPasswordMessage=Current password is incorrect. incorrectPasswordMessage=Current password is incorrect.
usernameExistsMessage=New Username already exists. 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. 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. deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted. deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=Cannot downgrade current user's role downgradeCurrentUserMessage=Cannot downgrade current user's role
@ -85,6 +86,7 @@ pipeline.defaultOption=Custom
pipeline.submitButton=Submit pipeline.submitButton=Submit
pipeline.help=Pipeline Help pipeline.help=Pipeline Help
pipeline.scanHelp=Folder Scanning Help pipeline.scanHelp=Folder Scanning Help
pipeline.deletePrompt=Are you sure you want to delete pipeline
###################### ######################
# Pipeline Options # # Pipeline Options #
@ -173,6 +175,8 @@ adminUserSettings.header=Admin User Control Settings
adminUserSettings.admin=Admin adminUserSettings.admin=Admin
adminUserSettings.user=User adminUserSettings.user=User
adminUserSettings.addUser=Add New 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.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Roles adminUserSettings.roles=Roles
adminUserSettings.role=Role adminUserSettings.role=Role
@ -799,6 +803,7 @@ merge.title=Merge
merge.header=Merge multiple PDFs (2+) merge.header=Merge multiple PDFs (2+)
merge.sortByName=Sort by name merge.sortByName=Sort by name
merge.sortByDate=Sort by date merge.sortByDate=Sort by date
merge.removeCertSign=Remove digital signature in the merged file?
merge.submit=Merge merge.submit=Merge

View File

@ -55,6 +55,7 @@ userNotFoundMessage=Usuario no encontrado.
incorrectPasswordMessage=La contraseña actual no es correcta. incorrectPasswordMessage=La contraseña actual no es correcta.
usernameExistsMessage=El nuevo nombre de usuario está en uso. 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. 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. deleteCurrentUserMessage=No puede eliminar el usuario que tiene la sesión actualmente en uso.
deleteUsernameExistsMessage=El usuario no existe y no puede eliminarse. deleteUsernameExistsMessage=El usuario no existe y no puede eliminarse.
downgradeCurrentUserMessage=No se puede degradar el rol del usuario actual downgradeCurrentUserMessage=No se puede degradar el rol del usuario actual
@ -85,6 +86,7 @@ pipeline.defaultOption=Personalizar
pipeline.submitButton=Enviar pipeline.submitButton=Enviar
pipeline.help=Ayuda de Canalización pipeline.help=Ayuda de Canalización
pipeline.scanHelp=Ayuda de escaneado de carpetas pipeline.scanHelp=Ayuda de escaneado de carpetas
pipeline.deletePrompt=Are you sure you want to delete pipeline
###################### ######################
# Pipeline Options # # Pipeline Options #
@ -173,6 +175,8 @@ adminUserSettings.header=Configuración de control de usuario administrador
adminUserSettings.admin=Administrador adminUserSettings.admin=Administrador
adminUserSettings.user=Usuario adminUserSettings.user=Usuario
adminUserSettings.addUser=Añadir Nuevo 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.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.roles=Roles
adminUserSettings.role=Rol adminUserSettings.role=Rol
@ -799,6 +803,7 @@ merge.title=Unir
merge.header=Unir múltiples PDFs (2+) merge.header=Unir múltiples PDFs (2+)
merge.sortByName=Ordenar por nombre merge.sortByName=Ordenar por nombre
merge.sortByDate=Ordenar por fecha merge.sortByDate=Ordenar por fecha
merge.removeCertSign=Remove digital signature in the merged file?
merge.submit=Unir merge.submit=Unir

View File

@ -55,6 +55,7 @@ userNotFoundMessage=User not found.
incorrectPasswordMessage=Current password is incorrect. incorrectPasswordMessage=Current password is incorrect.
usernameExistsMessage=New Username already exists. 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. 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. deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted. deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=Ezin da uneko erabiltzailearen rola jaitsi downgradeCurrentUserMessage=Ezin da uneko erabiltzailearen rola jaitsi
@ -85,6 +86,7 @@ pipeline.defaultOption=Custom
pipeline.submitButton=Submit pipeline.submitButton=Submit
pipeline.help=Pipeline Help pipeline.help=Pipeline Help
pipeline.scanHelp=Folder Scanning Help pipeline.scanHelp=Folder Scanning Help
pipeline.deletePrompt=Are you sure you want to delete pipeline
###################### ######################
# Pipeline Options # # Pipeline Options #
@ -173,6 +175,8 @@ adminUserSettings.header=Admin Erabiltzailearen Ezarpenen Kontrolak
adminUserSettings.admin=Admin adminUserSettings.admin=Admin
adminUserSettings.user=Erabiltzaile adminUserSettings.user=Erabiltzaile
adminUserSettings.addUser=Erabiltzaile berria 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.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Rolak adminUserSettings.roles=Rolak
adminUserSettings.role=Rol adminUserSettings.role=Rol
@ -799,6 +803,7 @@ merge.title=Elkartu
merge.header=Elkartu zenbait PDF (2+) merge.header=Elkartu zenbait PDF (2+)
merge.sortByName=Sort by nameOrdenatu izenaren arabera merge.sortByName=Sort by nameOrdenatu izenaren arabera
merge.sortByDate=Ordenatu dataren arabera merge.sortByDate=Ordenatu dataren arabera
merge.removeCertSign=Remove digital signature in the merged file?
merge.submit=Elkartu merge.submit=Elkartu

View File

@ -55,6 +55,7 @@ userNotFoundMessage=Utilisateur non trouvé.
incorrectPasswordMessage=Le mot de passe actuel est incorrect. incorrectPasswordMessage=Le mot de passe actuel est incorrect.
usernameExistsMessage=Le nouveau nom dutilisateur existe déjà. 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. 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é. deleteCurrentUserMessage=Impossible de supprimer lutilisateur actuellement connecté.
deleteUsernameExistsMessage=Le nom dutilisateur nexiste pas et ne peut pas être supprimé. deleteUsernameExistsMessage=Le nom dutilisateur nexiste pas et ne peut pas être supprimé.
downgradeCurrentUserMessage=Impossible de rétrograder le rôle de l'utilisateur actuel. downgradeCurrentUserMessage=Impossible de rétrograder le rôle de l'utilisateur actuel.
@ -85,6 +86,7 @@ pipeline.defaultOption=Personnaliser
pipeline.submitButton=Soumettre pipeline.submitButton=Soumettre
pipeline.help=Aide Pipeline pipeline.help=Aide Pipeline
pipeline.scanHelp=Aide analyse de dossier pipeline.scanHelp=Aide analyse de dossier
pipeline.deletePrompt=Are you sure you want to delete pipeline
###################### ######################
# Pipeline Options # # Pipeline Options #
@ -173,6 +175,8 @@ adminUserSettings.header=Administration des paramètres des utilisateurs
adminUserSettings.admin=Administateur adminUserSettings.admin=Administateur
adminUserSettings.user=Utilisateur adminUserSettings.user=Utilisateur
adminUserSettings.addUser=Ajouter un 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.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.roles=Rôles
adminUserSettings.role=Rôle adminUserSettings.role=Rôle
@ -456,12 +460,12 @@ login.locked=Votre compte a été verrouillé.
login.signinTitle=Veuillez vous connecter login.signinTitle=Veuillez vous connecter
login.ssoSignIn=Se connecter via l'authentification unique login.ssoSignIn=Se connecter via l'authentification unique
login.oauth2AutoCreateDisabled=OAUTH2 Création automatique d'utilisateur désactivée login.oauth2AutoCreateDisabled=OAUTH2 Création automatique d'utilisateur désactivée
login.oauth2RequestNotFound=Authorization request not found login.oauth2RequestNotFound=Demande d'autorisation introuvable
login.oauth2InvalidUserInfoResponse=Invalid User Info Response login.oauth2InvalidUserInfoResponse=Réponse contenant les informations de l'utilisateur est invalide
login.oauth2invalidRequest=Invalid Request login.oauth2invalidRequest=Requête invalide
login.oauth2AccessDenied=Access Denied login.oauth2AccessDenied=Accès refusé
login.oauth2InvalidTokenResponse=Invalid Token Response login.oauth2InvalidTokenResponse=Réponse contenant le jeton est invalide
login.oauth2InvalidIdToken=Invalid Id Token login.oauth2InvalidIdToken=Jeton d'identification invalide
#auto-redact #auto-redact
@ -690,14 +694,14 @@ compare.document.2=Document 2
compare.submit=Comparer compare.submit=Comparer
#BookToPDF #BookToPDF
BookToPDF.title=Books and Comics to PDF BookToPDF.title=Livres et BD vers PDF
BookToPDF.header=Book to PDF BookToPDF.header=Livre vers PDF
BookToPDF.credit=Utiliser Calibre BookToPDF.credit=Utiliser Calibre
BookToPDF.submit=Convertir BookToPDF.submit=Convertir
#PDFToBook #PDFToBook
PDFToBook.title=PDF to Book PDFToBook.title=PDF vers Livre
PDFToBook.header=PDF to Book PDFToBook.header=PDF vers Livre
PDFToBook.selectText.1=Format PDFToBook.selectText.1=Format
PDFToBook.credit=Utiliser Calibre PDFToBook.credit=Utiliser Calibre
PDFToBook.submit=Convertir PDFToBook.submit=Convertir
@ -799,6 +803,7 @@ merge.title=Fusionner
merge.header=Fusionner plusieurs PDF merge.header=Fusionner plusieurs PDF
merge.sortByName=Trier par nom merge.sortByName=Trier par nom
merge.sortByDate=Trier par date merge.sortByDate=Trier par date
merge.removeCertSign=Remove digital signature in the merged file?
merge.submit=Fusionner merge.submit=Fusionner

View File

@ -55,6 +55,7 @@ userNotFoundMessage=उपयोगकर्ता नहीं मिला।
incorrectPasswordMessage=वर्तमान पासवर्ड गलत है। incorrectPasswordMessage=वर्तमान पासवर्ड गलत है।
usernameExistsMessage=नया उपयोगकर्ता नाम पहले से मौजूद है। usernameExistsMessage=नया उपयोगकर्ता नाम पहले से मौजूद है।
invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address. 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. deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted. deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=मौजूदा यूज़र की भूमिका को डाउनग्रेड नहीं किया जा सकता downgradeCurrentUserMessage=मौजूदा यूज़र की भूमिका को डाउनग्रेड नहीं किया जा सकता
@ -85,6 +86,7 @@ pipeline.defaultOption=Custom
pipeline.submitButton=Submit pipeline.submitButton=Submit
pipeline.help=Pipeline Help pipeline.help=Pipeline Help
pipeline.scanHelp=Folder Scanning Help pipeline.scanHelp=Folder Scanning Help
pipeline.deletePrompt=Are you sure you want to delete pipeline
###################### ######################
# Pipeline Options # # Pipeline Options #
@ -173,6 +175,8 @@ adminUserSettings.header=व्यवस्थापक उपयोगकर्
adminUserSettings.admin=व्यवस्थापक adminUserSettings.admin=व्यवस्थापक
adminUserSettings.user=उपयोगकर्ता adminUserSettings.user=उपयोगकर्ता
adminUserSettings.addUser=नया उपयोगकर्ता जोड़ें 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.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=रोल्स adminUserSettings.roles=रोल्स
adminUserSettings.role=रोल adminUserSettings.role=रोल
@ -799,6 +803,7 @@ merge.title=मर्ज
merge.header=एक से अधिक PDF एक साथ मर्ज करें (2+) merge.header=एक से अधिक PDF एक साथ मर्ज करें (2+)
merge.sortByName=नाम से क्रमबद्ध करें merge.sortByName=नाम से क्रमबद्ध करें
merge.sortByDate=तारीख से क्रमबद्ध करें merge.sortByDate=तारीख से क्रमबद्ध करें
merge.removeCertSign=Remove digital signature in the merged file?
merge.submit=मर्ज करें merge.submit=मर्ज करें

View File

@ -1,7 +1,7 @@
########### ###########
# Generic # # 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 language.direction=ltr
pdfPrompt=Odaberi PDF(ove) pdfPrompt=Odaberi PDF(ove)
@ -55,6 +55,7 @@ userNotFoundMessage=Korisnik nije pronađen.
incorrectPasswordMessage=Kriva zaporka. incorrectPasswordMessage=Kriva zaporka.
usernameExistsMessage=Korisničko ime već postoji usernameExistsMessage=Korisničko ime već postoji
invalidUsernameMessage=Nevažeće korisničko ime, korisničko ime može sadržavati samo slova, brojke i sljedeće posebne znakove @._+- ili mora biti važeća adresa e-pošte. invalidUsernameMessage=Nevažeće korisničko ime, korisničko ime može sadržavati samo slova, brojke i sljedeće posebne znakove @._+- ili mora biti važeća adresa e-pošte.
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
deleteCurrentUserMessage=Nije moguće izbrisati trenutno prijavljenog korisnika. deleteCurrentUserMessage=Nije moguće izbrisati trenutno prijavljenog korisnika.
deleteUsernameExistsMessage=Korisničko ime ne postoji i ne može se izbrisati. deleteUsernameExistsMessage=Korisničko ime ne postoji i ne može se izbrisati.
downgradeCurrentUserMessage=Nije moguće vratiti unazad ulogu trenutnog korisnika downgradeCurrentUserMessage=Nije moguće vratiti unazad ulogu trenutnog korisnika
@ -85,6 +86,7 @@ pipeline.defaultOption=Prilagođeno
pipeline.submitButton=Pošalji pipeline.submitButton=Pošalji
pipeline.help=Pipeline Pomoć pipeline.help=Pipeline Pomoć
pipeline.scanHelp=Pomoć za skeniranje mapa pipeline.scanHelp=Pomoć za skeniranje mapa
pipeline.deletePrompt=Are you sure you want to delete pipeline
###################### ######################
# Pipeline Options # # Pipeline Options #
@ -173,6 +175,8 @@ adminUserSettings.header=Postavka kontrole korisnika za administratora
adminUserSettings.admin=Administrator adminUserSettings.admin=Administrator
adminUserSettings.user=Korisnik adminUserSettings.user=Korisnik
adminUserSettings.addUser=Dodaj novog korisnika adminUserSettings.addUser=Dodaj novog korisnika
adminUserSettings.deleteUser=Delete User
adminUserSettings.confirmDeleteUser=Should the user be deleted?
adminUserSettings.usernameInfo=Korisničko ime može sadržavati samo slova, brojke i sljedeće posebne znakove @._+- ili mora biti važeća adresa e-pošte. adminUserSettings.usernameInfo=Korisničko ime može sadržavati samo slova, brojke i sljedeće posebne znakove @._+- ili mora biti važeća adresa e-pošte.
adminUserSettings.roles=Uloge adminUserSettings.roles=Uloge
adminUserSettings.role=Uloga adminUserSettings.role=Uloga
@ -799,6 +803,7 @@ merge.title=Spajanje
merge.header=Spajanje više PDF-ova (2+) merge.header=Spajanje više PDF-ova (2+)
merge.sortByName=Poredaj po imenu merge.sortByName=Poredaj po imenu
merge.sortByDate=Poredaj po datumu merge.sortByDate=Poredaj po datumu
merge.removeCertSign=Remove digital signature in the merged file?
merge.submit=Spajanje merge.submit=Spajanje

View File

@ -55,6 +55,7 @@ userNotFoundMessage=A felhasználó nem található.
incorrectPasswordMessage=A jelenlegi jelszó helytelen. incorrectPasswordMessage=A jelenlegi jelszó helytelen.
usernameExistsMessage=Az új felhasználónév már létezik. 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. 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. deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted. deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=A jelenlegi felhasználó szerepkörét nem lehet visszaminősíteni downgradeCurrentUserMessage=A jelenlegi felhasználó szerepkörét nem lehet visszaminősíteni
@ -85,6 +86,7 @@ pipeline.defaultOption=Custom
pipeline.submitButton=Submit pipeline.submitButton=Submit
pipeline.help=Pipeline Help pipeline.help=Pipeline Help
pipeline.scanHelp=Folder Scanning Help pipeline.scanHelp=Folder Scanning Help
pipeline.deletePrompt=Are you sure you want to delete pipeline
###################### ######################
# Pipeline Options # # Pipeline Options #
@ -173,6 +175,8 @@ adminUserSettings.header=Adminisztrátori Felhasználói Vezérlési Beállítá
adminUserSettings.admin=Adminisztrátor adminUserSettings.admin=Adminisztrátor
adminUserSettings.user=Felhasználó adminUserSettings.user=Felhasználó
adminUserSettings.addUser=Új felhasználó hozzáadása 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.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Szerepek adminUserSettings.roles=Szerepek
adminUserSettings.role=Szerep adminUserSettings.role=Szerep
@ -799,6 +803,7 @@ merge.title=Összevonás
merge.header=Több PDF összevonása (2+) merge.header=Több PDF összevonása (2+)
merge.sortByName=Név szerinti rendezés merge.sortByName=Név szerinti rendezés
merge.sortByDate=Dátum szerinti rendezés merge.sortByDate=Dátum szerinti rendezés
merge.removeCertSign=Remove digital signature in the merged file?
merge.submit=Összevonás merge.submit=Összevonás

View File

@ -55,6 +55,7 @@ userNotFoundMessage=Pengguna tidak ditemukan.
incorrectPasswordMessage=Kata sandi saat ini salah. incorrectPasswordMessage=Kata sandi saat ini salah.
usernameExistsMessage=Nama pengguna baru sudah ada. 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. 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. deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted. deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=Tidak dapat menurunkan peran pengguna saat ini downgradeCurrentUserMessage=Tidak dapat menurunkan peran pengguna saat ini
@ -85,6 +86,7 @@ pipeline.defaultOption=Custom
pipeline.submitButton=Submit pipeline.submitButton=Submit
pipeline.help=Pipeline Help pipeline.help=Pipeline Help
pipeline.scanHelp=Folder Scanning Help pipeline.scanHelp=Folder Scanning Help
pipeline.deletePrompt=Are you sure you want to delete pipeline
###################### ######################
# Pipeline Options # # Pipeline Options #
@ -173,6 +175,8 @@ adminUserSettings.header=Pengaturan Kontrol Admin
adminUserSettings.admin=Admin adminUserSettings.admin=Admin
adminUserSettings.user=Pengguna adminUserSettings.user=Pengguna
adminUserSettings.addUser=Tambahkan Pengguna Baru 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.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Peran adminUserSettings.roles=Peran
adminUserSettings.role=Peran adminUserSettings.role=Peran
@ -799,6 +803,7 @@ merge.title=Gabungkan
merge.header=Gabungkan beberapa PDFs (2+) merge.header=Gabungkan beberapa PDFs (2+)
merge.sortByName=Sortir berdasarkan nama merge.sortByName=Sortir berdasarkan nama
merge.sortByDate=Sortir berdasrkan tanggal merge.sortByDate=Sortir berdasrkan tanggal
merge.removeCertSign=Remove digital signature in the merged file?
merge.submit=Gabungkan merge.submit=Gabungkan

View File

@ -55,6 +55,7 @@ userNotFoundMessage=Utente non trovato.
incorrectPasswordMessage=La password attuale non è corretta. incorrectPasswordMessage=La password attuale non è corretta.
usernameExistsMessage=Il nuovo nome utente esiste già. usernameExistsMessage=Il nuovo nome utente esiste già.
invalidUsernameMessage=Nome utente non valido, il nome utente può contenere solo lettere, numeri e i seguenti caratteri speciali @._+- o deve essere un indirizzo email valido. invalidUsernameMessage=Nome utente non valido, il nome utente può contenere solo lettere, numeri e i seguenti caratteri speciali @._+- o deve essere un indirizzo email valido.
confirmPasswordErrorMessage=La nuova password e la conferma della nuova password devono corrispondere.
deleteCurrentUserMessage=Impossibile eliminare l'utente attualmente connesso. deleteCurrentUserMessage=Impossibile eliminare l'utente attualmente connesso.
deleteUsernameExistsMessage=Il nome utente non esiste e non può essere eliminato. deleteUsernameExistsMessage=Il nome utente non esiste e non può essere eliminato.
downgradeCurrentUserMessage=Impossibile declassare il ruolo dell'utente corrente downgradeCurrentUserMessage=Impossibile declassare il ruolo dell'utente corrente
@ -85,6 +86,7 @@ pipeline.defaultOption=Personalizzato
pipeline.submitButton=Invia pipeline.submitButton=Invia
pipeline.help=Aiuto sulla pipeline pipeline.help=Aiuto sulla pipeline
pipeline.scanHelp=Aiuto per la scansione delle cartelle pipeline.scanHelp=Aiuto per la scansione delle cartelle
pipeline.deletePrompt=Are you sure you want to delete pipeline
###################### ######################
# Pipeline Options # # Pipeline Options #
@ -173,6 +175,8 @@ adminUserSettings.header=Impostazioni di controllo utente amministratore
adminUserSettings.admin=Amministratore adminUserSettings.admin=Amministratore
adminUserSettings.user=Utente adminUserSettings.user=Utente
adminUserSettings.addUser=Aggiungi un nuovo Utente adminUserSettings.addUser=Aggiungi un nuovo Utente
adminUserSettings.deleteUser=Elimina utente
adminUserSettings.confirmDeleteUser=L'utente deve essere eliminato?
adminUserSettings.usernameInfo=Il nome utente può contenere solo lettere, numeri e i seguenti caratteri speciali @._+- oppure deve essere un indirizzo email valido. adminUserSettings.usernameInfo=Il nome utente può contenere solo lettere, numeri e i seguenti caratteri speciali @._+- oppure deve essere un indirizzo email valido.
adminUserSettings.roles=Ruoli adminUserSettings.roles=Ruoli
adminUserSettings.role=Ruolo adminUserSettings.role=Ruolo
@ -332,9 +336,9 @@ home.certSign.title=Firma con certificato
home.certSign.desc=Firma un PDF con un certificato/chiave (PEM/P12) home.certSign.desc=Firma un PDF con un certificato/chiave (PEM/P12)
certSign.tags=autenticare,PEM,P12,ufficiale,crittografare certSign.tags=autenticare,PEM,P12,ufficiale,crittografare
home.removeCertSign.title=Remove Certificate Sign home.removeCertSign.title=Rimuovere firma dal certificato
home.removeCertSign.desc=Remove certificate signature from PDF home.removeCertSign.desc=Rimuovi la firma del certificato dal PDF
removeCertSign.tags=authenticate,PEM,P12,official,decrypt removeCertSign.tags=autenticare,PEM,P12,ufficiale,decifrare
home.pageLayout.title=Layout multipagina home.pageLayout.title=Layout multipagina
home.pageLayout.desc=Unisci più pagine di un documento PDF in un'unica pagina home.pageLayout.desc=Unisci più pagine di un documento PDF in un'unica pagina
@ -799,6 +803,7 @@ merge.title=Unisci
merge.header=Unisci 2 o più PDF merge.header=Unisci 2 o più PDF
merge.sortByName=Ordina per nome merge.sortByName=Ordina per nome
merge.sortByDate=Ordina per data merge.sortByDate=Ordina per data
merge.removeCertSign=Remove digital signature in the merged file?
merge.submit=Unisci merge.submit=Unisci
@ -976,7 +981,7 @@ pdfToPDFA.credit=Questo servizio utilizza OCRmyPDF per la conversione in PDF/A.
pdfToPDFA.submit=Converti pdfToPDFA.submit=Converti
pdfToPDFA.tip=Attualmente non funziona per più input contemporaneamente pdfToPDFA.tip=Attualmente non funziona per più input contemporaneamente
pdfToPDFA.outputFormat=Formato di output pdfToPDFA.outputFormat=Formato di output
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step. pdfToPDFA.pdfWithDigitalSignature=Il PDF contiene una firma digitale. Questo verrà rimosso nel passaggio successivo.
#PDFToWord #PDFToWord

View File

@ -55,6 +55,7 @@ userNotFoundMessage=ユーザーが見つかりません。
incorrectPasswordMessage=現在のパスワードが正しくありません。 incorrectPasswordMessage=現在のパスワードが正しくありません。
usernameExistsMessage=新しいユーザー名はすでに存在します。 usernameExistsMessage=新しいユーザー名はすでに存在します。
invalidUsernameMessage=ユーザー名が無効です。ユーザー名には文字、数字、およびそれに続く特殊文字 @._+- のみを含めることができます。または、有効な電子メール アドレスである必要があります。 invalidUsernameMessage=ユーザー名が無効です。ユーザー名には文字、数字、およびそれに続く特殊文字 @._+- のみを含めることができます。または、有効な電子メール アドレスである必要があります。
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
deleteCurrentUserMessage=現在ログインしているユーザーは削除できません。 deleteCurrentUserMessage=現在ログインしているユーザーは削除できません。
deleteUsernameExistsMessage=そのユーザー名は存在しないため削除できません。 deleteUsernameExistsMessage=そのユーザー名は存在しないため削除できません。
downgradeCurrentUserMessage=現在のユーザーの役割をダウングレードできません downgradeCurrentUserMessage=現在のユーザーの役割をダウングレードできません
@ -85,6 +86,7 @@ pipeline.defaultOption=カスタム
pipeline.submitButton=送信 pipeline.submitButton=送信
pipeline.help=パイプラインのヘルプ pipeline.help=パイプラインのヘルプ
pipeline.scanHelp=フォルダ スキャンのヘルプ pipeline.scanHelp=フォルダ スキャンのヘルプ
pipeline.deletePrompt=Are you sure you want to delete pipeline
###################### ######################
# Pipeline Options # # Pipeline Options #
@ -173,6 +175,8 @@ adminUserSettings.header=管理者ユーザー制御設定
adminUserSettings.admin=管理者 adminUserSettings.admin=管理者
adminUserSettings.user=ユーザー adminUserSettings.user=ユーザー
adminUserSettings.addUser=新しいユーザを追加 adminUserSettings.addUser=新しいユーザを追加
adminUserSettings.deleteUser=Delete User
adminUserSettings.confirmDeleteUser=Should the user be deleted?
adminUserSettings.usernameInfo=ユーザー名には、文字、数字、および次の特殊文字 @._+- のみを含めることができます。または、有効な電子メール アドレスである必要があります。 adminUserSettings.usernameInfo=ユーザー名には、文字、数字、および次の特殊文字 @._+- のみを含めることができます。または、有効な電子メール アドレスである必要があります。
adminUserSettings.roles=役割 adminUserSettings.roles=役割
adminUserSettings.role=役割 adminUserSettings.role=役割
@ -799,6 +803,7 @@ merge.title=結合
merge.header=複数のPDFを結合 (2ファイル以上) merge.header=複数のPDFを結合 (2ファイル以上)
merge.sortByName=名前で並べ替え merge.sortByName=名前で並べ替え
merge.sortByDate=日付で並べ替え merge.sortByDate=日付で並べ替え
merge.removeCertSign=Remove digital signature in the merged file?
merge.submit=結合 merge.submit=結合

View File

@ -55,6 +55,7 @@ userNotFoundMessage=사용자를 찾을 수 없습니다.
incorrectPasswordMessage=현재 비밀번호가 틀립니다. incorrectPasswordMessage=현재 비밀번호가 틀립니다.
usernameExistsMessage=새 사용자명이 이미 존재합니다. usernameExistsMessage=새 사용자명이 이미 존재합니다.
invalidUsernameMessage=잘못된 사용자 이름입니다. 사용자 이름에는 문자, 숫자 및 다음 특수 문자(@._+-)만 포함할 수 있거나 유효한 이메일 주소여야 합니다. invalidUsernameMessage=잘못된 사용자 이름입니다. 사용자 이름에는 문자, 숫자 및 다음 특수 문자(@._+-)만 포함할 수 있거나 유효한 이메일 주소여야 합니다.
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
deleteCurrentUserMessage=현재 로그인한 사용자를 삭제할 수 없습니다. deleteCurrentUserMessage=현재 로그인한 사용자를 삭제할 수 없습니다.
deleteUsernameExistsMessage=사용자 이름이 존재하지 않으며 삭제할 수 없습니다. deleteUsernameExistsMessage=사용자 이름이 존재하지 않으며 삭제할 수 없습니다.
downgradeCurrentUserMessage=현재 사용자의 역할을 다운그레이드할 수 없습니다 downgradeCurrentUserMessage=현재 사용자의 역할을 다운그레이드할 수 없습니다
@ -85,6 +86,7 @@ pipeline.defaultOption=관습
pipeline.submitButton=전송 pipeline.submitButton=전송
pipeline.help=파이프라인 도움말 pipeline.help=파이프라인 도움말
pipeline.scanHelp=폴더 스캔 도움말 pipeline.scanHelp=폴더 스캔 도움말
pipeline.deletePrompt=Are you sure you want to delete pipeline
###################### ######################
# Pipeline Options # # Pipeline Options #
@ -173,6 +175,8 @@ adminUserSettings.header=사용자 관리
adminUserSettings.admin=관리자 adminUserSettings.admin=관리자
adminUserSettings.user=사용자 adminUserSettings.user=사용자
adminUserSettings.addUser=새 사용자 추가 adminUserSettings.addUser=새 사용자 추가
adminUserSettings.deleteUser=Delete User
adminUserSettings.confirmDeleteUser=Should the user be deleted?
adminUserSettings.usernameInfo=사용자 이름은 문자, 숫자, 특수 문자 @._+-만 포함할 수 있으며 유효한 이메일 주소여야 합니다. adminUserSettings.usernameInfo=사용자 이름은 문자, 숫자, 특수 문자 @._+-만 포함할 수 있으며 유효한 이메일 주소여야 합니다.
adminUserSettings.roles=역할 adminUserSettings.roles=역할
adminUserSettings.role=역할 adminUserSettings.role=역할
@ -799,6 +803,7 @@ merge.title=병합
merge.header=여러 개의 PDF 병합 (2개 이상) merge.header=여러 개의 PDF 병합 (2개 이상)
merge.sortByName=이름순 정렬 merge.sortByName=이름순 정렬
merge.sortByDate=날짜순 정렬 merge.sortByDate=날짜순 정렬
merge.removeCertSign=Remove digital signature in the merged file?
merge.submit=병합 merge.submit=병합

View File

@ -55,6 +55,7 @@ userNotFoundMessage=Gebruiker niet gevonden.
incorrectPasswordMessage=Huidige wachtwoord is onjuist. incorrectPasswordMessage=Huidige wachtwoord is onjuist.
usernameExistsMessage=Nieuwe gebruikersnaam bestaat al. usernameExistsMessage=Nieuwe gebruikersnaam bestaat al.
invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address. invalidUsernameMessage=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. deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted. deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=Kan de rol van de huidige gebruiker niet downgraden downgradeCurrentUserMessage=Kan de rol van de huidige gebruiker niet downgraden
@ -85,6 +86,7 @@ pipeline.defaultOption=Aangepast
pipeline.submitButton=Opslaan pipeline.submitButton=Opslaan
pipeline.help=Pipeline Help pipeline.help=Pipeline Help
pipeline.scanHelp=Folder Scanning Help pipeline.scanHelp=Folder Scanning Help
pipeline.deletePrompt=Are you sure you want to delete pipeline
###################### ######################
# Pipeline Options # # Pipeline Options #
@ -173,6 +175,8 @@ adminUserSettings.header=Beheer gebruikers
adminUserSettings.admin=Beheerder adminUserSettings.admin=Beheerder
adminUserSettings.user=Gebruiker adminUserSettings.user=Gebruiker
adminUserSettings.addUser=Voeg nieuwe gebruiker toe adminUserSettings.addUser=Voeg nieuwe gebruiker toe
adminUserSettings.deleteUser=Delete User
adminUserSettings.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.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Rollen adminUserSettings.roles=Rollen
adminUserSettings.role=Rol adminUserSettings.role=Rol
@ -799,6 +803,7 @@ merge.title=Samenvoegen
merge.header=Meerdere PDF's samenvoegen (2+) merge.header=Meerdere PDF's samenvoegen (2+)
merge.sortByName=Sorteer op naam merge.sortByName=Sorteer op naam
merge.sortByDate=Sorteer op datum merge.sortByDate=Sorteer op datum
merge.removeCertSign=Remove digital signature in the merged file?
merge.submit=Samenvoegen merge.submit=Samenvoegen

View File

@ -1,7 +1,7 @@
########### ###########
# Generic # # 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 language.direction=ltr
pdfPrompt=Velg PDF(er) pdfPrompt=Velg PDF(er)
@ -55,6 +55,7 @@ userNotFoundMessage=Bruker ikke funnet.
incorrectPasswordMessage=Nåværende passord er feil. incorrectPasswordMessage=Nåværende passord er feil.
usernameExistsMessage=Det nye brukernavnet eksisterer allerede. usernameExistsMessage=Det nye brukernavnet eksisterer allerede.
invalidUsernameMessage=Ugyldig brukernavn, brukernavnet kan bare inneholde bokstaver, tall og følgende spesialtegn @._+- eller må være en gyldig e-postadresse. invalidUsernameMessage=Ugyldig brukernavn, brukernavnet kan bare inneholde bokstaver, tall og følgende spesialtegn @._+- eller må være en gyldig e-postadresse.
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
deleteCurrentUserMessage=Kan ikke slette den innloggede brukeren. deleteCurrentUserMessage=Kan ikke slette den innloggede brukeren.
deleteUsernameExistsMessage=Brukernavnet eksisterer ikke og kan ikke slettes. deleteUsernameExistsMessage=Brukernavnet eksisterer ikke og kan ikke slettes.
downgradeCurrentUserMessage=Kan ikke nedgradere den innloggede brukerens rolle. downgradeCurrentUserMessage=Kan ikke nedgradere den innloggede brukerens rolle.
@ -85,6 +86,7 @@ pipeline.defaultOption=Tilpasset
pipeline.submitButton=Send inn pipeline.submitButton=Send inn
pipeline.help=Pipeline hjelp pipeline.help=Pipeline hjelp
pipeline.scanHelp=Mappe skanning hjelp pipeline.scanHelp=Mappe skanning hjelp
pipeline.deletePrompt=Are you sure you want to delete pipeline
###################### ######################
# Pipeline Options # # Pipeline Options #
@ -173,6 +175,8 @@ adminUserSettings.header=Admin Brukerkontroll Innstillinger
adminUserSettings.admin=Admin adminUserSettings.admin=Admin
adminUserSettings.user=Bruker adminUserSettings.user=Bruker
adminUserSettings.addUser=Legg til Ny Bruker adminUserSettings.addUser=Legg til Ny Bruker
adminUserSettings.deleteUser=Delete User
adminUserSettings.confirmDeleteUser=Should the user be deleted?
adminUserSettings.usernameInfo=Brukernavn kan bare inneholde bokstaver, tall og følgende spesialtegn @._+- eller må være en gyldig e-postadresse. adminUserSettings.usernameInfo=Brukernavn kan bare inneholde bokstaver, tall og følgende spesialtegn @._+- eller må være en gyldig e-postadresse.
adminUserSettings.roles=Roller adminUserSettings.roles=Roller
adminUserSettings.role=Rolle adminUserSettings.role=Rolle
@ -799,6 +803,7 @@ merge.title=Slå sammen
merge.header=Slå sammen flere PDF-er (2+) merge.header=Slå sammen flere PDF-er (2+)
merge.sortByName=Sorter etter navn merge.sortByName=Sorter etter navn
merge.sortByDate=Sorter etter dato merge.sortByDate=Sorter etter dato
merge.removeCertSign=Remove digital signature in the merged file?
merge.submit=Slå sammen merge.submit=Slå sammen

View File

@ -55,6 +55,7 @@ userNotFoundMessage=User not found.
incorrectPasswordMessage=Current password is incorrect. incorrectPasswordMessage=Current password is incorrect.
usernameExistsMessage=New Username already exists. 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. 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. deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted. deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=Nie można obniżyć roli bieżącego użytkownika downgradeCurrentUserMessage=Nie można obniżyć roli bieżącego użytkownika
@ -85,6 +86,7 @@ pipeline.defaultOption=Custom
pipeline.submitButton=Submit pipeline.submitButton=Submit
pipeline.help=Pipeline Help pipeline.help=Pipeline Help
pipeline.scanHelp=Folder Scanning Help pipeline.scanHelp=Folder Scanning Help
pipeline.deletePrompt=Are you sure you want to delete pipeline
###################### ######################
# Pipeline Options # # Pipeline Options #
@ -173,6 +175,8 @@ adminUserSettings.header=Admin User Control Settings
adminUserSettings.admin=Admin adminUserSettings.admin=Admin
adminUserSettings.user=User adminUserSettings.user=User
adminUserSettings.addUser=Add New 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.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Roles adminUserSettings.roles=Roles
adminUserSettings.role=Role adminUserSettings.role=Role
@ -799,6 +803,7 @@ merge.title=Połącz
merge.header=Połącz wiele dokumentów PDF (2+) merge.header=Połącz wiele dokumentów PDF (2+)
merge.sortByName=Sort by name merge.sortByName=Sort by name
merge.sortByDate=Sort by date merge.sortByDate=Sort by date
merge.removeCertSign=Remove digital signature in the merged file?
merge.submit=Połącz merge.submit=Połącz

View File

@ -55,6 +55,7 @@ userNotFoundMessage=User not found.
incorrectPasswordMessage=Current password is incorrect. incorrectPasswordMessage=Current password is incorrect.
usernameExistsMessage=New Username already exists. 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. 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. deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted. deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=Não é possível fazer downgrade da função do usuário atual downgradeCurrentUserMessage=Não é possível fazer downgrade da função do usuário atual
@ -85,6 +86,7 @@ pipeline.defaultOption=Custom
pipeline.submitButton=Submit pipeline.submitButton=Submit
pipeline.help=Pipeline Help pipeline.help=Pipeline Help
pipeline.scanHelp=Folder Scanning Help pipeline.scanHelp=Folder Scanning Help
pipeline.deletePrompt=Are you sure you want to delete pipeline
###################### ######################
# Pipeline Options # # Pipeline Options #
@ -173,6 +175,8 @@ adminUserSettings.header=Admin User Control Settings
adminUserSettings.admin=Admin adminUserSettings.admin=Admin
adminUserSettings.user=User adminUserSettings.user=User
adminUserSettings.addUser=Add New 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.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Roles adminUserSettings.roles=Roles
adminUserSettings.role=Role adminUserSettings.role=Role
@ -799,6 +803,7 @@ merge.title=Mesclar
merge.header=Mesclar Vários PDFs (2+) merge.header=Mesclar Vários PDFs (2+)
merge.sortByName=Sort by name merge.sortByName=Sort by name
merge.sortByDate=Sort by date merge.sortByDate=Sort by date
merge.removeCertSign=Remove digital signature in the merged file?
merge.submit=Mesclar merge.submit=Mesclar

View File

@ -55,6 +55,7 @@ userNotFoundMessage=Utilizador inexistente.
incorrectPasswordMessage=Senha incorreta. incorrectPasswordMessage=Senha incorreta.
usernameExistsMessage=Esse utilizador já existe. usernameExistsMessage=Esse utilizador já existe.
invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address. 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. deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted. deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=Não é possível fazer downgrade da função do utilizador atual downgradeCurrentUserMessage=Não é possível fazer downgrade da função do utilizador atual
@ -85,6 +86,7 @@ pipeline.defaultOption=Personalizar
pipeline.submitButton=Submeter pipeline.submitButton=Submeter
pipeline.help=Pipeline Help pipeline.help=Pipeline Help
pipeline.scanHelp=Folder Scanning Help pipeline.scanHelp=Folder Scanning Help
pipeline.deletePrompt=Are you sure you want to delete pipeline
###################### ######################
# Pipeline Options # # Pipeline Options #
@ -173,6 +175,8 @@ adminUserSettings.header=Admin User Control Settings
adminUserSettings.admin=Admin adminUserSettings.admin=Admin
adminUserSettings.user=User adminUserSettings.user=User
adminUserSettings.addUser=Add New 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.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Roles adminUserSettings.roles=Roles
adminUserSettings.role=Role adminUserSettings.role=Role
@ -799,6 +803,7 @@ merge.title=Juntar
merge.header=Juntar Vários PDFs (2+) merge.header=Juntar Vários PDFs (2+)
merge.sortByName=Ordenar por nome merge.sortByName=Ordenar por nome
merge.sortByDate=Ordenar por data merge.sortByDate=Ordenar por data
merge.removeCertSign=Remove digital signature in the merged file?
merge.submit=Juntar merge.submit=Juntar

View File

@ -55,6 +55,7 @@ userNotFoundMessage=User not found.
incorrectPasswordMessage=Current password is incorrect. incorrectPasswordMessage=Current password is incorrect.
usernameExistsMessage=New Username already exists. 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. 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. deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted. deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=Rolul utilizatorului curent nu poate fi retrogradat downgradeCurrentUserMessage=Rolul utilizatorului curent nu poate fi retrogradat
@ -85,6 +86,7 @@ pipeline.defaultOption=Custom
pipeline.submitButton=Submit pipeline.submitButton=Submit
pipeline.help=Pipeline Help pipeline.help=Pipeline Help
pipeline.scanHelp=Folder Scanning Help pipeline.scanHelp=Folder Scanning Help
pipeline.deletePrompt=Are you sure you want to delete pipeline
###################### ######################
# Pipeline Options # # Pipeline Options #
@ -173,6 +175,8 @@ adminUserSettings.header=Admin User Control Settings
adminUserSettings.admin=Admin adminUserSettings.admin=Admin
adminUserSettings.user=User adminUserSettings.user=User
adminUserSettings.addUser=Add New 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.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Roles adminUserSettings.roles=Roles
adminUserSettings.role=Role adminUserSettings.role=Role
@ -799,6 +803,7 @@ merge.title=Unire
merge.header=Unirea mai multor PDF-uri (2+) merge.header=Unirea mai multor PDF-uri (2+)
merge.sortByName=Sort by name merge.sortByName=Sort by name
merge.sortByDate=Sort by date merge.sortByDate=Sort by date
merge.removeCertSign=Remove digital signature in the merged file?
merge.submit=Unire merge.submit=Unire

View File

@ -55,6 +55,7 @@ userNotFoundMessage=Пользователь не найден.
incorrectPasswordMessage=Текущий пароль неверен. incorrectPasswordMessage=Текущий пароль неверен.
usernameExistsMessage=Новое имя пользователя уже существует. usernameExistsMessage=Новое имя пользователя уже существует.
invalidUsernameMessage=Неверное имя пользователя. Имя пользователя может содержать только буквы, цифры и следующие специальные символы @._+- или должно быть действительным адресом электронной почты. invalidUsernameMessage=Неверное имя пользователя. Имя пользователя может содержать только буквы, цифры и следующие специальные символы @._+- или должно быть действительным адресом электронной почты.
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
deleteCurrentUserMessage=Невозможно удалить пользователя, вошедшего в систему. deleteCurrentUserMessage=Невозможно удалить пользователя, вошедшего в систему.
deleteUsernameExistsMessage=Имя пользователя не существует и не может быть удалено. deleteUsernameExistsMessage=Имя пользователя не существует и не может быть удалено.
downgradeCurrentUserMessage=Невозможно понизить роль текущего пользователя downgradeCurrentUserMessage=Невозможно понизить роль текущего пользователя
@ -85,6 +86,7 @@ pipeline.defaultOption=Пользовательский
pipeline.submitButton=Отправить pipeline.submitButton=Отправить
pipeline.help=Справка по конвейерной обработке pipeline.help=Справка по конвейерной обработке
pipeline.scanHelp=Справка по сканированию папок pipeline.scanHelp=Справка по сканированию папок
pipeline.deletePrompt=Are you sure you want to delete pipeline
###################### ######################
# Pipeline Options # # Pipeline Options #
@ -173,6 +175,8 @@ adminUserSettings.header=Настройки контроля пользоват
adminUserSettings.admin=Администратор adminUserSettings.admin=Администратор
adminUserSettings.user=Пользователь adminUserSettings.user=Пользователь
adminUserSettings.addUser=Добавить нового пользователя adminUserSettings.addUser=Добавить нового пользователя
adminUserSettings.deleteUser=Delete User
adminUserSettings.confirmDeleteUser=Should the user be deleted?
adminUserSettings.usernameInfo=Имя пользователя может содержать только буквы, цифры и следующие специальные символы @._+- или должно быть действительным адресом электронной почты. adminUserSettings.usernameInfo=Имя пользователя может содержать только буквы, цифры и следующие специальные символы @._+- или должно быть действительным адресом электронной почты.
adminUserSettings.roles=Роли adminUserSettings.roles=Роли
adminUserSettings.role=Роль adminUserSettings.role=Роль
@ -799,6 +803,7 @@ merge.title=Объединить
merge.header=Объединение нескольких PDF-файлов (2+) merge.header=Объединение нескольких PDF-файлов (2+)
merge.sortByName=Сортировка по имени merge.sortByName=Сортировка по имени
merge.sortByDate=Сортировка по дате merge.sortByDate=Сортировка по дате
merge.removeCertSign=Remove digital signature in the merged file?
merge.submit=Объединить merge.submit=Объединить

View File

@ -55,6 +55,7 @@ userNotFoundMessage=Používateľ nebol nájdený.
incorrectPasswordMessage=Aktuálne heslo je nesprávne. incorrectPasswordMessage=Aktuálne heslo je nesprávne.
usernameExistsMessage=Nové používateľské meno už existuje. usernameExistsMessage=Nové používateľské meno už existuje.
invalidUsernameMessage=Neplatné používateľské meno, používateľské meno musí obsahovať len abecedné znaky a čísla. invalidUsernameMessage=Neplatné používateľské meno, používateľské meno musí obsahovať len abecedné znaky a čísla.
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
deleteCurrentUserMessage=Nie je možné zmazať aktuálne prihláseného používateľa. deleteCurrentUserMessage=Nie je možné zmazať aktuálne prihláseného používateľa.
deleteUsernameExistsMessage=Používateľské meno neexistuje a nemôže byť zmazané. deleteUsernameExistsMessage=Používateľské meno neexistuje a nemôže byť zmazané.
downgradeCurrentUserMessage=Nie je možné znížiť rolu aktuálneho používateľa downgradeCurrentUserMessage=Nie je možné znížiť rolu aktuálneho používateľa
@ -85,6 +86,7 @@ pipeline.defaultOption=Vlastné
pipeline.submitButton=Odoslať pipeline.submitButton=Odoslať
pipeline.help=Pomoc s pipeline pipeline.help=Pomoc s pipeline
pipeline.scanHelp=Pomoc so skenovaním priečinka pipeline.scanHelp=Pomoc so skenovaním priečinka
pipeline.deletePrompt=Are you sure you want to delete pipeline
###################### ######################
# Pipeline Options # # Pipeline Options #
@ -173,6 +175,8 @@ adminUserSettings.header=Admin nastavenia kontroly používateľov
adminUserSettings.admin=Admin adminUserSettings.admin=Admin
adminUserSettings.user=Používateľ adminUserSettings.user=Používateľ
adminUserSettings.addUser=Pridať nového používateľa adminUserSettings.addUser=Pridať nového používateľa
adminUserSettings.deleteUser=Delete User
adminUserSettings.confirmDeleteUser=Should the user be deleted?
adminUserSettings.usernameInfo=Používateľské meno musí obsahovať iba písmená a čísla, žiadne medzery alebo špeciálne znaky. adminUserSettings.usernameInfo=Používateľské meno musí obsahovať iba písmená a čísla, žiadne medzery alebo špeciálne znaky.
adminUserSettings.roles=Role adminUserSettings.roles=Role
adminUserSettings.role=Rola adminUserSettings.role=Rola
@ -799,6 +803,7 @@ merge.title=Zlúčiť
merge.header=Zlúčiť viacero PDF (2+) merge.header=Zlúčiť viacero PDF (2+)
merge.sortByName=Zoradiť podľa názvu merge.sortByName=Zoradiť podľa názvu
merge.sortByDate=Zoradiť podľa dátumu merge.sortByDate=Zoradiť podľa dátumu
merge.removeCertSign=Remove digital signature in the merged file?
merge.submit=Zlúčiť merge.submit=Zlúčiť

View File

@ -55,6 +55,7 @@ userNotFoundMessage=Korisnik nije pronađen.
incorrectPasswordMessage=Trenutna šifra je netačna. incorrectPasswordMessage=Trenutna šifra je netačna.
usernameExistsMessage=Novi korisnik već postoji usernameExistsMessage=Novi korisnik već postoji
invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address. 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. deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted. deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=Nije moguće degradirati ulogu trenutnog korisnika downgradeCurrentUserMessage=Nije moguće degradirati ulogu trenutnog korisnika
@ -85,6 +86,7 @@ pipeline.defaultOption=Prilagođeno
pipeline.submitButton=Pošalji pipeline.submitButton=Pošalji
pipeline.help=Pipeline Help pipeline.help=Pipeline Help
pipeline.scanHelp=Folder Scanning Help pipeline.scanHelp=Folder Scanning Help
pipeline.deletePrompt=Are you sure you want to delete pipeline
###################### ######################
# Pipeline Options # # Pipeline Options #
@ -173,6 +175,8 @@ adminUserSettings.header=Podešavanja kontrole korisnika za administratora
adminUserSettings.admin=Administrator adminUserSettings.admin=Administrator
adminUserSettings.user=Korisnik adminUserSettings.user=Korisnik
adminUserSettings.addUser=Dodaj novog korisnika adminUserSettings.addUser=Dodaj novog korisnika
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.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Uloge adminUserSettings.roles=Uloge
adminUserSettings.role=Uloga adminUserSettings.role=Uloga
@ -799,6 +803,7 @@ merge.title=Spajanje
merge.header=Spajanje više PDF fajlova (2+) merge.header=Spajanje više PDF fajlova (2+)
merge.sortByName=Sortiraj po imenu merge.sortByName=Sortiraj po imenu
merge.sortByDate=Sortiraj po datumu merge.sortByDate=Sortiraj po datumu
merge.removeCertSign=Remove digital signature in the merged file?
merge.submit=Spajanje merge.submit=Spajanje

View File

@ -55,6 +55,7 @@ userNotFoundMessage=User not found.
incorrectPasswordMessage=Current password is incorrect. incorrectPasswordMessage=Current password is incorrect.
usernameExistsMessage=New Username already exists. 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. 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. deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted. deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=Kan inte nedgradera nuvarande användares roll downgradeCurrentUserMessage=Kan inte nedgradera nuvarande användares roll
@ -85,6 +86,7 @@ pipeline.defaultOption=Custom
pipeline.submitButton=Submit pipeline.submitButton=Submit
pipeline.help=Pipeline Help pipeline.help=Pipeline Help
pipeline.scanHelp=Folder Scanning Help pipeline.scanHelp=Folder Scanning Help
pipeline.deletePrompt=Are you sure you want to delete pipeline
###################### ######################
# Pipeline Options # # Pipeline Options #
@ -173,6 +175,8 @@ adminUserSettings.header=Admin User Control Settings
adminUserSettings.admin=Admin adminUserSettings.admin=Admin
adminUserSettings.user=User adminUserSettings.user=User
adminUserSettings.addUser=Add New 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.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Roles adminUserSettings.roles=Roles
adminUserSettings.role=Role adminUserSettings.role=Role
@ -799,6 +803,7 @@ merge.title=Sammanfoga
merge.header=Slå samman flera PDF-filer (2+) merge.header=Slå samman flera PDF-filer (2+)
merge.sortByName=Sort by name merge.sortByName=Sort by name
merge.sortByDate=Sort by date merge.sortByDate=Sort by date
merge.removeCertSign=Remove digital signature in the merged file?
merge.submit=Slå samman merge.submit=Slå samman

View File

@ -55,6 +55,7 @@ userNotFoundMessage=Kullanıcı bulunamadı.
incorrectPasswordMessage=Mevcut şifre yanlış. incorrectPasswordMessage=Mevcut şifre yanlış.
usernameExistsMessage=Yeni Kullanıcı Adı zaten var. usernameExistsMessage=Yeni Kullanıcı Adı zaten var.
invalidUsernameMessage=Geçersiz kullanıcı adı, kullanıcı adı yalnızca harf, rakam ve aşağıdaki özel karakterleri @._+- içerebilir veya geçerli bir e-posta adresi olmalıdır. invalidUsernameMessage=Geçersiz kullanıcı adı, kullanıcı adı yalnızca harf, rakam ve aşağıdaki özel karakterleri @._+- içerebilir veya geçerli bir e-posta adresi olmalıdır.
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
deleteCurrentUserMessage=Şu anda oturum açmış olan kullanıcı silinemiyor. deleteCurrentUserMessage=Şu anda oturum açmış olan kullanıcı silinemiyor.
deleteUsernameExistsMessage=Kullanıcı adı mevcut değil ve silinemez. deleteUsernameExistsMessage=Kullanıcı adı mevcut değil ve silinemez.
downgradeCurrentUserMessage=Mevcut kullanıcının rolü düşürülemiyor downgradeCurrentUserMessage=Mevcut kullanıcının rolü düşürülemiyor
@ -85,6 +86,7 @@ pipeline.defaultOption=Özel
pipeline.submitButton=Gönder pipeline.submitButton=Gönder
pipeline.help=Çoklu İşlemler Yardım pipeline.help=Çoklu İşlemler Yardım
pipeline.scanHelp=Klasör Tarama Yardımı pipeline.scanHelp=Klasör Tarama Yardımı
pipeline.deletePrompt=Are you sure you want to delete pipeline
###################### ######################
# Pipeline Options # # Pipeline Options #
@ -173,6 +175,8 @@ adminUserSettings.header=Yönetici Kullanıcı Kontrol Ayarları
adminUserSettings.admin=Yönetici adminUserSettings.admin=Yönetici
adminUserSettings.user=Kullanıcı adminUserSettings.user=Kullanıcı
adminUserSettings.addUser=Yeni Kullanıcı Ekle adminUserSettings.addUser=Yeni Kullanıcı Ekle
adminUserSettings.deleteUser=Delete User
adminUserSettings.confirmDeleteUser=Should the user be deleted?
adminUserSettings.usernameInfo=Kullanıcı adı yalnızca harf, rakam ve aşağıdaki özel karakterleri @._+- içerebilir veya geçerli bir e-posta adresi olmalıdır. adminUserSettings.usernameInfo=Kullanıcı adı yalnızca harf, rakam ve aşağıdaki özel karakterleri @._+- içerebilir veya geçerli bir e-posta adresi olmalıdır.
adminUserSettings.roles=Roller adminUserSettings.roles=Roller
adminUserSettings.role=Rol adminUserSettings.role=Rol
@ -799,6 +803,7 @@ merge.title=Birleştir
merge.header=Çoklu PDF'leri Birleştir (2+) merge.header=Çoklu PDF'leri Birleştir (2+)
merge.sortByName=İsme göre sırala merge.sortByName=İsme göre sırala
merge.sortByDate=Tarihe göre sırala merge.sortByDate=Tarihe göre sırala
merge.removeCertSign=Remove digital signature in the merged file?
merge.submit=Birleştir merge.submit=Birleştir

View File

@ -55,6 +55,7 @@ userNotFoundMessage=Користувача не знайдено.
incorrectPasswordMessage=Поточний пароль невірний. incorrectPasswordMessage=Поточний пароль невірний.
usernameExistsMessage=Нове ім'я користувача вже існує. usernameExistsMessage=Нове ім'я користувача вже існує.
invalidUsernameMessage=Недійсне ім’я користувача, ім’я користувача може містити лише літери, цифри та наступні спеціальні символи @._+- або має бути дійсною електронною адресою. invalidUsernameMessage=Недійсне ім’я користувача, ім’я користувача може містити лише літери, цифри та наступні спеціальні символи @._+- або має бути дійсною електронною адресою.
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
deleteCurrentUserMessage=Неможливо видалити користувача, який увійшов в систему. deleteCurrentUserMessage=Неможливо видалити користувача, який увійшов в систему.
deleteUsernameExistsMessage=Ім'я користувача не існує і не може бути видалено. deleteUsernameExistsMessage=Ім'я користувача не існує і не може бути видалено.
downgradeCurrentUserMessage=Неможливо понизити роль поточного користувача downgradeCurrentUserMessage=Неможливо понизити роль поточного користувача
@ -85,6 +86,7 @@ pipeline.defaultOption=Користувацький
pipeline.submitButton=Надіслати pipeline.submitButton=Надіслати
pipeline.help=Довідка з конвеєрної обробки pipeline.help=Довідка з конвеєрної обробки
pipeline.scanHelp=Довідка зі сканування папок pipeline.scanHelp=Довідка зі сканування папок
pipeline.deletePrompt=Are you sure you want to delete pipeline
###################### ######################
# Pipeline Options # # Pipeline Options #
@ -173,6 +175,8 @@ adminUserSettings.header=Налаштування контролю корист
adminUserSettings.admin=Адміністратор adminUserSettings.admin=Адміністратор
adminUserSettings.user=Користувач adminUserSettings.user=Користувач
adminUserSettings.addUser=Додати нового користувача adminUserSettings.addUser=Додати нового користувача
adminUserSettings.deleteUser=Delete User
adminUserSettings.confirmDeleteUser=Should the user be deleted?
adminUserSettings.usernameInfo=Ім’я користувача може містити лише літери, цифри та наступні спеціальні символи @._+- або має бути дійсною електронною адресою. adminUserSettings.usernameInfo=Ім’я користувача може містити лише літери, цифри та наступні спеціальні символи @._+- або має бути дійсною електронною адресою.
adminUserSettings.roles=Ролі adminUserSettings.roles=Ролі
adminUserSettings.role=Роль adminUserSettings.role=Роль
@ -799,6 +803,7 @@ merge.title=Об'єднати
merge.header=Об'єднання кількох PDF-файлів (2+) merge.header=Об'єднання кількох PDF-файлів (2+)
merge.sortByName=Сортування за ім'ям merge.sortByName=Сортування за ім'ям
merge.sortByDate=Сортування за датою merge.sortByDate=Сортування за датою
merge.removeCertSign=Remove digital signature in the merged file?
merge.submit=Об'єднати merge.submit=Об'єднати

View File

@ -55,6 +55,7 @@ userNotFoundMessage=未找到用户。
incorrectPasswordMessage=当前密码不正确。 incorrectPasswordMessage=当前密码不正确。
usernameExistsMessage=新用户名已存在。 usernameExistsMessage=新用户名已存在。
invalidUsernameMessage=用户名无效,用户名只能包含字母、数字和以下特殊字符@._+- 或必须是有效的电子邮件地址。 invalidUsernameMessage=用户名无效,用户名只能包含字母、数字和以下特殊字符@._+- 或必须是有效的电子邮件地址。
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
deleteCurrentUserMessage=无法删除当前登录的用户。 deleteCurrentUserMessage=无法删除当前登录的用户。
deleteUsernameExistsMessage=用户名不存在,无法删除。 deleteUsernameExistsMessage=用户名不存在,无法删除。
downgradeCurrentUserMessage=无法降级当前用户的角色 downgradeCurrentUserMessage=无法降级当前用户的角色
@ -85,6 +86,7 @@ pipeline.defaultOption=自定义
pipeline.submitButton=提交 pipeline.submitButton=提交
pipeline.help=工作流帮助 pipeline.help=工作流帮助
pipeline.scanHelp=文件夹扫描帮助 pipeline.scanHelp=文件夹扫描帮助
pipeline.deletePrompt=Are you sure you want to delete pipeline
###################### ######################
# Pipeline Options # # Pipeline Options #
@ -173,6 +175,8 @@ adminUserSettings.header=管理员用户控制设置
adminUserSettings.admin=管理员 adminUserSettings.admin=管理员
adminUserSettings.user=用户 adminUserSettings.user=用户
adminUserSettings.addUser=添加新用户 adminUserSettings.addUser=添加新用户
adminUserSettings.deleteUser=Delete User
adminUserSettings.confirmDeleteUser=Should the user be deleted?
adminUserSettings.usernameInfo=用户名只能包含字母、数字和以下特殊字符@._+-,或者必须是有效的电子邮件地址。 adminUserSettings.usernameInfo=用户名只能包含字母、数字和以下特殊字符@._+-,或者必须是有效的电子邮件地址。
adminUserSettings.roles=角色 adminUserSettings.roles=角色
adminUserSettings.role=角色 adminUserSettings.role=角色
@ -799,6 +803,7 @@ merge.title=合并
merge.header=合并多个PDF2个以上 merge.header=合并多个PDF2个以上
merge.sortByName=按名称排序 merge.sortByName=按名称排序
merge.sortByDate=按日期排序 merge.sortByDate=按日期排序
merge.removeCertSign=Remove digital signature in the merged file?
merge.submit=合并 merge.submit=合并

View File

@ -55,6 +55,7 @@ userNotFoundMessage=找不到使用者。
incorrectPasswordMessage=目前密碼不正確。 incorrectPasswordMessage=目前密碼不正確。
usernameExistsMessage=新使用者名稱已存在。 usernameExistsMessage=新使用者名稱已存在。
invalidUsernameMessage=使用者名稱無效,使用者名稱只能包含字母、數字和以下特殊字元@._+- 或必須是有效的電子郵件地址。 invalidUsernameMessage=使用者名稱無效,使用者名稱只能包含字母、數字和以下特殊字元@._+- 或必須是有效的電子郵件地址。
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
deleteCurrentUserMessage=無法刪除目前登錄的使用者。 deleteCurrentUserMessage=無法刪除目前登錄的使用者。
deleteUsernameExistsMessage=使用者名不存在,無法刪除。 deleteUsernameExistsMessage=使用者名不存在,無法刪除。
downgradeCurrentUserMessage=無法降級目前使用者的角色 downgradeCurrentUserMessage=無法降級目前使用者的角色
@ -85,6 +86,7 @@ pipeline.defaultOption=自訂
pipeline.submitButton=送出 pipeline.submitButton=送出
pipeline.help=管道説明 pipeline.help=管道説明
pipeline.scanHelp=資料夾掃描説明 pipeline.scanHelp=資料夾掃描説明
pipeline.deletePrompt=Are you sure you want to delete pipeline
###################### ######################
# Pipeline Options # # Pipeline Options #
@ -173,6 +175,8 @@ adminUserSettings.header=管理使用者控制設定
adminUserSettings.admin=管理員 adminUserSettings.admin=管理員
adminUserSettings.user=使用者 adminUserSettings.user=使用者
adminUserSettings.addUser=新增使用者 adminUserSettings.addUser=新增使用者
adminUserSettings.deleteUser=Delete User
adminUserSettings.confirmDeleteUser=Should the user be deleted?
adminUserSettings.usernameInfo=使用者名稱只能包含字母、數字和以下特殊字元@._+-,或必須是有效的電子郵件地址。 adminUserSettings.usernameInfo=使用者名稱只能包含字母、數字和以下特殊字元@._+-,或必須是有效的電子郵件地址。
adminUserSettings.roles=角色 adminUserSettings.roles=角色
adminUserSettings.role=角色 adminUserSettings.role=角色
@ -799,6 +803,7 @@ merge.title=合併
merge.header=合併多個 PDF merge.header=合併多個 PDF
merge.sortByName=依名稱排序 merge.sortByName=依名稱排序
merge.sortByDate=依日期排序 merge.sortByDate=依日期排序
merge.removeCertSign=Remove digital signature in the merged file?
merge.submit=合併 merge.submit=合併

File diff suppressed because one or more lines are too long

View File

@ -20,10 +20,35 @@ async function getLatestReleaseVersion() {
const url = "https://api.github.com/repos/Stirling-Tools/Stirling-PDF/releases/latest"; const url = "https://api.github.com/repos/Stirling-Tools/Stirling-PDF/releases/latest";
try { try {
const response = await fetch(url); const response = await fetch(url);
const data = await response.json(); if (response.status === 200) {
return data.tag_name ? data.tag_name.substring(1) : ""; const data = await response.json();
return data.tag_name ? data.tag_name.substring(1) : "";
} else {
// If the status is not 200, try to get the version from build.gradle
return await getCurrentVersionFromBypass();
}
} catch (error) { } catch (error) {
console.error("Failed to fetch latest version:", error); console.error("Failed to fetch latest version from GitHub:", error);
// If an error occurs, try to get the version from build.gradle
return await getCurrentVersionFromBypass();
}
}
async function getCurrentVersionFromBypass() {
const url = "https://raw.githubusercontent.com/Stirling-Tools/Stirling-PDF/master/build.gradle";
try {
const response = await fetch(url);
if (response.status === 200) {
const text = await response.text();
const versionRegex = /version\s*=\s*['"](\d+\.\d+\.\d+)['"]/;
const match = versionRegex.exec(text);
if (match) {
return match[1];
}
}
throw new Error("Version number not found");
} catch (error) {
console.error("Failed to fetch latest version from build.gradle:", error);
return ""; // Return an empty string if the fetch fails return ""; // Return an empty string if the fetch fails
} }
} }

View File

@ -96,7 +96,6 @@ document.getElementById("submitConfigBtn").addEventListener("click", function ()
for (let i = 0; i < pipelineList.length; i++) { for (let i = 0; i < pipelineList.length; i++) {
let operationName = pipelineList[i].querySelector(".operationName").textContent; let operationName = pipelineList[i].querySelector(".operationName").textContent;
let parameters = operationSettings[operationName] || {}; let parameters = operationSettings[operationName] || {};
pipelineConfig.pipeline.push({ pipelineConfig.pipeline.push({
operation: operationName, operation: operationName,
parameters: parameters, parameters: parameters,
@ -104,7 +103,6 @@ document.getElementById("submitConfigBtn").addEventListener("click", function ()
} }
let pipelineConfigJson = JSON.stringify(pipelineConfig, null, 2); let pipelineConfigJson = JSON.stringify(pipelineConfig, null, 2);
let formData = new FormData(); let formData = new FormData();
let fileInput = document.getElementById("fileInput-input"); let fileInput = document.getElementById("fileInput-input");
@ -218,6 +216,41 @@ fetch("v1/api-docs")
}); });
}); });
document.getElementById('deletePipelineBtn').addEventListener('click', function(event) {
event.preventDefault();
let pipelineName = document.getElementById('pipelineName').value;
if (confirm(deletePipelineText + pipelineName)) {
removePipelineFromUI(pipelineName);
let key = "#Pipeline-" + pipelineName;
if (localStorage.getItem(key)) {
localStorage.removeItem(key);
}
let pipelineSelect = document.getElementById("pipelineSelect");
let modal = document.getElementById('pipelineSettingsModal');
if (modal.style.display !== 'none') {
$('#pipelineSettingsModal').modal('hide');
}
if (pipelineSelect.options.length > 0) {
pipelineSelect.selectedIndex = 0;
pipelineSelect.dispatchEvent(new Event('change'));
}
}
});
function removePipelineFromUI(pipelineName) {
let pipelineSelect = document.getElementById("pipelineSelect");
for (let i = 0; i < pipelineSelect.options.length; i++) {
console.log(pipelineSelect.options[i])
console.log("list " + pipelineSelect.options[i].innerText + " vs " + pipelineName)
if (pipelineSelect.options[i].innerText === pipelineName) {
pipelineSelect.remove(i);
break;
}
}
}
document.getElementById("addOperationBtn").addEventListener("click", function () { document.getElementById("addOperationBtn").addEventListener("click", function () {
let selectedOperation = document.getElementById("operationsDropdown").value; let selectedOperation = document.getElementById("operationsDropdown").value;
let pipelineList = document.getElementById("pipelineList"); let pipelineList = document.getElementById("pipelineList");
@ -378,18 +411,22 @@ document.getElementById("addOperationBtn").addEventListener("click", function ()
parameterInput.type = "checkbox"; parameterInput.type = "checkbox";
if (defaultValue === true) parameterInput.checked = true; if (defaultValue === true) parameterInput.checked = true;
break; break;
case "array": case "array":
case "object": // If parameter.schema.format === 'binary' is to be checked, it should be checked here
//TODO compare to doc and check if fileInput array? parameter.schema.format === 'binary' parameterInput = document.createElement("textarea");
parameterInput = document.createElement("textarea"); parameterInput.placeholder = 'Enter a JSON formatted array, e.g., ["item1", "item2", "item3"]';
parameterInput.placeholder = `Enter a JSON formatted ${parameter.schema.type}, If this is a fileInput, it is not currently supported`; parameterInput.className = "form-control";
parameterInput.className = "form-control"; break;
break; case "object":
default: parameterInput = document.createElement("textarea");
parameterInput = document.createElement("input"); parameterInput.placeholder = 'Enter a JSON formatted object, e.g., {"key": "value"} If this is a fileInput, it is not currently supported';
parameterInput.type = "text"; parameterInput.className = "form-control";
parameterInput.className = "form-control"; break;
if (defaultValue !== undefined) parameterInput.value = defaultValue; default:
parameterInput = document.createElement("input");
parameterInput.type = "text";
parameterInput.className = "form-control";
if (defaultValue !== undefined) parameterInput.value = defaultValue;
} }
} }
parameterInput.id = parameter.name; parameterInput.id = parameter.name;
@ -441,16 +478,21 @@ document.getElementById("addOperationBtn").addEventListener("click", function ()
break; break;
case "array": case "array":
case "object": case "object":
if (value === null || value === "") { if (value === null || value === "") {
settings[parameter.name] = ""; settings[parameter.name] = "";
} else { } else {
try { try {
settings[parameter.name] = JSON.parse(value); const parsedValue = JSON.parse(value);
} catch (err) { if (Array.isArray(parsedValue)) {
console.error(`Invalid JSON format for ${parameter.name}`); settings[parameter.name] = parsedValue;
} } else {
} settings[parameter.name] = value;
break; }
} catch (e) {
settings[parameter.name] = value;
}
}
break;
default: default:
settings[parameter.name] = value; settings[parameter.name] = value;
} }
@ -558,7 +600,6 @@ function configToJson() {
parameters: parameters, parameters: parameters,
}); });
} }
return JSON.stringify(pipelineConfig, null, 2); return JSON.stringify(pipelineConfig, null, 2);
} }
@ -642,7 +683,13 @@ async function processPipelineConfig(configString) {
case "text": case "text":
case "textarea": case "textarea":
default: default:
input.value = JSON.stringify(operationConfig.parameters[parameterName]); var value = operationConfig.parameters[parameterName]
if (typeof value !== 'string') {
input.value = JSON.stringify(value) ;
} else {
input.value = value;
}
} }
} }
}); });

View File

@ -13,6 +13,242 @@
* limitations under the License. * limitations under the License.
*/ */
.dialog{
--dialog-bg-color:white;
--dialog-border-color:white;
--dialog-shadow:0 2px 14px 0 rgb(58 57 68 / 0.2);
--text-primary-color:#15141a;
--text-secondary-color:#5b5b66;
--hover-filter:brightness(0.9);
--focus-ring-color:#0060df;
--focus-ring-outline:2px solid var(--focus-ring-color);
--textarea-border-color:#8f8f9d;
--textarea-bg-color:white;
--textarea-fg-color:var(--text-secondary-color);
--radio-bg-color:#f0f0f4;
--radio-checked-bg-color:#fbfbfe;
--radio-border-color:#8f8f9d;
--radio-checked-border-color:#0060df;
--button-secondary-bg-color:#f0f0f4;
--button-secondary-fg-color:var(--text-primary-color);
--button-secondary-border-color:var(--button-secondary-bg-color);
--button-secondary-hover-bg-color:var(--button-secondary-bg-color);
--button-secondary-hover-fg-color:var(--button-secondary-fg-color);
--button-secondary-hover-border-color:var(--button-secondary-hover-bg-color);
--button-primary-bg-color:#0060df;
--button-primary-fg-color:#fbfbfe;
--button-primary-hover-bg-color:var(--button-primary-bg-color);
--button-primary-hover-fg-color:var(--button-primary-fg-color);
--button-primary-hover-border-color:var(--button-primary-hover-bg-color);
font:message-box;
font-size:13px;
font-weight:400;
line-height:150%;
border-radius:4px;
padding:12px 16px;
border:1px solid var(--dialog-border-color);
background:var(--dialog-bg-color);
color:var(--text-primary-color);
box-shadow:var(--dialog-shadow);
}
@media (prefers-color-scheme: dark){
:where(html:not(.is-light)) .dialog{
--dialog-bg-color:#1c1b22;
--dialog-border-color:#1c1b22;
--dialog-shadow:0 2px 14px 0 #15141a;
--text-primary-color:#fbfbfe;
--text-secondary-color:#cfcfd8;
--focus-ring-color:#0df;
--hover-filter:brightness(1.4);
--textarea-bg-color:#42414d;
--radio-bg-color:#2b2a33;
--radio-checked-bg-color:#15141a;
--radio-checked-border-color:#0df;
--button-secondary-bg-color:#2b2a33;
--button-primary-bg-color:#0df;
--button-primary-fg-color:#15141a;
}
}
:where(html.is-dark) .dialog{
--dialog-bg-color:#1c1b22;
--dialog-border-color:#1c1b22;
--dialog-shadow:0 2px 14px 0 #15141a;
--text-primary-color:#fbfbfe;
--text-secondary-color:#cfcfd8;
--focus-ring-color:#0df;
--hover-filter:brightness(1.4);
--textarea-bg-color:#42414d;
--radio-bg-color:#2b2a33;
--radio-checked-bg-color:#15141a;
--radio-checked-border-color:#0df;
--button-secondary-bg-color:#2b2a33;
--button-primary-bg-color:#0df;
--button-primary-fg-color:#15141a;
}
@media screen and (forced-colors: active){
.dialog{
--dialog-bg-color:Canvas;
--dialog-border-color:CanvasText;
--dialog-shadow:none;
--text-primary-color:CanvasText;
--text-secondary-color:CanvasText;
--hover-filter:none;
--focus-ring-color:ButtonBorder;
--textarea-border-color:ButtonBorder;
--textarea-bg-color:Field;
--textarea-fg-color:ButtonText;
--radio-bg-color:ButtonFace;
--radio-checked-bg-color:ButtonFace;
--radio-border-color:ButtonText;
--radio-checked-border-color:ButtonText;
--button-secondary-bg-color:ButtonFace;
--button-secondary-fg-color:ButtonText;
--button-secondary-border-color:ButtonText;
--button-secondary-hover-bg-color:AccentColor;
--button-secondary-hover-fg-color:AccentColorText;
--button-primary-bg-color:ButtonText;
--button-primary-fg-color:ButtonFace;
--button-primary-hover-bg-color:AccentColor;
--button-primary-hover-fg-color:AccentColorText;
}
}
.dialog .mainContainer *:focus-visible{
outline:var(--focus-ring-outline);
outline-offset:2px;
}
.dialog .mainContainer .radio{
display:flex;
flex-direction:column;
align-items:flex-start;
gap:4px;
}
.dialog .mainContainer .radio > .radioButton{
display:flex;
gap:8px;
align-self:stretch;
align-items:center;
}
.dialog .mainContainer .radio > .radioButton input{
-webkit-appearance:none;
-moz-appearance:none;
appearance:none;
box-sizing:border-box;
width:16px;
height:16px;
border-radius:50%;
background-color:var(--radio-bg-color);
border:1px solid var(--radio-border-color);
}
.dialog .mainContainer .radio > .radioButton input:hover{
filter:var(--hover-filter);
}
.dialog .mainContainer .radio > .radioButton input:checked{
background-color:var(--radio-checked-bg-color);
border:4px solid var(--radio-checked-border-color);
}
.dialog .mainContainer .radio > .radioLabel{
display:flex;
padding-inline-start:24px;
align-items:flex-start;
gap:10px;
align-self:stretch;
}
.dialog .mainContainer .radio > .radioLabel > span{
flex:1 0 0;
font-size:11px;
color:var(--text-secondary-color);
}
.dialog .mainContainer button{
border-radius:4px;
border:1px solid;
font:menu;
font-weight:600;
padding:4px 16px;
width:auto;
height:32px;
}
.dialog .mainContainer button:hover{
cursor:pointer;
filter:var(--hover-filter);
}
.dialog .mainContainer button.secondaryButton{
color:var(--button-secondary-fg-color);
background-color:var(--button-secondary-bg-color);
border-color:var(--button-secondary-border-color);
}
.dialog .mainContainer button.secondaryButton:hover{
color:var(--button-secondary-hover-fg-color);
background-color:var(--button-secondary-hover-bg-color);
border-color:var(--button-secondary-hover-border-color);
}
.dialog .mainContainer button.primaryButton{
color:var(--button-primary-hover-fg-color);
background-color:var(--button-primary-hover-bg-color);
border-color:var(--button-primary-hover-border-color);
opacity:1;
}
.dialog .mainContainer button.primaryButton:hover{
color:var(--button-primary-hover-fg-color);
background-color:var(--button-primary-hover-bg-color);
border-color:var(--button-primary-hover-border-color);
}
.dialog .mainContainer textarea{
font:inherit;
padding:8px;
resize:none;
margin:0;
box-sizing:border-box;
border-radius:4px;
border:1px solid var(--textarea-border-color);
background:var(--textarea-bg-color);
color:var(--textarea-fg-color);
}
.dialog .mainContainer textarea:focus{
outline-offset:0;
border-color:transparent;
}
.dialog .mainContainer textarea:disabled{
pointer-events:none;
opacity:0.4;
}
.textLayer{ .textLayer{
position:absolute; position:absolute;
text-align:initial; text-align:initial;
@ -1946,136 +2182,16 @@
inset-block-start:0; inset-block-start:0;
} }
#altTextDialog{ .dialog.altText::backdrop{
--dialog-bg-color:white;
--dialog-border-color:white;
--dialog-shadow:0 2px 14px 0 rgb(58 57 68 / 0.2);
--text-primary-color:#15141a;
--text-secondary-color:#5b5b66;
--hover-filter:brightness(0.9);
--focus-ring-color:#0060df;
--focus-ring-outline:2px solid var(--focus-ring-color);
--textarea-border-color:#8f8f9d;
--textarea-bg-color:white;
--textarea-fg-color:var(--text-secondary-color);
--radio-bg-color:#f0f0f4;
--radio-checked-bg-color:#fbfbfe;
--radio-border-color:#8f8f9d;
--radio-checked-border-color:#0060df;
--button-cancel-bg-color:#f0f0f4;
--button-cancel-fg-color:var(--text-primary-color);
--button-cancel-border-color:var(--button-cancel-bg-color);
--button-cancel-hover-bg-color:var(--button-cancel-bg-color);
--button-cancel-hover-fg-color:var(--button-cancel-fg-color);
--button-cancel-hover-border-color:var(--button-cancel-hover-bg-color);
--button-save-bg-color:#0060df;
--button-save-fg-color:#fbfbfe;
--button-save-hover-bg-color:var(--button-save-bg-color);
--button-save-hover-fg-color:var(--button-save-fg-color);
--button-save-hover-border-color:var(--button-save-hover-bg-color);
font:message-box;
font-size:13px;
font-weight:400;
line-height:150%;
border-radius:4px;
padding:12px 16px;
border:1px solid var(--dialog-border-color);
background:var(--dialog-bg-color);
color:var(--text-primary-color);
box-shadow:var(--dialog-shadow);
}
@media (prefers-color-scheme: dark){
:where(html:not(.is-light)) #altTextDialog{
--dialog-bg-color:#1c1b22;
--dialog-border-color:#1c1b22;
--dialog-shadow:0 2px 14px 0 #15141a;
--text-primary-color:#fbfbfe;
--text-secondary-color:#cfcfd8;
--focus-ring-color:#0df;
--hover-filter:brightness(1.4);
--textarea-bg-color:#42414d;
--radio-bg-color:#2b2a33;
--radio-checked-bg-color:#15141a;
--radio-checked-border-color:#0df;
--button-cancel-bg-color:#2b2a33;
--button-save-bg-color:#0df;
--button-save-fg-color:#15141a;
}
}
:where(html.is-dark) #altTextDialog{
--dialog-bg-color:#1c1b22;
--dialog-border-color:#1c1b22;
--dialog-shadow:0 2px 14px 0 #15141a;
--text-primary-color:#fbfbfe;
--text-secondary-color:#cfcfd8;
--focus-ring-color:#0df;
--hover-filter:brightness(1.4);
--textarea-bg-color:#42414d;
--radio-bg-color:#2b2a33;
--radio-checked-bg-color:#15141a;
--radio-checked-border-color:#0df;
--button-cancel-bg-color:#2b2a33;
--button-save-bg-color:#0df;
--button-save-fg-color:#15141a;
}
@media screen and (forced-colors: active){
#altTextDialog{
--dialog-bg-color:Canvas;
--dialog-border-color:CanvasText;
--dialog-shadow:none;
--text-primary-color:CanvasText;
--text-secondary-color:CanvasText;
--hover-filter:none;
--focus-ring-color:ButtonBorder;
--textarea-border-color:ButtonBorder;
--textarea-bg-color:Field;
--textarea-fg-color:ButtonText;
--radio-bg-color:ButtonFace;
--radio-checked-bg-color:ButtonFace;
--radio-border-color:ButtonText;
--radio-checked-border-color:ButtonText;
--button-cancel-bg-color:ButtonFace;
--button-cancel-fg-color:ButtonText;
--button-cancel-border-color:ButtonText;
--button-cancel-hover-bg-color:AccentColor;
--button-cancel-hover-fg-color:AccentColorText;
--button-save-bg-color:ButtonText;
--button-save-fg-color:ButtonFace;
--button-save-hover-bg-color:AccentColor;
--button-save-hover-fg-color:AccentColorText;
}
}
#altTextDialog::backdrop{
-webkit-mask:url(#alttext-manager-mask); -webkit-mask:url(#alttext-manager-mask);
mask:url(#alttext-manager-mask); mask:url(#alttext-manager-mask);
} }
#altTextDialog.positioned{ .dialog.altText.positioned{
margin:0; margin:0;
} }
#altTextDialog #altTextContainer{ .dialog.altText #altTextContainer{
width:300px; width:300px;
height:-moz-fit-content; height:-moz-fit-content;
height:fit-content; height:fit-content;
@ -2085,61 +2201,7 @@
gap:16px; gap:16px;
} }
#altTextDialog #altTextContainer *:focus-visible{ .dialog.altText #altTextContainer #overallDescription{
outline:var(--focus-ring-outline);
outline-offset:2px;
}
#altTextDialog #altTextContainer .radio{
display:flex;
flex-direction:column;
align-items:flex-start;
gap:4px;
}
#altTextDialog #altTextContainer .radio .radioButton{
display:flex;
gap:8px;
align-self:stretch;
align-items:center;
}
#altTextDialog #altTextContainer .radio .radioButton input{
-webkit-appearance:none;
-moz-appearance:none;
appearance:none;
box-sizing:border-box;
width:16px;
height:16px;
border-radius:50%;
background-color:var(--radio-bg-color);
border:1px solid var(--radio-border-color);
}
#altTextDialog #altTextContainer .radio .radioButton input:hover{
filter:var(--hover-filter);
}
#altTextDialog #altTextContainer .radio .radioButton input:checked{
background-color:var(--radio-checked-bg-color);
border:4px solid var(--radio-checked-border-color);
}
#altTextDialog #altTextContainer .radio .radioLabel{
display:flex;
padding-inline-start:24px;
align-items:flex-start;
gap:10px;
align-self:stretch;
}
#altTextDialog #altTextContainer .radio .radioLabel span{
flex:1 0 0;
font-size:11px;
color:var(--text-secondary-color);
}
#altTextDialog #altTextContainer #overallDescription{
display:flex; display:flex;
flex-direction:column; flex-direction:column;
align-items:flex-start; align-items:flex-start;
@ -2147,53 +2209,34 @@
align-self:stretch; align-self:stretch;
} }
#altTextDialog #altTextContainer #overallDescription span{ .dialog.altText #altTextContainer #overallDescription span{
align-self:stretch; align-self:stretch;
} }
#altTextDialog #altTextContainer #overallDescription .title{ .dialog.altText #altTextContainer #overallDescription .title{
font-size:13px; font-size:13px;
font-style:normal; font-style:normal;
font-weight:590; font-weight:590;
} }
#altTextDialog #altTextContainer #addDescription{ .dialog.altText #altTextContainer #addDescription{
display:flex; display:flex;
flex-direction:column; flex-direction:column;
align-items:stretch; align-items:stretch;
gap:8px; gap:8px;
} }
#altTextDialog #altTextContainer #addDescription .descriptionArea{ .dialog.altText #altTextContainer #addDescription .descriptionArea{
flex:1; flex:1;
padding-inline:24px 10px; padding-inline:24px 10px;
} }
#altTextDialog #altTextContainer #addDescription .descriptionArea textarea{ .dialog.altText #altTextContainer #addDescription .descriptionArea textarea{
font:inherit;
width:100%; width:100%;
min-height:75px; min-height:75px;
padding:8px;
resize:none;
margin:0;
box-sizing:border-box;
border-radius:4px;
border:1px solid var(--textarea-border-color);
background:var(--textarea-bg-color);
color:var(--textarea-fg-color);
} }
#altTextDialog #altTextContainer #addDescription .descriptionArea textarea:focus{ .dialog.altText #altTextContainer #buttons{
outline-offset:0;
border-color:transparent;
}
#altTextDialog #altTextContainer #addDescription .descriptionArea textarea:disabled{
pointer-events:none;
opacity:0.4;
}
#altTextDialog #altTextContainer #buttons{
display:flex; display:flex;
justify-content:flex-end; justify-content:flex-end;
align-items:flex-start; align-items:flex-start;
@ -2201,46 +2244,6 @@
align-self:stretch; align-self:stretch;
} }
#altTextDialog #altTextContainer #buttons button{
border-radius:4px;
border:1px solid;
font:menu;
font-weight:600;
padding:4px 16px;
width:auto;
height:32px;
}
#altTextDialog #altTextContainer #buttons button:hover{
cursor:pointer;
filter:var(--hover-filter);
}
#altTextDialog #altTextContainer #buttons button#altTextCancel{
color:var(--button-cancel-fg-color);
background-color:var(--button-cancel-bg-color);
border-color:var(--button-cancel-border-color);
}
#altTextDialog #altTextContainer #buttons button#altTextCancel:hover{
color:var(--button-cancel-hover-fg-color);
background-color:var(--button-cancel-hover-bg-color);
border-color:var(--button-cancel-hover-border-color);
}
#altTextDialog #altTextContainer #buttons button#altTextSave{
color:var(--button-save-hover-fg-color);
background-color:var(--button-save-hover-bg-color);
border-color:var(--button-save-hover-border-color);
opacity:1;
}
#altTextDialog #altTextContainer #buttons button#altTextSave:hover{
color:var(--button-save-hover-fg-color);
background-color:var(--button-save-hover-bg-color);
border-color:var(--button-save-hover-border-color);
}
.colorPicker{ .colorPicker{
--hover-outline-color:#0250bb; --hover-outline-color:#0250bb;
--selected-outline-color:#0060df; --selected-outline-color:#0060df;

View File

@ -8912,17 +8912,18 @@ class TextHighlighter {
class TextLayerBuilder { class TextLayerBuilder {
#enablePermissions = false; #enablePermissions = false;
#onAppend = null; #onAppend = null;
#textContentSource = null; #renderingDone = false;
#textLayer = null; #textLayer = null;
static #textLayers = new Map(); static #textLayers = new Map();
static #selectionChangeAbortController = null; static #selectionChangeAbortController = null;
constructor({ constructor({
pdfPage,
highlighter = null, highlighter = null,
accessibilityManager = null, accessibilityManager = null,
enablePermissions = false, enablePermissions = false,
onAppend = null onAppend = null
}) { }) {
this.renderingDone = false; this.pdfPage = pdfPage;
this.highlighter = highlighter; this.highlighter = highlighter;
this.accessibilityManager = accessibilityManager; this.accessibilityManager = accessibilityManager;
this.#enablePermissions = enablePermissions === true; this.#enablePermissions = enablePermissions === true;
@ -8932,17 +8933,14 @@ class TextLayerBuilder {
this.div.className = "textLayer"; this.div.className = "textLayer";
} }
#finishRendering() { #finishRendering() {
this.renderingDone = true; this.#renderingDone = true;
const endOfContent = document.createElement("div"); const endOfContent = document.createElement("div");
endOfContent.className = "endOfContent"; endOfContent.className = "endOfContent";
this.div.append(endOfContent); this.div.append(endOfContent);
this.#bindMouse(endOfContent); this.#bindMouse(endOfContent);
} }
async render(viewport) { async render(viewport, textContentParams = null) {
if (!this.#textContentSource) { if (this.#renderingDone && this.#textLayer) {
throw new Error('No "textContentSource" parameter specified.');
}
if (this.renderingDone && this.#textLayer) {
this.#textLayer.update({ this.#textLayer.update({
viewport, viewport,
onBefore: this.hide.bind(this) onBefore: this.hide.bind(this)
@ -8952,7 +8950,10 @@ class TextLayerBuilder {
} }
this.cancel(); this.cancel();
this.#textLayer = new TextLayer({ this.#textLayer = new TextLayer({
textContentSource: this.#textContentSource, textContentSource: this.pdfPage.streamTextContent(textContentParams || {
includeMarkedContent: true,
disableNormalization: true
}),
container: this.div, container: this.div,
viewport viewport
}); });
@ -8969,13 +8970,13 @@ class TextLayerBuilder {
this.accessibilityManager?.enable(); this.accessibilityManager?.enable();
} }
hide() { hide() {
if (!this.div.hidden && this.renderingDone) { if (!this.div.hidden && this.#renderingDone) {
this.highlighter?.disable(); this.highlighter?.disable();
this.div.hidden = true; this.div.hidden = true;
} }
} }
show() { show() {
if (this.div.hidden && this.renderingDone) { if (this.div.hidden && this.#renderingDone) {
this.div.hidden = false; this.div.hidden = false;
this.highlighter?.enable(); this.highlighter?.enable();
} }
@ -8987,10 +8988,6 @@ class TextLayerBuilder {
this.accessibilityManager?.disable(); this.accessibilityManager?.disable();
TextLayerBuilder.#removeGlobalSelectionListener(this.div); TextLayerBuilder.#removeGlobalSelectionListener(this.div);
} }
setTextContentSource(source) {
this.cancel();
this.#textContentSource = source;
}
#bindMouse(end) { #bindMouse(end) {
const { const {
div div
@ -9261,6 +9258,13 @@ class PDFPageView {
findController: this.#layerProperties.findController findController: this.#layerProperties.findController
})); }));
} }
#dispatchLayerRendered(name, error) {
this.eventBus.dispatch(name, {
source: this,
pageNumber: this.id,
error
});
}
async #renderAnnotationLayer() { async #renderAnnotationLayer() {
let error = null; let error = null;
try { try {
@ -9269,11 +9273,7 @@ class PDFPageView {
console.error(`#renderAnnotationLayer: "${ex}".`); console.error(`#renderAnnotationLayer: "${ex}".`);
error = ex; error = ex;
} finally { } finally {
this.eventBus.dispatch("annotationlayerrendered", { this.#dispatchLayerRendered("annotationlayerrendered", error);
source: this,
pageNumber: this.id,
error
});
} }
} }
async #renderAnnotationEditorLayer() { async #renderAnnotationEditorLayer() {
@ -9284,11 +9284,7 @@ class PDFPageView {
console.error(`#renderAnnotationEditorLayer: "${ex}".`); console.error(`#renderAnnotationEditorLayer: "${ex}".`);
error = ex; error = ex;
} finally { } finally {
this.eventBus.dispatch("annotationeditorlayerrendered", { this.#dispatchLayerRendered("annotationeditorlayerrendered", error);
source: this,
pageNumber: this.id,
error
});
} }
} }
async #renderDrawLayer() { async #renderDrawLayer() {
@ -9314,32 +9310,16 @@ class PDFPageView {
this.#addLayer(this.xfaLayer.div, "xfaLayer"); this.#addLayer(this.xfaLayer.div, "xfaLayer");
this.l10n.resume(); this.l10n.resume();
} }
this.eventBus.dispatch("xfalayerrendered", { this.#dispatchLayerRendered("xfalayerrendered", error);
source: this,
pageNumber: this.id,
error
});
} }
} }
async #renderTextLayer() { async #renderTextLayer() {
const { if (!this.textLayer) {
pdfPage,
textLayer,
viewport
} = this;
if (!textLayer) {
return; return;
} }
let error = null; let error = null;
try { try {
if (!textLayer.renderingDone) { await this.textLayer.render(this.viewport);
const readableStream = pdfPage.streamTextContent({
includeMarkedContent: true,
disableNormalization: true
});
textLayer.setTextContentSource(readableStream);
}
await textLayer.render(viewport);
} catch (ex) { } catch (ex) {
if (ex instanceof AbortException) { if (ex instanceof AbortException) {
return; return;
@ -9347,11 +9327,7 @@ class PDFPageView {
console.error(`#renderTextLayer: "${ex}".`); console.error(`#renderTextLayer: "${ex}".`);
error = ex; error = ex;
} }
this.eventBus.dispatch("textlayerrendered", { this.#dispatchLayerRendered("textlayerrendered", error);
source: this,
pageNumber: this.id,
error
});
this.#renderStructTreeLayer(); this.#renderStructTreeLayer();
} }
async #renderStructTreeLayer() { async #renderStructTreeLayer() {
@ -9694,6 +9670,7 @@ class PDFPageView {
if (!this.textLayer && this.#textLayerMode !== TextLayerMode.DISABLE && !pdfPage.isPureXfa) { if (!this.textLayer && this.#textLayerMode !== TextLayerMode.DISABLE && !pdfPage.isPureXfa) {
this._accessibilityManager ||= new TextAccessibilityManager(); this._accessibilityManager ||= new TextAccessibilityManager();
this.textLayer = new TextLayerBuilder({ this.textLayer = new TextLayerBuilder({
pdfPage,
highlighter: this._textHighlighter, highlighter: this._textHighlighter,
accessibilityManager: this._accessibilityManager, accessibilityManager: this._accessibilityManager,
enablePermissions: this.#textLayerMode === TextLayerMode.ENABLE_PERMISSIONS, enablePermissions: this.#textLayerMode === TextLayerMode.ENABLE_PERMISSIONS,
@ -9801,7 +9778,7 @@ class PDFPageView {
annotationCanvasMap: this._annotationCanvasMap, annotationCanvasMap: this._annotationCanvasMap,
pageColors pageColors
}; };
const renderTask = this.renderTask = this.pdfPage.render(renderContext); const renderTask = this.renderTask = pdfPage.render(renderContext);
renderTask.onContinue = renderContinueCallback; renderTask.onContinue = renderContinueCallback;
const resultPromise = renderTask.promise.then(async () => { const resultPromise = renderTask.promise.then(async () => {
showCanvas?.(true); showCanvas?.(true);
@ -9969,7 +9946,7 @@ class PDFViewer {
#scaleTimeoutId = null; #scaleTimeoutId = null;
#textLayerMode = TextLayerMode.ENABLE; #textLayerMode = TextLayerMode.ENABLE;
constructor(options) { constructor(options) {
const viewerVersion = "4.3.118"; const viewerVersion = "4.3.136";
if (version !== viewerVersion) { if (version !== viewerVersion) {
throw new Error(`The API version "${version}" does not match the Viewer version "${viewerVersion}".`); throw new Error(`The API version "${version}" does not match the Viewer version "${viewerVersion}".`);
} }
@ -10634,7 +10611,8 @@ class PDFViewer {
#setScaleUpdatePages(newScale, newValue, { #setScaleUpdatePages(newScale, newValue, {
noScroll = false, noScroll = false,
preset = false, preset = false,
drawingDelay = -1 drawingDelay = -1,
origin = null
}) { }) {
this._currentScaleValue = newValue.toString(); this._currentScaleValue = newValue.toString();
if (this.#isSameScale(newScale)) { if (this.#isSameScale(newScale)) {
@ -10659,6 +10637,7 @@ class PDFViewer {
this.refresh(); this.refresh();
}, drawingDelay); }, drawingDelay);
} }
const previousScale = this._currentScale;
this._currentScale = newScale; this._currentScale = newScale;
if (!noScroll) { if (!noScroll) {
let page = this._currentPageNumber, let page = this._currentPageNumber,
@ -10674,6 +10653,12 @@ class PDFViewer {
destArray: dest, destArray: dest,
allowNegativeOffset: true allowNegativeOffset: true
}); });
if (Array.isArray(origin)) {
const scaleDiff = newScale / previousScale - 1;
const [top, left] = this.containerTopLeft;
this.container.scrollLeft += (origin[0] - left) * scaleDiff;
this.container.scrollTop += (origin[1] - top) * scaleDiff;
}
} }
this.eventBus.dispatch("scalechanging", { this.eventBus.dispatch("scalechanging", {
source: this, source: this,
@ -11281,48 +11266,46 @@ class PDFViewer {
this.currentPageNumber = Math.max(currentPageNumber - advance, 1); this.currentPageNumber = Math.max(currentPageNumber - advance, 1);
return true; return true;
} }
increaseScale({ updateScale({
drawingDelay, drawingDelay,
scaleFactor, scaleFactor = null,
steps steps = null,
} = {}) { origin
}) {
if (steps === null && scaleFactor === null) {
throw new Error("Invalid updateScale options: either `steps` or `scaleFactor` must be provided.");
}
if (!this.pdfDocument) { if (!this.pdfDocument) {
return; return;
} }
let newScale = this._currentScale; let newScale = this._currentScale;
if (scaleFactor > 1) { if (scaleFactor > 0 && scaleFactor !== 1) {
newScale = Math.round(newScale * scaleFactor * 100) / 100; newScale = Math.round(newScale * scaleFactor * 100) / 100;
} else { } else if (steps) {
steps ??= 1; const delta = steps > 0 ? DEFAULT_SCALE_DELTA : 1 / DEFAULT_SCALE_DELTA;
const round = steps > 0 ? Math.ceil : Math.floor;
steps = Math.abs(steps);
do { do {
newScale = Math.ceil((newScale * DEFAULT_SCALE_DELTA).toFixed(2) * 10) / 10; newScale = round((newScale * delta).toFixed(2) * 10) / 10;
} while (--steps > 0 && newScale < MAX_SCALE); } while (--steps > 0);
} }
this.#setScale(Math.min(MAX_SCALE, newScale), { newScale = Math.max(MIN_SCALE, Math.min(MAX_SCALE, newScale));
this.#setScale(newScale, {
noScroll: false, noScroll: false,
drawingDelay drawingDelay,
origin
}); });
} }
decreaseScale({ increaseScale(options = {}) {
drawingDelay, this.updateScale({
scaleFactor, ...options,
steps steps: options.steps ?? 1
} = {}) { });
if (!this.pdfDocument) { }
return; decreaseScale(options = {}) {
} this.updateScale({
let newScale = this._currentScale; ...options,
if (scaleFactor > 0 && scaleFactor < 1) { steps: -(options.steps ?? 1)
newScale = Math.round(newScale * scaleFactor * 100) / 100;
} else {
steps ??= 1;
do {
newScale = Math.floor((newScale / DEFAULT_SCALE_DELTA).toFixed(2) * 10) / 10;
} while (--steps > 0 && newScale > MIN_SCALE);
}
this.#setScale(Math.max(MIN_SCALE, newScale), {
noScroll: false,
drawingDelay
}); });
} }
#updateContainerHeightCss(height = this.container.clientHeight) { #updateContainerHeightCss(height = this.container.clientHeight) {
@ -12465,25 +12448,22 @@ const PDFViewerApplication = {
get initializedPromise() { get initializedPromise() {
return this._initializedCapability.promise; return this._initializedCapability.promise;
}, },
zoomIn(steps, scaleFactor) { updateZoom(steps, scaleFactor, origin) {
if (this.pdfViewer.isInPresentationMode) { if (this.pdfViewer.isInPresentationMode) {
return; return;
} }
this.pdfViewer.increaseScale({ this.pdfViewer.updateScale({
drawingDelay: AppOptions.get("defaultZoomDelay"), drawingDelay: AppOptions.get("defaultZoomDelay"),
steps, steps,
scaleFactor scaleFactor,
origin
}); });
}, },
zoomOut(steps, scaleFactor) { zoomIn() {
if (this.pdfViewer.isInPresentationMode) { this.updateZoom(1);
return; },
} zoomOut() {
this.pdfViewer.decreaseScale({ this.updateZoom(-1);
drawingDelay: AppOptions.get("defaultZoomDelay"),
steps,
scaleFactor
});
}, },
zoomReset() { zoomReset() {
if (this.pdfViewer.isInPresentationMode) { if (this.pdfViewer.isInPresentationMode) {
@ -13510,17 +13490,6 @@ const PDFViewerApplication = {
this[prop] = factor / newFactor; this[prop] = factor / newFactor;
return newFactor; return newFactor;
}, },
_centerAtPos(previousScale, x, y) {
const {
pdfViewer
} = this;
const scaleDiff = pdfViewer.currentScale / previousScale - 1;
if (scaleDiff !== 0) {
const [top, left] = pdfViewer.containerTopLeft;
pdfViewer.container.scrollLeft += (x - left) * scaleDiff;
pdfViewer.container.scrollTop += (y - top) * scaleDiff;
}
},
_unblockDocumentLoadEvent() { _unblockDocumentLoadEvent() {
document.blockUnblockOnload?.(false); document.blockUnblockOnload?.(false);
this._unblockDocumentLoadEvent = () => {}; this._unblockDocumentLoadEvent = () => {};
@ -13866,21 +13835,15 @@ function webViewerWheel(evt) {
let scaleFactor = Math.exp(-evt.deltaY / 100); let scaleFactor = Math.exp(-evt.deltaY / 100);
const isBuiltInMac = false; const isBuiltInMac = false;
const isPinchToZoom = evt.ctrlKey && !PDFViewerApplication._isCtrlKeyDown && deltaMode === WheelEvent.DOM_DELTA_PIXEL && evt.deltaX === 0 && (Math.abs(scaleFactor - 1) < 0.05 || isBuiltInMac) && evt.deltaZ === 0; const isPinchToZoom = evt.ctrlKey && !PDFViewerApplication._isCtrlKeyDown && deltaMode === WheelEvent.DOM_DELTA_PIXEL && evt.deltaX === 0 && (Math.abs(scaleFactor - 1) < 0.05 || isBuiltInMac) && evt.deltaZ === 0;
const origin = [evt.clientX, evt.clientY];
if (isPinchToZoom || evt.ctrlKey && supportsMouseWheelZoomCtrlKey || evt.metaKey && supportsMouseWheelZoomMetaKey) { if (isPinchToZoom || evt.ctrlKey && supportsMouseWheelZoomCtrlKey || evt.metaKey && supportsMouseWheelZoomMetaKey) {
evt.preventDefault(); evt.preventDefault();
if (PDFViewerApplication._isScrolling || zoomDisabledTimeout || document.visibilityState === "hidden" || PDFViewerApplication.overlayManager.active) { if (PDFViewerApplication._isScrolling || zoomDisabledTimeout || document.visibilityState === "hidden" || PDFViewerApplication.overlayManager.active) {
return; return;
} }
const previousScale = pdfViewer.currentScale;
if (isPinchToZoom && supportsPinchToZoom) { if (isPinchToZoom && supportsPinchToZoom) {
scaleFactor = PDFViewerApplication._accumulateFactor(previousScale, scaleFactor, "_wheelUnusedFactor"); scaleFactor = PDFViewerApplication._accumulateFactor(pdfViewer.currentScale, scaleFactor, "_wheelUnusedFactor");
if (scaleFactor < 1) { PDFViewerApplication.updateZoom(null, scaleFactor, origin);
PDFViewerApplication.zoomOut(null, scaleFactor);
} else if (scaleFactor > 1) {
PDFViewerApplication.zoomIn(null, scaleFactor);
} else {
return;
}
} else { } else {
const delta = normalizeWheelEventDirection(evt); const delta = normalizeWheelEventDirection(evt);
let ticks = 0; let ticks = 0;
@ -13894,15 +13857,8 @@ function webViewerWheel(evt) {
const PIXELS_PER_LINE_SCALE = 30; const PIXELS_PER_LINE_SCALE = 30;
ticks = PDFViewerApplication._accumulateTicks(delta / PIXELS_PER_LINE_SCALE, "_wheelUnusedTicks"); ticks = PDFViewerApplication._accumulateTicks(delta / PIXELS_PER_LINE_SCALE, "_wheelUnusedTicks");
} }
if (ticks < 0) { PDFViewerApplication.updateZoom(ticks, null, origin);
PDFViewerApplication.zoomOut(-ticks);
} else if (ticks > 0) {
PDFViewerApplication.zoomIn(ticks);
} else {
return;
}
} }
PDFViewerApplication._centerAtPos(previousScale, evt.clientX, evt.clientY);
} }
} }
function webViewerTouchStart(evt) { function webViewerTouchStart(evt) {
@ -13988,30 +13944,17 @@ function webViewerTouchMove(evt) {
} }
} }
evt.preventDefault(); evt.preventDefault();
const origin = [(page0X + page1X) / 2, (page0Y + page1Y) / 2];
const distance = Math.hypot(page0X - page1X, page0Y - page1Y) || 1; const distance = Math.hypot(page0X - page1X, page0Y - page1Y) || 1;
const pDistance = Math.hypot(pTouch0X - pTouch1X, pTouch0Y - pTouch1Y) || 1; const pDistance = Math.hypot(pTouch0X - pTouch1X, pTouch0Y - pTouch1Y) || 1;
const previousScale = pdfViewer.currentScale;
if (supportsPinchToZoom) { if (supportsPinchToZoom) {
const newScaleFactor = PDFViewerApplication._accumulateFactor(previousScale, distance / pDistance, "_touchUnusedFactor"); const newScaleFactor = PDFViewerApplication._accumulateFactor(pdfViewer.currentScale, distance / pDistance, "_touchUnusedFactor");
if (newScaleFactor < 1) { PDFViewerApplication.updateZoom(null, newScaleFactor, origin);
PDFViewerApplication.zoomOut(null, newScaleFactor);
} else if (newScaleFactor > 1) {
PDFViewerApplication.zoomIn(null, newScaleFactor);
} else {
return;
}
} else { } else {
const PIXELS_PER_LINE_SCALE = 30; const PIXELS_PER_LINE_SCALE = 30;
const ticks = PDFViewerApplication._accumulateTicks((distance - pDistance) / PIXELS_PER_LINE_SCALE, "_touchUnusedTicks"); const ticks = PDFViewerApplication._accumulateTicks((distance - pDistance) / PIXELS_PER_LINE_SCALE, "_touchUnusedTicks");
if (ticks < 0) { PDFViewerApplication.updateZoom(ticks, null, origin);
PDFViewerApplication.zoomOut(-ticks);
} else if (ticks > 0) {
PDFViewerApplication.zoomIn(ticks);
} else {
return;
}
} }
PDFViewerApplication._centerAtPos(previousScale, (page0X + page1X) / 2, (page0Y + page1Y) / 2);
} }
function webViewerTouchEnd(evt) { function webViewerTouchEnd(evt) {
if (!PDFViewerApplication._touchInfo) { if (!PDFViewerApplication._touchInfo) {
@ -14329,8 +14272,8 @@ function webViewerReportTelemetry({
const pdfjsVersion = "4.3.118"; const pdfjsVersion = "4.3.136";
const pdfjsBuild = "17e09e547"; const pdfjsBuild = "0cec64437";
const AppConstants = { const AppConstants = {
LinkTarget: LinkTarget, LinkTarget: LinkTarget,
RenderingStates: RenderingStates, RenderingStates: RenderingStates,
@ -14465,7 +14408,7 @@ function getViewerConfiguration() {
editorFreeHighlightThickness: document.getElementById("editorFreeHighlightThickness"), editorFreeHighlightThickness: document.getElementById("editorFreeHighlightThickness"),
editorHighlightShowAll: document.getElementById("editorHighlightShowAll") editorHighlightShowAll: document.getElementById("editorHighlightShowAll")
}, },
printContainer: document.getElementById("printContainer"), printContainer: document.getElementById("printContainer")
}; };
} }
function webViewerLoad() { function webViewerLoad() {

File diff suppressed because one or more lines are too long

View File

@ -10256,7 +10256,6 @@ class TextLayer {
this.#pageWidth = pageWidth; this.#pageWidth = pageWidth;
this.#pageHeight = pageHeight; this.#pageHeight = pageHeight;
setLayerDimensions(container, viewport); setLayerDimensions(container, viewport);
TextLayer.#pendingTextLayers.add(this);
this.#capability.promise.catch(() => {}).then(() => { this.#capability.promise.catch(() => {}).then(() => {
TextLayer.#pendingTextLayers.delete(this); TextLayer.#pendingTextLayers.delete(this);
this.#layoutTextParams = null; this.#layoutTextParams = null;
@ -10280,6 +10279,7 @@ class TextLayer {
}, this.#capability.reject); }, this.#capability.reject);
}; };
this.#reader = this.#textContentSource.getReader(); this.#reader = this.#textContentSource.getReader();
TextLayer.#pendingTextLayers.add(this);
pump(); pump();
return this.#capability.promise; return this.#capability.promise;
} }
@ -10724,7 +10724,7 @@ function getDocument(src) {
} }
const docParams = { const docParams = {
docId, docId,
apiVersion: "4.3.118", apiVersion: "4.3.136",
data, data,
password, password,
disableAutoFetch, disableAutoFetch,
@ -12491,8 +12491,8 @@ class InternalRenderTask {
} }
} }
} }
const version = "4.3.118"; const version = "4.3.136";
const build = "17e09e547"; const build = "0cec64437";
;// CONCATENATED MODULE: ./src/shared/scripting_utils.js ;// CONCATENATED MODULE: ./src/shared/scripting_utils.js
function makeColorComp(n) { function makeColorComp(n) {
@ -19367,8 +19367,8 @@ class DrawLayer {
const pdfjsVersion = "4.3.118"; const pdfjsVersion = "4.3.136";
const pdfjsBuild = "17e09e547"; const pdfjsBuild = "0cec64437";
var __webpack_exports__AbortException = __webpack_exports__.AbortException; var __webpack_exports__AbortException = __webpack_exports__.AbortException;
var __webpack_exports__AnnotationEditorLayer = __webpack_exports__.AnnotationEditorLayer; var __webpack_exports__AnnotationEditorLayer = __webpack_exports__.AnnotationEditorLayer;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -8930,11 +8930,10 @@ class Parser {
if (this.tryShift() && isCmd(this.buf2, "endstream")) { if (this.tryShift() && isCmd(this.buf2, "endstream")) {
this.shift(); this.shift();
} else { } else {
const actualLength = this.#findStreamLength(startPos); length = this.#findStreamLength(startPos);
if (actualLength < 0) { if (length < 0) {
throw new FormatError("Missing endstream command."); throw new FormatError("Missing endstream command.");
} }
length = actualLength;
lexer.nextChar(); lexer.nextChar();
this.shift(); this.shift();
this.shift(); this.shift();
@ -29696,7 +29695,7 @@ class PartialEvaluator {
this.globalImageCache = globalImageCache; this.globalImageCache = globalImageCache;
this.systemFontCache = systemFontCache; this.systemFontCache = systemFontCache;
this.options = options || DefaultPartialEvaluatorOptions; this.options = options || DefaultPartialEvaluatorOptions;
this.parsingType3Font = false; this.type3FontRefs = null;
this._regionalImageCache = new RegionalImageCache(); this._regionalImageCache = new RegionalImageCache();
this._fetchBuiltInCMapBound = this.fetchBuiltInCMap.bind(this); this._fetchBuiltInCMapBound = this.fetchBuiltInCMap.bind(this);
ImageResizer.setMaxArea(this.options.canvasMaxAreaInBytes); ImageResizer.setMaxArea(this.options.canvasMaxAreaInBytes);
@ -29708,6 +29707,9 @@ class PartialEvaluator {
}); });
return shadow(this, "_pdfFunctionFactory", pdfFunctionFactory); return shadow(this, "_pdfFunctionFactory", pdfFunctionFactory);
} }
get parsingType3Font() {
return !!this.type3FontRefs;
}
clone(newOptions = null) { clone(newOptions = null) {
const newEvaluator = Object.create(this); const newEvaluator = Object.create(this);
newEvaluator.options = Object.assign(Object.create(null), this.options, newOptions); newEvaluator.options = Object.assign(Object.create(null), this.options, newOptions);
@ -30396,7 +30398,7 @@ class PartialEvaluator {
} }
} }
if (fontRef) { if (fontRef) {
if (this.parsingType3Font && this.type3FontRefs.has(fontRef)) { if (this.type3FontRefs?.has(fontRef)) {
return errorFont(); return errorFont();
} }
if (this.fontCache.has(fontRef)) { if (this.fontCache.has(fontRef)) {
@ -32831,7 +32833,6 @@ class TranslatedFont {
const type3Evaluator = evaluator.clone({ const type3Evaluator = evaluator.clone({
ignoreErrors: false ignoreErrors: false
}); });
type3Evaluator.parsingType3Font = true;
const type3FontRefs = new RefSet(evaluator.type3FontRefs); const type3FontRefs = new RefSet(evaluator.type3FontRefs);
if (this.dict.objId && !type3FontRefs.has(this.dict.objId)) { if (this.dict.objId && !type3FontRefs.has(this.dict.objId)) {
type3FontRefs.put(this.dict.objId); type3FontRefs.put(this.dict.objId);
@ -53722,52 +53723,49 @@ class Page {
systemFontCache: this.systemFontCache, systemFontCache: this.systemFontCache,
options: this.evaluatorOptions options: this.evaluatorOptions
}); });
const newAnnotationsByPage = !this.xfaFactory ? getNewAnnotationsMap(annotationStorage) : null; const newAnnotsByPage = !this.xfaFactory ? getNewAnnotationsMap(annotationStorage) : null;
let deletedAnnotations = null; const newAnnots = newAnnotsByPage?.get(this.pageIndex);
let newAnnotationsPromise = Promise.resolve(null); let newAnnotationsPromise = Promise.resolve(null);
if (newAnnotationsByPage) { let deletedAnnotations = null;
const newAnnotations = newAnnotationsByPage.get(this.pageIndex); if (newAnnots) {
if (newAnnotations) { const annotationGlobalsPromise = this.pdfManager.ensureDoc("annotationGlobals");
const annotationGlobalsPromise = this.pdfManager.ensureDoc("annotationGlobals"); let imagePromises;
let imagePromises; const missingBitmaps = new Set();
const missingBitmaps = new Set(); for (const {
for (const { bitmapId,
bitmapId, bitmap
bitmap } of newAnnots) {
} of newAnnotations) { if (bitmapId && !bitmap && !missingBitmaps.has(bitmapId)) {
if (bitmapId && !bitmap && !missingBitmaps.has(bitmapId)) { missingBitmaps.add(bitmapId);
missingBitmaps.add(bitmapId);
}
} }
const {
isOffscreenCanvasSupported
} = this.evaluatorOptions;
if (missingBitmaps.size > 0) {
const annotationWithBitmaps = newAnnotations.slice();
for (const [key, annotation] of annotationStorage) {
if (!key.startsWith(AnnotationEditorPrefix)) {
continue;
}
if (annotation.bitmap && missingBitmaps.has(annotation.bitmapId)) {
annotationWithBitmaps.push(annotation);
}
}
imagePromises = AnnotationFactory.generateImages(annotationWithBitmaps, this.xref, isOffscreenCanvasSupported);
} else {
imagePromises = AnnotationFactory.generateImages(newAnnotations, this.xref, isOffscreenCanvasSupported);
}
deletedAnnotations = new RefSet();
this.#replaceIdByRef(newAnnotations, deletedAnnotations, null);
newAnnotationsPromise = annotationGlobalsPromise.then(annotationGlobals => {
if (!annotationGlobals) {
return null;
}
return AnnotationFactory.printNewAnnotations(annotationGlobals, partialEvaluator, task, newAnnotations, imagePromises);
});
} }
const {
isOffscreenCanvasSupported
} = this.evaluatorOptions;
if (missingBitmaps.size > 0) {
const annotationWithBitmaps = newAnnots.slice();
for (const [key, annotation] of annotationStorage) {
if (!key.startsWith(AnnotationEditorPrefix)) {
continue;
}
if (annotation.bitmap && missingBitmaps.has(annotation.bitmapId)) {
annotationWithBitmaps.push(annotation);
}
}
imagePromises = AnnotationFactory.generateImages(annotationWithBitmaps, this.xref, isOffscreenCanvasSupported);
} else {
imagePromises = AnnotationFactory.generateImages(newAnnots, this.xref, isOffscreenCanvasSupported);
}
deletedAnnotations = new RefSet();
this.#replaceIdByRef(newAnnots, deletedAnnotations, null);
newAnnotationsPromise = annotationGlobalsPromise.then(annotationGlobals => {
if (!annotationGlobals) {
return null;
}
return AnnotationFactory.printNewAnnotations(annotationGlobals, partialEvaluator, task, newAnnots, imagePromises);
});
} }
const dataPromises = Promise.all([contentStreamPromise, resourcesPromise]); const pageListPromise = Promise.all([contentStreamPromise, resourcesPromise]).then(([contentStream]) => {
const pageListPromise = dataPromises.then(([contentStream]) => {
const opList = new OperatorList(intent, sink); const opList = new OperatorList(intent, sink);
handler.send("StartRenderPage", { handler.send("StartRenderPage", {
transparency: partialEvaluator.hasBlendModes(this.resources, this.nonBlendModesSet), transparency: partialEvaluator.hasBlendModes(this.resources, this.nonBlendModesSet),
@ -55532,7 +55530,7 @@ class WorkerMessageHandler {
docId, docId,
apiVersion apiVersion
} = docParams; } = docParams;
const workerVersion = "4.3.118"; const workerVersion = "4.3.136";
if (apiVersion !== workerVersion) { if (apiVersion !== workerVersion) {
throw new Error(`The API version "${apiVersion}" does not match ` + `the Worker version "${workerVersion}".`); throw new Error(`The API version "${apiVersion}" does not match ` + `the Worker version "${workerVersion}".`);
} }
@ -56102,8 +56100,8 @@ if (typeof window === "undefined" && !isNodeJS && typeof self !== "undefined" &&
;// CONCATENATED MODULE: ./src/pdf.worker.js ;// CONCATENATED MODULE: ./src/pdf.worker.js
const pdfjsVersion = "4.3.118"; const pdfjsVersion = "4.3.136";
const pdfjsBuild = "17e09e547"; const pdfjsBuild = "0cec64437";
var __webpack_exports__WorkerMessageHandler = __webpack_exports__.WorkerMessageHandler; var __webpack_exports__WorkerMessageHandler = __webpack_exports__.WorkerMessageHandler;
export { __webpack_exports__WorkerMessageHandler as WorkerMessageHandler }; export { __webpack_exports__WorkerMessageHandler as WorkerMessageHandler };

File diff suppressed because one or more lines are too long

View File

@ -12,7 +12,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-9"> <div class="col-md-9 bg-card">
<!-- User Settings Title --> <!-- User Settings Title -->
<h2 class="text-center" th:text="#{account.accountSettings}">User Settings</h2> <h2 class="text-center" th:text="#{account.accountSettings}">User Settings</h2>
@ -33,15 +33,15 @@
<!-- Change Username Form --> <!-- Change Username Form -->
<th:block th:if="${!oAuth2Login}"> <th:block th:if="${!oAuth2Login}">
<h4 th:text="#{account.changeUsername}">Change Username?</h4> <h4 th:text="#{account.changeUsername}">Change Username?</h4>
<form id="formsavechangeusername" class="bg-card mt-4 mb-4" action="api/v1/user/change-username" method="post"> <form id="formsavechangeusername" class="bg-card mt-4 mb-4" th:action="@{'/api/v1/user/change-username'}" method="post">
<div class="mb-3"> <div class="mb-3">
<label for="newUsername" th:text="#{account.newUsername}">Change Username</label> <label for="newUsername" th:text="#{account.newUsername}">Change Username</label>
<input type="text" class="form-control" name="newUsername" id="newUsername" th:placeholder="#{account.newUsername}"> <input type="text" class="form-control" name="newUsername" id="newUsername" th:placeholder="#{account.newUsername}">
<span id="usernameError" style="display: none;" th:text="#{invalidUsernameMessage}">Invalid username!</span> <span id="usernameError" style="display: none;" th:text="#{invalidUsernameMessage}">Invalid username!</span>
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label for="currentPassword" th:text="#{password}">Password</label> <label for="currentPasswordChangeUsername" th:text="#{password}">Password</label>
<input type="password" class="form-control" name="currentPassword" id="currentPassword" th:placeholder="#{password}"> <input type="password" class="form-control" name="currentPasswordChangeUsername" id="currentPasswordChangeUsername" th:placeholder="#{password}">
</div> </div>
<div class="mb-3"> <div class="mb-3">
<button type="submit" class="btn btn-primary" th:text="#{account.changeUsername}">Change Username</button> <button type="submit" class="btn btn-primary" th:text="#{account.changeUsername}">Change Username</button>
@ -52,7 +52,7 @@
<!-- Change Password Form --> <!-- Change Password Form -->
<th:block th:if="${!oAuth2Login}"> <th:block th:if="${!oAuth2Login}">
<h4 th:text="#{account.changePassword}">Change Password?</h4> <h4 th:text="#{account.changePassword}">Change Password?</h4>
<form id="formsavechangepassword" class="bg-card mt-4 mb-4" action="api/v1/user/change-password" method="post"> <form id="formsavechangepassword" class="bg-card mt-4 mb-4" th:action="@{'/api/v1/user/change-password'}" method="post">
<div class="mb-3"> <div class="mb-3">
<label for="currentPassword" th:text="#{account.oldPassword}">Old Password</label> <label for="currentPassword" th:text="#{account.oldPassword}">Old Password</label>
<input type="password" class="form-control" name="currentPassword" id="currentPassword" th:placeholder="#{account.oldPassword}"> <input type="password" class="form-control" name="currentPassword" id="currentPassword" th:placeholder="#{account.oldPassword}">
@ -66,6 +66,7 @@
<input type="password" class="form-control" name="confirmNewPassword" id="confirmNewPassword" th:placeholder="#{account.confirmNewPassword}"> <input type="password" class="form-control" name="confirmNewPassword" id="confirmNewPassword" th:placeholder="#{account.confirmNewPassword}">
</div> </div>
<div class="mb-3"> <div class="mb-3">
<span id="confirmPasswordError" style="display: none;" th:text="#{confirmPasswordErrorMessage}">New Password and Confirm New Password must match.</span>
<button type="submit" class="btn btn-primary" th:text="#{account.changePassword}">Change Password</button> <button type="submit" class="btn btn-primary" th:text="#{account.changePassword}">Change Password</button>
</div> </div>
</form> </form>
@ -103,6 +104,9 @@
return this.optional(element) || /^[a-zA-Z0-9][a-zA-Z0-9@._+-]*[a-zA-Z0-9]$|^(?=.{1,64}@)[A-Za-z0-9]+(\.[A-Za-z0-9_+.-]+)*@[^-][A-Za-z0-9-]+(\.[A-Za-z0-9-]+)*(\.[A-Za-z]{2,})$/.test(value); return this.optional(element) || /^[a-zA-Z0-9][a-zA-Z0-9@._+-]*[a-zA-Z0-9]$|^(?=.{1,64}@)[A-Za-z0-9]+(\.[A-Za-z0-9_+.-]+)*@[^-][A-Za-z0-9-]+(\.[A-Za-z0-9-]+)*(\.[A-Za-z]{2,})$/.test(value);
}, /*[[#{invalidUsernameMessage}]]*/ "Invalid username format"); }, /*[[#{invalidUsernameMessage}]]*/ "Invalid username format");
$(document).ready(function() { $(document).ready(function() {
$.validator.addMethod("passwordMatch", function(value, element) {
return $('#newPassword').val() === $('#confirmNewPassword').val();
}, /*[[#{confirmPasswordErrorMessage}]]*/ "New Password and Confirm New Password must match.");
$('#formsavechangepassword').validate({ $('#formsavechangepassword').validate({
rules: { rules: {
currentPassword: { currentPassword: {
@ -112,17 +116,31 @@
required: true required: true
}, },
confirmNewPassword: { confirmNewPassword: {
required: true required: true,
passwordMatch: true
},
errorPlacement: function(error, element) {
if ($(element).attr("name") === "newPassword" || $(element).attr("name") === "confirmNewPassword") {
$("#confirmPasswordError").text(error.text()).show();
} else {
error.insertAfter(element);
}
},
success: function(label, element) {
if ($(element).attr("name") === "newPassword" || $(element).attr("name") === "confirmNewPassword") {
$("#confirmPasswordError").hide();
}
} }
} }
}); });
$('#formsavechangeusername').validate({ $('#formsavechangeusername').validate({
rules: { rules: {
newUsername: { newUsername: {
required: true, required: true,
usernamePattern: true usernamePattern: true
}, },
currentPassword: { currentPasswordChangeUsername: {
required: true required: true
} }
}, },
@ -144,32 +162,10 @@
} }
} }
}); });
$('#formsavechangepassword').on('submit', function(event) {
var newPassword = $('#newPassword').val();
var confirmNewPassword = $('#confirmNewPassword').val();
if (newPassword !== confirmNewPassword) {
alert('New Password and Confirm New Password must match.');
event.preventDefault();
}
});
$('#newUsername').on('input', function() {
var usernameInput = $(this);
var isValid = usernameInput[0].checkValidity();
var errorSpan = $('#usernameError');
if (isValid) {
usernameInput.removeClass('invalid').addClass('valid');
errorSpan.hide();
} else {
usernameInput.removeClass('valid').addClass('invalid');
errorSpan.show();
}
});
}); });
</script> </script>
<script> <script th:inline="javascript">
function copyToClipboard() { function copyToClipboard() {
const apiKeyElement = document.getElementById("apiKey"); const apiKeyElement = document.getElementById("apiKey");
apiKeyElement.select(); apiKeyElement.select();
@ -192,8 +188,12 @@
} }
document.addEventListener("DOMContentLoaded", async function() { document.addEventListener("DOMContentLoaded", async function() {
showApiKey();
try { try {
let response = await fetch('/api/v1/user/get-api-key', { method: 'POST' }); /*<![CDATA[*/
const urlGetApiKey = /*[[@{/api/v1/user/get-api-key}]]*/ "/api/v1/user/get-api-key";
/*]]>*/
let response = await fetch(urlGetApiKey, { method: 'POST' });
if (response.status === 200) { if (response.status === 200) {
let apiKey = await response.text(); let apiKey = await response.text();
manageUIState(apiKey); manageUIState(apiKey);
@ -207,7 +207,10 @@
async function refreshApiKey() { async function refreshApiKey() {
try { try {
let response = await fetch('/api/v1/user/update-api-key', { method: 'POST' }); /*<![CDATA[*/
const urlUpdateApiKey = /*[[@{/api/v1/user/update-api-key}]]*/ "/api/v1/user/update-api-key";
/*]]>*/
let response = await fetch(urlUpdateApiKey, { method: 'POST' });
if (response.status === 200) { if (response.status === 200) {
let apiKey = await response.text(); let apiKey = await response.text();
manageUIState(apiKey); manageUIState(apiKey);
@ -229,27 +232,13 @@
if (apiKey && apiKey.trim().length > 0) { if (apiKey && apiKey.trim().length > 0) {
apiKeyElement.value = apiKey; apiKeyElement.value = apiKey;
showBtn.disabled = false; showBtn.disabled = false;
copyBtn.disabled = true; copyBtn.disabled = false;
} else { } else {
apiKeyElement.value = ""; apiKeyElement.value = "";
showBtn.disabled = true; showBtn.disabled = true;
copyBtn.disabled = true; copyBtn.disabled = true;
} }
} }
document.addEventListener("DOMContentLoaded", function() {
const form = document.querySelector('form[action="api/v1/user/change-password"]');
form.addEventListener('submit', function(event) {
const newPassword = document.getElementById('newPassword').value;
const confirmNewPassword = document.getElementById('confirmNewPassword').value;
if (newPassword !== confirmNewPassword) {
alert('New Password and Confirm New Password must match.');
event.preventDefault(); // Prevent form submission
}
});
});
</script> </script>
<h4 th:text="#{account.syncTitle}">Sync browser settings with Account</h4> <h4 th:text="#{account.syncTitle}">Sync browser settings with Account</h4>
@ -315,9 +304,12 @@
}); });
document.getElementById('syncToAccount').addEventListener('click', function() { document.getElementById('syncToAccount').addEventListener('click', function() {
/*<![CDATA[*/
const urlUpdateUserSettings = /*[[@{/api/v1/user/updateUserSettings}]]*/ "/api/v1/user/updateUserSettings";
/*]]>*/
let form = document.createElement("form"); let form = document.createElement("form");
form.method = "POST"; form.method = "POST";
form.action = "api/v1/user/updateUserSettings"; // Your endpoint URL form.action = urlUpdateUserSettings; // Your endpoint URL
for (let i = 0; i < localStorage.length; i++) { for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i); const key = localStorage.key(i);

View File

@ -16,6 +16,16 @@
<!-- User Settings Title --> <!-- User Settings Title -->
<h2 class="text-center" th:text="#{adminUserSettings.header}">Admin User Control Settings</h2> <h2 class="text-center" th:text="#{adminUserSettings.header}">Admin User Control Settings</h2>
<div style="background: var(--md-sys-color-outline-variant);padding: .8rem; margin: 10px 0; border-radius: 2rem; text-align: center;">
<a href="#" data-bs-toggle="modal" data-bs-target="#addUserModal" class="btn btn-outline-info" th:title="#{adminUserSettings.addUser}">
<span class="material-symbols-rounded">person_add</span>
<span th:text="#{adminUserSettings.addUser}">Add New User</span>
</a>
<a href="#" data-bs-toggle="modal" data-bs-target="#changeUserRoleModal" class="btn btn-outline-info" th:title="#{adminUserSettings.changeUserRole}">
<span class="material-symbols-rounded">edit</span>
<span th:text="#{adminUserSettings.changeUserRole}">Change User's Role</span>
</a>
</div>
<div th:if="${deleteMessage}" class="alert alert-danger"> <div th:if="${deleteMessage}" class="alert alert-danger">
<span th:text="#{${deleteMessage}}">Message</span> <span th:text="#{${deleteMessage}}">Message</span>
</div> </div>
@ -30,55 +40,47 @@
</thead> </thead>
<tbody> <tbody>
<tr th:each="user : ${users}"> <tr th:each="user : ${users}">
<td th:text="${user.username}"></td> <td style="align-content: center;" th:text="${user.username}"></td>
<td th:text="#{${user.roleName}}"></td> <td style="align-content: center;" th:text="#{${user.roleName}}"></td>
<td> <td style="align-content: center;">
<form th:if="${user.username != currentUsername}" th:action="@{'/api/v1/user/admin/deleteUser/' + ${user.username}}" method="post"> <form th:if="${user.username != currentUsername}" th:action="@{'/api/v1/user/admin/deleteUser/' + ${user.username}}" method="post" onsubmit="return confirmDelete()">
<button class="btn btn-danger" type="submit" th:text="#{delete}">Delete</button> <button type="submit" th:title="#{adminUserSettings.deleteUser}" class="btn btn-info"><span class="material-symbols-rounded">person_remove</span></button>
</form> </form>
<script th:inline="javascript">
const confirm_text = /*[[#{adminUserSettings.confirmDeleteUser}]]*/ 'Should the user be deleted?';
function confirmDelete() {
return confirm(confirm_text);
}
</script>
<a th:if="${user.username == currentUsername}" th:href="@{'/account'}" class="btn btn-outline-info"><span class="material-symbols-rounded">edit</span></a>
</td> </td>
<td th:text="${user.authenticationType}"></td> <td style="align-content: center;" th:text="${user.authenticationType}"></td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
</div>
</div>
</div>
</div>
<h2 th:text="#{adminUserSettings.addUser}">Add New User</h2> <!-- change User role Modal start -->
<div th:if="${addMessage}" class="alert alert-danger"> <div class="modal fade" id="changeUserRoleModal" tabindex="-1" aria-labelledby="changeUserRoleModalLabel" aria-hidden="true">
<span th:text="#{${addMessage}}">Default message if not found</span> <div class="modal-dialog modal-dialog-centered" role="document">
</div> <div class="modal-content">
<button class="btn btn-outline-info" data-toggle="tooltip" data-placement="auto" th:title="#{adminUserSettings.usernameInfo}" th:text="#{help}">Help</button> <div class="modal-header">
<form id="formsaveuser" th:action="@{/api/v1/user/admin/saveUser}" method="post">
<div class="mb-3">
<label for="username" th:text="#{username}">Username</label>
<input type="text" class="form-control" name="username" id="username" th:title="#{adminUserSettings.usernameInfo}" required>
<span id="usernameError" style="display: none;" th:text="#{invalidUsernameMessage}">Invalid username!</span>
</div>
<div class="mb-3">
<label for="password" th:text="#{password}">Password</label>
<input type="password" class="form-control" name="password" required>
</div>
<div class="mb-3">
<label for="role" th:text="#{adminUserSettings.role}">Role</label>
<select name="role" class="form-control" required>
<option value="" disabled selected th:text="#{selectFillter}">-- Select --</option>
<option th:each="roleDetail : ${roleDetails}" th:value="${roleDetail.key}" th:text="#{${roleDetail.value}}">Role</option>
</select>
</div>
<div class="mb-3">
<input type="checkbox" class="form-check-input" id="forceChange" name="forceChange">
<label class="form-check-label" for="forceChange" th:text="#{adminUserSettings.forceChange}">Force user to change username/password on login</label>
</div>
<!-- Add other fields as required -->
<button type="submit" class="btn btn-primary" th:text="#{adminUserSettings.submit}">Save User</button>
</form>
<hr />
<h2 th:text="#{adminUserSettings.changeUserRole}">Change User's Role</h2> <h2 th:text="#{adminUserSettings.changeUserRole}">Change User's Role</h2>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close">
<span class="material-symbols-rounded">
close
</span>
</button>
</div>
<div class="modal-body">
<button class="btn btn-outline-info" data-toggle="tooltip" data-placement="auto" th:title="#{downgradeCurrentUserLongMessage}" th:text="#{help}">Help</button> <button class="btn btn-outline-info" data-toggle="tooltip" data-placement="auto" th:title="#{downgradeCurrentUserLongMessage}" th:text="#{help}">Help</button>
<div th:if="${changeMessage}" class="alert alert-danger"> <div th:if="${changeMessage}" class="alert alert-danger">
<span th:text="#{${changeMessage}}">Default message if not found</span> <span th:text="#{${changeMessage}}">Default message if not found</span>
</div> </div>
<form th:action="@{/api/v1/user/admin/changeRole}" method="post"> <form th:action="@{'/api/v1/user/admin/changeRole'}" method="post">
<div class="mb-3"> <div class="mb-3">
<label for="username" th:text="#{username}">Username</label> <label for="username" th:text="#{username}">Username</label>
<select name="username" class="form-control" required> <select name="username" class="form-control" required>
@ -98,9 +100,59 @@
<button type="submit" class="btn btn-primary" th:text="#{adminUserSettings.submit}">Save User</button> <button type="submit" class="btn btn-primary" th:text="#{adminUserSettings.submit}">Save User</button>
</form> </form>
</div> </div>
<div class="modal-footer"></div>
</div> </div>
</div> </div>
</div> </div>
<!-- change User role Modal end -->
<!-- Add User Modal start -->
<div class="modal fade" id="addUserModal" tabindex="-1" aria-labelledby="addUserModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="addUserModalLabel" th:text="#{adminUserSettings.addUser}">Add New User</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close">
<span class="material-symbols-rounded">
close
</span>
</button>
</div>
<div class="modal-body">
<div th:if="${addMessage}" class="alert alert-danger">
<span th:text="#{${addMessage}}">Default message if not found</span>
</div>
<button class="btn btn-outline-info" data-toggle="tooltip" data-placement="auto" th:title="#{adminUserSettings.usernameInfo}" th:text="#{help}">Help</button>
<form id="formsaveuser" th:action="@{'/api/v1/user/admin/saveUser'}" method="post">
<div class="mb-3">
<label for="username" th:text="#{username}">Username</label>
<input type="text" class="form-control" name="username" id="username" th:title="#{adminUserSettings.usernameInfo}" required>
<span id="usernameError" style="display: none;" th:text="#{invalidUsernameMessage}">Invalid username!</span>
</div>
<div class="mb-3">
<label for="password" th:text="#{password}">Password</label>
<input type="password" class="form-control" name="password" required>
</div>
<div class="mb-3">
<label for="role" th:text="#{adminUserSettings.role}">Role</label>
<select name="role" class="form-control" required>
<option value="" disabled selected th:text="#{selectFillter}">-- Select --</option>
<option th:each="roleDetail : ${roleDetails}" th:value="${roleDetail.key}" th:text="#{${roleDetail.value}}">Role</option>
</select>
</div>
<div class="form-check mb-3">
<input type="checkbox" class="form-check-input" id="forceChange" name="forceChange">
<label class="form-check-label" for="forceChange" th:text="#{adminUserSettings.forceChange}">Force user to change username/password on login</label>
</div>
<button type="submit" class="btn btn-primary" th:text="#{adminUserSettings.submit}">Save User</button>
</form>
</div>
<div class="modal-footer"></div>
</div>
</div>
</div>
<!-- Add User Modal end -->
<script th:inline="javascript"> <script th:inline="javascript">
jQuery.validator.addMethod("usernamePattern", function(value, element) { jQuery.validator.addMethod("usernamePattern", function(value, element) {
return this.optional(element) || /^[a-zA-Z0-9][a-zA-Z0-9@._+-]*[a-zA-Z0-9]$|^(?=.{1,64}@)[A-Za-z0-9]+(\.[A-Za-z0-9_+.-]+)*@[^-][A-Za-z0-9-]+(\.[A-Za-z0-9-]+)*(\.[A-Za-z]{2,})$/.test(value); return this.optional(element) || /^[a-zA-Z0-9][a-zA-Z0-9@._+-]*[a-zA-Z0-9]$|^(?=.{1,64}@)[A-Za-z0-9]+(\.[A-Za-z0-9_+.-]+)*@[^-][A-Za-z0-9-]+(\.[A-Za-z0-9-]+)*(\.[A-Za-z]{2,})$/.test(value);
@ -154,5 +206,27 @@
</script> </script>
<th:block th:insert="~{fragments/footer.html :: footer}"></th:block> <th:block th:insert="~{fragments/footer.html :: footer}"></th:block>
</div> </div>
<div th:if="${oAuth2Enabled}" class="modal fade" id="editUserModal" tabindex="-1" role="dialog" aria-labelledby="editUserModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="editUserModalLabel" th:text="#{login.ssoSignIn}"></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close">
<span class="material-symbols-rounded">
close
</span>
</button>
</div>
<div class="modal-body">
<div class="mb-3" th:each="provider : ${providerlist}">
<a th:href="@{|/oauth2/authorization/${provider.key}|}" th:text="${provider.value}" class="w-100 btn btn-lg btn-primary">OpenID Connect</a>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" th:text="#{close}"></button>
</div>
</div>
</div>
</div>
</body> </body>
</html> </html>

View File

@ -27,7 +27,7 @@
<!-- Change Username Form --> <!-- Change Username Form -->
<h4 th:text="#{changeCreds.changePassword}">Change password</h4> <h4 th:text="#{changeCreds.changePassword}">Change password</h4>
<form action="api/v1/user/change-password-on-login" method="post"> <form action="api/v1/user/change-password-on-login" method="post" id="formsavechangecreds">
<div class="mb-3"> <div class="mb-3">
<label for="currentPassword" th:text="#{changeCreds.oldPassword}">Old Password</label> <label for="currentPassword" th:text="#{changeCreds.oldPassword}">Old Password</label>
<input type="password" class="form-control" name="currentPassword" id="currentPassword" th:placeholder="#{changeCreds.oldPassword}"> <input type="password" class="form-control" name="currentPassword" id="currentPassword" th:placeholder="#{changeCreds.oldPassword}">
@ -41,20 +41,39 @@
<input type="password" class="form-control" name="confirmNewPassword" id="confirmNewPassword" th:placeholder="#{account.confirmNewPassword}"> <input type="password" class="form-control" name="confirmNewPassword" id="confirmNewPassword" th:placeholder="#{account.confirmNewPassword}">
</div> </div>
<div class="mb-3"> <div class="mb-3">
<span id="confirmPasswordError" style="display: none;" th:text="#{confirmPasswordErrorMessage}">New Password and Confirm New Password must match.</span>
<button type="submit" class="btn btn-primary" th:text="#{changeCreds.submit}">Change credentials!</button> <button type="submit" class="btn btn-primary" th:text="#{changeCreds.submit}">Change credentials!</button>
</div> </div>
</form> </form>
<script> <script th:inline="javascript">
document.addEventListener("DOMContentLoaded", function() { $(document).ready(function() {
const form = document.querySelector('form[action="api/v1/user/change-password-on-login"]'); $.validator.addMethod("passwordMatch", function(value, element) {
return $('#newPassword').val() === $('#confirmNewPassword').val();
form.addEventListener('submit', function(event) { }, /*[[#{confirmPasswordErrorMessage}]]*/ "New Password and Confirm New Password must match.");
const newPassword = document.getElementById('newPassword').value; $('#formsavechangecreds').validate({
const confirmNewPassword = document.getElementById('confirmNewPassword').value; rules: {
currentPassword: {
if (newPassword !== confirmNewPassword) { required: true
alert('New Password and Confirm New Password must match.'); },
event.preventDefault(); // Prevent form submission newPassword: {
required: true
},
confirmNewPassword: {
required: true,
passwordMatch: true
},
errorPlacement: function(error, element) {
if ($(element).attr("name") === "newPassword" || $(element).attr("name") === "confirmNewPassword") {
$("#confirmPasswordError").text(error.text()).show();
} else {
error.insertAfter(element);
}
},
success: function(label, element) {
if ($(element).attr("name") === "newPassword" || $(element).attr("name") === "confirmNewPassword") {
$("#confirmPasswordError").hide();
}
}
} }
}); });
}); });

View File

@ -12,7 +12,7 @@
<br><br> <br><br>
<div class="container"> <div class="container">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="mb-3 bg-card"> <div class="col-md-6 bg-card">
<div class="tool-header"> <div class="tool-header">
<span class="material-symbols-rounded tool-header-icon convert">html</span> <span class="material-symbols-rounded tool-header-icon convert">html</span>
<span class="tool-header-text" th:text="#{HTMLToPDF.header}"></span> <span class="tool-header-text" th:text="#{HTMLToPDF.header}"></span>

View File

@ -403,7 +403,7 @@
<a href="swagger-ui/index.html" class="btn btn-sm btn-outline-primary mx-1" role="button" <a href="swagger-ui/index.html" class="btn btn-sm btn-outline-primary mx-1" role="button"
target="_blank">API</a> target="_blank">API</a>
<a th:if="${@shouldShow}" href="https://github.com/Stirling-Tools/Stirling-PDF/releases" <a href="https://github.com/Stirling-Tools/Stirling-PDF/releases"
class="btn btn-sm btn-outline-primary mx-1" id="update-btn" th:utext="#{settings.update}" role="button" class="btn btn-sm btn-outline-primary mx-1" id="update-btn" th:utext="#{settings.update}" role="button"
target="_blank"></a> target="_blank"></a>
</div> </div>

View File

@ -44,7 +44,6 @@
</a> </a>
</div> </div>
<div <div
th:replace="~{fragments/card :: card(id='pipeline', cardTitle=#{home.pipeline.title}, cardText=#{home.pipeline.desc}, cardLink='pipeline', toolIcon='family_history', tags=#{pipeline.tags}, toolGroup='advance')}"> th:replace="~{fragments/card :: card(id='pipeline', cardTitle=#{home.pipeline.title}, cardText=#{home.pipeline.desc}, cardLink='pipeline', toolIcon='family_history', tags=#{pipeline.tags}, toolGroup='advance')}">
</div> </div>

View File

@ -19,9 +19,13 @@
</div> </div>
<form action="api/v1/general/merge-pdfs" method="post" enctype="multipart/form-data"> <form action="api/v1/general/merge-pdfs" method="post" enctype="multipart/form-data">
<div class="mb-3"> <div class="mb-3">
<label th:text="#{multiPdfDropPrompt}"></label> <label th:text="#{multiPdfDropPrompt}" for="fileInput-input"></label>
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=true, accept='application/pdf')}"></div> <div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=true, accept='application/pdf')}"></div>
</div> </div>
<div class="mb-3">
<input type="checkbox" name="removeCertSign" id="removeCertSign">
<label for="removeCertSign" th:text="#{merge.removeCertSign}">Remove digital signature in the merged file?</label>
</div>
<div class="mb-3"> <div class="mb-3">
<ul id="selectedFiles" class="list-group"></ul> <ul id="selectedFiles" class="list-group"></ul>
</div> </div>

View File

@ -16,6 +16,7 @@
/> />
<script th:inline="javascript"> <script th:inline="javascript">
const saveSettings = /*[[#{pipelineOptions.saveSettings}]]*/ ""; const saveSettings = /*[[#{pipelineOptions.saveSettings}]]*/ "";
const deletePipelineText = /*[[#{pipeline.pipeline.deletePrompt}]]*/ "Are you sure you want to delete pipeline";
</script> </script>
</head> </head>
@ -92,7 +93,7 @@
<!-- The Modal --> <!-- The Modal -->
<div class="modal" id="pipelineSettingsModal"> <div class="modal" id="pipelineSettingsModal">
<div class="modal-dialog"> <div class="modal-dialog modal-lg">
<div class="modal-content dark-card"> <div class="modal-content dark-card">
<!-- Modal Header --> <!-- Modal Header -->
<div class="modal-header"> <div class="modal-header">
@ -158,6 +159,12 @@
<!-- Modal footer --> <!-- Modal footer -->
<div class="modal-footer"> <div class="modal-footer">
<button
id="deletePipelineBtn"
class="btn btn-danger"
th:text="#{delete}"
></button>
<button <button
id="saveBrowserPipelineBtn" id="saveBrowserPipelineBtn"
class="btn btn-success" class="btn btn-success"

View File

@ -20,23 +20,23 @@
<div class="mb-3"> <div class="mb-3">
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"></div> <div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"></div>
</div> </div>
<div class="form-check"> <div class="form-check ms-3">
<input type="checkbox" id="removeJavaScript" name="removeJavaScript" checked> <input type="checkbox" id="removeJavaScript" name="removeJavaScript" checked>
<label for="removeJavaScript" th:text="#{sanitizePDF.selectText.1}"></label> <label for="removeJavaScript" th:text="#{sanitizePDF.selectText.1}"></label>
</div> </div>
<div class="form-check"> <div class="form-check ms-3">
<input type="checkbox" id="removeEmbeddedFiles" name="removeEmbeddedFiles" checked> <input type="checkbox" id="removeEmbeddedFiles" name="removeEmbeddedFiles" checked>
<label for="removeEmbeddedFiles" th:text="#{sanitizePDF.selectText.2}"></label> <label for="removeEmbeddedFiles" th:text="#{sanitizePDF.selectText.2}"></label>
</div> </div>
<div class="form-check"> <div class="form-check ms-3">
<input type="checkbox" id="removeMetadata" name="removeMetadata" checked> <input type="checkbox" id="removeMetadata" name="removeMetadata" checked>
<label for="removeMetadata" th:text="#{sanitizePDF.selectText.3}"></label> <label for="removeMetadata" th:text="#{sanitizePDF.selectText.3}"></label>
</div> </div>
<div class="form-check"> <div class="form-check ms-3">
<input type="checkbox" id="removeLinks" name="removeLinks"> <input type="checkbox" id="removeLinks" name="removeLinks">
<label for="removeLinks" th:text="#{sanitizePDF.selectText.4}"></label> <label for="removeLinks" th:text="#{sanitizePDF.selectText.4}"></label>
</div> </div>
<div class="form-check"> <div class="form-check ms-3">
<input type="checkbox" id="removeFonts" name="removeFonts"> <input type="checkbox" id="removeFonts" name="removeFonts">
<label for="removeFonts" th:text="#{sanitizePDF.selectText.5}"></label> <label for="removeFonts" th:text="#{sanitizePDF.selectText.5}"></label>
</div> </div>

View File

@ -20,7 +20,7 @@ Adobe CMap resources are covered by their own copyright but the same license:
See https://github.com/adobe-type-tools/cmap-resources See https://github.com/adobe-type-tools/cmap-resources
--> -->
<html dir="ltr" mozdisallowselectionprint th:lang="${#locale.language}" th:data-language="${#locale.toString()}" xmlns:th="https://www.thymeleaf.org"> <html dir="ltr" mozdisallowselectionprint th:lang="${#locale.language}" th:data-language="${#locale.toString()}" xmlns:th="https://www.thymeleaf.org">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
@ -461,8 +461,8 @@ See https://github.com/adobe-type-tools/cmap-resources
<button id="documentPropertiesClose" class="dialogButton"><span data-l10n-id="pdfjs-document-properties-close-button">Close</span></button> <button id="documentPropertiesClose" class="dialogButton"><span data-l10n-id="pdfjs-document-properties-close-button">Close</span></button>
</div> </div>
</dialog> </dialog>
<dialog id="altTextDialog" aria-labelledby="dialogLabel" aria-describedby="dialogDescription"> <dialog class="dialog altText" id="altTextDialog" aria-labelledby="dialogLabel" aria-describedby="dialogDescription">
<div id="altTextContainer"> <div id="altTextContainer" class="mainContainer">
<div id="overallDescription"> <div id="overallDescription">
<span id="dialogLabel" data-l10n-id="pdfjs-editor-alt-text-dialog-label" class="title">Choose an option</span> <span id="dialogLabel" data-l10n-id="pdfjs-editor-alt-text-dialog-label" class="title">Choose an option</span>
<span id="dialogDescription" data-l10n-id="pdfjs-editor-alt-text-dialog-description"> <span id="dialogDescription" data-l10n-id="pdfjs-editor-alt-text-dialog-description">
@ -499,8 +499,8 @@ See https://github.com/adobe-type-tools/cmap-resources
</div> </div>
</div> </div>
<div id="buttons"> <div id="buttons">
<button id="altTextCancel" tabindex="0"><span data-l10n-id="pdfjs-editor-alt-text-cancel-button">Cancel</span></button> <button id="altTextCancel" class="secondaryButton" tabindex="0"><span data-l10n-id="pdfjs-editor-alt-text-cancel-button">Cancel</span></button>
<button id="altTextSave" tabindex="0"><span data-l10n-id="pdfjs-editor-alt-text-save-button">Save</span></button> <button id="altTextSave" class="primaryButton" tabindex="0"><span data-l10n-id="pdfjs-editor-alt-text-save-button">Save</span></button>
</div> </div>
</div> </div>
</dialog> </dialog>

View File

@ -0,0 +1,45 @@
package stirling.software.SPDF.utils;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import org.junit.jupiter.api.Test;
import org.springframework.ui.Model;
import org.springframework.web.servlet.ModelAndView;
public class ErrorUtilsTest {
@Test
public void testExceptionToModel() {
// Create a mock Model
Model model = new org.springframework.ui.ExtendedModelMap();
// Create a test exception
Exception ex = new Exception("Test Exception");
// Call the method under test
Model resultModel = ErrorUtils.exceptionToModel(model, ex);
// Verify the result
assertNotNull(resultModel);
assertEquals("Test Exception", resultModel.getAttribute("errorMessage"));
assertNotNull(resultModel.getAttribute("stackTrace"));
}
@Test
public void testExceptionToModelView() {
// Create a mock Model
Model model = new org.springframework.ui.ExtendedModelMap();
// Create a test exception
Exception ex = new Exception("Test Exception");
// Call the method under test
ModelAndView modelAndView = ErrorUtils.exceptionToModelView(model, ex);
// Verify the result
assertNotNull(modelAndView);
assertEquals("Test Exception", modelAndView.getModel().get("errorMessage"));
assertNotNull(modelAndView.getModel().get("stackTrace"));
}
}

View File

@ -0,0 +1,36 @@
package stirling.software.SPDF.utils;
import static org.junit.jupiter.api.Assertions.*;
import java.io.IOException;
import org.junit.jupiter.api.Test;
import stirling.software.SPDF.model.api.converters.HTMLToPdfRequest;
public class FileToPdfTest {
@Test
public void testConvertHtmlToPdf() {
HTMLToPdfRequest request = new HTMLToPdfRequest();
byte[] fileBytes = new byte[10]; // Sample file bytes
String fileName = "test.html"; // Sample file name
boolean htmlFormatsInstalled = true; // Sample boolean value
// Check if the method throws IOException
assertThrows(IOException.class, () -> {
FileToPdf.convertHtmlToPdf(request, fileBytes, fileName, htmlFormatsInstalled);
});
}
@Test
public void testConvertBookTypeToPdf() {
byte[] bytes = new byte[10]; // Sample bytes
String originalFilename = "test.epub"; // Sample original filename
// Check if the method throws IOException
assertThrows(IOException.class, () -> {
FileToPdf.convertBookTypeToPdf(bytes, originalFilename);
});
}
}

View File

@ -0,0 +1,76 @@
package stirling.software.SPDF.utils;
import org.junit.jupiter.api.Test;
import java.awt.image.BufferedImage;
import java.awt.Color;
import static org.junit.jupiter.api.Assertions.*;
public class ImageProcessingUtilsTest {
@Test
void testConvertColorTypeToGreyscale() {
BufferedImage sourceImage = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
fillImageWithColor(sourceImage, Color.RED);
BufferedImage convertedImage = ImageProcessingUtils.convertColorType(sourceImage, "greyscale");
assertNotNull(convertedImage);
assertEquals(BufferedImage.TYPE_BYTE_GRAY, convertedImage.getType());
assertEquals(sourceImage.getWidth(), convertedImage.getWidth());
assertEquals(sourceImage.getHeight(), convertedImage.getHeight());
// Check if a pixel is correctly converted to greyscale
Color grey = new Color(convertedImage.getRGB(0, 0));
assertEquals(grey.getRed(), grey.getGreen());
assertEquals(grey.getGreen(), grey.getBlue());
}
@Test
void testConvertColorTypeToBlackWhite() {
BufferedImage sourceImage = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
fillImageWithColor(sourceImage, Color.RED);
BufferedImage convertedImage = ImageProcessingUtils.convertColorType(sourceImage, "blackwhite");
assertNotNull(convertedImage);
assertEquals(BufferedImage.TYPE_BYTE_BINARY, convertedImage.getType());
assertEquals(sourceImage.getWidth(), convertedImage.getWidth());
assertEquals(sourceImage.getHeight(), convertedImage.getHeight());
// Check if a pixel is converted correctly (binary image will be either black or white)
int rgb = convertedImage.getRGB(0, 0);
assertTrue(rgb == Color.BLACK.getRGB() || rgb == Color.WHITE.getRGB());
}
@Test
void testConvertColorTypeToFullColor() {
BufferedImage sourceImage = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
fillImageWithColor(sourceImage, Color.RED);
BufferedImage convertedImage = ImageProcessingUtils.convertColorType(sourceImage, "fullcolor");
assertNotNull(convertedImage);
assertEquals(sourceImage, convertedImage);
}
@Test
void testConvertColorTypeInvalid() {
BufferedImage sourceImage = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
fillImageWithColor(sourceImage, Color.RED);
BufferedImage convertedImage = ImageProcessingUtils.convertColorType(sourceImage, "invalidtype");
assertNotNull(convertedImage);
assertEquals(sourceImage, convertedImage);
}
private void fillImageWithColor(BufferedImage image, Color color) {
for (int y = 0; y < image.getHeight(); y++) {
for (int x = 0; x < image.getWidth(); x++) {
image.setRGB(x, y, color.getRGB());
}
}
}
}

View File

@ -0,0 +1,60 @@
package stirling.software.SPDF.utils;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDResources;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import stirling.software.SPDF.model.PdfMetadata;
import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import static org.junit.jupiter.api.Assertions.*;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.apache.pdfbox.cos.COSName;
public class PdfUtilsTest {
@Test
void testTextToPageSize() {
assertEquals(PDRectangle.A4, PdfUtils.textToPageSize("A4"));
assertEquals(PDRectangle.LETTER, PdfUtils.textToPageSize("LETTER"));
assertThrows(IllegalArgumentException.class, () -> PdfUtils.textToPageSize("INVALID"));
}
@Test
void testHasImagesOnPage() throws IOException {
// Mock a PDPage and its resources
PDPage page = Mockito.mock(PDPage.class);
PDResources resources = Mockito.mock(PDResources.class);
Mockito.when(page.getResources()).thenReturn(resources);
// Case 1: No images in resources
Mockito.when(resources.getXObjectNames()).thenReturn(Collections.emptySet());
assertFalse(PdfUtils.hasImagesOnPage(page));
// Case 2: Resources with an image
Set<COSName> xObjectNames = new HashSet<>();
COSName cosName = Mockito.mock(COSName.class);
xObjectNames.add(cosName);
PDImageXObject imageXObject = Mockito.mock(PDImageXObject.class);
Mockito.when(resources.getXObjectNames()).thenReturn(xObjectNames);
Mockito.when(resources.getXObject(cosName)).thenReturn(imageXObject);
assertTrue(PdfUtils.hasImagesOnPage(page));
}
@Test
void testExtractMetadataFromPdf() throws IOException {
PDDocument document = Mockito.mock(PDDocument.class);
Mockito.when(document.getDocumentInformation()).thenReturn(Mockito.mock(org.apache.pdfbox.pdmodel.PDDocumentInformation.class));
PdfMetadata metadata = PdfUtils.extractMetadataFromPdf(document);
assertNotNull(metadata);
}
}

View File

@ -0,0 +1,55 @@
package stirling.software.SPDF.utils;
import static org.junit.jupiter.api.Assertions.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class ProcessExecutorTest {
private ProcessExecutor processExecutor;
@BeforeEach
public void setUp() {
// Initialize the ProcessExecutor instance
processExecutor = ProcessExecutor.getInstance(ProcessExecutor.Processes.LIBRE_OFFICE);
}
@Test
public void testRunCommandWithOutputHandling() throws IOException, InterruptedException {
// Mock the command to execute
List<String> command = new ArrayList<>();
command.add("java");
command.add("-version");
// Execute the command
ProcessExecutor.ProcessExecutorResult result = processExecutor.runCommandWithOutputHandling(command);
// Check the exit code and output messages
assertEquals(0, result.getRc());
assertNotNull(result.getMessages()); // Check if messages are not null
}
@Test
public void testRunCommandWithOutputHandling_Error() {
// Mock the command to execute
List<String> command = new ArrayList<>();
command.add("nonexistent-command");
// Execute the command and expect an IOException
IOException thrown = assertThrows(IOException.class, () -> {
processExecutor.runCommandWithOutputHandling(command);
});
// Log the actual error message
System.out.println("Caught IOException: " + thrown.getMessage());
// Check the exception message to ensure it indicates the command was not found
String errorMessage = thrown.getMessage();
assertTrue(errorMessage.contains("error=2") || errorMessage.contains("No such file or directory"), "Unexpected error message: " + errorMessage);
}
}

View File

@ -0,0 +1,69 @@
package stirling.software.SPDF.utils;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class PropertyConfigsTest {
@Test
public void testGetBooleanValue_WithKeys() {
// Define keys and default value
List<String> keys = Arrays.asList("test.key1", "test.key2", "test.key3");
boolean defaultValue = false;
// Set property for one of the keys
System.setProperty("test.key2", "true");
// Call the method under test
boolean result = PropertyConfigs.getBooleanValue(keys, defaultValue);
// Verify the result
assertEquals(true, result);
}
@Test
public void testGetStringValue_WithKeys() {
// Define keys and default value
List<String> keys = Arrays.asList("test.key1", "test.key2", "test.key3");
String defaultValue = "default";
// Set property for one of the keys
System.setProperty("test.key2", "value");
// Call the method under test
String result = PropertyConfigs.getStringValue(keys, defaultValue);
// Verify the result
assertEquals("value", result);
}
@Test
public void testGetBooleanValue_WithKey() {
// Define key and default value
String key = "test.key";
boolean defaultValue = true;
// Call the method under test
boolean result = PropertyConfigs.getBooleanValue(key, defaultValue);
// Verify the result
assertEquals(true, result);
}
@Test
public void testGetStringValue_WithKey() {
// Define key and default value
String key = "test.key";
String defaultValue = "default";
// Call the method under test
String result = PropertyConfigs.getStringValue(key, defaultValue);
// Verify the result
assertEquals("default", result);
}
}

View File

@ -0,0 +1,26 @@
package stirling.software.SPDF.utils;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.Test;
public class RequestUriUtilsTest {
@Test
public void testIsStaticResource() {
assertTrue(RequestUriUtils.isStaticResource("/css/styles.css"));
assertTrue(RequestUriUtils.isStaticResource("/js/script.js"));
assertTrue(RequestUriUtils.isStaticResource("/images/logo.png"));
assertTrue(RequestUriUtils.isStaticResource("/public/index.html"));
assertTrue(RequestUriUtils.isStaticResource("/pdfjs/pdf.worker.js"));
assertTrue(RequestUriUtils.isStaticResource("/api/v1/info/status"));
assertTrue(RequestUriUtils.isStaticResource("/some-path/icon.svg"));
assertFalse(RequestUriUtils.isStaticResource("/api/v1/users"));
assertFalse(RequestUriUtils.isStaticResource("/api/v1/orders"));
assertFalse(RequestUriUtils.isStaticResource("/"));
assertFalse(RequestUriUtils.isStaticResource("/login"));
assertFalse(RequestUriUtils.isStaticResource("/register"));
assertFalse(RequestUriUtils.isStaticResource("/api/v1/products"));
}
}

View File

@ -0,0 +1,76 @@
package stirling.software.SPDF.utils;
import static org.junit.jupiter.api.Assertions.*;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.core.env.Environment;
import stirling.software.SPDF.SPdfApplication;
import stirling.software.SPDF.model.ApplicationProperties;
@ExtendWith(MockitoExtension.class)
public class SPdfApplicationTest {
@Mock
private Environment env;
@Mock
private ApplicationProperties applicationProperties;
@InjectMocks
private SPdfApplication sPdfApplication;
@BeforeEach
public void setUp() {
sPdfApplication = new SPdfApplication();
sPdfApplication.setServerPortStatic("8080");
}
@Test
public void testSetServerPortStatic() {
sPdfApplication.setServerPortStatic("9090");
assertEquals("9090", SPdfApplication.getStaticPort());
}
@Test
public void testMainApplicationStartup() throws IOException, InterruptedException {
// Setup mock environment for the main method
Path settingsPath = Paths.get("configs/settings.yml");
Path customSettingsPath = Paths.get("configs/custom_settings.yml");
// Ensure the files do not exist for the test
if (Files.exists(settingsPath)) {
Files.delete(settingsPath);
}
if (Files.exists(customSettingsPath)) {
Files.delete(customSettingsPath);
}
// Run the main method
SPdfApplication.main(new String[]{});
// Verify that the directories were created
assertTrue(Files.exists(Path.of("customFiles/static/")));
assertTrue(Files.exists(Path.of("customFiles/templates/")));
}
@Test
public void testGetStaticPort() {
assertEquals("8080", SPdfApplication.getStaticPort());
}
@Test
public void testGetNonStaticPort() {
assertEquals("8080", sPdfApplication.getNonStaticPort());
}
}

View File

@ -0,0 +1,26 @@
package stirling.software.SPDF.utils;
import jakarta.servlet.http.HttpServletRequest;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class UrlUtilsTest {
@Test
void testGetOrigin() {
// Mock HttpServletRequest
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
Mockito.when(request.getScheme()).thenReturn("http");
Mockito.when(request.getServerName()).thenReturn("localhost");
Mockito.when(request.getServerPort()).thenReturn(8080);
Mockito.when(request.getContextPath()).thenReturn("/myapp");
// Call the method under test
String origin = UrlUtils.getOrigin(request);
// Assert the result
assertEquals("http://localhost:8080/myapp", origin);
}
}

View File

@ -0,0 +1,111 @@
package stirling.software.SPDF.utils;
import static org.junit.jupiter.api.Assertions.*;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.junit.jupiter.api.Test;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile;
public class WebResponseUtilsTest {
@Test
public void testBoasToWebResponse() {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
baos.write("Sample PDF content".getBytes());
String docName = "sample.pdf";
ResponseEntity<byte[]> responseEntity = WebResponseUtils.boasToWebResponse(baos, docName);
assertNotNull(responseEntity);
assertEquals(HttpStatus.OK, responseEntity.getStatusCode());
assertNotNull(responseEntity.getBody());
HttpHeaders headers = responseEntity.getHeaders();
assertNotNull(headers);
assertEquals(MediaType.APPLICATION_PDF, headers.getContentType());
assertNotNull(headers.getContentDisposition());
//assertEquals("attachment; filename=\"sample.pdf\"", headers.getContentDisposition().toString());
} catch (IOException e) {
fail("Exception thrown: " + e.getMessage());
}
}
@Test
public void testMultiPartFileToWebResponse() {
try {
byte[] fileContent = "Sample file content".getBytes();
MockMultipartFile file = new MockMultipartFile("file", "sample.txt", "text/plain", fileContent);
ResponseEntity<byte[]> responseEntity = WebResponseUtils.multiPartFileToWebResponse(file);
assertNotNull(responseEntity);
assertEquals(HttpStatus.OK, responseEntity.getStatusCode());
assertNotNull(responseEntity.getBody());
HttpHeaders headers = responseEntity.getHeaders();
assertNotNull(headers);
assertEquals(MediaType.TEXT_PLAIN, headers.getContentType());
assertNotNull(headers.getContentDisposition());
} catch (IOException e) {
fail("Exception thrown: " + e.getMessage());
}
}
@Test
public void testBytesToWebResponse() {
try {
byte[] bytes = "Sample bytes".getBytes();
String docName = "sample.txt";
MediaType mediaType = MediaType.TEXT_PLAIN;
ResponseEntity<byte[]> responseEntity = WebResponseUtils.bytesToWebResponse(bytes, docName, mediaType);
assertNotNull(responseEntity);
assertEquals(HttpStatus.OK, responseEntity.getStatusCode());
assertNotNull(responseEntity.getBody());
HttpHeaders headers = responseEntity.getHeaders();
assertNotNull(headers);
assertEquals(MediaType.TEXT_PLAIN, headers.getContentType());
assertNotNull(headers.getContentDisposition());
} catch (IOException e) {
fail("Exception thrown: " + e.getMessage());
}
}
@Test
public void testPdfDocToWebResponse() {
try {
PDDocument document = new PDDocument();
document.addPage(new org.apache.pdfbox.pdmodel.PDPage());
String docName = "sample.pdf";
ResponseEntity<byte[]> responseEntity = WebResponseUtils.pdfDocToWebResponse(document, docName);
assertNotNull(responseEntity);
assertEquals(HttpStatus.OK, responseEntity.getStatusCode());
assertNotNull(responseEntity.getBody());
HttpHeaders headers = responseEntity.getHeaders();
assertNotNull(headers);
assertEquals(MediaType.APPLICATION_PDF, headers.getContentType());
assertNotNull(headers.getContentDisposition());
} catch (IOException e) {
fail("Exception thrown: " + e.getMessage());
}
}
}