Compare commits

...

22 Commits

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

Co-authored-by: GitHub Action action@github.com <GitHub Action action@github.com>
2024-08-24 17:14:47 +01:00
Anthony Stirling
4088132597 Update build.gradle 2024-08-24 17:14:16 +01:00
github-actions[bot]
7b9d419267 Update 3rd Party Licenses (#1754)
Signed-off-by: GitHub Action <action@github.com>
Co-authored-by: GitHub Action <action@github.com>
2024-08-24 17:12:27 +01:00
Anthony Stirling
9b710b489e Fixes #1552 and #1554 (#1753)
* fix

* cleanups!

* fix

* fix for #1552 pipeline not accepting non pdfs

* fix for #1154 font not accepting numbers etc

* Update User.java

---------

Co-authored-by: a <a>
2024-08-24 17:08:51 +01:00
Anthony Stirling
e2ff418c89 Increase linecounts to check #1618 (#1752)
Increase linecounts to check #1618
2024-08-24 15:32:33 +01:00
albanobattistella
be006f08a6 Update messages_it_IT.properties (#1751) 2024-08-24 15:34:02 +02:00
Ludy
b007c805bf Removes double equal signs (#1750) 2024-08-23 22:55:01 +01:00
github-actions[bot]
24be10eed4 Update 3rd Party Licenses (#1746)
Signed-off-by: GitHub Action <action@github.com>
Co-authored-by: GitHub Action <action@github.com>
2024-08-23 22:49:31 +01:00
Dimitris Kaitantzidis
0854a1d26e Fixes LazyInitializationException in User entity (#1749)
Temp integration of playground dist files of pdfme as-is to investigate the result
2024-08-23 21:37:45 +01:00
Ludy
33c7bb7e13 Add: Make Login Attempt Service deactivatable (#1747) 2024-08-23 14:46:09 +01:00
Anthony Stirling
cdf31622e2 Fixes for eager loading (#1748)
* fix

* cleanups!

* fix

---------

Co-authored-by: a <a>
2024-08-23 14:45:53 +01:00
Anthony Stirling
c7e5987342 Cleanup logs (#1739)
* fix

* cleanups!

---------

Co-authored-by: a <a>
2024-08-23 11:52:45 +01:00
Ludy
d3ef335c24 Fix: validations is not a permitted attribute - dropdown (#1745) 2024-08-23 11:52:31 +01:00
Ludy
b23784f598 Fix: authentication ApiKey NullPointerException (#1744) 2024-08-23 12:10:58 +02:00
Ludy
90cbcde029 Fix: Missing multi-selection and Python validation (#1740)
Missing multi-selection and Python validation
2024-08-23 09:28:06 +01:00
Anthony Stirling
382edc01f8 Multiple flag fix (#1742)
* fix

* multiple file logic cleanup

* fix

---------

Co-authored-by: a <a>
2024-08-23 09:17:50 +01:00
github-actions[bot]
dee912f075 📝 Update README: Translation Progress Table (#1734)
📝 Sync README
> Made via sync_files.yml

Co-authored-by: GitHub Action action@github.com <GitHub Action action@github.com>
2024-08-22 21:47:37 +01:00
albanobattistella
faed367cde Update messages_it_IT.properties (#1732) 2024-08-22 11:54:55 +01:00
Anthony Stirling
788744c1be Update pull_request_template.md 2024-08-21 20:43:13 +01:00
github-actions[bot]
686b88d21d 📝 Update README: Translation Progress Table (#1731)
📝 Sync README
> Made via sync_files.yml

Co-authored-by: GitHub Action action@github.com <GitHub Action action@github.com>
2024-08-21 11:37:45 +01:00
Ludy
1a594b27ab Fix: introduces the verification of the python installation (#1730)
* Fix: introduces the verification of the python installation

* Update ExtractImageScansController.java

* Update CheckProgramInstall.java
2024-08-21 11:16:29 +01:00
Anthony Stirling
9f0088c839 Create release.yml 2024-08-20 22:56:15 +01:00
141 changed files with 447 additions and 281 deletions

View File

@@ -22,8 +22,6 @@ body:
- Docker ultra lite
- Docker fat
- Local Installation
validations:
required: true
- type: textarea
id: problem

View File

@@ -10,9 +10,3 @@ Closes #(issue_number)
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] My changes generate no new warnings
## Contributor License Agreement
By submitting this pull request, I acknowledge and agree that my contributions will be included in Stirling-PDF and that they can be relicensed in the future under the MPL 2.0 (Mozilla Public License Version 2.0) license.
(This does not change the general open-source nature of Stirling-PDF, simply moving from one license to another license)

32
.github/release.yml vendored Normal file
View File

@@ -0,0 +1,32 @@
changelog:
exclude:
labels:
- Documentation
- Test
- Github
categories:
- title: Bug Fixes
labels:
- Bug
- title: Enhancements
labels:
- enhancement
- title: Minor Enhancements
labels:
- Java
- Front End
- title: Docker Updates
labels:
- Docker
- title: Translation Changes
labels:
- Translation
- title: Other Changes
labels:
- "*"

View File

@@ -173,7 +173,7 @@ Stirling PDF currently supports 38!
| Basque (Euskara) (eu_ES) | ![60%](https://geps.dev/progress/60) |
| Bulgarian (Български) (bg_BG) | ![92%](https://geps.dev/progress/92) |
| Catalan (Català) (ca_CA) | ![47%](https://geps.dev/progress/47) |
| Croatian (Hrvatski) (hr_HR) | ![93%](https://geps.dev/progress/93) |
| Croatian (Hrvatski) (hr_HR) | ![92%](https://geps.dev/progress/92) |
| Czech (Česky) (cs_CZ) | ![88%](https://geps.dev/progress/88) |
| Danish (Dansk) (da_DK) | ![9%](https://geps.dev/progress/9) |
| Dutch (Nederlands) (nl_NL) | ![94%](https://geps.dev/progress/94) |
@@ -184,18 +184,18 @@ Stirling PDF currently supports 38!
| Greek (Ελληνικά) (el_GR) | ![80%](https://geps.dev/progress/80) |
| Hindi (हिंदी) (hi_IN) | ![75%](https://geps.dev/progress/75) |
| Hungarian (Magyar) (hu_HU) | ![74%](https://geps.dev/progress/74) |
| Indonesia (Bahasa Indonesia) (id_ID) | ![75%](https://geps.dev/progress/75) |
| Indonesia (Bahasa Indonesia) (id_ID) | ![74%](https://geps.dev/progress/74) |
| Irish (Gaeilge) (ga_IE) | ![96%](https://geps.dev/progress/96) |
| Italian (Italiano) (it_IT) | ![98%](https://geps.dev/progress/98) |
| Japanese (日本語) (ja_JP) | ![91%](https://geps.dev/progress/91) |
| Italian (Italiano) (it_IT) | ![99%](https://geps.dev/progress/99) |
| Japanese (日本語) (ja_JP) | ![90%](https://geps.dev/progress/90) |
| Korean (한국어) (ko_KR) | ![82%](https://geps.dev/progress/82) |
| Norwegian (Norsk) (no_NB) | ![96%](https://geps.dev/progress/96) |
| Polish (Polski) (pl_PL) | ![90%](https://geps.dev/progress/90) |
| Portuguese (Português) (pt_PT) | ![77%](https://geps.dev/progress/77) |
| Portuguese (Português) (pt_PT) | ![76%](https://geps.dev/progress/76) |
| Portuguese Brazilian (Português) (pt_BR) | ![99%](https://geps.dev/progress/99) |
| Romanian (Română) (ro_RO) | ![38%](https://geps.dev/progress/38) |
| Russian (Русский) (ru_RU) | ![82%](https://geps.dev/progress/82) |
| Serbian Latin alphabet (Srpski) (sr_LATN_RS) | ![77%](https://geps.dev/progress/77) |
| Serbian Latin alphabet (Srpski) (sr_LATN_RS) | ![76%](https://geps.dev/progress/76) |
| Simplified Chinese (简体中文) (zh_CN) | ![97%](https://geps.dev/progress/97) |
| Slovakian (Slovensky) (sk_SK) | ![90%](https://geps.dev/progress/90) |
| Spanish (Español) (es_ES) | ![96%](https://geps.dev/progress/96) |
@@ -237,7 +237,7 @@ The Current list of settings is
security:
enableLogin: false # set to 'true' to enable login
csrfDisabled: true # Set to 'true' to disable CSRF protection (not recommended for production)
loginAttemptCount: 5 # lock user account after 5 tries
loginAttemptCount: 5 # lock user account after 5 tries; when using e.g. Fail2Ban you can deactivate the function with -1
loginResetTimeMinutes: 120 # lock account for 2 hours after x attempts
loginMethod: all # 'all' (Login Username/Password and OAuth2[must be enabled and configured]), 'normal'(only Login with Username/Password) or 'oauth2'(only Login with OAuth2)
initialLogin:

View File

@@ -7,6 +7,7 @@ plugins {
id "edu.sc.seis.launch4j" version "3.0.6"
id "com.diffplug.spotless" version "6.25.0"
id "com.github.jk1.dependency-license-report" version "2.9"
//id "nebula.lint" version "19.0.3"
}
import com.github.jk1.license.render.*
@@ -21,7 +22,7 @@ ext {
}
group = "stirling.software"
version = "0.28.2"
version = "0.28.3"
java {
// 17 is lowest but we support and recommend 21
@@ -100,14 +101,20 @@ spotless {
}
}
//gradleLint {
// rules=['unused-dependency']
// }
tasks.wrapper {
gradleVersion = "8.7"
}
//tasks.withType(JavaCompile) {
// options.compilerArgs << "-Xlint:deprecation"
//}
configurations.all {
exclude group: "org.springframework.boot", module: "spring-boot-starter-tomcat"
}
dependencies {
//security updates
implementation "ch.qos.logback:logback-classic:$logbackVersion"
implementation "ch.qos.logback:logback-core:$logbackVersion"
implementation "org.springframework:spring-webmvc:6.1.9"
implementation("io.github.pixee:java-security-toolkit:1.2.0")
@@ -116,21 +123,19 @@ dependencies {
implementation 'com.github.Carleslc.Simple-YAML:Simple-Yaml:1.8.4'
// Exclude Tomcat and include Jetty
implementation("org.springframework.boot:spring-boot-starter-web:$springBootVersion") {
exclude group: "org.springframework.boot", module: "spring-boot-starter-tomcat"
}
implementation("org.springframework.boot:spring-boot-starter-web:$springBootVersion")
implementation "org.springframework.boot:spring-boot-starter-jetty:$springBootVersion"
implementation "org.springframework.boot:spring-boot-starter-thymeleaf:$springBootVersion"
if (System.getenv("DOCKER_ENABLE_SECURITY") != "false") {
implementation "org.springframework.boot:spring-boot-starter-security:$springBootVersion"
implementation "org.thymeleaf.extras:thymeleaf-extras-springsecurity5:3.1.2.RELEASE"
runtimeOnly "org.thymeleaf.extras:thymeleaf-extras-springsecurity5:3.1.2.RELEASE"
implementation "org.springframework.boot:spring-boot-starter-data-jpa:$springBootVersion"
implementation "org.springframework.boot:spring-boot-starter-oauth2-client:$springBootVersion"
//2.2.x requires rebuild of DB file.. need migration path
implementation "com.h2database:h2:2.1.214"
runtimeOnly "com.h2database:h2:2.1.214"
// implementation "com.h2database:h2:2.2.224"
}
@@ -138,28 +143,27 @@ dependencies {
// Batik
implementation "org.apache.xmlgraphics:batik-all:1.17"
// TwelveMonkeys
implementation "com.twelvemonkeys.imageio:imageio-batik:$imageioVersion"
implementation "com.twelvemonkeys.imageio:imageio-bmp:$imageioVersion"
// implementation "com.twelvemonkeys.imageio:imageio-hdr:$imageioVersion"
// implementation "com.twelvemonkeys.imageio:imageio-icns:$imageioVersion"
// implementation "com.twelvemonkeys.imageio:imageio-iff:$imageioVersion"
implementation "com.twelvemonkeys.imageio:imageio-jpeg:$imageioVersion"
// implementation "com.twelvemonkeys.imageio:imageio-pcx:$imageioVersion@
// implementation "com.twelvemonkeys.imageio:imageio-pict:$imageioVersion"
// implementation "com.twelvemonkeys.imageio:imageio-pnm:$imageioVersion"
// implementation "com.twelvemonkeys.imageio:imageio-psd:$imageioVersion"
// implementation "com.twelvemonkeys.imageio:imageio-sgi:$imageioVersion"
// implementation "com.twelvemonkeys.imageio:imageio-tga:$imageioVersion"
// implementation "com.twelvemonkeys.imageio:imageio-thumbsdb:$imageioVersion"
implementation "com.twelvemonkeys.imageio:imageio-tiff:$imageioVersion"
implementation "com.twelvemonkeys.imageio:imageio-webp:$imageioVersion"
// implementation "com.twelvemonkeys.imageio:imageio-xwd:$imageioVersion"
runtimeOnly "com.twelvemonkeys.imageio:imageio-batik:$imageioVersion"
runtimeOnly "com.twelvemonkeys.imageio:imageio-bmp:$imageioVersion"
// runtimeOnly "com.twelvemonkeys.imageio:imageio-hdr:$imageioVersion"
// runtimeOnly "com.twelvemonkeys.imageio:imageio-icns:$imageioVersion"
// runtimeOnly "com.twelvemonkeys.imageio:imageio-iff:$imageioVersion"
runtimeOnly "com.twelvemonkeys.imageio:imageio-jpeg:$imageioVersion"
// runtimeOnly "com.twelvemonkeys.imageio:imageio-pcx:$imageioVersion@
// runtimeOnly "com.twelvemonkeys.imageio:imageio-pict:$imageioVersion"
// runtimeOnly "com.twelvemonkeys.imageio:imageio-pnm:$imageioVersion"
// runtimeOnly "com.twelvemonkeys.imageio:imageio-psd:$imageioVersion"
// runtimeOnly "com.twelvemonkeys.imageio:imageio-sgi:$imageioVersion"
// runtimeOnly "com.twelvemonkeys.imageio:imageio-tga:$imageioVersion"
// runtimeOnly "com.twelvemonkeys.imageio:imageio-thumbsdb:$imageioVersion"
runtimeOnly "com.twelvemonkeys.imageio:imageio-tiff:$imageioVersion"
runtimeOnly "com.twelvemonkeys.imageio:imageio-webp:$imageioVersion"
// runtimeOnly "com.twelvemonkeys.imageio:imageio-xwd:$imageioVersion"
implementation "commons-io:commons-io:2.16.1"
implementation "org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0"
//general PDF
// https://mvnrepository.com/artifact/com.opencsv/opencsv
@@ -196,7 +200,7 @@ dependencies {
compileOnly "org.projectlombok:lombok:$lombokVersion"
annotationProcessor "org.projectlombok:lombok:$lombokVersion"
testImplementation 'org.mockito:mockito-inline:5.2.0'
testRuntimeOnly 'org.mockito:mockito-inline:5.2.0'
}
tasks.withType(JavaCompile).configureEach {

View File

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

View File

@@ -65,6 +65,7 @@ public class SPdfApplication {
public static void main(String[] args) throws IOException, InterruptedException {
SpringApplication app = new SpringApplication(SPdfApplication.class);
app.setAdditionalProfiles("default");
app.addInitializers(new ConfigInitializer());
Map<String, String> propertyFiles = new HashMap<>();

View File

@@ -126,13 +126,12 @@ public class AppConfig {
}
@Bean(name = "directoryFilter")
public Predicate<Path> processPDFOnlyFilter() {
public Predicate<Path> processOnlyFiles() {
return path -> {
if (Files.isDirectory(path)) {
return !path.toString().contains("processing");
} else {
String fileName = path.getFileName().toString();
return fileName.endsWith(".pdf");
return true;
}
};
}

View File

@@ -7,21 +7,28 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.model.ApplicationProperties;
import stirling.software.SPDF.model.AttemptCounter;
@Service
@Slf4j
public class LoginAttemptService {
@Autowired ApplicationProperties applicationProperties;
@Autowired private ApplicationProperties applicationProperties;
private int MAX_ATTEMPT;
private long ATTEMPT_INCREMENT_TIME;
private ConcurrentHashMap<String, AttemptCounter> attemptsCache;
private boolean isBlockedEnabled = true;
@PostConstruct
public void init() {
MAX_ATTEMPT = applicationProperties.getSecurity().getLoginAttemptCount();
if (MAX_ATTEMPT == -1) {
isBlockedEnabled = false;
log.info("Login attempt tracking is disabled.");
}
ATTEMPT_INCREMENT_TIME =
TimeUnit.MINUTES.toMillis(
applicationProperties.getSecurity().getLoginResetTimeMinutes());
@@ -29,14 +36,16 @@ public class LoginAttemptService {
}
public void loginSucceeded(String key) {
if (key == null || key.trim().isEmpty()) {
if (!isBlockedEnabled || key == null || key.trim().isEmpty()) {
return;
}
attemptsCache.remove(key.toLowerCase());
}
public void loginFailed(String key) {
if (key == null || key.trim().isEmpty()) return;
if (!isBlockedEnabled || key == null || key.trim().isEmpty()) {
return;
}
AttemptCounter attemptCounter = attemptsCache.get(key.toLowerCase());
if (attemptCounter == null) {
@@ -51,7 +60,9 @@ public class LoginAttemptService {
}
public boolean isBlocked(String key) {
if (key == null || key.trim().isEmpty()) return false;
if (!isBlockedEnabled || key == null || key.trim().isEmpty()) {
return false;
}
AttemptCounter attemptCounter = attemptsCache.get(key.toLowerCase());
if (attemptCounter == null) {
return false;
@@ -61,7 +72,9 @@ public class LoginAttemptService {
}
public int getRemainingAttempts(String key) {
if (key == null || key.trim().isEmpty()) return MAX_ATTEMPT;
if (!isBlockedEnabled || key == null || key.trim().isEmpty()) {
return Integer.MAX_VALUE; // Arbitrarily high number if tracking is disabled
}
AttemptCounter attemptCounter = attemptsCache.get(key.toLowerCase());
if (attemptCounter == null) {

View File

@@ -10,7 +10,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
@@ -150,8 +149,7 @@ public class SecurityConfiguration {
})
.permitAll()
.anyRequest()
.authenticated())
.authenticationProvider(authenticationProvider());
.authenticated());
// Handle OAUTH2 Logins
if (applicationProperties.getSecurity().getOAUTH2() != null
@@ -379,14 +377,6 @@ public class SecurityConfiguration {
return new IPRateLimitingFilter(maxRequestsPerIp, maxRequestsPerIp);
}
@Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userDetailsService);
authProvider.setPasswordEncoder(passwordEncoder());
return authProvider;
}
@Bean
public PersistentTokenRepository persistentTokenRepository() {
return new JPATokenRepositoryImpl();

View File

@@ -58,7 +58,7 @@ public class UserAuthenticationFilter extends OncePerRequestFilter {
try {
// Use API key to authenticate. This requires you to have an authentication
// provider for API keys.
Optional<User> user = userService.loadUserByApiKey(apiKey);
Optional<User> user = userService.getUserByApiKey(apiKey);
if (!user.isPresent()) {
response.setStatus(HttpStatus.UNAUTHORIZED.value());
response.getWriter().write("Invalid API Key.");

View File

@@ -1,13 +1,5 @@
package stirling.software.SPDF.config.security;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
@@ -21,8 +13,6 @@ import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.stereotype.Service;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.DatabaseBackupInterface;
import stirling.software.SPDF.config.security.session.SessionPersistentRegistry;
import stirling.software.SPDF.controller.api.pipeline.UserServiceInterface;
@@ -33,6 +23,10 @@ import stirling.software.SPDF.model.User;
import stirling.software.SPDF.repository.AuthorityRepository;
import stirling.software.SPDF.repository.UserRepository;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
@Service
public class UserService implements UserServiceInterface {
@@ -222,7 +216,7 @@ public class UserService implements UserServiceInterface {
public void updateUserSettings(String username, Map<String, String> updates)
throws IOException {
Optional<User> userOpt = findByUsernameIgnoreCase(username);
Optional<User> userOpt = findByUsernameIgnoreCaseWithSettings(username);
if (userOpt.isPresent()) {
User user = userOpt.get();
Map<String, String> settingsMap = user.getSettings();
@@ -247,6 +241,10 @@ public class UserService implements UserServiceInterface {
return userRepository.findByUsernameIgnoreCase(username);
}
public Optional<User> findByUsernameIgnoreCaseWithSettings(String username) {
return userRepository.findByUsernameIgnoreCaseWithSettings(username);
}
public Authority findRole(User user) {
return authorityRepository.findByUserId(user.getId());
}

View File

@@ -7,7 +7,6 @@ import java.net.URLConnection;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
@@ -17,7 +16,6 @@ import org.apache.commons.io.FileUtils;
import org.apache.pdfbox.rendering.ImageType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ModelAttribute;
@@ -32,6 +30,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import stirling.software.SPDF.model.api.converters.ConvertToImageRequest;
import stirling.software.SPDF.model.api.converters.ConvertToPdfRequest;
import stirling.software.SPDF.utils.CheckProgramInstall;
import stirling.software.SPDF.utils.PdfUtils;
import stirling.software.SPDF.utils.ProcessExecutor;
import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult;
@@ -82,7 +81,10 @@ public class ConvertImgPDFController {
if (result == null || result.length == 0) {
logger.error("resultant bytes for {} is null, error converting ", filename);
}
if (imageFormat.equalsIgnoreCase("webp")) {
if (imageFormat.equalsIgnoreCase("webp") && !CheckProgramInstall.isPythonAvailable()) {
throw new IOException("Python is not installed. Required for WebP conversion.");
} else if (imageFormat.equalsIgnoreCase("webp")
&& CheckProgramInstall.isPythonAvailable()) {
// Write the output stream to a temp file
Path tempFile = Files.createTempFile("temp_png", ".png");
try (FileOutputStream fos = new FileOutputStream(tempFile.toFile())) {
@@ -90,21 +92,13 @@ public class ConvertImgPDFController {
fos.flush();
}
String pythonVersion = "python3";
try {
ProcessExecutor.getInstance(ProcessExecutor.Processes.PYTHON_OPENCV)
.runCommandWithOutputHandling(Arrays.asList("python3", "--version"));
} catch (IOException e) {
ProcessExecutor.getInstance(ProcessExecutor.Processes.PYTHON_OPENCV)
.runCommandWithOutputHandling(Arrays.asList("python", "--version"));
pythonVersion = "python";
}
String pythonVersion = CheckProgramInstall.getAvailablePythonCommand();
List<String> command = new ArrayList<>();
command.add(pythonVersion);
command.add("./scripts/png_to_webp.py"); // Python script to handle the conversion
// Create a temporary directory for the output WebP files
// Create a temporary directory for the output WebP files
Path tempOutputDir = Files.createTempDirectory("webp_output");
if (singleImage) {
// Run the Python script to convert PNG to WebP

View File

@@ -33,7 +33,7 @@ public class AutoRenameController {
private static final Logger logger = LoggerFactory.getLogger(AutoRenameController.class);
private static final float TITLE_FONT_SIZE_THRESHOLD = 20.0f;
private static final int LINE_LIMIT = 11;
private static final int LINE_LIMIT = 200;
@PostMapping(consumes = "multipart/form-data", value = "/auto-rename")
@Operation(

View File

@@ -32,6 +32,7 @@ import io.swagger.v3.oas.annotations.parameters.RequestBody;
import io.swagger.v3.oas.annotations.tags.Tag;
import stirling.software.SPDF.model.api.misc.ExtractImageScansRequest;
import stirling.software.SPDF.utils.CheckProgramInstall;
import stirling.software.SPDF.utils.ProcessExecutor;
import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult;
import stirling.software.SPDF.utils.WebResponseUtils;
@@ -76,6 +77,11 @@ public class ExtractImageScansController {
Path tempZipFile = null;
List<Path> tempDirs = new ArrayList<>();
if (!CheckProgramInstall.isPythonAvailable()) {
throw new IOException("Python is not installed.");
}
String pythonVersion = CheckProgramInstall.getAvailablePythonCommand();
try {
// Check if input file is a PDF
if ("pdf".equalsIgnoreCase(extension)) {
@@ -117,7 +123,7 @@ public class ExtractImageScansController {
List<String> command =
new ArrayList<>(
Arrays.asList(
"python3",
pythonVersion,
"./scripts/split_photos.py",
images.get(i),
tempDir.toString(),

View File

@@ -140,9 +140,9 @@ public class ExtractImagesController {
Set<Integer> processedImages,
ZipOutputStream zos)
throws IOException {
if(page.getResources() == null || page.getResources().getXObjectNames() == null) {
return;
}
if (page.getResources() == null || page.getResources().getXObjectNames() == null) {
return;
}
for (COSName name : page.getResources().getXObjectNames()) {
if (page.getResources().isImageXObject(name)) {
PDImageXObject image = (PDImageXObject) page.getResources().getXObject(name);

View File

@@ -43,7 +43,7 @@ public class ApiDocService {
Map<String, List<String>> outputToFileTypes = new HashMap<>();
public List getExtensionTypes(boolean output, String operationName) {
public List<String> getExtensionTypes(boolean output, String operationName) {
if (outputToFileTypes.size() == 0) {
outputToFileTypes.put("PDF", Arrays.asList("pdf"));
outputToFileTypes.put(

View File

@@ -1,15 +1,10 @@
package stirling.software.SPDF.controller.web;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
@@ -18,27 +13,20 @@ import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.security.session.SessionPersistentRegistry;
import stirling.software.SPDF.model.ApplicationProperties;
import stirling.software.SPDF.model.*;
import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2;
import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2.Client;
import stirling.software.SPDF.model.Authority;
import stirling.software.SPDF.model.Role;
import stirling.software.SPDF.model.SessionEntity;
import stirling.software.SPDF.model.User;
import stirling.software.SPDF.model.provider.GithubProvider;
import stirling.software.SPDF.model.provider.GoogleProvider;
import stirling.software.SPDF.model.provider.KeycloakProvider;
import stirling.software.SPDF.repository.UserRepository;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;
@Controller
@Slf4j
@Tag(name = "Account Security", description = "Account Security APIs")
@@ -361,7 +349,7 @@ public class AccountWebController {
if (username != null) {
// Fetch user details from the database
Optional<User> user =
userRepository.findByUsernameIgnoreCase(
userRepository.findByUsernameIgnoreCaseWithSettings(
username); // Assuming findByUsername method exists
if (!user.isPresent()) {
return "redirect:/error";

View File

@@ -9,6 +9,8 @@ import org.springframework.web.servlet.ModelAndView;
import io.swagger.v3.oas.annotations.Hidden;
import io.swagger.v3.oas.annotations.tags.Tag;
import stirling.software.SPDF.utils.CheckProgramInstall;
@Controller
@Tag(name = "Convert", description = "Convert APIs")
public class ConverterWebController {
@@ -69,6 +71,8 @@ public class ConverterWebController {
@GetMapping("/pdf-to-img")
@Hidden
public String pdfToimgForm(Model model) {
boolean isPython = CheckProgramInstall.isPythonAvailable();
model.addAttribute("isPython", isPython);
model.addAttribute("currentPage", "pdf-to-img");
return "convert/pdf-to-img";
}

View File

@@ -16,6 +16,7 @@ import io.swagger.v3.oas.annotations.Hidden;
import io.swagger.v3.oas.annotations.tags.Tag;
import stirling.software.SPDF.model.ApplicationProperties;
import stirling.software.SPDF.utils.CheckProgramInstall;
@Controller
@Tag(name = "Misc", description = "Miscellaneous APIs")
@@ -34,6 +35,8 @@ public class OtherWebController {
@Hidden
public ModelAndView extractImageScansForm() {
ModelAndView modelAndView = new ModelAndView("misc/extract-image-scans");
boolean isPython = CheckProgramInstall.isPythonAvailable();
modelAndView.addObject("isPython", isPython);
modelAndView.addObject("currentPage", "extract-image-scans");
return modelAndView;
}

View File

@@ -1,5 +1,7 @@
package stirling.software.SPDF.model;
import jakarta.persistence.*;
import java.io.Serializable;
import java.util.HashMap;
import java.util.HashSet;
@@ -7,21 +9,6 @@ import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import jakarta.persistence.CascadeType;
import jakarta.persistence.CollectionTable;
import jakarta.persistence.Column;
import jakarta.persistence.ElementCollection;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.Lob;
import jakarta.persistence.MapKeyColumn;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
@Entity
@Table(name = "users")
public class User implements Serializable {

View File

@@ -9,6 +9,8 @@ import lombok.EqualsAndHashCode;
@EqualsAndHashCode
public class UrlToPdfRequest {
@Schema(description = "The input URL to be converted to a PDF file", required = true)
@Schema(
description = "The input URL to be converted to a PDF file",
requiredMode = Schema.RequiredMode.REQUIRED)
private String urlInput;
}

View File

@@ -10,6 +10,6 @@ import stirling.software.SPDF.model.api.PDFWithPageNums;
@EqualsAndHashCode(callSuper = true)
public class ContainsTextRequest extends PDFWithPageNums {
@Schema(description = "The text to check for", required = true)
@Schema(description = "The text to check for", requiredMode = Schema.RequiredMode.REQUIRED)
private String text;
}

View File

@@ -10,6 +10,6 @@ import stirling.software.SPDF.model.api.PDFComparison;
@EqualsAndHashCode(callSuper = true)
public class FileSizeRequest extends PDFComparison {
@Schema(description = "File Size", required = true)
@Schema(description = "File Size", requiredMode = Schema.RequiredMode.REQUIRED)
private String fileSize;
}

View File

@@ -10,6 +10,6 @@ import stirling.software.SPDF.model.api.PDFComparison;
@EqualsAndHashCode(callSuper = true)
public class PageRotationRequest extends PDFComparison {
@Schema(description = "Rotation in degrees", required = true)
@Schema(description = "Rotation in degrees", requiredMode = Schema.RequiredMode.REQUIRED)
private int rotation;
}

View File

@@ -10,6 +10,6 @@ import stirling.software.SPDF.model.api.PDFComparison;
@EqualsAndHashCode(callSuper = true)
public class PageSizeRequest extends PDFComparison {
@Schema(description = "Standard Page Size", required = true)
@Schema(description = "Standard Page Size", requiredMode = Schema.RequiredMode.REQUIRED)
private String standardPageSize;
}

View File

@@ -20,13 +20,13 @@ public class OverlayPdfsRequest extends PDFFile {
@Schema(
description =
"The mode of overlaying: 'SequentialOverlay' for sequential application, 'InterleavedOverlay' for round-robin application, 'FixedRepeatOverlay' for fixed repetition based on provided counts",
required = true)
requiredMode = Schema.RequiredMode.REQUIRED)
private String overlayMode;
@Schema(
description =
"An array of integers specifying the number of times each corresponding overlay file should be applied in the 'FixedRepeatOverlay' mode. This should match the length of the overlayFiles array.",
required = false)
requiredMode = Schema.RequiredMode.NOT_REQUIRED)
private int[] counts;
@Schema(description = "Overlay position 0 is Foregound, 1 is Background")

View File

@@ -13,14 +13,14 @@ public class SplitPdfBySizeOrCountRequest extends PDFFile {
@Schema(
description =
"Determines the type of split: 0 for size, 1 for page count, 2 for document count",
required = false,
requiredMode = Schema.RequiredMode.NOT_REQUIRED,
defaultValue = "0")
private int splitType;
@Schema(
description =
"Value for split: size in MB (e.g., '10MB') or number of pages (e.g., '5')",
required = false,
requiredMode = Schema.RequiredMode.NOT_REQUIRED,
defaultValue = "10MB")
private String splitValue;
}

View File

@@ -15,7 +15,7 @@ public class AddStampRequest extends PDFWithPageNums {
@Schema(
description = "The stamp type (text or image)",
allowableValues = {"text", "image"},
required = true)
requiredMode = Schema.RequiredMode.REQUIRED)
private String stampType;
@Schema(description = "The stamp text")

View File

@@ -13,7 +13,7 @@ public class AutoSplitPdfRequest extends PDFFile {
@Schema(
description =
"Flag indicating if the duplex mode is active, where the page after the divider also gets removed.",
required = false,
requiredMode = Schema.RequiredMode.NOT_REQUIRED,
defaultValue = "false")
private boolean duplexMode;
}

View File

@@ -13,7 +13,7 @@ public class ExtractHeaderRequest extends PDFFile {
@Schema(
description =
"Flag indicating whether to use the first text as a fallback if no suitable title is found. Defaults to false.",
required = false,
requiredMode = Schema.RequiredMode.NOT_REQUIRED,
defaultValue = "false")
private boolean useFirstTextAsFallback;
}

View File

@@ -10,7 +10,9 @@ import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode
public class ExtractImageScansRequest {
@Schema(description = "The input file containing image scans", required = true)
@Schema(
description = "The input file containing image scans",
requiredMode = Schema.RequiredMode.REQUIRED)
private MultipartFile fileInput;
@Schema(

View File

@@ -10,6 +10,8 @@ import stirling.software.SPDF.model.api.PDFFile;
@EqualsAndHashCode(callSuper = true)
public class PrintFileRequest extends PDFFile {
@Schema(description = "Name of printer to match against", required = true)
@Schema(
description = "Name of printer to match against",
requiredMode = Schema.RequiredMode.REQUIRED)
private String printerName;
}

View File

@@ -15,7 +15,7 @@ public class AddWatermarkRequest extends PDFFile {
@Schema(
description = "The watermark type (text or image)",
allowableValues = {"text", "image"},
required = true)
requiredMode = Schema.RequiredMode.REQUIRED)
private String watermarkType;
@Schema(description = "The watermark text")

View File

@@ -10,6 +10,8 @@ import stirling.software.SPDF.model.api.PDFFile;
@EqualsAndHashCode(callSuper = true)
public class PDFPasswordRequest extends PDFFile {
@Schema(description = "The password of the PDF file", required = true)
@Schema(
description = "The password of the PDF file",
requiredMode = Schema.RequiredMode.REQUIRED)
private String password;
}

View File

@@ -10,7 +10,10 @@ import stirling.software.SPDF.model.api.PDFFile;
@EqualsAndHashCode(callSuper = true)
public class RedactPdfRequest extends PDFFile {
@Schema(description = "List of text to redact from the PDF", type = "string", required = true)
@Schema(
description = "List of text to redact from the PDF",
type = "string",
requiredMode = Schema.RequiredMode.REQUIRED)
private String listOfText;
@Schema(description = "Whether to use regex for the listOfText", defaultValue = "false")

View File

@@ -1,16 +1,19 @@
package stirling.software.SPDF.repository;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import stirling.software.SPDF.model.User;
import java.util.Optional;
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByUsernameIgnoreCase(String username);
@Query("FROM User u LEFT JOIN FETCH u.settings where upper(u.username) = upper(:username)")
Optional<User> findByUsernameIgnoreCaseWithSettings(String username);
Optional<User> findByUsername(String username);
Optional<User> findByApiKey(String apiKey);

View File

@@ -0,0 +1,59 @@
package stirling.software.SPDF.utils;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult;
public class CheckProgramInstall {
private static final List<String> PYTHON_COMMANDS = Arrays.asList("python3", "python");
private static boolean pythonAvailableChecked = false;
private static String availablePythonCommand = null;
/**
* Checks which Python command is available and returns it.
*
* @return The available Python command ("python3" or "python"), or null if neither is
* available.
*/
public static String getAvailablePythonCommand() {
if (!pythonAvailableChecked) {
availablePythonCommand =
PYTHON_COMMANDS.stream()
.filter(CheckProgramInstall::checkPythonVersion)
.findFirst()
.orElse(null);
pythonAvailableChecked = true;
}
return availablePythonCommand;
}
/**
* Checks if the specified command is available by running the command with --version.
*
* @param pythonCommand The Python command to check.
* @return true if the command is available, false otherwise.
*/
private static boolean checkPythonVersion(String pythonCommand) {
try {
ProcessExecutorResult result =
ProcessExecutor.getInstance(ProcessExecutor.Processes.PYTHON_OPENCV)
.runCommandWithOutputHandling(
Arrays.asList(pythonCommand, "--version"));
return true; // Command succeeded, Python is available
} catch (IOException | InterruptedException e) {
return false; // Command failed, Python is not available
}
}
/**
* Checks if any Python command is available.
*
* @return true if any Python command is available, false otherwise.
*/
public static boolean isPythonAvailable() {
return getAvailablePythonCommand() != null;
}
}

View File

@@ -4,7 +4,10 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -13,8 +16,6 @@ import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.List;
import java.net.URL;
import java.net.HttpURLConnection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -73,12 +74,11 @@ public class GeneralUtils {
} catch (MalformedURLException e) {
return false;
}
}
}
public static boolean isURLReachable(String urlStr) {
try {
URL url = new URL(urlStr);
URL url = URI.create(urlStr).toURL();
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("HEAD");
int responseCode = connection.getResponseCode();
@@ -112,16 +112,19 @@ public class GeneralUtils {
sizeStr = sizeStr.replace(",", ".").replace(" ", "");
try {
if (sizeStr.endsWith("KB")) {
return (long) (Double.parseDouble(sizeStr.substring(0, sizeStr.length() - 2)) * 1024);
return (long)
(Double.parseDouble(sizeStr.substring(0, sizeStr.length() - 2)) * 1024);
} else if (sizeStr.endsWith("MB")) {
return (long) (Double.parseDouble(sizeStr.substring(0, sizeStr.length() - 2))
* 1024
* 1024);
return (long)
(Double.parseDouble(sizeStr.substring(0, sizeStr.length() - 2))
* 1024
* 1024);
} else if (sizeStr.endsWith("GB")) {
return (long) (Double.parseDouble(sizeStr.substring(0, sizeStr.length() - 2))
* 1024
* 1024
* 1024);
return (long)
(Double.parseDouble(sizeStr.substring(0, sizeStr.length() - 2))
* 1024
* 1024
* 1024);
} else if (sizeStr.endsWith("B")) {
return Long.parseLong(sizeStr.substring(0, sizeStr.length() - 1));
} else {
@@ -191,8 +194,7 @@ public class GeneralUtils {
// Check if the result is null or not within bounds
if (result == null || result <= 0 || result.intValue() > maxValue) {
if (n != 0)
break;
if (n != 0) break;
} else {
results.add(result.intValue());
}

View File

@@ -1,5 +1,11 @@
multipart.enabled=true
logging.level.org.springframework=WARN
logging.level.org.hibernate=WARN
logging.level.org.eclipse.jetty=WARN
logging.level.com.zaxxer.hikari=WARN
spring.jpa.open-in-view=false
server.forward-headers-strategy=NATIVE
@@ -24,10 +30,8 @@ spring.devtools.livereload.enabled=true
spring.thymeleaf.encoding=UTF-8
server.connection-timeout=${SYSTEM_CONNECTIONTIMEOUTMINUTES:20m}
spring.mvc.async.request-timeout=${SYSTEM_CONNECTIONTIMEOUTMILLISECONDS:1200000}
spring.resources.static-locations=file:customFiles/static/
spring.mvc.async.request-timeout=${SYSTEM_CONNECTIONTIMEOUTMILLISECONDS:1200000}
#spring.thymeleaf.prefix=file:/customFiles/templates/,classpath:/templates/
#spring.thymeleaf.cache=false

View File

@@ -291,7 +291,7 @@ compressPdfs.tags=squish,small,tiny
home.changeMetadata.title=تغيير البيانات الوصفية
home.changeMetadata.desc=تغيير / إزالة / إضافة بيانات أولية من مستند PDF
changeMetadata.tags==Title,author,date,creation,time,publisher,producer,stats
changeMetadata.tags=Title,author,date,creation,time,publisher,producer,stats
home.fileToPDF.title=تحويل الملف إلى PDF
home.fileToPDF.desc=تحويل أي ملف تقريبا إلى PDF (DOCX وPNG وXLS وPPT وTXT والمزيد)
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=الحد الأدنى لمنطقة المحيط:
ScannerImageSplit.selectText.8=تعيين الحد الأدنى لمنطقة المحيط للصورة
ScannerImageSplit.selectText.9=حجم الحدود:
ScannerImageSplit.selectText.10=يضبط حجم الحدود المضافة والمزالة لمنع الحدود البيضاء في الإخراج (الافتراضي: 1).
ScannerImageSplit.info=Python is not installed. It is required to run.
#OCR
@@ -925,6 +926,7 @@ pdfToImage.color=اللون
pdfToImage.grey=تدرج الرمادي
pdfToImage.blackwhite=أبيض وأسود (قد يفقد البيانات!)
pdfToImage.submit=تحول
pdfToImage.info=Python is not installed. Required for WebP conversion.
#addPassword

View File

@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Минимална контурна площ:
ScannerImageSplit.selectText.8=Задава минималния праг на контурната площ за изображение
ScannerImageSplit.selectText.9=Размер на рамката:
ScannerImageSplit.selectText.10=Задава размера на добавената и премахната граница, за да предотврати бели граници към изхода (по подразбиране: 1).
ScannerImageSplit.info=Python is not installed. It is required to run.
#OCR
@@ -925,6 +926,7 @@ pdfToImage.color=Цвят
pdfToImage.grey=Скала на сивото
pdfToImage.blackwhite=Черно и бяло (може да загубите данни!)
pdfToImage.submit=Преобразуване
pdfToImage.info=Python is not installed. Required for WebP conversion.
#addPassword

View File

@@ -291,7 +291,7 @@ compressPdfs.tags=squish,small,tiny
home.changeMetadata.title=Canvia Metadades
home.changeMetadata.desc=Canvia/Treu/Afegeix matadades al document PDF.
changeMetadata.tags==Title,author,date,creation,time,publisher,producer,stats
changeMetadata.tags=Title,author,date,creation,time,publisher,producer,stats
home.fileToPDF.title=Converteix arxiu a PDF
home.fileToPDF.desc=Converteix qualsevol arxiu a PDF (DOCX, PNG, XLS, PPT, TXT i més)
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Àrea de contorn mínima:
ScannerImageSplit.selectText.8=Estableix el llindar mínim de l'àrea de contorn per a una foto
ScannerImageSplit.selectText.9=Mida Vora:
ScannerImageSplit.selectText.10=Estableix la mida de la vora afegida i eliminada per evitar vores blanques a la sortida (per defecte: 1).
ScannerImageSplit.info=Python is not installed. It is required to run.
#OCR
@@ -925,6 +926,7 @@ pdfToImage.color=Color
pdfToImage.grey=Escala de Grisos
pdfToImage.blackwhite=Blanc i Negre (Pot perdre dades!)
pdfToImage.submit=Converteix
pdfToImage.info=Python is not installed. Required for WebP conversion.
#addPassword

View File

@@ -291,7 +291,7 @@ compressPdfs.tags=rozmáčknout,malý,drobný
home.changeMetadata.title=Změnit Metadata
home.changeMetadata.desc=Změnit/Odebrat/Přidat metadata z PDF dokumentu
changeMetadata.tags==Název,autor,datum,tvorba,čas,vydavatel,výrobce,statistiky
changeMetadata.tags=Název,autor,datum,tvorba,čas,vydavatel,výrobce,statistiky
home.fileToPDF.title=Převést soubor do PDF
home.fileToPDF.desc=Převést téměř jakýkoli soubor do PDF (DOCX, PNG, XLS, PPT, TXT a více)
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Minimální plocha kontury:
ScannerImageSplit.selectText.8=Nastaví minimální plošný práh kontury pro fotografii
ScannerImageSplit.selectText.9=Velikost okraje:
ScannerImageSplit.selectText.10=Nastaví velikost okraje přidaného a odebraného k zabránění bílých ohraničení ve výstupu (výchozí: 1).
ScannerImageSplit.info=Python is not installed. It is required to run.
#OCR
@@ -925,6 +926,7 @@ pdfToImage.color=Barevný
pdfToImage.grey=Stupně šedi
pdfToImage.blackwhite=Černobílý (Může dojít k ztrátě dat!)
pdfToImage.submit=Převést
pdfToImage.info=Python is not installed. Required for WebP conversion.
#addPassword

View File

@@ -291,7 +291,7 @@ compressPdfs.tags=squish,small,tiny
home.changeMetadata.title=Change Metadata
home.changeMetadata.desc=Change/Remove/Add metadata from a PDF document
changeMetadata.tags==Title,author,date,creation,time,publisher,producer,stats
changeMetadata.tags=Title,author,date,creation,time,publisher,producer,stats
home.fileToPDF.title=Convert file to PDF
home.fileToPDF.desc=Convert nearly any file to PDF (DOCX, PNG, XLS, PPT, TXT and more)
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Minimum Contour Area:
ScannerImageSplit.selectText.8=Sets the minimum contour area threshold for a photo
ScannerImageSplit.selectText.9=Border Size:
ScannerImageSplit.selectText.10=Sets the size of the border added and removed to prevent white borders in the output (default: 1).
ScannerImageSplit.info=Python is not installed. It is required to run.
#OCR
@@ -925,6 +926,7 @@ pdfToImage.color=Colour
pdfToImage.grey=Greyscale
pdfToImage.blackwhite=Black and White (May lose data!)
pdfToImage.submit=Convert
pdfToImage.info=Python is not installed. Required for WebP conversion.
#addPassword

View File

@@ -4,7 +4,7 @@
# the direction that the language is written (ltr=left to right, rtl = right to left)
language.direction=ltr
pdfPrompt=PDF auswählen
pdfPrompwt=PDF auswählen
multiPdfPrompt=PDFs auswählen(2+)
multiPdfDropPrompt=Wählen Sie alle gewünschten PDFs aus (oder ziehen Sie sie per Drag & Drop hierhin)
imgPrompt=Wählen Sie ein Bild
@@ -291,7 +291,7 @@ compressPdfs.tags=komprimieren,verkleinern,minimieren
home.changeMetadata.title=Metadaten ändern
home.changeMetadata.desc=Ändern/Entfernen/Hinzufügen von Metadaten aus einem PDF-Dokument
changeMetadata.tags==titel,autor,datum,erstellung,uhrzeit,herausgeber,produzent,statistiken
changeMetadata.tags=titel,autor,datum,erstellung,uhrzeit,herausgeber,produzent,statistiken
home.fileToPDF.title=Datei in PDF konvertieren
home.fileToPDF.desc=Konvertieren Sie nahezu jede Datei in PDF (DOCX, PNG, XLS, PPT, TXT und mehr)
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Minimaler Konturbereich:
ScannerImageSplit.selectText.8=Legt den minimalen Konturbereichsschwellenwert für ein Foto fest
ScannerImageSplit.selectText.9=Randgröße:
ScannerImageSplit.selectText.10=Legt die Größe des hinzugefügten und entfernten Randes fest, um weiße Ränder in der Ausgabe zu verhindern (Standard: 1).
ScannerImageSplit.info=Python is not installed. It is required to run.
#OCR
@@ -925,6 +926,7 @@ pdfToImage.color=Farbe
pdfToImage.grey=Graustufen
pdfToImage.blackwhite=Schwarzweiß (Datenverlust möglich!)
pdfToImage.submit=Umwandeln
pdfToImage.info=Python is not installed. Required for WebP conversion.
#addPassword

View File

@@ -291,7 +291,7 @@ compressPdfs.tags=squish,small,tiny
home.changeMetadata.title=Αλλαγή Μεταδεδομένων
home.changeMetadata.desc=Αλλαγή/Κατάργηση/Προσθήκη μεταδεδομένων από ένα έγγραφο PDF.
changeMetadata.tags==Title,author,date,creation,time,publisher,producer,stats
changeMetadata.tags=Title,author,date,creation,time,publisher,producer,stats
home.fileToPDF.title=Μετατροπή ενός αρχείου σε PDF
home.fileToPDF.desc=Μετατροπή σχεδόν οποιουδήποτε αρχείου σε PDF (DOCX, PNG, XLS, PPT, TXT and more)
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Ελάχιστη επιφάνεια περιγρ
ScannerImageSplit.selectText.8=Ρυθμίζει το ελάχιστο όριο περιγράμματος για μια φωτογραφία
ScannerImageSplit.selectText.9=Μέγεθος περιγράμματος:
ScannerImageSplit.selectText.10=Ορίζει το μέγεθος του περιγράμματος που προστίθεται και αφαιρείται για να αποτρέπονται λευκά περιγράμματα στην έξοδο (προεπιλογή: 1).
ScannerImageSplit.info=Python is not installed. It is required to run.
#OCR
@@ -925,6 +926,7 @@ pdfToImage.color=Χρώμα
pdfToImage.grey=Κλίμακα του γκρι
pdfToImage.blackwhite=Ασπρόμαυρο (Μπορεί να χαθούν δεδομένα!)
pdfToImage.submit=Μετατροπή
pdfToImage.info=Python is not installed. Required for WebP conversion.
#addPassword

View File

@@ -291,7 +291,7 @@ compressPdfs.tags=squish,small,tiny
home.changeMetadata.title=Change Metadata
home.changeMetadata.desc=Change/Remove/Add metadata from a PDF document
changeMetadata.tags==Title,author,date,creation,time,publisher,producer,stats
changeMetadata.tags=Title,author,date,creation,time,publisher,producer,stats
home.fileToPDF.title=Convert file to PDF
home.fileToPDF.desc=Convert nearly any file to PDF (DOCX, PNG, XLS, PPT, TXT and more)
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Minimum Contour Area:
ScannerImageSplit.selectText.8=Sets the minimum contour area threshold for a photo
ScannerImageSplit.selectText.9=Border Size:
ScannerImageSplit.selectText.10=Sets the size of the border added and removed to prevent white borders in the output (default: 1).
ScannerImageSplit.info=Python is not installed. It is required to run.
#OCR
@@ -925,6 +926,7 @@ pdfToImage.color=Colour
pdfToImage.grey=Greyscale
pdfToImage.blackwhite=Black and White (May lose data!)
pdfToImage.submit=Convert
pdfToImage.info=Python is not installed. Required for WebP conversion.
#addPassword

View File

@@ -291,7 +291,7 @@ compressPdfs.tags=squish,small,tiny
home.changeMetadata.title=Change Metadata
home.changeMetadata.desc=Change/Remove/Add metadata from a PDF document
changeMetadata.tags==Title,author,date,creation,time,publisher,producer,stats
changeMetadata.tags=Title,author,date,creation,time,publisher,producer,stats
home.fileToPDF.title=Convert file to PDF
home.fileToPDF.desc=Convert nearly any file to PDF (DOCX, PNG, XLS, PPT, TXT and more)
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Minimum Contour Area:
ScannerImageSplit.selectText.8=Sets the minimum contour area threshold for a photo
ScannerImageSplit.selectText.9=Border Size:
ScannerImageSplit.selectText.10=Sets the size of the border added and removed to prevent white borders in the output (default: 1).
ScannerImageSplit.info=Python is not installed. It is required to run.
#OCR
@@ -925,6 +926,7 @@ pdfToImage.color=Color
pdfToImage.grey=Grayscale
pdfToImage.blackwhite=Black and White (May lose data!)
pdfToImage.submit=Convert
pdfToImage.info=Python is not installed. Required for WebP conversion.
#addPassword

View File

@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Área mínima de contorno:
ScannerImageSplit.selectText.8=Establecer el umbral mínimo del área de contorno para una foto
ScannerImageSplit.selectText.9=Tamaño del borde:
ScannerImageSplit.selectText.10=Establece el tamaño del borde agregado y eliminado para evitar bordes blancos en la salida (predeterminado: 1).
ScannerImageSplit.info=Python is not installed. It is required to run.
#OCR
@@ -925,6 +926,7 @@ pdfToImage.color=Color
pdfToImage.grey=Escala de grises
pdfToImage.blackwhite=Blanco y Negro (¡Puede perder datos!)
pdfToImage.submit=Convertir
pdfToImage.info=Python is not installed. Required for WebP conversion.
#addPassword

View File

@@ -291,7 +291,7 @@ compressPdfs.tags=squish,small,tiny
home.changeMetadata.title=Aldatu metadatuak
home.changeMetadata.desc=Aldatu/Ezabatu/Gehitu metadatuak PDF dokumentuari
changeMetadata.tags==Title,author,date,creation,time,publisher,producer,stats
changeMetadata.tags=Title,author,date,creation,time,publisher,producer,stats
home.fileToPDF.title=Fitxategia PDF bihurtu
home.fileToPDF.desc=PDF bihurtu ia edozein fitxategi (DOCX, PNG, XLS, PPT, TXT eta gehiago)
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Inguruko area gutxienekoa:
ScannerImageSplit.selectText.8=Ezarri inguruko arearen gutxieneko balioa argazki batentzat
ScannerImageSplit.selectText.9=Ertzaren tamaina:
ScannerImageSplit.selectText.10=Ezarri gehitutako eta ezabatutako ertzaren tamaina irteeran ertz zuriak saihesteko (lehenetsia: 1).
ScannerImageSplit.info=Python is not installed. It is required to run.
#OCR
@@ -925,6 +926,7 @@ pdfToImage.color=Kolorea
pdfToImage.grey=Gris-eskala
pdfToImage.blackwhite=Zuria eta Beltza (Datuak galdu ditzake!)
pdfToImage.submit=Bihurtu
pdfToImage.info=Python is not installed. Required for WebP conversion.
#addPassword

View File

@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Surface de contour minimale
ScannerImageSplit.selectText.8=Définit la surface de contour minimale pour une photo (par défaut : 500).
ScannerImageSplit.selectText.9=Taille de la bordure
ScannerImageSplit.selectText.10=Définit la taille de la bordure ajoutée et supprimée pour éviter les bordures blanches dans la sortie (par défaut : 1).
ScannerImageSplit.info=Python is not installed. It is required to run.
#OCR
@@ -925,6 +926,7 @@ pdfToImage.color=Couleur
pdfToImage.grey=Niveaux de gris
pdfToImage.blackwhite=Noir et blanc (peut engendrer une perte de données !)
pdfToImage.submit=Convertir
pdfToImage.info=Python is not installed. Required for WebP conversion.
#addPassword

View File

@@ -291,7 +291,7 @@ compressPdfs.tags=squish, beag, beag bídeach
home.changeMetadata.title=Athraigh Meiteashonraí
home.changeMetadata.desc=Athraigh/Bain/Cuir meiteashonraí ó dhoiciméad PDF
changeMetadata.tags==Title,author,date,creation,time,publisher,producer,stats
changeMetadata.tags=Title,author,date,creation,time,publisher,producer,stats
home.fileToPDF.title=Comhad a thiontú go PDF
home.fileToPDF.desc=Tiontaigh beagnach aon chomhad go PDF (DOCX, PNG, XLS, PPT, TXT agus go leor eile)
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Íos-Limistéar Comhrianta:
ScannerImageSplit.selectText.8=Socraíonn sé an tairseach íosta achar comhrianta le haghaidh grianghraf
ScannerImageSplit.selectText.9=Méid na Teorann:
ScannerImageSplit.selectText.10=Socraíonn sé méid na teorann a chuirtear leis agus a bhaintear chun teorainneacha bán a chosc san aschur (réamhshocraithe: 1).
ScannerImageSplit.info=Python is not installed. It is required to run.
#OCR
@@ -925,6 +926,7 @@ pdfToImage.color=Dath
pdfToImage.grey=Scála Liath
pdfToImage.blackwhite=Dubh agus Bán (Dfhéadfadh sonraí a chailleadh!)
pdfToImage.submit=Tiontaigh
pdfToImage.info=Python is not installed. Required for WebP conversion.
#addPassword

View File

@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=न्यूनतम कंटोर क्ष
ScannerImageSplit.selectText.8=फोटो के लिए न्यूनतम कंटोर क्षेत्र थ्रेशोल्ड को सेट करता है।
ScannerImageSplit.selectText.9=बॉर्डर का आकार:
ScannerImageSplit.selectText.10=निकालने और जोड़ने के लिए जोड़ा जाने वाला बॉर्डर का आकार सेट करता है ताकि आउटपुट में सफेद बॉर्डर न आए (डिफ़ॉल्ट: 1)।
ScannerImageSplit.info=Python is not installed. It is required to run.
#OCR
@@ -925,6 +926,7 @@ pdfToImage.color=रंगीन
pdfToImage.grey=ग्रे स्केल
pdfToImage.blackwhite=काला और सफेद (डेटा खो सकता है!)
pdfToImage.submit=परिवर्तित करें
pdfToImage.info=Python is not installed. Required for WebP conversion.
#addPassword

View File

@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Minimalna konturna površina:
ScannerImageSplit.selectText.8=Postavlja minimalni prag površine konture za fotografiju
ScannerImageSplit.selectText.9=Veličina obruba:
ScannerImageSplit.selectText.10=Postavlja veličinu obruba koji se dodaje i uklanja kako bi se spriječili bijeli obrubi u ispisu (zadano: 1).
ScannerImageSplit.info=Python is not installed. It is required to run.
#OCR
@@ -925,6 +926,7 @@ pdfToImage.color=Boja
pdfToImage.grey=Sivi tonovi
pdfToImage.blackwhite=Crno-bijelo (mogu se izgubiti podaci!)
pdfToImage.submit=Pretvori
pdfToImage.info=Python is not installed. Required for WebP conversion.
#addPassword

View File

@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Minimális kontúr terület:
ScannerImageSplit.selectText.8=A fotók minimális kontúrterületének beállítása
ScannerImageSplit.selectText.9=Keret mérete:
ScannerImageSplit.selectText.10=A hozzáadott és eltávolított keret méretének beállítása a fehér keretek elkerülése érdekében a kimeneten (alapértelmezett: 1).
ScannerImageSplit.info=Python is not installed. It is required to run.
#OCR
@@ -925,6 +926,7 @@ pdfToImage.color=színes
pdfToImage.grey=szürkeárnyalatos
pdfToImage.blackwhite=fekete-fehér (adatvesztéssel járhat!)
pdfToImage.submit=Átalakítás
pdfToImage.info=Python is not installed. Required for WebP conversion.
#addPassword

View File

@@ -291,7 +291,7 @@ compressPdfs.tags=squish, kecil, kecil
home.changeMetadata.title=Ubah Metadata
home.changeMetadata.desc=Mengubah/Menghapus/Menambahkan metadata dari dokumen PDF
changeMetadata.tags==Judul,penulis,tanggal,pembuatan,waktu,penerbit,produser,statistik
changeMetadata.tags=Judul,penulis,tanggal,pembuatan,waktu,penerbit,produser,statistik
home.fileToPDF.title=Mengonversi berkas ke PDF
home.fileToPDF.desc=Mengonversi hampir semua berkas ke PDF (DOCX, PNG, XLS, PPT, TXT dan lain-lain)
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Area Kontur Minimum:
ScannerImageSplit.selectText.8=Menetapkan ambang batas area kontur minimum untuk foto
ScannerImageSplit.selectText.9=Ukuran Batas:
ScannerImageSplit.selectText.10=Menetapkan ukuran batas yang ditambahkan dan dihapus untuk mencegah batas putih pada output (default: 1).
ScannerImageSplit.info=Python is not installed. It is required to run.
#OCR
@@ -925,6 +926,7 @@ pdfToImage.color=Warna
pdfToImage.grey=Skala abu-abu
pdfToImage.blackwhite=Black and White (Bisa kehilangan data!)
pdfToImage.submit=Konversi
pdfToImage.info=Python is not installed. Required for WebP conversion.
#addPassword

View File

@@ -55,12 +55,12 @@ userNotFoundMessage=Utente non trovato.
incorrectPasswordMessage=La password attuale non è corretta.
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.
invalidPasswordMessage=The password must not be empty and must not have spaces at the beginning or end.
invalidPasswordMessage=La password non deve essere vuota e non deve contenere spazi all'inizio o alla fine.
confirmPasswordErrorMessage=La nuova password e la conferma della nuova password devono corrispondere.
deleteCurrentUserMessage=Impossibile eliminare l'utente attualmente connesso.
deleteUsernameExistsMessage=Il nome utente non esiste e non può essere eliminato.
downgradeCurrentUserMessage=Impossibile declassare il ruolo dell'utente corrente
disabledCurrentUserMessage=The current user cannot be disabled
disabledCurrentUserMessage=L'utente corrente non può essere disabilitato
downgradeCurrentUserLongMessage=Impossibile declassare il ruolo dell'utente corrente. Pertanto, l'utente corrente non verrà visualizzato.
userAlreadyExistsOAuthMessage=L'utente esiste già come utente OAuth2.
userAlreadyExistsWebMessage=L'utente esiste già come utente web.
@@ -179,7 +179,7 @@ adminUserSettings.user=Utente
adminUserSettings.addUser=Aggiungi un nuovo Utente
adminUserSettings.deleteUser=Elimina utente
adminUserSettings.confirmDeleteUser=L'utente deve essere eliminato?
adminUserSettings.confirmChangeUserStatus=Should the user be disabled/enabled?
adminUserSettings.confirmChangeUserStatus=L'utente dovrebbe essere disabilitato/abilitato?
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.role=Ruolo
@@ -193,13 +193,13 @@ adminUserSettings.forceChange=Forza l'utente a cambiare nome username/password a
adminUserSettings.submit=Salva utente
adminUserSettings.changeUserRole=Cambia il ruolo dell'utente
adminUserSettings.authenticated=Autenticato
adminUserSettings.editOwnProfil=Edit own profile
adminUserSettings.enabledUser=enabled user
adminUserSettings.disabledUser=disabled user
adminUserSettings.activeUsers=Active Users:
adminUserSettings.disabledUsers=Disabled Users:
adminUserSettings.totalUsers=Total Users:
adminUserSettings.lastRequest=Last Request
adminUserSettings.editOwnProfil=Modifica il tuo profilo
adminUserSettings.enabledUser=utente abilitato
adminUserSettings.disabledUser=utente disabilitato
adminUserSettings.activeUsers=Utenti attivi:
adminUserSettings.disabledUsers=Utenti disabili:
adminUserSettings.totalUsers=Utenti totali:
adminUserSettings.lastRequest=Ultima richiesta
database.title=Importazione/Esportazione database
@@ -291,7 +291,7 @@ compressPdfs.tags=comprimere,piccolo,minuscolo
home.changeMetadata.title=Modifica Proprietà
home.changeMetadata.desc=Modifica/Aggiungi/Rimuovi le proprietà di un documento PDF.
changeMetadata.tags==Titolo,autore,data,creazione,ora,editore,produttore,statistiche
changeMetadata.tags=Titolo,autore,data,creazione,ora,editore,produttore,statistiche
home.fileToPDF.title=Converti file in PDF
home.fileToPDF.desc=Converti quasi ogni file in PDF (DOCX, PNG, XLS, PPT, TXT e altro)
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Area di contorno minima:
ScannerImageSplit.selectText.8=Imposta l'area minima del contorno di una foto
ScannerImageSplit.selectText.9=Spessore bordo:
ScannerImageSplit.selectText.10=Imposta lo spessore del bordo aggiunto o rimosso per prevenire bordi bianchi nel risultato (predefinito: 1).
ScannerImageSplit.info=Python non è installato. È necessario per l'esecuzione.
#OCR
@@ -925,6 +926,7 @@ pdfToImage.color=A colori
pdfToImage.grey=Scala di grigi
pdfToImage.blackwhite=Bianco e Nero (potresti perdere dettagli!)
pdfToImage.submit=Converti
pdfToImage.info=Python non è installato.È richiesto per la conversione WebP.
#addPassword

View File

@@ -291,7 +291,7 @@ compressPdfs.tags=squish,small,tiny
home.changeMetadata.title=メタデータの変更
home.changeMetadata.desc=PDFのメタデータを変更/削除/追加します。
changeMetadata.tags==Title,author,date,creation,time,publisher,producer,stats
changeMetadata.tags=Title,author,date,creation,time,publisher,producer,stats
home.fileToPDF.title=ファイルをPDFに変換
home.fileToPDF.desc=ほぼすべてのファイルをPDFに変換します。 (DOCX, PNG, XLS, PPT, TXTなど)
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=最小輪郭面積:
ScannerImageSplit.selectText.8=画像の最小の輪郭面積のしきい値を設定。
ScannerImageSplit.selectText.9=境界線サイズ:
ScannerImageSplit.selectText.10=出力に白い縁取りが出ないように追加・削除される境界線の大きさを設定 (初期値:1)。
ScannerImageSplit.info=Python is not installed. It is required to run.
#OCR
@@ -925,6 +926,7 @@ pdfToImage.color=カラー
pdfToImage.grey=グレースケール
pdfToImage.blackwhite=白黒 (データが失われる可能性があります!)
pdfToImage.submit=変換
pdfToImage.info=Python is not installed. Required for WebP conversion.
#addPassword

View File

@@ -291,7 +291,7 @@ compressPdfs.tags=squish,small,tiny
home.changeMetadata.title=메타데이터 변경
home.changeMetadata.desc=PDF 문서의 메타데이터를 수정/제거/추가합니다.
changeMetadata.tags==Title,author,date,creation,time,publisher,producer,stats
changeMetadata.tags=Title,author,date,creation,time,publisher,producer,stats
home.fileToPDF.title=파일을 PDF로 변환
home.fileToPDF.desc=거의 모든 파일을 PDF로 변환합니다(DOCX, PNG, XLS, PPT, TXT 등)
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=최소 윤곽 영역:
ScannerImageSplit.selectText.8=사진의 최소 윤곽선 영역 임계값을 설정합니다.
ScannerImageSplit.selectText.9=테두리 크기:
ScannerImageSplit.selectText.10=출력에서 흰색 테두리를 방지하기 위해 추가 및 제거되는 테두리의 크기를 설정합니다(기본값: 1).
ScannerImageSplit.info=Python is not installed. It is required to run.
#OCR
@@ -925,6 +926,7 @@ pdfToImage.color=컬러
pdfToImage.grey=그레이스케일
pdfToImage.blackwhite=흑백 (데이터 손실 가능성 있음!)
pdfToImage.submit=변환
pdfToImage.info=Python is not installed. Required for WebP conversion.
#addPassword

View File

@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Minimum contour oppervlakte:
ScannerImageSplit.selectText.8=Stelt de minimale contour oppervlakte drempel in voor een foto
ScannerImageSplit.selectText.9=Randgrootte:
ScannerImageSplit.selectText.10=Stelt de grootte van de toegevoegde en verwijderde rand in om witte randen in de uitvoer te voorkomen (standaard: 1).
ScannerImageSplit.info=Python is not installed. It is required to run.
#OCR
@@ -925,6 +926,7 @@ pdfToImage.color=Kleur
pdfToImage.grey=Grijstinten
pdfToImage.blackwhite=Zwart en wit (kan data verliezen!)
pdfToImage.submit=Omzetten
pdfToImage.info=Python is not installed. Required for WebP conversion.
#addPassword

View File

@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Minimumskonturområde:
ScannerImageSplit.selectText.8=Angir minimumskonturområde terskel for et bilde
ScannerImageSplit.selectText.9=Kantstørrelse:
ScannerImageSplit.selectText.10=Angir størrelsen på kanten som legges til og fjernes for å forhindre hvite kanter i utdataen (standard: 1).
ScannerImageSplit.info=Python is not installed. It is required to run.
#OCR
@@ -925,6 +926,7 @@ pdfToImage.color=Farge
pdfToImage.grey=Gråtone
pdfToImage.blackwhite=Svart-hvitt (kan miste data!)
pdfToImage.submit=Konverter
pdfToImage.info=Python is not installed. Required for WebP conversion.
#addPassword

View File

@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Minimalny obszar konturu:
ScannerImageSplit.selectText.8=Ustawia próg minimalnego obszaru konturu dla zdjęcia
ScannerImageSplit.selectText.9=Rozmiar obramowania:
ScannerImageSplit.selectText.10=Ustawia rozmiar dodawanego i usuwanego obramowania, aby uniknąć białych obramowań na wyjściu (domyślnie: 1).
ScannerImageSplit.info=Python is not installed. It is required to run.
#OCR
@@ -925,6 +926,7 @@ pdfToImage.color=Kolor
pdfToImage.grey=Odcień szarości
pdfToImage.blackwhite=Czarno-biały (może spowodować utratę danych!)
pdfToImage.submit=Konwertuj
pdfToImage.info=Python is not installed. Required for WebP conversion.
#addPassword

View File

@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Área mínima de contorno:
ScannerImageSplit.selectText.8=Define o limite mínimo da área de contorno para uma foto
ScannerImageSplit.selectText.9=Tamanho da borda:
ScannerImageSplit.selectText.10=Define o tamanho da borda adicionada e removida para evitar bordas brancas na saída (padrão: 1).
ScannerImageSplit.info=Python is not installed. It is required to run.
#OCR
@@ -925,6 +926,7 @@ pdfToImage.color=Colorida
pdfToImage.grey=Escala de Cinza
pdfToImage.blackwhite=Preto e Branco (pode perder de dados!)
pdfToImage.submit=Converter
pdfToImage.info=Python is not installed. Required for WebP conversion.
#addPassword

View File

@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Área mínima de contorno:
ScannerImageSplit.selectText.8=Define o limite mínimo da área de contorno para uma foto
ScannerImageSplit.selectText.9=Tamanho do contorno:
ScannerImageSplit.selectText.10=Define o tamanho do contorno adicionado e removido para evitar contornos brancos na saída (padrão: 1).
ScannerImageSplit.info=Python is not installed. It is required to run.
#OCR
@@ -925,6 +926,7 @@ pdfToImage.color=Colorida
pdfToImage.grey=Escala de Cinza
pdfToImage.blackwhite=Preto e Branco (pode resultar em perda de dados!)
pdfToImage.submit=Converter
pdfToImage.info=Python is not installed. Required for WebP conversion.
#addPassword

View File

@@ -291,7 +291,7 @@ compressPdfs.tags=squish,small,tiny
home.changeMetadata.title=Schimbă Metadatele
home.changeMetadata.desc=Schimbă/Elimină/Adaugă metadate într-un document PDF.
changeMetadata.tags==Title,author,date,creation,time,publisher,producer,stats
changeMetadata.tags=Title,author,date,creation,time,publisher,producer,stats
home.fileToPDF.title=Convertește fișierul în PDF
home.fileToPDF.desc=Convertește aproape orice fișier în format PDF (DOCX, PNG, XLS, PPT, TXT și altele).
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Arie minimă a conturului:
ScannerImageSplit.selectText.8=Stabilește pragul minim de arie a conturului pentru o fotografie.
ScannerImageSplit.selectText.9=Mărimea marginii:
ScannerImageSplit.selectText.10=Stabilește mărimea marginii adăugate și eliminate pentru a evita marginile albe în rezultat (implicit: 1).
ScannerImageSplit.info=Python is not installed. It is required to run.
#OCR
@@ -925,6 +926,7 @@ pdfToImage.color=Culoare
pdfToImage.grey=Scală de gri
pdfToImage.blackwhite=Alb și negru (Poate pierde date!)
pdfToImage.submit=Convertă
pdfToImage.info=Python is not installed. Required for WebP conversion.
#addPassword

View File

@@ -291,7 +291,7 @@ compressPdfs.tags=squish,small,tiny
home.changeMetadata.title=Изменить метаданные
home.changeMetadata.desc=Изменить/удалить/добавить метаданные из документа PDF
changeMetadata.tags==Title,author,date,creation,time,publisher,producer,stats
changeMetadata.tags=Title,author,date,creation,time,publisher,producer,stats
home.fileToPDF.title=Конвертировать файл в PDF
home.fileToPDF.desc=Конвертируйте практически любой файл в PDF (DOCX, PNG, XLS, PPT, TXT и другие)
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Минимальная площадь конту
ScannerImageSplit.selectText.8=Устанавливает минимальный порог области контура для фотографии
ScannerImageSplit.selectText.9=Размер границы:
ScannerImageSplit.selectText.10=Устанавливает размер добавляемой и удаляемой границы, чтобы предотвратить появление белых границ на выходе (по умолчанию: 1).
ScannerImageSplit.info=Python is not installed. It is required to run.
#OCR
@@ -925,6 +926,7 @@ pdfToImage.color=Цвет
pdfToImage.grey=Оттенки серого
pdfToImage.blackwhite=Черно-белый (может потерять данные!)
pdfToImage.submit=Конвертировать
pdfToImage.info=Python is not installed. Required for WebP conversion.
#addPassword

View File

@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Minimálna plocha obrysu:
ScannerImageSplit.selectText.8=Nastaví minimálnu prahovú hodnotu plochy obrysu pre fotografiu
ScannerImageSplit.selectText.9=Veľkosť okraja:
ScannerImageSplit.selectText.10=Nastaví veľkosť okraja pridaného a odstráneného, aby sa zabránilo bielym okrajom vo výstupe (predvolené: 1).
ScannerImageSplit.info=Python is not installed. It is required to run.
#OCR
@@ -925,6 +926,7 @@ pdfToImage.color=Farba
pdfToImage.grey=Odtiene šedej
pdfToImage.blackwhite=Čierno-biele (Môže stratiť údaje!)
pdfToImage.submit=Konvertovať
pdfToImage.info=Python is not installed. Required for WebP conversion.
#addPassword

View File

@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Minimalna površina konture:
ScannerImageSplit.selectText.8=Postavlja minimalni prag površine konture za fotografiju
ScannerImageSplit.selectText.9=Veličina ivice:
ScannerImageSplit.selectText.10=Postavlja veličinu ivice dodate i uklonjene kako bi se sprečile bele ivice u izlazu (podrazumevano: 1).
ScannerImageSplit.info=Python is not installed. It is required to run.
#OCR
@@ -925,6 +926,7 @@ pdfToImage.color=Boja
pdfToImage.grey=Nijanse sive
pdfToImage.blackwhite=Crno-belo (Može izgubiti podatke!)
pdfToImage.submit=Konvertuj
pdfToImage.info=Python is not installed. Required for WebP conversion.
#addPassword

View File

@@ -291,7 +291,7 @@ compressPdfs.tags=squish,small,tiny
home.changeMetadata.title=Ändra metadata
home.changeMetadata.desc=Ändra/ta bort/lägg till metadata från ett PDF-dokument
changeMetadata.tags==Title,author,date,creation,time,publisher,producer,stats
changeMetadata.tags=Title,author,date,creation,time,publisher,producer,stats
home.fileToPDF.title=Konvertera fil till PDF
home.fileToPDF.desc=Konvertera nästan vilken fil som helst till PDF (DOCX, PNG, XLS, PPT, TXT och mer)
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Minsta konturarea:
ScannerImageSplit.selectText.8=Ställer in minsta tröskelvärde för konturarea för ett foto
ScannerImageSplit.selectText.9=Kantstorlek:
ScannerImageSplit.selectText.10=Ställer in storleken på kanten som läggs till och tas bort för att förhindra vita kanter i utdata (standard: 1).
ScannerImageSplit.info=Python is not installed. It is required to run.
#OCR
@@ -925,6 +926,7 @@ pdfToImage.color=Färg
pdfToImage.grey=Gråskala
pdfToImage.blackwhite=Svartvitt (kan förlora data!)
pdfToImage.submit=Konvertera
pdfToImage.info=Python is not installed. Required for WebP conversion.
#addPassword

View File

@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=พื้นที่เค้าโครงข
ScannerImageSplit.selectText.8=ตั้งค่าเกณฑ์พื้นที่เค้าโครงขั้นต่ำสำหรับรูปภาพ
ScannerImageSplit.selectText.9=ขนาดขอบ:
ScannerImageSplit.selectText.10=ตั้งค่าขนาดขอบที่เพิ่มและลบเพื่อป้องกันขอบขาวในผลลัพธ์ (ค่าเริ่มต้น: 1)
ScannerImageSplit.info=Python is not installed. It is required to run.
#OCR
@@ -925,6 +926,7 @@ pdfToImage.color=สี
pdfToImage.grey=ระดับสีเทา
pdfToImage.blackwhite=ขาวดำ (อาจสูญเสียข้อมูล!)
pdfToImage.submit=แปลง
pdfToImage.info=Python is not installed. Required for WebP conversion.
#addPassword

View File

@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Minimum Kontur Alanı:
ScannerImageSplit.selectText.8=Bir fotoğraf için minimum kontur alanı eşiğini ayarlar
ScannerImageSplit.selectText.9=Kenar Boyutu:
ScannerImageSplit.selectText.10=Çıktıda beyaz kenarların önlenmesi için eklenen ve kaldırılan kenarın boyutunu ayarlar (varsayılan: 1).
ScannerImageSplit.info=Python is not installed. It is required to run.
#OCR
@@ -925,6 +926,7 @@ pdfToImage.color=Renk
pdfToImage.grey=Gri tonlama
pdfToImage.blackwhite=Siyah ve Beyaz (Veri kaybolabilir!)
pdfToImage.submit=Dönüştür
pdfToImage.info=Python is not installed. Required for WebP conversion.
#addPassword

View File

@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Мінімальна площа контуру:
ScannerImageSplit.selectText.8=Встановлює мінімальний поріг площі контуру для фотографії
ScannerImageSplit.selectText.9=Розмір рамки:
ScannerImageSplit.selectText.10=Встановлює розмір додаваної та видаляної рамки, щоб запобігти появі білих рамок на виході (за замовчуванням: 1).
ScannerImageSplit.info=Python is not installed. It is required to run.
#OCR
@@ -925,6 +926,7 @@ pdfToImage.color=Колір
pdfToImage.grey=Відтінки сірого
pdfToImage.blackwhite=Чорно-білий (може втратити дані!)
pdfToImage.submit=Конвертувати
pdfToImage.info=Python is not installed. Required for WebP conversion.
#addPassword

View File

@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Diện tích đường viền tối thiểu:
ScannerImageSplit.selectText.8=Đặt ngưỡng diện tích đường viền tối thiểu cho một ảnh
ScannerImageSplit.selectText.9=Kích thước viền:
ScannerImageSplit.selectText.10=Đặt kích thước của viền được thêm vào và loại bỏ để ngăn chặn viền trắng trong đầu ra (mặc định: 1).
ScannerImageSplit.info=Python is not installed. It is required to run.
#OCR
@@ -925,6 +926,7 @@ pdfToImage.color=Màu
pdfToImage.grey=Thang độ xám
pdfToImage.blackwhite=Đen trắng (Có thể mất dữ liệu!)
pdfToImage.submit=Chuyển đổi
pdfToImage.info=Python is not installed. Required for WebP conversion.
#addPassword

View File

@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=最小轮廓面积:
ScannerImageSplit.selectText.8=设置照片的最小轮廓面积阈值。
ScannerImageSplit.selectText.9=边框尺寸:
ScannerImageSplit.selectText.10=设置添加和删除的边框大小以防止输出中出现白边默认值1
ScannerImageSplit.info=Python is not installed. It is required to run.
#OCR
@@ -925,6 +926,7 @@ pdfToImage.color=颜色
pdfToImage.grey=灰度
pdfToImage.blackwhite=黑白(可能会丢失数据!)。
pdfToImage.submit=转换
pdfToImage.info=Python is not installed. Required for WebP conversion.
#addPassword

View File

@@ -291,7 +291,7 @@ compressPdfs.tags=壓縮,小,微小
home.changeMetadata.title=變更中繼資料
home.changeMetadata.desc=從 PDF 檔案中變更/移除/新增中繼資料
changeMetadata.tags==標題,作者,日期,建立,時間,出版商,製作人,統計
changeMetadata.tags=標題,作者,日期,建立,時間,出版商,製作人,統計
home.fileToPDF.title=檔案轉 PDF
home.fileToPDF.desc=將幾乎所有格式轉換為 PDFDOCX、PNG、XLS、PPT、TXT 等等)
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=最小輪廓區域:
ScannerImageSplit.selectText.8=設定照片的最小輪廓區域閾值
ScannerImageSplit.selectText.9=邊框大小:
ScannerImageSplit.selectText.10=設定新增和移除的邊框大小以防止輸出中的白色邊框預設1
ScannerImageSplit.info=Python is not installed. It is required to run.
#OCR
@@ -925,6 +926,7 @@ pdfToImage.color=顏色
pdfToImage.grey=灰度
pdfToImage.blackwhite=黑白(可能會遺失資料!)
pdfToImage.submit=轉換
pdfToImage.info=Python is not installed. Required for WebP conversion.
#addPassword

View File

@@ -14,7 +14,7 @@
security:
enableLogin: false # set to 'true' to enable login
csrfDisabled: true # Set to 'true' to disable CSRF protection (not recommended for production)
loginAttemptCount: 5 # lock user account after 5 tries
loginAttemptCount: 5 # lock user account after 5 tries; when using e.g. Fail2Ban you can deactivate the function with -1
loginResetTimeMinutes: 120 # lock account for 2 hours after x attempts
loginMethod: all # 'all' (Login Username/Password and OAuth2[must be enabled and configured]), 'normal'(only Login with Username/Password) or 'oauth2'(only Login with OAuth2)
initialLogin:

View File

@@ -3,14 +3,14 @@
{
"moduleName": "ch.qos.logback:logback-classic",
"moduleUrl": "http://www.qos.ch",
"moduleVersion": "1.5.7",
"moduleVersion": "1.5.6",
"moduleLicense": "GNU Lesser General Public License",
"moduleLicenseUrl": "http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html"
},
{
"moduleName": "ch.qos.logback:logback-core",
"moduleUrl": "http://www.qos.ch",
"moduleVersion": "1.5.7",
"moduleVersion": "1.5.6",
"moduleLicense": "GNU Lesser General Public License",
"moduleLicenseUrl": "http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html"
},

View File

@@ -37,7 +37,7 @@ $(document).ready(function () {
try {
if (remoteCall === true) {
if (override === "multi" || (!multiple && files.length > 1 && override !== "single")) {
if (override === "multi" || (!multipleInputsForSingleRequest && files.length > 1 && override !== "single")) {
await submitMultiPdfForm(url, files);
} else {
await handleSingleDownload(url, formData);

View File

@@ -24,7 +24,7 @@
<form method="post" enctype="multipart/form-data" th:action="@{'/api/v1/misc/auto-split-pdf'}">
<p th:text="#{autoSplitPDF.formPrompt}"></p>
<div
th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}">
th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='application/pdf')}">
</div>
<div class="form-check ms-3">
<input type="checkbox" name="duplexMode" id="duplexMode">

View File

@@ -15,7 +15,7 @@
<div class="col-md-6">
<h2 th:text="#{BookToPDF.header}"></h2>
<form method="post" enctype="multipart/form-data" th:action="@{'/api/v1/convert/book/pdf'}">
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false)}"></div>
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false)}"></div>
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{BookToPDF.submit}"></button>
</form>
<p class="mt-3" th:text="#{BookToPDF.credit}"></p>

View File

@@ -21,7 +21,7 @@
</div>
<p th:text="#{processTimeWarning}"></p>
<form method="post" enctype="multipart/form-data" th:action="@{'/api/v1/convert/file/pdf'}">
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false)}"></div>
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false)}"></div>
<a class="btn btn-outline-primary" data-bs-toggle="collapse" href="#info" role="button"
aria-expanded="false" aria-controls="info" th:text="#{fileToPDF.supportedFileTypesInfo}"></a>
<div class="collapse" id="info">

View File

@@ -18,7 +18,7 @@
<span class="tool-header-text" th:text="#{HTMLToPDF.header}"></span>
</div>
<form method="post" enctype="multipart/form-data" th:action="@{'/api/v1/convert/html/pdf'}">
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='text/html,application/zip' )}"></div>
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='text/html,application/zip' )}"></div>
<div class="mb-3">
<label for="zoom" th:text="#{HTMLToPDF.zoom}" class="form-label"></label>
<input type="number" step="0.1" class="form-control" id="zoom" name="zoom" value="1">

View File

@@ -18,7 +18,7 @@
<span class="tool-header-text" th:text="#{imageToPDF.header}"></span>
</div>
<form method="post" enctype="multipart/form-data" th:action="@{'/api/v1/convert/img/pdf'}">
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='image/*', inputText=#{imgPrompt})}"></div>
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='image/*', inputText=#{imgPrompt})}"></div>
<div class="mb-3">
<label for="fitOption" th:text="#{imageToPDF.selectLabel}">Fit Options</label>
<select class="form-control" id="fitOption" name="fitOption">

View File

@@ -18,7 +18,7 @@
<span class="tool-header-text" th:text="#{MarkdownToPDF.header}"></span>
</div>
<form method="post" enctype="multipart/form-data" th:action="@{'/api/v1/convert/markdown/pdf'}">
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='text/markdown')}"></div>
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='text/markdown')}"></div>
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{MarkdownToPDF.submit}"></button>
</form>
<p class="mt-3" th:text="#{MarkdownToPDF.help}"></p>

View File

@@ -15,7 +15,7 @@
<div class="col-md-6">
<h2 th:text="#{PDFToBook.header}"></h2>
<form method="post" enctype="multipart/form-data" th:action="@{'/api/v1/convert/pdf/book'}">
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"></div>
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='application/pdf')}"></div>
<div class="mb-3">
<label th:text="#{PDFToBook.selectText.1}"></label>
<select class="form-control" name="outputFormat">

View File

@@ -18,7 +18,7 @@
</div>
<form id="PDFToCSVForm" th:action="@{'/api/v1/convert/pdf/csv'}" method="post" enctype="multipart/form-data">
<input id="pageId" type="hidden" name="pageId">
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"></div>
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='application/pdf')}"></div>
<button type="submit" class="btn btn-primary" th:text="#{PDFToCSV.submit}"></button>
</form>
<p id="instruction-text" style="margin: 0; display: none" th:text="#{PDFToCSV.prompt}"></p>

View File

@@ -18,7 +18,7 @@
<span class="tool-header-text" th:text="#{PDFToHTML.header}"></span>
</div>
<form method="post" enctype="multipart/form-data" th:action="@{'/api/v1/convert/pdf/html'}">
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"></div>
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='application/pdf')}"></div>
<br>
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{PDFToHTML.submit}"></button>
</form>

View File

@@ -18,8 +18,9 @@
<span class="tool-header-text" th:text="#{pdfToImage.header}"></span>
</div>
<p th:text="#{processTimeWarning}"></p>
<p th:if="${!isPython}" th:text="#{pdfToImage.info}">Python is not installed. Required for WebP conversion.</p>
<form method="post" enctype="multipart/form-data" th:action="@{'/api/v1/convert/pdf/img'}">
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"></div>
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='application/pdf')}"></div>
<div class="mb-3">
<label th:text="#{pdfToImage.selectText}"></label>
<select class="form-control" name="imageFormat">
@@ -28,7 +29,7 @@
<option value="gif">GIF</option>
<option value="tiff">TIFF</option>
<option value="bmp">BMP</option>
<option value="webp">WEPB</option>
<option th:if="${isPython}" value="webp">WEPB</option>
</select>
</div>
<div class="mb-3">

View File

@@ -19,7 +19,7 @@
</div>
<p th:text="#{pdfToPDFA.tip}"></p>
<form method="post" enctype="multipart/form-data" th:action="@{'/api/v1/convert/pdf/pdfa'}">
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"></div>
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='application/pdf')}"></div>
<div class="mb-3">
<label for="outputFormat" th:text="#{pdfToPDFA.outputFormat}"></label>
<select class="form-control" name="outputFormat" id="outputFormat">

View File

@@ -18,7 +18,7 @@
<span class="tool-header-text" th:text="#{PDFToPresentation.header}"></span>
</div>
<form method="post" enctype="multipart/form-data" th:action="@{'/api/v1/convert/pdf/presentation'}">
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"></div>
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='application/pdf')}"></div>
<div class="mb-3">
<label th:text="#{PDFToPresentation.selectText.1}"></label>
<select class="form-control" name="outputFormat">

View File

@@ -18,7 +18,7 @@
<span class="tool-header-text" th:text="#{PDFToText.header}"></span>
</div>
<form method="post" enctype="multipart/form-data" th:action="@{'/api/v1/convert/pdf/text'}">
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"></div>
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='application/pdf')}"></div>
<div class="mb-3">
<label th:text="#{PDFToText.selectText.1}"></label>
<select class="form-control" name="outputFormat">

View File

@@ -18,7 +18,7 @@
<span class="tool-header-text" th:text="#{PDFToWord.header}"></span>
</div>
<form method="post" enctype="multipart/form-data" th:action="@{'/api/v1/convert/pdf/word'}">
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"></div>
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='application/pdf')}"></div>
<div class="mb-3">
<label th:text="#{PDFToWord.selectText.1}"></label>
<select class="form-control" name="outputFormat">

View File

@@ -18,7 +18,7 @@
<span class="tool-header-text" th:text="#{PDFToXML.header}"></span>
</div>
<form method="post" enctype="multipart/form-data" th:action="@{'/api/v1/convert/pdf/xml'}">
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"></div>
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='application/pdf')}"></div>
<br>
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{PDFToXML.submit}"></button>
</form>

View File

@@ -17,7 +17,7 @@
<span class="tool-header-text" th:text="#{crop.header}"></span>
</div>
<form id="cropForm" th:action="@{'/api/v1/general/crop'}" method="post" enctype="multipart/form-data">
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"></div>
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='application/pdf')}"></div>
<input id="x" type="hidden" name="x">
<input id="y" type="hidden" name="y">
<input id="width" type="hidden" name="width">

View File

@@ -17,7 +17,7 @@
<span class="tool-header-text" th:text="#{pageExtracter.header}"></span>
</div>
<form th:action="@{'/api/v1/general/rearrange-pages'}" method="post" enctype="multipart/form-data">
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"></div>
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='application/pdf')}"></div>
<input type="hidden" id="customMode" name="customMode" value="">
<div class="mb-3">
<label for="pageOrder" th:text="#{pageOrderPrompt}"></label>

View File

@@ -144,17 +144,18 @@
</dialog>
</th:block>
<th:block th:fragment="fileSelector(name, multiple)" th:with="accept=${accept} ?: '*/*', inputText=${inputText} ?: #{pdfPrompt}, remoteCall=${remoteCall} ?: true, notRequired=${notRequired} ?: false">
<th:block th:fragment="fileSelector(name, multipleInputsForSingleRequest)" th:with="accept=${accept} ?: '*/*', inputText=${inputText} ?: #{pdfPrompt}, remoteCall=${remoteCall} ?: true, disableMultipleFiles=${disableMultipleFiles} ?: false, notRequired=${notRequired} ?: false">
<script th:inline="javascript">
const pdfPasswordPrompt = /*[[#{error.pdfPassword}]]*/ '';
const multiple = /*[[${multiple}]]*/ false;
const multipleInputsForSingleRequest = /*[[${multipleInputsForSingleRequest}]]*/ false;
const disableMultipleFiles = /*[[${disableMultipleFiles}]]*/ false;
const remoteCall = /*[[${remoteCall}]]*/ true;
</script>
<script th:src="@{'/js/downloader.js'}"></script>
<div class="custom-file-chooser" th:attr="data-bs-unique-id=${name}, data-bs-element-id=${name+'-input'}, data-bs-files-selected=#{filesSelected}, data-bs-pdf-prompt=#{pdfPrompt}">
<div class="mb-3">
<input type="file" class="form-control" th:name="${name}" th:id="${name}+'-input'" th:accept="${accept}" th:attr="multiple=${multiple}" th:required="${notRequired} ? null : 'required'">
<input type="file" class="form-control" th:name="${name}" th:id="${name}+'-input'" th:accept="${accept}" th:attr="multiple=${!disableMultipleFiles}" th:required="${notRequired} ? null : 'required'">
</div>
<div class="selected-files"></div>
</div>

View File

@@ -20,7 +20,7 @@
<form action="api/v1/general/merge-pdfs" method="post" enctype="multipart/form-data">
<div class="mb-3">
<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', multipleInputsForSingleRequest=true, accept='application/pdf')}"></div>
</div>
<div class="mb-3">
<input type="checkbox" name="removeCertSign" id="removeCertSign">

View File

@@ -20,7 +20,7 @@
</div>
<!-- pdf selector -->
<div th:replace="~{fragments/common :: fileSelector(name='pdf-upload', multiple=false, accept='application/pdf')}"></div>
<div th:replace="~{fragments/common :: fileSelector(name='pdf-upload', multipleInputsForSingleRequest=false, accept='application/pdf')}"></div>
<script>
let originalFileName = '';
document.querySelector('input[name=pdf-upload]').addEventListener('change', async (event) => {
@@ -46,7 +46,7 @@
<div class="tab-group show-on-file-selected">
<div class="tab-container" th:title="#{addImage.upload}">
<div th:replace="~{fragments/common :: fileSelector(name='image-upload', multiple=true, accept='image/*', inputText=#{imgPrompt})}"></div>
<div th:replace="~{fragments/common :: fileSelector(name='image-upload', multipleInputsForSingleRequest=true, accept='image/*', inputText=#{imgPrompt})}"></div>
<script>
const imageUpload = document.querySelector('input[name=image-upload]');
imageUpload.addEventListener('change', e => {

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