Compare commits
1 Commits
bugFixes
...
Frooodle-p
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5790ea8c01 |
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@@ -141,4 +141,4 @@ jobs:
|
||||
run: |
|
||||
chmod +x ./testing/test_webpages.sh
|
||||
chmod +x ./testing/test.sh
|
||||
./testing/test.sh
|
||||
./testing/test.sh "${{ github.event.pull_request.user.login == 'dependabot[bot]' }}"
|
||||
|
||||
2
.github/workflows/licenses-update.yml
vendored
2
.github/workflows/licenses-update.yml
vendored
@@ -38,7 +38,7 @@ jobs:
|
||||
java-version: "17"
|
||||
distribution: "adopt"
|
||||
|
||||
- uses: gradle/actions/setup-gradle@94baf225fe0a508e581a564467443d0e2379123b # v4.3.0
|
||||
- uses: gradle/actions/setup-gradle@0bdd871935719febd78681f197cd39af5b6e16a6 # v4.2.2
|
||||
|
||||
- name: check the licenses for compatibility
|
||||
run: ./gradlew clean checkLicense
|
||||
|
||||
4
.github/workflows/multiOSReleases.yml
vendored
4
.github/workflows/multiOSReleases.yml
vendored
@@ -63,7 +63,7 @@ jobs:
|
||||
java-version: "21"
|
||||
distribution: "temurin"
|
||||
|
||||
- uses: gradle/actions/setup-gradle@94baf225fe0a508e581a564467443d0e2379123b # v4.3.0
|
||||
- uses: gradle/actions/setup-gradle@0bdd871935719febd78681f197cd39af5b6e16a6 # v4.2.2
|
||||
with:
|
||||
gradle-version: 8.12
|
||||
|
||||
@@ -151,7 +151,7 @@ jobs:
|
||||
java-version: "21"
|
||||
distribution: "temurin"
|
||||
|
||||
- uses: gradle/actions/setup-gradle@94baf225fe0a508e581a564467443d0e2379123b # v4.3.0
|
||||
- uses: gradle/actions/setup-gradle@0bdd871935719febd78681f197cd39af5b6e16a6 # v4.2.2
|
||||
with:
|
||||
gradle-version: 8.12
|
||||
|
||||
|
||||
2
.github/workflows/push-docker.yml
vendored
2
.github/workflows/push-docker.yml
vendored
@@ -30,7 +30,7 @@ jobs:
|
||||
java-version: "17"
|
||||
distribution: "temurin"
|
||||
|
||||
- uses: gradle/actions/setup-gradle@94baf225fe0a508e581a564467443d0e2379123b # v4.3.0
|
||||
- uses: gradle/actions/setup-gradle@0bdd871935719febd78681f197cd39af5b6e16a6 # v4.2.2
|
||||
with:
|
||||
gradle-version: 8.12
|
||||
|
||||
|
||||
2
.github/workflows/releaseArtifacts.yml
vendored
2
.github/workflows/releaseArtifacts.yml
vendored
@@ -35,7 +35,7 @@ jobs:
|
||||
java-version: "17"
|
||||
distribution: "temurin"
|
||||
|
||||
- uses: gradle/actions/setup-gradle@94baf225fe0a508e581a564467443d0e2379123b # v4.3.0
|
||||
- uses: gradle/actions/setup-gradle@0bdd871935719febd78681f197cd39af5b6e16a6 # v4.2.2
|
||||
with:
|
||||
gradle-version: 8.12
|
||||
|
||||
|
||||
14
.github/workflows/sonarqube.yml
vendored
14
.github/workflows/sonarqube.yml
vendored
@@ -31,6 +31,20 @@ jobs:
|
||||
java-version: '17'
|
||||
distribution: 'temurin'
|
||||
|
||||
- name: Cache SonarCloud packages
|
||||
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
|
||||
with:
|
||||
path: ~/.sonar/cache
|
||||
key: ${{ runner.os }}-sonar
|
||||
restore-keys: ${{ runner.os }}-sonar
|
||||
|
||||
- name: Cache Gradle packages
|
||||
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
|
||||
with:
|
||||
path: ~/.gradle/caches
|
||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
|
||||
restore-keys: ${{ runner.os }}-gradle
|
||||
|
||||
- name: Build and analyze with Gradle
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
2
.github/workflows/swagger.yml
vendored
2
.github/workflows/swagger.yml
vendored
@@ -26,7 +26,7 @@ jobs:
|
||||
java-version: "17"
|
||||
distribution: "temurin"
|
||||
|
||||
- uses: gradle/actions/setup-gradle@94baf225fe0a508e581a564467443d0e2379123b # v4.3.0
|
||||
- uses: gradle/actions/setup-gradle@0bdd871935719febd78681f197cd39af5b6e16a6 # v4.2.2
|
||||
|
||||
- name: Generate Swagger documentation
|
||||
run: ./gradlew generateOpenApiDocs
|
||||
|
||||
4
.github/workflows/sync_files.yml
vendored
4
.github/workflows/sync_files.yml
vendored
@@ -111,11 +111,11 @@ jobs:
|
||||
author: ${{ needs.read_bot_entries.outputs.committer }}
|
||||
signoff: true
|
||||
branch: sync_readme
|
||||
title: ":globe_with_meridians: Sync Translations + Update README Progress Table"
|
||||
title: ":globe_with_meridians: Sync Translations + Update README Progress Table + Update Verification Metadata"
|
||||
body: |
|
||||
### Description of Changes
|
||||
|
||||
This Pull Request was automatically generated to synchronize updates to translation files and documentation. Below are the details of the changes made:
|
||||
This Pull Request was automatically generated to synchronize updates to translation files, verification metadata, and documentation. Below are the details of the changes made:
|
||||
|
||||
#### **1. Synchronization of Translation Files**
|
||||
- Updated translation files (`messages_*.properties`) to reflect changes in the reference file `messages_en_GB.properties`.
|
||||
|
||||
@@ -56,15 +56,13 @@ RUN echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /et
|
||||
openssl-dev \
|
||||
openjdk21-jre \
|
||||
# Doc conversion
|
||||
gcompat \
|
||||
libc6-compat \
|
||||
libreoffice \
|
||||
# pdftohtml
|
||||
poppler-utils \
|
||||
# OCR MY PDF (unpaper for descew and other advanced features)
|
||||
tesseract-ocr-data-eng \
|
||||
# CV
|
||||
py3-opencv \
|
||||
py3-opencv \
|
||||
# python3/pip
|
||||
python3 \
|
||||
py3-pip && \
|
||||
|
||||
@@ -57,8 +57,6 @@ RUN echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /et
|
||||
openssl-dev \
|
||||
openjdk21-jre \
|
||||
# Doc conversion
|
||||
gcompat \
|
||||
libc6-compat \
|
||||
libreoffice \
|
||||
# pdftohtml
|
||||
poppler-utils \
|
||||
@@ -67,7 +65,7 @@ RUN echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /et
|
||||
tesseract-ocr-data-eng \
|
||||
font-terminus font-dejavu font-noto font-noto-cjk font-awesome font-noto-extra \
|
||||
# CV
|
||||
py3-opencv \
|
||||
py3-opencv \
|
||||
# python3/pip
|
||||
python3 \
|
||||
py3-pip && \
|
||||
|
||||
@@ -8,7 +8,7 @@ plugins {
|
||||
id "com.diffplug.spotless" version "7.0.2"
|
||||
id "com.github.jk1.dependency-license-report" version "2.9"
|
||||
//id "nebula.lint" version "19.0.3"
|
||||
id("org.panteleyev.jpackageplugin") version "1.6.1"
|
||||
id("org.panteleyev.jpackageplugin") version "1.6.0"
|
||||
id "org.sonarqube" version "6.0.1.5171"
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ ext {
|
||||
}
|
||||
|
||||
group = "stirling.software"
|
||||
version = "0.41.0"
|
||||
version = "0.40.1"
|
||||
|
||||
java {
|
||||
// 17 is lowest but we support and recommend 21
|
||||
|
||||
BIN
docs/stirling-pdf.png
Normal file
BIN
docs/stirling-pdf.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 50 KiB |
1
docs/stirling-transparent.svg
Normal file
1
docs/stirling-transparent.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 9.4 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 169 KiB After Width: | Height: | Size: 242 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 118 KiB After Width: | Height: | Size: 145 KiB |
@@ -265,6 +265,9 @@ public class EndpointConfiguration {
|
||||
// Pdftohtml dependent endpoints
|
||||
addEndpointToGroup("Pdftohtml", "pdf-to-html");
|
||||
addEndpointToGroup("Pdftohtml", "pdf-to-markdown");
|
||||
|
||||
// disabled for now while we resolve issues
|
||||
disableEndpoint("pdf-to-pdfa");
|
||||
}
|
||||
|
||||
private void processEnvironmentConfigs() {
|
||||
|
||||
@@ -44,7 +44,7 @@ public class ConvertHtmlToPDF {
|
||||
@Operation(
|
||||
summary = "Convert an HTML or ZIP (containing HTML and CSS) to PDF",
|
||||
description =
|
||||
"This endpoint takes an HTML or ZIP file input and converts it to a PDF format. Input:HTML Output:PDF Type:SISO")
|
||||
"This endpoint takes an HTML or ZIP file input and converts it to a PDF format.")
|
||||
public ResponseEntity<byte[]> HtmlToPdf(@ModelAttribute HTMLToPdfRequest request)
|
||||
throws Exception {
|
||||
MultipartFile fileInput = request.getFileInput();
|
||||
|
||||
@@ -73,8 +73,8 @@ public class ConvertPDFToPDFA {
|
||||
// Determine PDF/A filter based on requested format
|
||||
String pdfFilter =
|
||||
"pdfa".equals(outputFormat)
|
||||
? "pdf:writer_pdf_Export:{\"SelectPdfVersion\":{\"type\":\"long\",\"value\":\"2\"}}"
|
||||
: "pdf:writer_pdf_Export:{\"SelectPdfVersion\":{\"type\":\"long\",\"value\":\"1\"}}";
|
||||
? "writer_pdf_Export:{'SelectPdfVersion':{'Value':'2'}}:writer_pdf_Export"
|
||||
: "writer_pdf_Export:{'SelectPdfVersion':{'Value':'1'}}:writer_pdf_Export";
|
||||
|
||||
// Prepare LibreOffice command
|
||||
List<String> command =
|
||||
@@ -84,7 +84,7 @@ public class ConvertPDFToPDFA {
|
||||
"--headless",
|
||||
"--nologo",
|
||||
"--convert-to",
|
||||
pdfFilter,
|
||||
"pdf:" + pdfFilter,
|
||||
"--outdir",
|
||||
tempOutputDir.toString(),
|
||||
tempInputFile.toString()));
|
||||
|
||||
@@ -8,9 +8,7 @@ import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
@@ -43,12 +41,8 @@ import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
@Tag(name = "Misc", description = "Miscellaneous APIs")
|
||||
public class AutoSplitPdfController {
|
||||
|
||||
private static final Set<String> VALID_QR_CONTENTS =
|
||||
new HashSet<>(
|
||||
Set.of(
|
||||
"https://github.com/Stirling-Tools/Stirling-PDF",
|
||||
"https://github.com/Frooodle/Stirling-PDF",
|
||||
"https://stirlingpdf.com"));
|
||||
private static final String QR_CONTENT = "https://github.com/Stirling-Tools/Stirling-PDF";
|
||||
private static final String QR_CONTENT_OLD = "https://github.com/Frooodle/Stirling-PDF";
|
||||
|
||||
private final CustomPDDocumentFactory pdfDocumentFactory;
|
||||
|
||||
@@ -126,14 +120,13 @@ public class AutoSplitPdfController {
|
||||
for (int page = 0; page < document.getNumberOfPages(); ++page) {
|
||||
BufferedImage bim = pdfRenderer.renderImageWithDPI(page, 150);
|
||||
String result = decodeQRCode(bim);
|
||||
|
||||
boolean isValidQrCode = VALID_QR_CONTENTS.contains(result);
|
||||
log.debug("detected qr code {}, code is vale={}", result, isValidQrCode);
|
||||
if (isValidQrCode && page != 0) {
|
||||
if ((QR_CONTENT.equals(result) || QR_CONTENT_OLD.equals(result)) && page != 0) {
|
||||
splitDocuments.add(new PDDocument());
|
||||
}
|
||||
|
||||
if (!splitDocuments.isEmpty() && !isValidQrCode) {
|
||||
if (!splitDocuments.isEmpty()
|
||||
&& !QR_CONTENT.equals(result)
|
||||
&& !QR_CONTENT_OLD.equals(result)) {
|
||||
splitDocuments.get(splitDocuments.size() - 1).addPage(document.getPage(page));
|
||||
} else if (page == 0) {
|
||||
PDDocument firstDocument = new PDDocument();
|
||||
@@ -142,7 +135,7 @@ public class AutoSplitPdfController {
|
||||
}
|
||||
|
||||
// If duplexMode is true and current page is a divider, then skip next page
|
||||
if (duplexMode && isValidQrCode) {
|
||||
if (duplexMode && (QR_CONTENT.equals(result) || QR_CONTENT_OLD.equals(result))) {
|
||||
page++;
|
||||
}
|
||||
}
|
||||
@@ -175,9 +168,6 @@ public class AutoSplitPdfController {
|
||||
|
||||
return WebResponseUtils.bytesToWebResponse(
|
||||
data, filename + ".zip", MediaType.APPLICATION_OCTET_STREAM);
|
||||
} catch (Exception e) {
|
||||
log.error("Error in auto split", e);
|
||||
throw e;
|
||||
} finally {
|
||||
// Clean up resources
|
||||
if (document != null) {
|
||||
|
||||
@@ -52,7 +52,7 @@ public class ExtractImagesController {
|
||||
@Operation(
|
||||
summary = "Extract images from a PDF file",
|
||||
description =
|
||||
"This endpoint extracts images from a given PDF file and returns them in a zip file. Users can specify the output image format. Input:PDF Output:IMAGE/ZIP Type:SIMO")
|
||||
"This endpoint extracts images from a given PDF file and returns them in a zip file. Users can specify the output image format. Input: PDF Output: IMAGE/ZIP Type: SIMO")
|
||||
public ResponseEntity<byte[]> extractImages(@ModelAttribute PDFExtractImagesRequest request)
|
||||
throws IOException, InterruptedException, ExecutionException {
|
||||
MultipartFile file = request.getFileInput();
|
||||
|
||||
@@ -46,7 +46,7 @@ public class FlattenController {
|
||||
@Operation(
|
||||
summary = "Flatten PDF form fields or full page",
|
||||
description =
|
||||
"Flattening just PDF form fields or converting each page to images to make text unselectable. Input:PDF, Output:PDF. Type:SISO")
|
||||
"Flattening just PDF form fields or converting each page to images to make text unselectable. Input: PDF, Output: PDF. Type: SISO")
|
||||
public ResponseEntity<byte[]> flatten(@ModelAttribute FlattenRequest request) throws Exception {
|
||||
MultipartFile file = request.getFileInput();
|
||||
|
||||
|
||||
@@ -26,7 +26,6 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import io.github.pixee.security.BoundedLineReader;
|
||||
import io.github.pixee.security.Filenames;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -66,10 +65,6 @@ public class OCRController {
|
||||
}
|
||||
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/ocr-pdf")
|
||||
@Operation(
|
||||
summary = "Process PDF files with OCR using Tesseract",
|
||||
description =
|
||||
"Takes a PDF file as input, performs OCR using specified languages and OCR type (skip-text/force-ocr), and returns the processed PDF. Input:PDF Output:PDF Type:SISO")
|
||||
public ResponseEntity<byte[]> processPdfWithOCR(
|
||||
@ModelAttribute ProcessPdfWithOcrRequest request)
|
||||
throws IOException, InterruptedException {
|
||||
|
||||
@@ -25,7 +25,6 @@ import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import stirling.software.SPDF.model.PipelineConfig;
|
||||
import stirling.software.SPDF.model.PipelineResult;
|
||||
import stirling.software.SPDF.model.api.HandleDataRequest;
|
||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||
|
||||
@@ -59,8 +58,7 @@ public class PipelineController {
|
||||
if (inputFiles == null || inputFiles.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
PipelineResult result = processor.runPipelineAgainstFiles(inputFiles, config);
|
||||
List<Resource> outputFiles = result.getOutputFiles();
|
||||
List<Resource> outputFiles = processor.runPipelineAgainstFiles(inputFiles, config);
|
||||
if (outputFiles != null && outputFiles.size() == 1) {
|
||||
// If there is only one file, return it directly
|
||||
Resource singleFile = outputFiles.get(0);
|
||||
|
||||
@@ -27,7 +27,6 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import stirling.software.SPDF.config.InstallationPathConfig;
|
||||
import stirling.software.SPDF.model.PipelineConfig;
|
||||
import stirling.software.SPDF.model.PipelineOperation;
|
||||
import stirling.software.SPDF.model.PipelineResult;
|
||||
import stirling.software.SPDF.utils.FileMonitor;
|
||||
|
||||
@Service
|
||||
@@ -144,64 +143,19 @@ public class PipelineDirectoryProcessor {
|
||||
|
||||
private File[] collectFilesForProcessing(Path dir, Path jsonFile, PipelineOperation operation)
|
||||
throws IOException {
|
||||
|
||||
List<String> inputExtensions =
|
||||
apiDocService.getExtensionTypes(false, operation.getOperation());
|
||||
log.info(
|
||||
"Allowed extensions for operation {}: {}",
|
||||
operation.getOperation(),
|
||||
inputExtensions);
|
||||
|
||||
boolean allowAllFiles = inputExtensions.contains("ALL");
|
||||
|
||||
try (Stream<Path> paths = Files.list(dir)) {
|
||||
File[] files =
|
||||
paths.filter(
|
||||
path -> {
|
||||
if (Files.isDirectory(path)) {
|
||||
return false;
|
||||
}
|
||||
if (path.equals(jsonFile)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get file extension
|
||||
String filename = path.getFileName().toString();
|
||||
String extension =
|
||||
filename.contains(".")
|
||||
? filename.substring(
|
||||
filename.lastIndexOf(".")
|
||||
+ 1)
|
||||
.toLowerCase()
|
||||
: "";
|
||||
|
||||
// Check against allowed extensions
|
||||
boolean isAllowed =
|
||||
allowAllFiles
|
||||
|| inputExtensions.contains(extension);
|
||||
if (!isAllowed) {
|
||||
log.info(
|
||||
"Skipping file with unsupported extension: {} ({})",
|
||||
filename,
|
||||
extension);
|
||||
}
|
||||
return isAllowed;
|
||||
})
|
||||
.filter(
|
||||
path -> {
|
||||
boolean isReady =
|
||||
fileMonitor.isFileReadyForProcessing(path);
|
||||
if (!isReady) {
|
||||
log.info(
|
||||
"File not ready for processing (locked/created last 5s): {}",
|
||||
path);
|
||||
}
|
||||
return isReady;
|
||||
})
|
||||
.map(Path::toFile)
|
||||
.toArray(File[]::new);
|
||||
log.info("Collected {} files for processing", files.length);
|
||||
return files;
|
||||
if ("automated".equals(operation.getParameters().get("fileInput"))) {
|
||||
return paths.filter(
|
||||
path ->
|
||||
!Files.isDirectory(path)
|
||||
&& !path.equals(jsonFile)
|
||||
&& fileMonitor.isFileReadyForProcessing(path))
|
||||
.map(Path::toFile)
|
||||
.toArray(File[]::new);
|
||||
} else {
|
||||
String fileInput = (String) operation.getParameters().get("fileInput");
|
||||
return new File[] {new File(fileInput)};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -244,37 +198,19 @@ public class PipelineDirectoryProcessor {
|
||||
try {
|
||||
List<Resource> inputFiles =
|
||||
processor.generateInputFiles(filesToProcess.toArray(new File[0]));
|
||||
if (inputFiles == null || inputFiles.isEmpty()) {
|
||||
if (inputFiles == null || inputFiles.size() == 0) {
|
||||
return;
|
||||
}
|
||||
PipelineResult result = processor.runPipelineAgainstFiles(inputFiles, config);
|
||||
|
||||
if (result.isHasErrors()) {
|
||||
log.error("Errors occurred during processing, retaining original files");
|
||||
moveToErrorDirectory(filesToProcess, dir);
|
||||
} else {
|
||||
moveAndRenameFiles(result.getOutputFiles(), config, dir);
|
||||
deleteOriginalFiles(filesToProcess, processingDir);
|
||||
}
|
||||
List<Resource> outputFiles = processor.runPipelineAgainstFiles(inputFiles, config);
|
||||
if (outputFiles == null) return;
|
||||
moveAndRenameFiles(outputFiles, config, dir);
|
||||
deleteOriginalFiles(filesToProcess, processingDir);
|
||||
} catch (Exception e) {
|
||||
log.error("Error during processing", e);
|
||||
log.error("error during processing", e);
|
||||
moveFilesBack(filesToProcess, processingDir);
|
||||
}
|
||||
}
|
||||
|
||||
private void moveToErrorDirectory(List<File> files, Path originalDir) throws IOException {
|
||||
Path errorDir = originalDir.resolve("error");
|
||||
if (!Files.exists(errorDir)) {
|
||||
Files.createDirectories(errorDir);
|
||||
}
|
||||
|
||||
for (File file : files) {
|
||||
Path target = errorDir.resolve(file.getName());
|
||||
Files.move(file.toPath(), target);
|
||||
log.info("Moved failed file to error directory for investigation: {}", target);
|
||||
}
|
||||
}
|
||||
|
||||
private void moveAndRenameFiles(List<Resource> resources, PipelineConfig config, Path dir)
|
||||
throws IOException {
|
||||
for (Resource resource : resources) {
|
||||
|
||||
@@ -33,7 +33,6 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import stirling.software.SPDF.SPDFApplication;
|
||||
import stirling.software.SPDF.model.PipelineConfig;
|
||||
import stirling.software.SPDF.model.PipelineOperation;
|
||||
import stirling.software.SPDF.model.PipelineResult;
|
||||
import stirling.software.SPDF.model.Role;
|
||||
|
||||
@Service
|
||||
@@ -85,10 +84,8 @@ public class PipelineProcessor {
|
||||
return "http://localhost:" + port + contextPath + "/";
|
||||
}
|
||||
|
||||
PipelineResult runPipelineAgainstFiles(List<Resource> outputFiles, PipelineConfig config)
|
||||
List<Resource> runPipelineAgainstFiles(List<Resource> outputFiles, PipelineConfig config)
|
||||
throws Exception {
|
||||
PipelineResult result = new PipelineResult();
|
||||
|
||||
ByteArrayOutputStream logStream = new ByteArrayOutputStream();
|
||||
PrintStream logPrintStream = new PrintStream(logStream);
|
||||
boolean hasErrors = false;
|
||||
@@ -133,8 +130,7 @@ public class PipelineProcessor {
|
||||
if (operation.startsWith("filter-")
|
||||
&& (response.getBody() == null
|
||||
|| response.getBody().length == 0)) {
|
||||
result.setFiltersApplied(true);
|
||||
log.info("Skipping file due to filtering {}", operation);
|
||||
log.info("Skipping file due to failing {}", operation);
|
||||
continue;
|
||||
}
|
||||
if (!response.getStatusCode().equals(HttpStatus.OK)) {
|
||||
@@ -212,10 +208,7 @@ public class PipelineProcessor {
|
||||
if (hasErrors) {
|
||||
log.error("Errors occurred during processing. Log: {}", logStream.toString());
|
||||
}
|
||||
result.setHasErrors(hasErrors);
|
||||
result.setFiltersApplied(hasErrors);
|
||||
result.setOutputFiles(outputFiles);
|
||||
return result;
|
||||
return outputFiles;
|
||||
}
|
||||
|
||||
private ResponseEntity<byte[]> sendWebRequest(String url, MultiValueMap<String, Object> body) {
|
||||
|
||||
@@ -40,7 +40,8 @@ public class RemoveCertSignController {
|
||||
@Operation(
|
||||
summary = "Remove digital signature from PDF",
|
||||
description =
|
||||
"This endpoint accepts a PDF file and returns the PDF file without the digital signature. Input:PDF, Output:PDF Type:SISO")
|
||||
"This endpoint accepts a PDF file and returns the PDF file without the digital signature."
|
||||
+ " Input: PDF, Output: PDF")
|
||||
public ResponseEntity<byte[]> removeCertSignPDF(@ModelAttribute PDFFile request)
|
||||
throws Exception {
|
||||
MultipartFile pdf = request.getFileInput();
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
package stirling.software.SPDF.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class PipelineResult {
|
||||
private List<Resource> outputFiles;
|
||||
private boolean hasErrors;
|
||||
private boolean filtersApplied;
|
||||
}
|
||||
@@ -218,9 +218,6 @@ public class ProcessExecutor {
|
||||
errorReaderThread.join();
|
||||
outputReaderThread.join();
|
||||
|
||||
boolean isQpdf =
|
||||
command != null && !command.isEmpty() && command.get(0).contains("qpdf");
|
||||
|
||||
if (outputLines.size() > 0) {
|
||||
String outputMessage = String.join("\n", outputLines);
|
||||
messages += outputMessage;
|
||||
@@ -236,28 +233,20 @@ public class ProcessExecutor {
|
||||
log.warn("Command error output:\n" + errorMessage);
|
||||
}
|
||||
if (exitCode != 0) {
|
||||
if (isQpdf && exitCode == 3) {
|
||||
log.warn("qpdf succeeded with warnings: {}", messages);
|
||||
} else {
|
||||
throw new IOException(
|
||||
"Command process failed with exit code "
|
||||
+ exitCode
|
||||
+ ". Error message: "
|
||||
+ errorMessage);
|
||||
}
|
||||
throw new IOException(
|
||||
"Command process failed with exit code "
|
||||
+ exitCode
|
||||
+ ". Error message: "
|
||||
+ errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
if (exitCode != 0) {
|
||||
if (isQpdf && exitCode == 3) {
|
||||
log.warn("qpdf succeeded with warnings: {}", messages);
|
||||
} else {
|
||||
throw new IOException(
|
||||
"Command process failed with exit code "
|
||||
+ exitCode
|
||||
+ "\nLogs: "
|
||||
+ messages);
|
||||
}
|
||||
throw new IOException(
|
||||
"Command process failed with exit code "
|
||||
+ exitCode
|
||||
+ "\nLogs: "
|
||||
+ messages);
|
||||
}
|
||||
} finally {
|
||||
semaphore.release();
|
||||
|
||||
@@ -768,6 +768,7 @@ autoSplitPDF.selectText.3=Upload the single large scanned PDF file and let Stirl
|
||||
autoSplitPDF.selectText.4=Divider pages are automatically detected and removed, guaranteeing a neat final document.
|
||||
autoSplitPDF.formPrompt=Submit PDF containing Stirling-PDF Page dividers:
|
||||
autoSplitPDF.duplexMode=Duplex Mode (Front and back scanning)
|
||||
autoSplitPDF.dividerDownload1=Download 'Auto Splitter Divider (minimal).pdf'
|
||||
autoSplitPDF.dividerDownload2=Download 'Auto Splitter Divider (with instructions).pdf'
|
||||
autoSplitPDF.submit=Submit
|
||||
|
||||
@@ -1184,7 +1185,7 @@ changeMetadata.submit=Change
|
||||
#pdfToPDFA
|
||||
pdfToPDFA.title=PDF To PDF/A
|
||||
pdfToPDFA.header=PDF To PDF/A
|
||||
pdfToPDFA.credit=This service uses libreoffice for PDF/A conversion
|
||||
pdfToPDFA.credit=This service uses qpdf for PDF/A conversion
|
||||
pdfToPDFA.submit=Convert
|
||||
pdfToPDFA.tip=Currently does not work for multiple inputs at once
|
||||
pdfToPDFA.outputFormat=Output format
|
||||
|
||||
@@ -1185,7 +1185,7 @@ changeMetadata.submit=Change
|
||||
#pdfToPDFA
|
||||
pdfToPDFA.title=PDF To PDF/A
|
||||
pdfToPDFA.header=PDF To PDF/A
|
||||
pdfToPDFA.credit=This service uses libreoffice for PDF/A conversion
|
||||
pdfToPDFA.credit=This service uses qpdf for PDF/A conversion
|
||||
pdfToPDFA.submit=Convert
|
||||
pdfToPDFA.tip=Currently does not work for multiple inputs at once
|
||||
pdfToPDFA.outputFormat=Output format
|
||||
|
||||
@@ -138,7 +138,7 @@ analytics.settings=Você pode alterar as configurações de coleta de dados no a
|
||||
# NAVBAR #
|
||||
#############
|
||||
navbar.favorite=Favoritos
|
||||
navbar.recent=Novos e Recentemente Atualizados
|
||||
navbar.recent=New and recently updated
|
||||
navbar.darkmode=Modo Escuro
|
||||
navbar.language=Idiomas
|
||||
navbar.settings=Configurações
|
||||
@@ -266,14 +266,14 @@ home.viewPdf.title=Visualizar PDF
|
||||
home.viewPdf.desc=Visualizar, anotar, adicionar texto ou imagens ao PDF.
|
||||
viewPdf.tags=visualizar,ler,anotar,texto,imagem
|
||||
|
||||
home.setFavorites=Adicionar Favoritos
|
||||
home.hideFavorites=Ocultar Favoritos
|
||||
home.showFavorites=Mostrar Favoritos
|
||||
home.legacyHomepage=Homepage Antiga
|
||||
home.newHomePage=Experimente nossa nova Homepage!
|
||||
home.alphabetical=Alfabética
|
||||
home.globalPopularity=Popularidade Global
|
||||
home.sortBy=Ordenar por:
|
||||
home.setFavorites=Set Favourites
|
||||
home.hideFavorites=Hide Favourites
|
||||
home.showFavorites=Show Favourites
|
||||
home.legacyHomepage=Old homepage
|
||||
home.newHomePage=Try our new homepage!
|
||||
home.alphabetical=Alphabetical
|
||||
home.globalPopularity=Global Popularity
|
||||
home.sortBy=Sort by:
|
||||
|
||||
home.multiTool.title=Multiferramentas de PDF
|
||||
home.multiTool.desc=Mesclar, girar, reorganizar, dividir, inserir e remover páginas.
|
||||
@@ -417,7 +417,7 @@ home.pageLayout.title=Layout de Múltiplas Páginas
|
||||
home.pageLayout.desc=Mesclar várias páginas de um documento PDF em uma única página.
|
||||
pageLayout.tags=mesclar,composto,vista-única,organizar
|
||||
|
||||
home.scalePages.title=Ajustar Dimensões da Página
|
||||
home.scalePages.title=Ajustar Tamanho/Escala da Página
|
||||
home.scalePages.desc=Alterar o tamanho/escala da página e/ou seu conteúdo.
|
||||
scalePages.tags=redimensionar,modificar,dimensão,adaptar
|
||||
|
||||
@@ -429,7 +429,7 @@ home.add-page-numbers.title=Adicionar Números de Página
|
||||
home.add-page-numbers.desc=Adicionar números de página no documento, em um local definido.
|
||||
add-page-numbers.tags=paginar,rotular,organizar,índice
|
||||
|
||||
home.auto-rename.title=Renomeação Automática do PDF
|
||||
home.auto-rename.title=Renomear Automaticamente o PDF
|
||||
home.auto-rename.desc=Renomeia automaticamente o PDF com base no cabeçalho detectado.
|
||||
auto-rename.tags=detecção-automática,baseado-em-cabeçalho,organizar,relabel
|
||||
|
||||
@@ -738,8 +738,8 @@ addPageNumbers.submit=Adicionar Números de Página
|
||||
|
||||
|
||||
#auto-rename
|
||||
auto-rename.title=Renomeação Automática do PDF
|
||||
auto-rename.header=Renomeação Automática do PDF
|
||||
auto-rename.title=Renomear Automaticamente o PDF
|
||||
auto-rename.header=Renomear Automaticamente o PDF
|
||||
auto-rename.submit=Renomeação Automática
|
||||
|
||||
|
||||
@@ -786,8 +786,8 @@ pageLayout.submit=Enviar
|
||||
|
||||
|
||||
#scalePages
|
||||
scalePages.title=Ajustar Dimensões da Página
|
||||
scalePages.header=Ajustar Dimensões da Página
|
||||
scalePages.title=Ajustar Tamanho/Escala da Página
|
||||
scalePages.header=Ajustar Tamanho/Escala da Página
|
||||
scalePages.pageSize=Tamanho desejado do documento:
|
||||
scalePages.keepPageSize=Tamanho Original
|
||||
scalePages.scaleFactor=Fator de zoom (corte) de uma página:
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -48,7 +48,7 @@ window.tooltipSetup = () => {
|
||||
tooltipElements.forEach((element) => {
|
||||
const tooltipText = element.getAttribute('title');
|
||||
element.removeAttribute('title');
|
||||
element.setAttribute('data-title', tooltipText);
|
||||
element.setAttribute('data-title', 'tooltipText');
|
||||
const customTooltip = document.createElement('div');
|
||||
customTooltip.className = 'btn-tooltip';
|
||||
customTooltip.textContent = tooltipText;
|
||||
|
||||
@@ -45,6 +45,8 @@
|
||||
<li th:text="#{autoSplitPDF.selectText.3}"></li>
|
||||
<li th:text="#{autoSplitPDF.selectText.4}"></li>
|
||||
</ul>
|
||||
<p><a th:href="@{'/files/Auto%20Splitter%20Divider%20(minimal).pdf'}" download
|
||||
th:text="#{autoSplitPDF.dividerDownload1}"></a></p>
|
||||
<p><a th:href="@{'/files/Auto%20Splitter%20Divider%20(with%20instructions).pdf'}" download
|
||||
th:text="#{autoSplitPDF.dividerDownload2}"></a></p>
|
||||
</div>
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
<th:block th:fragment="navElements">
|
||||
<div id="groupOrganize" class="feature-group">
|
||||
<div th:replace="~{fragments/featureGroupHeader :: featureGroupHeader(groupTitle=#{navbar.sections.organize})}">
|
||||
</div>
|
||||
<div class="nav-group-container">
|
||||
<div id="groupOrganize" class="feature-group">
|
||||
<div
|
||||
th:replace="~{fragments/featureGroupHeader :: featureGroupHeader(groupTitle=#{navbar.sections.organize})}">
|
||||
</div>
|
||||
<div class="nav-group-container">
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry ('multi-tool', 'construction', 'home.multiTool.title', 'home.multiTool.desc', 'multiTool.tags', 'organize')}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry ('merge-pdfs', 'add_to_photos', 'home.merge.title', 'home.merge.desc', 'merge.tags', 'organize')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry ('split-pdfs', 'cut', 'home.split.title', 'home.split.desc', 'split.tags', 'organize')}">
|
||||
</div>
|
||||
<div
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry ('split-pdfs', 'cut', 'home.split.title', 'home.split.desc', 'split.tags', 'organize')}"></div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('rotate-pdf', 'rotate_right', 'home.rotate.title', 'home.rotate.desc', 'rotate.tags', 'organize')}">
|
||||
</div>
|
||||
<div
|
||||
@@ -37,14 +37,15 @@
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('pdf-to-single-page', 'looks_one', 'home.PdfToSinglePage.title', 'home.PdfToSinglePage.desc', 'PdfToSinglePage.tags', 'organize')}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="groupConvertTo" class="feature-group">
|
||||
<div th:replace="~{fragments/featureGroupHeader :: featureGroupHeader(groupTitle=#{navbar.sections.convertTo})}">
|
||||
</div>
|
||||
<div class="nav-group-container">
|
||||
<div id="groupConvertTo" class="feature-group">
|
||||
<div
|
||||
th:replace="~{fragments/featureGroupHeader :: featureGroupHeader(groupTitle=#{navbar.sections.convertTo})}">
|
||||
</div>
|
||||
<div class="nav-group-container">
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('img-to-pdf', 'picture_as_pdf', 'home.imageToPdf.title', 'home.imageToPdf.desc', 'imageToPdf.tags', 'convertto')}">
|
||||
</div>
|
||||
<div
|
||||
@@ -62,13 +63,14 @@
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('book-to-pdf', 'book', 'home.BookToPDF.title', 'home.BookToPDF.desc', 'BookToPDF.tags', 'convertto')}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="groupConvertFrom" class="feature-group">
|
||||
<div th:replace="~{fragments/featureGroupHeader :: featureGroupHeader(groupTitle=#{navbar.sections.convertFrom})}">
|
||||
</div>
|
||||
<div class="nav-group-container">
|
||||
<div id="groupConvertFrom" class="feature-group">
|
||||
<div
|
||||
th:replace="~{fragments/featureGroupHeader :: featureGroupHeader(groupTitle=#{navbar.sections.convertFrom})}">
|
||||
</div>
|
||||
<div class="nav-group-container">
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('pdf-to-img', 'photo_library', 'home.pdfToImage.title', 'home.pdfToImage.desc', 'pdfToImage.tags', 'convert')}">
|
||||
</div>
|
||||
<div
|
||||
@@ -96,16 +98,17 @@
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('pdf-to-book', 'book', 'home.PDFToBook.title', 'home.PDFToBook.desc', 'PDFToBook.tags', 'convert')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry ('pdf-to-markdown', 'markdown_copy', 'home.PDFToMarkdown.title', 'home.PDFToMarkdown.desc', 'PDFToMarkdown.tags', 'convert')}">
|
||||
</div>
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry ('pdf-to-markdown', 'markdown_copy', 'home.PDFToMarkdown.title', 'home.PDFToMarkdown.desc', 'PDFToMarkdown.tags', 'convert')}">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div id="convertGroup" class="feature-group">
|
||||
<div th:replace="~{fragments/featureGroupHeader :: featureGroupHeader(groupTitle=#{navbar.sections.convertTo})}">
|
||||
</div>
|
||||
<div class="nav-group-container">
|
||||
<div id="convertGroup" class="feature-group">
|
||||
<div
|
||||
th:replace="~{fragments/featureGroupHeader :: featureGroupHeader(groupTitle=#{navbar.sections.convertTo})}">
|
||||
</div>
|
||||
<div class="nav-group-container">
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('img-to-pdf', 'picture_as_pdf', 'home.imageToPdf.title', 'home.imageToPdf.desc', 'imageToPdf.tags', 'convertto')}">
|
||||
</div>
|
||||
<div
|
||||
@@ -123,11 +126,12 @@
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('book-to-pdf', 'book', 'home.BookToPDF.title', 'home.BookToPDF.desc', 'BookToPDF.tags', 'convertto')}">
|
||||
</div>
|
||||
</div>
|
||||
<div th:replace="~{fragments/featureGroupHeader :: featureGroupHeader(groupTitle=#{navbar.sections.convertFrom})}">
|
||||
</div>
|
||||
<div class="nav-group-container">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/featureGroupHeader :: featureGroupHeader(groupTitle=#{navbar.sections.convertFrom})}">
|
||||
</div>
|
||||
<div class="nav-group-container">
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('pdf-to-img', 'photo_library', 'home.pdfToImage.title', 'home.pdfToImage.desc', 'pdfToImage.tags', 'convert')}">
|
||||
</div>
|
||||
<div
|
||||
@@ -155,12 +159,13 @@
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('pdf-to-book', 'book', 'home.PDFToBook.title', 'home.PDFToBook.desc', 'PDFToBook.tags', 'convert')}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="groupSecurity" class="feature-group">
|
||||
<div th:replace="~{fragments/featureGroupHeader :: featureGroupHeader(groupTitle=#{navbar.sections.security})}">
|
||||
</div>
|
||||
<div class="nav-group-container">
|
||||
<div id="groupSecurity" class="feature-group">
|
||||
<div
|
||||
th:replace="~{fragments/featureGroupHeader :: featureGroupHeader(groupTitle=#{navbar.sections.security})}">
|
||||
</div>
|
||||
<div class="nav-group-container">
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('add-password', 'lock', 'home.addPassword.title', 'home.addPassword.desc', 'addPassword.tags', 'security')}">
|
||||
</div>
|
||||
<div
|
||||
@@ -177,34 +182,34 @@
|
||||
</div>
|
||||
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('validate-signature', 'verified', 'home.validateSignature.title', 'home.validateSignature.desc', 'validateSignature.tags', 'security')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('remove-cert-sign', 'remove_moderator', 'home.removeCertSign.title', 'home.removeCertSign.desc', 'removeCertSign.tags', 'security')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('sanitize-pdf', 'sanitizer', 'home.sanitizePdf.title', 'home.sanitizePdf.desc', 'sanitizePdf.tags', 'security')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntryCustom :: navbarEntry('auto-redact', '/images/redact-auto.svg#icon-redact-auto', 'home.autoRedact.title', 'home.autoRedact.desc', 'autoRedact.tags', 'security')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntryCustom :: navbarEntry('redact', '/images/redact-manual.svg#icon-redact-manual', 'home.redact.title', 'home.redact.desc', 'redact.tags', 'security')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('stamp', 'approval', 'home.AddStampRequest.title', 'home.AddStampRequest.desc', 'AddStampRequest.tags', 'security')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('add-watermark', 'water_drop', 'home.watermark.title', 'home.watermark.desc', 'watermark.tags', 'security')}">
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('validate-signature', 'verified', 'home.validateSignature.title', 'home.validateSignature.desc', 'validateSignature.tags', 'security')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('remove-cert-sign', 'remove_moderator', 'home.removeCertSign.title', 'home.removeCertSign.desc', 'removeCertSign.tags', 'security')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('sanitize-pdf', 'sanitizer', 'home.sanitizePdf.title', 'home.sanitizePdf.desc', 'sanitizePdf.tags', 'security')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntryCustom :: navbarEntry('auto-redact', '/images/redact-auto.svg#icon-redact-auto', 'home.autoRedact.title', 'home.autoRedact.desc', 'autoRedact.tags', 'security')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntryCustom :: navbarEntry('redact', '/images/redact-manual.svg#icon-redact-manual', 'home.redact.title', 'home.redact.desc', 'redact.tags', 'security')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('stamp', 'approval', 'home.AddStampRequest.title', 'home.AddStampRequest.desc', 'AddStampRequest.tags', 'security')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('add-watermark', 'water_drop', 'home.watermark.title', 'home.watermark.desc', 'watermark.tags', 'security')}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="groupView" class="feature-group">
|
||||
<div th:replace="~{fragments/featureGroupHeader :: featureGroupHeader(groupTitle=#{navbar.sections.edit})}">
|
||||
</div>
|
||||
<div class="nav-group-container">
|
||||
<div
|
||||
<div id="groupView" class="feature-group">
|
||||
<div th:replace="~{fragments/featureGroupHeader :: featureGroupHeader(groupTitle=#{navbar.sections.edit})}">
|
||||
</div>
|
||||
<div class="nav-group-container">
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('view-pdf', 'menu_book', 'home.viewPdf.title', 'home.viewPdf.desc', 'viewPdf.tags', 'other')}">
|
||||
</div>
|
||||
<div
|
||||
@@ -241,15 +246,16 @@
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('remove-image-pdf', 'remove_selection', 'home.removeImagePdf.title', 'home.removeImagePdf.desc', 'removeImagePdf.tags', 'other')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('replace-and-invert-color-pdf', 'format_color_fill', 'home.replaceColorPdf.title', 'home.replaceColorPdf.desc', 'replaceColorPdf.tags', 'other')}">
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('replace-color-pdf', 'format_color_fill', 'home.replaceColorPdf.title', 'home.replaceColorPdf.desc', 'replaceColorPdf.tags', 'other')}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="groupAdvanced" class="feature-group">
|
||||
<div th:replace="~{fragments/featureGroupHeader :: featureGroupHeader(groupTitle=#{navbar.sections.advance})}">
|
||||
</div>
|
||||
<div class="nav-group-container">
|
||||
<div id="groupAdvanced" class="feature-group">
|
||||
<div
|
||||
th:replace="~{fragments/featureGroupHeader :: featureGroupHeader(groupTitle=#{navbar.sections.advance})}">
|
||||
</div>
|
||||
<div class="nav-group-container">
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('pipeline', 'family_history', 'home.pipeline.title', 'home.pipeline.desc', 'pipeline.tags', 'advance')}">
|
||||
</div>
|
||||
<div
|
||||
@@ -285,6 +291,6 @@
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntryCustom :: navbarEntry('split-pdf-by-chapters', '/images/split-chapters.svg#icon-split-chapters', 'home.splitPdfByChapters.title', 'home.splitPdfByChapters.desc', 'splitPdfByChapters.tags', 'advance')}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</th:block>
|
||||
</th:block>
|
||||
@@ -27,16 +27,15 @@
|
||||
<span class="material-symbols-rounded search-icon">
|
||||
search
|
||||
</span>
|
||||
<input type="text" id="searchBar" onkeyup="filterCardsLegacy()" th:placeholder="#{home.searchBar}" autofocus>
|
||||
<input type="text" id="searchBar" onkeyup="filterCards()" th:placeholder="#{home.searchBar}" autofocus>
|
||||
<div style="display: flex; align-items: center;">
|
||||
<a href="home" onclick="setAsDefault('home')"
|
||||
style="text-decoration: none; color: inherit; cursor: pointer; display: flex; align-items: center;">
|
||||
<span th:text="#{home.newHomePage}">
|
||||
</span>
|
||||
<span class="material-symbols-rounded toggle-favourites" style="font-size: 2rem; margin-left: 0.2rem;">
|
||||
home
|
||||
</span>
|
||||
</a>
|
||||
<a href="home" onclick="setAsDefault('home')" style="text-decoration: none; color: inherit; cursor: pointer; display: flex; align-items: center;">
|
||||
<span th:text="#{home.newHomePage}">
|
||||
</span>
|
||||
<span class="material-symbols-rounded toggle-favourites" style="font-size: 2rem; margin-left: 0.2rem;" >
|
||||
home
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
<div id="filtersContainer">
|
||||
<span class="material-symbols-rounded filter-button" onclick="toggleFavoritesOnly()">
|
||||
@@ -71,8 +70,7 @@
|
||||
</div>
|
||||
|
||||
<div id="groupFavorites" class="feature-group-legacy">
|
||||
<div
|
||||
th:replace="~{fragments/featureGroupHeaderLegacy :: featureGroupHeader(groupTitle=#{navbar.favorite})}">
|
||||
<div th:replace="~{fragments/featureGroupHeaderLegacy :: featureGroupHeader(groupTitle=#{navbar.favorite})}">
|
||||
</div>
|
||||
<div class="feature-group-container">
|
||||
</div>
|
||||
@@ -250,8 +248,7 @@
|
||||
</div>
|
||||
|
||||
<div id="groupView" class="feature-group-legacy">
|
||||
<div
|
||||
th:replace="~{fragments/featureGroupHeaderLegacy :: featureGroupHeader(groupTitle=#{navbar.sections.edit})}">
|
||||
<div th:replace="~{fragments/featureGroupHeaderLegacy :: featureGroupHeader(groupTitle=#{navbar.sections.edit})}">
|
||||
</div>
|
||||
<div class="feature-group-container">
|
||||
<div
|
||||
@@ -292,7 +289,7 @@
|
||||
th:replace="~{fragments/card :: card(id='remove-image-pdf', cardTitle=#{home.removeImagePdf.title}, cardText=#{home.removeImagePdf.desc}, cardLink='remove-image-pdf', toolIcon='remove_selection', tags=#{removeImagePdf.tags}, toolGroup='other')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/card :: card(id='replace-and-invert-color-pdf', cardTitle=#{home.replaceColorPdf.title}, cardText=#{home.replaceColorPdf.desc}, cardLink='replace-and-invert-color-pdf', toolIcon='format_color_fill', tags=#{replaceColorPdf.tags}, toolGroup='other')}">
|
||||
th:replace="~{fragments/card :: card(id='replace-color-pdf', cardTitle=#{home.replaceColorPdf.title}, cardText=#{home.replaceColorPdf.desc}, cardLink='replace-and-invert-color-pdf', toolIcon='format_color_fill', tags=#{replaceColorPdf.tags}, toolGroup='other')}">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -516,7 +513,7 @@
|
||||
function setAsDefault(value) {
|
||||
localStorage.setItem('defaultView', value);
|
||||
console.log(`Default view set to: ${value}`);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
150
testing/test.sh
150
testing/test.sh
@@ -1,5 +1,8 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Default value for the Boolean parameter
|
||||
VERIFICATION=${1:-false} # Default is "false" if no parameter is passed
|
||||
|
||||
# Find project root by locating build.gradle
|
||||
find_root() {
|
||||
local dir="$PWD"
|
||||
@@ -23,18 +26,18 @@ check_health() {
|
||||
local end=$((SECONDS+60))
|
||||
|
||||
echo -n "Waiting for $service_name to become healthy..."
|
||||
until [ "$(docker inspect --format='{{json .State.Health.Status}}' "$service_name")" == '"healthy"' ] || [ $SECONDS -ge $end ]; do
|
||||
sleep 3
|
||||
echo -n "."
|
||||
if [ $SECONDS -ge $end ]; then
|
||||
echo -e "\n$service_name health check timed out after 80 seconds."
|
||||
echo "Printing logs for $service_name:"
|
||||
until [ "$(docker inspect --format='{{json .State.Health.Status}}' "$service_name")" == '"healthy"' ] || [ $SECONDS -ge $end ]; do
|
||||
sleep 3
|
||||
echo -n "."
|
||||
if [ $SECONDS -ge $end ]; then
|
||||
echo -e "\n$service_name health check timed out after 80 seconds."
|
||||
echo "Printing logs for $service_name:"
|
||||
docker logs "$service_name"
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
echo -e "\n$service_name is healthy!"
|
||||
echo "Printing logs for $service_name:"
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
echo -e "\n$service_name is healthy!"
|
||||
echo "Printing logs for $service_name:"
|
||||
docker logs "$service_name"
|
||||
return 0
|
||||
}
|
||||
@@ -78,10 +81,10 @@ run_tests() {
|
||||
|
||||
# Main testing routine
|
||||
main() {
|
||||
SECONDS=0
|
||||
SECONDS=0
|
||||
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
|
||||
export DOCKER_ENABLE_SECURITY=false
|
||||
# Run the gradlew build command and check if it fails
|
||||
if ! ./gradlew clean build; then
|
||||
@@ -89,26 +92,28 @@ main() {
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
# Building Docker images
|
||||
# docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t stirlingtools/stirling-pdf:latest -f ./Dockerfile .
|
||||
docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t stirlingtools/stirling-pdf:latest-ultra-lite -f ./Dockerfile.ultra-lite .
|
||||
|
||||
|
||||
# Test each configuration
|
||||
run_tests "Stirling-PDF-Ultra-Lite" "./exampleYmlFiles/docker-compose-latest-ultra-lite.yml"
|
||||
|
||||
echo "Testing webpage accessibility..."
|
||||
cd "testing"
|
||||
if ./test_webpages.sh -f webpage_urls.txt -b http://localhost:8080; then
|
||||
passed_tests+=("Webpage-Accessibility-lite")
|
||||
else
|
||||
failed_tests+=("Webpage-Accessibility-lite")
|
||||
echo "Webpage accessibility lite tests failed"
|
||||
fi
|
||||
cd "$PROJECT_ROOT"
|
||||
docker-compose -f "./exampleYmlFiles/docker-compose-latest-ultra-lite.yml" down
|
||||
|
||||
|
||||
echo "Testing webpage accessibility..."
|
||||
cd "testing"
|
||||
if ./test_webpages.sh -f webpage_urls.txt -b http://localhost:8080; then
|
||||
passed_tests+=("Webpage-Accessibility-lite")
|
||||
else
|
||||
failed_tests+=("Webpage-Accessibility-lite")
|
||||
echo "Webpage accessibility lite tests failed"
|
||||
fi
|
||||
cd "$PROJECT_ROOT"
|
||||
docker-compose -f "./exampleYmlFiles/docker-compose-latest-ultra-lite.yml" down
|
||||
|
||||
# run_tests "Stirling-PDF" "./exampleYmlFiles/docker-compose-latest.yml"
|
||||
# docker-compose -f "./exampleYmlFiles/docker-compose-latest.yml" down
|
||||
#run_tests "Stirling-PDF" "./exampleYmlFiles/docker-compose-latest.yml"
|
||||
#docker-compose -f "./exampleYmlFiles/docker-compose-latest.yml" down
|
||||
|
||||
export DOCKER_ENABLE_SECURITY=true
|
||||
# Run the gradlew build command and check if it fails
|
||||
@@ -117,68 +122,72 @@ main() {
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
# Building Docker images with security enabled
|
||||
# docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t stirlingtools/stirling-pdf:latest -f ./Dockerfile .
|
||||
# docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t stirlingtools/stirling-pdf:latest-ultra-lite -f ./Dockerfile.ultra-lite .
|
||||
# docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t stirlingtools/stirling-pdf:latest -f ./Dockerfile .
|
||||
# docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t stirlingtools/stirling-pdf:latest-ultra-lite -f ./Dockerfile.ultra-lite .
|
||||
docker build --no-cache --pull --build-arg VERSION_TAG=alpha -t stirlingtools/stirling-pdf:latest-fat -f ./Dockerfile.fat .
|
||||
|
||||
|
||||
|
||||
|
||||
# Test each configuration with security
|
||||
# run_tests "Stirling-PDF-Ultra-Lite-Security" "./exampleYmlFiles/docker-compose-latest-ultra-lite-security.yml"
|
||||
# docker-compose -f "./exampleYmlFiles/docker-compose-latest-ultra-lite-security.yml" down
|
||||
# run_tests "Stirling-PDF-Security" "./exampleYmlFiles/docker-compose-latest-security.yml"
|
||||
# docker-compose -f "./exampleYmlFiles/docker-compose-latest-security.yml" down
|
||||
# run_tests "Stirling-PDF-Ultra-Lite-Security" "./exampleYmlFiles/docker-compose-latest-ultra-lite-security.yml"
|
||||
#docker-compose -f "./exampleYmlFiles/docker-compose-latest-ultra-lite-security.yml" down
|
||||
# run_tests "Stirling-PDF-Security" "./exampleYmlFiles/docker-compose-latest-security.yml"
|
||||
# docker-compose -f "./exampleYmlFiles/docker-compose-latest-security.yml" down
|
||||
|
||||
|
||||
run_tests "Stirling-PDF-Security-Fat" "./exampleYmlFiles/docker-compose-latest-fat-security.yml"
|
||||
run_tests "Stirling-PDF-Security-Fat" "./exampleYmlFiles/docker-compose-latest-fat-security.yml"
|
||||
|
||||
echo "Testing webpage accessibility..."
|
||||
cd "testing"
|
||||
if ./test_webpages.sh -f webpage_urls_full.txt -b http://localhost:8080; then
|
||||
passed_tests+=("Webpage-Accessibility-full")
|
||||
else
|
||||
failed_tests+=("Webpage-Accessibility-full")
|
||||
echo "Webpage accessibility full tests failed"
|
||||
fi
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
docker-compose -f "./exampleYmlFiles/docker-compose-latest-fat-security.yml" down
|
||||
|
||||
echo "Testing webpage accessibility..."
|
||||
cd "testing"
|
||||
if ./test_webpages.sh -f webpage_urls_full.txt -b http://localhost:8080; then
|
||||
passed_tests+=("Webpage-Accessibility-full")
|
||||
else
|
||||
failed_tests+=("Webpage-Accessibility-full")
|
||||
echo "Webpage accessibility full tests failed"
|
||||
fi
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
docker-compose -f "./exampleYmlFiles/docker-compose-latest-fat-security.yml" down
|
||||
|
||||
run_tests "Stirling-PDF-Security-Fat-with-login" "./exampleYmlFiles/test_cicd.yml"
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
cd "testing/cucumber"
|
||||
if python -m behave; then
|
||||
passed_tests+=("Stirling-PDF-Regression")
|
||||
else
|
||||
failed_tests+=("Stirling-PDF-Regression")
|
||||
echo "Printing docker logs of failed regression"
|
||||
docker logs "Stirling-PDF-Security-Fat-with-login"
|
||||
echo "Printed docker logs of failed regression"
|
||||
fi
|
||||
cd "$PROJECT_ROOT"
|
||||
fi
|
||||
|
||||
docker-compose -f "./exampleYmlFiles/test_cicd.yml" down
|
||||
run_tests "Stirling-PDF-Security-Fat-with-login" "./exampleYmlFiles/test_cicd.yml"
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
cd "testing/cucumber"
|
||||
if python -m behave; then
|
||||
passed_tests+=("Stirling-PDF-Regression")
|
||||
else
|
||||
failed_tests+=("Stirling-PDF-Regression")
|
||||
echo "Printing docker logs of failed regression"
|
||||
docker logs "Stirling-PDF-Security-Fat-with-login"
|
||||
echo "Printed docker logs of failed regression"
|
||||
fi
|
||||
cd "$PROJECT_ROOT"
|
||||
fi
|
||||
|
||||
docker-compose -f "./exampleYmlFiles/test_cicd.yml" down
|
||||
|
||||
# Report results
|
||||
echo "All tests completed in $SECONDS seconds."
|
||||
|
||||
|
||||
if [ ${#passed_tests[@]} -ne 0 ]; then
|
||||
echo "Passed tests:"
|
||||
fi
|
||||
if [ ${#passed_tests[@]} -ne 0 ]; then
|
||||
echo "Passed tests:"
|
||||
fi
|
||||
for test in "${passed_tests[@]}"; do
|
||||
echo -e "\e[32m$test\e[0m" # Green color for passed tests
|
||||
done
|
||||
|
||||
if [ ${#failed_tests[@]} -ne 0 ]; then
|
||||
echo "Failed tests:"
|
||||
fi
|
||||
if [ ${#failed_tests[@]} -ne 0 ]; then
|
||||
echo "Failed tests:"
|
||||
fi
|
||||
for test in "${failed_tests[@]}"; do
|
||||
echo -e "\e[31m$test\e[0m" # Red color for failed tests
|
||||
done
|
||||
|
||||
|
||||
|
||||
# Check if there are any failed tests and exit with an error code if so
|
||||
if [ ${#failed_tests[@]} -ne 0 ]; then
|
||||
echo "Some tests failed."
|
||||
@@ -187,6 +196,7 @@ main() {
|
||||
echo "All tests passed successfully."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
main
|
||||
main
|
||||
Reference in New Issue
Block a user