mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2025-06-22 15:35:03 +00:00
changed response type, updated tests
This commit is contained in:
parent
db8de7c087
commit
244cbe36ff
@ -1242,15 +1242,13 @@ public class EmlToPdf {
|
|||||||
document, new ByteArrayInputStream(attachment.getData()));
|
document, new ByteArrayInputStream(attachment.getData()));
|
||||||
embeddedFile.setSize(attachment.getData().length);
|
embeddedFile.setSize(attachment.getData().length);
|
||||||
embeddedFile.setCreationDate(new GregorianCalendar());
|
embeddedFile.setCreationDate(new GregorianCalendar());
|
||||||
if (attachment.getContentType() != null) {
|
|
||||||
embeddedFile.setSubtype(attachment.getContentType());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create file specification
|
// Create file specification
|
||||||
PDComplexFileSpecification fileSpec = new PDComplexFileSpecification();
|
PDComplexFileSpecification fileSpec = new PDComplexFileSpecification();
|
||||||
fileSpec.setFile(uniqueFilename);
|
fileSpec.setFile(uniqueFilename);
|
||||||
fileSpec.setEmbeddedFile(embeddedFile);
|
fileSpec.setEmbeddedFile(embeddedFile);
|
||||||
if (attachment.getContentType() != null) {
|
if (attachment.getContentType() != null) {
|
||||||
|
embeddedFile.setSubtype(attachment.getContentType());
|
||||||
fileSpec.setFileDescription("Email attachment: " + uniqueFilename);
|
fileSpec.setFileDescription("Email attachment: " + uniqueFilename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,10 +60,11 @@ public class AttachmentsController {
|
|||||||
|
|
||||||
// Add attachments
|
// Add attachments
|
||||||
catalog.setNames(documentNames);
|
catalog.setNames(documentNames);
|
||||||
|
byte[] output =
|
||||||
pdfAttachmentService.addAttachment(document, embeddedFilesTree, attachments);
|
pdfAttachmentService.addAttachment(document, embeddedFilesTree, attachments);
|
||||||
|
|
||||||
return WebResponseUtils.pdfDocToWebResponse(
|
return WebResponseUtils.bytesToWebResponse(
|
||||||
document,
|
output,
|
||||||
Filenames.toSimpleFileName(pdfFile.getOriginalFilename())
|
Filenames.toSimpleFileName(pdfFile.getOriginalFilename())
|
||||||
.replaceFirst("[.][^.]+$", "")
|
.replaceFirst("[.][^.]+$", "")
|
||||||
+ "_with_attachments.pdf");
|
+ "_with_attachments.pdf");
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package stirling.software.SPDF.service;
|
package stirling.software.SPDF.service;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.GregorianCalendar;
|
import java.util.GregorianCalendar;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -13,6 +14,7 @@ import org.apache.pdfbox.pdmodel.PageMode;
|
|||||||
import org.apache.pdfbox.pdmodel.common.filespecification.PDComplexFileSpecification;
|
import org.apache.pdfbox.pdmodel.common.filespecification.PDComplexFileSpecification;
|
||||||
import org.apache.pdfbox.pdmodel.common.filespecification.PDEmbeddedFile;
|
import org.apache.pdfbox.pdmodel.common.filespecification.PDEmbeddedFile;
|
||||||
import org.apache.pdfbox.pdmodel.encryption.AccessPermission;
|
import org.apache.pdfbox.pdmodel.encryption.AccessPermission;
|
||||||
|
import org.apache.pdfbox.pdmodel.encryption.StandardProtectionPolicy;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
@ -25,7 +27,7 @@ import stirling.software.common.util.PDFAttachmentUtils;
|
|||||||
public class PDFAttachmentService implements PDFAttachmentServiceInterface {
|
public class PDFAttachmentService implements PDFAttachmentServiceInterface {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addAttachment(
|
public byte[] addAttachment(
|
||||||
PDDocument document,
|
PDDocument document,
|
||||||
PDEmbeddedFilesNameTreeNode embeddedFilesTree,
|
PDEmbeddedFilesNameTreeNode embeddedFilesTree,
|
||||||
List<MultipartFile> attachments)
|
List<MultipartFile> attachments)
|
||||||
@ -34,6 +36,7 @@ public class PDFAttachmentService implements PDFAttachmentServiceInterface {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
existingNames = embeddedFilesTree.getNames();
|
existingNames = embeddedFilesTree.getNames();
|
||||||
|
|
||||||
if (existingNames == null) {
|
if (existingNames == null) {
|
||||||
log.debug("No existing embedded files found, creating new names map.");
|
log.debug("No existing embedded files found, creating new names map.");
|
||||||
existingNames = new HashMap<>();
|
existingNames = new HashMap<>();
|
||||||
@ -45,58 +48,54 @@ public class PDFAttachmentService implements PDFAttachmentServiceInterface {
|
|||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
grantAccessPermissions(document);
|
||||||
final Map<String, PDComplexFileSpecification> existingEmbeddedFiles = existingNames;
|
final Map<String, PDComplexFileSpecification> existingEmbeddedFiles = existingNames;
|
||||||
|
|
||||||
attachments.forEach(
|
attachments.forEach(
|
||||||
attachment -> {
|
attachment -> {
|
||||||
// Create attachments specification
|
String filename = attachment.getOriginalFilename();
|
||||||
PDComplexFileSpecification fileSpecification = new PDComplexFileSpecification();
|
|
||||||
fileSpecification.setFile(attachment.getOriginalFilename());
|
|
||||||
fileSpecification.setFileUnicode(attachment.getOriginalFilename());
|
|
||||||
fileSpecification.setFileDescription(
|
|
||||||
"Embedded attachment: " + attachment.getOriginalFilename());
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Create embedded attachment
|
|
||||||
PDEmbeddedFile embeddedFile =
|
PDEmbeddedFile embeddedFile =
|
||||||
new PDEmbeddedFile(document, attachment.getInputStream());
|
new PDEmbeddedFile(document, attachment.getInputStream());
|
||||||
embeddedFile.setSize((int) attachment.getSize());
|
embeddedFile.setSize((int) attachment.getSize());
|
||||||
embeddedFile.setCreationDate(new GregorianCalendar());
|
embeddedFile.setCreationDate(new GregorianCalendar());
|
||||||
embeddedFile.setModDate(new GregorianCalendar());
|
embeddedFile.setModDate(new GregorianCalendar());
|
||||||
|
|
||||||
// Set MIME type if available
|
|
||||||
String contentType = attachment.getContentType();
|
String contentType = attachment.getContentType();
|
||||||
if (StringUtils.isNotBlank(contentType)) {
|
if (StringUtils.isNotBlank(contentType)) {
|
||||||
embeddedFile.setSubtype(contentType);
|
embeddedFile.setSubtype(contentType);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Associate embedded attachment with file specification
|
// Create attachments specification and associate embedded attachment with
|
||||||
|
// file
|
||||||
|
PDComplexFileSpecification fileSpecification =
|
||||||
|
new PDComplexFileSpecification();
|
||||||
|
fileSpecification.setFile(filename);
|
||||||
|
fileSpecification.setFileUnicode(filename);
|
||||||
|
fileSpecification.setFileDescription("Embedded attachment: " + filename);
|
||||||
embeddedFile.setFile(fileSpecification);
|
embeddedFile.setFile(fileSpecification);
|
||||||
fileSpecification.setEmbeddedFile(embeddedFile);
|
fileSpecification.setEmbeddedFile(embeddedFile);
|
||||||
fileSpecification.setEmbeddedFileUnicode(embeddedFile);
|
fileSpecification.setEmbeddedFileUnicode(embeddedFile);
|
||||||
|
|
||||||
// Add to the existing files map
|
// Add to the existing files map
|
||||||
existingEmbeddedFiles.put(
|
existingEmbeddedFiles.put(filename, fileSpecification);
|
||||||
attachment.getOriginalFilename(), fileSpecification);
|
|
||||||
|
|
||||||
log.info(
|
log.info("Added attachment: {} ({} bytes)", filename, attachment.getSize());
|
||||||
"Added attachment: {} ({} bytes)",
|
|
||||||
attachment.getOriginalFilename(),
|
|
||||||
attachment.getSize());
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.warn(
|
log.warn("Failed to create embedded file for attachment: {}", filename, e);
|
||||||
"Failed to create embedded file for attachment: {}",
|
|
||||||
attachment.getOriginalFilename(),
|
|
||||||
e);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
embeddedFilesTree.setNames(existingNames);
|
embeddedFilesTree.setNames(existingNames);
|
||||||
|
|
||||||
grantAccessPermissions(document);
|
|
||||||
PDFAttachmentUtils.setCatalogViewerPreferences(document, PageMode.USE_ATTACHMENTS);
|
PDFAttachmentUtils.setCatalogViewerPreferences(document, PageMode.USE_ATTACHMENTS);
|
||||||
|
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||||
|
document.save(output);
|
||||||
|
|
||||||
|
return output.toByteArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void grantAccessPermissions(PDDocument document) {
|
private void grantAccessPermissions(PDDocument document) {
|
||||||
|
try {
|
||||||
AccessPermission currentPermissions = document.getCurrentAccessPermission();
|
AccessPermission currentPermissions = document.getCurrentAccessPermission();
|
||||||
|
|
||||||
currentPermissions.setCanAssembleDocument(true);
|
currentPermissions.setCanAssembleDocument(true);
|
||||||
@ -109,5 +108,18 @@ public class PDFAttachmentService implements PDFAttachmentServiceInterface {
|
|||||||
currentPermissions.setCanExtractContent(true);
|
currentPermissions.setCanExtractContent(true);
|
||||||
currentPermissions.setCanExtractForAccessibility(true);
|
currentPermissions.setCanExtractForAccessibility(true);
|
||||||
currentPermissions.setCanModifyAnnotations(true);
|
currentPermissions.setCanModifyAnnotations(true);
|
||||||
|
|
||||||
|
var protectionPolicy = new StandardProtectionPolicy(null, null, currentPermissions);
|
||||||
|
|
||||||
|
if (!document.isAllSecurityToBeRemoved()) {
|
||||||
|
document.setAllSecurityToBeRemoved(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
document.protect(protectionPolicy);
|
||||||
|
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||||
|
document.save(output);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ import org.springframework.web.multipart.MultipartFile;
|
|||||||
|
|
||||||
public interface PDFAttachmentServiceInterface {
|
public interface PDFAttachmentServiceInterface {
|
||||||
|
|
||||||
void addAttachment(
|
byte[] addAttachment(
|
||||||
PDDocument document,
|
PDDocument document,
|
||||||
PDEmbeddedFilesNameTreeNode efTree,
|
PDEmbeddedFilesNameTreeNode efTree,
|
||||||
List<MultipartFile> attachments)
|
List<MultipartFile> attachments)
|
||||||
|
@ -61,16 +61,19 @@ class AttachmentsControllerTest {
|
|||||||
@Test
|
@Test
|
||||||
void addAttachments_WithExistingNames() throws IOException {
|
void addAttachments_WithExistingNames() throws IOException {
|
||||||
List<MultipartFile> attachments = List.of(attachment1, attachment2);
|
List<MultipartFile> attachments = List.of(attachment1, attachment2);
|
||||||
|
byte[] expectedOutput = "modified PDF content".getBytes();
|
||||||
|
|
||||||
when(pdfDocumentFactory.load(pdfFile, false)).thenReturn(mockDocument);
|
when(pdfDocumentFactory.load(pdfFile, false)).thenReturn(mockDocument);
|
||||||
when(mockDocument.getDocumentCatalog()).thenReturn(mockCatalog);
|
when(mockDocument.getDocumentCatalog()).thenReturn(mockCatalog);
|
||||||
when(mockCatalog.getNames()).thenReturn(mockNameDict);
|
when(mockCatalog.getNames()).thenReturn(mockNameDict);
|
||||||
when(mockNameDict.getEmbeddedFiles()).thenReturn(mockEmbeddedFilesTree);
|
when(mockNameDict.getEmbeddedFiles()).thenReturn(mockEmbeddedFilesTree);
|
||||||
|
when(pdfAttachmentService.addAttachment(mockDocument, mockEmbeddedFilesTree, attachments)).thenReturn(expectedOutput);
|
||||||
|
|
||||||
ResponseEntity<byte[]> response = attachmentsController.addAttachments(pdfFile, attachments);
|
ResponseEntity<byte[]> response = attachmentsController.addAttachments(pdfFile, attachments);
|
||||||
|
|
||||||
assertNotNull(response);
|
assertNotNull(response);
|
||||||
assertEquals(HttpStatus.OK, response.getStatusCode());
|
assertEquals(HttpStatus.OK, response.getStatusCode());
|
||||||
|
assertNotNull(response.getBody());
|
||||||
verify(pdfDocumentFactory).load(pdfFile, false);
|
verify(pdfDocumentFactory).load(pdfFile, false);
|
||||||
verify(mockCatalog).setNames(mockNameDict);
|
verify(mockCatalog).setNames(mockNameDict);
|
||||||
verify(pdfAttachmentService).addAttachment(mockDocument, mockEmbeddedFilesTree, attachments);
|
verify(pdfAttachmentService).addAttachment(mockDocument, mockEmbeddedFilesTree, attachments);
|
||||||
@ -79,14 +82,17 @@ class AttachmentsControllerTest {
|
|||||||
@Test
|
@Test
|
||||||
void addAttachments_WithoutExistingNames() throws IOException {
|
void addAttachments_WithoutExistingNames() throws IOException {
|
||||||
List<MultipartFile> attachments = List.of(attachment1);
|
List<MultipartFile> attachments = List.of(attachment1);
|
||||||
|
byte[] expectedOutput = "modified PDF content".getBytes();
|
||||||
|
|
||||||
try (PDDocument realDocument = new PDDocument()) {
|
try (PDDocument realDocument = new PDDocument()) {
|
||||||
when(pdfDocumentFactory.load(pdfFile, false)).thenReturn(realDocument);
|
when(pdfDocumentFactory.load(pdfFile, false)).thenReturn(realDocument);
|
||||||
|
when(pdfAttachmentService.addAttachment(eq(realDocument), any(PDEmbeddedFilesNameTreeNode.class), eq(attachments))).thenReturn(expectedOutput);
|
||||||
|
|
||||||
ResponseEntity<byte[]> response = attachmentsController.addAttachments(pdfFile, attachments);
|
ResponseEntity<byte[]> response = attachmentsController.addAttachments(pdfFile, attachments);
|
||||||
|
|
||||||
assertNotNull(response);
|
assertNotNull(response);
|
||||||
assertEquals(HttpStatus.OK, response.getStatusCode());
|
assertEquals(HttpStatus.OK, response.getStatusCode());
|
||||||
|
assertNotNull(response.getBody());
|
||||||
verify(pdfDocumentFactory).load(pdfFile, false);
|
verify(pdfDocumentFactory).load(pdfFile, false);
|
||||||
verify(pdfAttachmentService).addAttachment(eq(realDocument), any(PDEmbeddedFilesNameTreeNode.class), eq(attachments));
|
verify(pdfAttachmentService).addAttachment(eq(realDocument), any(PDEmbeddedFilesNameTreeNode.class), eq(attachments));
|
||||||
}
|
}
|
||||||
@ -113,7 +119,7 @@ class AttachmentsControllerTest {
|
|||||||
when(mockDocument.getDocumentCatalog()).thenReturn(mockCatalog);
|
when(mockDocument.getDocumentCatalog()).thenReturn(mockCatalog);
|
||||||
when(mockCatalog.getNames()).thenReturn(mockNameDict);
|
when(mockCatalog.getNames()).thenReturn(mockNameDict);
|
||||||
when(mockNameDict.getEmbeddedFiles()).thenReturn(mockEmbeddedFilesTree);
|
when(mockNameDict.getEmbeddedFiles()).thenReturn(mockEmbeddedFilesTree);
|
||||||
doThrow(ioException).when(pdfAttachmentService).addAttachment(mockDocument, mockEmbeddedFilesTree, attachments);
|
when(pdfAttachmentService.addAttachment(mockDocument, mockEmbeddedFilesTree, attachments)).thenThrow(ioException);
|
||||||
|
|
||||||
assertThrows(IOException.class, () -> attachmentsController.addAttachments(pdfFile, attachments));
|
assertThrows(IOException.class, () -> attachmentsController.addAttachments(pdfFile, attachments));
|
||||||
verify(pdfAttachmentService).addAttachment(mockDocument, mockEmbeddedFilesTree, attachments);
|
verify(pdfAttachmentService).addAttachment(mockDocument, mockEmbeddedFilesTree, attachments);
|
||||||
@ -162,16 +168,19 @@ class AttachmentsControllerTest {
|
|||||||
@Test
|
@Test
|
||||||
void addAttachments_EmptyAttachmentsList() throws IOException {
|
void addAttachments_EmptyAttachmentsList() throws IOException {
|
||||||
List<MultipartFile> emptyAttachments = List.of();
|
List<MultipartFile> emptyAttachments = List.of();
|
||||||
|
byte[] expectedOutput = "PDF content without new attachments".getBytes();
|
||||||
|
|
||||||
when(pdfDocumentFactory.load(pdfFile, false)).thenReturn(mockDocument);
|
when(pdfDocumentFactory.load(pdfFile, false)).thenReturn(mockDocument);
|
||||||
when(mockDocument.getDocumentCatalog()).thenReturn(mockCatalog);
|
when(mockDocument.getDocumentCatalog()).thenReturn(mockCatalog);
|
||||||
when(mockCatalog.getNames()).thenReturn(mockNameDict);
|
when(mockCatalog.getNames()).thenReturn(mockNameDict);
|
||||||
when(mockNameDict.getEmbeddedFiles()).thenReturn(mockEmbeddedFilesTree);
|
when(mockNameDict.getEmbeddedFiles()).thenReturn(mockEmbeddedFilesTree);
|
||||||
|
when(pdfAttachmentService.addAttachment(mockDocument, mockEmbeddedFilesTree, emptyAttachments)).thenReturn(expectedOutput);
|
||||||
|
|
||||||
ResponseEntity<byte[]> response = attachmentsController.addAttachments(pdfFile, emptyAttachments);
|
ResponseEntity<byte[]> response = attachmentsController.addAttachments(pdfFile, emptyAttachments);
|
||||||
|
|
||||||
assertNotNull(response);
|
assertNotNull(response);
|
||||||
assertEquals(HttpStatus.OK, response.getStatusCode());
|
assertEquals(HttpStatus.OK, response.getStatusCode());
|
||||||
|
assertNotNull(response.getBody());
|
||||||
verify(pdfAttachmentService).addAttachment(mockDocument, mockEmbeddedFilesTree, emptyAttachments);
|
verify(pdfAttachmentService).addAttachment(mockDocument, mockEmbeddedFilesTree, emptyAttachments);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,16 +188,19 @@ class AttachmentsControllerTest {
|
|||||||
void addAttachments_NullFilename() throws IOException {
|
void addAttachments_NullFilename() throws IOException {
|
||||||
MockMultipartFile attachmentWithNullName = new MockMultipartFile("attachment", null, "text/plain", "content".getBytes());
|
MockMultipartFile attachmentWithNullName = new MockMultipartFile("attachment", null, "text/plain", "content".getBytes());
|
||||||
List<MultipartFile> attachments = List.of(attachmentWithNullName);
|
List<MultipartFile> attachments = List.of(attachmentWithNullName);
|
||||||
|
byte[] expectedOutput = "PDF with null filename attachment".getBytes();
|
||||||
|
|
||||||
when(pdfDocumentFactory.load(pdfFile, false)).thenReturn(mockDocument);
|
when(pdfDocumentFactory.load(pdfFile, false)).thenReturn(mockDocument);
|
||||||
when(mockDocument.getDocumentCatalog()).thenReturn(mockCatalog);
|
when(mockDocument.getDocumentCatalog()).thenReturn(mockCatalog);
|
||||||
when(mockCatalog.getNames()).thenReturn(mockNameDict);
|
when(mockCatalog.getNames()).thenReturn(mockNameDict);
|
||||||
when(mockNameDict.getEmbeddedFiles()).thenReturn(mockEmbeddedFilesTree);
|
when(mockNameDict.getEmbeddedFiles()).thenReturn(mockEmbeddedFilesTree);
|
||||||
|
when(pdfAttachmentService.addAttachment(mockDocument, mockEmbeddedFilesTree, attachments)).thenReturn(expectedOutput);
|
||||||
|
|
||||||
ResponseEntity<byte[]> response = attachmentsController.addAttachments(pdfFile, attachments);
|
ResponseEntity<byte[]> response = attachmentsController.addAttachments(pdfFile, attachments);
|
||||||
|
|
||||||
assertNotNull(response);
|
assertNotNull(response);
|
||||||
assertEquals(HttpStatus.OK, response.getStatusCode());
|
assertEquals(HttpStatus.OK, response.getStatusCode());
|
||||||
|
assertNotNull(response.getBody());
|
||||||
verify(pdfAttachmentService).addAttachment(mockDocument, mockEmbeddedFilesTree, attachments);
|
verify(pdfAttachmentService).addAttachment(mockDocument, mockEmbeddedFilesTree, attachments);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,10 +7,14 @@ import java.util.List;
|
|||||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||||
import org.apache.pdfbox.pdmodel.PDEmbeddedFilesNameTreeNode;
|
import org.apache.pdfbox.pdmodel.PDEmbeddedFilesNameTreeNode;
|
||||||
import org.apache.pdfbox.pdmodel.common.filespecification.PDComplexFileSpecification;
|
import org.apache.pdfbox.pdmodel.common.filespecification.PDComplexFileSpecification;
|
||||||
|
import org.apache.pdfbox.pdmodel.encryption.AccessPermission;
|
||||||
|
import org.apache.pdfbox.pdmodel.encryption.StandardProtectionPolicy;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
import static org.mockito.ArgumentMatchers.anyMap;
|
import static org.mockito.ArgumentMatchers.anyMap;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
@ -39,8 +43,10 @@ class PDFAttachmentServiceTest {
|
|||||||
when(attachments.get(0).getSize()).thenReturn(12L);
|
when(attachments.get(0).getSize()).thenReturn(12L);
|
||||||
when(attachments.get(0).getContentType()).thenReturn("text/plain");
|
when(attachments.get(0).getContentType()).thenReturn("text/plain");
|
||||||
|
|
||||||
pdfAttachmentService.addAttachment(document, embeddedFilesTree, attachments);
|
byte[] result = pdfAttachmentService.addAttachment(document, embeddedFilesTree, attachments);
|
||||||
|
|
||||||
|
assertNotNull(result);
|
||||||
|
assertTrue(result.length > 0);
|
||||||
verify(embeddedFilesTree).setNames(anyMap());
|
verify(embeddedFilesTree).setNames(anyMap());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -58,8 +64,10 @@ class PDFAttachmentServiceTest {
|
|||||||
when(attachments.get(0).getSize()).thenReturn(15L);
|
when(attachments.get(0).getSize()).thenReturn(15L);
|
||||||
when(attachments.get(0).getContentType()).thenReturn("application/pdf");
|
when(attachments.get(0).getContentType()).thenReturn("application/pdf");
|
||||||
|
|
||||||
pdfAttachmentService.addAttachment(document, embeddedFilesTree, attachments);
|
byte[] result = pdfAttachmentService.addAttachment(document, embeddedFilesTree, attachments);
|
||||||
|
|
||||||
|
assertNotNull(result);
|
||||||
|
assertTrue(result.length > 0);
|
||||||
verify(embeddedFilesTree).setNames(anyMap());
|
verify(embeddedFilesTree).setNames(anyMap());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -78,8 +86,10 @@ class PDFAttachmentServiceTest {
|
|||||||
when(attachments.get(0).getSize()).thenReturn(25L);
|
when(attachments.get(0).getSize()).thenReturn(25L);
|
||||||
when(attachments.get(0).getContentType()).thenReturn("");
|
when(attachments.get(0).getContentType()).thenReturn("");
|
||||||
|
|
||||||
pdfAttachmentService.addAttachment(document, embeddedFilesTree, attachments);
|
byte[] result = pdfAttachmentService.addAttachment(document, embeddedFilesTree, attachments);
|
||||||
|
|
||||||
|
assertNotNull(result);
|
||||||
|
assertTrue(result.length > 0);
|
||||||
verify(embeddedFilesTree).setNames(anyMap());
|
verify(embeddedFilesTree).setNames(anyMap());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -111,8 +121,95 @@ class PDFAttachmentServiceTest {
|
|||||||
when(attachments.get(0).getInputStream()).thenThrow(ioException);
|
when(attachments.get(0).getInputStream()).thenThrow(ioException);
|
||||||
when(attachments.get(0).getSize()).thenReturn(10L);
|
when(attachments.get(0).getSize()).thenReturn(10L);
|
||||||
|
|
||||||
pdfAttachmentService.addAttachment(document, embeddedFilesTree, attachments);
|
byte[] result = pdfAttachmentService.addAttachment(document, embeddedFilesTree, attachments);
|
||||||
|
|
||||||
|
assertNotNull(result);
|
||||||
|
assertTrue(result.length > 0);
|
||||||
|
verify(embeddedFilesTree).setNames(anyMap());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void addAttachmentToPDF_WithProtectedDocument() throws IOException {
|
||||||
|
try (var document = new PDDocument()) {
|
||||||
|
// Create a document with restricted permissions (this simulates an encrypted/protected document)
|
||||||
|
AccessPermission ap = new AccessPermission();
|
||||||
|
ap.setCanExtractContent(false); // Restrict content extraction initially
|
||||||
|
var spp = new StandardProtectionPolicy("owner", "user", ap);
|
||||||
|
document.protect(spp);
|
||||||
|
|
||||||
|
var embeddedFilesTree = mock(PDEmbeddedFilesNameTreeNode.class);
|
||||||
|
var attachments = List.of(mock(MultipartFile.class));
|
||||||
|
var existingNames = new HashMap<String, PDComplexFileSpecification>();
|
||||||
|
|
||||||
|
when(embeddedFilesTree.getNames()).thenReturn(existingNames);
|
||||||
|
when(attachments.get(0).getOriginalFilename()).thenReturn("test.txt");
|
||||||
|
when(attachments.get(0).getInputStream()).thenReturn(
|
||||||
|
new ByteArrayInputStream("Test content".getBytes()));
|
||||||
|
when(attachments.get(0).getSize()).thenReturn(12L);
|
||||||
|
when(attachments.get(0).getContentType()).thenReturn("text/plain");
|
||||||
|
|
||||||
|
byte[] result = pdfAttachmentService.addAttachment(document, embeddedFilesTree, attachments);
|
||||||
|
|
||||||
|
assertNotNull(result);
|
||||||
|
assertTrue(result.length > 0);
|
||||||
|
verify(embeddedFilesTree).setNames(anyMap());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void addAttachmentToPDF_WithRestrictedPermissions() throws IOException {
|
||||||
|
try (var document = new PDDocument()) {
|
||||||
|
// Create a document with very restricted permissions that should block permission changes
|
||||||
|
AccessPermission ap = new AccessPermission();
|
||||||
|
ap.setCanModify(false);
|
||||||
|
ap.setCanAssembleDocument(false);
|
||||||
|
ap.setCanExtractContent(false);
|
||||||
|
var spp = new StandardProtectionPolicy("owner", "user", ap);
|
||||||
|
document.protect(spp);
|
||||||
|
|
||||||
|
var embeddedFilesTree = mock(PDEmbeddedFilesNameTreeNode.class);
|
||||||
|
var attachments = List.of(mock(MultipartFile.class));
|
||||||
|
var existingNames = new HashMap<String, PDComplexFileSpecification>();
|
||||||
|
|
||||||
|
when(embeddedFilesTree.getNames()).thenReturn(existingNames);
|
||||||
|
when(attachments.get(0).getOriginalFilename()).thenReturn("test.txt");
|
||||||
|
when(attachments.get(0).getInputStream()).thenReturn(
|
||||||
|
new ByteArrayInputStream("Test content".getBytes()));
|
||||||
|
when(attachments.get(0).getSize()).thenReturn(12L);
|
||||||
|
when(attachments.get(0).getContentType()).thenReturn("text/plain");
|
||||||
|
|
||||||
|
byte[] result = pdfAttachmentService.addAttachment(document, embeddedFilesTree, attachments);
|
||||||
|
|
||||||
|
assertNotNull(result);
|
||||||
|
assertTrue(result.length > 0);
|
||||||
|
verify(embeddedFilesTree).setNames(anyMap());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void addAttachmentToPDF_WithNonEncryptedDocument() throws IOException {
|
||||||
|
try (var document = new PDDocument()) {
|
||||||
|
var embeddedFilesTree = mock(PDEmbeddedFilesNameTreeNode.class);
|
||||||
|
var attachments = List.of(mock(MultipartFile.class));
|
||||||
|
var existingNames = new HashMap<String, PDComplexFileSpecification>();
|
||||||
|
|
||||||
|
when(embeddedFilesTree.getNames()).thenReturn(existingNames);
|
||||||
|
when(attachments.get(0).getOriginalFilename()).thenReturn("test.txt");
|
||||||
|
when(attachments.get(0).getInputStream()).thenReturn(
|
||||||
|
new ByteArrayInputStream("Test content".getBytes()));
|
||||||
|
when(attachments.get(0).getSize()).thenReturn(12L);
|
||||||
|
when(attachments.get(0).getContentType()).thenReturn("text/plain");
|
||||||
|
|
||||||
|
byte[] result = pdfAttachmentService.addAttachment(document, embeddedFilesTree, attachments);
|
||||||
|
|
||||||
|
assertNotNull(result);
|
||||||
|
assertTrue(result.length > 0);
|
||||||
|
// Verify permissions are set correctly for non-encrypted documents
|
||||||
|
AccessPermission permissions = document.getCurrentAccessPermission();
|
||||||
|
assertTrue(permissions.canExtractContent());
|
||||||
|
assertTrue(permissions.canExtractForAccessibility());
|
||||||
|
assertTrue(permissions.canModifyAnnotations());
|
||||||
verify(embeddedFilesTree).setNames(anyMap());
|
verify(embeddedFilesTree).setNames(anyMap());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user