diff --git a/.github/workflows/multiOSReleases.yml b/.github/workflows/multiOSReleases.yml
index 5f5d509bc..a2ffb5667 100644
--- a/.github/workflows/multiOSReleases.yml
+++ b/.github/workflows/multiOSReleases.yml
@@ -70,7 +70,7 @@ jobs:
- uses: gradle/actions/setup-gradle@06832c7b30a0129d7fb559bcc6e43d26f6374244 # v4.3.1
with:
- gradle-version: 8.12
+ gradle-version: 8.14
- name: Generate jar (With Security=${{ matrix.enable_security }})
run: ./gradlew clean createExe
@@ -158,7 +158,7 @@ jobs:
- uses: gradle/actions/setup-gradle@06832c7b30a0129d7fb559bcc6e43d26f6374244 # v4.3.1
with:
- gradle-version: 8.12
+ gradle-version: 8.14
# Install Windows dependencies
- name: Install WiX Toolset
diff --git a/.github/workflows/push-docker.yml b/.github/workflows/push-docker.yml
index 9d97e3225..dec93bad9 100644
--- a/.github/workflows/push-docker.yml
+++ b/.github/workflows/push-docker.yml
@@ -32,7 +32,7 @@ jobs:
- uses: gradle/actions/setup-gradle@06832c7b30a0129d7fb559bcc6e43d26f6374244 # v4.3.1
with:
- gradle-version: 8.12
+ gradle-version: 8.14
- name: Run Gradle Command
run: ./gradlew clean build
diff --git a/.github/workflows/releaseArtifacts.yml b/.github/workflows/releaseArtifacts.yml
index 225e5142b..f35d6f7c9 100644
--- a/.github/workflows/releaseArtifacts.yml
+++ b/.github/workflows/releaseArtifacts.yml
@@ -37,7 +37,7 @@ jobs:
- uses: gradle/actions/setup-gradle@06832c7b30a0129d7fb559bcc6e43d26f6374244 # v4.3.1
with:
- gradle-version: 8.12
+ gradle-version: 8.14
- name: Generate jar (With Security=${{ matrix.enable_security }})
run: ./gradlew clean createExe
diff --git a/README.md b/README.md
index 480abd567..2f7838606 100644
--- a/README.md
+++ b/README.md
@@ -128,14 +128,14 @@ Stirling-PDF currently supports 39 languages!
| English (English) (en_GB) |  |
| English (US) (en_US) |  |
| French (Français) (fr_FR) |  |
-| German (Deutsch) (de_DE) |  |
+| German (Deutsch) (de_DE) |  |
| Greek (Ελληνικά) (el_GR) |  |
| Hindi (हिंदी) (hi_IN) |  |
| Hungarian (Magyar) (hu_HU) |  |
| Indonesian (Bahasa Indonesia) (id_ID) |  |
| Irish (Gaeilge) (ga_IE) |  |
| Italian (Italiano) (it_IT) |  |
-| Japanese (日本語) (ja_JP) |  |
+| Japanese (日本語) (ja_JP) |  |
| Korean (한국어) (ko_KR) |  |
| Norwegian (Norsk) (no_NB) |  |
| Persian (فارسی) (fa_IR) |  |
diff --git a/build.gradle b/build.gradle
index 078ea9071..c0adcf012 100644
--- a/build.gradle
+++ b/build.gradle
@@ -404,7 +404,7 @@ sonar {
// rules=['unused-dependency']
// }
tasks.wrapper {
- gradleVersion = "8.12"
+ gradleVersion = "8.14"
distributionType = Wrapper.DistributionType.ALL
}
//tasks.withType(JavaCompile) {
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
index a4b76b953..1b33c55ba 100644
Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index e0fd02028..6514f919f 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-all.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
diff --git a/gradlew b/gradlew
index f3b75f3b0..23d15a936 100755
--- a/gradlew
+++ b/gradlew
@@ -114,7 +114,7 @@ case "$( uname )" in #(
NONSTOP* ) nonstop=true ;;
esac
-CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+CLASSPATH="\\\"\\\""
# Determine the Java command to use to start the JVM.
@@ -205,7 +205,7 @@ fi
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command:
-# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
@@ -213,7 +213,7 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
- org.gradle.wrapper.GradleWrapperMain \
+ -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
"$@"
# Stop when "xargs" is not available.
diff --git a/gradlew.bat b/gradlew.bat
index 9d21a2183..db3a6ac20 100644
--- a/gradlew.bat
+++ b/gradlew.bat
@@ -70,11 +70,11 @@ goto fail
:execute
@rem Setup the command line
-set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+set CLASSPATH=
@rem Execute Gradle
-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
:end
@rem End local scope for the variables with windows NT shell
diff --git a/settings.gradle b/settings.gradle
index f8139930e..6f039dc93 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1 +1,5 @@
+plugins {
+ // Apply the foojay-resolver plugin to allow automatic download of JDKs
+ id 'org.gradle.toolchains.foojay-resolver-convention' version '0.10.0'
+}
rootProject.name = 'Stirling-PDF'
diff --git a/src/main/java/stirling/software/SPDF/config/security/UserBasedRateLimitingFilter.java b/src/main/java/stirling/software/SPDF/config/security/UserBasedRateLimitingFilter.java
index 1c725c9f2..5ca7df214 100644
--- a/src/main/java/stirling/software/SPDF/config/security/UserBasedRateLimitingFilter.java
+++ b/src/main/java/stirling/software/SPDF/config/security/UserBasedRateLimitingFilter.java
@@ -121,7 +121,7 @@ public class UserBasedRateLimitingFilter extends OncePerRequestFilter {
if (probe.isConsumed()) {
response.setHeader(
"X-Rate-Limit-Remaining",
- Newlines.stripAll(Long.toString(probe.getRemainingTokens())));
+ stripNewlines(Newlines.stripAll(Long.toString(probe.getRemainingTokens()))));
filterChain.doFilter(request, response);
} else {
long waitForRefill = probe.getNanosToWaitForRefill() / 1_000_000_000;
@@ -141,4 +141,8 @@ public class UserBasedRateLimitingFilter extends OncePerRequestFilter {
.build();
return Bucket.builder().addLimit(limit).build();
}
+
+ private static String stripNewlines(final String s) {
+ return s.replaceAll("[\n\r]", "");
+ }
}
diff --git a/src/main/resources/static/js/multitool/PdfContainer.js b/src/main/resources/static/js/multitool/PdfContainer.js
index 72dd7f4c0..32c34ba46 100644
--- a/src/main/resources/static/js/multitool/PdfContainer.js
+++ b/src/main/resources/static/js/multitool/PdfContainer.js
@@ -34,7 +34,8 @@ class PdfContainer {
this.splitPDF = this.splitPDF.bind(this);
this.splitAll = this.splitAll.bind(this);
this.deleteSelected = this.deleteSelected.bind(this);
- this.toggleSelectAll = this.toggleSelectAll.bind(this);
+ this.selectAll = this.selectAll.bind(this);
+ this.deselectAll = this.deselectAll.bind(this);
this.updateSelectedPagesDisplay = this.updateSelectedPagesDisplay.bind(this);
this.toggleSelectPageVisibility = this.toggleSelectPageVisibility.bind(this);
this.updatePagesFromCSV = this.updatePagesFromCSV.bind(this);
@@ -63,7 +64,8 @@ class PdfContainer {
window.rotateAll = this.rotateAll;
window.splitAll = this.splitAll;
window.deleteSelected = this.deleteSelected;
- window.toggleSelectAll = this.toggleSelectAll;
+ window.selectAll = this.selectAll;
+ window.deselectAll = this.deselectAll;
window.updateSelectedPagesDisplay = this.updateSelectedPagesDisplay;
window.toggleSelectPageVisibility = this.toggleSelectPageVisibility;
window.updatePagesFromCSV = this.updatePagesFromCSV;
@@ -72,7 +74,6 @@ class PdfContainer {
window.addFilesBlankAll = this.addFilesBlankAll;
window.removeAllElements = this.removeAllElements;
window.resetPages = this.resetPages;
- window.selectAll = false;
let undoBtn = document.getElementById('undo-btn');
let redoBtn = document.getElementById('redo-btn');
@@ -433,33 +434,43 @@ class PdfContainer {
this.undoManager.pushUndoClearRedo(removeSelectedCommand);
}
- toggleSelectAll() {
+ selectAll() {
const checkboxes = document.querySelectorAll('.pdf-actions_checkbox');
- window.selectAll = !window.selectAll;
const selectIcon = document.getElementById('select-All-Container');
const deselectIcon = document.getElementById('deselect-All-Container');
- if (!window.selectAll) {
- this.showButton(selectIcon, true);
- this.showButton(deselectIcon, false);
- } else {
- this.showButton(selectIcon, false);
- this.showButton(deselectIcon, true);
- }
+ this.showButton(selectIcon, false);
+ this.showButton(deselectIcon, true);
+
checkboxes.forEach((checkbox) => {
- checkbox.checked = window.selectAll;
+ checkbox.checked = true;
const pageNumber = Array.from(checkbox.parentNode.parentNode.children).indexOf(checkbox.parentNode) + 1;
- if (checkbox.checked) {
- if (!window.selectedPages.includes(pageNumber)) {
- window.selectedPages.push(pageNumber);
- }
- } else {
- const index = window.selectedPages.indexOf(pageNumber);
- if (index !== -1) {
- window.selectedPages.splice(index, 1);
- }
+ if (!window.selectedPages.includes(pageNumber)) {
+ window.selectedPages.push(pageNumber);
+ }
+ });
+
+ this.updateSelectedPagesDisplay();
+ }
+
+ deselectAll() {
+ const checkboxes = document.querySelectorAll('.pdf-actions_checkbox');
+ const selectIcon = document.getElementById('select-All-Container');
+ const deselectIcon = document.getElementById('deselect-All-Container');
+
+ this.showButton(selectIcon, true);
+ this.showButton(deselectIcon, false);
+
+ checkboxes.forEach((checkbox) => {
+ checkbox.checked = false;
+
+ const pageNumber = Array.from(checkbox.parentNode.parentNode.children).indexOf(checkbox.parentNode) + 1;
+
+ const index = window.selectedPages.indexOf(pageNumber);
+ if (index !== -1) {
+ window.selectedPages.splice(index, 1);
}
});
@@ -569,6 +580,34 @@ class PdfContainer {
// Update the input field with the formatted page list
selectedPagesInput.value = this.formatSelectedPages(window.selectedPages);
+
+ const selectIcon = document.getElementById('select-All-Container');
+ const deselectIcon = document.getElementById('deselect-All-Container');
+
+ if (window.selectPage) { // Check if selectPage mode is active
+ console.log("Page Select on. Showing buttons");
+ //Check if no pages are selected
+ if (window.selectedPages.length === 0) {
+ this.showButton(selectIcon, true);
+ this.showButton(deselectIcon, false);
+ } else {
+ this.showButton(deselectIcon, true);
+ }
+
+ //Check if all pages are selected
+ const allCheckboxes = document.querySelectorAll('.pdf-actions_checkbox');
+ const allSelected = Array.from(allCheckboxes).every((checkbox) => checkbox.checked);
+ if (allSelected) {
+ this.showButton(selectIcon, false);
+ this.showButton(deselectIcon, true);
+ } else {
+ this.showButton(selectIcon, true);
+ }
+ } else {
+ console.log("Page Select off. Hidding buttons");
+ this.showButton(selectIcon, false);
+ this.showButton(deselectIcon, false);
+ }
}
parsePageRanges(ranges) {
@@ -793,13 +832,9 @@ class PdfContainer {
});
const checkboxes = document.querySelectorAll('.pdf-actions_checkbox');
- window.selectAll = false;
const selectIcon = document.getElementById('select-All-Container');
const deselectIcon = document.getElementById('deselect-All-Container');
- selectIcon.style.display = 'inline';
- deselectIcon.style.display = 'none';
-
checkboxes.forEach((checkbox) => {
const pageNumber = Array.from(checkbox.parentNode.parentNode.children).indexOf(checkbox.parentNode) + 1;
@@ -852,18 +887,30 @@ class PdfContainer {
deleteButton.classList.toggle('hidden', !window.selectPage);
const selectedPages = document.getElementById('selected-pages-display');
selectedPages.classList.toggle('hidden', !window.selectPage);
+
if(!window.selectPage)
{
this.showButton(document.getElementById('deselect-All-Container'), false);
this.showButton(document.getElementById('select-All-Container'), false);
- }
- else if(window.selectAll){
- this.showButton(document.getElementById('deselect-All-Container'), true);
- this.showButton(document.getElementById('select-All-Container'), false);
+
+ // Uncheck all checkboxes and clear selected pages
+ const allCheckboxes = document.querySelectorAll('.pdf-actions_checkbox');
+ allCheckboxes.forEach((checkbox) => {
+ checkbox.checked = false;
+ });
+ window.selectedPages = [];
+ this.updateSelectedPagesDisplay();
}
else{
- this.showButton(document.getElementById('deselect-All-Container'), false);
- this.showButton(document.getElementById('select-All-Container'), true);
+ const allCheckboxes = document.querySelectorAll('.pdf-actions_checkbox');
+ const allSelected = Array.from(allCheckboxes).every((checkbox) => checkbox.checked);
+ if (!allSelected) {
+ this.showButton(document.getElementById('select-All-Container'), true);
+ }
+
+ if (window.selectedPages.length > 0) {
+ this.showButton(document.getElementById('deselect-All-Container'), true);
+ }
}
const exportSelected = document.getElementById('export-selected-button');
diff --git a/src/main/resources/templates/multi-tool.html b/src/main/resources/templates/multi-tool.html
index 3c6c60fba..173b92838 100644
--- a/src/main/resources/templates/multi-tool.html
+++ b/src/main/resources/templates/multi-tool.html
@@ -94,11 +94,11 @@