Folders can now be dropped into the CyberChef input

This commit is contained in:
n1474335 2023-02-27 15:32:52 +00:00
parent cdde7166cf
commit dd6eae52ef
1 changed files with 89 additions and 2 deletions

View File

@ -905,7 +905,7 @@ class InputWaiter {
*
* @param {event} e
*/
inputDrop(e) {
async inputDrop(e) {
// This will be set if we're dragging an operation
if (e.dataTransfer.effectAllowed === "move")
return false;
@ -917,8 +917,95 @@ class InputWaiter {
// Dropped text is handled by the editor itself
if (e.dataTransfer.getData("Text")) return;
// Dropped files
if (e?.dataTransfer?.files?.length > 0) {
this.loadUIFiles(e.dataTransfer.files);
let files = [];
// Handling the files as FileSystemEntry objects allows us to open directories,
// but relies on a function that may be deprecated in future.
if (Object.prototype.hasOwnProperty.call(DataTransferItem.prototype, "webkitGetAsEntry")) {
const fileEntries = await this.getAllFileEntries(e.dataTransfer.items);
// Read all FileEntry objects into File objects
files = await Promise.all(fileEntries.map(async fe => await this.getFile(fe)));
} else {
files = e.dataTransfer.files;
}
this.loadUIFiles(files);
}
}
/**
*
* @param {DataTransferItemList} dataTransferItemList
* @returns {FileSystemEntry[]}
*/
async getAllFileEntries(dataTransferItemList) {
const fileEntries = [];
// Use BFS to traverse entire directory/file structure
const queue = [];
// Unfortunately dataTransferItemList is not iterable i.e. no forEach
for (let i = 0; i < dataTransferItemList.length; i++) {
// Note webkitGetAsEntry a non-standard feature and may change
// Usage is necessary for handling directories
queue.push(dataTransferItemList[i].webkitGetAsEntry());
}
while (queue.length > 0) {
const entry = queue.shift();
if (entry.isFile) {
fileEntries.push(entry);
} else if (entry.isDirectory) {
queue.push(...await this.readAllDirectoryEntries(entry.createReader()));
}
}
return fileEntries;
}
/**
* Get all the entries (files or sub-directories) in a directory by calling
* readEntries until it returns empty array
*
* @param {FileSystemDirectoryReader} directoryReader
* @returns {FileSystemEntry[]}
*/
async readAllDirectoryEntries(directoryReader) {
const entries = [];
let readEntries = await this.readEntriesPromise(directoryReader);
while (readEntries.length > 0) {
entries.push(...readEntries);
readEntries = await this.readEntriesPromise(directoryReader);
}
return entries;
}
/**
* Wrap readEntries in a promise to make working with readEntries easier.
* readEntries will return only some of the entries in a directory
* e.g. Chrome returns at most 100 entries at a time
*
* @param {FileSystemDirectoryReader} directoryReader
* @returns {Promise}
*/
async readEntriesPromise(directoryReader) {
try {
return await new Promise((resolve, reject) => {
directoryReader.readEntries(resolve, reject);
});
} catch (err) {
log.error(err);
}
}
/**
* Reads a FileEntry and returns it as a File object
* @param {FileEntry} fileEntry
* @returns {File}
*/
async getFile(fileEntry) {
try {
return new Promise((resolve, reject) => fileEntry.file(resolve, reject));
} catch (err) {
log.error(err);
}
}