Nearly finished the Excel Password Remover revamp, Only the download is missing

Update commons.yml, excel-password-remover.yml, and 14 more files...
This commit is contained in:
2025-03-01 18:27:13 +01:00
parent 0a02a1e56d
commit b2064cbbaf
16 changed files with 465 additions and 115 deletions

View File

@@ -1,14 +1,20 @@
import {initCore} from "../../js/nibblepoker-core.mjs"
// Implied Globals: JSZip
if(JSZip == null) {
alert("JSZip isn't available !");
}
const excelFileRegex = /^.*\.xls[xm]$/gi;
const excelWorksheetRegex = /^xl\/worksheets\/.*.xml$/gi;
import {initCore} from "../../js/nibblepoker-core.mjs"
import {cloneTemplate} from "../../js/nibblepoker-template.mjs"
export const excelFileRegex = /^.*\.xls[xm]$/gi;
export const excelWorksheetRegex = /^xl\/worksheets\/.*.xml$/gi;
/**
* Checks if the given filename appears to be for an Excel file.
* @param fileName {string} Filename to be checked
* @returns {boolean} `true` if it appears to be an Excel file, `false` otherwise.
*/
function isExcelExtension(fileName) {
export function isExcelExtension(fileName) {
return fileName.match(excelFileRegex) !== null;
}
@@ -16,43 +22,269 @@ function isExcelExtension(fileName) {
{
initCore();
var outputZip;
var outputZipFilename = "default-filename.error.zip";
var filesTotalCount = 0;
var filesProcessedCount = 0;
var passwordsRemoved = 0;
//let outputZip;
//let outputZipFilename = "default-filename.error.zip";
//let filesTotalCount = 0;
//let filesProcessedCount = 0;
//let passwordsRemoved = 0;
/** @type {string} */
const appletId = "excel-password-remover";
/** @type {HTMLElement} */
const eEulaContainer = document.querySelector(`#${appletId}-eula`);
///** @type {HTMLInputElement} */
//const eEulaDontAskAgainOption = document.querySelector(`input#${appletId}-eula-remember`);
///** @type {HTMLButtonElement} */
//const eEulaAcceptButton = document.querySelector(`button#${appletId}-eula-accept`);
/** @type {HTMLInputElement} */
const eFileInput = document.querySelector(`input[type=file]#${appletId}-input-file`);
/** @type {HTMLButtonElement} */
const eFileInputClearButton = document.querySelector(`button#${appletId}-input-file-reset`);
/*function acceptTerms() {
document.getElementById("warning").hidden = true;
document.getElementById("file-select").hidden = false;
}*/
/** @type {HTMLElement} */
const eResultEmptyText = document.querySelector(`#${appletId}-details-empty`);
/** @type {HTMLElement} */
const eResultPopulatedText = document.querySelector(`#${appletId}-details-populated`);
/** @type {HTMLElement} */
const eResultContainer = document.querySelector(`#${appletId}-result-container`);
/** @type {HTMLTemplateElement} */
const eSuccessTemplate = document.querySelector(`template#tmpl-success-root`);
/** @type {HTMLTemplateElement} */
const eWarningTemplate = document.querySelector(`template#tmpl-warning-root`);
/** @type {HTMLTemplateElement} */
const eErrorTemplate = document.querySelector(`template#tmpl-error-root`);
/** @type {HTMLButtonElement} */
const eFileDownloadAllButton = document.querySelector(`button#${appletId}-files-download-all`);
/** @type {HTMLButtonElement} */
const eFileClearButton = document.querySelector(`button#${appletId}-files-clear`);
class ExcelFileData {
/** @type {File} */
originalFile;
/** @type {any} */
processedZipFile;
filesTotalCount = 0;
filesProcessedCount = 0;
passwordsRemoved = 0;
constructor(originalFile) {
this.originalFile = originalFile;
}
/** @returns {string} */
getOutputName() {
let outputZipExtension = "." + this.originalFile.name.split(".").pop();
let outputZipFilename = this.originalFile.name.substring(0, this.originalFile.name.length - outputZipExtension.length);
return outputZipFilename + "_no-password" + outputZipExtension;
}
}
/** @type {ExcelFileData[]} */
let rawWorksheetFiles = [];
function onFileAddedToDom() {
eResultEmptyText.hidden = true;
eResultPopulatedText.hidden = false;
}
function onFilesRemovedFromDom() {
eResultEmptyText.hidden = false;
eResultPopulatedText.hidden = true;
}
/**
* @param excelFile {ExcelFileData}
*/
function onFileHavingPasswordRemoved(excelFile) {
console.debug(`Removed ${excelFile.passwordsRemoved} password(s) from '${excelFile.originalFile.name}'`);
cloneTemplate(
eSuccessTemplate,
{
"tmpl-success-filename": excelFile.originalFile.name,
"tmpl-success-password-count": excelFile.passwordsRemoved
},
true
).then(eFragment => {
console.debug(eFragment);
const uuid = crypto.randomUUID();
console.debug(eFragment.children);
eFragment.children.id = uuid;
eResultContainer.appendChild(eFragment);
onFileAddedToDom();
});
}
/**
* @param excelFile {ExcelFileData}
*/
function onFileWithoutPasswords(excelFile) {
console.warn(`No password(s) were found in ${excelFile.originalFile.name} !`);
cloneTemplate(
eWarningTemplate,
{
"tmpl-warning-filename": excelFile.originalFile.name,
"tmpl-warning-message-extension": "",
//"tmpl-warning-message-no-password": "",
},
true
).then(eFragment => {
console.debug(eFragment);
eResultContainer.appendChild(eFragment);
onFileAddedToDom();
});
}
/**
* @param excelFile {ExcelFileData}
*/
function onFileWithInvalidExtension(excelFile) {
console.warn(`The given file '${excelFile.originalFile.name}' doesn't have an Excel extension`);
cloneTemplate(
eWarningTemplate,
{
"tmpl-warning-filename": excelFile.originalFile.name,
//"tmpl-warning-message-extension": "",
"tmpl-warning-message-no-password": "",
},
true
).then(eFragment => {
console.debug(eFragment);
eResultContainer.appendChild(eFragment);
onFileAddedToDom();
});
}
/**
* @param excelFile {ExcelFileData}
* @param error {any}
*/
function onExtractionFailure(excelFile, error) {
console.error("Failed to extract the content of the file in the browser ! ("+error.message+")");
cloneTemplate(
eErrorTemplate,
{
"tmpl-error-filename": excelFile.originalFile.name,
//"tmpl-error-message-jszip": ""
},
true
).then(eFragment => {
console.debug(eFragment);
eResultContainer.appendChild(eFragment);
onFileAddedToDom();
});
}
window.onload = function () {
eFileInput.addEventListener('change', function(e) {
let fileCount = e.target.files.length;
eFileDownloadAllButton.addEventListener("click", function() {
console.log(fileCount);
});
/*console.log(eEulaContainer);
console.log(eEulaDontAskAgainOption);
console.log(eEulaAcceptButton);
eEulaAcceptButton.addEventListener("click", function() {
eEulaContainer.hidden = true;
});*/
eFileClearButton.addEventListener("click", function() {
while (eResultContainer.firstChild) {
eResultContainer.firstChild.remove();
}
onFilesRemovedFromDom();
rawWorksheetFiles = [];
eFileInputClearButton.click();
});
eFileInput.addEventListener('change', function(e) {
rawWorksheetFiles = [];
for (let i = 0; i < e.target.files.length; i++) {
console.debug(e.target.files[i]);
rawWorksheetFiles.push(new ExcelFileData(e.target.files[i]));
}
rawWorksheetFiles.forEach(excelFile => {
if(!isExcelExtension(excelFile.originalFile.name)) {
onFileWithInvalidExtension(excelFile);
return;
}
JSZip.loadAsync(excelFile.originalFile).then(function(zip) {
console.group(`JSZip - ${excelFile.originalFile.name}`);
excelFile.processedZipFile = new JSZip();
excelFile.filesTotalCount = 0;
excelFile.filesProcessedCount = 0;
excelFile.passwordsRemoved = 0;
for(const[fileKey, fileValue] of Object.entries(zip.files)) {
excelFile.filesTotalCount++;
if(fileKey.match(excelWorksheetRegex)) {
console.debug("Checking: "+fileKey);
fileValue.async("string").then(function(fileText) {
console.group(`JSZip - ${excelFile.originalFile.name} - ${fileKey}`);
let startIndex = fileText.indexOf('<sheetProtection ');
if(startIndex === -1) {
// No password found.
excelFile.processedZipFile.file(fileKey, fileText);
console.debug("Analysed: "+fileKey);
} else {
// Removing the password.
let endIndex = fileText.indexOf('/>', startIndex) + 2;
fileText = fileText.replace(fileText.substr(startIndex, endIndex-startIndex), "");
excelFile.processedZipFile.file(fileKey, fileText);
console.debug("Processed: "+fileKey);
excelFile.passwordsRemoved++;
}
excelFile.filesProcessedCount++;
console.groupEnd();
});
} else {
// Other files.
console.debug("Ignoring: "+fileKey);
fileValue.async("string").then(function(fileText) {
console.group(`JSZip - ${excelFile.originalFile.name} - ${fileKey}`);
console.debug(`Copying as-is`);
excelFile.processedZipFile.file(fileKey, fileText);
excelFile.filesProcessedCount++;
console.groupEnd();
});
}
}
console.debug("Waiting for all the files to be processed !");
function waitFilesBeingProcessed() {
console.debug("Processed "+excelFile.filesProcessedCount+" file(s) out of "+excelFile.filesTotalCount);
if(excelFile.filesTotalCount !== excelFile.filesProcessedCount) {
setTimeout(waitFilesBeingProcessed, 50);
} else {
console.debug("Done, now switching the page !");
if(excelFile.passwordsRemoved > 0) {
onFileHavingPasswordRemoved(excelFile);
} else {
onFileWithoutPasswords(excelFile);
}
}
}
setTimeout(waitFilesBeingProcessed, 50);
console.groupEnd();
}, function (e) {
onExtractionFailure(excelFile, e);
});
});
});
}
}

View File

@@ -5,7 +5,7 @@
/**
* @param eTemplate {HTMLTemplateElement | string} The template to be cloned, or its ID.
* @param subParts {Object.<string, Node | string | number | boolean>}
* @param ignoreMissingParts {bool}
* @param ignoreMissingParts {boolean}
* @returns {Promise<DocumentFragment>}
*/
export function cloneTemplate(eTemplate,
@@ -34,14 +34,22 @@ export function cloneTemplate(eTemplate,
reject(`Unable to find sub-element with id '${key}' !`);
}
ePart.removeAttribute('id');
if(value instanceof Node) {
ePart.innerHTML = "";
ePart.appendChild(value);
} else {
ePart.innerHTML += value;
ePart.innerHTML = value;
}
}
}
const childElements = eClone.querySelectorAll('*');
childElements.forEach(eChild => {
eChild.removeAttribute('id');
});
resolve(eClone);
}
});

View File

@@ -1,6 +1,7 @@
// NibblePoker - UI Scripts
// NibblePoker - Mandatory Scripts
// Author: Herwin Bozet (@NibblePoker)
// License: Public Domain (This code)
// Remark: This modules contains all the scripts that are globally required on this website
export const animationStepCount = 10;

View File

@@ -0,0 +1 @@
jszip.min.js