From 75e10efcbda1f794cd461a4bf7412e5d60d35649 Mon Sep 17 00:00:00 2001
From: Anthony Stirling <77850077+Frooodle@users.noreply.github.com.>
Date: Sun, 7 Jul 2024 22:49:21 +0100
Subject: [PATCH 1/2] auto decrypt, update discord, fix multi file support for
some inputs
---
.github/ISSUE_TEMPLATE/config.yml | 2 +-
README.md | 2 +-
.../api/security/PasswordController.java | 2 +-
src/main/resources/static/js/downloader.js | 116 ++++++++++++++++--
.../convert/pdf-to-presentation.html | 2 +-
.../templates/convert/pdf-to-word.html | 2 +-
src/main/resources/templates/error.html | 2 +-
.../templates/fragments/errorBanner.html | 2 +-
.../fragments/errorBannerPerPage.html | 2 +-
.../resources/templates/fragments/navbar.html | 2 +-
src/main/resources/templates/home.html | 4 +-
src/main/resources/templates/pipeline.html | 2 +-
.../resources/templates/remove-pages.html | 2 +-
.../templates/security/add-watermark.html | 4 +-
.../templates/security/auto-redact.html | 6 +-
15 files changed, 125 insertions(+), 27 deletions(-)
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
index 0f3580d5a8..2725e5f5a9 100644
--- a/.github/ISSUE_TEMPLATE/config.yml
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -1,5 +1,5 @@
blank_issues_enabled: true
contact_links:
- name: 💬 Discord Server
- url: https://discord.gg/Cn8pWhQRxZ
+ url: https://discord.gg/HYmhKj45pU
about: You can join our Discord server for real time discussion and support
diff --git a/README.md b/README.md
index 4d5eae28b4..dbaab98224 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
Stirling-PDF
[![Docker Pulls](https://img.shields.io/docker/pulls/frooodle/s-pdf)](https://hub.docker.com/r/frooodle/s-pdf)
-[![Discord](https://img.shields.io/discord/1068636748814483718?label=Discord)](https://discord.gg/Cn8pWhQRxZ)
+[![Discord](https://img.shields.io/discord/1068636748814483718?label=Discord)](https://discord.gg/HYmhKj45pU)
[![Docker Image Version (tag latest semver)](https://img.shields.io/docker/v/frooodle/s-pdf/latest)](https://github.com/Stirling-Tools/Stirling-PDF/)
[![GitHub Repo stars](https://img.shields.io/github/stars/stirling-tools/stirling-pdf?style=social)](https://github.com/Stirling-Tools/stirling-pdf)
[![Paypal Donate](https://img.shields.io/badge/Paypal%20Donate-yellow?style=flat&logo=paypal)](https://www.paypal.com/donate/?hosted_button_id=MN7JPG5G6G3JL)
diff --git a/src/main/java/stirling/software/SPDF/controller/api/security/PasswordController.java b/src/main/java/stirling/software/SPDF/controller/api/security/PasswordController.java
index 84c4493314..b8e36e0e10 100644
--- a/src/main/java/stirling/software/SPDF/controller/api/security/PasswordController.java
+++ b/src/main/java/stirling/software/SPDF/controller/api/security/PasswordController.java
@@ -68,7 +68,7 @@ public ResponseEntity addPassword(@ModelAttribute AddPasswordRequest req
boolean canModifyAnnotations = request.isCanModifyAnnotations();
boolean canPrint = request.isCanPrint();
boolean canPrintFaithful = request.isCanPrintFaithful();
-
+ System.out.println(fileInput.getOriginalFilename());
PDDocument document = Loader.loadPDF(fileInput.getBytes());
AccessPermission ap = new AccessPermission();
ap.setCanAssembleDocument(!canAssembleDocument);
diff --git a/src/main/resources/static/js/downloader.js b/src/main/resources/static/js/downloader.js
index c955bb1bbc..07f7c5b68c 100644
--- a/src/main/resources/static/js/downloader.js
+++ b/src/main/resources/static/js/downloader.js
@@ -12,7 +12,7 @@ $(document).ready(function () {
event.preventDefault();
firstErrorOccurred = false;
const url = this.action;
- const files = $("#fileInput-input")[0].files;
+ var files = $("#fileInput-input")[0].files;
const formData = new FormData(this);
// Remove empty file entries
@@ -36,6 +36,17 @@ $(document).ready(function () {
}, 5000);
try {
+
+ if (!url.includes("remove-password")) {
+ // Check if any PDF files are encrypted and handle decryption if necessary
+ const decryptedFiles = await checkAndDecryptFiles(url ,files);
+ files = decryptedFiles
+ // Append decrypted files to formData
+ decryptedFiles.forEach((file, index) => {
+ formData.set(`fileInput`, file);
+ });
+ }
+
if (remoteCall === true) {
if (override === "multi" || (!multiple && files.length > 1 && override !== "single")) {
await submitMultiPdfForm(url, files);
@@ -45,24 +56,24 @@ $(document).ready(function () {
}
clearTimeout(timeoutId);
$("#submitBtn").text(originalButtonText);
-
+
// After process finishes, check for boredWaiting and gameDialog open status
const boredWaiting = localStorage.getItem("boredWaiting") || "disabled";
const gameDialog = document.getElementById('game-container-wrapper');
if (boredWaiting === "enabled" && gameDialog && gameDialog.open) {
// Display a green banner at the bottom of the screen saying "Download complete"
let downloadCompleteText = "Download Complete";
- if(window.downloadCompleteText){
+ if (window.downloadCompleteText) {
downloadCompleteText = window.downloadCompleteText;
}
- $("body").append(''+ downloadCompleteText + '
');
- setTimeout(function() {
- $("#download-complete-banner").fadeOut("slow", function() {
+ $("body").append('' + downloadCompleteText + '
');
+ setTimeout(function () {
+ $("#download-complete-banner").fadeOut("slow", function () {
$(this).remove(); // Remove the banner after fading out
});
}, 5000); // Banner will fade out after 5 seconds
}
-
+
} catch (error) {
clearTimeout(timeoutId);
handleDownloadError(error);
@@ -72,6 +83,97 @@ $(document).ready(function () {
});
});
+async function checkAndDecryptFiles(url, files) {
+ const decryptedFiles = [];
+ pdfjsLib.GlobalWorkerOptions.workerSrc = './pdfjs-legacy/pdf.worker.mjs';
+
+// Extract the base URL
+ const baseUrl = new URL(url);
+ let removePasswordUrl = `${baseUrl.origin}`;
+
+ // Check if there's a path before /api/
+ const apiIndex = baseUrl.pathname.indexOf('/api/');
+ if (apiIndex > 0) {
+ removePasswordUrl += baseUrl.pathname.substring(0, apiIndex);
+ }
+
+ // Append the new endpoint
+ removePasswordUrl += '/api/v1/security/remove-password';
+
+ console.log(`Remove password URL: ${removePasswordUrl}`);
+
+
+ for (const file of files) {
+ console.log(`Processing file: ${file.name}`);
+ if (file.type !== 'application/pdf') {
+ console.log(`Skipping non-PDF file: ${file.name}`);
+ decryptedFiles.push(file);
+ continue;
+ }
+ try {
+ const arrayBuffer = await file.arrayBuffer();
+ const loadingTask = pdfjsLib.getDocument({ data: arrayBuffer });
+
+ console.log(`Attempting to load PDF: ${file.name}`);
+ const pdf = await loadingTask.promise;
+ console.log(`File is not encrypted: ${file.name}`);
+ decryptedFiles.push(file); // If no error, file is not encrypted
+ } catch (error) {
+ if (error.name === 'PasswordException' && error.code === 1) {
+ console.log(`PDF requires password: ${file.name}`, error);
+ console.log(`Attempting to remove password from PDF: ${file.name} with password.`);
+ const password = prompt(`This PDF (${file.name}) is encrypted. Please enter the password:`);
+
+ if (!password) {
+ console.error(`No password provided for encrypted PDF: ${file.name}`);
+ showErrorBanner(`No password provided for encrypted PDF: ${file.name}`, 'Please enter a valid password.');
+ throw error;
+ }
+
+ try {
+ // Prepare FormData for the decryption request
+ const formData = new FormData();
+ formData.append('fileInput', file);
+ formData.append('password', password);
+
+ // Use handleSingleDownload to send the request
+ const decryptionResult = await fetch(removePasswordUrl, { method: "POST", body: formData });
+
+ if (decryptionResult && decryptionResult.blob) {
+ const decryptedBlob = await decryptionResult.blob();
+ const decryptedFile = new File([decryptedBlob], file.name, { type: 'application/pdf' });
+
+ /* // Create a link element to download the file
+ const link = document.createElement('a');
+ link.href = URL.createObjectURL(decryptedBlob);
+ link.download = 'test.pdf';
+ document.body.appendChild(link);
+ link.click();
+ document.body.removeChild(link);
+*/
+ decryptedFiles.push(decryptedFile);
+ console.log(`Successfully decrypted PDF: ${file.name}`);
+ } else {
+ throw new Error('Decryption failed: No valid response from server');
+ }
+ } catch (decryptError) {
+ console.error(`Failed to decrypt PDF: ${file.name}`, decryptError);
+ showErrorBanner(`Failed to decrypt PDF: ${file.name}`, 'Incorrect password or unsupported encryption.');
+ throw decryptError;
+ }
+ } else {
+ console.log(`Error loading PDF: ${file.name}`, error);
+ throw error;
+ }
+ }
+ }
+ return decryptedFiles;
+}
+
+
+
+
+
async function handleSingleDownload(url, formData, isMulti = false, isZip = false) {
try {
const response = await fetch(url, { method: "POST", body: formData });
diff --git a/src/main/resources/templates/convert/pdf-to-presentation.html b/src/main/resources/templates/convert/pdf-to-presentation.html
index 794317609c..ce1f455dd5 100644
--- a/src/main/resources/templates/convert/pdf-to-presentation.html
+++ b/src/main/resources/templates/convert/pdf-to-presentation.html
@@ -22,8 +22,8 @@
diff --git a/src/main/resources/templates/convert/pdf-to-word.html b/src/main/resources/templates/convert/pdf-to-word.html
index 7e5f96c03a..f91b6a60e4 100644
--- a/src/main/resources/templates/convert/pdf-to-word.html
+++ b/src/main/resources/templates/convert/pdf-to-word.html
@@ -22,8 +22,8 @@
diff --git a/src/main/resources/templates/error.html b/src/main/resources/templates/error.html
index 314d28b399..00f22c27b0 100644
--- a/src/main/resources/templates/error.html
+++ b/src/main/resources/templates/error.html
@@ -19,7 +19,7 @@
diff --git a/src/main/resources/templates/fragments/errorBanner.html b/src/main/resources/templates/fragments/errorBanner.html
index 32fb9019c5..d682dcb922 100644
--- a/src/main/resources/templates/fragments/errorBanner.html
+++ b/src/main/resources/templates/fragments/errorBanner.html
@@ -20,7 +20,7 @@
-
+
diff --git a/src/main/resources/templates/pipeline.html b/src/main/resources/templates/pipeline.html
index 0a1d879f2a..1f5f1c7cb1 100644
--- a/src/main/resources/templates/pipeline.html
+++ b/src/main/resources/templates/pipeline.html
@@ -16,7 +16,7 @@
/>
diff --git a/src/main/resources/templates/remove-pages.html b/src/main/resources/templates/remove-pages.html
index 58dc18c788..84471ef295 100644
--- a/src/main/resources/templates/remove-pages.html
+++ b/src/main/resources/templates/remove-pages.html
@@ -21,7 +21,7 @@
diff --git a/src/main/resources/templates/security/add-watermark.html b/src/main/resources/templates/security/add-watermark.html
index 12e706e411..71c323746d 100644
--- a/src/main/resources/templates/security/add-watermark.html
+++ b/src/main/resources/templates/security/add-watermark.html
@@ -20,9 +20,7 @@