diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/OCRController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/OCRController.java index 768493ab..aa25b9b4 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/misc/OCRController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/misc/OCRController.java @@ -18,6 +18,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestPart; @@ -28,6 +29,7 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.tags.Tag; +import stirling.software.SPDF.model.api.misc.ProcessPdfWithOcrRequest; import stirling.software.SPDF.utils.ProcessExecutor; import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult; import stirling.software.SPDF.utils.WebResponseUtils; @@ -51,35 +53,16 @@ public class OCRController { @PostMapping(consumes = "multipart/form-data", value = "/ocr-pdf") @Operation(summary = "Process a PDF file with OCR", description = "This endpoint processes a PDF file using OCR (Optical Character Recognition). Users can specify languages, sidecar, deskew, clean, cleanFinal, ocrType, ocrRenderType, and removeImagesAfter options. Input:PDF Output:PDF Type:SI-Conditional") - public ResponseEntity processPdfWithOCR( - @RequestPart(required = true, value = "fileInput") - @Parameter(description = "The input PDF file to be processed with OCR") - MultipartFile inputFile, - @RequestParam("languages") - @Parameter(description = "List of languages to use in OCR processing") - List selectedLanguages, - @RequestParam(name = "sidecar", required = false) - @Parameter(description = "Include OCR text in a sidecar text file if set to true") - Boolean sidecar, - @RequestParam(name = "deskew", required = false) - @Parameter(description = "Deskew the input file if set to true") - Boolean deskew, - @RequestParam(name = "clean", required = false) - @Parameter(description = "Clean the input file if set to true") - Boolean clean, - @RequestParam(name = "clean-final", required = false) - @Parameter(description = "Clean the final output if set to true") - Boolean cleanFinal, - @RequestParam(name = "ocrType", required = false) - @Parameter(description = "Specify the OCR type, e.g., 'skip-text', 'force-ocr', or 'Normal'", schema = @Schema(allowableValues = {"skip-text", "force-ocr", "Normal"})) - String ocrType, - @RequestParam(name = "ocrRenderType", required = false, defaultValue = "hocr") - @Parameter(description = "Specify the OCR render type, either 'hocr' or 'sandwich'", schema = @Schema(allowableValues = {"hocr", "sandwich"})) - String ocrRenderType, - @RequestParam(name = "removeImagesAfter", required = false) - @Parameter(description = "Remove images from the output PDF if set to true") - Boolean removeImagesAfter) throws IOException, InterruptedException { - + public ResponseEntity processPdfWithOCR(@ModelAttribute ProcessPdfWithOcrRequest request) throws IOException, InterruptedException { + MultipartFile inputFile = request.getFileInput(); + List selectedLanguages = request.getSelectedLanguages(); + Boolean sidecar = request.getSidecar(); + Boolean deskew = request.getDeskew(); + Boolean clean = request.getClean(); + Boolean cleanFinal = request.getCleanFinal(); + String ocrType = request.getOcrType(); + String ocrRenderType = request.getOcrRenderType(); + Boolean removeImagesAfter = request.getRemoveImagesAfter(); // --output-type pdfa if (selectedLanguages == null || selectedLanguages.isEmpty()) { throw new IOException("Please select at least one language."); diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/OverlayImageController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/OverlayImageController.java index 975e7628..44c16fd7 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/misc/OverlayImageController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/misc/OverlayImageController.java @@ -6,6 +6,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestPart; @@ -15,6 +16,7 @@ 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.tags.Tag; +import stirling.software.SPDF.model.api.misc.OverlayImageRequest; import stirling.software.SPDF.utils.PdfUtils; import stirling.software.SPDF.utils.WebResponseUtils; @@ -29,22 +31,12 @@ public class OverlayImageController { summary = "Overlay image onto a PDF file", description = "This endpoint overlays an image onto a PDF file at the specified coordinates. The image can be overlaid on every page of the PDF if specified. Input:PDF/IMAGE Output:PDF Type:MF-SISO" ) - public ResponseEntity overlayImage( - @RequestPart(required = true, value = "fileInput") - @Parameter(description = "The input PDF file to overlay the image onto.", required = true) - MultipartFile pdfFile, - @RequestParam("fileInput2") - @Parameter(description = "The image file to be overlaid onto the PDF.", required = true) - MultipartFile imageFile, - @RequestParam("x") - @Parameter(description = "The x-coordinate at which to place the top-left corner of the image.", example = "0") - float x, - @RequestParam("y") - @Parameter(description = "The y-coordinate at which to place the top-left corner of the image.", example = "0") - float y, - @RequestParam("everyPage") - @Parameter(description = "Whether to overlay the image onto every page of the PDF.", example = "false") - boolean everyPage) { + public ResponseEntity overlayImage(@ModelAttribute OverlayImageRequest request) { + MultipartFile pdfFile = request.getFileInput(); + MultipartFile imageFile = request.getImageFile(); + float x = request.getX(); + float y = request.getY(); + boolean everyPage = request.isEveryPage(); try { byte[] pdfBytes = pdfFile.getBytes(); byte[] imageBytes = imageFile.getBytes(); diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/PageNumbersController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/PageNumbersController.java index 2192d876..d1ecc9df 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/misc/PageNumbersController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/misc/PageNumbersController.java @@ -13,6 +13,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @@ -22,6 +23,7 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.tags.Tag; +import stirling.software.SPDF.model.api.misc.AddPageNumbersRequest; import stirling.software.SPDF.utils.GeneralUtils; import stirling.software.SPDF.utils.WebResponseUtils; @@ -33,14 +35,13 @@ public class PageNumbersController { @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") - public ResponseEntity addPageNumbers( - @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 = "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 = "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) - throws IOException { + public ResponseEntity addPageNumbers(@ModelAttribute AddPageNumbersRequest request) throws IOException { + MultipartFile file = request.getFileInput(); + String customMargin = request.getCustomMargin(); + int position = request.getPosition(); + int startingNumber = request.getStartingNumber(); + String pagesToNumber = request.getPagesToNumber(); + String customText = request.getCustomText(); int pageNumber = startingNumber; byte[] fileBytes = file.getBytes(); PDDocument document = PDDocument.load(fileBytes); diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/RepairController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/RepairController.java index e9983902..819f8f70 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/misc/RepairController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/misc/RepairController.java @@ -9,6 +9,7 @@ import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.bind.annotation.RestController; @@ -17,6 +18,8 @@ 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.tags.Tag; +import stirling.software.SPDF.model.api.PDFFile; +import stirling.software.SPDF.model.api.misc.AddPageNumbersRequest; import stirling.software.SPDF.utils.ProcessExecutor; import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult; import stirling.software.SPDF.utils.WebResponseUtils; @@ -32,11 +35,8 @@ public class RepairController { summary = "Repair a PDF file", description = "This endpoint repairs a given PDF file by running Ghostscript command. The PDF is first saved to a temporary location, repaired, read back, and then returned as a response. Input:PDF Output:PDF Type:SISO" ) - public ResponseEntity repairPdf( - @RequestPart(required = true, value = "fileInput") - @Parameter(description = "The input PDF file to be repaired", required = true) - MultipartFile inputFile) throws IOException, InterruptedException { - + public ResponseEntity repairPdf(@ModelAttribute PDFFile request) throws IOException, InterruptedException { + MultipartFile inputFile = request.getFileInput(); // Save the uploaded file to a temporary location Path tempInputFile = Files.createTempFile("input_", ".pdf"); inputFile.transferTo(tempInputFile.toFile()); diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/ShowJavascript.java b/src/main/java/stirling/software/SPDF/controller/api/misc/ShowJavascript.java index 08ac3e1b..d3101ff2 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/misc/ShowJavascript.java +++ b/src/main/java/stirling/software/SPDF/controller/api/misc/ShowJavascript.java @@ -9,12 +9,14 @@ import org.apache.pdfbox.pdmodel.interactive.action.PDActionJavaScript; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import io.swagger.v3.oas.annotations.tags.Tag; +import stirling.software.SPDF.model.api.PDFFile; import stirling.software.SPDF.utils.WebResponseUtils; @RestController @Tag(name = "Other", description = "Other APIs") @@ -22,9 +24,8 @@ public class ShowJavascript { private static final Logger logger = LoggerFactory.getLogger(ShowJavascript.class); @PostMapping(consumes = "multipart/form-data", value = "/show-javascript") - public ResponseEntity extractHeader( - @RequestPart(value = "fileInput") MultipartFile inputFile) throws Exception { - + public ResponseEntity extractHeader(@ModelAttribute PDFFile request) throws Exception { + MultipartFile inputFile = request.getFileInput(); String script = ""; try (PDDocument document = PDDocument.load(inputFile.getInputStream())) { diff --git a/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineController.java b/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineController.java index d5a50329..0e5d8de3 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/pipeline/PipelineController.java @@ -37,6 +37,7 @@ import org.springframework.http.ResponseEntity; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; +import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestPart; @@ -51,6 +52,7 @@ import io.swagger.v3.oas.annotations.tags.Tag; import stirling.software.SPDF.model.ApplicationProperties; import stirling.software.SPDF.model.PipelineConfig; import stirling.software.SPDF.model.PipelineOperation; +import stirling.software.SPDF.model.api.HandleDataRequest; import stirling.software.SPDF.utils.WebResponseUtils; @RestController @@ -418,8 +420,9 @@ public class PipelineController { } @PostMapping("/handleData") - public ResponseEntity handleData(@RequestPart("fileInput") MultipartFile[] files, - @RequestParam("json") String jsonString) { + public ResponseEntity handleData(@ModelAttribute HandleDataRequest request) { + MultipartFile[] files = request.getFileInputs(); + String jsonString = request.getJsonString(); logger.info("Received POST request to /handleData with {} files", files.length); try { List outputFiles = handleFiles(files, jsonString); diff --git a/src/main/java/stirling/software/SPDF/controller/api/security/CertSignController.java b/src/main/java/stirling/software/SPDF/controller/api/security/CertSignController.java index 6392be96..d9eb68a3 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/security/CertSignController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/security/CertSignController.java @@ -44,6 +44,7 @@ import org.bouncycastle.util.io.pem.PemReader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestPart; @@ -54,6 +55,7 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.tags.Tag; +import stirling.software.SPDF.model.api.security.SignPDFWithCertRequest; import stirling.software.SPDF.utils.WebResponseUtils; @RestController @@ -68,30 +70,18 @@ public class CertSignController { @PostMapping(consumes = "multipart/form-data", value = "/cert-sign") @Operation(summary = "Sign PDF with a Digital Certificate", description = "This endpoint accepts a PDF file, a digital certificate and related information to sign the PDF. It then returns the digitally signed PDF file. Input:PDF Output:PDF Type:MF-SISO") - public ResponseEntity signPDF2( - @RequestPart(required = true, value = "fileInput") @Parameter(description = "The input PDF file") MultipartFile pdf, - - @RequestParam(value = "certType", required = false) @Parameter(description = "The type of the digital certificate", schema = @Schema(allowableValues = { - "PKCS12", "PEM" })) String certType, - - @RequestParam(value = "key", required = false) @Parameter(description = "The private key for the digital certificate (required for PEM type certificates)") MultipartFile privateKeyFile, - - @RequestParam(value = "cert", required = false) @Parameter(description = "The digital certificate (required for PEM type certificates)") MultipartFile certFile, - - @RequestParam(value = "p12", required = false) @Parameter(description = "The PKCS12 keystore file (required for PKCS12 type certificates)") MultipartFile p12File, - - @RequestParam(value = "password", required = false) @Parameter(description = "The password for the keystore or the private key") String password, - - @RequestParam(value = "showSignature", required = false) @Parameter(description = "Whether to visually show the signature in the PDF file") Boolean showSignature, - - @RequestParam(value = "reason", required = false) @Parameter(description = "The reason for signing the PDF") String reason, - - @RequestParam(value = "location", required = false) @Parameter(description = "The location where the PDF is signed") String location, - - @RequestParam(value = "name", required = false) @Parameter(description = "The name of the signer") String name, - - @RequestParam(value = "pageNumber", required = false) @Parameter(description = "The page number where the signature should be visible. This is required if showSignature is set to true") Integer pageNumber) - throws Exception { + public ResponseEntity signPDFWithCert(@ModelAttribute SignPDFWithCertRequest request) throws Exception { + MultipartFile pdf = request.getFileInput(); + String certType = request.getCertType(); + MultipartFile privateKeyFile = request.getPrivateKeyFile(); + MultipartFile certFile = request.getCertFile(); + MultipartFile p12File = request.getP12File(); + String password = request.getPassword(); + Boolean showSignature = request.getShowSignature(); + String reason = request.getReason(); + String location = request.getLocation(); + String name = request.getName(); + Integer pageNumber = request.getPageNumber(); PrivateKey privateKey = null; X509Certificate cert = null; diff --git a/src/main/java/stirling/software/SPDF/controller/api/security/GetInfoOnPDF.java b/src/main/java/stirling/software/SPDF/controller/api/security/GetInfoOnPDF.java index 1f0e7d62..48f1c655 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/security/GetInfoOnPDF.java +++ b/src/main/java/stirling/software/SPDF/controller/api/security/GetInfoOnPDF.java @@ -60,6 +60,7 @@ import org.apache.xmpbox.xml.XmpParsingException; import org.apache.xmpbox.xml.XmpSerializer; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.bind.annotation.RestController; @@ -72,6 +73,7 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; +import stirling.software.SPDF.model.api.PDFFile; import stirling.software.SPDF.utils.WebResponseUtils; @RestController @Tag(name = "Security", description = "Security APIs") @@ -81,11 +83,9 @@ public class GetInfoOnPDF { @PostMapping(consumes = "multipart/form-data", value = "/get-info-on-pdf") @Operation(summary = "Summary here", description = "desc. Input:PDF Output:JSON Type:SISO") - public ResponseEntity getPdfInfo( - @RequestPart(required = true, value = "fileInput") - @Parameter(description = "The input PDF file to get info on", required = true) MultipartFile inputFile) + public ResponseEntity getPdfInfo(@ModelAttribute PDFFile request) throws IOException { - + MultipartFile inputFile = request.getFileInput(); try ( PDDocument pdfBoxDoc = PDDocument.load(inputFile.getInputStream()); ) { diff --git a/src/main/java/stirling/software/SPDF/controller/api/security/PasswordController.java b/src/main/java/stirling/software/SPDF/controller/api/security/PasswordController.java index bcc7e37f..9634143b 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/security/PasswordController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/security/PasswordController.java @@ -8,6 +8,7 @@ import org.apache.pdfbox.pdmodel.encryption.StandardProtectionPolicy; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestPart; @@ -18,6 +19,8 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.tags.Tag; +import stirling.software.SPDF.model.api.security.AddPasswordRequest; +import stirling.software.SPDF.model.api.security.PDFPasswordRequest; import stirling.software.SPDF.utils.WebResponseUtils; @RestController @Tag(name = "Security", description = "Security APIs") @@ -31,13 +34,12 @@ public class PasswordController { summary = "Remove password from a PDF file", description = "This endpoint removes the password from a protected PDF file. Users need to provide the existing password. Input:PDF Output:PDF Type:SISO" ) - public ResponseEntity removePassword( - @RequestPart(required = true, value = "fileInput") - @Parameter(description = "The input PDF file from which the password should be removed", required = true) - MultipartFile fileInput, - @RequestParam(name = "password") - @Parameter(description = "The password of the PDF file", required = true) - String password) throws IOException { + public ResponseEntity removePassword(@ModelAttribute PDFPasswordRequest request) throws IOException { + MultipartFile fileInput = request.getFileInput(); + String password = request.getPassword(); + + + PDDocument document = PDDocument.load(fileInput.getBytes(), password); document.setAllSecurityToBeRemoved(true); return WebResponseUtils.pdfDocToWebResponse(document, fileInput.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_password_removed.pdf"); @@ -48,44 +50,19 @@ public class PasswordController { summary = "Add password to a PDF file", description = "This endpoint adds password protection to a PDF file. Users can specify a set of permissions that should be applied to the file. Input:PDF Output:PDF" ) - public ResponseEntity addPassword( - @RequestPart(required = true, value = "fileInput") - @Parameter(description = "The input PDF file to which the password should be added", required = true) - MultipartFile fileInput, - @RequestParam(value = "", name = "ownerPassword", required = false, defaultValue = "") - @Parameter(description = "The owner password to be added to the PDF file (Restricts what can be done with the document once it is opened)") - String ownerPassword, - @RequestParam( name = "password", required = false, defaultValue = "") - @Parameter(description = "The password to be added to the PDF file (Restricts the opening of the document itself.)") - String password, - @RequestParam( name = "keyLength", required = false, defaultValue = "256") - @Parameter(description = "The length of the encryption key", schema = @Schema(allowableValues = {"40", "128", "256"})) - int keyLength, - @RequestParam( name = "canAssembleDocument", required = false) - @Parameter(description = "Whether the document assembly is allowed", example = "false") - boolean canAssembleDocument, - @RequestParam( name = "canExtractContent", required = false) - @Parameter(description = "Whether content extraction for accessibility is allowed", example = "false") - boolean canExtractContent, - @RequestParam( name = "canExtractForAccessibility", required = false) - @Parameter(description = "Whether content extraction for accessibility is allowed", example = "false") - boolean canExtractForAccessibility, - @RequestParam( name = "canFillInForm", required = false) - @Parameter(description = "Whether form filling is allowed", example = "false") - boolean canFillInForm, - @RequestParam( name = "canModify", required = false) - @Parameter(description = "Whether the document modification is allowed", example = "false") - boolean canModify, - @RequestParam( name = "canModifyAnnotations", required = false) - @Parameter(description = "Whether modification of annotations is allowed", example = "false") - boolean canModifyAnnotations, - @RequestParam(name = "canPrint", required = false) - @Parameter(description = "Whether printing of the document is allowed", example = "false") - boolean canPrint, - @RequestParam( name = "canPrintFaithful", required = false) - @Parameter(description = "Whether faithful printing is allowed", example = "false") - boolean canPrintFaithful - ) throws IOException { + public ResponseEntity addPassword(@ModelAttribute AddPasswordRequest request) throws IOException { + MultipartFile fileInput = request.getFileInput(); + String ownerPassword = request.getOwnerPassword(); + String password = request.getPassword(); + int keyLength = request.getKeyLength(); + boolean canAssembleDocument = request.isCanAssembleDocument(); + boolean canExtractContent = request.isCanExtractContent(); + boolean canExtractForAccessibility = request.isCanExtractForAccessibility(); + boolean canFillInForm = request.isCanFillInForm(); + boolean canModify = request.isCanModify(); + boolean canModifyAnnotations = request.isCanModifyAnnotations(); + boolean canPrint = request.isCanPrint(); + boolean canPrintFaithful = request.isCanPrintFaithful(); PDDocument document = PDDocument.load(fileInput.getBytes()); AccessPermission ap = new AccessPermission(); diff --git a/src/main/java/stirling/software/SPDF/controller/api/security/RedactController.java b/src/main/java/stirling/software/SPDF/controller/api/security/RedactController.java index 006968ae..6c0a5526 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/security/RedactController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/security/RedactController.java @@ -18,6 +18,7 @@ import org.apache.pdfbox.rendering.PDFRenderer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @@ -28,6 +29,7 @@ import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.tags.Tag; import stirling.software.SPDF.model.PDFText; +import stirling.software.SPDF.model.api.security.RedactPdfRequest; import stirling.software.SPDF.pdf.TextFinder; import stirling.software.SPDF.utils.WebResponseUtils; @RestController @@ -40,14 +42,14 @@ public class RedactController { @PostMapping(value = "/auto-redact", consumes = "multipart/form-data") @Operation(summary = "Redacts listOfText in a PDF document", description = "This operation takes an input PDF file and redacts the provided listOfText. Input:PDF, Output:PDF, Type:SISO") - public ResponseEntity redactPdf( - @Parameter(description = "The input PDF file", required = true) @RequestParam("fileInput") MultipartFile file, - @Parameter(description = "List of listOfText to redact from the PDF", required = true, schema = @Schema(type = "string")) @RequestParam("listOfText") String listOfTextString, - @RequestParam(value = "useRegex", required = false) boolean useRegex, - @RequestParam(value = "wholeWordSearch", required = false) boolean wholeWordSearchBool, - @RequestParam(value = "redactColor", required = false, defaultValue = "#000000") String colorString, - @RequestParam(value = "customPadding", required = false) float customPadding, - @RequestParam(value = "convertPDFToImage", required = false) boolean convertPDFToImage) throws Exception { + public ResponseEntity redactPdf(@ModelAttribute RedactPdfRequest request) throws Exception { + MultipartFile file = request.getFileInput(); + String listOfTextString = request.getListOfText(); + boolean useRegex = request.isUseRegex(); + boolean wholeWordSearchBool = request.isWholeWordSearch(); + String colorString = request.getRedactColor(); + float customPadding = request.getCustomPadding(); + boolean convertPDFToImage = request.isConvertPDFToImage(); System.out.println(listOfTextString); String[] listOfText = listOfTextString.split("\n"); diff --git a/src/main/java/stirling/software/SPDF/controller/api/security/SanitizeController.java b/src/main/java/stirling/software/SPDF/controller/api/security/SanitizeController.java index fa49c6ad..ccf088de 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/security/SanitizeController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/security/SanitizeController.java @@ -20,6 +20,7 @@ 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.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestPart; @@ -28,6 +29,7 @@ import org.springframework.web.multipart.MultipartFile; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; +import stirling.software.SPDF.model.api.security.SanitizePdfRequest; import stirling.software.SPDF.utils.WebResponseUtils; @RestController @@ -36,25 +38,13 @@ 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 sanitizePDF( - @RequestPart(required = true, value = "fileInput") - @Parameter(description = "The input PDF file to be sanitized") - MultipartFile inputFile, - @RequestParam(name = "removeJavaScript", required = false, defaultValue = "false") - @Parameter(description = "Remove JavaScript actions from the PDF if set to true") - Boolean removeJavaScript, - @RequestParam(name = "removeEmbeddedFiles", required = false, defaultValue = "false") - @Parameter(description = "Remove embedded files from the PDF if set to true") - Boolean removeEmbeddedFiles, - @RequestParam(name = "removeMetadata", required = false, defaultValue = "false") - @Parameter(description = "Remove metadata from the PDF if set to true") - Boolean removeMetadata, - @RequestParam(name = "removeLinks", required = false, defaultValue = "false") - @Parameter(description = "Remove links from the PDF if set to true") - Boolean removeLinks, - @RequestParam(name = "removeFonts", required = false, defaultValue = "false") - @Parameter(description = "Remove fonts from the PDF if set to true") - Boolean removeFonts) throws IOException { + public ResponseEntity sanitizePDF(@ModelAttribute SanitizePdfRequest request) throws IOException { + MultipartFile inputFile = request.getFileInput(); + Boolean removeJavaScript = request.getRemoveJavaScript(); + Boolean removeEmbeddedFiles = request.getRemoveEmbeddedFiles(); + Boolean removeMetadata = request.getRemoveMetadata(); + Boolean removeLinks = request.getRemoveLinks(); + Boolean removeFonts = request.getRemoveFonts(); try (PDDocument document = PDDocument.load(inputFile.getInputStream())) { if (removeJavaScript) { diff --git a/src/main/java/stirling/software/SPDF/controller/api/security/WatermarkController.java b/src/main/java/stirling/software/SPDF/controller/api/security/WatermarkController.java index efc263f5..a46f4ff4 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/security/WatermarkController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/security/WatermarkController.java @@ -22,6 +22,7 @@ import org.apache.pdfbox.pdmodel.graphics.state.PDExtendedGraphicsState; import org.apache.pdfbox.util.Matrix; import org.springframework.core.io.ClassPathResource; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestPart; @@ -32,6 +33,7 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.tags.Tag; +import stirling.software.SPDF.model.api.security.AddWatermarkRequest; import stirling.software.SPDF.utils.WebResponseUtils; @RestController @@ -40,22 +42,17 @@ public class WatermarkController { @PostMapping(consumes = "multipart/form-data", value = "/add-watermark") @Operation(summary = "Add watermark to a PDF file", description = "This endpoint adds a watermark to a given PDF file. Users can specify the watermark type (text or image), rotation, opacity, width spacer, and height spacer. Input:PDF Output:PDF Type:SISO") - public ResponseEntity addWatermark( - @RequestPart(required = true, value = "fileInput") @Parameter(description = "The input PDF file to add a watermark") MultipartFile pdfFile, - @RequestParam(required = true) @Parameter(description = "The watermark type (text or image)") String watermarkType, - @RequestParam(required = false) @Parameter(description = "The watermark text") String watermarkText, - @RequestPart(required = false) @Parameter(description = "The watermark image") MultipartFile watermarkImage, - - @RequestParam(defaultValue = "roman", name = "alphabet") @Parameter(description = "The selected alphabet", - schema = @Schema(type = "string", - allowableValues = {"roman","arabic","japanese","korean","chinese"}, - defaultValue = "roman")) String alphabet, - @RequestParam(defaultValue = "30", name = "fontSize") @Parameter(description = "The font size of the watermark text", example = "30") float fontSize, - @RequestParam(defaultValue = "0", name = "rotation") @Parameter(description = "The rotation of the watermark in degrees", example = "0") float rotation, - @RequestParam(defaultValue = "0.5", name = "opacity") @Parameter(description = "The opacity of the watermark (0.0 - 1.0)", example = "0.5") float opacity, - @RequestParam(defaultValue = "50", name = "widthSpacer") @Parameter(description = "The width spacer between watermark elements", example = "50") int widthSpacer, - @RequestParam(defaultValue = "50", name = "heightSpacer") @Parameter(description = "The height spacer between watermark elements", example = "50") int heightSpacer) - throws IOException, Exception { + public ResponseEntity addWatermark(@ModelAttribute AddWatermarkRequest request) throws IOException, Exception { + MultipartFile pdfFile = request.getFileInput(); + String watermarkType = request.getWatermarkType(); + String watermarkText = request.getWatermarkText(); + MultipartFile watermarkImage = request.getWatermarkImage(); + String alphabet = request.getAlphabet(); + float fontSize = request.getFontSize(); + float rotation = request.getRotation(); + float opacity = request.getOpacity(); + int widthSpacer = request.getWidthSpacer(); + int heightSpacer = request.getHeightSpacer(); // Load the input PDF PDDocument document = PDDocument.load(pdfFile.getInputStream()); diff --git a/src/main/java/stirling/software/SPDF/model/api/HandleDataRequest.java b/src/main/java/stirling/software/SPDF/model/api/HandleDataRequest.java new file mode 100644 index 00000000..d22c8f67 --- /dev/null +++ b/src/main/java/stirling/software/SPDF/model/api/HandleDataRequest.java @@ -0,0 +1,15 @@ +package stirling.software.SPDF.model.api; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.web.multipart.MultipartFile; + +@Data +public class HandleDataRequest { + + @Schema(description = "The input files") + private MultipartFile[] fileInputs; + + @Schema(description = "JSON String") + private String jsonString; +} diff --git a/src/main/java/stirling/software/SPDF/model/api/misc/AddPageNumbersRequest.java b/src/main/java/stirling/software/SPDF/model/api/misc/AddPageNumbersRequest.java new file mode 100644 index 00000000..e258b59a --- /dev/null +++ b/src/main/java/stirling/software/SPDF/model/api/misc/AddPageNumbersRequest.java @@ -0,0 +1,26 @@ +package stirling.software.SPDF.model.api.misc; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import stirling.software.SPDF.model.api.PDFWithPageNums; + +import org.springframework.web.multipart.MultipartFile; + +@Data +public class AddPageNumbersRequest extends PDFWithPageNums { + + @Schema(description = "Custom margin: small/medium/large", allowableValues = {"small", "medium", "large"}) + private String customMargin; + + @Schema(description = "Position: 1 of 9 positions", minimum = "1", maximum = "9") + private int position; + + @Schema(description = "Starting number", minimum = "1") + private int startingNumber; + + @Schema(description = "Which pages to number, default all") + private String pagesToNumber; + + @Schema(description = "Custom text: defaults to just number but can have things like \"Page {n} of {p}\"") + private String customText; +} diff --git a/src/main/java/stirling/software/SPDF/model/api/misc/OverlayImageRequest.java b/src/main/java/stirling/software/SPDF/model/api/misc/OverlayImageRequest.java new file mode 100644 index 00000000..29350519 --- /dev/null +++ b/src/main/java/stirling/software/SPDF/model/api/misc/OverlayImageRequest.java @@ -0,0 +1,23 @@ +package stirling.software.SPDF.model.api.misc; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import stirling.software.SPDF.model.api.PDFFile; + +import org.springframework.web.multipart.MultipartFile; + +@Data +public class OverlayImageRequest extends PDFFile { + + @Schema(description = "The image file to be overlaid onto the PDF.") + private MultipartFile imageFile; + + @Schema(description = "The x-coordinate at which to place the top-left corner of the image.", example = "0") + private float x; + + @Schema(description = "The y-coordinate at which to place the top-left corner of the image.", example = "0") + private float y; + + @Schema(description = "Whether to overlay the image onto every page of the PDF.", example = "false") + private boolean everyPage; +} diff --git a/src/main/java/stirling/software/SPDF/model/api/misc/ProcessPdfWithOcrRequest.java b/src/main/java/stirling/software/SPDF/model/api/misc/ProcessPdfWithOcrRequest.java new file mode 100644 index 00000000..a332a7ff --- /dev/null +++ b/src/main/java/stirling/software/SPDF/model/api/misc/ProcessPdfWithOcrRequest.java @@ -0,0 +1,36 @@ +package stirling.software.SPDF.model.api.misc; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.web.multipart.MultipartFile; +import stirling.software.SPDF.model.api.PDFFile; + +import java.util.List; + +@Data +public class ProcessPdfWithOcrRequest extends PDFFile { + + @Schema(description = "List of languages to use in OCR processing") + private List selectedLanguages; + + @Schema(description = "Include OCR text in a sidecar text file if set to true") + private Boolean sidecar; + + @Schema(description = "Deskew the input file if set to true") + private Boolean deskew; + + @Schema(description = "Clean the input file if set to true") + private Boolean clean; + + @Schema(description = "Clean the final output if set to true") + private Boolean cleanFinal; + + @Schema(description = "Specify the OCR type, e.g., 'skip-text', 'force-ocr', or 'Normal'", allowableValues = {"skip-text", "force-ocr", "Normal"}) + private String ocrType; + + @Schema(description = "Specify the OCR render type, either 'hocr' or 'sandwich'", allowableValues = {"hocr", "sandwich"}, defaultValue = "hocr") + private String ocrRenderType; + + @Schema(description = "Remove images from the output PDF if set to true") + private Boolean removeImagesAfter; +} diff --git a/src/main/java/stirling/software/SPDF/model/api/security/AddPasswordRequest.java b/src/main/java/stirling/software/SPDF/model/api/security/AddPasswordRequest.java new file mode 100644 index 00000000..60bbcc6b --- /dev/null +++ b/src/main/java/stirling/software/SPDF/model/api/security/AddPasswordRequest.java @@ -0,0 +1,43 @@ +package stirling.software.SPDF.model.api.security; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.web.multipart.MultipartFile; +import stirling.software.SPDF.model.api.PDFFile; + +@Data +public class AddPasswordRequest extends PDFFile { + + @Schema(description = "The owner password to be added to the PDF file (Restricts what can be done with the document once it is opened)", defaultValue = "") + private String ownerPassword; + + @Schema(description = "The password to be added to the PDF file (Restricts the opening of the document itself.)", defaultValue = "") + private String password; + + @Schema(description = "The length of the encryption key", allowableValues = {"40", "128", "256"}, defaultValue = "256") + private int keyLength; + + @Schema(description = "Whether the document assembly is allowed", example = "false") + private boolean canAssembleDocument; + + @Schema(description = "Whether content extraction for accessibility is allowed", example = "false") + private boolean canExtractContent; + + @Schema(description = "Whether content extraction for accessibility is allowed", example = "false") + private boolean canExtractForAccessibility; + + @Schema(description = "Whether form filling is allowed", example = "false") + private boolean canFillInForm; + + @Schema(description = "Whether the document modification is allowed", example = "false") + private boolean canModify; + + @Schema(description = "Whether modification of annotations is allowed", example = "false") + private boolean canModifyAnnotations; + + @Schema(description = "Whether printing of the document is allowed", example = "false") + private boolean canPrint; + + @Schema(description = "Whether faithful printing is allowed", example = "false") + private boolean canPrintFaithful; +} diff --git a/src/main/java/stirling/software/SPDF/model/api/security/AddWatermarkRequest.java b/src/main/java/stirling/software/SPDF/model/api/security/AddWatermarkRequest.java new file mode 100644 index 00000000..42d34af4 --- /dev/null +++ b/src/main/java/stirling/software/SPDF/model/api/security/AddWatermarkRequest.java @@ -0,0 +1,39 @@ +package stirling.software.SPDF.model.api.security; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.web.multipart.MultipartFile; +import stirling.software.SPDF.model.api.PDFFile; + +@Data +public class AddWatermarkRequest extends PDFFile { + + @Schema(description = "The watermark type (text or image)", required = true) + private String watermarkType; + + @Schema(description = "The watermark text") + private String watermarkText; + + @Schema(description = "The watermark image") + private MultipartFile watermarkImage; + + @Schema(description = "The selected alphabet", + allowableValues = {"roman", "arabic", "japanese", "korean", "chinese"}, + defaultValue = "roman") + private String alphabet; + + @Schema(description = "The font size of the watermark text", example = "30") + private float fontSize; + + @Schema(description = "The rotation of the watermark in degrees", example = "0") + private float rotation; + + @Schema(description = "The opacity of the watermark (0.0 - 1.0)", example = "0.5") + private float opacity; + + @Schema(description = "The width spacer between watermark elements", example = "50") + private int widthSpacer; + + @Schema(description = "The height spacer between watermark elements", example = "50") + private int heightSpacer; +} diff --git a/src/main/java/stirling/software/SPDF/model/api/security/PDFPasswordRequest.java b/src/main/java/stirling/software/SPDF/model/api/security/PDFPasswordRequest.java new file mode 100644 index 00000000..c1acd32c --- /dev/null +++ b/src/main/java/stirling/software/SPDF/model/api/security/PDFPasswordRequest.java @@ -0,0 +1,13 @@ +package stirling.software.SPDF.model.api.security; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.web.multipart.MultipartFile; +import stirling.software.SPDF.model.api.PDFFile; + +@Data +public class PDFPasswordRequest extends PDFFile { + + @Schema(description = "The password of the PDF file", required = true) + private String password; +} diff --git a/src/main/java/stirling/software/SPDF/model/api/security/RedactPdfRequest.java b/src/main/java/stirling/software/SPDF/model/api/security/RedactPdfRequest.java new file mode 100644 index 00000000..fff02ff5 --- /dev/null +++ b/src/main/java/stirling/software/SPDF/model/api/security/RedactPdfRequest.java @@ -0,0 +1,28 @@ +package stirling.software.SPDF.model.api.security; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.web.multipart.MultipartFile; +import stirling.software.SPDF.model.api.PDFFile; + +@Data +public class RedactPdfRequest extends PDFFile { + + @Schema(description = "List of text to redact from the PDF", type = "string", required = true) + private String listOfText; + + @Schema(description = "Whether to use regex for the listOfText", defaultValue = "false") + private boolean useRegex; + + @Schema(description = "Whether to use whole word search", defaultValue = "false") + private boolean wholeWordSearch; + + @Schema(description = "The color for redaction", defaultValue = "#000000") + private String redactColor; + + @Schema(description = "Custom padding for redaction", type = "number") + private float customPadding; + + @Schema(description = "Convert the redacted PDF to an image", defaultValue = "false") + private boolean convertPDFToImage; +} diff --git a/src/main/java/stirling/software/SPDF/model/api/security/SanitizePdfRequest.java b/src/main/java/stirling/software/SPDF/model/api/security/SanitizePdfRequest.java new file mode 100644 index 00000000..280f2021 --- /dev/null +++ b/src/main/java/stirling/software/SPDF/model/api/security/SanitizePdfRequest.java @@ -0,0 +1,25 @@ +package stirling.software.SPDF.model.api.security; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.web.multipart.MultipartFile; +import stirling.software.SPDF.model.api.PDFFile; + +@Data +public class SanitizePdfRequest extends PDFFile { + + @Schema(description = "Remove JavaScript actions from the PDF", defaultValue = "false") + private Boolean removeJavaScript; + + @Schema(description = "Remove embedded files from the PDF", defaultValue = "false") + private Boolean removeEmbeddedFiles; + + @Schema(description = "Remove metadata from the PDF", defaultValue = "false") + private Boolean removeMetadata; + + @Schema(description = "Remove links from the PDF", defaultValue = "false") + private Boolean removeLinks; + + @Schema(description = "Remove fonts from the PDF", defaultValue = "false") + private Boolean removeFonts; +} diff --git a/src/main/java/stirling/software/SPDF/model/api/security/SignPDFWithCertRequest.java b/src/main/java/stirling/software/SPDF/model/api/security/SignPDFWithCertRequest.java new file mode 100644 index 00000000..5344bf4d --- /dev/null +++ b/src/main/java/stirling/software/SPDF/model/api/security/SignPDFWithCertRequest.java @@ -0,0 +1,40 @@ +package stirling.software.SPDF.model.api.security; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.web.multipart.MultipartFile; +import stirling.software.SPDF.model.api.PDFFile; + +@Data +public class SignPDFWithCertRequest extends PDFFile { + + @Schema(description = "The type of the digital certificate", allowableValues = { "PKCS12", "PEM" }) + private String certType; + + @Schema(description = "The private key for the digital certificate (required for PEM type certificates)") + private MultipartFile privateKeyFile; + + @Schema(description = "The digital certificate (required for PEM type certificates)") + private MultipartFile certFile; + + @Schema(description = "The PKCS12 keystore file (required for PKCS12 type certificates)") + private MultipartFile p12File; + + @Schema(description = "The password for the keystore or the private key") + private String password; + + @Schema(description = "Whether to visually show the signature in the PDF file") + private Boolean showSignature; + + @Schema(description = "The reason for signing the PDF") + private String reason; + + @Schema(description = "The location where the PDF is signed") + private String location; + + @Schema(description = "The name of the signer") + private String name; + + @Schema(description = "The page number where the signature should be visible. This is required if showSignature is set to true") + private Integer pageNumber; +}