mirror of
				https://github.com/Frooodle/Stirling-PDF.git
				synced 2025-11-01 01:21:18 +01:00 
			
		
		
		
	Merge branch 'main' into bump_googleJavaFormat_1_25_2
This commit is contained in:
		
						commit
						64f8348215
					
				@ -6,9 +6,6 @@ import java.net.Socket;
 | 
			
		||||
import java.util.concurrent.ExecutorService;
 | 
			
		||||
import java.util.concurrent.Executors;
 | 
			
		||||
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
 | 
			
		||||
import io.github.pixee.security.SystemCommand;
 | 
			
		||||
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
@ -16,7 +13,6 @@ import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
@Slf4j
 | 
			
		||||
public class LibreOfficeListener {
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(LibreOfficeListener.class);
 | 
			
		||||
    private static final long ACTIVITY_TIMEOUT = 20L * 60 * 1000; // 20 minutes
 | 
			
		||||
 | 
			
		||||
    private static final LibreOfficeListener INSTANCE = new LibreOfficeListener();
 | 
			
		||||
@ -87,7 +83,7 @@ public class LibreOfficeListener {
 | 
			
		||||
                Thread.sleep(1000);
 | 
			
		||||
            } catch (InterruptedException e) {
 | 
			
		||||
                Thread.currentThread().interrupt();
 | 
			
		||||
                logger.error("exception", e);
 | 
			
		||||
                log.error("exception", e);
 | 
			
		||||
            } // Check every 1 second
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -13,8 +13,6 @@ import java.util.Properties;
 | 
			
		||||
 | 
			
		||||
import javax.swing.*;
 | 
			
		||||
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Value;
 | 
			
		||||
import org.springframework.boot.SpringApplication;
 | 
			
		||||
@ -23,6 +21,7 @@ import org.springframework.core.env.Environment;
 | 
			
		||||
import org.springframework.scheduling.annotation.EnableScheduling;
 | 
			
		||||
 | 
			
		||||
import io.github.pixee.security.SystemCommand;
 | 
			
		||||
 | 
			
		||||
import jakarta.annotation.PostConstruct;
 | 
			
		||||
import jakarta.annotation.PreDestroy;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
@ -35,8 +34,6 @@ import stirling.software.SPDF.model.ApplicationProperties;
 | 
			
		||||
@Slf4j
 | 
			
		||||
public class SPdfApplication {
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(SPdfApplication.class);
 | 
			
		||||
 | 
			
		||||
    @Autowired private Environment env;
 | 
			
		||||
    @Autowired ApplicationProperties applicationProperties;
 | 
			
		||||
 | 
			
		||||
@ -95,7 +92,7 @@ public class SPdfApplication {
 | 
			
		||||
        if (Files.exists(Paths.get("configs/settings.yml"))) {
 | 
			
		||||
            propertyFiles.put("spring.config.additional-location", "file:configs/settings.yml");
 | 
			
		||||
        } else {
 | 
			
		||||
            logger.warn("External configuration file 'configs/settings.yml' does not exist.");
 | 
			
		||||
            log.warn("External configuration file 'configs/settings.yml' does not exist.");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (Files.exists(Paths.get("configs/custom_settings.yml"))) {
 | 
			
		||||
@ -108,7 +105,7 @@ public class SPdfApplication {
 | 
			
		||||
                    "spring.config.additional-location",
 | 
			
		||||
                    existingLocation + "file:configs/custom_settings.yml");
 | 
			
		||||
        } else {
 | 
			
		||||
            logger.warn("Custom configuration file 'configs/custom_settings.yml' does not exist.");
 | 
			
		||||
            log.warn("Custom configuration file 'configs/custom_settings.yml' does not exist.");
 | 
			
		||||
        }
 | 
			
		||||
        Properties finalProps = new Properties();
 | 
			
		||||
 | 
			
		||||
@ -131,16 +128,16 @@ public class SPdfApplication {
 | 
			
		||||
            Files.createDirectories(Path.of("customFiles/static/"));
 | 
			
		||||
            Files.createDirectories(Path.of("customFiles/templates/"));
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            logger.error("Error creating directories: {}", e.getMessage());
 | 
			
		||||
            log.error("Error creating directories: {}", e.getMessage());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        printStartupLogs();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static void printStartupLogs() {
 | 
			
		||||
        logger.info("Stirling-PDF Started.");
 | 
			
		||||
        log.info("Stirling-PDF Started.");
 | 
			
		||||
        String url = baseUrlStatic + ":" + getStaticPort();
 | 
			
		||||
        logger.info("Navigate to {}", url);
 | 
			
		||||
        log.info("Navigate to {}", url);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Autowired(required = false)
 | 
			
		||||
@ -169,11 +166,11 @@ public class SPdfApplication {
 | 
			
		||||
                        SystemCommand.runCommand(rt, "xdg-open " + url);
 | 
			
		||||
                    }
 | 
			
		||||
                } catch (Exception e) {
 | 
			
		||||
                    logger.error("Error opening browser: {}", e.getMessage());
 | 
			
		||||
                    log.error("Error opening browser: {}", e.getMessage());
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        logger.info("Running configs {}", applicationProperties.toString()); 
 | 
			
		||||
        log.info("Running configs {}", applicationProperties.toString());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @PreDestroy
 | 
			
		||||
 | 
			
		||||
@ -7,8 +7,6 @@ import java.nio.file.Paths;
 | 
			
		||||
import java.util.Properties;
 | 
			
		||||
import java.util.function.Predicate;
 | 
			
		||||
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
 | 
			
		||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 | 
			
		||||
@ -21,14 +19,14 @@ import org.springframework.core.io.Resource;
 | 
			
		||||
import org.springframework.core.io.ResourceLoader;
 | 
			
		||||
import org.thymeleaf.spring6.SpringTemplateEngine;
 | 
			
		||||
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import stirling.software.SPDF.model.ApplicationProperties;
 | 
			
		||||
 | 
			
		||||
@Configuration
 | 
			
		||||
@Lazy
 | 
			
		||||
@Slf4j
 | 
			
		||||
public class AppConfig {
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(AppConfig.class);
 | 
			
		||||
 | 
			
		||||
    @Autowired ApplicationProperties applicationProperties;
 | 
			
		||||
 | 
			
		||||
    @Bean
 | 
			
		||||
@ -61,7 +59,7 @@ public class AppConfig {
 | 
			
		||||
            props.load(resource.getInputStream());
 | 
			
		||||
            return props.getProperty("version");
 | 
			
		||||
        } catch (IOException e) {
 | 
			
		||||
            logger.error("exception", e);
 | 
			
		||||
            log.error("exception", e);
 | 
			
		||||
        }
 | 
			
		||||
        return "0.0.0";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -16,16 +16,15 @@ import org.simpleyaml.configuration.comments.CommentType;
 | 
			
		||||
import org.simpleyaml.configuration.file.YamlFile;
 | 
			
		||||
import org.simpleyaml.configuration.implementation.SimpleYamlImplementation;
 | 
			
		||||
import org.simpleyaml.configuration.implementation.snakeyaml.lib.DumperOptions;
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
import org.springframework.context.ApplicationContextInitializer;
 | 
			
		||||
import org.springframework.context.ConfigurableApplicationContext;
 | 
			
		||||
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
 | 
			
		||||
@Slf4j
 | 
			
		||||
public class ConfigInitializer
 | 
			
		||||
        implements ApplicationContextInitializer<ConfigurableApplicationContext> {
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(ConfigInitializer.class);
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void initialize(ConfigurableApplicationContext applicationContext) {
 | 
			
		||||
        try {
 | 
			
		||||
@ -149,7 +148,7 @@ public class ConfigInitializer
 | 
			
		||||
                    .commentSide(settingsTemplateFile.getComment(path, CommentType.SIDE));
 | 
			
		||||
        } else {
 | 
			
		||||
            // Log if the key is not found in both YAML files
 | 
			
		||||
            logger.info("Key not found in both YAML files: " + path);
 | 
			
		||||
            log.info("Key not found in both YAML files: " + path);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -7,19 +7,19 @@ import java.util.Set;
 | 
			
		||||
import java.util.concurrent.ConcurrentHashMap;
 | 
			
		||||
import java.util.stream.Collectors;
 | 
			
		||||
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Qualifier;
 | 
			
		||||
import org.springframework.context.annotation.DependsOn;
 | 
			
		||||
import org.springframework.stereotype.Service;
 | 
			
		||||
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import stirling.software.SPDF.model.ApplicationProperties;
 | 
			
		||||
 | 
			
		||||
@Service
 | 
			
		||||
@Slf4j
 | 
			
		||||
@DependsOn({"bookAndHtmlFormatsInstalled"})
 | 
			
		||||
public class EndpointConfiguration {
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(EndpointConfiguration.class);
 | 
			
		||||
 | 
			
		||||
    private Map<String, Boolean> endpointStatuses = new ConcurrentHashMap<>();
 | 
			
		||||
    private Map<String, Set<String>> endpointGroups = new ConcurrentHashMap<>();
 | 
			
		||||
 | 
			
		||||
@ -43,7 +43,7 @@ public class EndpointConfiguration {
 | 
			
		||||
 | 
			
		||||
    public void disableEndpoint(String endpoint) {
 | 
			
		||||
        if (!endpointStatuses.containsKey(endpoint) || endpointStatuses.get(endpoint) != false) {
 | 
			
		||||
            logger.debug("Disabling {}", endpoint);
 | 
			
		||||
            log.debug("Disabling {}", endpoint);
 | 
			
		||||
            endpointStatuses.put(endpoint, false);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@ -87,7 +87,7 @@ public class EndpointConfiguration {
 | 
			
		||||
                        .collect(Collectors.toList());
 | 
			
		||||
 | 
			
		||||
        if (!disabledList.isEmpty()) {
 | 
			
		||||
            logger.info(
 | 
			
		||||
            log.info(
 | 
			
		||||
                    "Total disabled endpoints: {}. Disabled endpoints: {}",
 | 
			
		||||
                    disabledList.size(),
 | 
			
		||||
                    String.join(", ", disabledList));
 | 
			
		||||
 | 
			
		||||
@ -2,8 +2,6 @@ package stirling.software.SPDF.config.security.oauth2;
 | 
			
		||||
 | 
			
		||||
import java.util.Optional;
 | 
			
		||||
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
import org.springframework.security.authentication.LockedException;
 | 
			
		||||
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest;
 | 
			
		||||
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService;
 | 
			
		||||
@ -13,6 +11,7 @@ import org.springframework.security.oauth2.core.OAuth2Error;
 | 
			
		||||
import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
 | 
			
		||||
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
 | 
			
		||||
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import stirling.software.SPDF.config.security.LoginAttemptService;
 | 
			
		||||
import stirling.software.SPDF.config.security.UserService;
 | 
			
		||||
import stirling.software.SPDF.model.ApplicationProperties;
 | 
			
		||||
@ -20,6 +19,7 @@ import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2;
 | 
			
		||||
import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2.Client;
 | 
			
		||||
import stirling.software.SPDF.model.User;
 | 
			
		||||
 | 
			
		||||
@Slf4j
 | 
			
		||||
public class CustomOAuth2UserService implements OAuth2UserService<OidcUserRequest, OidcUser> {
 | 
			
		||||
 | 
			
		||||
    private final OidcUserService delegate = new OidcUserService();
 | 
			
		||||
@ -30,8 +30,6 @@ public class CustomOAuth2UserService implements OAuth2UserService<OidcUserReques
 | 
			
		||||
 | 
			
		||||
    private ApplicationProperties applicationProperties;
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(CustomOAuth2UserService.class);
 | 
			
		||||
 | 
			
		||||
    public CustomOAuth2UserService(
 | 
			
		||||
            ApplicationProperties applicationProperties,
 | 
			
		||||
            UserService userService,
 | 
			
		||||
@ -82,10 +80,10 @@ public class CustomOAuth2UserService implements OAuth2UserService<OidcUserReques
 | 
			
		||||
                    user.getUserInfo(),
 | 
			
		||||
                    usernameAttribute);
 | 
			
		||||
        } catch (IllegalArgumentException e) {
 | 
			
		||||
            logger.error("Error loading OIDC user: {}", e.getMessage());
 | 
			
		||||
            log.error("Error loading OIDC user: {}", e.getMessage());
 | 
			
		||||
            throw new OAuth2AuthenticationException(new OAuth2Error(e.getMessage()), e);
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            logger.error("Unexpected error loading OIDC user", e);
 | 
			
		||||
            log.error("Unexpected error loading OIDC user", e);
 | 
			
		||||
            throw new OAuth2AuthenticationException("Unexpected error during authentication");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -11,8 +11,6 @@ import org.apache.pdfbox.pdmodel.PDPageContentStream;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.PDPageContentStream.AppendMode;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.common.PDRectangle;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject;
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.http.ResponseEntity;
 | 
			
		||||
import org.springframework.web.bind.annotation.ModelAttribute;
 | 
			
		||||
@ -33,8 +31,6 @@ import stirling.software.SPDF.utils.WebResponseUtils;
 | 
			
		||||
@Tag(name = "General", description = "General APIs")
 | 
			
		||||
public class CropController {
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(CropController.class);
 | 
			
		||||
 | 
			
		||||
    private final CustomPDDocumentFactory pdfDocumentFactory;
 | 
			
		||||
 | 
			
		||||
    private final PostHogService postHogService;
 | 
			
		||||
 | 
			
		||||
@ -20,8 +20,6 @@ import org.apache.pdfbox.pdmodel.PDPage;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.interactive.form.PDField;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.interactive.form.PDSignatureField;
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.http.ResponseEntity;
 | 
			
		||||
import org.springframework.web.bind.annotation.ModelAttribute;
 | 
			
		||||
@ -33,18 +31,18 @@ import org.springframework.web.multipart.MultipartFile;
 | 
			
		||||
import io.swagger.v3.oas.annotations.Operation;
 | 
			
		||||
import io.swagger.v3.oas.annotations.tags.Tag;
 | 
			
		||||
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import stirling.software.SPDF.model.api.general.MergePdfsRequest;
 | 
			
		||||
import stirling.software.SPDF.service.CustomPDDocumentFactory;
 | 
			
		||||
import stirling.software.SPDF.utils.GeneralUtils;
 | 
			
		||||
import stirling.software.SPDF.utils.WebResponseUtils;
 | 
			
		||||
 | 
			
		||||
@RestController
 | 
			
		||||
@Slf4j
 | 
			
		||||
@RequestMapping("/api/v1/general")
 | 
			
		||||
@Tag(name = "General", description = "General APIs")
 | 
			
		||||
public class MergeController {
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(MergeController.class);
 | 
			
		||||
 | 
			
		||||
    private final CustomPDDocumentFactory pdfDocumentFactory;
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
@ -184,7 +182,7 @@ public class MergeController {
 | 
			
		||||
                    baos.toByteArray(), mergedFileName); // Return the modified PDF
 | 
			
		||||
 | 
			
		||||
        } catch (Exception ex) {
 | 
			
		||||
            logger.error("Error in merge pdf process", ex);
 | 
			
		||||
            log.error("Error in merge pdf process", ex);
 | 
			
		||||
            throw ex;
 | 
			
		||||
        } finally {
 | 
			
		||||
            for (File file : filesToDelete) {
 | 
			
		||||
 | 
			
		||||
@ -12,8 +12,6 @@ import org.apache.pdfbox.pdmodel.PDPageContentStream;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.common.PDRectangle;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject;
 | 
			
		||||
import org.apache.pdfbox.util.Matrix;
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.http.ResponseEntity;
 | 
			
		||||
import org.springframework.web.bind.annotation.ModelAttribute;
 | 
			
		||||
@ -35,8 +33,6 @@ import stirling.software.SPDF.utils.WebResponseUtils;
 | 
			
		||||
@Tag(name = "General", description = "General APIs")
 | 
			
		||||
public class MultiPageLayoutController {
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(MultiPageLayoutController.class);
 | 
			
		||||
 | 
			
		||||
    private final CustomPDDocumentFactory pdfDocumentFactory;
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
 | 
			
		||||
@ -8,8 +8,6 @@ import java.util.List;
 | 
			
		||||
import org.apache.pdfbox.Loader;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.PDDocument;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.PDPage;
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.http.ResponseEntity;
 | 
			
		||||
import org.springframework.web.bind.annotation.ModelAttribute;
 | 
			
		||||
@ -22,6 +20,7 @@ import io.github.pixee.security.Filenames;
 | 
			
		||||
import io.swagger.v3.oas.annotations.Operation;
 | 
			
		||||
import io.swagger.v3.oas.annotations.tags.Tag;
 | 
			
		||||
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import stirling.software.SPDF.model.SortTypes;
 | 
			
		||||
import stirling.software.SPDF.model.api.PDFWithPageNums;
 | 
			
		||||
import stirling.software.SPDF.model.api.general.RearrangePagesRequest;
 | 
			
		||||
@ -31,11 +30,10 @@ import stirling.software.SPDF.utils.WebResponseUtils;
 | 
			
		||||
 | 
			
		||||
@RestController
 | 
			
		||||
@RequestMapping("/api/v1/general")
 | 
			
		||||
@Slf4j
 | 
			
		||||
@Tag(name = "General", description = "General APIs")
 | 
			
		||||
public class RearrangePagesPDFController {
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(RearrangePagesPDFController.class);
 | 
			
		||||
 | 
			
		||||
    private final CustomPDDocumentFactory pdfDocumentFactory;
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
@ -202,7 +200,7 @@ public class RearrangePagesPDFController {
 | 
			
		||||
                    throw new IllegalArgumentException("Unsupported custom mode");
 | 
			
		||||
            }
 | 
			
		||||
        } catch (IllegalArgumentException e) {
 | 
			
		||||
            logger.error("Unsupported custom mode", e);
 | 
			
		||||
            log.error("Unsupported custom mode", e);
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@ -230,8 +228,8 @@ public class RearrangePagesPDFController {
 | 
			
		||||
            } else {
 | 
			
		||||
                newPageOrder = GeneralUtils.parsePageList(pageOrderArr, totalPages, false);
 | 
			
		||||
            }
 | 
			
		||||
            logger.info("newPageOrder = " + newPageOrder);
 | 
			
		||||
            logger.info("totalPages = " + totalPages);
 | 
			
		||||
            log.info("newPageOrder = " + newPageOrder);
 | 
			
		||||
            log.info("totalPages = " + totalPages);
 | 
			
		||||
            // Create a new list to hold the pages in the new order
 | 
			
		||||
            List<PDPage> newPages = new ArrayList<>();
 | 
			
		||||
            for (int i = 0; i < newPageOrder.size(); i++) {
 | 
			
		||||
@ -254,7 +252,7 @@ public class RearrangePagesPDFController {
 | 
			
		||||
                                    .replaceFirst("[.][^.]+$", "")
 | 
			
		||||
                            + "_rearranged.pdf");
 | 
			
		||||
        } catch (IOException e) {
 | 
			
		||||
            logger.error("Failed rearranging documents", e);
 | 
			
		||||
            log.error("Failed rearranging documents", e);
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -5,8 +5,6 @@ import java.io.IOException;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.PDDocument;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.PDPage;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.PDPageTree;
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.http.ResponseEntity;
 | 
			
		||||
import org.springframework.web.bind.annotation.ModelAttribute;
 | 
			
		||||
@ -28,8 +26,6 @@ import stirling.software.SPDF.utils.WebResponseUtils;
 | 
			
		||||
@Tag(name = "General", description = "General APIs")
 | 
			
		||||
public class RotationController {
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(RotationController.class);
 | 
			
		||||
 | 
			
		||||
    private final CustomPDDocumentFactory pdfDocumentFactory;
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
 | 
			
		||||
@ -13,8 +13,6 @@ import org.apache.pdfbox.pdmodel.PDPageContentStream;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.common.PDRectangle;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject;
 | 
			
		||||
import org.apache.pdfbox.util.Matrix;
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.http.ResponseEntity;
 | 
			
		||||
import org.springframework.web.bind.annotation.ModelAttribute;
 | 
			
		||||
@ -36,8 +34,6 @@ import stirling.software.SPDF.utils.WebResponseUtils;
 | 
			
		||||
@Tag(name = "General", description = "General APIs")
 | 
			
		||||
public class ScalePagesController {
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(ScalePagesController.class);
 | 
			
		||||
 | 
			
		||||
    private final CustomPDDocumentFactory pdfDocumentFactory;
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
 | 
			
		||||
@ -13,8 +13,6 @@ import java.util.zip.ZipOutputStream;
 | 
			
		||||
import org.apache.pdfbox.Loader;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.PDDocument;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.PDPage;
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.http.MediaType;
 | 
			
		||||
import org.springframework.http.ResponseEntity;
 | 
			
		||||
@ -28,16 +26,17 @@ import io.github.pixee.security.Filenames;
 | 
			
		||||
import io.swagger.v3.oas.annotations.Operation;
 | 
			
		||||
import io.swagger.v3.oas.annotations.tags.Tag;
 | 
			
		||||
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import stirling.software.SPDF.model.api.PDFWithPageNums;
 | 
			
		||||
import stirling.software.SPDF.service.CustomPDDocumentFactory;
 | 
			
		||||
import stirling.software.SPDF.utils.WebResponseUtils;
 | 
			
		||||
 | 
			
		||||
@RestController
 | 
			
		||||
@RequestMapping("/api/v1/general")
 | 
			
		||||
@Slf4j
 | 
			
		||||
@Tag(name = "General", description = "General APIs")
 | 
			
		||||
public class SplitPDFController {
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(SplitPDFController.class);
 | 
			
		||||
    private final CustomPDDocumentFactory pdfDocumentFactory;
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
@ -73,7 +72,7 @@ public class SplitPDFController {
 | 
			
		||||
                pageNumbers.add(totalPages - 1);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            logger.info(
 | 
			
		||||
            log.info(
 | 
			
		||||
                    "Splitting PDF into pages: {}",
 | 
			
		||||
                    pageNumbers.stream().map(String::valueOf).collect(Collectors.joining(",")));
 | 
			
		||||
 | 
			
		||||
@ -86,7 +85,7 @@ public class SplitPDFController {
 | 
			
		||||
                    for (int i = previousPageNumber; i <= splitPoint; i++) {
 | 
			
		||||
                        PDPage page = document.getPage(i);
 | 
			
		||||
                        splitDocument.addPage(page);
 | 
			
		||||
                        logger.info("Adding page {} to split document", i);
 | 
			
		||||
                        log.info("Adding page {} to split document", i);
 | 
			
		||||
                    }
 | 
			
		||||
                    previousPageNumber = splitPoint + 1;
 | 
			
		||||
 | 
			
		||||
@ -98,7 +97,7 @@ public class SplitPDFController {
 | 
			
		||||
 | 
			
		||||
                    splitDocumentsBoas.add(baos);
 | 
			
		||||
                } catch (Exception e) {
 | 
			
		||||
                    logger.error("Failed splitting documents and saving them", e);
 | 
			
		||||
                    log.error("Failed splitting documents and saving them", e);
 | 
			
		||||
                    throw e;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@ -124,15 +123,14 @@ public class SplitPDFController {
 | 
			
		||||
                    zipOut.write(pdf);
 | 
			
		||||
                    zipOut.closeEntry();
 | 
			
		||||
 | 
			
		||||
                    logger.info("Wrote split document {} to zip file", fileName);
 | 
			
		||||
                    log.info("Wrote split document {} to zip file", fileName);
 | 
			
		||||
                }
 | 
			
		||||
            } catch (Exception e) {
 | 
			
		||||
                logger.error("Failed writing to zip", e);
 | 
			
		||||
                log.error("Failed writing to zip", e);
 | 
			
		||||
                throw e;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            logger.info(
 | 
			
		||||
                    "Successfully created zip file with split documents: {}", zipFile.toString());
 | 
			
		||||
            log.info("Successfully created zip file with split documents: {}", zipFile.toString());
 | 
			
		||||
            byte[] data = Files.readAllBytes(zipFile);
 | 
			
		||||
            Files.deleteIfExists(zipFile);
 | 
			
		||||
 | 
			
		||||
@ -159,7 +157,7 @@ public class SplitPDFController {
 | 
			
		||||
                    Files.deleteIfExists(zipFile);
 | 
			
		||||
                }
 | 
			
		||||
            } catch (Exception e) {
 | 
			
		||||
                logger.error("Error while cleaning up resources", e);
 | 
			
		||||
                log.error("Error while cleaning up resources", e);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -13,8 +13,6 @@ import org.apache.pdfbox.pdmodel.PDDocument;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.PDPage;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDDocumentOutline;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDOutlineItem;
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.http.MediaType;
 | 
			
		||||
import org.springframework.http.ResponseEntity;
 | 
			
		||||
@ -32,6 +30,7 @@ import lombok.AllArgsConstructor;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import lombok.EqualsAndHashCode;
 | 
			
		||||
import lombok.NoArgsConstructor;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import stirling.software.SPDF.model.PdfMetadata;
 | 
			
		||||
import stirling.software.SPDF.model.api.SplitPdfByChaptersRequest;
 | 
			
		||||
import stirling.software.SPDF.service.PdfMetadataService;
 | 
			
		||||
@ -39,12 +38,10 @@ import stirling.software.SPDF.utils.WebResponseUtils;
 | 
			
		||||
 | 
			
		||||
@RestController
 | 
			
		||||
@RequestMapping("/api/v1/general")
 | 
			
		||||
@Slf4j
 | 
			
		||||
@Tag(name = "General", description = "General APIs")
 | 
			
		||||
public class SplitPdfByChaptersController {
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger =
 | 
			
		||||
            LoggerFactory.getLogger(SplitPdfByChaptersController.class);
 | 
			
		||||
 | 
			
		||||
    private final PdfMetadataService pdfMetadataService;
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
@ -74,7 +71,7 @@ public class SplitPdfByChaptersController {
 | 
			
		||||
            PDDocumentOutline outline = sourceDocument.getDocumentCatalog().getDocumentOutline();
 | 
			
		||||
 | 
			
		||||
            if (outline == null) {
 | 
			
		||||
                logger.warn("No outline found for {}", file.getOriginalFilename());
 | 
			
		||||
                log.warn("No outline found for {}", file.getOriginalFilename());
 | 
			
		||||
                return ResponseEntity.badRequest().body("No outline found".getBytes());
 | 
			
		||||
            }
 | 
			
		||||
            List<Bookmark> bookmarks = new ArrayList<>();
 | 
			
		||||
@ -92,7 +89,7 @@ public class SplitPdfByChaptersController {
 | 
			
		||||
                Bookmark lastBookmark = bookmarks.get(bookmarks.size() - 1);
 | 
			
		||||
 | 
			
		||||
            } catch (Exception e) {
 | 
			
		||||
                logger.error("Unable to extract outline items", e);
 | 
			
		||||
                log.error("Unable to extract outline items", e);
 | 
			
		||||
                return ResponseEntity.internalServerError()
 | 
			
		||||
                        .body("Unable to extract outline items".getBytes());
 | 
			
		||||
            }
 | 
			
		||||
@ -107,7 +104,7 @@ public class SplitPdfByChaptersController {
 | 
			
		||||
                bookmarks = mergeBookmarksThatCorrespondToSamePage(bookmarks);
 | 
			
		||||
            }
 | 
			
		||||
            for (Bookmark bookmark : bookmarks) {
 | 
			
		||||
                logger.info(
 | 
			
		||||
                log.info(
 | 
			
		||||
                        "{}::::{} to {}",
 | 
			
		||||
                        bookmark.getTitle(),
 | 
			
		||||
                        bookmark.getStartPage(),
 | 
			
		||||
@ -136,7 +133,7 @@ public class SplitPdfByChaptersController {
 | 
			
		||||
                    Files.deleteIfExists(zipFile);
 | 
			
		||||
                }
 | 
			
		||||
            } catch (Exception e) {
 | 
			
		||||
                logger.error("Error while cleaning up resources", e);
 | 
			
		||||
                log.error("Error while cleaning up resources", e);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@ -256,14 +253,14 @@ public class SplitPdfByChaptersController {
 | 
			
		||||
                zipOut.write(pdf);
 | 
			
		||||
                zipOut.closeEntry();
 | 
			
		||||
 | 
			
		||||
                logger.info("Wrote split document {} to zip file", fileName);
 | 
			
		||||
                log.info("Wrote split document {} to zip file", fileName);
 | 
			
		||||
            }
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            logger.error("Failed writing to zip", e);
 | 
			
		||||
            log.error("Failed writing to zip", e);
 | 
			
		||||
            throw e;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        logger.info("Successfully created zip file with split documents: {}", zipFile);
 | 
			
		||||
        log.info("Successfully created zip file with split documents: {}", zipFile);
 | 
			
		||||
        return zipFile;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -284,7 +281,7 @@ public class SplitPdfByChaptersController {
 | 
			
		||||
                        i++) {
 | 
			
		||||
                    PDPage page = sourceDocument.getPage(i);
 | 
			
		||||
                    splitDocument.addPage(page);
 | 
			
		||||
                    logger.info("Adding page {} to split document", i);
 | 
			
		||||
                    log.info("Adding page {} to split document", i);
 | 
			
		||||
                }
 | 
			
		||||
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
 | 
			
		||||
                if (includeMetadata) {
 | 
			
		||||
@ -295,7 +292,7 @@ public class SplitPdfByChaptersController {
 | 
			
		||||
 | 
			
		||||
                splitDocumentsBoas.add(baos);
 | 
			
		||||
            } catch (Exception e) {
 | 
			
		||||
                logger.error("Failed splitting documents and saving them", e);
 | 
			
		||||
                log.error("Failed splitting documents and saving them", e);
 | 
			
		||||
                throw e;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -18,8 +18,6 @@ import org.apache.pdfbox.pdmodel.PDPageContentStream.AppendMode;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.common.PDRectangle;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject;
 | 
			
		||||
import org.apache.pdfbox.util.Matrix;
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.http.MediaType;
 | 
			
		||||
import org.springframework.http.ResponseEntity;
 | 
			
		||||
@ -42,9 +40,6 @@ import stirling.software.SPDF.utils.WebResponseUtils;
 | 
			
		||||
@Tag(name = "General", description = "General APIs")
 | 
			
		||||
public class SplitPdfBySectionsController {
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger =
 | 
			
		||||
            LoggerFactory.getLogger(SplitPdfBySectionsController.class);
 | 
			
		||||
 | 
			
		||||
    private final CustomPDDocumentFactory pdfDocumentFactory;
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
 | 
			
		||||
@ -10,8 +10,6 @@ import java.util.zip.ZipOutputStream;
 | 
			
		||||
import org.apache.pdfbox.Loader;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.PDDocument;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.PDPage;
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.http.MediaType;
 | 
			
		||||
import org.springframework.http.ResponseEntity;
 | 
			
		||||
@ -25,6 +23,7 @@ import io.github.pixee.security.Filenames;
 | 
			
		||||
import io.swagger.v3.oas.annotations.Operation;
 | 
			
		||||
import io.swagger.v3.oas.annotations.tags.Tag;
 | 
			
		||||
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import stirling.software.SPDF.model.api.general.SplitPdfBySizeOrCountRequest;
 | 
			
		||||
import stirling.software.SPDF.service.CustomPDDocumentFactory;
 | 
			
		||||
import stirling.software.SPDF.utils.GeneralUtils;
 | 
			
		||||
@ -32,10 +31,10 @@ import stirling.software.SPDF.utils.WebResponseUtils;
 | 
			
		||||
 | 
			
		||||
@RestController
 | 
			
		||||
@RequestMapping("/api/v1/general")
 | 
			
		||||
@Slf4j
 | 
			
		||||
@Tag(name = "General", description = "General APIs")
 | 
			
		||||
public class SplitPdfBySizeController {
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(SplitPdfBySizeController.class);
 | 
			
		||||
    private final CustomPDDocumentFactory pdfDocumentFactory;
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
@ -78,7 +77,7 @@ public class SplitPdfBySizeController {
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            logger.error("exception", e);
 | 
			
		||||
            log.error("exception", e);
 | 
			
		||||
        } finally {
 | 
			
		||||
            data = Files.readAllBytes(zipFile);
 | 
			
		||||
            Files.deleteIfExists(zipFile);
 | 
			
		||||
 | 
			
		||||
@ -11,8 +11,6 @@ import org.apache.pdfbox.pdmodel.PDPage;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.PDPageContentStream;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.common.PDRectangle;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject;
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.http.ResponseEntity;
 | 
			
		||||
import org.springframework.web.bind.annotation.ModelAttribute;
 | 
			
		||||
@ -32,8 +30,6 @@ import stirling.software.SPDF.utils.WebResponseUtils;
 | 
			
		||||
@Tag(name = "General", description = "General APIs")
 | 
			
		||||
public class ToSinglePageController {
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(ToSinglePageController.class);
 | 
			
		||||
 | 
			
		||||
    private final CustomPDDocumentFactory pdfDocumentFactory;
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
 | 
			
		||||
@ -14,8 +14,6 @@ import java.util.zip.ZipOutputStream;
 | 
			
		||||
 | 
			
		||||
import org.apache.commons.io.FileUtils;
 | 
			
		||||
import org.apache.pdfbox.rendering.ImageType;
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.http.MediaType;
 | 
			
		||||
import org.springframework.http.ResponseEntity;
 | 
			
		||||
@ -29,6 +27,7 @@ import io.github.pixee.security.Filenames;
 | 
			
		||||
import io.swagger.v3.oas.annotations.Operation;
 | 
			
		||||
import io.swagger.v3.oas.annotations.tags.Tag;
 | 
			
		||||
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import stirling.software.SPDF.model.api.converters.ConvertToImageRequest;
 | 
			
		||||
import stirling.software.SPDF.model.api.converters.ConvertToPdfRequest;
 | 
			
		||||
import stirling.software.SPDF.service.CustomPDDocumentFactory;
 | 
			
		||||
@ -40,11 +39,10 @@ import stirling.software.SPDF.utils.WebResponseUtils;
 | 
			
		||||
 | 
			
		||||
@RestController
 | 
			
		||||
@RequestMapping("/api/v1/convert")
 | 
			
		||||
@Slf4j
 | 
			
		||||
@Tag(name = "Convert", description = "Convert APIs")
 | 
			
		||||
public class ConvertImgPDFController {
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(ConvertImgPDFController.class);
 | 
			
		||||
 | 
			
		||||
    private final CustomPDDocumentFactory pdfDocumentFactory;
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
@ -95,7 +93,7 @@ public class ConvertImgPDFController {
 | 
			
		||||
                            Integer.valueOf(dpi),
 | 
			
		||||
                            filename);
 | 
			
		||||
            if (result == null || result.length == 0) {
 | 
			
		||||
                logger.error("resultant bytes for {} is null, error converting ", filename);
 | 
			
		||||
                log.error("resultant bytes for {} is null, error converting ", filename);
 | 
			
		||||
            }
 | 
			
		||||
            if ("webp".equalsIgnoreCase(imageFormat) && !CheckProgramInstall.isPythonAvailable()) {
 | 
			
		||||
                throw new IOException("Python is not installed. Required for WebP conversion.");
 | 
			
		||||
@ -142,7 +140,7 @@ public class ConvertImgPDFController {
 | 
			
		||||
                                .collect(Collectors.toList());
 | 
			
		||||
 | 
			
		||||
                if (webpFiles.isEmpty()) {
 | 
			
		||||
                    logger.error("No WebP files were created in: {}", tempOutputDir.toString());
 | 
			
		||||
                    log.error("No WebP files were created in: {}", tempOutputDir.toString());
 | 
			
		||||
                    throw new IOException(
 | 
			
		||||
                            "No WebP files were created. " + resultProcess.getMessages());
 | 
			
		||||
                }
 | 
			
		||||
@ -194,7 +192,7 @@ public class ConvertImgPDFController {
 | 
			
		||||
                    FileUtils.deleteDirectory(tempOutputDir.toFile());
 | 
			
		||||
                }
 | 
			
		||||
            } catch (Exception e) {
 | 
			
		||||
                logger.error("Error cleaning up temporary files", e);
 | 
			
		||||
                log.error("Error cleaning up temporary files", e);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -8,8 +8,6 @@ import java.util.Arrays;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
import org.apache.commons.io.FileUtils;
 | 
			
		||||
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;
 | 
			
		||||
@ -22,6 +20,7 @@ import io.github.pixee.security.Filenames;
 | 
			
		||||
import io.swagger.v3.oas.annotations.Operation;
 | 
			
		||||
import io.swagger.v3.oas.annotations.tags.Tag;
 | 
			
		||||
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import stirling.software.SPDF.model.api.converters.PdfToPdfARequest;
 | 
			
		||||
import stirling.software.SPDF.utils.ProcessExecutor;
 | 
			
		||||
import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult;
 | 
			
		||||
@ -29,11 +28,10 @@ import stirling.software.SPDF.utils.WebResponseUtils;
 | 
			
		||||
 | 
			
		||||
@RestController
 | 
			
		||||
@RequestMapping("/api/v1/convert")
 | 
			
		||||
@Slf4j
 | 
			
		||||
@Tag(name = "Convert", description = "Convert APIs")
 | 
			
		||||
public class ConvertPDFToPDFA {
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(ConvertPDFToPDFA.class);
 | 
			
		||||
 | 
			
		||||
    @PostMapping(consumes = "multipart/form-data", value = "/pdf/pdfa")
 | 
			
		||||
    @Operation(
 | 
			
		||||
            summary = "Convert a PDF to a PDF/A",
 | 
			
		||||
@ -46,7 +44,7 @@ public class ConvertPDFToPDFA {
 | 
			
		||||
 | 
			
		||||
        // Validate input file type
 | 
			
		||||
        if (!"application/pdf".equals(inputFile.getContentType())) {
 | 
			
		||||
            logger.error("Invalid input file type: {}", inputFile.getContentType());
 | 
			
		||||
            log.error("Invalid input file type: {}", inputFile.getContentType());
 | 
			
		||||
            throw new IllegalArgumentException("Input file must be a PDF");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -96,7 +94,7 @@ public class ConvertPDFToPDFA {
 | 
			
		||||
                            .runCommandWithOutputHandling(command);
 | 
			
		||||
 | 
			
		||||
            if (returnCode.getRc() != 0) {
 | 
			
		||||
                logger.error("PDF/A conversion failed with return code: {}", returnCode.getRc());
 | 
			
		||||
                log.error("PDF/A conversion failed with return code: {}", returnCode.getRc());
 | 
			
		||||
                throw new RuntimeException("PDF/A conversion failed");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -7,8 +7,6 @@ import java.util.ArrayList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
import org.apache.pdfbox.pdmodel.PDDocument;
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.http.ResponseEntity;
 | 
			
		||||
import org.springframework.web.bind.annotation.ModelAttribute;
 | 
			
		||||
@ -19,6 +17,7 @@ import org.springframework.web.bind.annotation.RestController;
 | 
			
		||||
import io.swagger.v3.oas.annotations.Operation;
 | 
			
		||||
import io.swagger.v3.oas.annotations.tags.Tag;
 | 
			
		||||
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import stirling.software.SPDF.model.api.converters.UrlToPdfRequest;
 | 
			
		||||
import stirling.software.SPDF.service.CustomPDDocumentFactory;
 | 
			
		||||
import stirling.software.SPDF.utils.GeneralUtils;
 | 
			
		||||
@ -28,11 +27,10 @@ import stirling.software.SPDF.utils.WebResponseUtils;
 | 
			
		||||
 | 
			
		||||
@RestController
 | 
			
		||||
@Tag(name = "Convert", description = "Convert APIs")
 | 
			
		||||
@Slf4j
 | 
			
		||||
@RequestMapping("/api/v1/convert")
 | 
			
		||||
public class ConvertWebsiteToPDF {
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(ConvertWebsiteToPDF.class);
 | 
			
		||||
 | 
			
		||||
    private final CustomPDDocumentFactory pdfDocumentFactory;
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
@ -88,7 +86,7 @@ public class ConvertWebsiteToPDF {
 | 
			
		||||
                try {
 | 
			
		||||
                    Files.deleteIfExists(tempOutputFile);
 | 
			
		||||
                } catch (IOException e) {
 | 
			
		||||
                    logger.error("Error deleting temporary output file", e);
 | 
			
		||||
                    log.error("Error deleting temporary output file", e);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -7,8 +7,6 @@ import org.apache.commons.csv.CSVFormat;
 | 
			
		||||
import org.apache.commons.csv.QuoteMode;
 | 
			
		||||
import org.apache.pdfbox.Loader;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.PDDocument;
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
import org.springframework.http.ContentDisposition;
 | 
			
		||||
import org.springframework.http.HttpHeaders;
 | 
			
		||||
import org.springframework.http.MediaType;
 | 
			
		||||
@ -34,8 +32,6 @@ import technology.tabula.writers.Writer;
 | 
			
		||||
@Tag(name = "Convert", description = "Convert APIs")
 | 
			
		||||
public class ExtractCSVController {
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(ExtractCSVController.class);
 | 
			
		||||
 | 
			
		||||
    @PostMapping(value = "/pdf/csv", consumes = "multipart/form-data")
 | 
			
		||||
    @Operation(
 | 
			
		||||
            summary = "Extracts a CSV document from a PDF",
 | 
			
		||||
 | 
			
		||||
@ -9,8 +9,6 @@ import org.apache.pdfbox.Loader;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.PDDocument;
 | 
			
		||||
import org.apache.pdfbox.text.PDFTextStripper;
 | 
			
		||||
import org.apache.pdfbox.text.TextPosition;
 | 
			
		||||
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;
 | 
			
		||||
@ -22,16 +20,16 @@ import io.github.pixee.security.Filenames;
 | 
			
		||||
import io.swagger.v3.oas.annotations.Operation;
 | 
			
		||||
import io.swagger.v3.oas.annotations.tags.Tag;
 | 
			
		||||
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import stirling.software.SPDF.model.api.misc.ExtractHeaderRequest;
 | 
			
		||||
import stirling.software.SPDF.utils.WebResponseUtils;
 | 
			
		||||
 | 
			
		||||
@RestController
 | 
			
		||||
@RequestMapping("/api/v1/misc")
 | 
			
		||||
@Slf4j
 | 
			
		||||
@Tag(name = "Misc", description = "Miscellaneous APIs")
 | 
			
		||||
public class AutoRenameController {
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(AutoRenameController.class);
 | 
			
		||||
 | 
			
		||||
    private static final float TITLE_FONT_SIZE_THRESHOLD = 20.0f;
 | 
			
		||||
    private static final int LINE_LIMIT = 200;
 | 
			
		||||
 | 
			
		||||
@ -133,7 +131,7 @@ public class AutoRenameController {
 | 
			
		||||
            header = header.replaceAll("[/\\\\?%*:|\"<>]", "").trim();
 | 
			
		||||
            return WebResponseUtils.pdfDocToWebResponse(document, header + ".pdf");
 | 
			
		||||
        } else {
 | 
			
		||||
            logger.info("File has no good title to be found");
 | 
			
		||||
            log.info("File has no good title to be found");
 | 
			
		||||
            return WebResponseUtils.pdfDocToWebResponse(
 | 
			
		||||
                    document, Filenames.toSimpleFileName(file.getOriginalFilename()));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -14,8 +14,6 @@ import java.util.zip.ZipOutputStream;
 | 
			
		||||
 | 
			
		||||
import org.apache.pdfbox.pdmodel.PDDocument;
 | 
			
		||||
import org.apache.pdfbox.rendering.PDFRenderer;
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.http.MediaType;
 | 
			
		||||
import org.springframework.http.ResponseEntity;
 | 
			
		||||
@ -37,16 +35,17 @@ import io.github.pixee.security.Filenames;
 | 
			
		||||
import io.swagger.v3.oas.annotations.Operation;
 | 
			
		||||
import io.swagger.v3.oas.annotations.tags.Tag;
 | 
			
		||||
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import stirling.software.SPDF.model.api.misc.AutoSplitPdfRequest;
 | 
			
		||||
import stirling.software.SPDF.service.CustomPDDocumentFactory;
 | 
			
		||||
import stirling.software.SPDF.utils.WebResponseUtils;
 | 
			
		||||
 | 
			
		||||
@RestController
 | 
			
		||||
@RequestMapping("/api/v1/misc")
 | 
			
		||||
@Slf4j
 | 
			
		||||
@Tag(name = "Misc", description = "Miscellaneous APIs")
 | 
			
		||||
public class AutoSplitPdfController {
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(AutoSplitPdfController.class);
 | 
			
		||||
    private static final String QR_CONTENT = "https://github.com/Stirling-Tools/Stirling-PDF";
 | 
			
		||||
    private static final String QR_CONTENT_OLD = "https://github.com/Frooodle/Stirling-PDF";
 | 
			
		||||
 | 
			
		||||
@ -134,7 +133,7 @@ public class AutoSplitPdfController {
 | 
			
		||||
                try {
 | 
			
		||||
                    document.close();
 | 
			
		||||
                } catch (IOException e) {
 | 
			
		||||
                    logger.error("Error closing main PDDocument", e);
 | 
			
		||||
                    log.error("Error closing main PDDocument", e);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@ -142,7 +141,7 @@ public class AutoSplitPdfController {
 | 
			
		||||
                try {
 | 
			
		||||
                    splitDoc.close();
 | 
			
		||||
                } catch (IOException e) {
 | 
			
		||||
                    logger.error("Error closing split PDDocument", e);
 | 
			
		||||
                    log.error("Error closing split PDDocument", e);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@ -150,7 +149,7 @@ public class AutoSplitPdfController {
 | 
			
		||||
                try {
 | 
			
		||||
                    Files.deleteIfExists(zipFile);
 | 
			
		||||
                } catch (IOException e) {
 | 
			
		||||
                    logger.error("Error deleting temporary zip file", e);
 | 
			
		||||
                    log.error("Error deleting temporary zip file", e);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -14,8 +14,6 @@ import org.apache.pdfbox.pdmodel.PDPage;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.PDPageTree;
 | 
			
		||||
import org.apache.pdfbox.rendering.PDFRenderer;
 | 
			
		||||
import org.apache.pdfbox.text.PDFTextStripper;
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.http.HttpStatus;
 | 
			
		||||
import org.springframework.http.MediaType;
 | 
			
		||||
@ -30,6 +28,7 @@ import io.github.pixee.security.Filenames;
 | 
			
		||||
import io.swagger.v3.oas.annotations.Operation;
 | 
			
		||||
import io.swagger.v3.oas.annotations.tags.Tag;
 | 
			
		||||
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import stirling.software.SPDF.model.api.misc.RemoveBlankPagesRequest;
 | 
			
		||||
import stirling.software.SPDF.service.CustomPDDocumentFactory;
 | 
			
		||||
import stirling.software.SPDF.utils.PdfUtils;
 | 
			
		||||
@ -37,11 +36,10 @@ import stirling.software.SPDF.utils.WebResponseUtils;
 | 
			
		||||
 | 
			
		||||
@RestController
 | 
			
		||||
@RequestMapping("/api/v1/misc")
 | 
			
		||||
@Slf4j
 | 
			
		||||
@Tag(name = "Misc", description = "Miscellaneous APIs")
 | 
			
		||||
public class BlankPageController {
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(BlankPageController.class);
 | 
			
		||||
 | 
			
		||||
    private final CustomPDDocumentFactory pdfDocumentFactory;
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
@ -71,7 +69,7 @@ public class BlankPageController {
 | 
			
		||||
            PDFRenderer pdfRenderer = new PDFRenderer(document);
 | 
			
		||||
            pdfRenderer.setSubsamplingAllowed(true);
 | 
			
		||||
            for (PDPage page : pages) {
 | 
			
		||||
                logger.info("checking page {}", pageIndex);
 | 
			
		||||
                log.info("checking page {}", pageIndex);
 | 
			
		||||
                textStripper.setStartPage(pageIndex + 1);
 | 
			
		||||
                textStripper.setEndPage(pageIndex + 1);
 | 
			
		||||
                String pageText = textStripper.getText(document);
 | 
			
		||||
@ -79,12 +77,12 @@ public class BlankPageController {
 | 
			
		||||
 | 
			
		||||
                boolean blank = true;
 | 
			
		||||
                if (hasText) {
 | 
			
		||||
                    logger.info("page {} has text, not blank", pageIndex);
 | 
			
		||||
                    log.info("page {} has text, not blank", pageIndex);
 | 
			
		||||
                    blank = false;
 | 
			
		||||
                } else {
 | 
			
		||||
                    boolean hasImages = PdfUtils.hasImagesOnPage(page);
 | 
			
		||||
                    if (hasImages) {
 | 
			
		||||
                        logger.info("page {} has image, running blank detection", pageIndex);
 | 
			
		||||
                        log.info("page {} has image, running blank detection", pageIndex);
 | 
			
		||||
                        // Render image and save as temp file
 | 
			
		||||
                        BufferedImage image = pdfRenderer.renderImageWithDPI(pageIndex, 30);
 | 
			
		||||
                        blank = isBlankImage(image, threshold, whitePercent, threshold);
 | 
			
		||||
@ -92,10 +90,10 @@ public class BlankPageController {
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (blank) {
 | 
			
		||||
                    logger.info("Skipping, Image was  blank for page #{}", pageIndex);
 | 
			
		||||
                    log.info("Skipping, Image was  blank for page #{}", pageIndex);
 | 
			
		||||
                    blankPages.add(page);
 | 
			
		||||
                } else {
 | 
			
		||||
                    logger.info("page {} has image which is not blank", pageIndex);
 | 
			
		||||
                    log.info("page {} has image which is not blank", pageIndex);
 | 
			
		||||
                    nonBlankPages.add(page);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
@ -121,12 +119,12 @@ public class BlankPageController {
 | 
			
		||||
 | 
			
		||||
            zos.close();
 | 
			
		||||
 | 
			
		||||
            logger.info("Returning ZIP file: {}", filename + "_processed.zip");
 | 
			
		||||
            log.info("Returning ZIP file: {}", filename + "_processed.zip");
 | 
			
		||||
            return WebResponseUtils.boasToWebResponse(
 | 
			
		||||
                    baos, filename + "_processed.zip", MediaType.APPLICATION_OCTET_STREAM);
 | 
			
		||||
 | 
			
		||||
        } catch (IOException e) {
 | 
			
		||||
            logger.error("exception", e);
 | 
			
		||||
            log.error("exception", e);
 | 
			
		||||
            return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@ -149,7 +147,7 @@ public class BlankPageController {
 | 
			
		||||
    public static boolean isBlankImage(
 | 
			
		||||
            BufferedImage image, int threshold, double whitePercent, int blurSize) {
 | 
			
		||||
        if (image == null) {
 | 
			
		||||
            logger.info("Error: Image is null");
 | 
			
		||||
            log.info("Error: Image is null");
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -167,7 +165,7 @@ public class BlankPageController {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        double whitePixelPercentage = (whitePixels / (double) totalPixels) * 100;
 | 
			
		||||
        logger.info(String.format("Page has white pixel percent of %.2f%%", whitePixelPercentage));
 | 
			
		||||
        log.info(String.format("Page has white pixel percent of %.2f%%", whitePixelPercentage));
 | 
			
		||||
 | 
			
		||||
        return whitePixelPercentage >= whitePercent;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -17,8 +17,6 @@ import org.apache.pdfbox.pdmodel.PDPage;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.PDResources;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.graphics.PDXObject;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.http.ResponseEntity;
 | 
			
		||||
import org.springframework.web.bind.annotation.ModelAttribute;
 | 
			
		||||
@ -31,6 +29,7 @@ import io.github.pixee.security.Filenames;
 | 
			
		||||
import io.swagger.v3.oas.annotations.Operation;
 | 
			
		||||
import io.swagger.v3.oas.annotations.tags.Tag;
 | 
			
		||||
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import stirling.software.SPDF.model.api.misc.OptimizePdfRequest;
 | 
			
		||||
import stirling.software.SPDF.service.CustomPDDocumentFactory;
 | 
			
		||||
import stirling.software.SPDF.utils.GeneralUtils;
 | 
			
		||||
@ -40,11 +39,10 @@ import stirling.software.SPDF.utils.WebResponseUtils;
 | 
			
		||||
 | 
			
		||||
@RestController
 | 
			
		||||
@RequestMapping("/api/v1/misc")
 | 
			
		||||
@Slf4j
 | 
			
		||||
@Tag(name = "Misc", description = "Miscellaneous APIs")
 | 
			
		||||
public class CompressController {
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(CompressController.class);
 | 
			
		||||
 | 
			
		||||
    private final CustomPDDocumentFactory pdfDocumentFactory;
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
@ -191,7 +189,7 @@ public class CompressController {
 | 
			
		||||
                            incrementOptimizeLevel(
 | 
			
		||||
                                    optimizeLevel, outputFileSize, expectedOutputSize);
 | 
			
		||||
                    if (autoMode && optimizeLevel > 9) {
 | 
			
		||||
                        logger.info("Maximum compression level reached in auto mode");
 | 
			
		||||
                        log.info("Maximum compression level reached in auto mode");
 | 
			
		||||
                        sizeMet = true;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
@ -203,7 +201,7 @@ public class CompressController {
 | 
			
		||||
 | 
			
		||||
            // Check if optimized file is larger than the original
 | 
			
		||||
            if (pdfBytes.length > inputFileSize) {
 | 
			
		||||
                logger.warn(
 | 
			
		||||
                log.warn(
 | 
			
		||||
                        "Optimized file is larger than the original. Returning the original file instead.");
 | 
			
		||||
                finalFile = tempInputFile;
 | 
			
		||||
            }
 | 
			
		||||
@ -234,7 +232,7 @@ public class CompressController {
 | 
			
		||||
 | 
			
		||||
    private int incrementOptimizeLevel(int currentLevel, long currentSize, long targetSize) {
 | 
			
		||||
        double currentRatio = currentSize / (double) targetSize;
 | 
			
		||||
        logger.info("Current compression ratio: {}", String.format("%.2f", currentRatio));
 | 
			
		||||
        log.info("Current compression ratio: {}", String.format("%.2f", currentRatio));
 | 
			
		||||
 | 
			
		||||
        if (currentRatio > 2.0) {
 | 
			
		||||
            return Math.min(9, currentLevel + 3);
 | 
			
		||||
 | 
			
		||||
@ -17,8 +17,6 @@ import org.apache.commons.io.FileUtils;
 | 
			
		||||
import org.apache.pdfbox.Loader;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.PDDocument;
 | 
			
		||||
import org.apache.pdfbox.rendering.PDFRenderer;
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
import org.springframework.http.MediaType;
 | 
			
		||||
import org.springframework.http.ResponseEntity;
 | 
			
		||||
import org.springframework.web.bind.annotation.PostMapping;
 | 
			
		||||
@ -31,6 +29,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
 | 
			
		||||
import io.swagger.v3.oas.annotations.parameters.RequestBody;
 | 
			
		||||
import io.swagger.v3.oas.annotations.tags.Tag;
 | 
			
		||||
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import stirling.software.SPDF.model.api.misc.ExtractImageScansRequest;
 | 
			
		||||
import stirling.software.SPDF.utils.CheckProgramInstall;
 | 
			
		||||
import stirling.software.SPDF.utils.ProcessExecutor;
 | 
			
		||||
@ -39,11 +38,10 @@ import stirling.software.SPDF.utils.WebResponseUtils;
 | 
			
		||||
 | 
			
		||||
@RestController
 | 
			
		||||
@RequestMapping("/api/v1/misc")
 | 
			
		||||
@Slf4j
 | 
			
		||||
@Tag(name = "Misc", description = "Miscellaneous APIs")
 | 
			
		||||
public class ExtractImageScansController {
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(ExtractImageScansController.class);
 | 
			
		||||
 | 
			
		||||
    @PostMapping(consumes = "multipart/form-data", value = "/extract-image-scans")
 | 
			
		||||
    @Operation(
 | 
			
		||||
            summary = "Extract image scans from an input file",
 | 
			
		||||
@ -201,7 +199,7 @@ public class ExtractImageScansController {
 | 
			
		||||
                        try {
 | 
			
		||||
                            Files.deleteIfExists(path);
 | 
			
		||||
                        } catch (IOException e) {
 | 
			
		||||
                            logger.error("Failed to delete temporary image file: " + path, e);
 | 
			
		||||
                            log.error("Failed to delete temporary image file: " + path, e);
 | 
			
		||||
                        }
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
@ -209,7 +207,7 @@ public class ExtractImageScansController {
 | 
			
		||||
                try {
 | 
			
		||||
                    Files.deleteIfExists(tempZipFile);
 | 
			
		||||
                } catch (IOException e) {
 | 
			
		||||
                    logger.error("Failed to delete temporary zip file: " + tempZipFile, e);
 | 
			
		||||
                    log.error("Failed to delete temporary zip file: " + tempZipFile, e);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@ -218,7 +216,7 @@ public class ExtractImageScansController {
 | 
			
		||||
                        try {
 | 
			
		||||
                            FileUtils.deleteDirectory(dir.toFile());
 | 
			
		||||
                        } catch (IOException e) {
 | 
			
		||||
                            logger.error("Failed to delete temporary directory: " + dir, e);
 | 
			
		||||
                            log.error("Failed to delete temporary directory: " + dir, e);
 | 
			
		||||
                        }
 | 
			
		||||
                    });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -25,8 +25,6 @@ import org.apache.pdfbox.cos.COSName;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.PDDocument;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.PDPage;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
 | 
			
		||||
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;
 | 
			
		||||
@ -39,17 +37,17 @@ import io.github.pixee.security.Filenames;
 | 
			
		||||
import io.swagger.v3.oas.annotations.Operation;
 | 
			
		||||
import io.swagger.v3.oas.annotations.tags.Tag;
 | 
			
		||||
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import stirling.software.SPDF.model.api.PDFExtractImagesRequest;
 | 
			
		||||
import stirling.software.SPDF.utils.ImageProcessingUtils;
 | 
			
		||||
import stirling.software.SPDF.utils.WebResponseUtils;
 | 
			
		||||
 | 
			
		||||
@RestController
 | 
			
		||||
@RequestMapping("/api/v1/misc")
 | 
			
		||||
@Slf4j
 | 
			
		||||
@Tag(name = "Misc", description = "Miscellaneous APIs")
 | 
			
		||||
public class ExtractImagesController {
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(ExtractImagesController.class);
 | 
			
		||||
 | 
			
		||||
    @PostMapping(consumes = "multipart/form-data", value = "/extract-images")
 | 
			
		||||
    @Operation(
 | 
			
		||||
            summary = "Extract images from a PDF file",
 | 
			
		||||
@ -107,7 +105,7 @@ public class ExtractImagesController {
 | 
			
		||||
                                                allowDuplicates);
 | 
			
		||||
                                    } catch (IOException e) {
 | 
			
		||||
                                        // Log the error and continue processing other pages
 | 
			
		||||
                                        logger.error(
 | 
			
		||||
                                        log.error(
 | 
			
		||||
                                                "Error extracting images from page {}: {}",
 | 
			
		||||
                                                pageNum,
 | 
			
		||||
                                                e.getMessage());
 | 
			
		||||
@ -167,7 +165,7 @@ public class ExtractImagesController {
 | 
			
		||||
        try {
 | 
			
		||||
            md = MessageDigest.getInstance("MD5");
 | 
			
		||||
        } catch (NoSuchAlgorithmException e) {
 | 
			
		||||
            logger.error("MD5 algorithm not available for extractImages hash.", e);
 | 
			
		||||
            log.error("MD5 algorithm not available for extractImages hash.", e);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        if (page.getResources() == null || page.getResources().getXObjectNames() == null) {
 | 
			
		||||
 | 
			
		||||
@ -27,8 +27,6 @@ import org.apache.pdfbox.pdmodel.graphics.image.JPEGFactory;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
 | 
			
		||||
import org.apache.pdfbox.rendering.ImageType;
 | 
			
		||||
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;
 | 
			
		||||
@ -50,8 +48,6 @@ import stirling.software.SPDF.utils.WebResponseUtils;
 | 
			
		||||
@Tag(name = "Misc", description = "Miscellaneous APIs")
 | 
			
		||||
public class FakeScanControllerWIP {
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(FakeScanControllerWIP.class);
 | 
			
		||||
 | 
			
		||||
    // TODO finish
 | 
			
		||||
    @PostMapping(consumes = "multipart/form-data", value = "/fake-scan")
 | 
			
		||||
    @Hidden
 | 
			
		||||
 | 
			
		||||
@ -12,8 +12,6 @@ import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
 | 
			
		||||
import org.apache.pdfbox.rendering.ImageType;
 | 
			
		||||
import org.apache.pdfbox.rendering.PDFRenderer;
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.http.ResponseEntity;
 | 
			
		||||
import org.springframework.web.bind.annotation.ModelAttribute;
 | 
			
		||||
@ -26,17 +24,17 @@ import io.github.pixee.security.Filenames;
 | 
			
		||||
import io.swagger.v3.oas.annotations.Operation;
 | 
			
		||||
import io.swagger.v3.oas.annotations.tags.Tag;
 | 
			
		||||
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import stirling.software.SPDF.model.api.misc.FlattenRequest;
 | 
			
		||||
import stirling.software.SPDF.service.CustomPDDocumentFactory;
 | 
			
		||||
import stirling.software.SPDF.utils.WebResponseUtils;
 | 
			
		||||
 | 
			
		||||
@RestController
 | 
			
		||||
@RequestMapping("/api/v1/misc")
 | 
			
		||||
@Slf4j
 | 
			
		||||
@Tag(name = "Misc", description = "Miscellaneous APIs")
 | 
			
		||||
public class FlattenController {
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(FlattenController.class);
 | 
			
		||||
 | 
			
		||||
    private final CustomPDDocumentFactory pdfDocumentFactory;
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
@ -84,7 +82,7 @@ public class FlattenController {
 | 
			
		||||
                        contentStream.drawImage(pdImage, 0, 0, pageWidth, pageHeight);
 | 
			
		||||
                    }
 | 
			
		||||
                } catch (IOException e) {
 | 
			
		||||
                    logger.error("exception", e);
 | 
			
		||||
                    log.error("exception", e);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return WebResponseUtils.pdfDocToWebResponse(
 | 
			
		||||
 | 
			
		||||
@ -11,8 +11,6 @@ import org.apache.pdfbox.Loader;
 | 
			
		||||
import org.apache.pdfbox.cos.COSName;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.PDDocument;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.PDDocumentInformation;
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
import org.springframework.http.ResponseEntity;
 | 
			
		||||
import org.springframework.web.bind.WebDataBinder;
 | 
			
		||||
import org.springframework.web.bind.annotation.InitBinder;
 | 
			
		||||
@ -26,17 +24,17 @@ import io.github.pixee.security.Filenames;
 | 
			
		||||
import io.swagger.v3.oas.annotations.Operation;
 | 
			
		||||
import io.swagger.v3.oas.annotations.tags.Tag;
 | 
			
		||||
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import stirling.software.SPDF.model.api.misc.MetadataRequest;
 | 
			
		||||
import stirling.software.SPDF.utils.WebResponseUtils;
 | 
			
		||||
import stirling.software.SPDF.utils.propertyeditor.StringToMapPropertyEditor;
 | 
			
		||||
 | 
			
		||||
@RestController
 | 
			
		||||
@RequestMapping("/api/v1/misc")
 | 
			
		||||
@Slf4j
 | 
			
		||||
@Tag(name = "Misc", description = "Miscellaneous APIs")
 | 
			
		||||
public class MetadataController {
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(MetadataController.class);
 | 
			
		||||
 | 
			
		||||
    private String checkUndefined(String entry) {
 | 
			
		||||
        // Check if the string is "undefined"
 | 
			
		||||
        if ("undefined".equals(entry)) {
 | 
			
		||||
@ -148,7 +146,7 @@ public class MetadataController {
 | 
			
		||||
                creationDateCal.setTime(
 | 
			
		||||
                        new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse(creationDate));
 | 
			
		||||
            } catch (ParseException e) {
 | 
			
		||||
                logger.error("exception", e);
 | 
			
		||||
                log.error("exception", e);
 | 
			
		||||
            }
 | 
			
		||||
            info.setCreationDate(creationDateCal);
 | 
			
		||||
        } else {
 | 
			
		||||
@ -160,7 +158,7 @@ public class MetadataController {
 | 
			
		||||
                modificationDateCal.setTime(
 | 
			
		||||
                        new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse(modificationDate));
 | 
			
		||||
            } catch (ParseException e) {
 | 
			
		||||
                logger.error("exception", e);
 | 
			
		||||
                log.error("exception", e);
 | 
			
		||||
            }
 | 
			
		||||
            info.setModificationDate(modificationDateCal);
 | 
			
		||||
        } else {
 | 
			
		||||
 | 
			
		||||
@ -2,8 +2,6 @@ package stirling.software.SPDF.controller.api.misc;
 | 
			
		||||
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.http.HttpStatus;
 | 
			
		||||
import org.springframework.http.ResponseEntity;
 | 
			
		||||
@ -17,6 +15,7 @@ import io.github.pixee.security.Filenames;
 | 
			
		||||
import io.swagger.v3.oas.annotations.Operation;
 | 
			
		||||
import io.swagger.v3.oas.annotations.tags.Tag;
 | 
			
		||||
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import stirling.software.SPDF.model.api.misc.OverlayImageRequest;
 | 
			
		||||
import stirling.software.SPDF.service.CustomPDDocumentFactory;
 | 
			
		||||
import stirling.software.SPDF.utils.PdfUtils;
 | 
			
		||||
@ -24,11 +23,10 @@ import stirling.software.SPDF.utils.WebResponseUtils;
 | 
			
		||||
 | 
			
		||||
@RestController
 | 
			
		||||
@RequestMapping("/api/v1/misc")
 | 
			
		||||
@Slf4j
 | 
			
		||||
@Tag(name = "Misc", description = "Miscellaneous APIs")
 | 
			
		||||
public class OverlayImageController {
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(OverlayImageController.class);
 | 
			
		||||
 | 
			
		||||
    private final CustomPDDocumentFactory pdfDocumentFactory;
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
@ -60,7 +58,7 @@ public class OverlayImageController {
 | 
			
		||||
                                    .replaceFirst("[.][^.]+$", "")
 | 
			
		||||
                            + "_overlayed.pdf");
 | 
			
		||||
        } catch (IOException e) {
 | 
			
		||||
            logger.error("Failed to add image to PDF", e);
 | 
			
		||||
            log.error("Failed to add image to PDF", e);
 | 
			
		||||
            return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -10,8 +10,6 @@ import org.apache.pdfbox.pdmodel.PDPageContentStream;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.common.PDRectangle;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.font.PDType1Font;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.font.Standard14Fonts;
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.http.MediaType;
 | 
			
		||||
import org.springframework.http.ResponseEntity;
 | 
			
		||||
@ -35,8 +33,6 @@ import stirling.software.SPDF.utils.WebResponseUtils;
 | 
			
		||||
@Tag(name = "Misc", description = "Miscellaneous APIs")
 | 
			
		||||
public class PageNumbersController {
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(PageNumbersController.class);
 | 
			
		||||
 | 
			
		||||
    private final CustomPDDocumentFactory pdfDocumentFactory;
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
 | 
			
		||||
@ -6,8 +6,6 @@ import java.nio.file.Path;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.http.ResponseEntity;
 | 
			
		||||
import org.springframework.web.bind.annotation.ModelAttribute;
 | 
			
		||||
@ -31,8 +29,6 @@ import stirling.software.SPDF.utils.WebResponseUtils;
 | 
			
		||||
@Tag(name = "Misc", description = "Miscellaneous APIs")
 | 
			
		||||
public class RepairController {
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(RepairController.class);
 | 
			
		||||
 | 
			
		||||
    private final CustomPDDocumentFactory pdfDocumentFactory;
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
 | 
			
		||||
@ -7,8 +7,6 @@ import org.apache.pdfbox.Loader;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.PDDocument;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.common.PDNameTreeNode;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.interactive.action.PDActionJavaScript;
 | 
			
		||||
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;
 | 
			
		||||
@ -29,8 +27,6 @@ import stirling.software.SPDF.utils.WebResponseUtils;
 | 
			
		||||
@Tag(name = "Misc", description = "Miscellaneous APIs")
 | 
			
		||||
public class ShowJavascript {
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(ShowJavascript.class);
 | 
			
		||||
 | 
			
		||||
    @PostMapping(consumes = "multipart/form-data", value = "/show-javascript")
 | 
			
		||||
    @Operation(
 | 
			
		||||
            summary = "Grabs all JS from a PDF and returns a single JS file with all code",
 | 
			
		||||
 | 
			
		||||
@ -7,8 +7,6 @@ import java.util.Map;
 | 
			
		||||
import java.util.regex.Matcher;
 | 
			
		||||
import java.util.regex.Pattern;
 | 
			
		||||
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.http.HttpEntity;
 | 
			
		||||
import org.springframework.http.HttpHeaders;
 | 
			
		||||
@ -21,17 +19,17 @@ import com.fasterxml.jackson.databind.JsonNode;
 | 
			
		||||
import com.fasterxml.jackson.databind.ObjectMapper;
 | 
			
		||||
 | 
			
		||||
import jakarta.servlet.ServletContext;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import stirling.software.SPDF.SPdfApplication;
 | 
			
		||||
import stirling.software.SPDF.model.ApiEndpoint;
 | 
			
		||||
import stirling.software.SPDF.model.Role;
 | 
			
		||||
 | 
			
		||||
@Service
 | 
			
		||||
@Slf4j
 | 
			
		||||
public class ApiDocService {
 | 
			
		||||
 | 
			
		||||
    private final Map<String, ApiEndpoint> apiDocumentation = new HashMap<>();
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(ApiDocService.class);
 | 
			
		||||
 | 
			
		||||
    @Autowired private ServletContext servletContext;
 | 
			
		||||
 | 
			
		||||
    private String getApiDocsUrl() {
 | 
			
		||||
@ -135,7 +133,7 @@ public class ApiDocService {
 | 
			
		||||
                            });
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            // Handle exceptions
 | 
			
		||||
            logger.error("Error grabbing swagger doc, body result {}", apiDocsJson);
 | 
			
		||||
            log.error("Error grabbing swagger doc, body result {}", apiDocsJson);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -8,8 +8,6 @@ import java.util.Map;
 | 
			
		||||
import java.util.zip.ZipEntry;
 | 
			
		||||
import java.util.zip.ZipOutputStream;
 | 
			
		||||
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.core.io.Resource;
 | 
			
		||||
import org.springframework.http.MediaType;
 | 
			
		||||
@ -26,6 +24,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
 | 
			
		||||
 | 
			
		||||
import io.swagger.v3.oas.annotations.tags.Tag;
 | 
			
		||||
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import stirling.software.SPDF.model.ApplicationProperties;
 | 
			
		||||
import stirling.software.SPDF.model.PipelineConfig;
 | 
			
		||||
import stirling.software.SPDF.model.api.HandleDataRequest;
 | 
			
		||||
@ -33,11 +32,10 @@ import stirling.software.SPDF.utils.WebResponseUtils;
 | 
			
		||||
 | 
			
		||||
@RestController
 | 
			
		||||
@RequestMapping("/api/v1/pipeline")
 | 
			
		||||
@Slf4j
 | 
			
		||||
@Tag(name = "Pipeline", description = "Pipeline APIs")
 | 
			
		||||
public class PipelineController {
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(PipelineController.class);
 | 
			
		||||
 | 
			
		||||
    final String watchedFoldersDir = "./pipeline/watchedFolders/";
 | 
			
		||||
    final String finishedFoldersDir = "./pipeline/finishedFolders/";
 | 
			
		||||
    @Autowired PipelineProcessor processor;
 | 
			
		||||
@ -56,7 +54,7 @@ public class PipelineController {
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
        PipelineConfig config = objectMapper.readValue(jsonString, PipelineConfig.class);
 | 
			
		||||
        logger.info("Received POST request to /handleData with {} files", files.length);
 | 
			
		||||
        log.info("Received POST request to /handleData with {} files", files.length);
 | 
			
		||||
        try {
 | 
			
		||||
            List<Resource> inputFiles = processor.generateInputFiles(files);
 | 
			
		||||
            if (inputFiles == null || inputFiles.size() == 0) {
 | 
			
		||||
@ -71,7 +69,7 @@ public class PipelineController {
 | 
			
		||||
                is.read(bytes);
 | 
			
		||||
                is.close();
 | 
			
		||||
 | 
			
		||||
                logger.info("Returning single file response...");
 | 
			
		||||
                log.info("Returning single file response...");
 | 
			
		||||
                return WebResponseUtils.bytesToWebResponse(
 | 
			
		||||
                        bytes, singleFile.getFilename(), MediaType.APPLICATION_OCTET_STREAM);
 | 
			
		||||
            } else if (outputFiles == null) {
 | 
			
		||||
@ -118,11 +116,11 @@ public class PipelineController {
 | 
			
		||||
 | 
			
		||||
            zipOut.close();
 | 
			
		||||
 | 
			
		||||
            logger.info("Returning zipped file response...");
 | 
			
		||||
            log.info("Returning zipped file response...");
 | 
			
		||||
            return WebResponseUtils.boasToWebResponse(
 | 
			
		||||
                    baos, "output.zip", MediaType.APPLICATION_OCTET_STREAM);
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            logger.error("Error handling data: ", e);
 | 
			
		||||
            log.error("Error handling data: ", e);
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -16,8 +16,6 @@ import java.util.List;
 | 
			
		||||
import java.util.Optional;
 | 
			
		||||
import java.util.stream.Stream;
 | 
			
		||||
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Qualifier;
 | 
			
		||||
import org.springframework.core.io.ByteArrayResource;
 | 
			
		||||
@ -27,14 +25,15 @@ import org.springframework.stereotype.Service;
 | 
			
		||||
 | 
			
		||||
import com.fasterxml.jackson.databind.ObjectMapper;
 | 
			
		||||
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import stirling.software.SPDF.model.PipelineConfig;
 | 
			
		||||
import stirling.software.SPDF.model.PipelineOperation;
 | 
			
		||||
import stirling.software.SPDF.utils.FileMonitor;
 | 
			
		||||
 | 
			
		||||
@Service
 | 
			
		||||
@Slf4j
 | 
			
		||||
public class PipelineDirectoryProcessor {
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(PipelineDirectoryProcessor.class);
 | 
			
		||||
    @Autowired private ObjectMapper objectMapper;
 | 
			
		||||
    @Autowired private ApiDocService apiDocService;
 | 
			
		||||
    @Autowired PipelineProcessor processor;
 | 
			
		||||
@ -56,9 +55,9 @@ public class PipelineDirectoryProcessor {
 | 
			
		||||
        if (!Files.exists(watchedFolderPath)) {
 | 
			
		||||
            try {
 | 
			
		||||
                Files.createDirectories(watchedFolderPath);
 | 
			
		||||
                logger.info("Created directory: {}", watchedFolderPath);
 | 
			
		||||
                log.info("Created directory: {}", watchedFolderPath);
 | 
			
		||||
            } catch (IOException e) {
 | 
			
		||||
                logger.error("Error creating directory: {}", watchedFolderPath, e);
 | 
			
		||||
                log.error("Error creating directory: {}", watchedFolderPath, e);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@ -71,21 +70,21 @@ public class PipelineDirectoryProcessor {
 | 
			
		||||
                                        handleDirectory(t);
 | 
			
		||||
                                    }
 | 
			
		||||
                                } catch (Exception e) {
 | 
			
		||||
                                    logger.error("Error handling directory: {}", t, e);
 | 
			
		||||
                                    log.error("Error handling directory: {}", t, e);
 | 
			
		||||
                                }
 | 
			
		||||
                            });
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            logger.error("Error walking through directory: {}", watchedFolderPath, e);
 | 
			
		||||
            log.error("Error walking through directory: {}", watchedFolderPath, e);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void handleDirectory(Path dir) throws IOException {
 | 
			
		||||
        logger.info("Handling directory: {}", dir);
 | 
			
		||||
        log.info("Handling directory: {}", dir);
 | 
			
		||||
        Path processingDir = createProcessingDirectory(dir);
 | 
			
		||||
 | 
			
		||||
        Optional<Path> jsonFileOptional = findJsonFile(dir);
 | 
			
		||||
        if (!jsonFileOptional.isPresent()) {
 | 
			
		||||
            logger.warn("No .JSON settings file found. No processing will happen for dir {}.", dir);
 | 
			
		||||
            log.warn("No .JSON settings file found. No processing will happen for dir {}.", dir);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -98,7 +97,7 @@ public class PipelineDirectoryProcessor {
 | 
			
		||||
        Path processingDir = dir.resolve("processing");
 | 
			
		||||
        if (!Files.exists(processingDir)) {
 | 
			
		||||
            Files.createDirectory(processingDir);
 | 
			
		||||
            logger.info("Created processing directory: {}", processingDir);
 | 
			
		||||
            log.info("Created processing directory: {}", processingDir);
 | 
			
		||||
        }
 | 
			
		||||
        return processingDir;
 | 
			
		||||
    }
 | 
			
		||||
@ -111,7 +110,7 @@ public class PipelineDirectoryProcessor {
 | 
			
		||||
 | 
			
		||||
    private PipelineConfig readAndParseJson(Path jsonFile) throws IOException {
 | 
			
		||||
        String jsonString = new String(Files.readAllBytes(jsonFile), StandardCharsets.UTF_8);
 | 
			
		||||
        logger.debug("Reading JSON file: {}", jsonFile);
 | 
			
		||||
        log.debug("Reading JSON file: {}", jsonFile);
 | 
			
		||||
        return objectMapper.readValue(jsonString, PipelineConfig.class);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -121,7 +120,7 @@ public class PipelineDirectoryProcessor {
 | 
			
		||||
            validateOperation(operation);
 | 
			
		||||
            File[] files = collectFilesForProcessing(dir, jsonFile, operation);
 | 
			
		||||
            if (files == null || files.length == 0) {
 | 
			
		||||
                logger.debug("No files detected for {} ", dir);
 | 
			
		||||
                log.debug("No files detected for {} ", dir);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            List<File> filesToProcess = prepareFilesForProcessing(files, processingDir);
 | 
			
		||||
@ -202,7 +201,7 @@ public class PipelineDirectoryProcessor {
 | 
			
		||||
            moveAndRenameFiles(outputFiles, config, dir);
 | 
			
		||||
            deleteOriginalFiles(filesToProcess, processingDir);
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            logger.error("error during processing", e);
 | 
			
		||||
            log.error("error during processing", e);
 | 
			
		||||
            moveFilesBack(filesToProcess, processingDir);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@ -215,7 +214,7 @@ public class PipelineDirectoryProcessor {
 | 
			
		||||
 | 
			
		||||
            if (!Files.exists(outputPath)) {
 | 
			
		||||
                Files.createDirectories(outputPath);
 | 
			
		||||
                logger.info("Created directory: {}", outputPath);
 | 
			
		||||
                log.info("Created directory: {}", outputPath);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            Path outputFile = outputPath.resolve(outputFileName);
 | 
			
		||||
@ -223,7 +222,7 @@ public class PipelineDirectoryProcessor {
 | 
			
		||||
                os.write(((ByteArrayResource) resource).getByteArray());
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            logger.info("File moved and renamed to {}", outputFile);
 | 
			
		||||
            log.info("File moved and renamed to {}", outputFile);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -264,7 +263,7 @@ public class PipelineDirectoryProcessor {
 | 
			
		||||
            throws IOException {
 | 
			
		||||
        for (File file : filesToProcess) {
 | 
			
		||||
            Files.deleteIfExists(processingDir.resolve(file.getName()));
 | 
			
		||||
            logger.info("Deleted original file: {}", file.getName());
 | 
			
		||||
            log.info("Deleted original file: {}", file.getName());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -272,12 +271,12 @@ public class PipelineDirectoryProcessor {
 | 
			
		||||
        for (File file : filesToProcess) {
 | 
			
		||||
            try {
 | 
			
		||||
                Files.move(processingDir.resolve(file.getName()), file.toPath());
 | 
			
		||||
                logger.info(
 | 
			
		||||
                log.info(
 | 
			
		||||
                        "Moved file back to original location: {} , {}",
 | 
			
		||||
                        file.toPath(),
 | 
			
		||||
                        file.getName());
 | 
			
		||||
            } catch (IOException e) {
 | 
			
		||||
                logger.error("Error moving file back to original location: {}", file.getName(), e);
 | 
			
		||||
                log.error("Error moving file back to original location: {}", file.getName(), e);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -19,8 +19,6 @@ import java.util.stream.Collectors;
 | 
			
		||||
import java.util.zip.ZipEntry;
 | 
			
		||||
import java.util.zip.ZipInputStream;
 | 
			
		||||
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.core.io.ByteArrayResource;
 | 
			
		||||
import org.springframework.core.io.Resource;
 | 
			
		||||
@ -40,16 +38,16 @@ import io.github.pixee.security.Filenames;
 | 
			
		||||
import io.github.pixee.security.ZipSecurity;
 | 
			
		||||
 | 
			
		||||
import jakarta.servlet.ServletContext;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import stirling.software.SPDF.SPdfApplication;
 | 
			
		||||
import stirling.software.SPDF.model.PipelineConfig;
 | 
			
		||||
import stirling.software.SPDF.model.PipelineOperation;
 | 
			
		||||
import stirling.software.SPDF.model.Role;
 | 
			
		||||
 | 
			
		||||
@Service
 | 
			
		||||
@Slf4j
 | 
			
		||||
public class PipelineProcessor {
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(PipelineProcessor.class);
 | 
			
		||||
 | 
			
		||||
    @Autowired private ApiDocService apiDocService;
 | 
			
		||||
 | 
			
		||||
    @Autowired(required = false)
 | 
			
		||||
@ -81,7 +79,7 @@ public class PipelineProcessor {
 | 
			
		||||
            String operation = pipelineOperation.getOperation();
 | 
			
		||||
            boolean isMultiInputOperation = apiDocService.isMultiInput(operation);
 | 
			
		||||
 | 
			
		||||
            logger.info(
 | 
			
		||||
            log.info(
 | 
			
		||||
                    "Running operation: {} isMultiInputOperation {}",
 | 
			
		||||
                    operation,
 | 
			
		||||
                    isMultiInputOperation);
 | 
			
		||||
@ -124,7 +122,7 @@ public class PipelineProcessor {
 | 
			
		||||
                            if (operation.startsWith("filter-")
 | 
			
		||||
                                    && (response.getBody() == null
 | 
			
		||||
                                            || response.getBody().length == 0)) {
 | 
			
		||||
                                logger.info("Skipping file due to failing {}", operation);
 | 
			
		||||
                                log.info("Skipping file due to failing {}", operation);
 | 
			
		||||
                                continue;
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
@ -208,7 +206,7 @@ public class PipelineProcessor {
 | 
			
		||||
            outputFiles = newOutputFiles;
 | 
			
		||||
        }
 | 
			
		||||
        if (hasErrors) {
 | 
			
		||||
            logger.error("Errors occurred during processing. Log: {}", logStream.toString());
 | 
			
		||||
            log.error("Errors occurred during processing. Log: {}", logStream.toString());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return outputFiles;
 | 
			
		||||
@ -310,7 +308,7 @@ public class PipelineProcessor {
 | 
			
		||||
 | 
			
		||||
    List<Resource> generateInputFiles(File[] files) throws Exception {
 | 
			
		||||
        if (files == null || files.length == 0) {
 | 
			
		||||
            logger.info("No files");
 | 
			
		||||
            log.info("No files");
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -318,7 +316,7 @@ public class PipelineProcessor {
 | 
			
		||||
 | 
			
		||||
        for (File file : files) {
 | 
			
		||||
            Path path = Paths.get(file.getAbsolutePath());
 | 
			
		||||
            logger.info("Reading file: " + path); // debug statement
 | 
			
		||||
            log.info("Reading file: " + path); // debug statement
 | 
			
		||||
 | 
			
		||||
            if (Files.exists(path)) {
 | 
			
		||||
                Resource fileResource =
 | 
			
		||||
@ -330,16 +328,16 @@ public class PipelineProcessor {
 | 
			
		||||
                        };
 | 
			
		||||
                outputFiles.add(fileResource);
 | 
			
		||||
            } else {
 | 
			
		||||
                logger.info("File not found: " + path);
 | 
			
		||||
                log.info("File not found: " + path);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        logger.info("Files successfully loaded. Starting processing...");
 | 
			
		||||
        log.info("Files successfully loaded. Starting processing...");
 | 
			
		||||
        return outputFiles;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    List<Resource> generateInputFiles(MultipartFile[] files) throws Exception {
 | 
			
		||||
        if (files == null || files.length == 0) {
 | 
			
		||||
            logger.info("No files");
 | 
			
		||||
            log.info("No files");
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -355,7 +353,7 @@ public class PipelineProcessor {
 | 
			
		||||
                    };
 | 
			
		||||
            outputFiles.add(fileResource);
 | 
			
		||||
        }
 | 
			
		||||
        logger.info("Files successfully loaded. Starting processing...");
 | 
			
		||||
        log.info("Files successfully loaded. Starting processing...");
 | 
			
		||||
        return outputFiles;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -369,7 +367,7 @@ public class PipelineProcessor {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private List<Resource> unzip(byte[] data) throws IOException {
 | 
			
		||||
        logger.info("Unzipping data of length: {}", data.length);
 | 
			
		||||
        log.info("Unzipping data of length: {}", data.length);
 | 
			
		||||
        List<Resource> unzippedFiles = new ArrayList<>();
 | 
			
		||||
 | 
			
		||||
        try (ByteArrayInputStream bais = new ByteArrayInputStream(data);
 | 
			
		||||
@ -396,7 +394,7 @@ public class PipelineProcessor {
 | 
			
		||||
 | 
			
		||||
                // If the unzipped file is a zip file, unzip it
 | 
			
		||||
                if (isZip(baos.toByteArray())) {
 | 
			
		||||
                    logger.info("File {} is a zip file. Unzipping...", filename);
 | 
			
		||||
                    log.info("File {} is a zip file. Unzipping...", filename);
 | 
			
		||||
                    unzippedFiles.addAll(unzip(baos.toByteArray()));
 | 
			
		||||
                } else {
 | 
			
		||||
                    unzippedFiles.add(fileResource);
 | 
			
		||||
@ -404,7 +402,7 @@ public class PipelineProcessor {
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        logger.info("Unzipping completed. {} files were unzipped.", unzippedFiles.size());
 | 
			
		||||
        log.info("Unzipping completed. {} files were unzipped.", unzippedFiles.size());
 | 
			
		||||
        return unzippedFiles;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -63,8 +63,6 @@ import org.bouncycastle.operator.InputDecryptorProvider;
 | 
			
		||||
import org.bouncycastle.operator.OperatorCreationException;
 | 
			
		||||
import org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo;
 | 
			
		||||
import org.bouncycastle.pkcs.PKCSException;
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.core.io.ClassPathResource;
 | 
			
		||||
import org.springframework.http.ResponseEntity;
 | 
			
		||||
@ -78,17 +76,17 @@ import io.github.pixee.security.Filenames;
 | 
			
		||||
import io.swagger.v3.oas.annotations.Operation;
 | 
			
		||||
import io.swagger.v3.oas.annotations.tags.Tag;
 | 
			
		||||
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import stirling.software.SPDF.model.api.security.SignPDFWithCertRequest;
 | 
			
		||||
import stirling.software.SPDF.service.CustomPDDocumentFactory;
 | 
			
		||||
import stirling.software.SPDF.utils.WebResponseUtils;
 | 
			
		||||
 | 
			
		||||
@RestController
 | 
			
		||||
@RequestMapping("/api/v1/security")
 | 
			
		||||
@Slf4j
 | 
			
		||||
@Tag(name = "Security", description = "Security APIs")
 | 
			
		||||
public class CertSignController {
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(CertSignController.class);
 | 
			
		||||
 | 
			
		||||
    static {
 | 
			
		||||
        Security.addProvider(new BouncyCastleProvider());
 | 
			
		||||
    }
 | 
			
		||||
@ -108,7 +106,7 @@ public class CertSignController {
 | 
			
		||||
                logoFile = Files.createTempFile("signature", ".png").toFile();
 | 
			
		||||
                FileUtils.copyInputStreamToFile(is, logoFile);
 | 
			
		||||
            } catch (IOException e) {
 | 
			
		||||
                logger.error("Failed to load image signature file");
 | 
			
		||||
                log.error("Failed to load image signature file");
 | 
			
		||||
                throw e;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@ -212,7 +210,9 @@ public class CertSignController {
 | 
			
		||||
    @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:SISO")
 | 
			
		||||
                    "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:SISO")
 | 
			
		||||
    public ResponseEntity<byte[]> signPDFWithCert(@ModelAttribute SignPDFWithCertRequest request)
 | 
			
		||||
            throws Exception {
 | 
			
		||||
        MultipartFile pdf = request.getFileInput();
 | 
			
		||||
@ -308,7 +308,7 @@ public class CertSignController {
 | 
			
		||||
            }
 | 
			
		||||
            doc.saveIncremental(output);
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            logger.error("exception", e);
 | 
			
		||||
            log.error("exception", e);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -56,8 +56,6 @@ import org.apache.xmpbox.XMPMetadata;
 | 
			
		||||
import org.apache.xmpbox.xml.DomXmpParser;
 | 
			
		||||
import org.apache.xmpbox.xml.XmpParsingException;
 | 
			
		||||
import org.apache.xmpbox.xml.XmpSerializer;
 | 
			
		||||
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;
 | 
			
		||||
@ -73,16 +71,16 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
 | 
			
		||||
import io.swagger.v3.oas.annotations.Operation;
 | 
			
		||||
import io.swagger.v3.oas.annotations.tags.Tag;
 | 
			
		||||
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import stirling.software.SPDF.model.api.PDFFile;
 | 
			
		||||
import stirling.software.SPDF.utils.WebResponseUtils;
 | 
			
		||||
 | 
			
		||||
@RestController
 | 
			
		||||
@RequestMapping("/api/v1/security")
 | 
			
		||||
@Slf4j
 | 
			
		||||
@Tag(name = "Security", description = "Security APIs")
 | 
			
		||||
public class GetInfoOnPDF {
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(GetInfoOnPDF.class);
 | 
			
		||||
 | 
			
		||||
    static ObjectMapper objectMapper = new ObjectMapper();
 | 
			
		||||
 | 
			
		||||
    @PostMapping(consumes = "multipart/form-data", value = "/get-info-on-pdf")
 | 
			
		||||
@ -224,7 +222,7 @@ public class GetInfoOnPDF {
 | 
			
		||||
                            javascriptArray.add(jsNode);
 | 
			
		||||
                        }
 | 
			
		||||
                    } catch (IOException e) {
 | 
			
		||||
                        logger.error("exception", e);
 | 
			
		||||
                        log.error("exception", e);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@ -257,7 +255,7 @@ public class GetInfoOnPDF {
 | 
			
		||||
                }
 | 
			
		||||
            } catch (Exception e) {
 | 
			
		||||
                // TODO Auto-generated catch block
 | 
			
		||||
                logger.error("exception", e);
 | 
			
		||||
                log.error("exception", e);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            boolean isPdfACompliant = checkForStandard(pdfBoxDoc, "PDF/A");
 | 
			
		||||
@ -309,7 +307,7 @@ public class GetInfoOnPDF {
 | 
			
		||||
                    new XmpSerializer().serialize(xmpMeta, os, true);
 | 
			
		||||
                    xmpString = new String(os.toByteArray(), StandardCharsets.UTF_8);
 | 
			
		||||
                } catch (XmpParsingException | IOException e) {
 | 
			
		||||
                    logger.error("exception", e);
 | 
			
		||||
                    log.error("exception", e);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@ -585,7 +583,7 @@ public class GetInfoOnPDF {
 | 
			
		||||
                    MediaType.APPLICATION_JSON);
 | 
			
		||||
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            logger.error("exception", e);
 | 
			
		||||
            log.error("exception", e);
 | 
			
		||||
        }
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
@ -701,7 +699,7 @@ public class GetInfoOnPDF {
 | 
			
		||||
                Exception
 | 
			
		||||
                        e) { // Catching general exception for brevity, ideally you'd catch specific
 | 
			
		||||
            // exceptions.
 | 
			
		||||
            logger.error("exception", e);
 | 
			
		||||
            log.error("exception", e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
 | 
			
		||||
@ -5,8 +5,6 @@ import java.io.IOException;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.PDDocument;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.encryption.AccessPermission;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.encryption.StandardProtectionPolicy;
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.http.ResponseEntity;
 | 
			
		||||
import org.springframework.web.bind.annotation.ModelAttribute;
 | 
			
		||||
@ -29,8 +27,6 @@ import stirling.software.SPDF.utils.WebResponseUtils;
 | 
			
		||||
@Tag(name = "Security", description = "Security APIs")
 | 
			
		||||
public class PasswordController {
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(PasswordController.class);
 | 
			
		||||
 | 
			
		||||
    private final CustomPDDocumentFactory pdfDocumentFactory;
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
@ -39,7 +35,11 @@ public class PasswordController {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @PostMapping(consumes = "multipart/form-data", value = "/remove-password")
 | 
			
		||||
    @Operation(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")
 | 
			
		||||
    @Operation(
 | 
			
		||||
            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<byte[]> removePassword(@ModelAttribute PDFPasswordRequest request)
 | 
			
		||||
            throws IOException {
 | 
			
		||||
        MultipartFile fileInput = request.getFileInput();
 | 
			
		||||
@ -54,7 +54,11 @@ public class PasswordController {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @PostMapping(consumes = "multipart/form-data", value = "/add-password")
 | 
			
		||||
    @Operation(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")
 | 
			
		||||
    @Operation(
 | 
			
		||||
            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<byte[]> addPassword(@ModelAttribute AddPasswordRequest request)
 | 
			
		||||
            throws IOException {
 | 
			
		||||
        MultipartFile fileInput = request.getFileInput();
 | 
			
		||||
 | 
			
		||||
@ -8,8 +8,6 @@ import java.util.List;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.PDDocument;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.PDPageContentStream;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.common.PDRectangle;
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.http.ResponseEntity;
 | 
			
		||||
import org.springframework.web.bind.annotation.ModelAttribute;
 | 
			
		||||
@ -22,6 +20,7 @@ import io.github.pixee.security.Filenames;
 | 
			
		||||
import io.swagger.v3.oas.annotations.Operation;
 | 
			
		||||
import io.swagger.v3.oas.annotations.tags.Tag;
 | 
			
		||||
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import stirling.software.SPDF.model.PDFText;
 | 
			
		||||
import stirling.software.SPDF.model.api.security.RedactPdfRequest;
 | 
			
		||||
import stirling.software.SPDF.pdf.TextFinder;
 | 
			
		||||
@ -31,11 +30,10 @@ import stirling.software.SPDF.utils.WebResponseUtils;
 | 
			
		||||
 | 
			
		||||
@RestController
 | 
			
		||||
@RequestMapping("/api/v1/security")
 | 
			
		||||
@Slf4j
 | 
			
		||||
@Tag(name = "Security", description = "Security APIs")
 | 
			
		||||
public class RedactController {
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(RedactController.class);
 | 
			
		||||
 | 
			
		||||
    private final CustomPDDocumentFactory pdfDocumentFactory;
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
@ -47,7 +45,8 @@ public class RedactController {
 | 
			
		||||
    @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")
 | 
			
		||||
                    "This operation takes an input PDF file and redacts the provided listOfText. Input:PDF,"
 | 
			
		||||
                            + " Output:PDF, Type:SISO")
 | 
			
		||||
    public ResponseEntity<byte[]> redactPdf(@ModelAttribute RedactPdfRequest request)
 | 
			
		||||
            throws Exception {
 | 
			
		||||
        MultipartFile file = request.getFileInput();
 | 
			
		||||
@ -68,7 +67,7 @@ public class RedactController {
 | 
			
		||||
            }
 | 
			
		||||
            redactColor = Color.decode(colorString);
 | 
			
		||||
        } catch (NumberFormatException e) {
 | 
			
		||||
            logger.warn("Invalid color string provided. Using default color BLACK for redaction.");
 | 
			
		||||
            log.warn("Invalid color string provided. Using default color BLACK for redaction.");
 | 
			
		||||
            redactColor = Color.BLACK;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -8,8 +8,6 @@ import org.apache.pdfbox.pdmodel.PDDocumentCatalog;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.interactive.form.PDField;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.interactive.form.PDSignatureField;
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.http.ResponseEntity;
 | 
			
		||||
import org.springframework.web.bind.annotation.ModelAttribute;
 | 
			
		||||
@ -31,8 +29,6 @@ import stirling.software.SPDF.utils.WebResponseUtils;
 | 
			
		||||
@Tag(name = "Security", description = "Security APIs")
 | 
			
		||||
public class RemoveCertSignController {
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(RemoveCertSignController.class);
 | 
			
		||||
 | 
			
		||||
    private final CustomPDDocumentFactory pdfDocumentFactory;
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
@ -44,7 +40,8 @@ public class RemoveCertSignController {
 | 
			
		||||
    @Operation(
 | 
			
		||||
            summary = "Remove digital signature from PDF",
 | 
			
		||||
            description =
 | 
			
		||||
                    "This endpoint accepts a PDF file and returns the PDF file without the digital signature. Input: PDF, Output: PDF")
 | 
			
		||||
                    "This endpoint accepts a PDF file and returns the PDF file without the digital signature."
 | 
			
		||||
                            + " Input: PDF, Output: PDF")
 | 
			
		||||
    public ResponseEntity<byte[]> removeCertSignPDF(@ModelAttribute PDFFile request)
 | 
			
		||||
            throws Exception {
 | 
			
		||||
        MultipartFile pdf = request.getFileInput();
 | 
			
		||||
 | 
			
		||||
@ -15,8 +15,6 @@ import java.util.Objects;
 | 
			
		||||
import java.util.stream.Collectors;
 | 
			
		||||
import java.util.stream.Stream;
 | 
			
		||||
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.core.io.Resource;
 | 
			
		||||
import org.springframework.core.io.ResourceLoader;
 | 
			
		||||
@ -31,16 +29,16 @@ import com.fasterxml.jackson.databind.ObjectMapper;
 | 
			
		||||
import io.swagger.v3.oas.annotations.Hidden;
 | 
			
		||||
import io.swagger.v3.oas.annotations.tags.Tag;
 | 
			
		||||
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import stirling.software.SPDF.controller.api.pipeline.UserServiceInterface;
 | 
			
		||||
import stirling.software.SPDF.model.SignatureFile;
 | 
			
		||||
import stirling.software.SPDF.service.SignatureService;
 | 
			
		||||
 | 
			
		||||
@Controller
 | 
			
		||||
@Tag(name = "General", description = "General APIs")
 | 
			
		||||
@Slf4j
 | 
			
		||||
public class GeneralWebController {
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(GeneralWebController.class);
 | 
			
		||||
 | 
			
		||||
    @GetMapping("/pipeline")
 | 
			
		||||
    @Hidden
 | 
			
		||||
    public String pipelineForm(Model model) {
 | 
			
		||||
@ -82,7 +80,7 @@ public class GeneralWebController {
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            } catch (IOException e) {
 | 
			
		||||
                logger.error("exception", e);
 | 
			
		||||
                log.error("exception", e);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if (pipelineConfigsWithNames.size() == 0) {
 | 
			
		||||
 | 
			
		||||
@ -6,8 +6,6 @@ import java.nio.charset.StandardCharsets;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.core.io.ClassPathResource;
 | 
			
		||||
import org.springframework.core.io.Resource;
 | 
			
		||||
@ -22,14 +20,14 @@ import com.fasterxml.jackson.databind.ObjectMapper;
 | 
			
		||||
 | 
			
		||||
import io.swagger.v3.oas.annotations.Hidden;
 | 
			
		||||
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import stirling.software.SPDF.model.ApplicationProperties;
 | 
			
		||||
import stirling.software.SPDF.model.Dependency;
 | 
			
		||||
 | 
			
		||||
@Controller
 | 
			
		||||
@Slf4j
 | 
			
		||||
public class HomeWebController {
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(HomeWebController.class);
 | 
			
		||||
 | 
			
		||||
    @GetMapping("/about")
 | 
			
		||||
    @Hidden
 | 
			
		||||
    public String gameForm(Model model) {
 | 
			
		||||
@ -50,7 +48,7 @@ public class HomeWebController {
 | 
			
		||||
                    mapper.readValue(json, new TypeReference<Map<String, List<Dependency>>>() {});
 | 
			
		||||
            model.addAttribute("dependencies", data.get("dependencies"));
 | 
			
		||||
        } catch (IOException e) {
 | 
			
		||||
            logger.error("exception", e);
 | 
			
		||||
            log.error("exception", e);
 | 
			
		||||
        }
 | 
			
		||||
        return "licenses";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -5,8 +5,6 @@ import java.util.List;
 | 
			
		||||
 | 
			
		||||
import org.apache.pdfbox.Loader;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.PDDocument;
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
 | 
			
		||||
import io.swagger.v3.oas.annotations.Hidden;
 | 
			
		||||
import io.swagger.v3.oas.annotations.media.Schema;
 | 
			
		||||
@ -14,18 +12,20 @@ import io.swagger.v3.oas.annotations.media.Schema;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import lombok.EqualsAndHashCode;
 | 
			
		||||
import lombok.NoArgsConstructor;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import stirling.software.SPDF.utils.GeneralUtils;
 | 
			
		||||
 | 
			
		||||
@Data
 | 
			
		||||
@NoArgsConstructor
 | 
			
		||||
@Slf4j
 | 
			
		||||
@EqualsAndHashCode(callSuper = true)
 | 
			
		||||
public class PDFWithPageNums extends PDFFile {
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(PDFWithPageNums.class);
 | 
			
		||||
 | 
			
		||||
    @Schema(
 | 
			
		||||
            description =
 | 
			
		||||
                    "The pages to select, Supports ranges (e.g., '1,3,5-9'), or 'all' or functions in the format 'an+b' where 'a' is the multiplier of the page number 'n', and 'b' is a constant (e.g., '2n+1', '3n', '6n-5')\"")
 | 
			
		||||
                    "The pages to select, Supports ranges (e.g., '1,3,5-9'), or 'all' or functions in the"
 | 
			
		||||
                            + " format 'an+b' where 'a' is the multiplier of the page number 'n', and 'b' is a"
 | 
			
		||||
                            + " constant (e.g., '2n+1', '3n', '6n-5')\"")
 | 
			
		||||
    private String pageNumbers;
 | 
			
		||||
 | 
			
		||||
    @Hidden
 | 
			
		||||
@ -35,7 +35,7 @@ public class PDFWithPageNums extends PDFFile {
 | 
			
		||||
            pageCount = Loader.loadPDF(getFileInput().getBytes()).getNumberOfPages();
 | 
			
		||||
        } catch (IOException e) {
 | 
			
		||||
            // TODO Auto-generated catch block
 | 
			
		||||
            logger.error("exception", e);
 | 
			
		||||
            log.error("exception", e);
 | 
			
		||||
        }
 | 
			
		||||
        return GeneralUtils.parsePageList(pageNumbers, pageCount, zeroCount);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -7,20 +7,18 @@ import java.io.InputStream;
 | 
			
		||||
 | 
			
		||||
import org.apache.pdfbox.Loader;
 | 
			
		||||
import org.apache.pdfbox.pdmodel.PDDocument;
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.stereotype.Component;
 | 
			
		||||
import org.springframework.web.multipart.MultipartFile;
 | 
			
		||||
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import stirling.software.SPDF.model.PdfMetadata;
 | 
			
		||||
import stirling.software.SPDF.model.api.PDFFile;
 | 
			
		||||
 | 
			
		||||
@Component
 | 
			
		||||
@Slf4j
 | 
			
		||||
public class CustomPDDocumentFactory {
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(CustomPDDocumentFactory.class);
 | 
			
		||||
 | 
			
		||||
    private final PdfMetadataService pdfMetadataService;
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
@ -133,10 +131,10 @@ public class CustomPDDocumentFactory {
 | 
			
		||||
    private PDDocument removezeropassword(PDDocument document) throws IOException {
 | 
			
		||||
        if (document.isEncrypted()) {
 | 
			
		||||
            try {
 | 
			
		||||
                logger.info("Removing security from the source document");
 | 
			
		||||
                log.info("Removing security from the source document");
 | 
			
		||||
                document.setAllSecurityToBeRemoved(true);
 | 
			
		||||
            } catch (Exception e) {
 | 
			
		||||
                logger.warn("Cannot decrypt the pdf");
 | 
			
		||||
                log.warn("Cannot decrypt the pdf");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return document;
 | 
			
		||||
 | 
			
		||||
@ -9,16 +9,17 @@ import java.util.concurrent.ConcurrentHashMap;
 | 
			
		||||
import java.util.function.Predicate;
 | 
			
		||||
import java.util.stream.Stream;
 | 
			
		||||
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Qualifier;
 | 
			
		||||
import org.springframework.scheduling.annotation.Scheduled;
 | 
			
		||||
import org.springframework.stereotype.Component;
 | 
			
		||||
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
 | 
			
		||||
@Component
 | 
			
		||||
@Slf4j
 | 
			
		||||
public class FileMonitor {
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(FileMonitor.class);
 | 
			
		||||
 | 
			
		||||
    private final Map<Path, WatchKey> path2KeyMapping;
 | 
			
		||||
    private final Set<Path> newlyDiscoveredFiles;
 | 
			
		||||
    private final ConcurrentHashMap.KeySetView<Path, Boolean> readyForProcessingFiles;
 | 
			
		||||
@ -53,7 +54,7 @@ public class FileMonitor {
 | 
			
		||||
    private void recursivelyRegisterEntry(Path dir) throws IOException {
 | 
			
		||||
        WatchKey key = dir.register(watchService, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
 | 
			
		||||
        path2KeyMapping.put(dir, key);
 | 
			
		||||
        logger.info("Registered directory: {}", dir);
 | 
			
		||||
        log.info("Registered directory: {}", dir);
 | 
			
		||||
 | 
			
		||||
        try (Stream<Path> directoryVisitor = Files.walk(dir, 1)) {
 | 
			
		||||
            final Iterator<Path> iterator = directoryVisitor.iterator();
 | 
			
		||||
@ -80,14 +81,13 @@ public class FileMonitor {
 | 
			
		||||
        readyForProcessingFiles.clear();
 | 
			
		||||
 | 
			
		||||
        if (path2KeyMapping.isEmpty()) {
 | 
			
		||||
            logger.warn(
 | 
			
		||||
                    "not monitoring any directory, even the root directory itself: {}", rootDir);
 | 
			
		||||
            log.warn("not monitoring any directory, even the root directory itself: {}", rootDir);
 | 
			
		||||
            if (Files.exists(
 | 
			
		||||
                    rootDir)) { // if the root directory exists, re-register the root directory
 | 
			
		||||
                try {
 | 
			
		||||
                    recursivelyRegisterEntry(rootDir);
 | 
			
		||||
                } catch (IOException e) {
 | 
			
		||||
                    logger.error("unable to register monitoring", e);
 | 
			
		||||
                    log.error("unable to register monitoring", e);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@ -122,7 +122,7 @@ public class FileMonitor {
 | 
			
		||||
                                        handleFileModification(relativePathFromRoot);
 | 
			
		||||
                                    }
 | 
			
		||||
                                } catch (Exception e) {
 | 
			
		||||
                                    logger.error("Error while processing file: {}", path, e);
 | 
			
		||||
                                    log.error("Error while processing file: {}", path, e);
 | 
			
		||||
                                }
 | 
			
		||||
                            });
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -27,8 +27,6 @@ import org.simpleyaml.configuration.file.YamlFile;
 | 
			
		||||
import org.simpleyaml.configuration.file.YamlFileWrapper;
 | 
			
		||||
import org.simpleyaml.configuration.implementation.SimpleYamlImplementation;
 | 
			
		||||
import org.simpleyaml.configuration.implementation.snakeyaml.lib.DumperOptions;
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
import org.springframework.web.multipart.MultipartFile;
 | 
			
		||||
 | 
			
		||||
import com.fathzer.soft.javaluator.DoubleEvaluator;
 | 
			
		||||
@ -36,9 +34,10 @@ import com.fathzer.soft.javaluator.DoubleEvaluator;
 | 
			
		||||
import io.github.pixee.security.HostValidator;
 | 
			
		||||
import io.github.pixee.security.Urls;
 | 
			
		||||
 | 
			
		||||
public class GeneralUtils {
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(GeneralUtils.class);
 | 
			
		||||
@Slf4j
 | 
			
		||||
public class GeneralUtils {
 | 
			
		||||
 | 
			
		||||
    public static File convertMultipartFileToFile(MultipartFile multipartFile) throws IOException {
 | 
			
		||||
        File tempFile = Files.createTempFile("temp", null).toFile();
 | 
			
		||||
@ -121,10 +120,15 @@ public class GeneralUtils {
 | 
			
		||||
            InetAddress address = InetAddress.getByName(host);
 | 
			
		||||
 | 
			
		||||
            // Check for local addresses
 | 
			
		||||
            return address.isAnyLocalAddress() ||  // Matches 0.0.0.0 or similar
 | 
			
		||||
                   address.isLoopbackAddress() || // Matches 127.0.0.1 or ::1
 | 
			
		||||
                   address.isSiteLocalAddress() || // Matches private IPv4 ranges: 192.168.x.x, 10.x.x.x, 172.16.x.x to 172.31.x.x
 | 
			
		||||
                   address.getHostAddress().startsWith("fe80:"); // Matches link-local IPv6 addresses
 | 
			
		||||
            return address.isAnyLocalAddress()
 | 
			
		||||
                    || // Matches 0.0.0.0 or similar
 | 
			
		||||
                    address.isLoopbackAddress()
 | 
			
		||||
                    || // Matches 127.0.0.1 or ::1
 | 
			
		||||
                    address.isSiteLocalAddress()
 | 
			
		||||
                    || // Matches private IPv4 ranges: 192.168.x.x, 10.x.x.x, 172.16.x.x to
 | 
			
		||||
                    // 172.31.x.x
 | 
			
		||||
                    address.getHostAddress()
 | 
			
		||||
                            .startsWith("fe80:"); // Matches link-local IPv6 addresses
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            return false; // Return false for invalid or unresolved addresses
 | 
			
		||||
        }
 | 
			
		||||
@ -296,7 +300,7 @@ public class GeneralUtils {
 | 
			
		||||
            try {
 | 
			
		||||
                Files.createDirectories(folder);
 | 
			
		||||
            } catch (IOException e) {
 | 
			
		||||
                logger.error("exception", e);
 | 
			
		||||
                log.error("exception", e);
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -12,8 +12,6 @@ import java.nio.ByteBuffer;
 | 
			
		||||
 | 
			
		||||
import javax.imageio.ImageIO;
 | 
			
		||||
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
import org.springframework.web.multipart.MultipartFile;
 | 
			
		||||
 | 
			
		||||
import com.drew.imaging.ImageMetadataReader;
 | 
			
		||||
@ -22,9 +20,10 @@ import com.drew.metadata.Metadata;
 | 
			
		||||
import com.drew.metadata.MetadataException;
 | 
			
		||||
import com.drew.metadata.exif.ExifSubIFDDirectory;
 | 
			
		||||
 | 
			
		||||
public class ImageProcessingUtils {
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(PdfUtils.class);
 | 
			
		||||
@Slf4j
 | 
			
		||||
public class ImageProcessingUtils {
 | 
			
		||||
 | 
			
		||||
    static BufferedImage convertColorType(BufferedImage sourceImage, String colorType) {
 | 
			
		||||
        BufferedImage convertedImage;
 | 
			
		||||
@ -97,7 +96,7 @@ public class ImageProcessingUtils {
 | 
			
		||||
                case 8:
 | 
			
		||||
                    return 270;
 | 
			
		||||
                default:
 | 
			
		||||
                    logger.warn("Unknown orientation tag: {}", orientationTag);
 | 
			
		||||
                    log.warn("Unknown orientation tag: {}", orientationTag);
 | 
			
		||||
                    return 0;
 | 
			
		||||
            }
 | 
			
		||||
        } catch (ImageProcessingException | MetadataException e) {
 | 
			
		||||
 | 
			
		||||
@ -14,8 +14,6 @@ import java.util.zip.ZipOutputStream;
 | 
			
		||||
 | 
			
		||||
import org.apache.commons.io.FileUtils;
 | 
			
		||||
import org.apache.commons.io.IOUtils;
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
import org.springframework.http.HttpStatus;
 | 
			
		||||
import org.springframework.http.MediaType;
 | 
			
		||||
import org.springframework.http.ResponseEntity;
 | 
			
		||||
@ -23,10 +21,11 @@ import org.springframework.web.multipart.MultipartFile;
 | 
			
		||||
 | 
			
		||||
import io.github.pixee.security.Filenames;
 | 
			
		||||
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult;
 | 
			
		||||
 | 
			
		||||
@Slf4j
 | 
			
		||||
public class PDFToFile {
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(PDFToFile.class);
 | 
			
		||||
 | 
			
		||||
    public ResponseEntity<byte[]> processPdfToHtml(MultipartFile inputFile)
 | 
			
		||||
            throws IOException, InterruptedException {
 | 
			
		||||
@ -77,12 +76,12 @@ public class PDFToFile {
 | 
			
		||||
                    try (FileInputStream fis = new FileInputStream(outputFile)) {
 | 
			
		||||
                        IOUtils.copy(fis, zipOutputStream);
 | 
			
		||||
                    } catch (IOException e) {
 | 
			
		||||
                        logger.error("Exception writing zip entry", e);
 | 
			
		||||
                        log.error("Exception writing zip entry", e);
 | 
			
		||||
                    }
 | 
			
		||||
                    zipOutputStream.closeEntry();
 | 
			
		||||
                }
 | 
			
		||||
            } catch (IOException e) {
 | 
			
		||||
                logger.error("Exception writing zip", e);
 | 
			
		||||
                log.error("Exception writing zip", e);
 | 
			
		||||
            }
 | 
			
		||||
            fileBytes = byteArrayOutputStream.toByteArray();
 | 
			
		||||
 | 
			
		||||
@ -174,13 +173,13 @@ public class PDFToFile {
 | 
			
		||||
                        try (FileInputStream fis = new FileInputStream(outputFile)) {
 | 
			
		||||
                            IOUtils.copy(fis, zipOutputStream);
 | 
			
		||||
                        } catch (IOException e) {
 | 
			
		||||
                            logger.error("Exception writing zip entry", e);
 | 
			
		||||
                            log.error("Exception writing zip entry", e);
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        zipOutputStream.closeEntry();
 | 
			
		||||
                    }
 | 
			
		||||
                } catch (IOException e) {
 | 
			
		||||
                    logger.error("Exception writing zip", e);
 | 
			
		||||
                    log.error("Exception writing zip", e);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                fileBytes = byteArrayOutputStream.toByteArray();
 | 
			
		||||
 | 
			
		||||
@ -30,18 +30,16 @@ import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
 | 
			
		||||
import org.apache.pdfbox.rendering.ImageType;
 | 
			
		||||
import org.apache.pdfbox.rendering.PDFRenderer;
 | 
			
		||||
import org.apache.pdfbox.text.PDFTextStripper;
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
import org.springframework.web.multipart.MultipartFile;
 | 
			
		||||
 | 
			
		||||
import io.github.pixee.security.Filenames;
 | 
			
		||||
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import stirling.software.SPDF.service.CustomPDDocumentFactory;
 | 
			
		||||
 | 
			
		||||
@Slf4j
 | 
			
		||||
public class PdfUtils {
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(PdfUtils.class);
 | 
			
		||||
 | 
			
		||||
    public static PDRectangle textToPageSize(String size) {
 | 
			
		||||
        switch (size.toUpperCase()) {
 | 
			
		||||
            case "A0":
 | 
			
		||||
@ -310,7 +308,7 @@ public class PdfUtils {
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Log that the image was successfully written to the byte array
 | 
			
		||||
                logger.info("Image successfully written to byte array");
 | 
			
		||||
                log.info("Image successfully written to byte array");
 | 
			
		||||
            } else {
 | 
			
		||||
                // Zip the images and return as byte array
 | 
			
		||||
                try (ZipOutputStream zos = new ZipOutputStream(baos)) {
 | 
			
		||||
@ -330,13 +328,13 @@ public class PdfUtils {
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    // Log that the images were successfully written to the byte array
 | 
			
		||||
                    logger.info("Images successfully written to byte array as a zip");
 | 
			
		||||
                    log.info("Images successfully written to byte array as a zip");
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return baos.toByteArray();
 | 
			
		||||
        } catch (IOException e) {
 | 
			
		||||
            // Log an error message if there is an issue converting the PDF to an image
 | 
			
		||||
            logger.error("Error converting PDF to image", e);
 | 
			
		||||
            log.error("Error converting PDF to image", e);
 | 
			
		||||
            throw e;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@ -421,7 +419,7 @@ public class PdfUtils {
 | 
			
		||||
            }
 | 
			
		||||
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
 | 
			
		||||
            doc.save(byteArrayOutputStream);
 | 
			
		||||
            logger.info("PDF successfully saved to byte array");
 | 
			
		||||
            log.info("PDF successfully saved to byte array");
 | 
			
		||||
            return byteArrayOutputStream.toByteArray();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@ -471,7 +469,7 @@ public class PdfUtils {
 | 
			
		||||
                        image.getHeight() * scaleFactor);
 | 
			
		||||
            }
 | 
			
		||||
        } catch (IOException e) {
 | 
			
		||||
            logger.error("Error adding image to PDF", e);
 | 
			
		||||
            log.error("Error adding image to PDF", e);
 | 
			
		||||
            throw e;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@ -498,20 +496,20 @@ public class PdfUtils {
 | 
			
		||||
                PDImageXObject image = PDImageXObject.createFromByteArray(document, imageBytes, "");
 | 
			
		||||
                // Draw the image onto the page at the specified x and y coordinates
 | 
			
		||||
                contentStream.drawImage(image, x, y);
 | 
			
		||||
                logger.info("Image successfully overlayed onto PDF");
 | 
			
		||||
                log.info("Image successfully overlayed onto PDF");
 | 
			
		||||
                if (!everyPage && i == 0) {
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
            } catch (IOException e) {
 | 
			
		||||
                // Log an error message if there is an issue overlaying the image onto the PDF
 | 
			
		||||
                logger.error("Error overlaying image onto PDF", e);
 | 
			
		||||
                log.error("Error overlaying image onto PDF", e);
 | 
			
		||||
                throw e;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        // Create a ByteArrayOutputStream to save the PDF to
 | 
			
		||||
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
 | 
			
		||||
        document.save(baos);
 | 
			
		||||
        logger.info("PDF successfully saved to byte array");
 | 
			
		||||
        log.info("PDF successfully saved to byte array");
 | 
			
		||||
        return baos.toByteArray();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -13,17 +13,14 @@ import java.util.concurrent.ConcurrentHashMap;
 | 
			
		||||
import java.util.concurrent.Semaphore;
 | 
			
		||||
import java.util.concurrent.TimeUnit;
 | 
			
		||||
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
 | 
			
		||||
import io.github.pixee.security.BoundedLineReader;
 | 
			
		||||
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import stirling.software.SPDF.model.ApplicationProperties;
 | 
			
		||||
 | 
			
		||||
@Slf4j
 | 
			
		||||
public class ProcessExecutor {
 | 
			
		||||
 | 
			
		||||
    private static final Logger logger = LoggerFactory.getLogger(ProcessExecutor.class);
 | 
			
		||||
 | 
			
		||||
    private static ApplicationProperties applicationProperties = new ApplicationProperties();
 | 
			
		||||
 | 
			
		||||
    public enum Processes {
 | 
			
		||||
@ -160,7 +157,7 @@ public class ProcessExecutor {
 | 
			
		||||
        semaphore.acquire();
 | 
			
		||||
        try {
 | 
			
		||||
 | 
			
		||||
            logger.info("Running command: " + String.join(" ", command));
 | 
			
		||||
            log.info("Running command: " + String.join(" ", command));
 | 
			
		||||
            ProcessBuilder processBuilder = new ProcessBuilder(command);
 | 
			
		||||
 | 
			
		||||
            // Use the working directory if it's set
 | 
			
		||||
@ -187,13 +184,12 @@ public class ProcessExecutor {
 | 
			
		||||
                                                            errorReader, 5_000_000))
 | 
			
		||||
                                            != null) {
 | 
			
		||||
                                        errorLines.add(line);
 | 
			
		||||
                                        if (liveUpdates) logger.info(line);
 | 
			
		||||
                                        if (liveUpdates) log.info(line);
 | 
			
		||||
                                    }
 | 
			
		||||
                                } catch (InterruptedIOException e) {
 | 
			
		||||
                                    logger.warn(
 | 
			
		||||
                                            "Error reader thread was interrupted due to timeout.");
 | 
			
		||||
                                    log.warn("Error reader thread was interrupted due to timeout.");
 | 
			
		||||
                                } catch (IOException e) {
 | 
			
		||||
                                    logger.error("exception", e);
 | 
			
		||||
                                    log.error("exception", e);
 | 
			
		||||
                                }
 | 
			
		||||
                            });
 | 
			
		||||
 | 
			
		||||
@ -211,13 +207,12 @@ public class ProcessExecutor {
 | 
			
		||||
                                                            outputReader, 5_000_000))
 | 
			
		||||
                                            != null) {
 | 
			
		||||
                                        outputLines.add(line);
 | 
			
		||||
                                        if (liveUpdates) logger.info(line);
 | 
			
		||||
                                        if (liveUpdates) log.info(line);
 | 
			
		||||
                                    }
 | 
			
		||||
                                } catch (InterruptedIOException e) {
 | 
			
		||||
                                    logger.warn(
 | 
			
		||||
                                            "Error reader thread was interrupted due to timeout.");
 | 
			
		||||
                                    log.warn("Error reader thread was interrupted due to timeout.");
 | 
			
		||||
                                } catch (IOException e) {
 | 
			
		||||
                                    logger.error("exception", e);
 | 
			
		||||
                                    log.error("exception", e);
 | 
			
		||||
                                }
 | 
			
		||||
                            });
 | 
			
		||||
 | 
			
		||||
@ -244,7 +239,7 @@ public class ProcessExecutor {
 | 
			
		||||
                String outputMessage = String.join("\n", outputLines);
 | 
			
		||||
                messages += outputMessage;
 | 
			
		||||
                if (!liveUpdates) {
 | 
			
		||||
                    logger.info("Command output:\n" + outputMessage);
 | 
			
		||||
                    log.info("Command output:\n" + outputMessage);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@ -252,7 +247,7 @@ public class ProcessExecutor {
 | 
			
		||||
                String errorMessage = String.join("\n", errorLines);
 | 
			
		||||
                messages += errorMessage;
 | 
			
		||||
                if (!liveUpdates) {
 | 
			
		||||
                    logger.warn("Command error output:\n" + errorMessage);
 | 
			
		||||
                    log.warn("Command error output:\n" + errorMessage);
 | 
			
		||||
                }
 | 
			
		||||
                if (exitCode != 0) {
 | 
			
		||||
                    throw new IOException(
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user