1
0
Fork 0
mirror of https://github.com/Ylianst/MeshCentral.git synced 2025-02-12 11:01:52 +00:00

Added RDP alternate shell / working dir, #3943

This commit is contained in:
Ylian Saint-Hilaire 2022-05-08 11:46:07 -07:00
parent 2023a2f929
commit 6797f8199c
4 changed files with 243 additions and 228 deletions

View file

@ -179,7 +179,11 @@ module.exports.CreateMstscRelay = function (parent, db, ws, req, args, domain) {
screen: obj.infos.screen, screen: obj.infos.screen,
locale: obj.infos.locale, locale: obj.infos.locale,
}; };
if (obj.infos.options && (obj.infos.options.flags != null)) { args.perfFlags = obj.infos.options.flags; delete obj.infos.options.flags; } if (obj.infos.options) {
if (obj.infos.options.flags != null) { args.perfFlags = obj.infos.options.flags; delete obj.infos.options.flags; }
if ((obj.infos.options.workingDir != null) && (obj.infos.options.workingDir != '')) { args.workingDir = obj.infos.options.workingDir; }
if ((obj.infos.options.alternateShell != null) && (obj.infos.options.alternateShell != '')) { args.alternateShell = obj.infos.options.alternateShell; }
}
rdpClient = require('./rdp').createClient(args).on('connect', function () { rdpClient = require('./rdp').createClient(args).on('connect', function () {
send(['rdp-connect']); send(['rdp-connect']);
if ((typeof obj.infos.options == 'object') && (obj.infos.options.savepass == true)) { saveRdpCredentials(); } // Save the credentials if needed if ((typeof obj.infos.options == 'object') && (obj.infos.options.savepass == true)) { saveRdpCredentials(); } // Save the credentials if needed

View file

@ -27,7 +27,7 @@ var CreateRDPDesktop = function (canvasid) {
obj.nodeid = nodeid; obj.nodeid = nodeid;
obj.port = port; obj.port = port;
obj.credentials = credentials; obj.credentials = credentials;
var options = { savepass: credentials.savecred, useServerCreds: credentials.servercred, width: credentials.width, height: credentials.height, flags: credentials.flags }; var options = { savepass: credentials.savecred, useServerCreds: credentials.servercred, width: credentials.width, height: credentials.height, flags: credentials.flags, workingDir: credentials.workdir, alternateShell: credentials.altshell };
if (credentials.width && credentials.height) { if (credentials.width && credentials.height) {
options.width = obj.ScreenWidth = obj.width = credentials.width; options.width = obj.ScreenWidth = obj.width = credentials.width;
options.height = obj.ScreenHeight = obj.height = credentials.height; options.height = obj.ScreenHeight = obj.height = credentials.height;

View file

@ -33,81 +33,81 @@ var pdu = require('./pdu');
* decompress bitmap from RLE algorithm * decompress bitmap from RLE algorithm
* @param bitmap {object} bitmap object of bitmap event of node-rdpjs * @param bitmap {object} bitmap object of bitmap event of node-rdpjs
*/ */
function decompress (bitmap) { function decompress(bitmap) {
var fName = null; var fName = null;
switch (bitmap.bitsPerPixel.value) { switch (bitmap.bitsPerPixel.value) {
case 15: case 15:
fName = 'bitmap_decompress_15'; fName = 'bitmap_decompress_15';
break; break;
case 16: case 16:
fName = 'bitmap_decompress_16'; fName = 'bitmap_decompress_16';
break; break;
case 24: case 24:
fName = 'bitmap_decompress_24'; fName = 'bitmap_decompress_24';
break; break;
case 32: case 32:
fName = 'bitmap_decompress_32'; fName = 'bitmap_decompress_32';
break; break;
default: default:
throw 'invalid bitmap data format'; throw 'invalid bitmap data format';
} }
var input = new Uint8Array(bitmap.bitmapDataStream.value);
var inputPtr = rle._malloc(input.length);
var inputHeap = new Uint8Array(rle.HEAPU8.buffer, inputPtr, input.length);
inputHeap.set(input);
var ouputSize = bitmap.width.value * bitmap.height.value * 4;
var outputPtr = rle._malloc(ouputSize);
var outputHeap = new Uint8Array(rle.HEAPU8.buffer, outputPtr, ouputSize); var input = new Uint8Array(bitmap.bitmapDataStream.value);
var inputPtr = rle._malloc(input.length);
var inputHeap = new Uint8Array(rle.HEAPU8.buffer, inputPtr, input.length);
inputHeap.set(input);
var res = rle.ccall(fName, var ouputSize = bitmap.width.value * bitmap.height.value * 4;
'number', var outputPtr = rle._malloc(ouputSize);
['number', 'number', 'number', 'number', 'number', 'number', 'number', 'number'],
[outputHeap.byteOffset, bitmap.width.value, bitmap.height.value, bitmap.width.value, bitmap.height.value, inputHeap.byteOffset, input.length] var outputHeap = new Uint8Array(rle.HEAPU8.buffer, outputPtr, ouputSize);
);
var res = rle.ccall(fName,
var output = new Uint8ClampedArray(outputHeap.buffer, outputHeap.byteOffset, ouputSize); 'number',
['number', 'number', 'number', 'number', 'number', 'number', 'number', 'number'],
rle._free(inputPtr); [outputHeap.byteOffset, bitmap.width.value, bitmap.height.value, bitmap.width.value, bitmap.height.value, inputHeap.byteOffset, input.length]
rle._free(outputPtr); );
return output; var output = new Uint8ClampedArray(outputHeap.buffer, outputHeap.byteOffset, ouputSize);
rle._free(inputPtr);
rle._free(outputPtr);
return output;
} }
/** /**
* Main RDP module * Main RDP module
*/ */
function RdpClient(config) { function RdpClient(config) {
config = config || {}; config = config || {};
this.connected = false; this.connected = false;
this.bufferLayer = new layer.BufferLayer(new net.Socket()); this.bufferLayer = new layer.BufferLayer(new net.Socket());
this.tpkt = new TPKT(this.bufferLayer); this.tpkt = new TPKT(this.bufferLayer);
this.x224 = new x224.Client(this.tpkt, config); this.x224 = new x224.Client(this.tpkt, config);
this.mcs = new t125.mcs.Client(this.x224); this.mcs = new t125.mcs.Client(this.x224);
this.sec = new pdu.sec.Client(this.mcs, this.tpkt); this.sec = new pdu.sec.Client(this.mcs, this.tpkt);
this.global = new pdu.global.Client(this.sec, this.sec); this.global = new pdu.global.Client(this.sec, this.sec);
// config log level // config log level
log.level = log.Levels[config.logLevel || 'INFO'] || log.Levels.INFO; log.level = log.Levels[config.logLevel || 'INFO'] || log.Levels.INFO;
// credentials // credentials
if (config.domain) { if (config.domain) {
this.sec.infos.obj.domain.value = Buffer.from(config.domain + '\x00', 'ucs2'); this.sec.infos.obj.domain.value = Buffer.from(config.domain + '\x00', 'ucs2');
} }
if (config.userName) { if (config.userName) {
this.sec.infos.obj.userName.value = Buffer.from(config.userName + '\x00', 'ucs2'); this.sec.infos.obj.userName.value = Buffer.from(config.userName + '\x00', 'ucs2');
} }
if (config.password) { if (config.password) {
this.sec.infos.obj.password.value = Buffer.from(config.password + '\x00', 'ucs2'); this.sec.infos.obj.password.value = Buffer.from(config.password + '\x00', 'ucs2');
} }
if(config.workingDir) { if (config.workingDir) {
this.sec.infos.obj.workingDir.value = Buffer.from(config.workingDir + '\x00', 'ucs2'); this.sec.infos.obj.workingDir.value = Buffer.from(config.workingDir + '\x00', 'ucs2');
} }
if(config.alternateShell) { if (config.alternateShell) {
this.sec.infos.obj.alternateShell.value = Buffer.from(config.alternateShell + '\x00', 'ucs2'); this.sec.infos.obj.alternateShell.value = Buffer.from(config.alternateShell + '\x00', 'ucs2');
} }
if (config.perfFlags != null) { if (config.perfFlags != null) {
this.sec.infos.obj.extendedInfo.obj.performanceFlags.value = config.perfFlags; this.sec.infos.obj.extendedInfo.obj.performanceFlags.value = config.perfFlags;
@ -121,72 +121,72 @@ function RdpClient(config) {
| pdu.sec.PerfFlag.PERF_DISABLE_FULLWINDOWDRAG; | pdu.sec.PerfFlag.PERF_DISABLE_FULLWINDOWDRAG;
} }
} }
if (config.autoLogin) { if (config.autoLogin) {
this.sec.infos.obj.flag.value |= pdu.sec.InfoFlag.INFO_AUTOLOGON; this.sec.infos.obj.flag.value |= pdu.sec.InfoFlag.INFO_AUTOLOGON;
} }
if (config.screen && config.screen.width && config.screen.height) { if (config.screen && config.screen.width && config.screen.height) {
this.mcs.clientCoreData.obj.desktopWidth.value = config.screen.width; this.mcs.clientCoreData.obj.desktopWidth.value = config.screen.width;
this.mcs.clientCoreData.obj.desktopHeight.value = config.screen.height; this.mcs.clientCoreData.obj.desktopHeight.value = config.screen.height;
} }
log.debug('screen ' + this.mcs.clientCoreData.obj.desktopWidth.value + 'x' + this.mcs.clientCoreData.obj.desktopHeight.value); log.debug('screen ' + this.mcs.clientCoreData.obj.desktopWidth.value + 'x' + this.mcs.clientCoreData.obj.desktopHeight.value);
// config keyboard layout // config keyboard layout
switch (config.locale) { switch (config.locale) {
case 'fr': case 'fr':
log.debug('french keyboard layout'); log.debug('french keyboard layout');
this.mcs.clientCoreData.obj.kbdLayout.value = t125.gcc.KeyboardLayout.FRENCH; this.mcs.clientCoreData.obj.kbdLayout.value = t125.gcc.KeyboardLayout.FRENCH;
break; break;
case 'en': case 'en':
default: default:
log.debug('english keyboard layout'); log.debug('english keyboard layout');
this.mcs.clientCoreData.obj.kbdLayout.value = t125.gcc.KeyboardLayout.US; this.mcs.clientCoreData.obj.kbdLayout.value = t125.gcc.KeyboardLayout.US;
} }
//bind all events //bind all events
var self = this; var self = this;
this.global.on('connect', function () { this.global.on('connect', function () {
self.connected = true; self.connected = true;
self.emit('connect'); self.emit('connect');
}).on('session', function () { }).on('session', function () {
self.emit('session'); self.emit('session');
}).on('close', function () { }).on('close', function () {
self.connected = false; self.connected = false;
self.emit('close'); self.emit('close');
}).on('bitmap', function (bitmaps) { }).on('bitmap', function (bitmaps) {
for(var bitmap in bitmaps) { for (var bitmap in bitmaps) {
var bitmapData = bitmaps[bitmap].obj.bitmapDataStream.value; var bitmapData = bitmaps[bitmap].obj.bitmapDataStream.value;
var isCompress = bitmaps[bitmap].obj.flags.value & pdu.data.BitmapFlag.BITMAP_COMPRESSION; var isCompress = bitmaps[bitmap].obj.flags.value & pdu.data.BitmapFlag.BITMAP_COMPRESSION;
if (isCompress && config.decompress) { if (isCompress && config.decompress) {
bitmapData = decompress(bitmaps[bitmap].obj); bitmapData = decompress(bitmaps[bitmap].obj);
isCompress = false; isCompress = false;
} }
self.emit('bitmap', { self.emit('bitmap', {
destTop : bitmaps[bitmap].obj.destTop.value, destTop: bitmaps[bitmap].obj.destTop.value,
destLeft : bitmaps[bitmap].obj.destLeft.value, destLeft: bitmaps[bitmap].obj.destLeft.value,
destBottom : bitmaps[bitmap].obj.destBottom.value, destBottom: bitmaps[bitmap].obj.destBottom.value,
destRight : bitmaps[bitmap].obj.destRight.value, destRight: bitmaps[bitmap].obj.destRight.value,
width : bitmaps[bitmap].obj.width.value, width: bitmaps[bitmap].obj.width.value,
height : bitmaps[bitmap].obj.height.value, height: bitmaps[bitmap].obj.height.value,
bitsPerPixel : bitmaps[bitmap].obj.bitsPerPixel.value, bitsPerPixel: bitmaps[bitmap].obj.bitsPerPixel.value,
isCompress : isCompress, isCompress: isCompress,
data : bitmapData data: bitmapData
}); });
} }
}).on('error', function (err) { }).on('error', function (err) {
log.warn(err.code + '(' + err.message + ')\n' + err.stack); log.warn(err.code + '(' + err.message + ')\n' + err.stack);
if (err instanceof error.FatalError) { if (err instanceof error.FatalError) {
throw err; throw err;
} }
else { else {
self.emit('error', err); self.emit('error', err);
} }
}); });
} }
inherits(RdpClient, events.EventEmitter); inherits(RdpClient, events.EventEmitter);
@ -197,24 +197,24 @@ inherits(RdpClient, events.EventEmitter);
* @param port {integer} destination port * @param port {integer} destination port
*/ */
RdpClient.prototype.connect = function (host, port) { RdpClient.prototype.connect = function (host, port) {
log.debug('connect to ' + host + ':' + port); log.debug('connect to ' + host + ':' + port);
var self = this; var self = this;
this.bufferLayer.socket.connect(port, host, function () { this.bufferLayer.socket.connect(port, host, function () {
// in client mode connection start from x224 layer // in client mode connection start from x224 layer
self.x224.connect(); self.x224.connect();
}); });
return this; return this;
}; };
/** /**
* Close RDP client * Close RDP client
*/ */
RdpClient.prototype.close = function () { RdpClient.prototype.close = function () {
if(this.connected) { if (this.connected) {
this.global.close(); this.global.close();
} }
this.connected = false; this.connected = false;
return this; return this;
}; };
/** /**
@ -225,31 +225,31 @@ RdpClient.prototype.close = function () {
* @param isPressed {boolean} state of button * @param isPressed {boolean} state of button
*/ */
RdpClient.prototype.sendPointerEvent = function (x, y, button, isPressed) { RdpClient.prototype.sendPointerEvent = function (x, y, button, isPressed) {
if (!this.connected) if (!this.connected)
return; return;
var event = pdu.data.pointerEvent(); var event = pdu.data.pointerEvent();
if (isPressed) { if (isPressed) {
event.obj.pointerFlags.value |= pdu.data.PointerFlag.PTRFLAGS_DOWN; event.obj.pointerFlags.value |= pdu.data.PointerFlag.PTRFLAGS_DOWN;
} }
switch(button) { switch (button) {
case 1: case 1:
event.obj.pointerFlags.value |= pdu.data.PointerFlag.PTRFLAGS_BUTTON1; event.obj.pointerFlags.value |= pdu.data.PointerFlag.PTRFLAGS_BUTTON1;
break; break;
case 2: case 2:
event.obj.pointerFlags.value |= pdu.data.PointerFlag.PTRFLAGS_BUTTON2; event.obj.pointerFlags.value |= pdu.data.PointerFlag.PTRFLAGS_BUTTON2;
break; break;
case 3: case 3:
event.obj.pointerFlags.value |= pdu.data.PointerFlag.PTRFLAGS_BUTTON3 event.obj.pointerFlags.value |= pdu.data.PointerFlag.PTRFLAGS_BUTTON3
break; break;
default: default:
event.obj.pointerFlags.value |= pdu.data.PointerFlag.PTRFLAGS_MOVE; event.obj.pointerFlags.value |= pdu.data.PointerFlag.PTRFLAGS_MOVE;
} }
event.obj.xPos.value = x; event.obj.xPos.value = x;
event.obj.yPos.value = y; event.obj.yPos.value = y;
this.global.sendInputEvents([event]); this.global.sendInputEvents([event]);
}; };
@ -260,20 +260,20 @@ RdpClient.prototype.sendPointerEvent = function (x, y, button, isPressed) {
* @param extended {boolenan} extended keys * @param extended {boolenan} extended keys
*/ */
RdpClient.prototype.sendKeyEventScancode = function (code, isPressed, extended) { RdpClient.prototype.sendKeyEventScancode = function (code, isPressed, extended) {
if (!this.connected) if (!this.connected)
return; return;
extended = extended || false; extended = extended || false;
var event = pdu.data.scancodeKeyEvent(); var event = pdu.data.scancodeKeyEvent();
event.obj.keyCode.value = code; event.obj.keyCode.value = code;
if (!isPressed) { if (!isPressed) {
event.obj.keyboardFlags.value |= pdu.data.KeyboardFlag.KBDFLAGS_RELEASE; event.obj.keyboardFlags.value |= pdu.data.KeyboardFlag.KBDFLAGS_RELEASE;
}
if (extended) {
event.obj.keyboardFlags.value |= pdu.data.KeyboardFlag.KBDFLAGS_EXTENDED;
} }
if (extended) {
event.obj.keyboardFlags.value |= pdu.data.KeyboardFlag.KBDFLAGS_EXTENDED;
}
this.global.sendInputEvents([event]); this.global.sendInputEvents([event]);
}; };
@ -283,16 +283,16 @@ RdpClient.prototype.sendKeyEventScancode = function (code, isPressed, extended)
* @param isPressed {boolean} * @param isPressed {boolean}
*/ */
RdpClient.prototype.sendKeyEventUnicode = function (code, isPressed) { RdpClient.prototype.sendKeyEventUnicode = function (code, isPressed) {
if (!this.connected) if (!this.connected)
return; return;
var event = pdu.data.unicodeKeyEvent(); var event = pdu.data.unicodeKeyEvent();
event.obj.unicode.value = code; event.obj.unicode.value = code;
if (!isPressed) { if (!isPressed) {
event.obj.keyboardFlags.value |= pdu.data.KeyboardFlag.KBDFLAGS_RELEASE; event.obj.keyboardFlags.value |= pdu.data.KeyboardFlag.KBDFLAGS_RELEASE;
} }
this.global.sendInputEvents([event]); this.global.sendInputEvents([event]);
} }
/** /**
@ -304,32 +304,32 @@ RdpClient.prototype.sendKeyEventUnicode = function (code, isPressed) {
* @param isHorizontal {boolean} * @param isHorizontal {boolean}
*/ */
RdpClient.prototype.sendWheelEvent = function (x, y, step, isNegative, isHorizontal) { RdpClient.prototype.sendWheelEvent = function (x, y, step, isNegative, isHorizontal) {
if (!this.connected) if (!this.connected)
return; return;
var event = pdu.data.pointerEvent(); var event = pdu.data.pointerEvent();
if (isHorizontal) { if (isHorizontal) {
event.obj.pointerFlags.value |= pdu.data.PointerFlag.PTRFLAGS_HWHEEL; event.obj.pointerFlags.value |= pdu.data.PointerFlag.PTRFLAGS_HWHEEL;
}
else {
event.obj.pointerFlags.value |= pdu.data.PointerFlag.PTRFLAGS_WHEEL;
} }
else {
event.obj.pointerFlags.value |= pdu.data.PointerFlag.PTRFLAGS_WHEEL;
if (isNegative) { }
if (isNegative) {
event.obj.pointerFlags.value |= pdu.data.PointerFlag.PTRFLAGS_WHEEL_NEGATIVE; event.obj.pointerFlags.value |= pdu.data.PointerFlag.PTRFLAGS_WHEEL_NEGATIVE;
} }
event.obj.pointerFlags.value |= (step & pdu.data.PointerFlag.WheelRotationMask) event.obj.pointerFlags.value |= (step & pdu.data.PointerFlag.WheelRotationMask)
event.obj.xPos.value = x; event.obj.xPos.value = x;
event.obj.yPos.value = y; event.obj.yPos.value = y;
this.global.sendInputEvents([event]); this.global.sendInputEvents([event]);
} }
function createClient(config) { function createClient(config) {
return new RdpClient(config); return new RdpClient(config);
}; };
/** /**
@ -338,28 +338,28 @@ function createClient(config) {
* @param socket {net.Socket} * @param socket {net.Socket}
*/ */
function RdpServer(config, socket) { function RdpServer(config, socket) {
if (!(config.key && config.cert)) { if (!(config.key && config.cert)) {
throw new error.FatalError('NODE_RDP_PROTOCOL_RDP_SERVER_CONFIG_MISSING', 'missing cryptographic tools') throw new error.FatalError('NODE_RDP_PROTOCOL_RDP_SERVER_CONFIG_MISSING', 'missing cryptographic tools')
} }
this.connected = false; this.connected = false;
this.bufferLayer = new layer.BufferLayer(socket); this.bufferLayer = new layer.BufferLayer(socket);
this.tpkt = new TPKT(this.bufferLayer); this.tpkt = new TPKT(this.bufferLayer);
this.x224 = new x224.Server(this.tpkt, config.key, config.cert); this.x224 = new x224.Server(this.tpkt, config.key, config.cert);
this.mcs = new t125.mcs.Server(this.x224); this.mcs = new t125.mcs.Server(this.x224);
}; };
inherits(RdpServer, events.EventEmitter); inherits(RdpServer, events.EventEmitter);
function createServer (config, next) { function createServer(config, next) {
return net.createServer(function (socket) { return net.createServer(function (socket) {
next(new RdpServer(config, socket)); next(new RdpServer(config, socket));
}); });
}; };
/** /**
* Module exports * Module exports
*/ */
module.exports = { module.exports = {
createClient : createClient, createClient: createClient,
createServer : createServer createServer: createServer
}; };

View file

@ -1379,6 +1379,10 @@
<input id="idx_dlgCancelButton" type="button" value="Cancel" style="" onclick="dialogclose(0)" /> <input id="idx_dlgCancelButton" type="button" value="Cancel" style="" onclick="dialogclose(0)" />
<input id="idx_dlgOkButton" type="button" value="OK" style="" onclick="dialogclose(1)" /> <input id="idx_dlgOkButton" type="button" value="OK" style="" onclick="dialogclose(1)" />
<div><input id="idx_dlgDeleteButton" type="button" value="Delete" style="display:none" onclick="dialogclose(2)" /></div> <div><input id="idx_dlgDeleteButton" type="button" value="Delete" style="display:none" onclick="dialogclose(2)" /></div>
<div id="idx_dlgMoreButtons">
<a href=# id=morexxx1 style=cursor:pointer;color:gray;text-decoration:none title="Toggle advanced options" onclick=MoreToggle(true)>&#x25BC;</a>
<a href=# id=morexxx2 style=cursor:pointer;color:gray;text-decoration:none title="Toggle advanced options" onclick=MoreToggle(false)>&#x25B2;</a>
</div>
</div> </div>
</div> </div>
<iframe name="fileUploadFrame" style="display:none"></iframe> <iframe name="fileUploadFrame" style="display:none"></iframe>
@ -8552,7 +8556,11 @@
x += addHtmlValue("Username", '<input type=text id=d2user style=width:230px onKeyUp=askRdpCredentialsValidate() maxlength=128 />'); x += addHtmlValue("Username", '<input type=text id=d2user style=width:230px onKeyUp=askRdpCredentialsValidate() maxlength=128 />');
x += addHtmlValue("Password", '<input type=password id=d2pass style=width:230px maxlength=128 autocomplete=off />'); x += addHtmlValue("Password", '<input type=password id=d2pass style=width:230px maxlength=128 autocomplete=off />');
if ((features2 & 0x00400000) == 0) { x += addHtmlValue("", '<label><input type="checkbox" id=d2savecred>' + "Remember credentials" + '</label>'); } if ((features2 & 0x00400000) == 0) { x += addHtmlValue("", '<label><input type="checkbox" id=d2savecred>' + "Remember credentials" + '</label>'); }
x + '</div></div>'; x += '</div>';
x += MoreStart();
x += addHtmlValue("Alt Shell", '<input type=text id=d2altshell style=width:230px maxlength=2048 />');
x += addHtmlValue("Working Dir", '<input type=text id=d2workdir style=width:230px maxlength=2048 />');
x += MoreEnd();
setDialogMode(2, "RDP Credentials", 3, askRdpCredentialsEx, x); setDialogMode(2, "RDP Credentials", 3, askRdpCredentialsEx, x);
} }
@ -8586,11 +8594,11 @@
height = Q('DeskParent').offsetHeight; height = Q('DeskParent').offsetHeight;
} }
if ((currentNode.rdp == 1) && (Q('d2mode').value == 1)) { if ((currentNode.rdp == 1) && (Q('d2mode').value == 1)) {
connectDesktop(null, 4, { servercred: true, width: width, height: height, flags: (desktopsettings.rdpflags != null) ? desktopsettings.rdpflags : 0x2F }); connectDesktop(null, 4, { servercred: true, width: width, height: height, flags: (desktopsettings.rdpflags != null) ? desktopsettings.rdpflags : 0x2F, altshell: Q('d2altshell').value, workdir: Q('d2workdir').value });
} else { } else {
var savecred = false; var savecred = false;
if ((features2 & 0x00400000) == 0) { savecred = Q('d2savecred').checked; } if ((features2 & 0x00400000) == 0) { savecred = Q('d2savecred').checked; }
connectDesktop(null, 4, { domain: Q('d2domain').value, username: Q('d2user').value, password: Q('d2pass').value, savecred: savecred, width: width, height: height, flags: (desktopsettings.rdpflags != null) ? desktopsettings.rdpflags : 0x2F }); connectDesktop(null, 4, { domain: Q('d2domain').value, username: Q('d2user').value, password: Q('d2pass').value, savecred: savecred, width: width, height: height, flags: (desktopsettings.rdpflags != null) ? desktopsettings.rdpflags : 0x2F, altshell: Q('d2altshell').value, workdir: Q('d2workdir').value });
} }
} }
@ -16857,6 +16865,7 @@
// Reset dialog size // Reset dialog size
QS('dialog').width = QS('dialog').top = QS('dialog').left = QS('dialog').right = QS('dialog').bottom = null; QS('dialog').width = QS('dialog').top = QS('dialog').left = QS('dialog').right = QS('dialog').bottom = null;
MoreToggle(false);
QE('idx_dlgOkButton', true); QE('idx_dlgOkButton', true);
QV('idx_dlgOkButton', b & 1); QV('idx_dlgOkButton', b & 1);
@ -16869,6 +16878,7 @@
for (var i = 1; i < 24; i++) { QV('dialog' + i, i == x); } // Edit this line when more dialogs are added for (var i = 1; i < 24; i++) { QV('dialog' + i, i == x); } // Edit this line when more dialogs are added
QV('dialog', x); QV('dialog', x);
if (c) { if (x == 2) { QH('id_dialogOptions', c); } else { QH('id_dialogMessage', c); } } if (c) { if (x == 2) { QH('id_dialogOptions', c); } else { QH('id_dialogMessage', c); } }
QV('idx_dlgMoreButtons', (Q('morexxx3') != null));
} }
function dialogclose(x) { function dialogclose(x) {
@ -17470,8 +17480,9 @@
function AddButton(v, f) { return '<input type=button value="' + v + '" onclick="' + f + '" style=margin:4px>'; } function AddButton(v, f) { return '<input type=button value="' + v + '" onclick="' + f + '" style=margin:4px>'; }
function AddButton2(v, f) { return '<input type=button value="' + v + '" onclick="' + f + '">'; } function AddButton2(v, f) { return '<input type=button value="' + v + '" onclick="' + f + '">'; }
function AddRefreshButton(f) { return '<input type=button name=refreshbtn value=Refresh onclick="refreshButtons(false);' + f + '" style=margin:4px ' + (refreshButtonsState==false?'disabled':'') + '>'; } function AddRefreshButton(f) { return '<input type=button name=refreshbtn value=Refresh onclick="refreshButtons(false);' + f + '" style=margin:4px ' + (refreshButtonsState==false?'disabled':'') + '>'; }
function MoreStart() { return '<a href=# style=cursor:pointer;color:blue id=morexxx1 onclick=QV("morexxx1",false);QV("morexxx2",true)>&#x25BC; ' + "More" + '</a><div id=morexxx2 style=display:none><br><hr>'; }; function MoreStart() { return '<div id=morexxx3 style=display:none><hr>'; };
function MoreEnd() { return '<a href=# style=cursor:pointer;color:blue onclick=QV("morexxx2",false);QV("morexxx1",true)>&#x25B2; ' + "Less" + '</a></div>'; }; function MoreEnd() { return '</div>'; };
function MoreToggle(v) { QV("morexxx1",!v); QV("morexxx2",v); QV("morexxx3",v); }
function getSelectedOptions(sel) { var opts = [], opt; for (var i = 0, len = sel.options.length; i < len; i++) { opt = sel.options[i]; if (opt.selected) { opts.push(opt.value); } } return opts; } function getSelectedOptions(sel) { var opts = [], opt; for (var i = 0, len = sel.options.length; i < len; i++) { opt = sel.options[i]; if (opt.selected) { opts.push(opt.value); } } return opts; }
function getInstance(x, y) { for (var i in x) { if (x[i]['InstanceID'] == y) return x[i]; } return null; } function getInstance(x, y) { for (var i in x) { if (x[i]['InstanceID'] == y) return x[i]; } return null; }
function getItem(x, y, z) { for (var i in x) { if (x[i][y] == z) return x[i]; } return null; } function getItem(x, y, z) { for (var i in x) { if (x[i][y] == z) return x[i]; } return null; }