Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1e4134c7d1 | ||
|
|
a7bcdd0003 | ||
|
|
121af0501a | ||
|
|
82c4e9cf41 | ||
|
|
142e11a59a |
@@ -33,6 +33,7 @@ RUN echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /et
|
||||
curl \
|
||||
openjdk17-jre \
|
||||
su-exec \
|
||||
shadow \
|
||||
# Doc conversion
|
||||
libreoffice@testing \
|
||||
# OCR MY PDF (unpaper for descew and other advanced featues)
|
||||
|
||||
@@ -29,8 +29,10 @@ RUN echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /et
|
||||
tini \
|
||||
bash \
|
||||
curl \
|
||||
gcc \
|
||||
openjdk17-jre \
|
||||
su-exec \
|
||||
shadow \
|
||||
# Doc conversion
|
||||
libreoffice@testing \
|
||||
# python and pip
|
||||
|
||||
@@ -30,6 +30,7 @@ RUN mkdir /configs /logs /customFiles && \
|
||||
bash \
|
||||
curl \
|
||||
su-exec \
|
||||
shadow \
|
||||
openjdk17-jre && \
|
||||
echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /etc/apk/repositories && \
|
||||
echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/community" | tee -a /etc/apk/repositories && \
|
||||
|
||||
@@ -12,7 +12,8 @@ plugins {
|
||||
import com.github.jk1.license.render.*
|
||||
|
||||
group = 'stirling.software'
|
||||
version = '0.22.0'
|
||||
|
||||
version = '0.22.2'
|
||||
sourceCompatibility = '17'
|
||||
|
||||
repositories {
|
||||
@@ -158,6 +159,8 @@ dependencies {
|
||||
// https://mvnrepository.com/artifact/com.github.vladimir-bukhtoyarov/bucket4j-core
|
||||
implementation 'com.github.vladimir-bukhtoyarov:bucket4j-core:7.6.0'
|
||||
|
||||
implementation 'com.fathzer:javaluator:3.0.3'
|
||||
|
||||
developmentOnly("org.springframework.boot:spring-boot-devtools:3.2.2")
|
||||
compileOnly 'org.projectlombok:lombok:1.18.30'
|
||||
annotationProcessor 'org.projectlombok:lombok:1.18.28'
|
||||
|
||||
@@ -21,6 +21,9 @@ services:
|
||||
environment:
|
||||
DOCKER_ENABLE_SECURITY: "true"
|
||||
SECURITY_ENABLELOGIN: "true"
|
||||
PUID: 1002
|
||||
GGID: 1002
|
||||
UMASK: "022"
|
||||
SYSTEM_DEFAULTLOCALE: en-US
|
||||
UI_APPNAME: Stirling-PDF
|
||||
UI_HOMEDESCRIPTION: Demo site for Stirling-PDF Latest with Security
|
||||
|
||||
@@ -14,8 +14,8 @@ if [ "$DOCKER_ENABLE_SECURITY" = "true" ] && [ "$VERSION_TAG" != "alpha" ]; then
|
||||
if [ $? -eq 0 ]; then # checks if curl was successful
|
||||
rm -f app.jar
|
||||
ln -s app-security.jar app.jar
|
||||
chown stirlingpdfuser:stirlingpdfgroup app.jar
|
||||
chmod 755 app.jar
|
||||
chown stirlingpdfuser:stirlingpdfgroup app.jar || true
|
||||
chmod 755 app.jar || true
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -2,22 +2,21 @@
|
||||
|
||||
# Update the user and group IDs as per environment variables
|
||||
if [ ! -z "$PUID" ] && [ "$PUID" != "$(id -u stirlingpdfuser)" ]; then
|
||||
usermod -o -u "$PUID" stirlingpdfuser
|
||||
usermod -o -u "$PUID" stirlingpdfuser || true
|
||||
fi
|
||||
|
||||
if [ ! -z "$PGID" ] && [ "$PGID" != "$(id -g stirlingpdfgroup)" ]; then
|
||||
groupmod -o -g "$PGID" stirlingpdfgroup
|
||||
if [ ! -z "$PGID" ] && [ "$PGID" != "$(getent group stirlingpdfgroup | cut -d: -f3)" ]; then
|
||||
groupmod -o -g "$PGID" stirlingpdfgroup || true
|
||||
fi
|
||||
umask "$UMASK"
|
||||
umask "$UMASK" || true
|
||||
|
||||
echo "Setting permissions and ownership for necessary directories..."
|
||||
chown -R stirlingpdfuser:stirlingpdfgroup /logs /scripts /usr/share/fonts/opentype/noto /usr/share/tessdata /configs /customFiles
|
||||
chmod -R 755 /logs /scripts /usr/share/fonts/opentype/noto /usr/share/tessdata /configs /customFiles
|
||||
chown -R stirlingpdfuser:stirlingpdfgroup $HOME /logs /scripts /usr/share/fonts/opentype/noto /usr/share/tessdata /configs /customFiles /pipeline /app.jar || true
|
||||
chmod -R 755 /logs /scripts /usr/share/fonts/opentype/noto /usr/share/tessdata /configs /customFiles /pipeline /app.jar || true
|
||||
if [[ "$INSTALL_BOOK_AND_ADVANCED_HTML_OPS" == "true" ]]; then
|
||||
apk add --no-cache calibre@testing
|
||||
fi
|
||||
|
||||
|
||||
/scripts/download-security-jar.sh
|
||||
|
||||
# Run the main command
|
||||
|
||||
@@ -13,20 +13,20 @@ if [ -d /usr/share/tesseract-ocr/5/tessdata ]; then
|
||||
cp -r /usr/share/tesseract-ocr/5/tessdata/* /usr/share/tessdata || true;
|
||||
fi
|
||||
|
||||
|
||||
# Update the user and group IDs as per environment variables
|
||||
if [ ! -z "$PUID" ] && [ "$PUID" != "$(id -u stirlingpdfuser)" ]; then
|
||||
usermod -o -u "$PUID" stirlingpdfuser
|
||||
usermod -o -u "$PUID" stirlingpdfuser || true
|
||||
fi
|
||||
|
||||
if [ ! -z "$PGID" ] && [ "$PGID" != "$(id -g stirlingpdfgroup)" ]; then
|
||||
groupmod -o -g "$PGID" stirlingpdfgroup
|
||||
|
||||
if [ ! -z "$PGID" ] && [ "$PGID" != "$(getent group stirlingpdfgroup | cut -d: -f3)" ]; then
|
||||
groupmod -o -g "$PGID" stirlingpdfgroup || true
|
||||
fi
|
||||
umask "$UMASK"
|
||||
umask "$UMASK" || true
|
||||
|
||||
echo "Setting permissions and ownership for necessary directories..."
|
||||
chown -R stirlingpdfuser:stirlingpdfgroup /logs /scripts /usr/share/fonts/opentype/noto /usr/share/tessdata /configs /customFiles
|
||||
chmod -R 755 /logs /scripts /usr/share/fonts/opentype/noto /usr/share/tessdata /configs /customFiles
|
||||
chown -R stirlingpdfuser:stirlingpdfgroup $HOME /logs /scripts /usr/share/fonts/opentype/noto /usr/share/tessdata /configs /customFiles /pipeline /app.jar || true
|
||||
chmod -R 755 /logs /scripts /usr/share/fonts/opentype/noto /usr/share/tessdata /configs /customFiles /pipeline /app.jar || true
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -60,6 +60,5 @@ public class CustomAuthenticationFailureHandler extends SimpleUrlAuthenticationF
|
||||
return user.isPresent()
|
||||
&& user.get().getAuthorities().stream()
|
||||
.anyMatch(authority -> "ROLE_DEMO_USER".equals(authority.getAuthority()));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,10 +66,11 @@ public class SecurityConfiguration {
|
||||
sessionManagement ->
|
||||
sessionManagement
|
||||
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
|
||||
.maximumSessions(3)
|
||||
.maxSessionsPreventsLogin(true)
|
||||
.maximumSessions(10)
|
||||
.maxSessionsPreventsLogin(false)
|
||||
.sessionRegistry(sessionRegistry())
|
||||
.expiredUrl("/login?logout=true"));
|
||||
|
||||
http.formLogin(
|
||||
formLogin ->
|
||||
formLogin
|
||||
@@ -92,8 +93,7 @@ public class SecurityConfiguration {
|
||||
.addLogoutHandler(
|
||||
(request, response, authentication) -> {
|
||||
HttpSession session =
|
||||
request.getSession(
|
||||
false);
|
||||
request.getSession(false);
|
||||
if (session != null) {
|
||||
String sessionId = session.getId();
|
||||
sessionRegistry()
|
||||
|
||||
@@ -51,7 +51,7 @@ public class RearrangePagesPDFController {
|
||||
String[] pageOrderArr = pagesToDelete.split(",");
|
||||
|
||||
List<Integer> pagesToRemove =
|
||||
GeneralUtils.parsePageList(pageOrderArr, document.getNumberOfPages(), true);
|
||||
GeneralUtils.parsePageList(pageOrderArr, document.getNumberOfPages(), false);
|
||||
|
||||
Collections.sort(pagesToRemove);
|
||||
|
||||
@@ -195,7 +195,7 @@ public class RearrangePagesPDFController {
|
||||
if (sortType != null && sortType.length() > 0) {
|
||||
newPageOrder = processSortTypes(sortType, totalPages);
|
||||
} else {
|
||||
newPageOrder = GeneralUtils.parsePageList(pageOrderArr, totalPages, true);
|
||||
newPageOrder = GeneralUtils.parsePageList(pageOrderArr, totalPages, false);
|
||||
}
|
||||
logger.info("newPageOrder = " + newPageOrder);
|
||||
logger.info("totalPages = " + totalPages);
|
||||
|
||||
@@ -49,12 +49,14 @@ public class SplitPDFController {
|
||||
// open the pdf document
|
||||
|
||||
PDDocument document = Loader.loadPDF(file.getBytes());
|
||||
|
||||
List<Integer> pageNumbers = request.getPageNumbersList(document, true);
|
||||
if (!pageNumbers.contains(document.getNumberOfPages() - 1)) {
|
||||
int totalPages = document.getNumberOfPages();
|
||||
List<Integer> pageNumbers = request.getPageNumbersList(document, false);
|
||||
System.out.println(
|
||||
pageNumbers.stream().map(String::valueOf).collect(Collectors.joining(",")));
|
||||
if (!pageNumbers.contains(totalPages - 1)) {
|
||||
// Create a mutable ArrayList so we can add to it
|
||||
pageNumbers = new ArrayList<>(pageNumbers);
|
||||
pageNumbers.add(document.getNumberOfPages() - 1);
|
||||
pageNumbers.add(totalPages - 1);
|
||||
}
|
||||
|
||||
logger.info(
|
||||
@@ -69,7 +71,7 @@ public class SplitPDFController {
|
||||
for (int i = previousPageNumber; i <= splitPoint; i++) {
|
||||
PDPage page = document.getPage(i);
|
||||
splitDocument.addPage(page);
|
||||
logger.debug("Adding page {} to split document", i);
|
||||
logger.info("Adding page {} to split document", i);
|
||||
}
|
||||
previousPageNumber = splitPoint + 1;
|
||||
|
||||
|
||||
@@ -56,8 +56,8 @@ public class UserController {
|
||||
@PostMapping("/change-username")
|
||||
public RedirectView changeUsername(
|
||||
Principal principal,
|
||||
@RequestParam String currentPassword,
|
||||
@RequestParam String newUsername,
|
||||
@RequestParam(name = "currentPassword") String currentPassword,
|
||||
@RequestParam(name = "newUsername") String newUsername,
|
||||
HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
RedirectAttributes redirectAttributes) {
|
||||
@@ -95,8 +95,8 @@ public class UserController {
|
||||
@PostMapping("/change-password-on-login")
|
||||
public RedirectView changePasswordOnLogin(
|
||||
Principal principal,
|
||||
@RequestParam String currentPassword,
|
||||
@RequestParam String newPassword,
|
||||
@RequestParam(name = "currentPassword") String currentPassword,
|
||||
@RequestParam(name = "newPassword") String newPassword,
|
||||
HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
RedirectAttributes redirectAttributes) {
|
||||
@@ -128,8 +128,8 @@ public class UserController {
|
||||
@PostMapping("/change-password")
|
||||
public RedirectView changePassword(
|
||||
Principal principal,
|
||||
@RequestParam String currentPassword,
|
||||
@RequestParam String newPassword,
|
||||
@RequestParam(name = "currentPassword") String currentPassword,
|
||||
@RequestParam(name = "newPassword") String newPassword,
|
||||
HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
RedirectAttributes redirectAttributes) {
|
||||
@@ -180,9 +180,9 @@ public class UserController {
|
||||
@PreAuthorize("hasRole('ROLE_ADMIN')")
|
||||
@PostMapping("/admin/saveUser")
|
||||
public RedirectView saveUser(
|
||||
@RequestParam String username,
|
||||
@RequestParam String password,
|
||||
@RequestParam String role,
|
||||
@RequestParam(name = "username") String username,
|
||||
@RequestParam(name = "password") String password,
|
||||
@RequestParam(name = "role") String role,
|
||||
@RequestParam(name = "forceChange", required = false, defaultValue = "false")
|
||||
boolean forceChange) {
|
||||
|
||||
@@ -207,7 +207,8 @@ public class UserController {
|
||||
|
||||
@PreAuthorize("hasRole('ROLE_ADMIN')")
|
||||
@PostMapping("/admin/deleteUser/{username}")
|
||||
public RedirectView deleteUser(@PathVariable String username, Authentication authentication) {
|
||||
public RedirectView deleteUser(
|
||||
@PathVariable(name = "username") String username, Authentication authentication) {
|
||||
|
||||
if (!userService.usernameExists(username)) {
|
||||
return new RedirectView("/addUsers?messageType=deleteUsernameExists");
|
||||
|
||||
@@ -142,7 +142,8 @@ public class ExtractImageScansController {
|
||||
.runCommandWithOutputHandling(command);
|
||||
|
||||
// Read the output photos in temp directory
|
||||
List<Path> tempOutputFiles = Files.list(tempDir).sorted().collect(Collectors.toList());
|
||||
List<Path> tempOutputFiles =
|
||||
Files.list(tempDir).sorted().collect(Collectors.toList());
|
||||
for (Path tempOutputFile : tempOutputFiles) {
|
||||
byte[] imageBytes = Files.readAllBytes(tempOutputFile);
|
||||
processedImageBytes.add(imageBytes);
|
||||
@@ -153,7 +154,8 @@ public class ExtractImageScansController {
|
||||
|
||||
// Create zip file if multiple images
|
||||
if (processedImageBytes.size() > 1) {
|
||||
String outputZipFilename = fileName.replaceFirst("[.][^.]+$", "") + "_processed.zip";
|
||||
String outputZipFilename =
|
||||
fileName.replaceFirst("[.][^.]+$", "") + "_processed.zip";
|
||||
tempZipFile = Files.createTempFile("output_", ".zip");
|
||||
|
||||
try (ZipOutputStream zipOut =
|
||||
@@ -189,7 +191,8 @@ public class ExtractImageScansController {
|
||||
}
|
||||
} finally {
|
||||
// Cleanup logic for all temporary files and directories
|
||||
tempImageFiles.forEach(path -> {
|
||||
tempImageFiles.forEach(
|
||||
path -> {
|
||||
try {
|
||||
Files.deleteIfExists(path);
|
||||
} catch (IOException e) {
|
||||
@@ -205,7 +208,8 @@ public class ExtractImageScansController {
|
||||
}
|
||||
}
|
||||
|
||||
tempDirs.forEach(dir -> {
|
||||
tempDirs.forEach(
|
||||
dir -> {
|
||||
try {
|
||||
FileUtils.deleteDirectory(dir.toFile());
|
||||
} catch (IOException e) {
|
||||
|
||||
@@ -88,7 +88,7 @@ public class StampController {
|
||||
// Load the input PDF
|
||||
PDDocument document = Loader.loadPDF(pdfFile.getBytes());
|
||||
|
||||
List<Integer> pageNumbers = request.getPageNumbersList(document, false);
|
||||
List<Integer> pageNumbers = request.getPageNumbersList(document, true);
|
||||
|
||||
for (int pageIndex : pageNumbers) {
|
||||
int zeroBasedIndex = pageIndex - 1;
|
||||
|
||||
@@ -33,13 +33,13 @@ public class PDFWithPageNums extends PDFFile {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
return GeneralUtils.parsePageString(pageNumbers, pageCount, zeroCount);
|
||||
return GeneralUtils.parsePageList(pageNumbers, pageCount, zeroCount);
|
||||
}
|
||||
|
||||
@Hidden
|
||||
public List<Integer> getPageNumbersList(PDDocument doc, boolean zeroCount) {
|
||||
int pageCount = 0;
|
||||
pageCount = doc.getNumberOfPages();
|
||||
return GeneralUtils.parsePageString(pageNumbers, pageCount, zeroCount);
|
||||
return GeneralUtils.parsePageList(pageNumbers, pageCount, zeroCount);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,11 +12,12 @@ import java.nio.file.Paths;
|
||||
import java.nio.file.SimpleFileVisitor;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import com.fathzer.soft.javaluator.DoubleEvaluator;
|
||||
|
||||
import io.github.pixee.security.HostValidator;
|
||||
import io.github.pixee.security.Urls;
|
||||
|
||||
@@ -115,91 +116,114 @@ public class GeneralUtils {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static List<Integer> parsePageString(String pageOrder, int totalPages) {
|
||||
return parsePageString(pageOrder, totalPages, false);
|
||||
public static List<Integer> parsePageList(String pages, int totalPages, boolean oneBased) {
|
||||
if (pages == null) {
|
||||
return List.of(1); // Default to first page if input is null
|
||||
}
|
||||
try {
|
||||
return parsePageList(pages.split(","), totalPages, oneBased);
|
||||
} catch (NumberFormatException e) {
|
||||
return List.of(1); // Default to first page if input is invalid
|
||||
}
|
||||
}
|
||||
|
||||
public static List<Integer> parsePageString(
|
||||
String pageOrder, int totalPages, boolean isOneBased) {
|
||||
if (pageOrder == null || pageOrder.isEmpty()) {
|
||||
return Collections.singletonList(1);
|
||||
}
|
||||
if (pageOrder.matches("\\d+")) {
|
||||
// Convert the single number string to an integer and return it in a list
|
||||
return Collections.singletonList(Integer.parseInt(pageOrder));
|
||||
}
|
||||
return parsePageList(pageOrder.split(","), totalPages, isOneBased);
|
||||
public static List<Integer> parsePageList(String[] pages, int totalPages) {
|
||||
return parsePageList(pages, totalPages, false);
|
||||
}
|
||||
|
||||
public static List<Integer> parsePageList(String[] pageOrderArr, int totalPages) {
|
||||
return parsePageList(pageOrderArr, totalPages, false);
|
||||
}
|
||||
|
||||
public static List<Integer> parsePageList(
|
||||
String[] pageOrderArr, int totalPages, boolean isOneBased) {
|
||||
List<Integer> newPageOrder = new ArrayList<>();
|
||||
|
||||
int adjustmentFactor = isOneBased ? 1 : 0;
|
||||
|
||||
// loop through the page order array
|
||||
for (String element : pageOrderArr) {
|
||||
if ("all".equalsIgnoreCase(element)) {
|
||||
public static List<Integer> parsePageList(String[] pages, int totalPages, boolean oneBased) {
|
||||
List<Integer> result = new ArrayList<>();
|
||||
int offset = oneBased ? 1 : 0;
|
||||
for (String page : pages) {
|
||||
if ("all".equalsIgnoreCase(page)) {
|
||||
for (int i = 0; i < totalPages; i++) {
|
||||
newPageOrder.add(i + adjustmentFactor);
|
||||
result.add(i + offset);
|
||||
}
|
||||
// As all pages are already added, no need to check further
|
||||
break;
|
||||
} else if (element.matches("\\d*n\\+?-?\\d*|\\d*\\+?n")) {
|
||||
// Handle page order as a function
|
||||
int coefficient = 0;
|
||||
int constant = 0;
|
||||
boolean coefficientExists = false;
|
||||
boolean constantExists = false;
|
||||
|
||||
if (element.contains("n")) {
|
||||
String[] parts = element.split("n");
|
||||
if (!"".equals(parts[0]) && parts[0] != null) {
|
||||
coefficient = Integer.parseInt(parts[0]);
|
||||
coefficientExists = true;
|
||||
}
|
||||
if (parts.length > 1 && !"".equals(parts[1]) && parts[1] != null) {
|
||||
constant = Integer.parseInt(parts[1]);
|
||||
constantExists = true;
|
||||
}
|
||||
} else if (element.contains("+")) {
|
||||
constant = Integer.parseInt(element.replace("+", ""));
|
||||
constantExists = true;
|
||||
}
|
||||
|
||||
for (int i = 1; i <= totalPages; i++) {
|
||||
int pageNum = coefficientExists ? coefficient * i : i;
|
||||
pageNum += constantExists ? constant : 0;
|
||||
|
||||
if (pageNum <= totalPages && pageNum > 0) {
|
||||
newPageOrder.add(pageNum - adjustmentFactor);
|
||||
}
|
||||
}
|
||||
} else if (element.contains("-")) {
|
||||
// split the range into start and end page
|
||||
String[] range = element.split("-");
|
||||
int start = Integer.parseInt(range[0]);
|
||||
int end = Integer.parseInt(range[1]);
|
||||
// check if the end page is greater than total pages
|
||||
if (end > totalPages) {
|
||||
end = totalPages;
|
||||
}
|
||||
// loop through the range of pages
|
||||
for (int j = start; j <= end; j++) {
|
||||
// print the current index
|
||||
newPageOrder.add(j - adjustmentFactor);
|
||||
} else if (page.contains(",")) {
|
||||
// Split the string into parts, could be single pages or ranges
|
||||
String[] parts = page.split(",");
|
||||
for (String part : parts) {
|
||||
result.addAll(handlePart(part, totalPages, offset));
|
||||
}
|
||||
} else {
|
||||
// if the element is a single page
|
||||
newPageOrder.add(Integer.parseInt(element) - adjustmentFactor);
|
||||
result.addAll(handlePart(page, totalPages, offset));
|
||||
}
|
||||
}
|
||||
return new ArrayList<>(
|
||||
new java.util.LinkedHashSet<>(result)); // Remove duplicates and maintain order
|
||||
}
|
||||
|
||||
return newPageOrder;
|
||||
public static List<Integer> evaluateNFunc(String expression, int maxValue) {
|
||||
List<Integer> results = new ArrayList<>();
|
||||
DoubleEvaluator evaluator = new DoubleEvaluator();
|
||||
|
||||
// Validate the expression
|
||||
if (!expression.matches("[0-9n+\\-*/() ]+")) {
|
||||
throw new IllegalArgumentException("Invalid expression");
|
||||
}
|
||||
|
||||
int n = 0;
|
||||
while (true) {
|
||||
// Replace 'n' with the current value of n, correctly handling numbers before 'n'
|
||||
String sanitizedExpression = insertMultiplicationBeforeN(expression, n);
|
||||
Double result = evaluator.evaluate(sanitizedExpression);
|
||||
|
||||
// Check if the result is null or not within bounds
|
||||
if (result == null || result <= 0 || result.intValue() > maxValue) {
|
||||
if (n != 0) break;
|
||||
} else {
|
||||
results.add(result.intValue());
|
||||
}
|
||||
n++;
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
private static String insertMultiplicationBeforeN(String expression, int nValue) {
|
||||
// Insert multiplication between a number and 'n' (e.g., "4n" becomes "4*n")
|
||||
String withMultiplication = expression.replaceAll("(\\d)n", "$1*n");
|
||||
// Now replace 'n' with its current value
|
||||
return withMultiplication.replaceAll("n", String.valueOf(nValue));
|
||||
}
|
||||
|
||||
private static List<Integer> handlePart(String part, int totalPages, int offset) {
|
||||
List<Integer> partResult = new ArrayList<>();
|
||||
|
||||
// First check for n-syntax because it should not be processed as a range
|
||||
if (part.contains("n")) {
|
||||
partResult = evaluateNFunc(part, totalPages);
|
||||
// Adjust the results according to the offset
|
||||
for (int i = 0; i < partResult.size(); i++) {
|
||||
int adjustedValue = partResult.get(i) - 1 + offset;
|
||||
partResult.set(i, adjustedValue);
|
||||
}
|
||||
} else if (part.contains("-")) {
|
||||
// Process ranges only if it's not n-syntax
|
||||
String[] rangeParts = part.split("-");
|
||||
try {
|
||||
int start = Integer.parseInt(rangeParts[0]);
|
||||
int end = Integer.parseInt(rangeParts[1]);
|
||||
for (int i = start; i <= end; i++) {
|
||||
if (i >= 1 && i <= totalPages) {
|
||||
partResult.add(i - 1 + offset);
|
||||
}
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
// Range is invalid, ignore this part
|
||||
}
|
||||
} else {
|
||||
// This is a single page number
|
||||
try {
|
||||
int pageNum = Integer.parseInt(part.trim());
|
||||
if (pageNum >= 1 && pageNum <= totalPages) {
|
||||
partResult.add(pageNum - 1 + offset);
|
||||
}
|
||||
} catch (NumberFormatException ignored) {
|
||||
// Ignore invalid numbers
|
||||
}
|
||||
}
|
||||
return partResult;
|
||||
}
|
||||
|
||||
public static boolean createDir(String path) {
|
||||
|
||||
@@ -413,6 +413,7 @@ BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
|
||||
###########################
|
||||
#login
|
||||
login.title=Sign in
|
||||
login.header=Sign in
|
||||
login.signin=Sign in
|
||||
login.rememberme=Remember me
|
||||
login.invalid=Invalid username or password.
|
||||
@@ -951,6 +952,7 @@ PDFToCSV.prompt=Choose page to extract table
|
||||
PDFToCSV.submit=??????
|
||||
|
||||
#split-by-size-or-count
|
||||
split-by-size-or-count.title=Split PDF by Size or Count
|
||||
split-by-size-or-count.header=Split PDF by Size or Count
|
||||
split-by-size-or-count.type.label=Select Split Type
|
||||
split-by-size-or-count.type.size=By Size
|
||||
|
||||
@@ -413,6 +413,7 @@ BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
|
||||
###########################
|
||||
#login
|
||||
login.title=Вход
|
||||
login.header=Вход
|
||||
login.signin=Впишете се
|
||||
login.rememberme=Запомни ме
|
||||
login.invalid=Невалидно потребителско име или парола.
|
||||
@@ -951,6 +952,7 @@ PDFToCSV.prompt=Choose page to extract table
|
||||
PDFToCSV.submit=????????
|
||||
|
||||
#split-by-size-or-count
|
||||
split-by-size-or-count.title=Split PDF by Size or Count
|
||||
split-by-size-or-count.header=Split PDF by Size or Count
|
||||
split-by-size-or-count.type.label=Select Split Type
|
||||
split-by-size-or-count.type.size=By Size
|
||||
|
||||
@@ -413,6 +413,7 @@ BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
|
||||
###########################
|
||||
#login
|
||||
login.title=Accedir
|
||||
login.header=Accedir
|
||||
login.signin=Accedir
|
||||
login.rememberme=Recordar
|
||||
login.invalid=Nom usuari / password no vàlid
|
||||
@@ -951,6 +952,7 @@ PDFToCSV.prompt=Choose page to extract table
|
||||
PDFToCSV.submit=Extracte
|
||||
|
||||
#split-by-size-or-count
|
||||
split-by-size-or-count.title=Split PDF by Size or Count
|
||||
split-by-size-or-count.header=Split PDF by Size or Count
|
||||
split-by-size-or-count.type.label=Select Split Type
|
||||
split-by-size-or-count.type.size=By Size
|
||||
|
||||
@@ -413,6 +413,7 @@ BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
|
||||
###########################
|
||||
#login
|
||||
login.title=Anmelden
|
||||
login.header=Anmelden
|
||||
login.signin=Anmelden
|
||||
login.rememberme=Angemeldet bleiben
|
||||
login.invalid=Ungültiger Benutzername oder Passwort.
|
||||
@@ -773,7 +774,7 @@ pageRemover.submit=Seiten löschen
|
||||
rotate.title=PDF drehen
|
||||
rotate.header=PDF drehen
|
||||
rotate.selectAngle=Wählen Sie den Winkel (in Vielfachen von 90 Grad):
|
||||
rotate.submit=Drehen
|
||||
rotate.submit=Herunterladen
|
||||
|
||||
|
||||
#merge
|
||||
@@ -951,6 +952,7 @@ PDFToCSV.prompt=Seite mit der zu extrahierenden Tabelle wählen
|
||||
PDFToCSV.submit=Extrahieren
|
||||
|
||||
#split-by-size-or-count
|
||||
split-by-size-or-count.title=PDF nach Größe oder Anzahl teilen
|
||||
split-by-size-or-count.header=PDF nach Größe oder Anzahl teilen
|
||||
split-by-size-or-count.type.label=Teil-Modus wählen
|
||||
split-by-size-or-count.type.size=Nach Größe
|
||||
|
||||
@@ -413,6 +413,7 @@ BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
|
||||
###########################
|
||||
#login
|
||||
login.title=\u0395\u03AF\u03C3\u03BF\u03B4\u03BF\u03C2
|
||||
login.header=\u0395\u03AF\u03C3\u03BF\u03B4\u03BF\u03C2
|
||||
login.signin=\u0395\u03AF\u03C3\u03BF\u03B4\u03BF\u03C2
|
||||
login.rememberme=\u039D\u03B1 \u039C\u03B5 \u0398\u03C5\u03BC\u03AC\u03C3\u03B1\u03B9
|
||||
login.invalid=\u039B\u03AC\u03B8\u03BF\u03C2 \u03CC\u03BD\u03BF\u03BC\u03B1 \u03C7\u03C1\u03AE\u03C3\u03C4\u03B7 \u03AE \u03BA\u03C9\u03B4\u03B9\u03BA\u03BF\u03CD \u03C0\u03C1\u03CC\u03C3\u03B2\u03B1\u03C3\u03B7\u03C2.
|
||||
@@ -951,6 +952,7 @@ PDFToCSV.prompt=Choose page to extract table
|
||||
PDFToCSV.submit=?????????
|
||||
|
||||
#split-by-size-or-count
|
||||
split-by-size-or-count.title=Split PDF by Size or Count
|
||||
split-by-size-or-count.header=Split PDF by Size or Count
|
||||
split-by-size-or-count.type.label=Select Split Type
|
||||
split-by-size-or-count.type.size=By Size
|
||||
|
||||
@@ -413,6 +413,7 @@ BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle,epub,mobi,azw3,doc
|
||||
###########################
|
||||
#login
|
||||
login.title=Sign in
|
||||
login.header=Sign in
|
||||
login.signin=Sign in
|
||||
login.rememberme=Remember me
|
||||
login.invalid=Invalid username or password.
|
||||
@@ -951,6 +952,7 @@ PDFToCSV.prompt=Choose page to extract table
|
||||
PDFToCSV.submit=Extract
|
||||
|
||||
#split-by-size-or-count
|
||||
split-by-size-or-count.title=Split PDF by Size or Count
|
||||
split-by-size-or-count.header=Split PDF by Size or Count
|
||||
split-by-size-or-count.type.label=Select Split Type
|
||||
split-by-size-or-count.type.size=By Size
|
||||
|
||||
@@ -413,6 +413,7 @@ BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
|
||||
###########################
|
||||
#login
|
||||
login.title=Sign in
|
||||
login.header=Sign in
|
||||
login.signin=Sign in
|
||||
login.rememberme=Remember me
|
||||
login.invalid=Invalid username or password.
|
||||
@@ -951,6 +952,7 @@ PDFToCSV.prompt=Choose page to extract table
|
||||
PDFToCSV.submit=Extract
|
||||
|
||||
#split-by-size-or-count
|
||||
split-by-size-or-count.title=Split PDF by Size or Count
|
||||
split-by-size-or-count.header=Split PDF by Size or Count
|
||||
split-by-size-or-count.type.label=Select Split Type
|
||||
split-by-size-or-count.type.size=By Size
|
||||
|
||||
@@ -413,6 +413,7 @@ BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
|
||||
###########################
|
||||
#login
|
||||
login.title=Iniciar sesión
|
||||
login.header=Iniciar sesión
|
||||
login.signin=Iniciar sesión
|
||||
login.rememberme=Recordarme
|
||||
login.invalid=Nombre de usuario o contraseña erróneos.
|
||||
@@ -951,6 +952,7 @@ PDFToCSV.prompt=Elija una página para extraer la tabla
|
||||
PDFToCSV.submit=Extraer
|
||||
|
||||
#split-by-size-or-count
|
||||
split-by-size-or-count.title=Split PDF by Size or Count
|
||||
split-by-size-or-count.header=Dividir PDF por tamaño o número
|
||||
split-by-size-or-count.type.label=Seleccionar tipo de división
|
||||
split-by-size-or-count.type.size=Por tamaño
|
||||
|
||||
@@ -413,6 +413,7 @@ BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
|
||||
###########################
|
||||
#login
|
||||
login.title=Saioa hasi
|
||||
login.header=Saioa hasi
|
||||
login.signin=Saioa hasi
|
||||
login.rememberme=Oroitu nazazu
|
||||
login.invalid=Okerreko erabiltzaile izena edo pasahitza.
|
||||
@@ -951,6 +952,7 @@ PDFToCSV.prompt=Choose page to extract table
|
||||
PDFToCSV.submit=Extracto
|
||||
|
||||
#split-by-size-or-count
|
||||
split-by-size-or-count.title=Split PDF by Size or Count
|
||||
split-by-size-or-count.header=Split PDF by Size or Count
|
||||
split-by-size-or-count.type.label=Select Split Type
|
||||
split-by-size-or-count.type.size=By Size
|
||||
|
||||
@@ -413,6 +413,7 @@ BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
|
||||
###########################
|
||||
#login
|
||||
login.title=Connexion
|
||||
login.header=Connexion
|
||||
login.signin=Connexion
|
||||
login.rememberme=Se souvenir de moi
|
||||
login.invalid=Nom d\u2019utilisateur ou mot de passe invalide.
|
||||
@@ -951,6 +952,7 @@ PDFToCSV.prompt=Choisir la page pour en extraire le tableau
|
||||
PDFToCSV.submit=Extrait
|
||||
|
||||
#split-by-size-or-count
|
||||
split-by-size-or-count.title=Séparer le PDF par taille ou par nombre
|
||||
split-by-size-or-count.header=Séparer le PDF par taille ou par nombre
|
||||
split-by-size-or-count.type.label=Sélectionner le type de division
|
||||
split-by-size-or-count.type.size=Par taille
|
||||
|
||||
@@ -413,6 +413,7 @@ BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
|
||||
###########################
|
||||
#login
|
||||
login.title=साइन इन करें
|
||||
login.header=साइन इन करें
|
||||
login.signin=साइन इन करें
|
||||
login.rememberme=मुझे याद रखें
|
||||
login.invalid=अमान्य उपयोगकर्ता नाम या पासवर्ड।
|
||||
@@ -951,6 +952,7 @@ PDFToCSV.prompt=टेबल निकालने के लिए पृष्
|
||||
PDFToCSV.submit=निकालें
|
||||
|
||||
#split-by-size-or-count
|
||||
split-by-size-or-count.title=आकार या गणना द्वारा PDF को विभाजित करें
|
||||
split-by-size-or-count.header=आकार या गणना द्वारा PDF को विभाजित करें
|
||||
split-by-size-or-count.type.label=स्प्लिट प्रकार चुनें
|
||||
split-by-size-or-count.type.size=आकार द्वारा
|
||||
|
||||
@@ -413,6 +413,7 @@ BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
|
||||
###########################
|
||||
#login
|
||||
login.title=Bejelentkezés
|
||||
login.header=Bejelentkezés
|
||||
login.signin=Bejelentkezés
|
||||
login.rememberme=Emlékezz rám
|
||||
login.invalid=Érvénytelen felhasználónév vagy jelszó!
|
||||
@@ -951,6 +952,7 @@ PDFToCSV.prompt=Válassza ki az oldalt a táblázat kinyeréséhez
|
||||
PDFToCSV.submit=Kinyerés
|
||||
|
||||
#split-by-size-or-count
|
||||
split-by-size-or-count.title=PDF felosztása méret vagy oldalszám alapján
|
||||
split-by-size-or-count.header=PDF felosztása méret vagy oldalszám alapján
|
||||
split-by-size-or-count.type.label=Válassza ki a felosztás típusát
|
||||
split-by-size-or-count.type.size=Méret alapján
|
||||
|
||||
@@ -413,6 +413,7 @@ BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
|
||||
###########################
|
||||
#login
|
||||
login.title=Masuk
|
||||
login.header=Masuk
|
||||
login.signin=Masuk
|
||||
login.rememberme=Ingat saya
|
||||
login.invalid=Nama pengguna atau kata sandi tidak valid.
|
||||
@@ -951,6 +952,7 @@ PDFToCSV.prompt=Pilih halaman untuk mengambil tabel
|
||||
PDFToCSV.submit=Ektraksi
|
||||
|
||||
#split-by-size-or-count
|
||||
split-by-size-or-count.title=Pisahkan PDF berdasarkan ukuran atau jumlah
|
||||
split-by-size-or-count.header=Pisahkan PDF berdasarkan ukuran atau jumlah
|
||||
split-by-size-or-count.type.label=Pilih Tipe Split
|
||||
split-by-size-or-count.type.size=Berdasarkan Ukuran
|
||||
|
||||
@@ -110,7 +110,7 @@ settings.accountSettings=Impostazioni Account
|
||||
|
||||
changeCreds.title=Cambia credenziali
|
||||
changeCreds.header=Aggiorna i dettagli del tuo account
|
||||
changeCreds.changePassword=You are using default login credentials. Please enter a new password
|
||||
changeCreds.changePassword=Stai utilizzando le credenziali di accesso predefinite. Inserisci una nuova password
|
||||
changeCreds.newUsername=Nuovo nome utente
|
||||
changeCreds.oldPassword=Password attuale
|
||||
changeCreds.newPassword=Nuova Password
|
||||
@@ -413,6 +413,7 @@ BookToPDF.tags=Libro,fumetto,calibre,conversione,manga,amazon,kindle
|
||||
###########################
|
||||
#login
|
||||
login.title=Accedi
|
||||
login.header=Accedi
|
||||
login.signin=Accedi
|
||||
login.rememberme=Ricordami
|
||||
login.invalid=Nome utente o password errati.
|
||||
@@ -951,6 +952,7 @@ PDFToCSV.prompt=Scegli la pagina per estrarre la tabella
|
||||
PDFToCSV.submit=Estrai
|
||||
|
||||
#split-by-size-or-count
|
||||
split-by-size-or-count.title=Dividi il PDF per dimensione o numero
|
||||
split-by-size-or-count.header=Dividi il PDF per dimensione o numero
|
||||
split-by-size-or-count.type.label=Seleziona il tipo di divisione
|
||||
split-by-size-or-count.type.size=Per dimensione
|
||||
|
||||
@@ -413,6 +413,7 @@ BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
|
||||
###########################
|
||||
#login
|
||||
login.title=サインイン
|
||||
login.header=サインイン
|
||||
login.signin=サインイン
|
||||
login.rememberme=サインイン状態を記憶する
|
||||
login.invalid=ユーザー名かパスワードが無効です。
|
||||
@@ -951,6 +952,7 @@ PDFToCSV.prompt=表を抽出するページを選択
|
||||
PDFToCSV.submit=変換
|
||||
|
||||
#split-by-size-or-count
|
||||
split-by-size-or-count.title=サイズまたは数で分割
|
||||
split-by-size-or-count.header=サイズまたは数で分割
|
||||
split-by-size-or-count.type.label=分割タイプの選択
|
||||
split-by-size-or-count.type.size=サイズ
|
||||
|
||||
@@ -413,6 +413,7 @@ BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
|
||||
###########################
|
||||
#login
|
||||
login.title=로그인
|
||||
login.header=로그인
|
||||
login.signin=로그인
|
||||
login.rememberme=로그인 유지
|
||||
login.invalid=사용자 이름이나 비밀번호가 틀립니다.
|
||||
@@ -951,6 +952,7 @@ PDFToCSV.prompt=Choose page to extract table
|
||||
PDFToCSV.submit=??
|
||||
|
||||
#split-by-size-or-count
|
||||
split-by-size-or-count.title=Split PDF by Size or Count
|
||||
split-by-size-or-count.header=Split PDF by Size or Count
|
||||
split-by-size-or-count.type.label=Select Split Type
|
||||
split-by-size-or-count.type.size=By Size
|
||||
|
||||
@@ -413,6 +413,7 @@ BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
|
||||
###########################
|
||||
#login
|
||||
login.title=Inloggen
|
||||
login.header=Inloggen
|
||||
login.signin=Inloggen
|
||||
login.rememberme=Onthoud mij
|
||||
login.invalid=Ongeldige gebruikersnaam of wachtwoord.
|
||||
@@ -951,6 +952,7 @@ PDFToCSV.prompt=Kies pagina om tabel te extraheren
|
||||
PDFToCSV.submit=Extraheren
|
||||
|
||||
#split-by-size-or-count
|
||||
split-by-size-or-count.title=PDF splitsen op grootte of aantal
|
||||
split-by-size-or-count.header=PDF splitsen op grootte of aantal
|
||||
split-by-size-or-count.type.label=Selecteer splits type
|
||||
split-by-size-or-count.type.size=Op grootte
|
||||
|
||||
@@ -413,6 +413,7 @@ BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
|
||||
###########################
|
||||
#login
|
||||
login.title=Sign in
|
||||
login.header=Sign in
|
||||
login.signin=Sign in
|
||||
login.rememberme=Remember me
|
||||
login.invalid=Invalid username or password.
|
||||
@@ -951,6 +952,7 @@ PDFToCSV.prompt=Choose page to extract table
|
||||
PDFToCSV.submit=Wyci?g
|
||||
|
||||
#split-by-size-or-count
|
||||
split-by-size-or-count.title=Split PDF by Size or Count
|
||||
split-by-size-or-count.header=Split PDF by Size or Count
|
||||
split-by-size-or-count.type.label=Select Split Type
|
||||
split-by-size-or-count.type.size=By Size
|
||||
|
||||
@@ -413,6 +413,7 @@ BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
|
||||
###########################
|
||||
#login
|
||||
login.title=Sign in
|
||||
login.header=Sign in
|
||||
login.signin=Sign in
|
||||
login.rememberme=Remember me
|
||||
login.invalid=Invalid username or password.
|
||||
@@ -951,6 +952,7 @@ PDFToCSV.prompt=Choose page to extract table
|
||||
PDFToCSV.submit=Eztenna
|
||||
|
||||
#split-by-size-or-count
|
||||
split-by-size-or-count.title=Split PDF by Size or Count
|
||||
split-by-size-or-count.header=Split PDF by Size or Count
|
||||
split-by-size-or-count.type.label=Select Split Type
|
||||
split-by-size-or-count.type.size=By Size
|
||||
|
||||
@@ -413,6 +413,7 @@ BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
|
||||
###########################
|
||||
#login
|
||||
login.title=Aceder
|
||||
login.header=Aceder
|
||||
login.signin=Aceder
|
||||
login.rememberme=Lembrar dados
|
||||
login.invalid=Utilizador ou senha inválidos.
|
||||
@@ -951,6 +952,7 @@ PDFToCSV.prompt=Escolha a página para extrair a tabela
|
||||
PDFToCSV.submit=Eztenna
|
||||
|
||||
#split-by-size-or-count
|
||||
split-by-size-or-count.title=Dividir o PDF por tamanho, número de páginas ou número de documentos
|
||||
split-by-size-or-count.header=Dividir o PDF por tamanho, número de páginas ou número de documentos
|
||||
split-by-size-or-count.type.label=Seleccione o tipo de divisão
|
||||
split-by-size-or-count.type.size=Por Tamanho
|
||||
|
||||
@@ -413,6 +413,7 @@ BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
|
||||
###########################
|
||||
#login
|
||||
login.title=Sign in
|
||||
login.header=Sign in
|
||||
login.signin=Sign in
|
||||
login.rememberme=Remember me
|
||||
login.invalid=Invalid username or password.
|
||||
@@ -951,6 +952,7 @@ PDFToCSV.prompt=Choose page to extract table
|
||||
PDFToCSV.submit=Extrage
|
||||
|
||||
#split-by-size-or-count
|
||||
split-by-size-or-count.title=Split PDF by Size or Count
|
||||
split-by-size-or-count.header=Split PDF by Size or Count
|
||||
split-by-size-or-count.type.label=Select Split Type
|
||||
split-by-size-or-count.type.size=By Size
|
||||
|
||||
@@ -413,6 +413,7 @@ BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
|
||||
###########################
|
||||
#login
|
||||
login.title=Sign in
|
||||
login.header=Sign in
|
||||
login.signin=Sign in
|
||||
login.rememberme=Remember me
|
||||
login.invalid=Invalid username or password.
|
||||
@@ -951,6 +952,7 @@ PDFToCSV.prompt=Choose page to extract table
|
||||
PDFToCSV.submit=???????
|
||||
|
||||
#split-by-size-or-count
|
||||
split-by-size-or-count.title=Split PDF by Size or Count
|
||||
split-by-size-or-count.header=Split PDF by Size or Count
|
||||
split-by-size-or-count.type.label=Select Split Type
|
||||
split-by-size-or-count.type.size=By Size
|
||||
|
||||
@@ -413,6 +413,7 @@ BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
|
||||
###########################
|
||||
#login
|
||||
login.title=Prijavite se
|
||||
login.header=Prijavite se
|
||||
login.signin=Prijavite se
|
||||
login.rememberme=Zapamti me
|
||||
login.invalid=Neispravno korisničko ime ili lozinka.
|
||||
@@ -951,6 +952,7 @@ PDFToCSV.prompt=Izaberite stranicu za ekstrakciju tabele
|
||||
PDFToCSV.submit=Izvuci
|
||||
|
||||
#split-by-size-or-count
|
||||
split-by-size-or-count.title=Razdvoji PDF po veličini ili broju
|
||||
split-by-size-or-count.header=Razdvoji PDF po veličini ili broju
|
||||
split-by-size-or-count.type.label=Izaberite tip razdvajanja
|
||||
split-by-size-or-count.type.size=Po veličini
|
||||
|
||||
@@ -413,6 +413,7 @@ BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
|
||||
###########################
|
||||
#login
|
||||
login.title=Sign in
|
||||
login.header=Sign in
|
||||
login.signin=Sign in
|
||||
login.rememberme=Remember me
|
||||
login.invalid=Invalid username or password.
|
||||
@@ -951,6 +952,7 @@ PDFToCSV.prompt=Choose page to extract table
|
||||
PDFToCSV.submit=Navvit
|
||||
|
||||
#split-by-size-or-count
|
||||
split-by-size-or-count.title=Split PDF by Size or Count
|
||||
split-by-size-or-count.header=Split PDF by Size or Count
|
||||
split-by-size-or-count.type.label=Select Split Type
|
||||
split-by-size-or-count.type.size=By Size
|
||||
|
||||
@@ -413,6 +413,7 @@ BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
|
||||
###########################
|
||||
#login
|
||||
login.title=Giriş Yap
|
||||
login.header=Giriş Yap
|
||||
login.signin=Giriş Yap
|
||||
login.rememberme=Beni hatırla
|
||||
login.invalid=Geçersiz kullanıcı adı veya şifre.
|
||||
@@ -951,6 +952,7 @@ PDFToCSV.prompt=Choose page to extract table
|
||||
PDFToCSV.submit=Extract
|
||||
|
||||
#split-by-size-or-count
|
||||
split-by-size-or-count.title=Split PDF by Size or Count
|
||||
split-by-size-or-count.header=Split PDF by Size or Count
|
||||
split-by-size-or-count.type.label=Select Split Type
|
||||
split-by-size-or-count.type.size=By Size
|
||||
|
||||
@@ -413,6 +413,7 @@ BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
|
||||
###########################
|
||||
#login
|
||||
login.title=登录
|
||||
login.header=登录
|
||||
login.signin=登录
|
||||
login.rememberme=记住我
|
||||
login.invalid=用户名或密码无效。
|
||||
@@ -951,6 +952,7 @@ PDFToCSV.prompt=选择需要提取表格的页面
|
||||
PDFToCSV.submit=提取
|
||||
|
||||
#split-by-size-or-count
|
||||
split-by-size-or-count.title=按照大小或数目拆分PDF
|
||||
split-by-size-or-count.header=按照大小或数目拆分PDF
|
||||
split-by-size-or-count.type.label=选择拆分类型
|
||||
split-by-size-or-count.type.size=按照大小
|
||||
|
||||
@@ -413,6 +413,7 @@ BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
|
||||
###########################
|
||||
#login
|
||||
login.title=登入
|
||||
login.header=登入
|
||||
login.signin=登入
|
||||
login.rememberme=記住我
|
||||
login.invalid=使用者名稱或密碼無效。
|
||||
@@ -951,6 +952,7 @@ PDFToCSV.prompt=選擇要提取表格的頁面
|
||||
PDFToCSV.submit=提取
|
||||
|
||||
#split-by-size-or-count
|
||||
split-by-size-or-count.title=依大小或數量分割 PDF
|
||||
split-by-size-or-count.header=依大小或數量分割 PDF
|
||||
split-by-size-or-count.type.label=選擇分割類型
|
||||
split-by-size-or-count.type.size=依大小
|
||||
|
||||
@@ -179,7 +179,9 @@ class PdfContainer {
|
||||
|
||||
rotateAll(deg) {
|
||||
for (var i = 0; i < this.pagesContainer.childNodes.length; i++) {
|
||||
const img = this.pagesContainer.childNodes[i].querySelector("img");
|
||||
const child = this.pagesContainer.children[i];
|
||||
if (!child) continue;
|
||||
const img = child.querySelector("img");
|
||||
if (!img) continue;
|
||||
this.rotateElement(img, deg);
|
||||
}
|
||||
|
||||
105
src/test/java/stirling/software/SPDF/utils/GeneralUtilsTest.java
Normal file
105
src/test/java/stirling/software/SPDF/utils/GeneralUtilsTest.java
Normal file
@@ -0,0 +1,105 @@
|
||||
package stirling.software.SPDF.utils;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class GeneralUtilsTest {
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
void testParsePageListWithAll() {
|
||||
List<Integer> result = GeneralUtils.parsePageList(new String[]{"all"}, 5, false);
|
||||
assertEquals(List.of(0, 1, 2, 3, 4), result, "'All' keyword should return all pages.");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParsePageListWithAllOneBased() {
|
||||
List<Integer> result = GeneralUtils.parsePageList(new String[]{"all"}, 5, true);
|
||||
assertEquals(List.of(1, 2, 3, 4, 5), result, "'All' keyword should return all pages.");
|
||||
}
|
||||
|
||||
@Test
|
||||
void nFunc() {
|
||||
List<Integer> result = GeneralUtils.parsePageList(new String[]{"n"}, 5, true);
|
||||
assertEquals(List.of(1, 2, 3, 4, 5), result, "'n' keyword should return all pages.");
|
||||
}
|
||||
|
||||
@Test
|
||||
void nFuncAdvanced() {
|
||||
List<Integer> result = GeneralUtils.parsePageList(new String[]{"4n"}, 9, true);
|
||||
//skip 0 as not valid
|
||||
assertEquals(List.of(4,8), result, "'All' keyword should return all pages.");
|
||||
}
|
||||
|
||||
@Test
|
||||
void nFuncAdvancedZero() {
|
||||
List<Integer> result = GeneralUtils.parsePageList(new String[]{"4n"}, 9, false);
|
||||
//skip 0 as not valid
|
||||
assertEquals(List.of(3,7), result, "'All' keyword should return all pages.");
|
||||
}
|
||||
|
||||
@Test
|
||||
void nFuncAdvanced2() {
|
||||
List<Integer> result = GeneralUtils.parsePageList(new String[]{"4n-1"}, 9, true);
|
||||
// skip -1 as not valid
|
||||
assertEquals(List.of(3,7), result, "4n-1 should do (0-1), (4-1), (8-1)");
|
||||
}
|
||||
|
||||
@Test
|
||||
void nFuncAdvanced3() {
|
||||
List<Integer> result = GeneralUtils.parsePageList(new String[]{"4n+1"}, 9, true);
|
||||
assertEquals(List.of(1,5,9), result, "'All' keyword should return all pages.");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void nFuncAdvanced4() {
|
||||
List<Integer> result = GeneralUtils.parsePageList(new String[]{"3+2n"}, 9, true);
|
||||
assertEquals(List.of(3,5,7,9), result, "'All' keyword should return all pages.");
|
||||
}
|
||||
|
||||
@Test
|
||||
void nFuncAdvancedZerobased() {
|
||||
List<Integer> result = GeneralUtils.parsePageList(new String[]{"4n"}, 9, false);
|
||||
assertEquals(List.of(3,7), result, "'All' keyword should return all pages.");
|
||||
}
|
||||
|
||||
@Test
|
||||
void nFuncAdvanced2Zerobased() {
|
||||
List<Integer> result = GeneralUtils.parsePageList(new String[]{"4n-1"}, 9, false);
|
||||
assertEquals(List.of(2,6), result, "'All' keyword should return all pages.");
|
||||
}
|
||||
@Test
|
||||
void testParsePageListWithRangeOneBasedOutput() {
|
||||
List<Integer> result = GeneralUtils.parsePageList(new String[]{"1-3"}, 5, true);
|
||||
assertEquals(List.of(1, 2, 3), result, "Range should be parsed correctly.");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void testParsePageListWithRangeZeroBaseOutput() {
|
||||
List<Integer> result = GeneralUtils.parsePageList(new String[]{"1-3"}, 5, false);
|
||||
assertEquals(List.of(0, 1, 2), result, "Range should be parsed correctly.");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void testParsePageListWithRangeOneBasedOutputFull() {
|
||||
List<Integer> result = GeneralUtils.parsePageList(new String[]{"1,3,7-8"}, 8, true);
|
||||
assertEquals(List.of(1, 3, 7,8), result, "Range should be parsed correctly.");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParsePageListWithRangeOneBasedOutputFullOutOfRange() {
|
||||
List<Integer> result = GeneralUtils.parsePageList(new String[]{"1,3,7-8"}, 5, true);
|
||||
assertEquals(List.of(1, 3), result, "Range should be parsed correctly.");
|
||||
}
|
||||
@Test
|
||||
void testParsePageListWithRangeZeroBaseOutputFull() {
|
||||
List<Integer> result = GeneralUtils.parsePageList(new String[]{"1,3,7-8"}, 8, false);
|
||||
assertEquals(List.of(0, 2, 6,7), result, "Range should be parsed correctly.");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user