summaryrefslogtreecommitdiff
path: root/www/js/file-transfer.js
diff options
context:
space:
mode:
authorsss <sss@dark-alexandr.net>2023-01-17 00:38:19 +0300
committersss <sss@dark-alexandr.net>2023-01-17 00:38:19 +0300
commitcc3f33db7a8d3c4ad373e646b199808e01bc5d9b (patch)
treeec09d690c7656ab5f2cc72607e05fb359c24d8b2 /www/js/file-transfer.js
added webrdp public code
Diffstat (limited to 'www/js/file-transfer.js')
-rw-r--r--www/js/file-transfer.js365
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);
+ // }
+}
+
+
+
+