mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2024-11-17 12:40:11 +01:00
language cleanups and sanitize
This commit is contained in:
parent
d07e3e6522
commit
92b9142902
@ -1,200 +1,208 @@
|
|||||||
package stirling.software.SPDF.config;
|
package stirling.software.SPDF.config;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@Service
|
@Service
|
||||||
public class EndpointConfiguration {
|
public class EndpointConfiguration {
|
||||||
private static final Logger logger = LoggerFactory.getLogger(EndpointConfiguration.class);
|
private static final Logger logger = LoggerFactory.getLogger(EndpointConfiguration.class);
|
||||||
private Map<String, Boolean> endpointStatuses = new ConcurrentHashMap<>();
|
private Map<String, Boolean> endpointStatuses = new ConcurrentHashMap<>();
|
||||||
private Map<String, Set<String>> endpointGroups = new ConcurrentHashMap<>();
|
private Map<String, Set<String>> endpointGroups = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
public EndpointConfiguration() {
|
public EndpointConfiguration() {
|
||||||
init();
|
init();
|
||||||
processEnvironmentConfigs();
|
processEnvironmentConfigs();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void enableEndpoint(String endpoint) {
|
public void enableEndpoint(String endpoint) {
|
||||||
endpointStatuses.put(endpoint, true);
|
endpointStatuses.put(endpoint, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void disableEndpoint(String endpoint) {
|
public void disableEndpoint(String endpoint) {
|
||||||
if(!endpointStatuses.containsKey(endpoint) || endpointStatuses.get(endpoint) != false) {
|
if(!endpointStatuses.containsKey(endpoint) || endpointStatuses.get(endpoint) != false) {
|
||||||
logger.info("Disabling {}", endpoint);
|
logger.info("Disabling {}", endpoint);
|
||||||
endpointStatuses.put(endpoint, false);
|
endpointStatuses.put(endpoint, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEndpointEnabled(String endpoint) {
|
public boolean isEndpointEnabled(String endpoint) {
|
||||||
if (endpoint.startsWith("/")) {
|
if (endpoint.startsWith("/")) {
|
||||||
endpoint = endpoint.substring(1);
|
endpoint = endpoint.substring(1);
|
||||||
}
|
}
|
||||||
return endpointStatuses.getOrDefault(endpoint, true);
|
return endpointStatuses.getOrDefault(endpoint, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addEndpointToGroup(String group, String endpoint) {
|
public void addEndpointToGroup(String group, String endpoint) {
|
||||||
endpointGroups.computeIfAbsent(group, k -> new HashSet<>()).add(endpoint);
|
endpointGroups.computeIfAbsent(group, k -> new HashSet<>()).add(endpoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void enableGroup(String group) {
|
public void enableGroup(String group) {
|
||||||
Set<String> endpoints = endpointGroups.get(group);
|
Set<String> endpoints = endpointGroups.get(group);
|
||||||
if (endpoints != null) {
|
if (endpoints != null) {
|
||||||
for (String endpoint : endpoints) {
|
for (String endpoint : endpoints) {
|
||||||
enableEndpoint(endpoint);
|
enableEndpoint(endpoint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void disableGroup(String group) {
|
public void disableGroup(String group) {
|
||||||
Set<String> endpoints = endpointGroups.get(group);
|
Set<String> endpoints = endpointGroups.get(group);
|
||||||
if (endpoints != null) {
|
if (endpoints != null) {
|
||||||
for (String endpoint : endpoints) {
|
for (String endpoint : endpoints) {
|
||||||
disableEndpoint(endpoint);
|
disableEndpoint(endpoint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void init() {
|
public void init() {
|
||||||
// Adding endpoints to "PageOps" group
|
// Adding endpoints to "PageOps" group
|
||||||
addEndpointToGroup("PageOps", "remove-pages");
|
addEndpointToGroup("PageOps", "remove-pages");
|
||||||
addEndpointToGroup("PageOps", "merge-pdfs");
|
addEndpointToGroup("PageOps", "merge-pdfs");
|
||||||
addEndpointToGroup("PageOps", "split-pdfs");
|
addEndpointToGroup("PageOps", "split-pdfs");
|
||||||
addEndpointToGroup("PageOps", "pdf-organizer");
|
addEndpointToGroup("PageOps", "pdf-organizer");
|
||||||
addEndpointToGroup("PageOps", "rotate-pdf");
|
addEndpointToGroup("PageOps", "rotate-pdf");
|
||||||
addEndpointToGroup("PageOps", "multi-page-layout");
|
addEndpointToGroup("PageOps", "multi-page-layout");
|
||||||
addEndpointToGroup("PageOps", "scale-pages");
|
addEndpointToGroup("PageOps", "scale-pages");
|
||||||
|
addEndpointToGroup("PageOps", "adjust-contrast");
|
||||||
// Adding endpoints to "Convert" group
|
addEndpointToGroup("PageOps", "crop");
|
||||||
addEndpointToGroup("Convert", "pdf-to-img");
|
addEndpointToGroup("PageOps", "auto-split-pdf");
|
||||||
addEndpointToGroup("Convert", "img-to-pdf");
|
|
||||||
addEndpointToGroup("Convert", "pdf-to-pdfa");
|
// Adding endpoints to "Convert" group
|
||||||
addEndpointToGroup("Convert", "file-to-pdf");
|
addEndpointToGroup("Convert", "pdf-to-img");
|
||||||
addEndpointToGroup("Convert", "xlsx-to-pdf");
|
addEndpointToGroup("Convert", "img-to-pdf");
|
||||||
addEndpointToGroup("Convert", "pdf-to-word");
|
addEndpointToGroup("Convert", "pdf-to-pdfa");
|
||||||
addEndpointToGroup("Convert", "pdf-to-presentation");
|
addEndpointToGroup("Convert", "file-to-pdf");
|
||||||
addEndpointToGroup("Convert", "pdf-to-text");
|
addEndpointToGroup("Convert", "xlsx-to-pdf");
|
||||||
addEndpointToGroup("Convert", "pdf-to-html");
|
addEndpointToGroup("Convert", "pdf-to-word");
|
||||||
addEndpointToGroup("Convert", "pdf-to-xml");
|
addEndpointToGroup("Convert", "pdf-to-presentation");
|
||||||
|
addEndpointToGroup("Convert", "pdf-to-text");
|
||||||
// Adding endpoints to "Security" group
|
addEndpointToGroup("Convert", "pdf-to-html");
|
||||||
addEndpointToGroup("Security", "add-password");
|
addEndpointToGroup("Convert", "pdf-to-xml");
|
||||||
addEndpointToGroup("Security", "remove-password");
|
|
||||||
addEndpointToGroup("Security", "change-permissions");
|
// Adding endpoints to "Security" group
|
||||||
addEndpointToGroup("Security", "add-watermark");
|
addEndpointToGroup("Security", "add-password");
|
||||||
addEndpointToGroup("Security", "cert-sign");
|
addEndpointToGroup("Security", "remove-password");
|
||||||
|
addEndpointToGroup("Security", "change-permissions");
|
||||||
|
addEndpointToGroup("Security", "add-watermark");
|
||||||
|
addEndpointToGroup("Security", "cert-sign");
|
||||||
// Adding endpoints to "Other" group
|
addEndpointToGroup("Security", "sanitize-pdf");
|
||||||
addEndpointToGroup("Other", "ocr-pdf");
|
|
||||||
addEndpointToGroup("Other", "add-image");
|
|
||||||
addEndpointToGroup("Other", "compress-pdf");
|
// Adding endpoints to "Other" group
|
||||||
addEndpointToGroup("Other", "extract-images");
|
addEndpointToGroup("Other", "ocr-pdf");
|
||||||
addEndpointToGroup("Other", "change-metadata");
|
addEndpointToGroup("Other", "add-image");
|
||||||
addEndpointToGroup("Other", "extract-image-scans");
|
addEndpointToGroup("Other", "compress-pdf");
|
||||||
addEndpointToGroup("Other", "sign");
|
addEndpointToGroup("Other", "extract-images");
|
||||||
addEndpointToGroup("Other", "flatten");
|
addEndpointToGroup("Other", "change-metadata");
|
||||||
addEndpointToGroup("Other", "repair");
|
addEndpointToGroup("Other", "extract-image-scans");
|
||||||
addEndpointToGroup("Other", "remove-blanks");
|
addEndpointToGroup("Other", "sign");
|
||||||
addEndpointToGroup("Other", "compare");
|
addEndpointToGroup("Other", "flatten");
|
||||||
|
addEndpointToGroup("Other", "repair");
|
||||||
|
addEndpointToGroup("Other", "remove-blanks");
|
||||||
|
addEndpointToGroup("Other", "compare");
|
||||||
|
addEndpointToGroup("Other", "add-page-numbers");
|
||||||
|
addEndpointToGroup("Other", "auto-rename");
|
||||||
|
|
||||||
|
|
||||||
//CLI
|
|
||||||
addEndpointToGroup("CLI", "compress-pdf");
|
|
||||||
addEndpointToGroup("CLI", "extract-image-scans");
|
//CLI
|
||||||
addEndpointToGroup("CLI", "remove-blanks");
|
addEndpointToGroup("CLI", "compress-pdf");
|
||||||
addEndpointToGroup("CLI", "repair");
|
addEndpointToGroup("CLI", "extract-image-scans");
|
||||||
addEndpointToGroup("CLI", "pdf-to-pdfa");
|
addEndpointToGroup("CLI", "remove-blanks");
|
||||||
addEndpointToGroup("CLI", "file-to-pdf");
|
addEndpointToGroup("CLI", "repair");
|
||||||
addEndpointToGroup("CLI", "xlsx-to-pdf");
|
addEndpointToGroup("CLI", "pdf-to-pdfa");
|
||||||
addEndpointToGroup("CLI", "pdf-to-word");
|
addEndpointToGroup("CLI", "file-to-pdf");
|
||||||
addEndpointToGroup("CLI", "pdf-to-presentation");
|
addEndpointToGroup("CLI", "xlsx-to-pdf");
|
||||||
addEndpointToGroup("CLI", "pdf-to-text");
|
addEndpointToGroup("CLI", "pdf-to-word");
|
||||||
addEndpointToGroup("CLI", "pdf-to-html");
|
addEndpointToGroup("CLI", "pdf-to-presentation");
|
||||||
addEndpointToGroup("CLI", "pdf-to-xml");
|
addEndpointToGroup("CLI", "pdf-to-text");
|
||||||
addEndpointToGroup("CLI", "ocr-pdf");
|
addEndpointToGroup("CLI", "pdf-to-html");
|
||||||
|
addEndpointToGroup("CLI", "pdf-to-xml");
|
||||||
//python
|
addEndpointToGroup("CLI", "ocr-pdf");
|
||||||
addEndpointToGroup("Python", "extract-image-scans");
|
|
||||||
addEndpointToGroup("Python", "remove-blanks");
|
//python
|
||||||
|
addEndpointToGroup("Python", "extract-image-scans");
|
||||||
|
addEndpointToGroup("Python", "remove-blanks");
|
||||||
|
|
||||||
//openCV
|
|
||||||
addEndpointToGroup("OpenCV", "extract-image-scans");
|
|
||||||
addEndpointToGroup("OpenCV", "remove-blanks");
|
//openCV
|
||||||
|
addEndpointToGroup("OpenCV", "extract-image-scans");
|
||||||
//LibreOffice
|
addEndpointToGroup("OpenCV", "remove-blanks");
|
||||||
addEndpointToGroup("LibreOffice", "repair");
|
|
||||||
addEndpointToGroup("LibreOffice", "file-to-pdf");
|
//LibreOffice
|
||||||
addEndpointToGroup("LibreOffice", "xlsx-to-pdf");
|
addEndpointToGroup("LibreOffice", "repair");
|
||||||
addEndpointToGroup("LibreOffice", "pdf-to-word");
|
addEndpointToGroup("LibreOffice", "file-to-pdf");
|
||||||
addEndpointToGroup("LibreOffice", "pdf-to-presentation");
|
addEndpointToGroup("LibreOffice", "xlsx-to-pdf");
|
||||||
addEndpointToGroup("LibreOffice", "pdf-to-text");
|
addEndpointToGroup("LibreOffice", "pdf-to-word");
|
||||||
addEndpointToGroup("LibreOffice", "pdf-to-html");
|
addEndpointToGroup("LibreOffice", "pdf-to-presentation");
|
||||||
addEndpointToGroup("LibreOffice", "pdf-to-xml");
|
addEndpointToGroup("LibreOffice", "pdf-to-text");
|
||||||
|
addEndpointToGroup("LibreOffice", "pdf-to-html");
|
||||||
|
addEndpointToGroup("LibreOffice", "pdf-to-xml");
|
||||||
//OCRmyPDF
|
|
||||||
addEndpointToGroup("OCRmyPDF", "compress-pdf");
|
|
||||||
addEndpointToGroup("OCRmyPDF", "pdf-to-pdfa");
|
//OCRmyPDF
|
||||||
addEndpointToGroup("OCRmyPDF", "ocr-pdf");
|
addEndpointToGroup("OCRmyPDF", "compress-pdf");
|
||||||
|
addEndpointToGroup("OCRmyPDF", "pdf-to-pdfa");
|
||||||
//Java
|
addEndpointToGroup("OCRmyPDF", "ocr-pdf");
|
||||||
addEndpointToGroup("Java", "merge-pdfs");
|
|
||||||
addEndpointToGroup("Java", "remove-pages");
|
//Java
|
||||||
addEndpointToGroup("Java", "split-pdfs");
|
addEndpointToGroup("Java", "merge-pdfs");
|
||||||
addEndpointToGroup("Java", "pdf-organizer");
|
addEndpointToGroup("Java", "remove-pages");
|
||||||
addEndpointToGroup("Java", "rotate-pdf");
|
addEndpointToGroup("Java", "split-pdfs");
|
||||||
addEndpointToGroup("Java", "pdf-to-img");
|
addEndpointToGroup("Java", "pdf-organizer");
|
||||||
addEndpointToGroup("Java", "img-to-pdf");
|
addEndpointToGroup("Java", "rotate-pdf");
|
||||||
addEndpointToGroup("Java", "add-password");
|
addEndpointToGroup("Java", "pdf-to-img");
|
||||||
addEndpointToGroup("Java", "remove-password");
|
addEndpointToGroup("Java", "img-to-pdf");
|
||||||
addEndpointToGroup("Java", "change-permissions");
|
addEndpointToGroup("Java", "add-password");
|
||||||
addEndpointToGroup("Java", "add-watermark");
|
addEndpointToGroup("Java", "remove-password");
|
||||||
addEndpointToGroup("Java", "add-image");
|
addEndpointToGroup("Java", "change-permissions");
|
||||||
addEndpointToGroup("Java", "extract-images");
|
addEndpointToGroup("Java", "add-watermark");
|
||||||
addEndpointToGroup("Java", "change-metadata");
|
addEndpointToGroup("Java", "add-image");
|
||||||
addEndpointToGroup("Java", "cert-sign");
|
addEndpointToGroup("Java", "extract-images");
|
||||||
addEndpointToGroup("Java", "multi-page-layout");
|
addEndpointToGroup("Java", "change-metadata");
|
||||||
addEndpointToGroup("Java", "scale-pages");
|
addEndpointToGroup("Java", "cert-sign");
|
||||||
|
addEndpointToGroup("Java", "multi-page-layout");
|
||||||
|
addEndpointToGroup("Java", "scale-pages");
|
||||||
//Javascript
|
addEndpointToGroup("Java", "add-page-numbers");
|
||||||
addEndpointToGroup("Javascript", "pdf-organizer");
|
addEndpointToGroup("Java", "auto-rename");
|
||||||
addEndpointToGroup("Javascript", "sign");
|
addEndpointToGroup("Java", "auto-split-pdf");
|
||||||
addEndpointToGroup("Javascript", "compare");
|
addEndpointToGroup("Java", "sanitize-pdf");
|
||||||
|
addEndpointToGroup("Java", "crop");
|
||||||
}
|
|
||||||
|
//Javascript
|
||||||
private void processEnvironmentConfigs() {
|
addEndpointToGroup("Javascript", "pdf-organizer");
|
||||||
String endpointsToRemove = System.getenv("ENDPOINTS_TO_REMOVE");
|
addEndpointToGroup("Javascript", "sign");
|
||||||
String groupsToRemove = System.getenv("GROUPS_TO_REMOVE");
|
addEndpointToGroup("Javascript", "compare");
|
||||||
|
addEndpointToGroup("Javascript", "adjust-contrast");
|
||||||
if (endpointsToRemove != null) {
|
|
||||||
String[] endpoints = endpointsToRemove.split(",");
|
|
||||||
for (String endpoint : endpoints) {
|
}
|
||||||
disableEndpoint(endpoint.trim());
|
|
||||||
}
|
private void processEnvironmentConfigs() {
|
||||||
}
|
String endpointsToRemove = System.getenv("ENDPOINTS_TO_REMOVE");
|
||||||
|
String groupsToRemove = System.getenv("GROUPS_TO_REMOVE");
|
||||||
if (groupsToRemove != null) {
|
|
||||||
String[] groups = groupsToRemove.split(",");
|
if (endpointsToRemove != null) {
|
||||||
for (String group : groups) {
|
String[] endpoints = endpointsToRemove.split(",");
|
||||||
disableGroup(group.trim());
|
for (String endpoint : endpoints) {
|
||||||
}
|
disableEndpoint(endpoint.trim());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
if (groupsToRemove != null) {
|
||||||
|
String[] groups = groupsToRemove.split(",");
|
||||||
|
for (String group : groups) {
|
||||||
|
disableGroup(group.trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -1,176 +1,176 @@
|
|||||||
package stirling.software.SPDF.controller.api.other;
|
package stirling.software.SPDF.controller.api.other;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.RequestPart;
|
import org.springframework.web.bind.annotation.RequestPart;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import stirling.software.SPDF.utils.GeneralUtils;
|
import stirling.software.SPDF.utils.GeneralUtils;
|
||||||
import stirling.software.SPDF.utils.PdfUtils;
|
import stirling.software.SPDF.utils.PdfUtils;
|
||||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||||
import org.apache.pdfbox.pdmodel.*;
|
import org.apache.pdfbox.pdmodel.*;
|
||||||
import org.apache.pdfbox.pdmodel.common.*;
|
import org.apache.pdfbox.pdmodel.common.*;
|
||||||
import org.apache.pdfbox.pdmodel.PDPageContentStream.*;
|
import org.apache.pdfbox.pdmodel.PDPageContentStream.*;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.http.*;
|
import org.springframework.http.*;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
import io.swagger.v3.oas.annotations.*;
|
import io.swagger.v3.oas.annotations.*;
|
||||||
import io.swagger.v3.oas.annotations.media.*;
|
import io.swagger.v3.oas.annotations.media.*;
|
||||||
import io.swagger.v3.oas.annotations.parameters.*;
|
import io.swagger.v3.oas.annotations.parameters.*;
|
||||||
import org.apache.pdfbox.pdmodel.font.PDType1Font;
|
import org.apache.pdfbox.pdmodel.font.PDType1Font;
|
||||||
import org.apache.tomcat.util.http.ResponseUtil;
|
import org.apache.tomcat.util.http.ResponseUtil;
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import com.itextpdf.io.font.constants.StandardFonts;
|
import com.itextpdf.io.font.constants.StandardFonts;
|
||||||
import com.itextpdf.kernel.font.PdfFont;
|
import com.itextpdf.kernel.font.PdfFont;
|
||||||
import com.itextpdf.kernel.font.PdfFontFactory;
|
import com.itextpdf.kernel.font.PdfFontFactory;
|
||||||
import com.itextpdf.kernel.geom.Rectangle;
|
import com.itextpdf.kernel.geom.Rectangle;
|
||||||
import com.itextpdf.kernel.pdf.PdfReader;
|
import com.itextpdf.kernel.pdf.PdfReader;
|
||||||
import com.itextpdf.kernel.pdf.PdfWriter;
|
import com.itextpdf.kernel.pdf.PdfWriter;
|
||||||
import com.itextpdf.kernel.pdf.PdfDocument;
|
import com.itextpdf.kernel.pdf.PdfDocument;
|
||||||
import com.itextpdf.kernel.pdf.PdfPage;
|
import com.itextpdf.kernel.pdf.PdfPage;
|
||||||
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
|
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
|
||||||
import com.itextpdf.layout.Canvas;
|
import com.itextpdf.layout.Canvas;
|
||||||
import com.itextpdf.layout.element.Paragraph;
|
import com.itextpdf.layout.element.Paragraph;
|
||||||
import com.itextpdf.layout.properties.TextAlignment;
|
import com.itextpdf.layout.properties.TextAlignment;
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@Tag(name = "Other", description = "Other APIs")
|
@Tag(name = "Other", description = "Other APIs")
|
||||||
public class PageNumbersController {
|
public class PageNumbersController {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(PageNumbersController.class);
|
private static final Logger logger = LoggerFactory.getLogger(PageNumbersController.class);
|
||||||
|
|
||||||
@PostMapping(value = "/add-page-numbers", consumes = "multipart/form-data")
|
@PostMapping(value = "/add-page-numbers", consumes = "multipart/form-data")
|
||||||
@Operation(summary = "Add page numbers to a PDF document", description = "This operation takes an input PDF file and adds page numbers to it. Input:PDF Output:PDF Type:SISO")
|
@Operation(summary = "Add page numbers to a PDF document", description = "This operation takes an input PDF file and adds page numbers to it. Input:PDF Output:PDF Type:SISO")
|
||||||
public ResponseEntity<byte[]> addPageNumbers(
|
public ResponseEntity<byte[]> addPageNumbers(
|
||||||
@Parameter(description = "The input PDF file", required = true) @RequestParam("fileInput") MultipartFile file,
|
@Parameter(description = "The input PDF file", required = true) @RequestParam("fileInput") MultipartFile file,
|
||||||
@Parameter(description = "Custom margin: small/medium/large", required = true, schema = @Schema(type = "string", allowableValues = {"small", "medium", "large"})) @RequestParam("customMargin") String customMargin,
|
@Parameter(description = "Custom margin: small/medium/large", required = true, schema = @Schema(type = "string", allowableValues = {"small", "medium", "large"})) @RequestParam("customMargin") String customMargin,
|
||||||
@Parameter(description = "Position: 1 of 9 positions", required = true, schema = @Schema(type = "integer", minimum = "1", maximum = "9")) @RequestParam("position") int position,
|
@Parameter(description = "Position: 1 of 9 positions", required = true, schema = @Schema(type = "integer", minimum = "1", maximum = "9")) @RequestParam("position") int position,
|
||||||
@Parameter(description = "Starting number", required = true, schema = @Schema(type = "integer", minimum = "1")) @RequestParam("startingNumber") int startingNumber,
|
@Parameter(description = "Starting number", required = true, schema = @Schema(type = "integer", minimum = "1")) @RequestParam("startingNumber") int startingNumber,
|
||||||
@Parameter(description = "Which pages to number, default all", required = false, schema = @Schema(type = "string")) @RequestParam(value = "pagesToNumber", required = false) String pagesToNumber,
|
@Parameter(description = "Which pages to number, default all", required = false, schema = @Schema(type = "string")) @RequestParam(value = "pagesToNumber", required = false) String pagesToNumber,
|
||||||
@Parameter(description = "Custom text: defaults to just number but can have things like \"Page {n} of {p}\"", required = false, schema = @Schema(type = "string")) @RequestParam(value = "customText", required = false) String customText)
|
@Parameter(description = "Custom text: defaults to just number but can have things like \"Page {n} of {p}\"", required = false, schema = @Schema(type = "string")) @RequestParam(value = "customText", required = false) String customText)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
|
||||||
byte[] fileBytes = file.getBytes();
|
byte[] fileBytes = file.getBytes();
|
||||||
ByteArrayInputStream bais = new ByteArrayInputStream(fileBytes);
|
ByteArrayInputStream bais = new ByteArrayInputStream(fileBytes);
|
||||||
|
|
||||||
int pageNumber = startingNumber;
|
int pageNumber = startingNumber;
|
||||||
float marginFactor;
|
float marginFactor;
|
||||||
switch (customMargin.toLowerCase()) {
|
switch (customMargin.toLowerCase()) {
|
||||||
case "small":
|
case "small":
|
||||||
marginFactor = 0.01f;
|
marginFactor = 0.02f;
|
||||||
break;
|
break;
|
||||||
case "medium":
|
case "medium":
|
||||||
marginFactor = 0.025f;
|
marginFactor = 0.035f;
|
||||||
break;
|
break;
|
||||||
case "large":
|
case "large":
|
||||||
marginFactor = 0.05f;
|
marginFactor = 0.05f;
|
||||||
break;
|
break;
|
||||||
case "x-large":
|
case "x-large":
|
||||||
marginFactor = 0.1f;
|
marginFactor = 0.1f;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
marginFactor = 0.01f;
|
marginFactor = 0.035f;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
float fontSize = 12.0f;
|
float fontSize = 12.0f;
|
||||||
|
|
||||||
PdfReader reader = new PdfReader(bais);
|
PdfReader reader = new PdfReader(bais);
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
PdfWriter writer = new PdfWriter(baos);
|
PdfWriter writer = new PdfWriter(baos);
|
||||||
|
|
||||||
PdfDocument pdfDoc = new PdfDocument(reader, writer);
|
PdfDocument pdfDoc = new PdfDocument(reader, writer);
|
||||||
|
|
||||||
List<Integer> pagesToNumberList = GeneralUtils.parsePageList(pagesToNumber.split(","), pdfDoc.getNumberOfPages());
|
List<Integer> pagesToNumberList = GeneralUtils.parsePageList(pagesToNumber.split(","), pdfDoc.getNumberOfPages());
|
||||||
|
|
||||||
for (int i : pagesToNumberList) {
|
for (int i : pagesToNumberList) {
|
||||||
PdfPage page = pdfDoc.getPage(i+1);
|
PdfPage page = pdfDoc.getPage(i+1);
|
||||||
Rectangle pageSize = page.getPageSize();
|
Rectangle pageSize = page.getPageSize();
|
||||||
PdfCanvas pdfCanvas = new PdfCanvas(page.newContentStreamAfter(), page.getResources(), pdfDoc);
|
PdfCanvas pdfCanvas = new PdfCanvas(page.newContentStreamAfter(), page.getResources(), pdfDoc);
|
||||||
|
|
||||||
String text = customText != null ? customText.replace("{n}", String.valueOf(pageNumber)).replace("{total}", String.valueOf(pdfDoc.getNumberOfPages())) : String.valueOf(pageNumber);
|
String text = customText != null ? customText.replace("{n}", String.valueOf(pageNumber)).replace("{total}", String.valueOf(pdfDoc.getNumberOfPages())) : String.valueOf(pageNumber);
|
||||||
|
|
||||||
PdfFont font = PdfFontFactory.createFont(StandardFonts.HELVETICA);
|
PdfFont font = PdfFontFactory.createFont(StandardFonts.HELVETICA);
|
||||||
float textWidth = font.getWidth(text, fontSize);
|
float textWidth = font.getWidth(text, fontSize);
|
||||||
float textHeight = font.getAscent(text, fontSize) - font.getDescent(text, fontSize);
|
float textHeight = font.getAscent(text, fontSize) - font.getDescent(text, fontSize);
|
||||||
|
|
||||||
float x, y;
|
float x, y;
|
||||||
TextAlignment alignment;
|
TextAlignment alignment;
|
||||||
|
|
||||||
int xGroup = (position - 1) % 3;
|
int xGroup = (position - 1) % 3;
|
||||||
int yGroup = 2 - (position - 1) / 3;
|
int yGroup = 2 - (position - 1) / 3;
|
||||||
|
|
||||||
switch (xGroup) {
|
switch (xGroup) {
|
||||||
case 0: // left
|
case 0: // left
|
||||||
x = pageSize.getLeft() + marginFactor * pageSize.getWidth();
|
x = pageSize.getLeft() + marginFactor * pageSize.getWidth();
|
||||||
alignment = TextAlignment.LEFT;
|
alignment = TextAlignment.LEFT;
|
||||||
break;
|
break;
|
||||||
case 1: // center
|
case 1: // center
|
||||||
x = pageSize.getLeft() + (pageSize.getWidth()) / 2;
|
x = pageSize.getLeft() + (pageSize.getWidth()) / 2;
|
||||||
alignment = TextAlignment.CENTER;
|
alignment = TextAlignment.CENTER;
|
||||||
break;
|
break;
|
||||||
default: // right
|
default: // right
|
||||||
x = pageSize.getRight() - marginFactor * pageSize.getWidth();
|
x = pageSize.getRight() - marginFactor * pageSize.getWidth();
|
||||||
alignment = TextAlignment.RIGHT;
|
alignment = TextAlignment.RIGHT;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (yGroup) {
|
switch (yGroup) {
|
||||||
case 0: // bottom
|
case 0: // bottom
|
||||||
y = pageSize.getBottom() + marginFactor * pageSize.getHeight();
|
y = pageSize.getBottom() + marginFactor * pageSize.getHeight();
|
||||||
break;
|
break;
|
||||||
case 1: // middle
|
case 1: // middle
|
||||||
y = pageSize.getBottom() + (pageSize.getHeight() ) / 2;
|
y = pageSize.getBottom() + (pageSize.getHeight() ) / 2;
|
||||||
break;
|
break;
|
||||||
default: // top
|
default: // top
|
||||||
y = pageSize.getTop() - marginFactor * pageSize.getHeight();
|
y = pageSize.getTop() - marginFactor * pageSize.getHeight();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
new Canvas(pdfCanvas, page.getPageSize())
|
new Canvas(pdfCanvas, page.getPageSize())
|
||||||
.showTextAligned(new Paragraph(text).setFont(font).setFontSize(fontSize), x, y, alignment);
|
.showTextAligned(new Paragraph(text).setFont(font).setFontSize(fontSize), x, y, alignment);
|
||||||
|
|
||||||
pageNumber++;
|
pageNumber++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pdfDoc.close();
|
pdfDoc.close();
|
||||||
byte[] resultBytes = baos.toByteArray();
|
byte[] resultBytes = baos.toByteArray();
|
||||||
|
|
||||||
return ResponseEntity.ok()
|
return ResponseEntity.ok()
|
||||||
.header("Content-Type", "application/pdf; charset=UTF-8")
|
.header("Content-Type", "application/pdf; charset=UTF-8")
|
||||||
.header("Content-Disposition", "inline; filename=" + URLEncoder.encode(file.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_numbersAdded.pdf", "UTF-8"))
|
.header("Content-Disposition", "inline; filename=" + URLEncoder.encode(file.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_numbersAdded.pdf", "UTF-8"))
|
||||||
.body(resultBytes);
|
.body(resultBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,140 @@
|
|||||||
|
package stirling.software.SPDF.controller.api.security;
|
||||||
|
import org.apache.pdfbox.cos.COSName;
|
||||||
|
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||||
|
import org.apache.pdfbox.pdmodel.PDPage;
|
||||||
|
import org.apache.pdfbox.pdmodel.PDResources;
|
||||||
|
import org.apache.pdfbox.pdmodel.PDPageTree;
|
||||||
|
import org.apache.pdfbox.pdmodel.common.PDMetadata;
|
||||||
|
import org.apache.pdfbox.pdmodel.common.PDStream;
|
||||||
|
import org.apache.pdfbox.pdmodel.interactive.action.*;
|
||||||
|
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation;
|
||||||
|
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationLink;
|
||||||
|
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationWidget;
|
||||||
|
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
|
||||||
|
import org.apache.pdfbox.pdmodel.interactive.form.PDField;
|
||||||
|
import org.apache.pdfbox.pdmodel.interactive.form.PDNonTerminalField;
|
||||||
|
import org.apache.pdfbox.pdmodel.interactive.form.PDTerminalField;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
public class SanitizeController {
|
||||||
|
|
||||||
|
@PostMapping(consumes = "multipart/form-data", value = "/sanitize-pdf")
|
||||||
|
@Operation(summary = "Sanitize a PDF file",
|
||||||
|
description = "This endpoint processes a PDF file and removes specific elements based on the provided options. Input:PDF Output:PDF Type:SISO")
|
||||||
|
public ResponseEntity<byte[]> sanitizePDF(
|
||||||
|
@RequestPart(required = true, value = "fileInput")
|
||||||
|
@Parameter(description = "The input PDF file to be sanitized")
|
||||||
|
MultipartFile inputFile,
|
||||||
|
@RequestParam(name = "removeJavaScript", required = false, defaultValue = "true")
|
||||||
|
@Parameter(description = "Remove JavaScript actions from the PDF if set to true")
|
||||||
|
Boolean removeJavaScript,
|
||||||
|
@RequestParam(name = "removeEmbeddedFiles", required = false, defaultValue = "true")
|
||||||
|
@Parameter(description = "Remove embedded files from the PDF if set to true")
|
||||||
|
Boolean removeEmbeddedFiles,
|
||||||
|
@RequestParam(name = "removeMetadata", required = false, defaultValue = "true")
|
||||||
|
@Parameter(description = "Remove metadata from the PDF if set to true")
|
||||||
|
Boolean removeMetadata,
|
||||||
|
@RequestParam(name = "removeLinks", required = false, defaultValue = "true")
|
||||||
|
@Parameter(description = "Remove links from the PDF if set to true")
|
||||||
|
Boolean removeLinks,
|
||||||
|
@RequestParam(name = "removeFonts", required = false, defaultValue = "true")
|
||||||
|
@Parameter(description = "Remove fonts from the PDF if set to true")
|
||||||
|
Boolean removeFonts) throws IOException {
|
||||||
|
|
||||||
|
try (PDDocument document = PDDocument.load(inputFile.getInputStream())) {
|
||||||
|
if (removeJavaScript) {
|
||||||
|
sanitizeJavaScript(document);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (removeEmbeddedFiles) {
|
||||||
|
sanitizeEmbeddedFiles(document);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (removeMetadata) {
|
||||||
|
sanitizeMetadata(document);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (removeLinks) {
|
||||||
|
sanitizeLinks(document);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (removeFonts) {
|
||||||
|
sanitizeFonts(document);
|
||||||
|
}
|
||||||
|
|
||||||
|
return WebResponseUtils.pdfDocToWebResponse(document, inputFile.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_sanitized.pdf");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void sanitizeJavaScript(PDDocument document) throws IOException {
|
||||||
|
for (PDPage page : document.getPages()) {
|
||||||
|
for (PDAnnotation annotation : page.getAnnotations()) {
|
||||||
|
if (annotation instanceof PDAnnotationWidget) {
|
||||||
|
PDAnnotationWidget widget = (PDAnnotationWidget) annotation;
|
||||||
|
PDAction action = widget.getAction();
|
||||||
|
if (action instanceof PDActionJavaScript) {
|
||||||
|
widget.setAction(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PDAcroForm acroForm = document.getDocumentCatalog().getAcroForm();
|
||||||
|
if (acroForm != null) {
|
||||||
|
for (PDField field : acroForm.getFields()) {
|
||||||
|
if (field.getActions().getF() instanceof PDActionJavaScript) {
|
||||||
|
field.getActions().setF(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sanitizeEmbeddedFiles(PDDocument document) {
|
||||||
|
PDPageTree allPages = document.getPages();
|
||||||
|
|
||||||
|
for (PDPage page : allPages) {
|
||||||
|
PDResources res = page.getResources();
|
||||||
|
|
||||||
|
// Remove embedded files from the PDF
|
||||||
|
res.getCOSObject().removeItem(COSName.getPDFName("EmbeddedFiles"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void sanitizeMetadata(PDDocument document) {
|
||||||
|
PDMetadata metadata = document.getDocumentCatalog().getMetadata();
|
||||||
|
if (metadata != null) {
|
||||||
|
document.getDocumentCatalog().setMetadata(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private void sanitizeLinks(PDDocument document) throws IOException {
|
||||||
|
for (PDPage page : document.getPages()) {
|
||||||
|
for (PDAnnotation annotation : page.getAnnotations()) {
|
||||||
|
if (annotation instanceof PDAnnotationLink) {
|
||||||
|
PDAction action = ((PDAnnotationLink) annotation).getAction();
|
||||||
|
if (action instanceof PDActionLaunch || action instanceof PDActionURI) {
|
||||||
|
((PDAnnotationLink) annotation).setAction(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sanitizeFonts(PDDocument document) {
|
||||||
|
for (PDPage page : document.getPages()) {
|
||||||
|
page.getResources().getCOSObject().removeItem(COSName.getPDFName("Font"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,46 +1,53 @@
|
|||||||
package stirling.software.SPDF.controller.web;
|
package stirling.software.SPDF.controller.web;
|
||||||
|
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.ui.Model;
|
import org.springframework.ui.Model;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.Hidden;
|
import io.swagger.v3.oas.annotations.Hidden;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
|
||||||
@Controller
|
@Controller
|
||||||
@Tag(name = "Security", description = "Security APIs")
|
@Tag(name = "Security", description = "Security APIs")
|
||||||
public class SecurityWebController {
|
public class SecurityWebController {
|
||||||
@GetMapping("/add-password")
|
@GetMapping("/add-password")
|
||||||
@Hidden
|
@Hidden
|
||||||
public String addPasswordForm(Model model) {
|
public String addPasswordForm(Model model) {
|
||||||
model.addAttribute("currentPage", "add-password");
|
model.addAttribute("currentPage", "add-password");
|
||||||
return "security/add-password";
|
return "security/add-password";
|
||||||
}
|
}
|
||||||
@GetMapping("/change-permissions")
|
@GetMapping("/change-permissions")
|
||||||
@Hidden
|
@Hidden
|
||||||
public String permissionsForm(Model model) {
|
public String permissionsForm(Model model) {
|
||||||
model.addAttribute("currentPage", "change-permissions");
|
model.addAttribute("currentPage", "change-permissions");
|
||||||
return "security/change-permissions";
|
return "security/change-permissions";
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/remove-password")
|
@GetMapping("/remove-password")
|
||||||
@Hidden
|
@Hidden
|
||||||
public String removePasswordForm(Model model) {
|
public String removePasswordForm(Model model) {
|
||||||
model.addAttribute("currentPage", "remove-password");
|
model.addAttribute("currentPage", "remove-password");
|
||||||
return "security/remove-password";
|
return "security/remove-password";
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/add-watermark")
|
@GetMapping("/add-watermark")
|
||||||
@Hidden
|
@Hidden
|
||||||
public String addWatermarkForm(Model model) {
|
public String addWatermarkForm(Model model) {
|
||||||
model.addAttribute("currentPage", "add-watermark");
|
model.addAttribute("currentPage", "add-watermark");
|
||||||
return "security/add-watermark";
|
return "security/add-watermark";
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/cert-sign")
|
@GetMapping("/cert-sign")
|
||||||
@Hidden
|
@Hidden
|
||||||
public String certSignForm(Model model) {
|
public String certSignForm(Model model) {
|
||||||
model.addAttribute("currentPage", "cert-sign");
|
model.addAttribute("currentPage", "cert-sign");
|
||||||
return "security/cert-sign";
|
return "security/cert-sign";
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@GetMapping("/sanitize-pdf")
|
||||||
|
@Hidden
|
||||||
|
public String sanitizeForm(Model model) {
|
||||||
|
model.addAttribute("currentPage", "");
|
||||||
|
return "security/sanitize-pdf";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -152,6 +152,10 @@ home.crop.desc=Crop a PDF to reduce its size (maintains text!)
|
|||||||
home.autoSplitPDF.title=Auto Split Pages
|
home.autoSplitPDF.title=Auto Split Pages
|
||||||
home.autoSplitPDF.desc=Auto Split Scanned PDF with physical scanned page splitter QR Code
|
home.autoSplitPDF.desc=Auto Split Scanned PDF with physical scanned page splitter QR Code
|
||||||
|
|
||||||
|
home.sanitizePdf.title=Sanitize
|
||||||
|
home.sanitizePdf.desc=Remove scripts and other elements from PDF files
|
||||||
|
|
||||||
|
|
||||||
error.pdfPassword=The PDF Document is passworded and either the password was not provided or was incorrect
|
error.pdfPassword=The PDF Document is passworded and either the password was not provided or was incorrect
|
||||||
|
|
||||||
downloadPdf=Download PDF
|
downloadPdf=Download PDF
|
||||||
@ -159,6 +163,49 @@ text=Text
|
|||||||
font=Font
|
font=Font
|
||||||
selectFillter=-- Select --
|
selectFillter=-- Select --
|
||||||
pageNum=Page Number
|
pageNum=Page Number
|
||||||
|
sizes.small=Small
|
||||||
|
sizes.medium=Medium
|
||||||
|
sizes.large=Large
|
||||||
|
sizes.x-large=X-Large
|
||||||
|
|
||||||
|
sanitizePDF.title=Sanitize PDF
|
||||||
|
sanitizePDF.header=Sanitize a PDF file
|
||||||
|
sanitizePDF.selectText.1=Remove JavaScript actions
|
||||||
|
sanitizePDF.selectText.2=Remove embedded files
|
||||||
|
sanitizePDF.selectText.3=Remove metadata
|
||||||
|
sanitizePDF.selectText.4=Remove links
|
||||||
|
sanitizePDF.selectText.5=Remove fonts
|
||||||
|
sanitizePDF.submit=Sanitize PDF
|
||||||
|
|
||||||
|
addPageNumbers.title=Add Page Numbers
|
||||||
|
addPageNumbers.header=Add Page Numbers
|
||||||
|
addPageNumbers.selectText.1=Select PDF file:
|
||||||
|
addPageNumbers.selectText.2=Margin Size
|
||||||
|
addPageNumbers.selectText.3=Position
|
||||||
|
addPageNumbers.selectText.4=Starting Number
|
||||||
|
addPageNumbers.selectText.5=Pages to Number
|
||||||
|
addPageNumbers.selectText.6=Custom Text
|
||||||
|
addPageNumbers.submit=Add Page Numbers
|
||||||
|
|
||||||
|
auto-rename.title=Auto Rename
|
||||||
|
auto-rename.header=Auto Rename PDF
|
||||||
|
auto-rename.submit=Auto Rename
|
||||||
|
|
||||||
|
adjustContrast.title=Adjust Contrast
|
||||||
|
adjustContrast.header=Adjust Contrast
|
||||||
|
adjustContrast.contrast=Contrast:
|
||||||
|
adjustContrast.brightness=Brightness:
|
||||||
|
adjustContrast.saturation=Saturation:
|
||||||
|
adjustContrast.download=Download
|
||||||
|
|
||||||
|
crop.title=Crop
|
||||||
|
crop.header=Crop Image
|
||||||
|
crop.submit=Submit
|
||||||
|
|
||||||
|
autoSplitPDF.title=Auto Split PDF
|
||||||
|
autoSplitPDF.header=Auto Split PDF
|
||||||
|
autoSplitPDF.submit=Submit
|
||||||
|
|
||||||
|
|
||||||
pipeline.title=Pipeline
|
pipeline.title=Pipeline
|
||||||
|
|
||||||
|
1
src/main/resources/static/images/sanitize.svg
Normal file
1
src/main/resources/static/images/sanitize.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg height="48" viewBox="0 0 48 48" width="48" xmlns="http://www.w3.org/2000/svg"><path d="m0 0h48v48h-48z" fill="none"/><path d="m8.091 21c0 1.089-.576 1.695-1.304 2.464-.755.797-1.696 1.788-1.696 3.394v11.142c0 2.757 2.243 5 5 5h12c2.757 0 5-2.243 5-5v-11.143c0-2.316-2.045-3.302-4.022-4.254-2.447-1.179-4.978-2.397-4.978-6.104v-.215l-.088-.195c-.081-.179-.287-.608-.6-1.09h1.969l2.032-1.242 5.949 5.949 1.414-1.414-5.608-5.608 1.841-1.123v-6.561h-14.186l-5.713 3.428-.12 6.572h3.46c-.219.456-.351.961-.351 1.5v4.5zm-1.01-11.428 4.287-2.572h11.632v3.439l-4.19 2.561h-4.219-3-4.572zm3.01 11.428v-4.5c0-.827.673-1.5 1.5-1.5h3c.341 0 1.054.832 1.502 1.731.108 4.784 3.569 6.451 6.107 7.674 1.846.89 2.89 1.441 2.89 2.452v11.143c0 1.654-1.346 3-3 3h-12c-1.654 0-3-1.346-3-3v-11.143c0-.771.415-1.244 1.147-2.017.826-.87 1.854-1.953 1.854-3.84z"/><path d="m15.091 38h2v-5h5v-2h-5v-5h-2v5h-5v2h5z"/><circle cx="30.091" cy="8" r="2"/><circle cx="36.091" cy="8" r="2"/><circle cx="42.091" cy="8" r="2"/><circle cx="33.091" cy="13" r="2"/><circle cx="37.091" cy="17" r="2"/></svg>
|
After Width: | Height: | Size: 1.0 KiB |
@ -1,105 +1,103 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html th:lang="${#locale.toString()}" th:lang-direction="#{language.direction}" xmlns:th="http://www.thymeleaf.org">
|
<html th:lang="${#locale.toString()}" th:lang-direction="#{language.direction}" xmlns:th="http://www.thymeleaf.org">
|
||||||
|
|
||||||
<th:block th:insert="~{fragments/common :: head(title=#{crop.title})}"></th:block>
|
<th:block th:insert="~{fragments/common :: head(title=#{crop.title})}"></th:block>
|
||||||
|
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="page-container">
|
<div id="page-container">
|
||||||
<div id="content-wrap">
|
<div id="content-wrap">
|
||||||
<div th:insert="~{fragments/navbar.html :: navbar}"></div>
|
<div th:insert="~{fragments/navbar.html :: navbar}"></div>
|
||||||
<br> <br>
|
<br> <br>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row justify-content-center">
|
<div class="row justify-content-center">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<h2 th:text="#{crop.header}"></h2>
|
<h2 th:text="#{crop.header}"></h2>
|
||||||
<form id="cropForm" action="/crop" method="post" enctype="multipart/form-data">
|
<form id="cropForm" action="/crop" method="post" enctype="multipart/form-data">
|
||||||
<input id="fileInput" type="file" name="file" required>
|
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"></div>
|
||||||
<input id="x" type="hidden" name="x">
|
<input id="x" type="hidden" name="x">
|
||||||
<input id="y" type="hidden" name="y">
|
<input id="y" type="hidden" name="y">
|
||||||
<input id="width" type="hidden" name="width">
|
<input id="width" type="hidden" name="width">
|
||||||
<input id="height" type="hidden" name="height">
|
<input id="height" type="hidden" name="height">
|
||||||
<button type="submit">Submit</button>
|
<button type="submit" class="btn btn-primary" th:text="#{crop.submit}"></button>
|
||||||
</form>
|
</form>
|
||||||
<canvas id="pdf-canvas"></canvas>
|
<canvas id="pdf-canvas"></canvas>
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
let canvas = document.getElementById('pdf-canvas');
|
let canvas = document.getElementById('pdf-canvas');
|
||||||
let context = canvas.getContext('2d');
|
let context = canvas.getContext('2d');
|
||||||
|
|
||||||
let cropForm = document.getElementById('cropForm');
|
let cropForm = document.getElementById('cropForm');
|
||||||
let fileInput = document.getElementById('fileInput');
|
let fileInput = document.getElementById('fileInput-input');
|
||||||
let xInput = document.getElementById('x');
|
let xInput = document.getElementById('x');
|
||||||
let yInput = document.getElementById('y');
|
let yInput = document.getElementById('y');
|
||||||
let widthInput = document.getElementById('width');
|
let widthInput = document.getElementById('width');
|
||||||
let heightInput = document.getElementById('height');
|
let heightInput = document.getElementById('height');
|
||||||
|
|
||||||
let pdfDoc = null;
|
let pdfDoc = null;
|
||||||
let currentPage = 1;
|
let currentPage = 1;
|
||||||
let totalPages = 0;
|
let totalPages = 0;
|
||||||
|
|
||||||
let startX = 0;
|
let startX = 0;
|
||||||
let startY = 0;
|
let startY = 0;
|
||||||
let rectWidth = 0;
|
let rectWidth = 0;
|
||||||
let rectHeight = 0;
|
let rectHeight = 0;
|
||||||
|
|
||||||
fileInput.addEventListener('change', function(e) {
|
fileInput.addEventListener('change', function(e) {
|
||||||
let file = e.target.files[0];
|
let file = e.target.files[0];
|
||||||
if (file.type === 'application/pdf') {
|
if (file.type === 'application/pdf') {
|
||||||
let reader = new FileReader();
|
let reader = new FileReader();
|
||||||
reader.onload = function(ev) {
|
reader.onload = function(ev) {
|
||||||
let typedArray = new Uint8Array(reader.result);
|
let typedArray = new Uint8Array(reader.result);
|
||||||
pdfjsLib.getDocument(typedArray).promise.then(function(pdf) {
|
pdfjsLib.getDocument(typedArray).promise.then(function(pdf) {
|
||||||
pdfDoc = pdf;
|
pdfDoc = pdf;
|
||||||
totalPages = pdf.numPages;
|
totalPages = pdf.numPages;
|
||||||
renderPage(currentPage);
|
renderPage(currentPage);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
reader.readAsArrayBuffer(file);
|
reader.readAsArrayBuffer(file);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
canvas.addEventListener('mousedown', function(e) {
|
canvas.addEventListener('mousedown', function(e) {
|
||||||
startX = e.offsetX;
|
startX = e.offsetX;
|
||||||
startY = e.offsetY;
|
startY = e.offsetY;
|
||||||
});
|
});
|
||||||
|
|
||||||
canvas.addEventListener('mouseup', function(e) {
|
canvas.addEventListener('mouseup', function(e) {
|
||||||
rectWidth = e.offsetX - startX;
|
rectWidth = e.offsetX - startX;
|
||||||
rectHeight = e.offsetY - startY;
|
rectHeight = e.offsetY - startY;
|
||||||
|
|
||||||
// Flip the y-coordinate
|
// Flip the y-coordinate
|
||||||
let flippedY = canvas.height - e.offsetY;
|
let flippedY = canvas.height - e.offsetY;
|
||||||
|
|
||||||
xInput.value = startX;
|
xInput.value = startX;
|
||||||
yInput.value = flippedY;
|
yInput.value = flippedY;
|
||||||
widthInput.value = rectWidth;
|
widthInput.value = rectWidth;
|
||||||
heightInput.value = rectHeight;
|
heightInput.value = rectHeight;
|
||||||
|
|
||||||
context.strokeStyle = 'red';
|
context.strokeStyle = 'red';
|
||||||
context.strokeRect(startX, startY, rectWidth, rectHeight);
|
context.strokeRect(startX, startY, rectWidth, rectHeight);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
function renderPage(pageNumber) {
|
function renderPage(pageNumber) {
|
||||||
pdfDoc.getPage(pageNumber).then(function(page) {
|
pdfDoc.getPage(pageNumber).then(function(page) {
|
||||||
let viewport = page.getViewport({ scale: 1.0 });
|
let viewport = page.getViewport({ scale: 1.0 });
|
||||||
canvas.width = viewport.width;
|
canvas.width = viewport.width;
|
||||||
canvas.height = viewport.height;
|
canvas.height = viewport.height;
|
||||||
let renderContext = { canvasContext: context, viewport: viewport };
|
let renderContext = { canvasContext: context, viewport: viewport };
|
||||||
page.render(renderContext);
|
page.render(renderContext);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
</script>
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div th:insert="~{fragments/footer.html :: footer}"></div>
|
||||||
</div>
|
</div>
|
||||||
<div th:insert="~{fragments/footer.html :: footer}"></div>
|
</body>
|
||||||
</div>
|
</html>
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
@ -40,7 +40,7 @@
|
|||||||
</li>-->
|
</li>-->
|
||||||
|
|
||||||
<li class="nav-item nav-item-separator"></li>
|
<li class="nav-item nav-item-separator"></li>
|
||||||
<li class="nav-item dropdown" th:classappend="${currentPage}=='remove-pages' OR ${currentPage}=='merge-pdfs' OR ${currentPage}=='split-pdfs' OR ${currentPage}=='pdf-organizer' OR ${currentPage}=='rotate-pdf' OR ${currentPage}=='multi-page-layout' OR ${currentPage}=='scale-pages' ? 'active' : ''">
|
<li class="nav-item dropdown" th:classappend="${currentPage}=='remove-pages' OR ${currentPage}=='merge-pdfs' OR ${currentPage}=='split-pdfs' OR ${currentPage}=='crop' OR ${currentPage}=='adjust-contrast' OR ${currentPage}=='pdf-organizer' OR ${currentPage}=='rotate-pdf' OR ${currentPage}=='multi-page-layout' OR ${currentPage}=='scale-pages' ? 'active' : ''">
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||||
<img class="icon" src="images/file-earmark-pdf.svg" alt="icon">
|
<img class="icon" src="images/file-earmark-pdf.svg" alt="icon">
|
||||||
<span class="icon-text" th:text="#{navbar.pageOps}"></span>
|
<span class="icon-text" th:text="#{navbar.pageOps}"></span>
|
||||||
@ -55,6 +55,8 @@
|
|||||||
<div th:replace="~{fragments/navbarEntry :: navbarEntry ( 'multi-page-layout', 'images/page-layout.svg', 'home.pageLayout.title', 'home.pageLayout.desc')}"></div>
|
<div th:replace="~{fragments/navbarEntry :: navbarEntry ( 'multi-page-layout', 'images/page-layout.svg', 'home.pageLayout.title', 'home.pageLayout.desc')}"></div>
|
||||||
<div th:replace="~{fragments/navbarEntry :: navbarEntry ( 'scale-pages', 'images/scale-pages.svg', 'home.scalePages.title', 'home.scalePages.desc')}"></div>
|
<div th:replace="~{fragments/navbarEntry :: navbarEntry ( 'scale-pages', 'images/scale-pages.svg', 'home.scalePages.title', 'home.scalePages.desc')}"></div>
|
||||||
<div th:replace="~{fragments/navbarEntry :: navbarEntry ( 'auto-split-pdf', 'images/layout-split.svg', 'home.autoSplitPDF.title', 'home.autoSplitPDF.desc')}"></div>
|
<div th:replace="~{fragments/navbarEntry :: navbarEntry ( 'auto-split-pdf', 'images/layout-split.svg', 'home.autoSplitPDF.title', 'home.autoSplitPDF.desc')}"></div>
|
||||||
|
<div th:replace="~{fragments/navbarEntry :: navbarEntry ('adjust-contrast', 'images/adjust-contrast.svg', 'home.adjust-contrast.title', 'home.adjust-contrast.desc')}"></div>
|
||||||
|
<div th:replace="~{fragments/navbarEntry :: navbarEntry ('crop', 'images/crop.svg', 'home.crop.title', 'home.crop.desc')}"></div>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -96,11 +98,12 @@
|
|||||||
<div th:replace="~{fragments/navbarEntry :: navbarEntry ('change-permissions', 'images/shield-lock.svg', 'home.permissions.title', 'home.permissions.desc')}"></div>
|
<div th:replace="~{fragments/navbarEntry :: navbarEntry ('change-permissions', 'images/shield-lock.svg', 'home.permissions.title', 'home.permissions.desc')}"></div>
|
||||||
<div th:replace="~{fragments/navbarEntry :: navbarEntry ('add-watermark', 'images/droplet.svg', 'home.watermark.title', 'home.watermark.desc')}"></div>
|
<div th:replace="~{fragments/navbarEntry :: navbarEntry ('add-watermark', 'images/droplet.svg', 'home.watermark.title', 'home.watermark.desc')}"></div>
|
||||||
<div th:replace="~{fragments/navbarEntry :: navbarEntry ('cert-sign', 'images/award.svg', 'home.certSign.title', 'home.certSign.desc')}"></div>
|
<div th:replace="~{fragments/navbarEntry :: navbarEntry ('cert-sign', 'images/award.svg', 'home.certSign.title', 'home.certSign.desc')}"></div>
|
||||||
|
<div th:replace="~{fragments/navbarEntry :: navbarEntry ('sanitize-pdf', 'images/sanitize.svg', 'home.sanitizePdf.title', 'home.sanitizePdf.desc')}"></div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="nav-item nav-item-separator"></li>
|
<li class="nav-item nav-item-separator"></li>
|
||||||
<li class="nav-item dropdown" th:classappend="${currentPage}=='sign' OR ${currentPage}=='repair' OR ${currentPage}=='compare' OR ${currentPage}=='flatten' OR ${currentPage}=='remove-blanks' OR ${currentPage}=='extract-image-scans' OR ${currentPage}=='change-metadata' OR ${currentPage}=='add-image' OR ${currentPage}=='ocr-pdf' OR ${currentPage}=='change-permissions' OR ${currentPage}=='extract-images' OR ${currentPage}=='compress-pdf' OR ${currentPage}=='add-page-numbers' OR ${currentPage}=='auto-rename' OR ${currentPage}=='adjust-contrast' OR ${currentPage}=='crop' ? 'active' : ''">
|
<li class="nav-item dropdown" th:classappend="${currentPage}=='sign' OR ${currentPage}=='repair' OR ${currentPage}=='compare' OR ${currentPage}=='flatten' OR ${currentPage}=='remove-blanks' OR ${currentPage}=='extract-image-scans' OR ${currentPage}=='change-metadata' OR ${currentPage}=='add-image' OR ${currentPage}=='ocr-pdf' OR ${currentPage}=='change-permissions' OR ${currentPage}=='extract-images' OR ${currentPage}=='compress-pdf' OR ${currentPage}=='add-page-numbers' OR ${currentPage}=='auto-rename' ? 'active' : ''">
|
||||||
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||||
<img class="icon" src="images/card-list.svg" alt="icon" style="width: 16px; height: 16px; vertical-align: middle;">
|
<img class="icon" src="images/card-list.svg" alt="icon" style="width: 16px; height: 16px; vertical-align: middle;">
|
||||||
<span class="icon-text" th:text="#{navbar.other}"></span>
|
<span class="icon-text" th:text="#{navbar.other}"></span>
|
||||||
@ -121,8 +124,6 @@
|
|||||||
<div th:replace="~{fragments/navbarEntry :: navbarEntry ('compare', 'images/scales.svg', 'home.compare.title', 'home.compare.desc')}"></div>
|
<div th:replace="~{fragments/navbarEntry :: navbarEntry ('compare', 'images/scales.svg', 'home.compare.title', 'home.compare.desc')}"></div>
|
||||||
<div th:replace="~{fragments/navbarEntry :: navbarEntry ('add-page-numbers', 'images/add-page-numbers.svg', 'home.add-page-numbers.title', 'home.add-page-numbers.desc')}"></div>
|
<div th:replace="~{fragments/navbarEntry :: navbarEntry ('add-page-numbers', 'images/add-page-numbers.svg', 'home.add-page-numbers.title', 'home.add-page-numbers.desc')}"></div>
|
||||||
<div th:replace="~{fragments/navbarEntry :: navbarEntry ('auto-rename', 'images/fonts.svg', 'home.auto-rename.title', 'home.auto-rename.desc')}"></div>
|
<div th:replace="~{fragments/navbarEntry :: navbarEntry ('auto-rename', 'images/fonts.svg', 'home.auto-rename.title', 'home.auto-rename.desc')}"></div>
|
||||||
<div th:replace="~{fragments/navbarEntry :: navbarEntry ('adjust-contrast', 'images/adjust-contrast.svg', 'home.adjust-contrast.title', 'home.adjust-contrast.desc')}"></div>
|
|
||||||
<div th:replace="~{fragments/navbarEntry :: navbarEntry ('crop', 'images/crop.svg', 'home.crop.title', 'home.crop.desc')}"></div>
|
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@
|
|||||||
<div th:replace="~{fragments/card :: card(id='adjust-contrast', cardTitle=#{home.adjust-contrast.title}, cardText=#{home.adjust-contrast.desc}, cardLink='adjust-contrast', svgPath='images/adjust-contrast.svg')}"></div>
|
<div th:replace="~{fragments/card :: card(id='adjust-contrast', cardTitle=#{home.adjust-contrast.title}, cardText=#{home.adjust-contrast.desc}, cardLink='adjust-contrast', svgPath='images/adjust-contrast.svg')}"></div>
|
||||||
<div th:replace="~{fragments/card :: card(id='crop', cardTitle=#{home.crop.title}, cardText=#{home.crop.desc}, cardLink='crop', svgPath='images/crop.svg')}"></div>
|
<div th:replace="~{fragments/card :: card(id='crop', cardTitle=#{home.crop.title}, cardText=#{home.crop.desc}, cardLink='crop', svgPath='images/crop.svg')}"></div>
|
||||||
<div th:replace="~{fragments/card :: card(id='auto-split-pdf', cardTitle=#{home.autoSplitPDF.title}, cardText=#{home.autoSplitPDF.desc}, cardLink='auto-split-pdf', svgPath='images/layout-split.svg')}"></div>
|
<div th:replace="~{fragments/card :: card(id='auto-split-pdf', cardTitle=#{home.autoSplitPDF.title}, cardText=#{home.autoSplitPDF.desc}, cardLink='auto-split-pdf', svgPath='images/layout-split.svg')}"></div>
|
||||||
|
<div th:replace="~{fragments/card :: card(id='sanitize-pdf', cardTitle=#{home.sanitizePdf.title}, cardText=#{home.sanitizePdf.desc}, cardLink='sanitize-pdf', svgPath='images/sanitize.svg')}"></div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div> </div>
|
</div> </div>
|
||||||
|
@ -23,15 +23,13 @@
|
|||||||
th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"></div>
|
th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"></div>
|
||||||
<br>
|
<br>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="customMargin">Margin Size</label> <select
|
<label for="customMargin" th:text="#{addPageNumbers.selectText.2}"></label> <select
|
||||||
class="form-control" id="customMargin" name="customMargin"
|
class="form-control" id="customMargin" name="customMargin"
|
||||||
required>
|
required>
|
||||||
<option value="" disabled selected>Select a margin
|
<option value="small" th:text="#{sizes.small}"></option>
|
||||||
size</option>
|
<option value="medium" selected th:text="#{sizes.medium}"></option>
|
||||||
<option value="small">Small</option>
|
<option value="large" th:text="#{sizes.large}"></option>
|
||||||
<option value="medium">Medium</option>
|
<option value="x-large" th:text="#{sizes.x-large}"></option>
|
||||||
<option value="large">Large</option>
|
|
||||||
<option value="x-large">X-Large</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<style>
|
<style>
|
||||||
@ -80,7 +78,7 @@
|
|||||||
|
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="position">Position</label>
|
<label for="position" th:text="#{addPageNumbers.selectText.3}"></label>
|
||||||
<div class="a4container">
|
<div class="a4container">
|
||||||
<div class="pageNumber" id="1" style="top: 10%; left: 10%;">1</div>
|
<div class="pageNumber" id="1" style="top: 10%; left: 10%;">1</div>
|
||||||
<div class="pageNumber" id="2" style="top: 10%; left: 50%;">2</div>
|
<div class="pageNumber" id="2" style="top: 10%; left: 50%;">2</div>
|
||||||
@ -92,27 +90,23 @@
|
|||||||
<div class="pageNumber" id="8" style="top: 90%; left: 50%;">8</div>
|
<div class="pageNumber" id="8" style="top: 90%; left: 50%;">8</div>
|
||||||
<div class="pageNumber" id="9" style="top: 90%; left: 90%;">9</div>
|
<div class="pageNumber" id="9" style="top: 90%; left: 90%;">9</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<input type="hidden" id="numberInput" name="position" min="1"
|
<input type="hidden" id="numberInput" name="position" min="1"
|
||||||
max="9" required>
|
max="9" required>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="startingNumber">Starting Number</label> <input
|
<label for="startingNumber" th:text="#{addPageNumbers.selectText.4}"></label> <input
|
||||||
type="number" class="form-control" id="startingNumber"
|
type="number" class="form-control" id="startingNumber"
|
||||||
name="startingNumber" min="1" required value="1" />
|
name="startingNumber" min="1" required value="1" />
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="pagesToNumber">Pages to Number</label> <input
|
<label for="pagesToNumber" th:text="#{addPageNumbers.selectText.5}"></label> <input
|
||||||
type="text" class="form-control" id="pagesToNumber"
|
type="text" class="form-control" id="pagesToNumber"
|
||||||
name="pagesToNumber"
|
name="pagesToNumber"
|
||||||
placeholder="Which pages to number, default 'all', also accepts 1-5 or 2,5,9 etc" />
|
placeholder="Which pages to number, default 'all', also accepts 1-5 or 2,5,9 etc" />
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="customText">Custom Text</label> <input type="text"
|
<label for="customText" th:text="#{addPageNumbers.selectText.6}"></label> <input type="text"
|
||||||
class="form-control" id="customText" name="customText"
|
class="form-control" id="customText" name="customText"
|
||||||
placeholder="Default just number, also accepts 'Page {n} of {total}', 'Tag-{n}' etc" />
|
placeholder="Default just number, also accepts 'Page {n} of {total}', 'Tag-{n}' etc" />
|
||||||
</div>
|
</div>
|
||||||
@ -157,4 +151,4 @@
|
|||||||
<div th:insert="~{fragments/footer.html :: footer}"></div>
|
<div th:insert="~{fragments/footer.html :: footer}"></div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -1,292 +1,293 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html th:lang="${#locale.toString()}"
|
<html th:lang="${#locale.toString()}"
|
||||||
th:lang-direction="#{language.direction}"
|
th:lang-direction="#{language.direction}"
|
||||||
xmlns:th="http://www.thymeleaf.org">
|
xmlns:th="http://www.thymeleaf.org">
|
||||||
|
|
||||||
<th:block
|
<th:block
|
||||||
th:insert="~{fragments/common :: head(title=#{extractImages.title})}"></th:block>
|
th:insert="~{fragments/common :: head(title=#{adjustContrast.title})}"></th:block>
|
||||||
|
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="page-container">
|
<div id="page-container">
|
||||||
<div id="content-wrap">
|
<div id="content-wrap">
|
||||||
<div th:insert="~{fragments/navbar.html :: navbar}"></div>
|
<div th:insert="~{fragments/navbar.html :: navbar}"></div>
|
||||||
<br> <br>
|
<br> <br>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row justify-content-center">
|
<div class="row justify-content-center">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<h2 th:text="#{extractImages.header}"></h2>
|
<h2 th:text="#{adjustContrast.header}"></h2>
|
||||||
<input type="file" id="pdf-file" accept="application/pdf" />
|
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf', remoteCall='false')}"></div>
|
||||||
<canvas id="pdf-canvas"></canvas>
|
<h4>
|
||||||
|
<span th:text="#{adjustContrast.contrast}"></span> <span id="contrast-val">100</span>%
|
||||||
<h4>
|
</h4>
|
||||||
Contrast: <span id="contrast-val">100</span>%
|
<input type="range" min="0" max="200" value="100"
|
||||||
</h4>
|
id="contrast-slider" />
|
||||||
<input type="range" min="0" max="200" value="100"
|
|
||||||
id="contrast-slider" />
|
<h4>
|
||||||
|
<span th:text="#{adjustContrast.brightness}"></span> <span id="brightness-val">100</span>%
|
||||||
<h4>
|
</h4>
|
||||||
Brightness: <span id="brightness-val">100</span>%
|
<input type="range" min="0" max="200" value="100"
|
||||||
</h4>
|
id="brightness-slider" />
|
||||||
<input type="range" min="0" max="200" value="100"
|
|
||||||
id="brightness-slider" />
|
<h4>
|
||||||
|
<span th:text="#{adjustContrast.saturation}"></span> <span id="saturation-val">100</span>%
|
||||||
<h4>
|
</h4>
|
||||||
Saturation: <span id="saturation-val">100</span>%
|
<input type="range" min="0" max="200" value="100"
|
||||||
</h4>
|
id="saturation-slider" />
|
||||||
<input type="range" min="0" max="200" value="100"
|
|
||||||
id="saturation-slider" />
|
</br>
|
||||||
|
<canvas id="pdf-canvas"></canvas>
|
||||||
<button id="download-button">Download</button>
|
|
||||||
|
|
||||||
<script src="pdfjs/pdf.js"></script>
|
|
||||||
<script>
|
<button id="download-button" class="btn btn-primary" th:text="#{adjustContrast.download}"></button>
|
||||||
var canvas = document.getElementById('pdf-canvas');
|
|
||||||
var context = canvas.getContext('2d');
|
<script src="pdfjs/pdf.js"></script>
|
||||||
var originalImageData = null;
|
<script>
|
||||||
var allPages = [];
|
var canvas = document.getElementById('pdf-canvas');
|
||||||
var pdfDoc = null;
|
var context = canvas.getContext('2d');
|
||||||
var pdf = null; // This is the current PDF document
|
var originalImageData = null;
|
||||||
|
var allPages = [];
|
||||||
async function renderPDFAndSaveOriginalImageData(file) {
|
var pdfDoc = null;
|
||||||
var fileReader = new FileReader();
|
var pdf = null; // This is the current PDF document
|
||||||
fileReader.onload = async function() {
|
|
||||||
var data = new Uint8Array(this.result);
|
async function renderPDFAndSaveOriginalImageData(file) {
|
||||||
pdf = await pdfjsLib.getDocument({data: data}).promise;
|
var fileReader = new FileReader();
|
||||||
|
fileReader.onload = async function() {
|
||||||
// Get the number of pages in the PDF
|
var data = new Uint8Array(this.result);
|
||||||
var numPages = pdf.numPages;
|
pdf = await pdfjsLib.getDocument({data: data}).promise;
|
||||||
allPages = Array.from({length: numPages}, (_, i) => i + 1);
|
|
||||||
|
// Get the number of pages in the PDF
|
||||||
// Create a new PDF document
|
var numPages = pdf.numPages;
|
||||||
pdfDoc = await PDFLib.PDFDocument.create();
|
allPages = Array.from({length: numPages}, (_, i) => i + 1);
|
||||||
// Render the first page in the viewer
|
|
||||||
await renderPageAndAdjustImageProperties(1);
|
// Create a new PDF document
|
||||||
};
|
pdfDoc = await PDFLib.PDFDocument.create();
|
||||||
fileReader.readAsArrayBuffer(file);
|
// Render the first page in the viewer
|
||||||
}
|
await renderPageAndAdjustImageProperties(1);
|
||||||
|
};
|
||||||
// This function is now async and returns a promise
|
fileReader.readAsArrayBuffer(file);
|
||||||
function renderPageAndAdjustImageProperties(pageNum) {
|
}
|
||||||
return new Promise(async function(resolve, reject) {
|
|
||||||
var page = await pdf.getPage(pageNum);
|
// This function is now async and returns a promise
|
||||||
var scale = 1.5;
|
function renderPageAndAdjustImageProperties(pageNum) {
|
||||||
var viewport = page.getViewport({ scale: scale });
|
return new Promise(async function(resolve, reject) {
|
||||||
|
var page = await pdf.getPage(pageNum);
|
||||||
canvas.height = viewport.height;
|
var scale = 1.5;
|
||||||
canvas.width = viewport.width;
|
var viewport = page.getViewport({ scale: scale });
|
||||||
|
|
||||||
var renderContext = {
|
canvas.height = viewport.height;
|
||||||
canvasContext: context,
|
canvas.width = viewport.width;
|
||||||
viewport: viewport
|
|
||||||
};
|
var renderContext = {
|
||||||
|
canvasContext: context,
|
||||||
var renderTask = page.render(renderContext);
|
viewport: viewport
|
||||||
renderTask.promise.then(function () {
|
};
|
||||||
originalImageData = context.getImageData(0, 0, canvas.width, canvas.height);
|
|
||||||
adjustImageProperties();
|
var renderTask = page.render(renderContext);
|
||||||
resolve();
|
renderTask.promise.then(function () {
|
||||||
});
|
originalImageData = context.getImageData(0, 0, canvas.width, canvas.height);
|
||||||
});
|
adjustImageProperties();
|
||||||
}
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
function adjustImageProperties() {
|
}
|
||||||
var contrast = parseFloat(document.getElementById('contrast-slider').value);
|
|
||||||
var brightness = parseFloat(document.getElementById('brightness-slider').value);
|
|
||||||
var saturation = parseFloat(document.getElementById('saturation-slider').value);
|
function adjustImageProperties() {
|
||||||
|
var contrast = parseFloat(document.getElementById('contrast-slider').value);
|
||||||
contrast /= 100; // normalize to range [0, 2]
|
var brightness = parseFloat(document.getElementById('brightness-slider').value);
|
||||||
brightness /= 100; // normalize to range [0, 2]
|
var saturation = parseFloat(document.getElementById('saturation-slider').value);
|
||||||
saturation /= 100; // normalize to range [0, 2]
|
|
||||||
|
contrast /= 100; // normalize to range [0, 2]
|
||||||
if (originalImageData) {
|
brightness /= 100; // normalize to range [0, 2]
|
||||||
var newImageData = context.createImageData(originalImageData.width, originalImageData.height);
|
saturation /= 100; // normalize to range [0, 2]
|
||||||
newImageData.data.set(originalImageData.data);
|
|
||||||
|
if (originalImageData) {
|
||||||
for(var i=0; i<newImageData.data.length; i+=4)
|
var newImageData = context.createImageData(originalImageData.width, originalImageData.height);
|
||||||
{
|
newImageData.data.set(originalImageData.data);
|
||||||
var r = newImageData.data[i];
|
|
||||||
var g = newImageData.data[i+1];
|
for(var i=0; i<newImageData.data.length; i+=4)
|
||||||
var b = newImageData.data[i+2];
|
{
|
||||||
// Adjust contrast
|
var r = newImageData.data[i];
|
||||||
r = adjustContrastForPixel(r, contrast);
|
var g = newImageData.data[i+1];
|
||||||
g = adjustContrastForPixel(g, contrast);
|
var b = newImageData.data[i+2];
|
||||||
b = adjustContrastForPixel(b, contrast);
|
// Adjust contrast
|
||||||
// Adjust brightness
|
r = adjustContrastForPixel(r, contrast);
|
||||||
r = adjustBrightnessForPixel(r, brightness);
|
g = adjustContrastForPixel(g, contrast);
|
||||||
g = adjustBrightnessForPixel(g, brightness);
|
b = adjustContrastForPixel(b, contrast);
|
||||||
b = adjustBrightnessForPixel(b, brightness);
|
// Adjust brightness
|
||||||
// Adjust saturation
|
r = adjustBrightnessForPixel(r, brightness);
|
||||||
var rgb = adjustSaturationForPixel(r, g, b, saturation);
|
g = adjustBrightnessForPixel(g, brightness);
|
||||||
newImageData.data[i] = rgb[0];
|
b = adjustBrightnessForPixel(b, brightness);
|
||||||
newImageData.data[i+1] = rgb[1];
|
// Adjust saturation
|
||||||
newImageData.data[i+2] = rgb[2];
|
var rgb = adjustSaturationForPixel(r, g, b, saturation);
|
||||||
}
|
newImageData.data[i] = rgb[0];
|
||||||
|
newImageData.data[i+1] = rgb[1];
|
||||||
context.putImageData(newImageData, 0, 0);
|
newImageData.data[i+2] = rgb[2];
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
context.putImageData(newImageData, 0, 0);
|
||||||
function rgbToHsl(r, g, b) {
|
}
|
||||||
r /= 255, g /= 255, b /= 255;
|
}
|
||||||
|
|
||||||
var max = Math.max(r, g, b), min = Math.min(r, g, b);
|
function rgbToHsl(r, g, b) {
|
||||||
var h, s, l = (max + min) / 2;
|
r /= 255, g /= 255, b /= 255;
|
||||||
|
|
||||||
if (max === min) {
|
var max = Math.max(r, g, b), min = Math.min(r, g, b);
|
||||||
h = s = 0; // achromatic
|
var h, s, l = (max + min) / 2;
|
||||||
} else {
|
|
||||||
var d = max - min;
|
if (max === min) {
|
||||||
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
h = s = 0; // achromatic
|
||||||
|
} else {
|
||||||
switch (max) {
|
var d = max - min;
|
||||||
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
|
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
||||||
case g: h = (b - r) / d + 2; break;
|
|
||||||
case b: h = (r - g) / d + 4; break;
|
switch (max) {
|
||||||
}
|
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
|
||||||
|
case g: h = (b - r) / d + 2; break;
|
||||||
h /= 6;
|
case b: h = (r - g) / d + 4; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return [h, s, l];
|
h /= 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
function hslToRgb(h, s, l) {
|
return [h, s, l];
|
||||||
var r, g, b;
|
}
|
||||||
|
|
||||||
if (s === 0) {
|
function hslToRgb(h, s, l) {
|
||||||
r = g = b = l; // achromatic
|
var r, g, b;
|
||||||
} else {
|
|
||||||
var hue2rgb = function hue2rgb(p, q, t) {
|
if (s === 0) {
|
||||||
if (t < 0) t += 1;
|
r = g = b = l; // achromatic
|
||||||
if (t > 1) t -= 1;
|
} else {
|
||||||
if (t < 1 / 6) return p + (q - p) * 6 * t;
|
var hue2rgb = function hue2rgb(p, q, t) {
|
||||||
if (t < 1 / 2) return q;
|
if (t < 0) t += 1;
|
||||||
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
|
if (t > 1) t -= 1;
|
||||||
return p;
|
if (t < 1 / 6) return p + (q - p) * 6 * t;
|
||||||
};
|
if (t < 1 / 2) return q;
|
||||||
|
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
|
||||||
var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
return p;
|
||||||
var p = 2 * l - q;
|
};
|
||||||
|
|
||||||
r = hue2rgb(p, q, h + 1 / 3);
|
var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
||||||
g = hue2rgb(p, q, h);
|
var p = 2 * l - q;
|
||||||
b = hue2rgb(p, q, h - 1 / 3);
|
|
||||||
}
|
r = hue2rgb(p, q, h + 1 / 3);
|
||||||
|
g = hue2rgb(p, q, h);
|
||||||
return [r * 255, g * 255, b * 255];
|
b = hue2rgb(p, q, h - 1 / 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
function adjustContrastForPixel(pixel, contrast) {
|
return [r * 255, g * 255, b * 255];
|
||||||
// Normalize to range [-0.5, 0.5]
|
}
|
||||||
var normalized = pixel / 255 - 0.5;
|
|
||||||
|
function adjustContrastForPixel(pixel, contrast) {
|
||||||
// Apply contrast
|
// Normalize to range [-0.5, 0.5]
|
||||||
normalized *= contrast;
|
var normalized = pixel / 255 - 0.5;
|
||||||
|
|
||||||
// Denormalize back to [0, 255]
|
// Apply contrast
|
||||||
return (normalized + 0.5) * 255;
|
normalized *= contrast;
|
||||||
}
|
|
||||||
function clamp(value, min, max) {
|
// Denormalize back to [0, 255]
|
||||||
return Math.min(Math.max(value, min), max);
|
return (normalized + 0.5) * 255;
|
||||||
}
|
}
|
||||||
|
function clamp(value, min, max) {
|
||||||
function adjustSaturationForPixel(r, g, b, saturation) {
|
return Math.min(Math.max(value, min), max);
|
||||||
var hsl = rgbToHsl(r, g, b);
|
}
|
||||||
|
|
||||||
// Adjust saturation
|
function adjustSaturationForPixel(r, g, b, saturation) {
|
||||||
hsl[1] = clamp(hsl[1] * saturation, 0, 1);
|
var hsl = rgbToHsl(r, g, b);
|
||||||
|
|
||||||
// Convert back to RGB
|
// Adjust saturation
|
||||||
var rgb = hslToRgb(hsl[0], hsl[1], hsl[2]);
|
hsl[1] = clamp(hsl[1] * saturation, 0, 1);
|
||||||
|
|
||||||
// Return adjusted RGB values
|
// Convert back to RGB
|
||||||
return rgb;
|
var rgb = hslToRgb(hsl[0], hsl[1], hsl[2]);
|
||||||
}
|
|
||||||
|
// Return adjusted RGB values
|
||||||
function adjustBrightnessForPixel(pixel, brightness) {
|
return rgb;
|
||||||
return Math.max(0, Math.min(255, pixel * brightness));
|
}
|
||||||
}
|
|
||||||
|
function adjustBrightnessForPixel(pixel, brightness) {
|
||||||
async function downloadPDF() {
|
return Math.max(0, Math.min(255, pixel * brightness));
|
||||||
for (var i = 0; i < allPages.length; i++) {
|
}
|
||||||
await renderPageAndAdjustImageProperties(allPages[i]);
|
|
||||||
const pngImageBytes = canvas.toDataURL('image/png');
|
async function downloadPDF() {
|
||||||
const pngImage = await pdfDoc.embedPng(pngImageBytes);
|
for (var i = 0; i < allPages.length; i++) {
|
||||||
const pngDims = pngImage.scale(1);
|
await renderPageAndAdjustImageProperties(allPages[i]);
|
||||||
|
const pngImageBytes = canvas.toDataURL('image/png');
|
||||||
// Create a blank page matching the dimensions of the image
|
const pngImage = await pdfDoc.embedPng(pngImageBytes);
|
||||||
const page = pdfDoc.addPage([pngDims.width, pngDims.height]);
|
const pngDims = pngImage.scale(1);
|
||||||
|
|
||||||
// Draw the PNG image
|
// Create a blank page matching the dimensions of the image
|
||||||
page.drawImage(pngImage, {
|
const page = pdfDoc.addPage([pngDims.width, pngDims.height]);
|
||||||
x: 0,
|
|
||||||
y: 0,
|
// Draw the PNG image
|
||||||
width: pngDims.width,
|
page.drawImage(pngImage, {
|
||||||
height: pngDims.height
|
x: 0,
|
||||||
});
|
y: 0,
|
||||||
}
|
width: pngDims.width,
|
||||||
|
height: pngDims.height
|
||||||
// Serialize the PDFDocument to bytes (a Uint8Array)
|
});
|
||||||
const pdfBytes = await pdfDoc.save();
|
}
|
||||||
|
|
||||||
// Create a Blob
|
// Serialize the PDFDocument to bytes (a Uint8Array)
|
||||||
const blob = new Blob([pdfBytes.buffer], {type: "application/pdf"});
|
const pdfBytes = await pdfDoc.save();
|
||||||
|
|
||||||
// Create download link
|
// Create a Blob
|
||||||
const downloadLink = document.createElement('a');
|
const blob = new Blob([pdfBytes.buffer], {type: "application/pdf"});
|
||||||
downloadLink.href = URL.createObjectURL(blob);
|
|
||||||
downloadLink.download = "download.pdf";
|
// Create download link
|
||||||
downloadLink.click();
|
const downloadLink = document.createElement('a');
|
||||||
|
downloadLink.href = URL.createObjectURL(blob);
|
||||||
// After download, reset the viewer and clear stored data
|
downloadLink.download = "download.pdf";
|
||||||
allPages = []; // Clear the pages
|
downloadLink.click();
|
||||||
originalImageData = null; // Clear the image data
|
|
||||||
|
// After download, reset the viewer and clear stored data
|
||||||
// Go back to page 1 and render it in the viewer
|
allPages = []; // Clear the pages
|
||||||
if (pdf !== null) {
|
originalImageData = null; // Clear the image data
|
||||||
renderPageAndAdjustImageProperties(1);
|
|
||||||
}
|
// Go back to page 1 and render it in the viewer
|
||||||
|
if (pdf !== null) {
|
||||||
}
|
renderPageAndAdjustImageProperties(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// Event listeners
|
|
||||||
document.getElementById('pdf-file').addEventListener('change', function(e) {
|
|
||||||
if (e.target.files.length > 0) {
|
|
||||||
renderPDFAndSaveOriginalImageData(e.target.files[0]);
|
// Event listeners
|
||||||
}
|
document.getElementById('fileInput-input').addEventListener('change', function(e) {
|
||||||
});
|
if (e.target.files.length > 0) {
|
||||||
|
renderPDFAndSaveOriginalImageData(e.target.files[0]);
|
||||||
document.getElementById('contrast-slider').addEventListener('input', function() {
|
}
|
||||||
document.getElementById('contrast-val').textContent = this.value;
|
});
|
||||||
adjustImageProperties();
|
|
||||||
});
|
document.getElementById('contrast-slider').addEventListener('input', function() {
|
||||||
|
document.getElementById('contrast-val').textContent = this.value;
|
||||||
document.getElementById('brightness-slider').addEventListener('input', function() {
|
adjustImageProperties();
|
||||||
document.getElementById('brightness-val').textContent = this.value;
|
});
|
||||||
adjustImageProperties();
|
|
||||||
});
|
document.getElementById('brightness-slider').addEventListener('input', function() {
|
||||||
|
document.getElementById('brightness-val').textContent = this.value;
|
||||||
document.getElementById('saturation-slider').addEventListener('input', function() {
|
adjustImageProperties();
|
||||||
document.getElementById('saturation-val').textContent = this.value;
|
});
|
||||||
adjustImageProperties();
|
|
||||||
});
|
document.getElementById('saturation-slider').addEventListener('input', function() {
|
||||||
|
document.getElementById('saturation-val').textContent = this.value;
|
||||||
document.getElementById('download-button').addEventListener('click', function() {
|
adjustImageProperties();
|
||||||
downloadPDF();
|
});
|
||||||
});
|
|
||||||
</script>
|
document.getElementById('download-button').addEventListener('click', function() {
|
||||||
|
downloadPDF();
|
||||||
|
});
|
||||||
</div>
|
</script>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div th:insert="~{fragments/footer.html :: footer}"></div>
|
</div>
|
||||||
</div>
|
<div th:insert="~{fragments/footer.html :: footer}"></div>
|
||||||
</body>
|
</div>
|
||||||
</html>
|
</body>
|
||||||
|
</html>
|
||||||
|
@ -1,31 +1,30 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html th:lang="${#locale.toString()}" th:lang-direction="#{language.direction}" xmlns:th="http://www.thymeleaf.org">
|
<html th:lang="${#locale.toString()}" th:lang-direction="#{language.direction}" xmlns:th="http://www.thymeleaf.org">
|
||||||
|
|
||||||
<th:block th:insert="~{fragments/common :: head(title=#{auto-rename.title})}"></th:block>
|
<th:block th:insert="~{fragments/common :: head(title=#{auto-rename.title})}"></th:block>
|
||||||
|
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<th:block th:insert="~{fragments/common :: game}"></th:block>
|
<th:block th:insert="~{fragments/common :: game}"></th:block>
|
||||||
<div id="page-container">
|
<div id="page-container">
|
||||||
<div id="content-wrap">
|
<div id="content-wrap">
|
||||||
<div th:insert="~{fragments/navbar.html :: navbar}"></div>
|
<div th:insert="~{fragments/navbar.html :: navbar}"></div>
|
||||||
<br> <br>
|
<br> <br>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row justify-content-center">
|
<div class="row justify-content-center">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<h2 th:text="#{auto-rename.header}"></h2>
|
<h2 th:text="#{auto-rename.header}"></h2>
|
||||||
<form method="post" enctype="multipart/form-data" th:action="@{auto-rename}">
|
<form method="post" enctype="multipart/form-data" th:action="@{auto-rename}">
|
||||||
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"></div>
|
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"></div>
|
||||||
<br>
|
<br>
|
||||||
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{auto-rename.submit}"></button>
|
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{auto-rename.submit}"></button>
|
||||||
</form>
|
</form>
|
||||||
<p class="mt-3" th:text="#{auto-rename.credit}"></p>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
</div>
|
||||||
</div>
|
<div th:insert="~{fragments/footer.html :: footer}"></div>
|
||||||
<div th:insert="~{fragments/footer.html :: footer}"></div>
|
</div>
|
||||||
</div>
|
</body>
|
||||||
</body>
|
</html>
|
||||||
</html>
|
|
||||||
|
53
src/main/resources/templates/security/sanitize-pdf.html
Normal file
53
src/main/resources/templates/security/sanitize-pdf.html
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html th:lang="${#locale.toString()}" th:lang-direction="#{language.direction}" xmlns:th="http://www.thymeleaf.org">
|
||||||
|
|
||||||
|
<th:block th:insert="~{fragments/common :: head(title=#{sanitizePDF.title})}"></th:block>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="page-container">
|
||||||
|
<div id="content-wrap">
|
||||||
|
<div th:insert="~{fragments/navbar.html :: navbar}"></div>
|
||||||
|
<br> <br>
|
||||||
|
<div class="container">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<h2 th:text="#{sanitizePDF.header}"></h2>
|
||||||
|
|
||||||
|
<form action="sanitize-pdf" method="post" enctype="multipart/form-data">
|
||||||
|
<div class="form-group">
|
||||||
|
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"></div>
|
||||||
|
</div>
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="checkbox" id="removeJavaScript" name="removeJavaScript" checked>
|
||||||
|
<label class="form-check-label" for="removeJavaScript" th:text="#{sanitizePDF.selectText.1}"></label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="checkbox" id="removeEmbeddedFiles" name="removeEmbeddedFiles" checked>
|
||||||
|
<label class="form-check-label" for="removeEmbeddedFiles" th:text="#{sanitizePDF.selectText.2}"></label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="checkbox" id="removeMetadata" name="removeMetadata" checked>
|
||||||
|
<label class="form-check-label" for="removeMetadata" th:text="#{sanitizePDF.selectText.3}"></label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="checkbox" id="removeLinks" name="removeLinks" checked>
|
||||||
|
<label class="form-check-label" for="removeLinks" th:text="#{sanitizePDF.selectText.4}"></label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="checkbox" id="removeFonts" name="removeFonts" checked>
|
||||||
|
<label class="form-check-label" for="removeFonts" th:text="#{sanitizePDF.selectText.5}"></label>
|
||||||
|
</div>
|
||||||
|
<br />
|
||||||
|
<div class="form-group text-center">
|
||||||
|
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{sanitizePDF.submit}"></button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div th:insert="~{fragments/footer.html :: footer}"></div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in New Issue
Block a user