'use strict'; /** BSD-2-Clause license * * Copyright (c) 2018-2023 NST , sss , smake . * */ /** * File handle files in clipboard and dispath events on transferring */ class FileEntry { constructor(rdp, raw_ft, fileId) { if (raw_ft instanceof File) { this.file = raw_ft; var file = this.file; var filename = new TextEncoder().encode(file.name); var raw_ft = new Uint8Array( new ArrayBuffer(2 + 4 + 8 + filename.length) ); var name_len = new Uint16Array(1); var id = new Uint32Array(1); var size = new BigUint64Array(1); name_len[0] = filename.length; id[0] = fileId; size[0] = BigInt(file.size); raw_ft.set(new Uint8Array(name_len.buffer)); raw_ft.set(new Uint8Array(id.buffer), 2); raw_ft.set(new Uint8Array(size.buffer), 2 + 4); raw_ft.set(filename, 2 + 4 + 8); } this.raw_ft = raw_ft; this.rdp = rdp; this.status = 0; this.name_len = new Uint16Array(this.raw_ft)[0]; this.id = new Uint32Array(this.raw_ft.slice(2, 2 + 4))[0]; this.size = new BigUint64Array(this.raw_ft.slice(6, 14).buffer)[0]; this.log = true; this.transfer_id = null; this.chunkSize = BigInt(8192); this.offset = BigInt(0); this.chunks = []; this.lastChunkTime = null; this.lastOffset = BigInt(0); this.timout = 120; this.refreshTimeout = 3; return this; } get fullname() { var fullname = new Uint8Array(this.raw_ft.slice(14, 14 + this.name_len)); fullname = new TextDecoder("utf-8").decode(fullname.filter(v => v != 0)); return fullname; } get isTransferring() { if (this.status == 2) { var now = new Date(); var timeleft = Math.floor((now - this.lastChunkTime)/100); if (!this.lastChunkTime) { return true; } if ( timeleft > this.timout ) { this.SendFtFinish(); return false; } else { return true; } } else { return false; } } get name() { var name = this.fullname.split('/').pop(); name = name.split('\\').pop(); return name; } get nextChunkRequest() { if (this.offset >= this.size) { this.status = 0; return; } this.status = 2; //transfer in progress var buf = new ArrayBuffer(4 + 4 + 8 + 8); var c = new Uint32Array(buf, 0, 1); c[0] = 0x09; // ws_in_ft_request var file_id = new Uint32Array(buf, 4, 1); var req_size = new BigUint64Array(buf, 4 + 4, 1); var file_offset = new BigUint64Array(buf, 4 + 4 + 8, 1); file_id[0] = this.id; req_size[0] = this.size; file_offset[0] = this.offset; return buf } get progress () { if (this.status == 2) { return '(' + this.chunks.length + "/" + this.size / this.chunkSize + ')'; } else { return ""; } } get percents () { if (this.status == 2) { return Math.floor((this.chunks.length / parseInt(this.size / this.chunkSize)) * 100); } else { return ""; } } get sizeHumanReadable() { var bytes = parseInt(this.size); return this.sizeParse(this.size); } get speed () { if (this.status == 2) { var bytes = parseInt(this.offset - this.lastOffset); return this.sizeParse(Math.floor(bytes / this.refreshTimeout)); } else { return ""; } } get uiElement () { var html = ""; if (!this.file) { if ( this.size < BigInt(2147483647) ){ html += '
  • ' html += '' } else { html += '
  • '; html += '(' + lables.file_lager_then_2g +') ' } } else { html += '
  • ' html += '' } if (this.status == 2) { html += this.id + ': ' + this.name + ': ' + this.sizeHumanReadable + " " + this.percents + "% (" + this.speed + "/sec)" +'
  • ' } else { html += this.id + ': ' + this.name + ': ' + this.sizeHumanReadable + '' } html += '' return html; } newChunk(data) { var size = BigInt(new Uint32Array(data,0,3)[2]); this.transfer_id = new Uint32Array(data,0,3)[1]; if (this.log) { var f = this; setTimeout(function () { f.log = true; }, this.refreshTimeout * 1000); // console.log(f.name + ": " + f.progress); f.log = false; this.rdp.cbd.update(); f.lastOffset = f.offset; } if (this.status == 2 && new Uint32Array(data,0,3)[2] != 0 ) { if (this.offset + size >= this.size) { this.status = 0; this.lastChunkTime = new Date(); this.chunks.push(data.slice(12)); this.offset += size; this.pushFileDownload(); } else { this.lastChunkTime = new Date(); this.chunks.push(data.slice(12)); this.offset += size; } } } sendChunk(req_size, offset) { if (!this.transfer_id) { this.transfer_id = (Math.random() * 4294967292).round(0); } this.status = 2; var offset = parseInt(offset); var req_size = parseInt(req_size); var blob = this.file.slice(offset, offset + req_size); var reader = new FileReader(); reader.fe = this; reader.onload = function(e) { var file = e.target.fe; var sock = e.target.fe.rdp.sock; var c = e.target.result; var buf = new ArrayBuffer(4 + 4 + 4 + c.byteLength); var cmd = new Uint32Array(buf, 0, 3); var transfer_id = new Uint32Array(buf, 0, 3); var size = new Uint32Array(buf, 0, 3); var data = new Uint8Array(buf) cmd[0] = 0x0a; // ws_in_ft_chunk transfer_id[1] = file.transfer_id; size[2] = c.byteLength; data.set(new Uint8Array(c), 12); // console.log("Sending chunk:" + (buf.byteLength - 12)); // console.log(buf.toHexdump()); file.lastChunkTime = new Date(); sock.send(buf); file.offset += BigInt(c.byteLength); file.lastOffset = file.offset; if (file.offset >= file.size) { file.SendFtFinish(); } }; reader.onerror = function(e) { var file = e.target.fe; var msg = file.name + ": " + e.target.error.message; file.rdp.fireEvent('alert', msg); file.SendFtFinish(); }; reader.readAsArrayBuffer(blob); } SendFtFinish() { if (this.offset >= this.size) { this.status = 0; } else { this.status = 1; } var buf = new ArrayBuffer(4 + 4 + 4 + 1); var cmd = new Uint32Array(buf, 0, 1); var id = new Uint32Array(buf, 4, 1); var transfer_id = new Uint32Array(buf, 8, 1); var status = new Uint8Array(buf, 12, 1); cmd[0] = 0x0b; // ws_in_ft_finished id[0] = this.id; transfer_id[0] = this.transfer_id; status[0] = this.status; // console.log(buf.toHexdump()); this.rdp.sock.send(buf); return; } sizeParse(bytes) { var bytes = parseInt(bytes); var decimals = null; if(bytes == 0) return '0 Bytes'; var k = 1024; var dm = decimals <= 0 ? 0 : decimals || 2; var sizes = lables.size_names; var i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i]; } pushFileDownload () { var blob = new Blob(this.chunks) var url = window.URL.createObjectURL(blob); var a = document.createElement("a"); document.body.appendChild(a); a.style = "display: none"; a.href = url; a.download = this.name; a.click(); window.URL.revokeObjectURL(url); this.chunks = []; } getFile() { if (this.rdp.sock.readyState == this.rdp.sock.OPEN) { this.log.debug('requesting file transfer', 1); var buf = this.nextChunkRequest; // console.log(buf.toHexdump()); this.rdp.sock.send(buf); }; } // startSending(offset) { // if (!this.transfer_id) { // this.transfer_id = (Math.random() * 4294967292).round(0); // } // this.status = 3; // var offset = parseInt(0); // var chunkSize = parseInt(8); // var blob = this.file.slice(offset, offset + chunkSize); // var reader = new FileReader(); // reader.fe = this; // reader.onload = function(e) { // var file = e.target.fe; // var sock = e.target.fe.rdp.sock; // var c = e.target.result; // var buf = new ArrayBuffer(4 + 4 + 4 + c.byteLength); // var cmd = new Uint32Array(buf, 0, 3); // var transfer_id = new Uint32Array(buf, 0, 3); // var size = new Uint32Array(buf, 0, 3); // var data = new Uint8Array(buf) // cmd[0] = 0x0a; // ws_in_ft_chunk // transfer_id[1] = file.transfer_id; // size[2] = c.byteLength; // data.set(new Uint8Array(c), 12); // console.log("Sending chunk:" + (buf.byteLength - 12)); // // console.log(buf.toHexdump()); // sock.send(buf); // file.offset += BigInt(c.byteLength); // file.sendNextChunk(); // }; // reader.readAsArrayBuffer(blob); // } // sendNextChunk() { // if (this.status != 3) { // return; // } // if (this.offset >= this.size) { // this.status = 0; // var buf = new ArrayBuffer(4 + 4 + 4 + 1); // var cmd = new Uint32Array(buf, 0, 1); // var id = new Uint32Array(buf, 4, 1); // var transfer_id = new Uint32Array(buf, 8, 1); // var status = new Uint8Array(buf, 9, 1); // cmd[0] = 0x0b; // ws_in_ft_finished // id[0] = this.id; // transfer_id[0] = this.transfer_id; // status[0] = 0; // console.log(buf.toHexdump()); // this.rdp.sock.send(buf); // return; // } // var offset = parseInt(this.offset); // var chunkSize = parseInt(this.chunkSize); // var blob = this.file.slice(offset, offset + chunkSize); // var reader = new FileReader(); // reader.fe = this; // reader.onload = function(e) { // var file = e.target.fe; // var sock = e.target.fe.rdp.sock; // var c = e.target.result; // var buf = new ArrayBuffer(4 + 4 + 4 + c.byteLength); // var cmd = new Uint32Array(buf, 0, 3); // var transfer_id = new Uint32Array(buf, 0, 3); // var size = new Uint32Array(buf, 0, 3); // var data = new Uint8Array(buf) // cmd[0] = 0x0a; // ws_in_ft_chunk // transfer_id[1] = file.transfer_id; // size[2] = c.byteLength; // data.set(new Uint8Array(c), 12); // console.log("Sending chunk:" + (buf.byteLength - 12)); // // console.log(buf.toHexdump()); // sock.send(buf); // file.offset += BigInt(c.byteLength); // file.sendNextChunk(); // }; // reader.readAsArrayBuffer(blob); // } }