mirror of
				https://github.com/Ylianst/MeshCentral.git
				synced 2025-10-29 23:35:02 -04:00 
			
		
		
		
	Merge branch 'master' of https://github.com/silversword411/MeshCentral
This commit is contained in:
		
						commit
						56527b76e0
					
				| @ -198,6 +198,7 @@ | ||||
|     <Compile Include="rdp\protocol\index.js" /> | ||||
|     <Compile Include="rdp\protocol\nla.js" /> | ||||
|     <Compile Include="rdp\protocol\pdu\caps.js" /> | ||||
|     <Compile Include="rdp\protocol\pdu\cliprdr.js" /> | ||||
|     <Compile Include="rdp\protocol\pdu\data.js" /> | ||||
|     <Compile Include="rdp\protocol\pdu\global.js" /> | ||||
|     <Compile Include="rdp\protocol\pdu\index.js" /> | ||||
|  | ||||
| @ -152,7 +152,7 @@ module.exports.CreateMstscRelay = function (parent, db, ws, req, args, domain) { | ||||
|                         obj.wsClient._socket.pause(); | ||||
|                         try { | ||||
|                             obj.relaySocket.write(data, function () { | ||||
|                                 try { obj.wsClient._socket.resume(); } catch (ex) { console.log(ex); } | ||||
|                                 if (obj.wsClient && obj.wsClient._socket) { try { obj.wsClient._socket.resume(); } catch (ex) { console.log(ex); } } | ||||
|                             }); | ||||
|                         } catch (ex) { console.log(ex); obj.close(); } | ||||
|                     } | ||||
| @ -201,6 +201,10 @@ module.exports.CreateMstscRelay = function (parent, db, ws, req, args, domain) { | ||||
|                 try { ws.send(bitmap.data); } catch (ex) { } // Send the bitmap data as binary
 | ||||
|                 delete bitmap.data; | ||||
|                 send(['rdp-bitmap', bitmap]); // Send the bitmap metadata seperately, without bitmap data.
 | ||||
|             }).on('clipboard', function (content) { | ||||
|                 // Clipboard data changed
 | ||||
|                 console.log('RDP clipboard recv', content); | ||||
|                 send(['rdp-clipboard', content]); | ||||
|             }).on('close', function () { | ||||
|                 send(['rdp-close']); | ||||
|             }).on('error', function (err) { | ||||
| @ -317,6 +321,7 @@ module.exports.CreateMstscRelay = function (parent, db, ws, req, args, domain) { | ||||
|                 } | ||||
|                 case 'mouse': { if (rdpClient && (obj.viewonly != true)) { rdpClient.sendPointerEvent(msg[1], msg[2], msg[3], msg[4]); } break; } | ||||
|                 case 'wheel': { if (rdpClient && (obj.viewonly != true)) { rdpClient.sendWheelEvent(msg[1], msg[2], msg[3], msg[4]); } break; } | ||||
|                 case 'clipboard': { rdpClient.setClipboardData(msg[1]); break; } | ||||
|                 case 'scancode': { | ||||
|                     if (obj.limitedinput == true) { // Limit keyboard input
 | ||||
|                         var ok = false, k = msg[1]; | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| { | ||||
|   "name": "meshcentral", | ||||
|   "version": "1.0.21", | ||||
|   "version": "1.0.22", | ||||
|   "keywords": [ | ||||
|     "Remote Device Management", | ||||
|     "Remote Device Monitoring", | ||||
|  | ||||
| @ -83,6 +83,10 @@ var CreateRDPDesktop = function (canvasid) { | ||||
|                         obj.Stop(); | ||||
|                         break; | ||||
|                     } | ||||
|                     case 'rdp-clipboard': { | ||||
|                         console.log('clipboard', msg[1]); | ||||
|                         break; | ||||
|                     } | ||||
|                     case 'ping': { obj.socket.send('["pong"]'); break; } | ||||
|                     case 'pong': { break; } | ||||
|                 } | ||||
| @ -100,6 +104,14 @@ var CreateRDPDesktop = function (canvasid) { | ||||
|         if (obj.socket) { obj.socket.close(); } | ||||
|     } | ||||
| 
 | ||||
|     obj.m.setClipboard = function (content) { | ||||
|         console.log('s1'); | ||||
|         if (obj.socket) { | ||||
|             console.log('s2', content); | ||||
|             obj.socket.send(JSON.stringify(['clipboard', content])); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     function changeState(newstate) { | ||||
|         if (obj.State == newstate) return; | ||||
|         obj.State = newstate; | ||||
| @ -153,14 +165,14 @@ var CreateRDPDesktop = function (canvasid) { | ||||
|     } | ||||
|     obj.m.handleKeyUp = function (e) { | ||||
|         if (!obj.socket || (obj.State != 3)) return; | ||||
|         console.log('handleKeyUp', Mstsc.scancode(e)); | ||||
|         //console.log('handleKeyUp', Mstsc.scancode(e));
 | ||||
|         obj.socket.send(JSON.stringify(['scancode', Mstsc.scancode(e), false])); | ||||
|         e.preventDefault(); | ||||
|         return false; | ||||
|     } | ||||
|     obj.m.handleKeyDown = function (e) { | ||||
|         if (!obj.socket || (obj.State != 3)) return; | ||||
|         console.log('handleKeyDown', Mstsc.scancode(e)); | ||||
|         //console.log('handleKeyDown', Mstsc.scancode(e));
 | ||||
|         obj.socket.send(JSON.stringify(['scancode', Mstsc.scancode(e), true])); | ||||
|         e.preventDefault(); | ||||
|         return false; | ||||
|  | ||||
							
								
								
									
										327
									
								
								rdp/protocol/pdu/cliprdr.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										327
									
								
								rdp/protocol/pdu/cliprdr.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,327 @@ | ||||
| const type = require('../../core').type; | ||||
| const EventEmitter = require('events').EventEmitter; | ||||
| const caps = require('./caps'); | ||||
| const log = require('../../core').log; | ||||
| const data = require('./data'); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /** | ||||
|  * Cliprdr channel for all clipboard | ||||
|  * capabilities exchange | ||||
|  */ | ||||
| class Cliprdr extends EventEmitter { | ||||
| 
 | ||||
|   constructor(transport) { | ||||
|     super(); | ||||
|     this.transport = transport; | ||||
|     // must be init via connect event
 | ||||
|     this.userId = 0; | ||||
|     this.serverCapabilities = []; | ||||
|     this.clientCapabilities = []; | ||||
|   } | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /** | ||||
|  * Client side of Cliprdr channel automata | ||||
|  * @param transport | ||||
|  */ | ||||
| class Client extends Cliprdr { | ||||
| 
 | ||||
|   constructor(transport, fastPathTransport) { | ||||
| 
 | ||||
|     super(transport, fastPathTransport); | ||||
| 
 | ||||
|     this.transport.once('connect', (gccCore, userId, channelId) => { | ||||
|       this.connect(gccCore, userId, channelId); | ||||
|     }).on('close', () => { | ||||
|       this.emit('close'); | ||||
|     }).on('error', (err) => { | ||||
|       this.emit('error', err); | ||||
|     }); | ||||
| 
 | ||||
|     this.content = ''; | ||||
|      | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * connect function | ||||
|    * @param gccCore {type.Component(clientCoreData)} | ||||
|    */ | ||||
|   connect(gccCore, userId, channelId) { | ||||
|     this.gccCore = gccCore; | ||||
|     this.userId = userId; | ||||
|     this.channelId = channelId; | ||||
|     this.transport.once('cliprdr', (s) => { | ||||
|       this.recv(s); | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
| 
 | ||||
|   send(message) { | ||||
|     this.transport.send('cliprdr', new type.Component([ | ||||
|       // Channel PDU Header
 | ||||
|       new type.UInt32Le(message.size()), | ||||
|       // CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST | CHANNEL_FLAG_SHOW_PROTOCOL
 | ||||
|       new type.UInt32Le(0x13), | ||||
|       message | ||||
|     ])); | ||||
|   }; | ||||
| 
 | ||||
|   recv(s) { | ||||
|     s.offset = 18; | ||||
|     const pdu = data.clipPDU().read(s), type = data.ClipPDUMsgType; | ||||
| 
 | ||||
|     switch (pdu.obj.header.obj.msgType.value) { | ||||
|       case type.CB_MONITOR_READY: | ||||
|         this.recvMonitorReadyPDU(s); | ||||
|         break; | ||||
|       case type.CB_FORMAT_LIST: | ||||
|         this.recvFormatListPDU(s); | ||||
|         break; | ||||
|       case type.CB_FORMAT_LIST_RESPONSE: | ||||
|         this.recvFormatListResponsePDU(s); | ||||
|         break; | ||||
|       case type.CB_FORMAT_DATA_REQUEST: | ||||
|         this.recvFormatDataRequestPDU(s); | ||||
|         break; | ||||
|       case type.CB_FORMAT_DATA_RESPONSE: | ||||
|         this.recvFormatDataResponsePDU(s); | ||||
|         break; | ||||
|       case type.CB_TEMP_DIRECTORY: | ||||
|         break; | ||||
|       case type.CB_CLIP_CAPS: | ||||
|         this.recvClipboardCapsPDU(s); | ||||
|         break; | ||||
|       case type.CB_FILECONTENTS_REQUEST: | ||||
|     } | ||||
| 
 | ||||
|     this.transport.once('cliprdr', (s) => { | ||||
|       this.recv(s); | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Receive capabilities from server | ||||
|    * @param s {type.Stream} | ||||
|    */ | ||||
|   recvClipboardCapsPDU(s) { | ||||
|     // Start at 18
 | ||||
|     s.offset = 18; | ||||
|     // const pdu = data.clipPDU().read(s);
 | ||||
|     // console.log('recvClipboardCapsPDU', s);
 | ||||
|   } | ||||
| 
 | ||||
| 
 | ||||
|   /** | ||||
|    * Receive monitor ready from server | ||||
|    * @param s {type.Stream} | ||||
|    */ | ||||
|   recvMonitorReadyPDU(s) { | ||||
|     s.offset = 18; | ||||
|     // const pdu = data.clipPDU().read(s);
 | ||||
|     // console.log('recvMonitorReadyPDU', s);
 | ||||
| 
 | ||||
|     this.sendClipboardCapsPDU(); | ||||
|     // this.sendClientTemporaryDirectoryPDU();
 | ||||
|     this.sendFormatListPDU(); | ||||
|   } | ||||
| 
 | ||||
| 
 | ||||
|   /** | ||||
|    * Send clipboard capabilities PDU | ||||
|    */ | ||||
|   sendClipboardCapsPDU() { | ||||
|     this.send(new type.Component({ | ||||
|       msgType: new type.UInt16Le(data.ClipPDUMsgType.CB_CLIP_CAPS), | ||||
|       msgFlags: new type.UInt16Le(0x00), | ||||
|       dataLen: new type.UInt32Le(0x10), | ||||
|       cCapabilitiesSets: new type.UInt16Le(0x01), | ||||
|       pad1: new type.UInt16Le(0x00), | ||||
|       capabilitySetType: new type.UInt16Le(0x01), | ||||
|       lengthCapability: new type.UInt16Le(0x0c), | ||||
|       version: new type.UInt32Le(0x02), | ||||
|       capabilityFlags: new type.UInt32Le(0x02) | ||||
|     })); | ||||
|   } | ||||
| 
 | ||||
| 
 | ||||
|   /** | ||||
|    * Send client temporary directory PDU | ||||
|    */ | ||||
|   sendClientTemporaryDirectoryPDU(path = '') { | ||||
|     // TODO
 | ||||
|     this.send(new type.Component({ | ||||
|       msgType: new type.UInt16Le(data.ClipPDUMsgType.CB_TEMP_DIRECTORY), | ||||
|       msgFlags: new type.UInt16Le(0x00), | ||||
|       dataLen: new type.UInt32Le(0x0208), | ||||
|       wszTempDir: new type.BinaryString(Buffer.from('D:\\Vectors' + Array(251).join('\x00'), 'ucs2'), { readLength : new type.CallableValue(520)}) | ||||
|     })); | ||||
|   } | ||||
| 
 | ||||
| 
 | ||||
|   /** | ||||
|    * Send format list PDU | ||||
|    */ | ||||
|   sendFormatListPDU() { | ||||
|     this.send(new type.Component({ | ||||
|       msgType: new type.UInt16Le(data.ClipPDUMsgType.CB_FORMAT_LIST), | ||||
|       msgFlags: new type.UInt16Le(0x00), | ||||
| 
 | ||||
|       dataLen: new type.UInt32Le(0x24), | ||||
| 
 | ||||
|       formatId6: new type.UInt32Le(0xc004), | ||||
|       formatName6: new type.BinaryString(Buffer.from('Native\x00' , 'ucs2'), { readLength : new type.CallableValue(14)}), | ||||
| 
 | ||||
|       formatId8: new type.UInt32Le(0x0d), | ||||
|       formatName8: new type.UInt16Le(0x00), | ||||
| 
 | ||||
|       formatId9: new type.UInt32Le(0x10), | ||||
|       formatName9: new type.UInt16Le(0x00), | ||||
| 
 | ||||
|       formatId0: new type.UInt32Le(0x01), | ||||
|       formatName0: new type.UInt16Le(0x00), | ||||
|        | ||||
|       // dataLen: new type.UInt32Le(0xe0),
 | ||||
| 
 | ||||
|       // formatId1: new type.UInt32Le(0xc08a),
 | ||||
|       // formatName1: new type.BinaryString(Buffer.from('Rich Text Format\x00' , 'ucs2'), { readLength : new type.CallableValue(34)}),
 | ||||
| 
 | ||||
|       // formatId2: new type.UInt32Le(0xc145),
 | ||||
|       // formatName2: new type.BinaryString(Buffer.from('Rich Text Format Without Objects\x00' , 'ucs2'), { readLength : new type.CallableValue(66)}),
 | ||||
| 
 | ||||
|       // formatId3: new type.UInt32Le(0xc143),
 | ||||
|       // formatName3: new type.BinaryString(Buffer.from('RTF As Text\x00' , 'ucs2'), { readLength : new type.CallableValue(24)}),
 | ||||
| 
 | ||||
|       // formatId4: new type.UInt32Le(0x01),
 | ||||
|       // formatName4: new type.BinaryString(0x00),
 | ||||
| 
 | ||||
|       formatId5: new type.UInt32Le(0x07), | ||||
|       formatName5: new type.UInt16Le(0x00), | ||||
| 
 | ||||
|       // formatId6: new type.UInt32Le(0xc004),
 | ||||
|       // formatName6: new type.BinaryString(Buffer.from('Native\x00' , 'ucs2'), { readLength : new type.CallableValue(14)}),
 | ||||
|        | ||||
|       // formatId7: new type.UInt32Le(0xc00e),
 | ||||
|       // formatName7: new type.BinaryString(Buffer.from('Object Descriptor\x00' , 'ucs2'), { readLength : new type.CallableValue(36)}),
 | ||||
| 
 | ||||
|       // formatId8: new type.UInt32Le(0x03),
 | ||||
|       // formatName8: new type.UInt16Le(0x00),
 | ||||
| 
 | ||||
|       // formatId9: new type.UInt32Le(0x10),
 | ||||
|       // formatName9: new type.UInt16Le(0x00),
 | ||||
| 
 | ||||
|       // formatId0: new type.UInt32Le(0x07),
 | ||||
|       // formatName0: new type.UInt16Le(0x00),
 | ||||
|     })); | ||||
| 
 | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Recvie format list PDU from server | ||||
|    * @param {type.Stream} s  | ||||
|    */ | ||||
|   recvFormatListPDU(s) { | ||||
|     s.offset = 18; | ||||
|     // const pdu = data.clipPDU().read(s);
 | ||||
|     // console.log('recvFormatListPDU', s);
 | ||||
|     this.sendFormatListResponsePDU(); | ||||
|   } | ||||
| 
 | ||||
| 
 | ||||
|   /** | ||||
|    * Send format list reesponse | ||||
|    */ | ||||
|    sendFormatListResponsePDU() { | ||||
|      this.send(new type.Component({ | ||||
|         msgType: new type.UInt16Le(data.ClipPDUMsgType.CB_FORMAT_LIST_RESPONSE), | ||||
|         msgFlags: new type.UInt16Le(0x01), | ||||
|         dataLen: new type.UInt32Le(0x00), | ||||
|      })); | ||||
| 
 | ||||
|      this.sendFormatDataRequestPDU(); | ||||
|    } | ||||
| 
 | ||||
| 
 | ||||
|   /** | ||||
|    * Receive format list response from server | ||||
|    * @param s {type.Stream} | ||||
|    */ | ||||
|   recvFormatListResponsePDU(s) { | ||||
|     s.offset = 18; | ||||
|     // const pdu = data.clipPDU().read(s);
 | ||||
|     // console.log('recvFormatListResponsePDU', s);
 | ||||
|     // this.sendFormatDataRequestPDU();
 | ||||
|   } | ||||
| 
 | ||||
| 
 | ||||
|   /** | ||||
|    * Send format data request PDU | ||||
|    */ | ||||
|   sendFormatDataRequestPDU(formartId = 0x0d) { | ||||
|     this.send(new type.Component({ | ||||
|       msgType: new type.UInt16Le(data.ClipPDUMsgType.CB_FORMAT_DATA_REQUEST), | ||||
|       msgFlags: new type.UInt16Le(0x00), | ||||
|       dataLen: new type.UInt32Le(0x04), | ||||
|       requestedFormatId: new type.UInt32Le(formartId), | ||||
|     })); | ||||
|   } | ||||
| 
 | ||||
| 
 | ||||
|   /** | ||||
|    * Receive format data request PDU from server | ||||
|    * @param s {type.Stream} | ||||
|    */ | ||||
|   recvFormatDataRequestPDU(s) { | ||||
|     s.offset = 18; | ||||
|     // const pdu = data.clipPDU().read(s);
 | ||||
|     // console.log('recvFormatDataRequestPDU', s);
 | ||||
|     this.sendFormatDataResponsePDU(); | ||||
|   } | ||||
| 
 | ||||
| 
 | ||||
|   /** | ||||
|    * Send format data reesponse PDU | ||||
|    */ | ||||
|   sendFormatDataResponsePDU() { | ||||
|      | ||||
|     const bufs = Buffer.from(this.content + '\x00' , 'ucs2'); | ||||
| 
 | ||||
|     this.send(new type.Component({ | ||||
|       msgType: new type.UInt16Le(data.ClipPDUMsgType.CB_FORMAT_DATA_RESPONSE), | ||||
|       msgFlags: new type.UInt16Le(0x01), | ||||
|       dataLen: new type.UInt32Le(bufs.length), | ||||
|       requestedFormatData: new type.BinaryString(bufs, { readLength : new type.CallableValue(bufs.length)}) | ||||
|     })); | ||||
| 
 | ||||
|   } | ||||
| 
 | ||||
| 
 | ||||
|   /** | ||||
|    * Receive format data response PDU from server | ||||
|    * @param s {type.Stream} | ||||
|    */ | ||||
|   recvFormatDataResponsePDU(s) { | ||||
|     s.offset = 18; | ||||
|     // const pdu = data.clipPDU().read(s);
 | ||||
|     const str = s.buffer.toString('ucs2', 26, s.buffer.length-2); | ||||
|     // console.log('recvFormatDataResponsePDU', str);
 | ||||
|     this.content = str; | ||||
|     this.emit('clipboard', str) | ||||
|   } | ||||
| 
 | ||||
| 
 | ||||
| // =====================================================================================
 | ||||
|   setClipboardData(content) { | ||||
|     this.content = content; | ||||
|     this.sendFormatListPDU(); | ||||
|   } | ||||
| 
 | ||||
| } | ||||
| 	 | ||||
| 
 | ||||
| module.exports = { | ||||
|   Client | ||||
| } | ||||
| @ -1040,6 +1040,36 @@ function pdu(userId, pduMessage, opt) { | ||||
| 	return new type.Component(self, opt); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| const ClipPDUMsgType = { | ||||
|     CB_MONITOR_READY: 0x0001, | ||||
|     CB_FORMAT_LIST: 0x0002, | ||||
|     CB_FORMAT_LIST_RESPONSE: 0x0003, | ||||
|     CB_FORMAT_DATA_REQUEST: 0x0004, | ||||
|     CB_FORMAT_DATA_RESPONSE: 0x0005, | ||||
|     CB_TEMP_DIRECTORY: 0x0006, | ||||
|     CB_CLIP_CAPS: 0x0007, | ||||
|     CB_FILECONTENTS_REQUEST: 0x0008 | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * @returns {type.Component} | ||||
|  */ | ||||
| function clipPDU() { | ||||
|     const self = { | ||||
|         header: new type.Factory(function (s) { | ||||
|             self.header = new type.Component({ | ||||
|                 msgType: new type.UInt16Le().read(s), | ||||
|                 msgFlags: new type.UInt16Le().read(s), | ||||
|                 dataLen: new type.UInt32Le().read(s) | ||||
|             }) | ||||
|         }) | ||||
| 
 | ||||
|     } | ||||
|     return new type.Component(self); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /** | ||||
|  * @see http://msdn.microsoft.com/en-us/library/dd306368.aspx
 | ||||
|  * @param opt {object} type option | ||||
| @ -1147,5 +1177,7 @@ module.exports = { | ||||
| 		updateDataPDU : updateDataPDU, | ||||
| 		dataPDU : dataPDU, | ||||
| 		fastPathBitmapUpdateDataPDU : fastPathBitmapUpdateDataPDU, | ||||
| 		fastPathUpdatePDU : fastPathUpdatePDU | ||||
|         fastPathUpdatePDU: fastPathUpdatePDU, | ||||
|         clipPDU: clipPDU, | ||||
|         ClipPDUMsgType: ClipPDUMsgType | ||||
| }; | ||||
| @ -21,10 +21,12 @@ var lic = require('./lic'); | ||||
| var sec = require('./sec'); | ||||
| var global = require('./global'); | ||||
| var data = require('./data'); | ||||
| var cliprdr = require('./cliprdr'); | ||||
| 
 | ||||
| module.exports = { | ||||
| 	lic: lic, | ||||
| 	sec: sec, | ||||
| 	global: global, | ||||
| 	data : data | ||||
|     data: data, | ||||
|     cliprdr: cliprdr | ||||
| }; | ||||
|  | ||||
| @ -87,6 +87,7 @@ function RdpClient(config) { | ||||
|     this.x224 = new x224.Client(this.tpkt, config); | ||||
|     this.mcs = new t125.mcs.Client(this.x224); | ||||
|     this.sec = new pdu.sec.Client(this.mcs, this.tpkt); | ||||
|     this.cliprdr = new pdu.cliprdr.Client(this.mcs); | ||||
|     this.global = new pdu.global.Client(this.sec, this.sec); | ||||
| 
 | ||||
|     // config log level
 | ||||
| @ -145,6 +146,9 @@ function RdpClient(config) { | ||||
|             this.mcs.clientCoreData.obj.kbdLayout.value = t125.gcc.KeyboardLayout.US; | ||||
|     } | ||||
| 
 | ||||
|     this.cliprdr.on('clipboard', (content) => { | ||||
|         this.emit('clipboard', content) | ||||
|     }); | ||||
| 
 | ||||
|     //bind all events
 | ||||
|     var self = this; | ||||
| @ -328,6 +332,14 @@ RdpClient.prototype.sendWheelEvent = function (x, y, step, isNegative, isHorizon | ||||
|     this.global.sendInputEvents([event]); | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * Clipboard event | ||||
|  * @param data {String} content for clipboard | ||||
|  */ | ||||
| RdpClient.prototype.setClipboardData = function (content) { | ||||
|     this.cliprdr.setClipboardData(content); | ||||
| } | ||||
| 
 | ||||
| function createClient(config) { | ||||
|     return new RdpClient(config); | ||||
| }; | ||||
|  | ||||
| @ -25,6 +25,7 @@ var error = require('../../core').error; | ||||
| var gcc = require('./gcc'); | ||||
| var per = require('./per'); | ||||
| var asn1 = require('../../asn1'); | ||||
| var cliprdr = require('../pdu/cliprdr'); | ||||
| 
 | ||||
| var Message = { | ||||
| 	MCS_TYPE_CONNECT_INITIAL : 0x65, | ||||
| @ -44,9 +45,32 @@ var DomainMCSPDU = { | ||||
| 
 | ||||
| var Channel = { | ||||
|     MCS_GLOBAL_CHANNEL: 1003, | ||||
|     MCS_USERCHANNEL_BASE : 1001 | ||||
|     MCS_USERCHANNEL_BASE: 1001, | ||||
|     MCS_CLIPRDR_CHANNEL: 1005 | ||||
| }; | ||||
| 
 | ||||
| /** | ||||
|  * Channel Definde | ||||
|  */ | ||||
| const RdpdrChannelDef = new type.Component({ | ||||
|     name: new type.BinaryString(Buffer.from('rdpdr' + '\x00\x00\x00', 'binary'), { readLength: new type.CallableValue(8) }), | ||||
|     options: new type.UInt32Le(0x80800000) | ||||
| }); | ||||
| 
 | ||||
| const RdpsndChannelDef = new type.Component({ | ||||
|     name: new type.BinaryString(Buffer.from('rdpsnd' + '\x00\x00', 'binary'), { readLength: new type.CallableValue(8) }), | ||||
|     options: new type.UInt32Le(0xc0000000) | ||||
| }); | ||||
| 
 | ||||
| const CliprdrChannelDef = new type.Component({ | ||||
|     name: new type.BinaryString(Buffer.from('cliprdr' + '\x00', 'binary'), { readLength: new type.CallableValue(8) }), | ||||
|     // CHANNEL_OPTION_INITIALIZED |
 | ||||
|     // CHANNEL_OPTION_ENCRYPT_RDP |
 | ||||
|     // CHANNEL_OPTION_COMPRESS_RDP |
 | ||||
|     // CHANNEL_OPTION_SHOW_PROTOCOL
 | ||||
|     options: new type.UInt32Le(0xc0a00000) | ||||
| }); | ||||
| 
 | ||||
| /** | ||||
|  * @see http://www.itu.int/rec/T-REC-T.125-199802-I/en page 25
 | ||||
|  * @returns {asn1.univ.Sequence} | ||||
| @ -126,7 +150,10 @@ function MCS(transport, recvOpCode, sendOpCode) { | ||||
| 	this.transport = transport; | ||||
| 	this.recvOpCode = recvOpCode; | ||||
| 	this.sendOpCode = sendOpCode; | ||||
| 	this.channels = [{id : Channel.MCS_GLOBAL_CHANNEL, name : 'global'}]; | ||||
|     this.channels = [ | ||||
|         { id: Channel.MCS_GLOBAL_CHANNEL, name: 'global' }, | ||||
|         { id: Channel.MCS_CLIPRDR_CHANNEL, name: 'cliprdr' } | ||||
|     ]; | ||||
| 	this.channels.find = function(callback) { | ||||
| 		for(var i in this) { | ||||
| 			if(callback(this[i])) return this[i]; | ||||
| @ -208,7 +235,8 @@ function Client(transport) { | ||||
| 	 | ||||
| 	// init gcc information
 | ||||
|     this.clientCoreData = gcc.clientCoreData(); | ||||
| 	this.clientNetworkData = gcc.clientNetworkData(new type.Component([])); | ||||
|     // cliprdr channel
 | ||||
|     this.clientNetworkData = gcc.clientNetworkData(new type.Component([RdpdrChannelDef, CliprdrChannelDef, RdpsndChannelDef])); | ||||
| 	this.clientSecurityData = gcc.clientSecurityData(); | ||||
| 	 | ||||
| 	// must be readed from protocol
 | ||||
| @ -317,7 +345,8 @@ Client.prototype.recvChannelJoinConfirm = function(s) { | ||||
|      | ||||
|     var channelId = per.readInteger16(s); | ||||
| 
 | ||||
|     if ((confirm !== 0) && (channelId === Channel.MCS_GLOBAL_CHANNEL || channelId === this.userId)) { | ||||
|     //if ((confirm !== 0) && (channelId === Channel.MCS_GLOBAL_CHANNEL || channelId === this.userId)) {
 | ||||
|     if ((confirm !== 0) && (channelId === Channel.MCS_CLIPRDR_CHANNEL || channelId === Channel.MCS_GLOBAL_CHANNEL || channelId === this.userId)) { | ||||
|     	throw new error.UnexpectedFatalError('NODE_RDP_PROTOCOL_T125_MCS_SERVER_MUST_CONFIRM_STATIC_CHANNEL'); | ||||
|     } | ||||
|      | ||||
|  | ||||
| @ -121,7 +121,7 @@ | ||||
|       } else if (message.length === undefined) { | ||||
|         return method(message); | ||||
|       } | ||||
|       return crypto.createHash('md4').update(new Buffer(message)).digest('hex'); | ||||
|       return crypto.createHash('md4').update(Buffer.from(message)).digest('hex'); | ||||
|     }; | ||||
|     return nodeMethod; | ||||
|   }; | ||||
|  | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -919,7 +919,8 @@ | ||||
|                                         <div id="terminalCustomUpperRight" style="float:left;margin-right:6px"></div> | ||||
|                                     </div> | ||||
|                                     <div> | ||||
|                                         <span id="connectbutton2span" style="margin-left:3px"><input type="button" id="connectbutton2" cmenu="termConnectButton" value="Connect" style="height:28px" onclick=connectTerminal(event,1) onkeypress="return false" onkeydown="return false" disabled="disabled" /></span> | ||||
|                                         <span id="connectbutton2span" style="margin-left:3px"><input type="button" id="connectbutton2" value="Connect" style="height:28px" onclick=connectTerminal(event,1) onkeypress="return false" onkeydown="return false" disabled="disabled" /></span> | ||||
|                                         <span id="connectbutton2sspan" style="margin-right:4px"><input type="button" id="connectbutton2s" value="SSH Connect" style="height:28px" onclick=connectTerminal(event,3) onkeypress="return false" onkeydown="return false" disabled="disabled" /></span> | ||||
|                                         <span id="disconnectbutton2span" style="margin-left:3px"><input type="button" id="disconnectbutton2" value="Disconnect" style="height:28px" onclick=connectTerminal(event,0) onkeypress="return false" onkeydown="return false" /></span> | ||||
|                                         <span id="termstatus" style="line-height:22px">Disconnected</span><span id="termtitle"></span> | ||||
|                                     </div> | ||||
| @ -951,7 +952,9 @@ | ||||
|                                     </div> | ||||
|                                     <div style="margin-left:2px"> | ||||
|                                         <input id=p13AutoConnect value="AutoConnect" onclick=autoConnectFiles(event) onkeypress="return false" onkeydown="return false" type="button" style="display:none"> | ||||
|                                         <input id=p13Connect value="Connect" onclick=connectFiles(event) onkeypress="return false" onkeydown="return false" type="button"> | ||||
|                                         <input id=p13Connect value="Connect" onclick=connectFiles(event,1) onkeypress="return false" onkeydown="return false" type="button" /> | ||||
|                                         <input id=p13Connects value="SFTP Connect" onclick=connectFiles(event,2) onkeypress="return false" onkeydown="return false" type="button" /> | ||||
|                                         <input id=p13Disconnect value="Disconnect" onclick=connectFiles(event) onkeypress="return false" onkeydown="return false" type="button" /> | ||||
|                                         <span class=textOverGray id=p13Status>Disconnected</span> | ||||
|                                     </div> | ||||
|                                 </td> | ||||
| @ -4683,15 +4686,17 @@ | ||||
| 
 | ||||
|             // Show the right buttons | ||||
|             QV('disconnectbutton2span', (termState == true)); | ||||
|             QV('connectbutton2span', (termState == false) && (currentNode.agent != null) && (currentNode.agent.caps & 2)); | ||||
|             QV('connectbutton2span', (termState == false) && (terminalNode.agent != null) && (terminalNode.agent.caps & 2) && (terminalNode.mtype != 3)); | ||||
|             QV('connectbutton2sspan', (termState == false) && (terminalNode.agent != null) && (terminalNode.agent.caps & 2) && (terminalNode.agent.id != 3) && (terminalNode.agent.id != 4)); | ||||
| 
 | ||||
|             // Enable buttons | ||||
|             var online = ((terminalNode.conn & 1) != 0) || (terminalNode.mtype == 3); // If Agent (1) connected, enable Terminal | ||||
|             QE('connectbutton2', online); | ||||
|             QE('connectbutton2s', online); | ||||
| 
 | ||||
|             // Enable action button if mesh type is not "local devices" | ||||
|             QV('termActionsBtn', terminalNode.mtype != 3); | ||||
|             if (terminalNode.mtype != 3) { | ||||
|             if (((termState == true) && (terminal.contype != 3)) || (terminalNode.agent.id == 3) || (terminalNode.agent.id == 4)) { | ||||
|                 QH('terminalCustomUpperRight', ''); | ||||
|             } else { | ||||
|                 QH('terminalCustomUpperRight', '<a style=cursor:pointer onclick=cmsshportaction(1,event)>' + format("SSH Port {0}", (terminalNode.sshport ? terminalNode.sshport : 22)) + '</a>'); | ||||
| @ -4975,8 +4980,8 @@ | ||||
|                 document.getElementsByClassName('xterm-viewport')[0].style.overflow = 'hidden'; | ||||
| 
 | ||||
|                 // Setup a terminal tunnel to the agent | ||||
|                 terminal = CreateAgentRedirect(meshserver, CreateRemoteTunnel((currentNode.mtype == 3) ? sshTunnelUpdate : tunnelUpdate, termoptions), serverPublicNamePort, authCookie, authRelayCookie, domainUrl); | ||||
|                 if (currentNode.mtype == 3) { terminal.urlname = 'sshterminalrelay.ashx'; } // If this is a SSH session, change the URL to the SSH application relay. | ||||
|                 terminal = CreateAgentRedirect(meshserver, CreateRemoteTunnel((contype == 3) ? sshTunnelUpdate : tunnelUpdate, termoptions), serverPublicNamePort, authCookie, authRelayCookie, domainUrl); | ||||
|                 if (contype == 3) { terminal.urlname = 'sshterminalrelay.ashx'; } // If this is a SSH session, change the URL to the SSH application relay. | ||||
|                 terminal.debugmode = debugmode; | ||||
|                 terminal.m.debugmode = debugmode; | ||||
|                 terminal.options = termoptions; | ||||
| @ -4984,7 +4989,7 @@ | ||||
|                 if (termoptions.requireLogin) { terminal.options.requireLogin = true; } | ||||
|                 terminal.Start(terminalNode._id); | ||||
|                 terminal.onStateChanged = onTerminalStateChange; | ||||
|                 terminal.contype = 1; | ||||
|                 terminal.contype = contype; | ||||
|                 terminal.attemptWebRTC = false; // Never do WebRTC on terminal, because of a race condition we can't do it. | ||||
|                 terminal.onConsoleMessageChange = function () { p12setConsoleMsg(terminal.consoleMessage ? formatAgentConsoleMessage(terminal.consoleMessage, terminal.consoleMessageId, terminal.consoleMessageArgs) : null, terminal.consoleMessageTimeout); } | ||||
|             } else { | ||||
| @ -5028,15 +5033,24 @@ | ||||
|             filesNode = currentNode; | ||||
|             var online = ((filesNode.conn & 1) != 0) || (filesNode.mtype == 3); // If Agent (1) connected, enable Terminal | ||||
|             QE('p13Connect', online); | ||||
|             QE('p13Connects', online); | ||||
|             QV('p13Connect', (files == null) && (filesNode.mtype == 2)); | ||||
|             QV('p13Connects', (files == null) && (filesNode.agent != null) && (filesNode.agent.id != 3) && (filesNode.agent.id != 4)); | ||||
|             QV('p13Disconnect', files != null); | ||||
|             if (((samenode == false) || (online == false)) && files) { files.Stop(); files = null; } | ||||
|             p13setActions(); | ||||
|         } | ||||
| 
 | ||||
|         function onFilesStateChange(xfiles, state) { | ||||
|             setSessionActivity(); | ||||
|             p13Connect.value = (state == 0) ? "Connect" : "Disconnect"; | ||||
|             QV('p13Connect', (state == 0) && (filesNode.mtype == 2)); | ||||
|             QV('p13Connects', (state == 0) && (filesNode.agent != null) && (filesNode.agent.id != 3) && (filesNode.agent.id != 4)); | ||||
|             QV('p13Disconnect', state != 0); | ||||
|             var str = StatusStrs[state]; | ||||
|             if (state == 3) { | ||||
|                 if (files.contype == 2) { str += ", SFTP"; } | ||||
|                 if (files.webRtcActive == true) { str += ", WebRTC"; } | ||||
|             } | ||||
|             Q('p13Status').textContent = str; | ||||
|             switch (state) { | ||||
|                 case 0: | ||||
| @ -5080,12 +5094,13 @@ | ||||
|         var autoConnectFilesTimer = null; | ||||
|         function autoConnectFiles(e) { if (autoConnectFilesTimer == null) { autoConnectFilesTimer = setInterval(connectFiles, 100); } else { clearInterval(autoConnectFilesTimer); autoConnectFilesTimer = null; } } | ||||
| 
 | ||||
|         function connectFiles(e) { | ||||
|         function connectFiles(e, contype) { | ||||
|             p13clearConsoleMsg(); | ||||
|             if (!files) { | ||||
|                 // Setup a mesh agent files | ||||
|                 files = CreateAgentRedirect(meshserver, CreateRemoteFiles(p13gotFiles), serverPublicNamePort, authCookie, authRelayCookie, domainUrl); | ||||
|                 if (filesNode.mtype == 3) { files.urlname = 'sshfilesrelay.ashx'; } // If this is a SSH session, change the URL to the SSH application relay. | ||||
|                 if (contype == 2) { files.urlname = 'sshfilesrelay.ashx'; } // If this is a SSH session, change the URL to the SSH application relay. | ||||
|                 files.contype = contype; | ||||
|                 files.attemptWebRTC = attemptWebRTC; | ||||
|                 files.onStateChanged = onFilesStateChange; | ||||
|                 files.onConsoleMessageChange = function () { | ||||
| @ -5304,7 +5319,8 @@ | ||||
|                 QE('p13CopyButton', advancedFeatures && (cc > 0) && (cc == sfc) && (currentNode.mtype != 3) && ((p13filetreelocation.length > 0) || (winAgent == false))); | ||||
|                 QE('p13PasteButton', advancedFeatures && (currentNode.mtype != 3) && ((p13filetreelocation.length > 0) || (winAgent == false)) && ((p13clipboard != null) && (p13clipboard.length > 0))); | ||||
|             } | ||||
|             if (filesNode.mtype != 3) { | ||||
|             var filesState = ((files != null) && (files.state != 0)); | ||||
|             if (((filesState == true) && (files.contype != 2)) || (filesNode.agent.id == 3) || (filesNode.agent.id == 4)) { | ||||
|                 QH('filesCustomUpperRight', ''); | ||||
|             } else { | ||||
|                 QH('filesCustomUpperRight', '<a style=cursor:pointer onclick=cmsshportaction(1,event)>' + format("SSH Port {0}", (filesNode.sshport ? filesNode.sshport : 22)) + '</a>'); | ||||
|  | ||||
| @ -743,7 +743,7 @@ | ||||
|                                     <div id="terminalCustomUiButtons" style="float:left"></div> | ||||
|                                 </div> | ||||
|                                 <div> | ||||
|                                     <input type="button" id="autoconnectbutton2" value="AutoConnect" onclick=autoConnectTerminal(event) onkeypress="return false" onkeydown="return false" style="display:none" /><span id="connectbutton2span" style="margin-right:4px"><input type="button" id="connectbutton2" cmenu="termConnectButton" value="Connect" onclick=connectTerminal(event,1) onkeypress="return false" onkeydown="return false" disabled="disabled" /></span><span id="connectbutton2hspan" style="margin-right:4px"><input type="button" id="connectbutton2h" value="HW Connect" title="Connect using Intel® AMT hardware KVM" onclick=connectTerminal(event,2) onkeypress="return false" onkeydown="return false" disabled="disabled" /></span><span id="disconnectbutton2span" style="margin-right:4px"><input type="button" id="disconnectbutton2" value="Disconnect" onclick=connectTerminal(event,0) onkeypress="return false" onkeydown="return false" /></span> | ||||
|                                     <input type="button" id="autoconnectbutton2" value="AutoConnect" onclick=autoConnectTerminal(event) onkeypress="return false" onkeydown="return false" style="display:none" /><span id="connectbutton2span" style="margin-right:4px"><input type="button" id="connectbutton2" cmenu="termConnectButton" value="Connect" onclick=connectTerminal(event,1) onkeypress="return false" onkeydown="return false" disabled="disabled" /></span><span id="connectbutton2sspan" style="margin-right:4px"><input type="button" id="connectbutton2s" cmenu=sshPortContextMenu value="SSH Connect" onclick=connectTerminal(event,3) onkeypress="return false" onkeydown="return false" disabled="disabled" /></span><span id="connectbutton2hspan" style="margin-right:4px"><input type="button" id="connectbutton2h" value="HW Connect" title="Connect using Intel® AMT hardware KVM" onclick=connectTerminal(event,2) onkeypress="return false" onkeydown="return false" disabled="disabled" /></span><span id="disconnectbutton2span" style="margin-right:4px"><input type="button" id="disconnectbutton2" value="Disconnect" onclick=connectTerminal(event,0) onkeypress="return false" onkeydown="return false" /></span> | ||||
|                                     <span id="termstatus" style="line-height:22px">Disconnected</span><span id="termtitle"></span> | ||||
|                                 </div> | ||||
|                             </td> | ||||
| @ -801,7 +801,9 @@ | ||||
|                             </div> | ||||
|                             <div> | ||||
|                                 <input id=p13AutoConnect value="AutoConnect" onclick=autoConnectFiles(event) type="button" style="display:none" /> | ||||
|                                 <input id=p13Connect value="Connect" onclick=connectFiles(event) type="button" /> | ||||
|                                 <input id=p13Connect value="Connect" onclick=connectFiles(event,1) type="button" /> | ||||
|                                 <input id=p13Connects value="SFTP Connect" cmenu=sshPortContextMenu onclick=connectFiles(event,2) type="button" /> | ||||
|                                 <input id=p13Disconnect value="Disconnect" onclick=connectFiles(event) type="button" /> | ||||
|                                 <span id=p13Status>Disconnected</span> | ||||
|                             </div> | ||||
|                         </td> | ||||
| @ -2722,7 +2724,6 @@ | ||||
|                         if (message.localport) { url += '&localport=' + message.localport; } | ||||
|                         if (message.ip != null) { url += ('&remoteip=' + message.ip); } | ||||
|                         url += ('&appid=' + message.protocol + '&autoexit=1'); // Protocol: 0 = Custom, 1 = HTTP, 2 = HTTPS, 3 = RDP, 4 = PuTTY, 5 = WinSCP, 6 = MCRDesktop, 7 = MCRFiles | ||||
|                         console.log(url); | ||||
|                         downloadFile(url, ''); | ||||
|                     } else if (message.tag == 'novnc') { | ||||
|                         var vncurl = window.location.origin + domainUrl + 'novnc/vnc.html?ws=wss%3A%2F%2F' + window.location.host + encodeURIComponentEx(domainUrl) + (message.localRelay?'local':'mesh') + 'relay.ashx%3Fauth%3D' + message.cookie + '&show_dot=1' + (urlargs.key?('&key=' + urlargs.key):'') + '&l={{{lang}}}'; | ||||
| @ -7565,7 +7566,7 @@ | ||||
|             if ((navigator.clipboard != null) && (navigator.clipboard.readText != null)) { | ||||
|                 try { | ||||
|                     navigator.clipboard.readText().then(function(text) { | ||||
|                         meshserver.send({ action: 'msg', type: 'setclip', nodeid: currentNode._id, data: text }); | ||||
|                         if (desktop.m.setClipboard) { desktop.m.setClipboard(text); } else { meshserver.send({ action: 'msg', type: 'setclip', nodeid: currentNode._id, data: text }); } | ||||
|                     }).catch(function(err) { console.log(err); }); | ||||
|                 } catch (ex) { console.log(ex); } | ||||
|             } | ||||
| @ -8331,7 +8332,8 @@ | ||||
|             var hwonline = ((currentNode.conn & 6) != 0); // If CIRA (2) or AMT (4) connected, enable hardware terminal | ||||
|             QE('connectbutton1h', hwonline); | ||||
|             QV('deskFocusBtn', (desktop != null) && (desktop.contype == 2) && (deskState != 0) && (desktopsettings.showfocus)); | ||||
|             QE('DeskClip', (deskState == 3) && (desktop.contype != 4)); | ||||
|             QE('DeskClip', deskState == 3); | ||||
|             //QE('DeskClip', (deskState == 3) && (desktop.contype != 4)); | ||||
|             QV('DeskClip', (inputAllowed) && (currentNode.agent) && ((features2 & 0x1800) != 0x1800) && (currentNode.agent.id != 11) && (currentNode.agent.id != 16) && ((desktop == null) || (desktop.contype != 2)) && ((desktopsettings.autoclipboard != true) || (navigator.clipboard == null) || (navigator.clipboard.readText == null))); // Clipboard not supported on macOS | ||||
|             QE('DeskESC', (deskState == 3) && (desktop.contype != 4)); | ||||
|             QV('DeskESC', browserfullscreen && inputAllowed); | ||||
| @ -8736,7 +8738,7 @@ | ||||
|                     try { | ||||
|                         navigator.clipboard.readText().then(function(text) { | ||||
|                             if ((text != null) && (deskLastClipboardSent != text)) { | ||||
|                                 meshserver.send({ action: 'msg', type: 'setclip', nodeid: currentNode._id, data: text }); | ||||
|                                 if (desktop.m.setClipboard) { desktop.m.setClipboard(text); } else { meshserver.send({ action: 'msg', type: 'setclip', nodeid: currentNode._id, data: text }); } | ||||
|                                 deskLastClipboardSent = text; | ||||
|                             } | ||||
|                         }).catch(function(err) { }); | ||||
| @ -9322,9 +9324,13 @@ | ||||
| 
 | ||||
|         function showDeskClipSet() { | ||||
|             if (desktop == null || desktop.State != 3) return; | ||||
|             if (desktop.m.setClipboard) { | ||||
|                 desktop.m.setClipboard(Q('d2clipText').value); | ||||
|             } else { | ||||
|                 meshserver.send({ action: 'msg', type: 'setclip', nodeid: currentNode._id, data: Q('d2clipText').value }); | ||||
|                 QV('linuxClipWarn', currentNode && currentNode.agent && (currentNode.agent.id > 4) && (currentNode.agent.id != 21) && (currentNode.agent.id != 22) && (currentNode.agent.id != 34)); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // Send CTRL-ALT-DEL | ||||
|         function sendCAD() { | ||||
| @ -9557,7 +9563,8 @@ | ||||
| 
 | ||||
|             // Show the right buttons | ||||
|             QV('disconnectbutton2span', (termState == true)); | ||||
|             QV('connectbutton2span', (termState == false) && (terminalNode.agent != null) && (terminalNode.agent.caps & 2)); | ||||
|             QV('connectbutton2span', (termState == false) && (terminalNode.agent != null) && (terminalNode.agent.caps & 2) && (terminalNode.mtype != 3)); | ||||
|             QV('connectbutton2sspan', (termState == false) && (terminalNode.agent != null) && (terminalNode.agent.caps & 2) && (terminalNode.agent.id != 3) && (terminalNode.agent.id != 4)); | ||||
|             if (terminalNode.mtype == 1) { | ||||
|                 QV('connectbutton2hspan', (termState == false) && (terminalNode.intelamt != null) && (terminalNode.intelamt.state == 2)); | ||||
|                 QV('terminalSizeDropDown', (termState == false) && (terminalNode.intelamt != null) && (terminalNode.intelamt.state == 2)); | ||||
| @ -9568,7 +9575,7 @@ | ||||
| 
 | ||||
|             // Enable action button if mesh type is not "local devices" | ||||
|             QV('termActionsBtn', terminalNode.mtype != 3); | ||||
|             if (terminalNode.mtype != 3) { | ||||
|             if (((termState == true) && (terminal.contype != 3)) || (terminalNode.agent.id == 3) || (terminalNode.agent.id == 4)) { | ||||
|                 QH('terminalCustomUpperRight', ''); | ||||
|             } else { | ||||
|                 QH('terminalCustomUpperRight', '<a style=cursor:pointer onclick=cmsshportaction(1,event)>' + format("SSH Port {0}", (terminalNode.sshport?terminalNode.sshport:22)) + '</a>'); | ||||
| @ -9577,6 +9584,7 @@ | ||||
|             // Enable buttons | ||||
|             var online = ((terminalNode.conn & 1) != 0) || (terminalNode.mtype == 3); // If Agent (1) connected, enable Terminal | ||||
|             QE('connectbutton2', online); | ||||
|             QE('connectbutton2s', online); | ||||
|             var hwonline = ((terminalNode.conn & 6) != 0); // If CIRA (2) or AMT (4) connected, enable hardware terminal | ||||
|             QE('connectbutton2h', hwonline); | ||||
| 
 | ||||
| @ -9612,7 +9620,10 @@ | ||||
|             var xstate = state; | ||||
|             if ((xstate == 3) && (xterminal.contype == 2)) { xstate++; } | ||||
|             var str = StatusStrs[xstate]; | ||||
|             if (xstate == 3) { | ||||
|                 if (terminal.contype == 3) { str += ", SSH"; } | ||||
|                 if (terminal.webRtcActive == true) { str += ", WebRTC"; } | ||||
|             } | ||||
|             QH('termstatus', str); | ||||
|             switch (state) { | ||||
|                 case 0: | ||||
| @ -9777,6 +9788,7 @@ | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // contype: 1 = Agent, 2 = AMT, 3 = SSH | ||||
|         function connectTerminal(e, contype, options) { | ||||
|             p12clearConsoleMsg(); | ||||
|             if (!terminal) { | ||||
| @ -9853,8 +9865,8 @@ | ||||
|                         }); | ||||
| 
 | ||||
|                         // Setup a terminal tunnel to the agent | ||||
|                         terminal = CreateAgentRedirect(meshserver, CreateRemoteTunnel((currentNode.mtype == 3)? sshTunnelUpdate : tunnelUpdate, termoptions), serverPublicNamePort, authCookie, authRelayCookie, domainUrl); | ||||
|                         if (currentNode.mtype == 3) { terminal.urlname = 'sshterminalrelay.ashx'; } // If this is a SSH session, change the URL to the SSH application relay. | ||||
|                         terminal = CreateAgentRedirect(meshserver, CreateRemoteTunnel((contype == 3)? sshTunnelUpdate : tunnelUpdate, termoptions), serverPublicNamePort, authCookie, authRelayCookie, domainUrl); | ||||
|                         if (contype == 3) { terminal.urlname = 'sshterminalrelay.ashx'; } // If this is a SSH session, change the URL to the SSH application relay. | ||||
|                         terminal.debugmode = debugmode; | ||||
|                         terminal.m.debugmode = debugmode; | ||||
|                         terminal.options = termoptions; | ||||
| @ -9862,7 +9874,7 @@ | ||||
|                         if (termoptions.requireLogin) { terminal.options.requireLogin = true; } | ||||
|                         terminal.Start(terminalNode._id); | ||||
|                         terminal.onStateChanged = onTerminalStateChange; | ||||
|                         terminal.contype = 1; | ||||
|                         terminal.contype = contype; | ||||
|                         terminal.attemptWebRTC = false; // Never do WebRTC on terminal, because of a race condition we can't do it. | ||||
|                         terminal.onConsoleMessageChange = function () { p12setConsoleMsg(terminal.consoleMessage ? formatAgentConsoleMessage(terminal.consoleMessage, terminal.consoleMessageId, terminal.consoleMessageArgs) : null, terminal.consoleMessageTimeout); } | ||||
|                     } else { | ||||
| @ -9880,7 +9892,7 @@ | ||||
|                         terminal.onStateChanged = onTerminalStateChange; | ||||
|                         terminal.onConsoleMessageChange = function () { p12setConsoleMsg(terminal.consoleMessage ? formatAgentConsoleMessage(terminal.consoleMessage, terminal.consoleMessageId, terminal.consoleMessageArgs) : null, terminal.consoleMessageTimeout); } | ||||
|                         terminal.Start(terminalNode._id); | ||||
|                         terminal.contype = 1; | ||||
|                         terminal.contype = contype; | ||||
|                         terminal.m.terminalEmulation = 0; | ||||
|                         terminal.m.fxEmulation = 0; | ||||
|                         Q('id_ttypebutton').value = terminalEmulations[0]; | ||||
| @ -9980,14 +9992,23 @@ | ||||
|             filesNode = currentNode; | ||||
|             var online = ((filesNode.conn & 1) != 0) || (filesNode.mtype == 3); // If Agent (1) connected, enable Terminal | ||||
|             QE('p13Connect', online); | ||||
|             QE('p13Connects', online); | ||||
|             QV('p13Connect', (files == null) && (filesNode.mtype == 2)); | ||||
|             QV('p13Connects', (files == null) && (filesNode.agent != null) && (filesNode.agent.id != 3) && (filesNode.agent.id != 4)); | ||||
|             QV('p13Disconnect', files != null); | ||||
|             if (((samenode == false) || (online == false)) && files) { files.Stop(); files = null; } | ||||
|             p13setActions(); | ||||
|         } | ||||
| 
 | ||||
|         function onFilesStateChange(xfiles, state) { | ||||
|             p13Connect.value = (state == 0) ? "Connect" : "Disconnect"; | ||||
|             QV('p13Connect', (state == 0) && (files == null) && (filesNode.mtype == 2)); | ||||
|             QV('p13Connects', (state == 0) && (files == null) && (filesNode.agent != null) && (filesNode.agent.id != 3) && (filesNode.agent.id != 4)); | ||||
|             QV('p13Disconnect', state != 0); | ||||
|             var str = StatusStrs[state]; | ||||
|             if (state == 3) { | ||||
|                 if (files.contype == 2) { str += ", SFTP"; } | ||||
|                 if (files.webRtcActive == true) { str += ", WebRTC"; } | ||||
|             } | ||||
|             Q('p13Status').textContent = str; | ||||
|             switch (state) { | ||||
|                 case 0: | ||||
| @ -10033,12 +10054,14 @@ | ||||
|         var autoConnectFilesTimer = null; | ||||
|         function autoConnectFiles(e) { if (autoConnectFilesTimer == null) { autoConnectFilesTimer = setInterval(connectFiles, 100); } else { clearInterval(autoConnectFilesTimer); autoConnectFilesTimer = null; } } | ||||
| 
 | ||||
|         function connectFiles(e) { | ||||
|         // 1 = Agent, 2 = SFTP | ||||
|         function connectFiles(e, contype) { | ||||
|             p13clearConsoleMsg(); | ||||
|             if (!files) { | ||||
|                 // Setup a mesh agent files | ||||
|                 files = CreateAgentRedirect(meshserver, CreateRemoteFiles(p13gotFiles), serverPublicNamePort, authCookie, authRelayCookie, domainUrl); | ||||
|                 if (filesNode.mtype == 3) { files.urlname = 'sshfilesrelay.ashx'; } // If this is a SSH session, change the URL to the SSH application relay. | ||||
|                 if (contype == 2) { files.urlname = 'sshfilesrelay.ashx'; } // If this is a SSH session, change the URL to the SSH application relay. | ||||
|                 files.contype = contype; | ||||
|                 files.attemptWebRTC = attemptWebRTC; | ||||
|                 files.onStateChanged = onFilesStateChange; | ||||
|                 files.onConsoleMessageChange = function () { | ||||
| @ -10340,7 +10363,8 @@ | ||||
|                 QE('p13ZipButton', advancedFeatures && (cc > 0) && ((p13filetreelocation.length > 0) || (winAgent == false))); | ||||
|                 QE('p13PasteButton', advancedFeatures && ((p13filetreelocation.length > 0) || (winAgent == false)) && ((p13clipboard != null) && (p13clipboard.length > 0))); | ||||
|             } | ||||
|             if (filesNode.mtype != 3) { | ||||
|             var filesState = ((files != null) && (files.state != 0)); | ||||
|             if (((filesState == true) && (files.contype != 2)) || (filesNode.agent.id == 3) || (filesNode.agent.id == 4)) { | ||||
|                 QH('filesCustomUpperRight', ''); | ||||
|             } else { | ||||
|                 QH('filesCustomUpperRight', '<a style=cursor:pointer onclick=cmsshportaction(1,event)>' + format("SSH Port {0}", (filesNode.sshport?filesNode.sshport:22)) + '</a>'); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user