From a837129f0c953dbef411b48993cef5aad070e5e1 Mon Sep 17 00:00:00 2001 From: joshuaboud Date: Fri, 16 Jul 2021 13:34:09 -0300 Subject: [PATCH] fix aborting upload for directories & empty files --- navigator/components/FileUpload.js | 12 +++- navigator/components/NavDragDrop.js | 104 ++++++++++++++++++---------- navigator/scripts/write-chunks.py3 | 19 ++--- 3 files changed, 87 insertions(+), 48 deletions(-) diff --git a/navigator/components/FileUpload.js b/navigator/components/FileUpload.js index 12273c9..6497d59 100644 --- a/navigator/components/FileUpload.js +++ b/navigator/components/FileUpload.js @@ -19,6 +19,7 @@ import {NavWindow} from "./NavWindow.js"; import {format_time_remaining} from "../functions.js"; +import {ModalPrompt} from "./ModalPrompt.js"; export class FileUpload { /** @@ -40,6 +41,7 @@ export class FileUpload { this.chunks = this.slice_file(file); this.chunk_index = 0; this.timestamp = Date.now(); + this.modal_prompt = new ModalPrompt(); } check_if_exists() { @@ -130,7 +132,7 @@ export class FileUpload { this.proc.fail((e, data) => { this.reader.onload = () => {} this.done(); - this.nav_window_ref.modal_prompt.alert(data, e); + this.nav_window_ref.modal_prompt.alert(e, data); }) this.proc.done((data) => { this.nav_window_ref.refresh(); @@ -147,7 +149,13 @@ export class FileUpload { } }; })(this); - this.reader.readAsArrayBuffer(this.chunks[0]); + try { + this.reader.readAsArrayBuffer(this.chunks[0]); + } catch { + this.reader.onload = () => {}; + this.done(); + this.modal_prompt.alert("Failed to read file: " + this.filename, "Upload of directories and empty files not supported."); + } } arrayBufferToBase64(buffer) { diff --git a/navigator/components/NavDragDrop.js b/navigator/components/NavDragDrop.js index 3ffc75f..7c6454a 100644 --- a/navigator/components/NavDragDrop.js +++ b/navigator/components/NavDragDrop.js @@ -27,16 +27,17 @@ export class NavDragDrop { * @param {NavWindow} nav_window_ref */ constructor(drop_area, nav_window_ref) { - drop_area.addEventListener("dragenter", this); - drop_area.addEventListener("dragover", this); - drop_area.addEventListener("dragleave", this); - drop_area.addEventListener("drop", this); + drop_area.addEventListener("dragenter", this, false); + drop_area.addEventListener("dragover", this, false); + drop_area.addEventListener("dragleave", this, false); + drop_area.addEventListener("drop", this, false); this.drop_area = drop_area; this.nav_window_ref = nav_window_ref; } - - handleEvent(e) { + + async handleEvent(e) { e.preventDefault(); + e.stopPropagation(); switch(e.type){ case "dragenter": this.drop_area.classList.add("drag-enter"); @@ -47,45 +48,72 @@ export class NavDragDrop { this.drop_area.classList.remove("drag-enter"); break; case "drop": - if (e.dataTransfer.items) { - for (let item of e.dataTransfer.items) { - if (item.kind === 'file') { - var file = item.getAsFile(); - if (file.type === "" && file.size !== 0) { - this.nav_window_ref.modal_prompt.alert(file.name + ": Cannot upload folders."); - continue; - } - if (file.size === 0) { - var proc = cockpit.spawn( - ["/usr/share/cockpit/navigator/scripts/touch.py3", this.nav_window_ref.pwd().path_str() + "/" + file.name], - {superuser: "try", err: "out"} - ); - proc.done(() => { - this.nav_window_ref.refresh(); - }); - proc.fail((e, data) => { - this.nav_window_ref.modal_prompt.alert(data); - }); - } else { - var uploader = new FileUpload(file, this.nav_window_ref); - uploader.upload(); - } - } + let uploads = []; + // console.log(e); + // console.log(e.dataTransfer.files); + // if (e.dataTransfer.items) { + // for (let item of e.dataTransfer.items) { + // if (item.kind === 'file') { + // var file = item.getAsFile(); + // if (file.type === "" && file.size !== 0) { + // await this.nav_window_ref.modal_prompt.alert(file.name + ": Cannot upload folders."); + // continue; + // } + // if (file.size === 0) { + // var proc = cockpit.spawn( + // ["/usr/share/cockpit/navigator/scripts/touch.py3", this.nav_window_ref.pwd().path_str() + "/" + file.name], + // {superuser: "try", err: "out"} + // ); + // proc.done(() => { + // this.nav_window_ref.refresh(); + // }); + // } else { + // uploads.push(new FileUpload(file, this.nav_window_ref)); + // } + // } + // } + // } else { + for (let file of e.dataTransfer.files) { + console.log(file); + // if (file.type === "") + // continue; + uploads.push(new FileUpload(file, this.nav_window_ref)); } - } else { - for (let file of ev.dataTransfer.files) { - if (file.type === "") - continue; - var uploader = new FileUpload(file, this.nav_window_ref); - uploader.upload(); + // } + this.drop_area.classList.remove("drag-enter"); + if (uploads.length === 0) + break; + let keepers = []; + let requests = {}; + for (let upload of uploads) { + if (!await upload.check_if_exists()) { + keepers.push(upload.filename); + continue; + } + let request = {}; + request.label = upload.filename; + request.type = "checkbox"; + let id = upload.filename; + requests[id] = request; + } + if (Object.keys(requests).length > 0) { + let responses = await this.nav_window_ref.modal_prompt.prompt( + "Conflicts found while uploading. Replace?", + requests + ) + if (responses === null) + break; + for (let key of Object.keys(responses)) { + if (responses[key]) + keepers.push(key); } } - this.drop_area.classList.remove("drag-enter"); + uploads = uploads.filter((upload) => {return keepers.includes(upload.filename)}); + uploads.forEach((upload) => {upload.upload()}); break; default: this.drop_area.classList.remove("drag-enter"); break; } - e.stopPropagation(); } } diff --git a/navigator/scripts/write-chunks.py3 b/navigator/scripts/write-chunks.py3 index 8beaf37..36494cf 100755 --- a/navigator/scripts/write-chunks.py3 +++ b/navigator/scripts/write-chunks.py3 @@ -32,27 +32,29 @@ import sys import json def write_chunk(chunk, file): + if not file: + path = sys.argv[1] + try: + file = open(path, "wb") + except Exception as e: + print(e) + sys.exit(1) seek = chunk["seek"] data = base64.b64decode(chunk["chunk"]) file.seek(seek) file.write(data) def main(): + file = None if len(sys.argv) != 2: print("Invalid number of arguments.") sys.exit(1) - path = sys.argv[1] - try: - file = open(path, "wb") - except Exception as e: - print(e) - sys.exit(1) while True: try: json_in = input() except EOFError: break - json_list = json_in.split("\n") + json_list = json_in.split("\n") # need to split in case writes happen faster than reads for json_obj in json_list: try: obj_in = json.loads(json_obj) @@ -63,7 +65,8 @@ def main(): log.close() sys.exit(1) write_chunk(obj_in, file) - file.close() + if file: + file.close() sys.exit(0) if __name__ == "__main__":