diff --git a/build.gradle b/build.gradle index 2e3d575b..de4f68b3 100644 --- a/build.gradle +++ b/build.gradle @@ -27,7 +27,6 @@ ext { group = "stirling.software" version = "0.39.0" - java { // 17 is lowest but we support and recommend 21 sourceCompatibility = JavaVersion.VERSION_17 @@ -38,7 +37,6 @@ repositories { maven { url = "https://jitpack.io" } maven { url = "https://build.shibboleth.net/maven/releases" } maven { url = "https://maven.pkg.github.com/jcefmaven/jcefmaven" } - } licenseReport { @@ -303,7 +301,7 @@ dependencies { implementation "org.springframework.boot:spring-boot-starter-jetty:$springBootVersion" implementation "org.springframework.boot:spring-boot-starter-thymeleaf:$springBootVersion" - implementation 'com.posthog.java:posthog:1.1.1' + implementation 'com.posthog.java:posthog:1.2.0' implementation 'com.googlecode.owasp-java-html-sanitizer:owasp-java-html-sanitizer:20240325.1' diff --git a/gradle/verification-keyring.gpg b/gradle/verification-keyring.gpg new file mode 100644 index 00000000..9f8b865e Binary files /dev/null and b/gradle/verification-keyring.gpg differ diff --git a/gradle/verification-keyring.keys b/gradle/verification-keyring.keys index 96a72d3b..402dccc2 100644 --- a/gradle/verification-keyring.keys +++ b/gradle/verification-keyring.keys @@ -2900,6 +2900,21 @@ KXHgSDM9uRjq5Dks7glcrzO22nmN02ScLe6wP4u+Eg0= =xepC -----END PGP PUBLIC KEY BLOCK----- +pub 123F4925FE992840 +uid Manoel Aranda Neto + +sub 9FFBEE24201BC16B +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mDMEZQ1OshYJKwYBBAHaRw8BAQdAAEeA4hEQiapEC5UcbFiprm3geLbxEqYCyY20 +3bKleLW0Kk1hbm9lbCBBcmFuZGEgTmV0byA8bWFyYW5kYW5ldG9AZ21haWwuY29t +Prg4BGUNTrISCisGAQQBl1UBBQEBB0BYXZ1afD/OmWHkT3OyN6PXmG3SdCvcfFWm +mI+4S74LVQMBCAeIeAQYFgoAIBYhBAg1kzn96oh/+oMxKBI/SSX+mShABQJlDU6y +AhsMAAoJEBI/SSX+mShA7dwA/0ifrCv4q6pNo8aDIvX4KbD9fpObN0OSJgc394dl +pt++APwIs9mrkDLbgRWdWamlNSGceHfInFDRwcOYTO6tyk2YDw== +=XpYs +-----END PGP PUBLIC KEY BLOCK----- + pub 152888E10EF880B3 uid Daniel Fernandez diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 2d228daf..c8ad2d6c 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -20,18 +20,23 @@ + + + + + @@ -41,6 +46,7 @@ + @@ -49,13 +55,17 @@ + - + + + + @@ -65,6 +75,7 @@ + @@ -78,7 +89,12 @@ - + + + + + + @@ -88,7 +104,9 @@ + + @@ -98,6 +116,7 @@ + @@ -110,9 +129,12 @@ + + + @@ -125,13 +147,16 @@ + + + @@ -161,6 +186,7 @@ + @@ -1321,7 +1347,7 @@ - + @@ -1344,7 +1370,7 @@ - + @@ -1867,7 +1893,7 @@ - + @@ -3401,7 +3427,7 @@ - + @@ -3422,7 +3448,7 @@ - + @@ -3785,7 +3811,7 @@ - + diff --git a/src/main/java/stirling/software/SPDF/config/PostHogConfig.java b/src/main/java/stirling/software/SPDF/config/PostHogConfig.java index 42d5b101..fc5ed308 100644 --- a/src/main/java/stirling/software/SPDF/config/PostHogConfig.java +++ b/src/main/java/stirling/software/SPDF/config/PostHogConfig.java @@ -7,8 +7,10 @@ import org.springframework.context.annotation.Configuration; import com.posthog.java.PostHog; import jakarta.annotation.PreDestroy; +import lombok.extern.slf4j.Slf4j; @Configuration +@Slf4j public class PostHogConfig { @Value("${posthog.api.key}") @@ -21,7 +23,11 @@ public class PostHogConfig { @Bean public PostHog postHogClient() { - postHogClient = new PostHog.Builder(posthogApiKey).host(posthogHost).build(); + postHogClient = + new PostHog.Builder(posthogApiKey) + .host(posthogHost) + .logger(new PostHogLoggerImpl()) + .build(); return postHogClient; } diff --git a/src/main/java/stirling/software/SPDF/config/PostHogLoggerImpl.java b/src/main/java/stirling/software/SPDF/config/PostHogLoggerImpl.java new file mode 100644 index 00000000..61c0493d --- /dev/null +++ b/src/main/java/stirling/software/SPDF/config/PostHogLoggerImpl.java @@ -0,0 +1,42 @@ +package stirling.software.SPDF.config; + +import org.springframework.stereotype.Component; + +import com.posthog.java.PostHogLogger; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Component +public class PostHogLoggerImpl implements PostHogLogger { + + @Override + public void debug(String message) { + log.debug(message); + } + + @Override + public void info(String message) { + log.info(message); + } + + @Override + public void warn(String message) { + log.warn(message); + } + + @Override + public void error(String message) { + log.error(message); + } + + @Override + public void error(String message, Throwable throwable) { + if (message.contains("Error sending events to PostHog")) { + log.warn( + "Error sending metrics, Likely caused by no internet connection. Non Blocking"); + } else { + log.error(message, throwable); + } + } +} diff --git a/src/main/java/stirling/software/SPDF/controller/api/AnalysisController.java b/src/main/java/stirling/software/SPDF/controller/api/AnalysisController.java index f1d3942f..0e0d0534 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/AnalysisController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/AnalysisController.java @@ -1,41 +1,43 @@ package stirling.software.SPDF.controller.api; +import java.io.IOException; +import java.util.*; + 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.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.PDPageTree; -import org.apache.pdfbox.pdmodel.PDDocumentInformation; -import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm; -import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation; import org.apache.pdfbox.pdmodel.encryption.PDEncryption; +import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation; +import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm; import org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; + import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; -import stirling.software.SPDF.model.api.PDFFile; -import java.io.IOException; -import java.util.*; +import stirling.software.SPDF.model.api.PDFFile; @RestController @RequestMapping("/api/v1/analysis") @Tag(name = "Analysis", description = "Analysis APIs") public class AnalysisController { + @PostMapping(value = "/page-count", consumes = "multipart/form-data") + @Operation( + summary = "Get PDF page count", + description = "Returns total number of pages in PDF. Input:PDF Output:JSON Type:SISO") + public Map getPageCount(@ModelAttribute PDFFile file) throws IOException { + try (PDDocument document = Loader.loadPDF(file.getFileInput().getBytes())) { + return Map.of("pageCount", document.getNumberOfPages()); + } + } - @PostMapping(value = "/page-count", consumes = "multipart/form-data") - @Operation(summary = "Get PDF page count", - description = "Returns total number of pages in PDF. Input:PDF Output:JSON Type:SISO") - public Map getPageCount(@ModelAttribute PDFFile file) throws IOException { - try (PDDocument document = Loader.loadPDF(file.getFileInput().getBytes())) { - return Map.of("pageCount", document.getNumberOfPages()); - } - } - - @PostMapping(value ="/basic-info", consumes = "multipart/form-data") - @Operation(summary = "Get basic PDF information", - description = "Returns page count, version, file size. Input:PDF Output:JSON Type:SISO") + @PostMapping(value = "/basic-info", consumes = "multipart/form-data") + @Operation( + summary = "Get basic PDF information", + description = "Returns page count, version, file size. Input:PDF Output:JSON Type:SISO") public Map getBasicInfo(@ModelAttribute PDFFile file) throws IOException { try (PDDocument document = Loader.loadPDF(file.getFileInput().getBytes())) { Map info = new HashMap<>(); @@ -46,10 +48,12 @@ public class AnalysisController { } } - @PostMapping(value ="/document-properties", consumes = "multipart/form-data") - @Operation(summary = "Get PDF document properties", - description = "Returns title, author, subject, etc. Input:PDF Output:JSON Type:SISO") - public Map getDocumentProperties(@ModelAttribute PDFFile file) throws IOException { + @PostMapping(value = "/document-properties", consumes = "multipart/form-data") + @Operation( + summary = "Get PDF document properties", + description = "Returns title, author, subject, etc. Input:PDF Output:JSON Type:SISO") + public Map getDocumentProperties(@ModelAttribute PDFFile file) + throws IOException { try (PDDocument document = Loader.loadPDF(file.getFileInput().getBytes())) { PDDocumentInformation info = document.getDocumentInformation(); Map properties = new HashMap<>(); @@ -65,10 +69,12 @@ public class AnalysisController { } } - @PostMapping(value ="/page-dimensions", consumes = "multipart/form-data") - @Operation(summary = "Get page dimensions for all pages", - description = "Returns width and height of each page. Input:PDF Output:JSON Type:SISO") - public List> getPageDimensions(@ModelAttribute PDFFile file) throws IOException { + @PostMapping(value = "/page-dimensions", consumes = "multipart/form-data") + @Operation( + summary = "Get page dimensions for all pages", + description = "Returns width and height of each page. Input:PDF Output:JSON Type:SISO") + public List> getPageDimensions(@ModelAttribute PDFFile file) + throws IOException { try (PDDocument document = Loader.loadPDF(file.getFileInput().getBytes())) { List> dimensions = new ArrayList<>(); PDPageTree pages = document.getPages(); @@ -83,9 +89,11 @@ public class AnalysisController { } } - @PostMapping(value ="/form-fields", consumes = "multipart/form-data") - @Operation(summary = "Get form field information", - description = "Returns count and details of form fields. Input:PDF Output:JSON Type:SISO") + @PostMapping(value = "/form-fields", consumes = "multipart/form-data") + @Operation( + summary = "Get form field information", + description = + "Returns count and details of form fields. Input:PDF Output:JSON Type:SISO") public Map getFormFields(@ModelAttribute PDFFile file) throws IOException { try (PDDocument document = Loader.loadPDF(file.getFileInput().getBytes())) { Map formInfo = new HashMap<>(); @@ -104,9 +112,10 @@ public class AnalysisController { } } - @PostMapping(value ="/annotation-info", consumes = "multipart/form-data") - @Operation(summary = "Get annotation information", - description = "Returns count and types of annotations. Input:PDF Output:JSON Type:SISO") + @PostMapping(value = "/annotation-info", consumes = "multipart/form-data") + @Operation( + summary = "Get annotation information", + description = "Returns count and types of annotations. Input:PDF Output:JSON Type:SISO") public Map getAnnotationInfo(@ModelAttribute PDFFile file) throws IOException { try (PDDocument document = Loader.loadPDF(file.getFileInput().getBytes())) { Map annotInfo = new HashMap<>(); @@ -127,9 +136,11 @@ public class AnalysisController { } } - @PostMapping(value ="/font-info", consumes = "multipart/form-data") - @Operation(summary = "Get font information", - description = "Returns list of fonts used in the document. Input:PDF Output:JSON Type:SISO") + @PostMapping(value = "/font-info", consumes = "multipart/form-data") + @Operation( + summary = "Get font information", + description = + "Returns list of fonts used in the document. Input:PDF Output:JSON Type:SISO") public Map getFontInfo(@ModelAttribute PDFFile file) throws IOException { try (PDDocument document = Loader.loadPDF(file.getFileInput().getBytes())) { Map fontInfo = new HashMap<>(); @@ -147,9 +158,11 @@ public class AnalysisController { } } - @PostMapping(value ="/security-info", consumes = "multipart/form-data") - @Operation(summary = "Get security information", - description = "Returns encryption and permission details. Input:PDF Output:JSON Type:SISO") + @PostMapping(value = "/security-info", consumes = "multipart/form-data") + @Operation( + summary = "Get security information", + description = + "Returns encryption and permission details. Input:PDF Output:JSON Type:SISO") public Map getSecurityInfo(@ModelAttribute PDFFile file) throws IOException { try (PDDocument document = Loader.loadPDF(file.getFileInput().getBytes())) { Map securityInfo = new HashMap<>(); @@ -163,8 +176,12 @@ public class AnalysisController { Map permissions = new HashMap<>(); permissions.put("canPrint", document.getCurrentAccessPermission().canPrint()); permissions.put("canModify", document.getCurrentAccessPermission().canModify()); - permissions.put("canExtractContent", document.getCurrentAccessPermission().canExtractContent()); - permissions.put("canModifyAnnotations", document.getCurrentAccessPermission().canModifyAnnotations()); + permissions.put( + "canExtractContent", + document.getCurrentAccessPermission().canExtractContent()); + permissions.put( + "canModifyAnnotations", + document.getCurrentAccessPermission().canModifyAnnotations()); securityInfo.put("permissions", permissions); } else { @@ -174,7 +191,4 @@ public class AnalysisController { return securityInfo; } } - - - }