diff options
author | sss <sss@dark-alexandr.net> | 2023-01-17 00:38:19 +0300 |
---|---|---|
committer | sss <sss@dark-alexandr.net> | 2023-01-17 00:38:19 +0300 |
commit | cc3f33db7a8d3c4ad373e646b199808e01bc5d9b (patch) | |
tree | ec09d690c7656ab5f2cc72607e05fb359c24d8b2 /www/js/file-transfer.js |
added webrdp public code
Diffstat (limited to 'www/js/file-transfer.js')
-rw-r--r-- | www/js/file-transfer.js | 365 |
1 files changed, 365 insertions, 0 deletions
diff --git a/www/js/file-transfer.js b/www/js/file-transfer.js new file mode 100644 index 0000000..e5def90 --- /dev/null +++ b/www/js/file-transfer.js @@ -0,0 +1,365 @@ +'use strict'; +/** BSD-2-Clause license + * + * Copyright (c) 2018-2023 NST <www.newinfosec.ru>, sss <sss at dark-alexandr dot net>, smake <smake at ya dot ru>. + * + */ + +/** + * 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 += '<li class="tab-menu" onclick="rdp.cbd.ClipoboardFileGet('+this.id+')">' + html += '<a>' + } else { + html += '<li class="tab-menu">'; + html += '<a style="background-color: #555">(' + lables.file_lager_then_2g +') ' + } + } else { + html += '<li class="tab-menu">' + html += '<a>' + } + if (this.status == 2) { + html += this.id + ': ' + this.name + ': ' + this.sizeHumanReadable + " " + this.percents + "% (" + this.speed + "/sec)" +'</li>' + } else { + html += this.id + ': ' + this.name + ': ' + this.sizeHumanReadable + '</li>' + } + html += '</a></li>' + 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); + // } +} + + + + |