diff --git a/MeshCentralServer.njsproj b/MeshCentralServer.njsproj index 794ef46d..697f5c3d 100644 --- a/MeshCentralServer.njsproj +++ b/MeshCentralServer.njsproj @@ -104,6 +104,7 @@ + @@ -181,6 +182,181 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -281,6 +457,7 @@ + @@ -301,6 +478,8 @@ + + @@ -315,6 +494,7 @@ + @@ -324,6 +504,7 @@ + diff --git a/agents/MeshAgentOSXPackager.zip b/agents/MeshAgentOSXPackager.zip index b0424e37..c4936a66 100644 Binary files a/agents/MeshAgentOSXPackager.zip and b/agents/MeshAgentOSXPackager.zip differ diff --git a/agents/MeshCentralRouter.exe b/agents/MeshCentralRouter.exe index 56ce7aae..a64f1c7b 100644 Binary files a/agents/MeshCentralRouter.exe and b/agents/MeshCentralRouter.exe differ diff --git a/agents/MeshCmd-signed.exe b/agents/MeshCmd-signed.exe index 2323ca42..e4f98a07 100644 Binary files a/agents/MeshCmd-signed.exe and b/agents/MeshCmd-signed.exe differ diff --git a/agents/MeshCmd64-signed.exe b/agents/MeshCmd64-signed.exe index abafe367..66acf817 100644 Binary files a/agents/MeshCmd64-signed.exe and b/agents/MeshCmd64-signed.exe differ diff --git a/agents/MeshService-signed.exe b/agents/MeshService-signed.exe index 373539be..11974d61 100644 Binary files a/agents/MeshService-signed.exe and b/agents/MeshService-signed.exe differ diff --git a/agents/MeshService.exe b/agents/MeshService.exe index ea60de73..db9e59f7 100644 Binary files a/agents/MeshService.exe and b/agents/MeshService.exe differ diff --git a/agents/MeshService64-signed.exe b/agents/MeshService64-signed.exe index 144a8748..4ea4aa9e 100644 Binary files a/agents/MeshService64-signed.exe and b/agents/MeshService64-signed.exe differ diff --git a/agents/MeshService64.exe b/agents/MeshService64.exe index 6b2612fb..e27d6109 100644 Binary files a/agents/MeshService64.exe and b/agents/MeshService64.exe differ diff --git a/agents/meshagent_arm b/agents/meshagent_arm index 4e55577d..3dc983ec 100644 Binary files a/agents/meshagent_arm and b/agents/meshagent_arm differ diff --git a/agents/meshagent_arm-linaro b/agents/meshagent_arm-linaro new file mode 100644 index 00000000..5eaf834d Binary files /dev/null and b/agents/meshagent_arm-linaro differ diff --git a/agents/meshagent_arm64 b/agents/meshagent_arm64 index 8e79ded3..9c9273bd 100644 Binary files a/agents/meshagent_arm64 and b/agents/meshagent_arm64 differ diff --git a/agents/meshagent_armhf b/agents/meshagent_armhf index 0c88fd01..8a668297 100644 Binary files a/agents/meshagent_armhf and b/agents/meshagent_armhf differ diff --git a/agents/meshagent_freebsd_x86-64 b/agents/meshagent_freebsd_x86-64 index 1c360374..8b70a5dd 100644 Binary files a/agents/meshagent_freebsd_x86-64 and b/agents/meshagent_freebsd_x86-64 differ diff --git a/agents/meshagent_mips b/agents/meshagent_mips index 1be08985..03d18542 100644 Binary files a/agents/meshagent_mips and b/agents/meshagent_mips differ diff --git a/agents/meshagent_osx-x86-64 b/agents/meshagent_osx-x86-64 index 3774b1eb..f8bc6a9f 100644 Binary files a/agents/meshagent_osx-x86-64 and b/agents/meshagent_osx-x86-64 differ diff --git a/agents/meshagent_pogo b/agents/meshagent_pogo index 0f58ba52..2decb9ff 100644 Binary files a/agents/meshagent_pogo and b/agents/meshagent_pogo differ diff --git a/agents/meshagent_poky b/agents/meshagent_poky index d56d1b0a..696b1f54 100644 Binary files a/agents/meshagent_poky and b/agents/meshagent_poky differ diff --git a/agents/meshagent_poky64 b/agents/meshagent_poky64 index 61ab7956..c86cc578 100644 Binary files a/agents/meshagent_poky64 and b/agents/meshagent_poky64 differ diff --git a/agents/meshagent_x86 b/agents/meshagent_x86 index 8123f2cc..355b7f1a 100644 Binary files a/agents/meshagent_x86 and b/agents/meshagent_x86 differ diff --git a/agents/meshagent_x86-64 b/agents/meshagent_x86-64 index 90682865..ac612813 100644 Binary files a/agents/meshagent_x86-64 and b/agents/meshagent_x86-64 differ diff --git a/agents/meshagent_x86-64_nokvm b/agents/meshagent_x86-64_nokvm index 8c2ef497..5a343109 100644 Binary files a/agents/meshagent_x86-64_nokvm and b/agents/meshagent_x86-64_nokvm differ diff --git a/agents/meshagent_x86_nokvm b/agents/meshagent_x86_nokvm index c1d22dd2..b8f91c0e 100644 Binary files a/agents/meshagent_x86_nokvm and b/agents/meshagent_x86_nokvm differ diff --git a/agents/meshcmd.js b/agents/meshcmd.js index c213e8b3..17f04751 100644 --- a/agents/meshcmd.js +++ b/agents/meshcmd.js @@ -153,8 +153,10 @@ function run(argv) { if ((typeof args.cdrom) == 'string') { settings.cdrom = args.cdrom; } if ((typeof args.tag) == 'string') { settings.tag = args.tag; } if ((typeof args.scan) == 'string') { settings.scan = args.scan; } + if ((typeof args.token) == 'string') { settings.token = args.token; } if ((typeof args.timeout) == 'string') { settings.timeout = parseInt(args.timeout); } if ((typeof args.uuidoutput) == 'string' || args.uuidoutput) { settings.uuidoutput = args.uuidoutput; } + if (args.emailtoken) { settings.emailtoken = true; } if (args.debug === true) { settings.debuglevel = 1; } if (args.debug) { try { waitForDebugger(); } catch (e) { } } if (args.noconsole) { settings.noconsole = true; } @@ -591,10 +593,11 @@ function run(argv) { if ((settings.password == null) || (typeof settings.password != 'string') || (settings.password == '')) { console.log('No or invalid \"password\" specified, use --password [password].'); exit(1); return; } if ((settings.hostname == null) || (typeof settings.hostname != 'string') || (settings.hostname == '')) { settings.hostname = '127.0.0.1'; } if ((settings.username == null) || (typeof settings.username != 'string') || (settings.username == '')) { settings.username = 'admin'; } - if ((settings.script == null) || (typeof settings.script != 'string') || (settings.script == '')) { if (mescriptJSON != '') { settings.scriptjson = mescriptJSON; } else { console.log('No or invalid \"script\" file specified, use --script [filename].'); exit(1); return; } } + //if ((settings.script == null) || (typeof settings.script != 'string') || (settings.script == '')) { if (mescriptJSON != '') { settings.scriptjson = mescriptJSON; } else { console.log('No or invalid \"script\" file specified, use --script [filename].'); exit(1); return; } } + if ((settings.script == null) || (typeof settings.script != 'string') || (settings.script == '')) { console.log('No or invalid \"script\" file specified, use --script [filename].'); exit(1); return; } startMeScript(); } else if (settings.action == 'amtuuid') { - // Start running + // Start running if (settings.hostname != null) { if ((settings.password == null) || (typeof settings.password != 'string') || (settings.password == '')) { console.log('No or invalid \"password\" specified, use --password [password].'); exit(1); return; } if ((settings.username == null) || (typeof settings.username != 'string') || (settings.username == '')) { settings.username = 'admin'; } @@ -1021,7 +1024,8 @@ function startMeshCommander() { } else { // If TLS is going to be used, setup a TLS socket var tls = require('tls'); - var tlsoptions = { host: webargs.host, port: webargs.port, secureProtocol: ((webargs.tls1only == 1) ? 'TLSv1_method' : 'SSLv23_method'), rejectUnauthorized: false }; + var tlsoptions = { host: webargs.host, port: webargs.port, rejectUnauthorized: false }; + if (webargs.tls1only == 1) { tlsoptions.secureProtocol = 'TLSv1_method'; } ws.forwardclient = tls.connect(tlsoptions, function () { debug(1, 'Connected TLS to ' + webargs.host + ':' + webargs.port + '.'); this.pipe(this.ws, { end: false }); this.ws.pipe(this, { end: false }); }); ws.forwardclient.on('error', function () { debug(1, 'TLS connection error to ' + webargs.host + ':' + webargs.port + '.'); try { this.ws.end(); } catch (e) { } }); ws.forwardclient.ws = ws; @@ -2046,20 +2050,80 @@ function processLmsControlData(data) { // function startRouter() { + // Start by requesting a login token, this is needed because of 2FA and check that we have correct credentials from the start + var options; + try { + var url = settings.serverurl.split('meshrelay.ashx').join('control.ashx') + '?user=' + settings.username + '&pass=' + settings.password; + if (settings.emailtoken) { url += '&token=**email**'; } else if (settings.token != null) { url += '&token=' + settings.token; } + options = http.parseUri(url); + } catch (e) { console.log("Unable to parse \"serverUrl\"."); process.exit(1); return; } + options.checkServerIdentity = onVerifyServer; + options.rejectUnauthorized = false; + settings.websocket = http.request(options); + settings.websocket.upgrade = OnServerWebSocket; + settings.websocket.on('error', function (e) { console.log("ERROR: " + JSON.stringify(e)); }); + settings.websocket.end(); +} + +function OnServerWebSocket(msg, s, head) { + settings.webchannel = s; + s.on('data', function (msg) { + var command = JSON.parse(msg); + switch (command.action) { + case 'close': { + if (command.cause == 'noauth') { + if (command.msg == 'tokenrequired') { + if (command.email2fasent === true) { + console.log("Login token email sent."); + } else if (command.email2fa === true) { + console.log("Login token required, use --token [token], or --emailtoken get a token."); + } else { + console.log("Login token required, use --token [token]."); + } + } else { console.log("Invalid username or password."); } + } else { console.log("Server disconnected: " + command.msg); } + process.exit(1); + return; + } + case 'serverinfo': { + s.write("{\"action\":\"authcookie\"}"); // Ask for our first authentication cookie + break; + } + case 'authcookie': { + if (settings.acookie == null) { + settings.acookie = command.cookie; + settings.rcookie = command.rcookie; + settings.renewCookieTimer = setInterval(function () { settings.webchannel.write("{\"action\":\"authcookie\"}"); }, 600000); // Ask for new cookie every 10 minutes + startRouterEx(); + } else { + settings.acookie = command.cookie; + settings.rcookie = command.rcookie; + } + break; + } + } + }); + s.on('error', function () { console.log("Server connection error."); process.exit(1); return; }); + s.on('close', function () { console.log("Server closed the connection."); process.exit(1); return; }); +} + +function startRouterEx() { tcpserver = net.createServer(OnTcpClientConnected); tcpserver.on('error', function (e) { console.log("ERROR: " + JSON.stringify(e)); exit(0); return; }); - tcpserver.listen(settings.localport, function () { - // We started listening. - if (settings.remotetarget == null) { - console.log('Redirecting local port ' + settings.localport + ' to remote port ' + settings.remoteport + '.'); - } else { - console.log('Redirecting local port ' + settings.localport + ' to ' + settings.remotetarget + ':' + settings.remoteport + '.'); - } - console.log("Press ctrl-c to exit."); + try { + tcpserver.listen(settings.localport, function () { + // We started listening. + if (settings.remotetarget == null) { + console.log('Redirecting local port ' + settings.localport + ' to remote port ' + settings.remoteport + '.'); + } else { + console.log('Redirecting local port ' + settings.localport + ' to ' + settings.remotetarget + ':' + settings.remoteport + '.'); + } + console.log("Press ctrl-c to exit."); - // If settings has a "cmd", run it now. - //process.exec("notepad.exe"); - }); + // If settings has a "cmd", run it now. + //process.exec("notepad.exe"); + }); + } catch (ex) { console.log("Unable to bind to local TCP port " + settings.localport + "."); exit(1); return; } } // Called when a TCP connect is received on the local port. Launch a tunnel. @@ -2069,8 +2133,9 @@ function OnTcpClientConnected(c) { debug(1, "Client connected"); c.on('end', function () { disconnectTunnel(this, this.websocket, "Client closed"); }); c.pause(); + var options; try { - options = http.parseUri(settings.serverurl + '?user=' + settings.username + '&pass=' + settings.password + '&nodeid=' + settings.remotenodeid + '&tcpport=' + settings.remoteport + (settings.remotetarget == null ? '' : '&tcpaddr=' + settings.remotetarget)); + options = http.parseUri(settings.serverurl + '?auth=' + settings.acookie + '&nodeid=' + settings.remotenodeid + '&tcpport=' + settings.remoteport + (settings.remotetarget == null ? '' : '&tcpaddr=' + settings.remotetarget)); } catch (e) { console.log("Unable to parse \"serverUrl\"."); process.exit(1); return; } options.checkServerIdentity = onVerifyServer; options.rejectUnauthorized = false; @@ -2104,8 +2169,8 @@ function OnWebSocket(msg, s, head) { } } }); - s.on('error', function (msg) { disconnectTunnel(this.tcp, this, 'Websocket error'); }); - s.on('close', function (msg) { disconnectTunnel(this.tcp, this, 'Websocket closed'); }); + s.on('error', function () { disconnectTunnel(this.tcp, this, 'Websocket error'); }); + s.on('close', function () { disconnectTunnel(this.tcp, this, 'Websocket closed'); }); s.parent = this; } diff --git a/agents/meshcore.js b/agents/meshcore.js index 40508924..cff452d7 100644 --- a/agents/meshcore.js +++ b/agents/meshcore.js @@ -36,6 +36,10 @@ var MESHRIGHT_NOTERMINAL = 512; var MESHRIGHT_NOFILES = 1024; var MESHRIGHT_NOAMT = 2048; var MESHRIGHT_LIMITEDINPUT = 4096; +var MESHRIGHT_LIMITEVENTS = 8192; +var MESHRIGHT_CHATNOTIFY = 16384; +var MESHRIGHT_UNINSTALL = 32768; +var MESHRIGHT_NODESKTOP = 65536; function createMeshCore(agent) { var obj = {}; @@ -276,7 +280,8 @@ function createMeshCore(agent) { */ // MeshAgent JavaScript Core Module. This code is sent to and running on the mesh agent. - var meshCoreObj = { action: 'coreinfo', value: 'MeshCore v6', caps: 14 }; // Capability bitmask: 1 = Desktop, 2 = Terminal, 4 = Files, 8 = Console, 16 = JavaScript, 32 = Temporary Agent, 64 = Recovery Agent + var meshCoreObj = { action: 'coreinfo', value: (require('MeshAgent').coreHash ? ('MeshCore CRC[' + crc32c(require('MeshAgent').coreHash) + ']') : ('MeshCore v6')), caps: 14 }; // Capability bitmask: 1 = Desktop, 2 = Terminal, 4 = Files, 8 = Console, 16 = JavaScript, 32 = Temporary Agent, 64 = Recovery Agent + // Get the operating system description string try { require('os').name().then(function (v) { meshCoreObj.osdesc = v; }); } catch (ex) { } @@ -790,7 +795,7 @@ function createMeshCore(agent) { if (process.platform != 'win32') break; var p = require('user-sessions').enumerateUsers(); p.sessionid = data.sessionid; - p.then(function (u) { mesh.SendCommand({ action: 'msg', type: 'userSessions', sessionid: u.sessionid, data: u }); }); + p.then(function (u) { mesh.SendCommand({ action: 'msg', type: 'userSessions', sessionid: data.sessionid, data: u }); }); break; } default: @@ -1328,7 +1333,7 @@ function createMeshCore(agent) { //this.write('MeshCore Terminal Hello'); } else if (this.httprequest.protocol == 2) { // Check user access rights for desktop - if (((this.httprequest.rights & MESHRIGHT_REMOTECONTROL) == 0) && ((this.httprequest.rights & MESHRIGHT_REMOTEVIEW) == 0)) { + if ((((this.httprequest.rights & MESHRIGHT_REMOTECONTROL) == 0) && ((this.httprequest.rights & MESHRIGHT_REMOTEVIEW) == 0)) || ((this.httprequest.rights != 0xFFFFFFFF) && ((this.httprequest.rights & MESHRIGHT_NODESKTOP) != 0))) { // Disengage this tunnel, user does not have the rights to do this!! this.httprequest.protocol = 999999; this.httprequest.s.end(); @@ -1396,8 +1401,7 @@ function createMeshCore(agent) { if (this.httprequest.desktop.kvm.hasOwnProperty('connectionCount')) { this.httprequest.desktop.kvm.connectionCount++; this.httprequest.desktop.kvm.users.push(this.httprequest.username); - } - else { + } else { this.httprequest.desktop.kvm.connectionCount = 1; this.httprequest.desktop.kvm.users = [this.httprequest.username]; } @@ -1505,7 +1509,6 @@ function createMeshCore(agent) { //this.write('MeshCore KVM Hello!1'); } else if (this.httprequest.protocol == 5) { - // Check user access rights for files if (((this.httprequest.rights & MESHRIGHT_REMOTECONTROL) == 0) || ((this.httprequest.rights != 0xFFFFFFFF) && ((this.httprequest.rights & MESHRIGHT_NOFILES) != 0))) { // Disengage this tunnel, user does not have the rights to do this!! @@ -1958,7 +1961,7 @@ function createMeshCore(agent) { var response = null; switch (cmd) { case 'help': { // Displays available commands - var fin = '', f = '', availcommands = 'agentsize,version,help,info,osinfo,args,print,type,dbkeys,dbget,dbset,dbcompact,eval,parseuri,httpget,nwslist,plugin,wsconnect,wssend,wsclose,notify,ls,ps,kill,amt,netinfo,location,power,wakeonlan,setdebug,smbios,rawsmbios,toast,lock,users,sendcaps,openurl,amtreset,amtccm,amtacm,amtdeactivate,amtpolicy,getscript,getclip,setclip,log,av,cpuinfo,sysinfo,apf,scanwifi,scanamt,wallpaper'; + var fin = '', f = '', availcommands = 'startupoptions,alert,agentsize,version,help,info,osinfo,args,print,type,dbkeys,dbget,dbset,dbcompact,eval,parseuri,httpget,nwslist,plugin,wsconnect,wssend,wsclose,notify,ls,ps,kill,amt,netinfo,location,power,wakeonlan,setdebug,smbios,rawsmbios,toast,lock,users,sendcaps,openurl,amtreset,amtccm,amtacm,amtdeactivate,amtpolicy,getscript,getclip,setclip,log,av,cpuinfo,sysinfo,apf,scanwifi,scanamt,wallpaper'; if (process.platform == 'win32') { availcommands += ',safemode,wpfhwacceleration'; } availcommands = availcommands.split(',').sort(); while (availcommands.length > 0) { @@ -1969,6 +1972,27 @@ function createMeshCore(agent) { response = "Available commands: \r\n" + fin + "."; break; } + case 'startupoptions': + response = JSON.stringify(require('MeshAgent').getStartupOptions()); + break; + case 'alert': + if (args['_'].length == 0) + { + response = "Proper usage: alert TITLE, CAPTION [, TIMEOUT]"; // Display usage + } + else + { + var p = args['_'].join(' ').split(','); + if(p.length<2) + { + response = "Proper usage: alert TITLE, CAPTION [, TIMEOUT]"; // Display usage + } + else + { + this._alert = require('message-box').create(p[0], p[1], p.length==3?parseInt(p[2]):9999,1); + } + } + break; case 'agentsize': var actualSize = Math.floor(require('fs').statSync(process.execPath).size / 1024); if (process.platform == 'win32') { @@ -2366,7 +2390,7 @@ function createMeshCore(agent) { break; } case 'info': { // Return information about the agent and agent core module - response = 'Current Core: ' + meshCoreObj.value + '.\r\nAgent Time: ' + Date() + '.\r\nUser Rights: 0x' + rights.toString(16) + '.\r\nPlatform: ' + process.platform + '.\r\nCapabilities: ' + meshCoreObj.caps + '.\r\nServer URL: ' + mesh.ServerUrl + '.'; + response = 'Current Core: ' + meshCoreObj.value + '\r\nAgent Time: ' + Date() + '.\r\nUser Rights: 0x' + rights.toString(16) + '.\r\nPlatform: ' + process.platform + '.\r\nCapabilities: ' + meshCoreObj.caps + '.\r\nServer URL: ' + mesh.ServerUrl + '.'; if (amt != null) { response += '\r\nBuilt-in LMS: ' + ['Disabled', 'Connecting..', 'Connected'][amt.lmsstate] + '.'; } if (meshCoreObj.osdesc) { response += '\r\nOS: ' + meshCoreObj.osdesc + '.'; } response += '\r\nModules: ' + addedModules.join(', ') + '.'; diff --git a/agents/meshinstall-linux.sh b/agents/meshinstall-linux.sh index 033ab750..294e1f54 100644 --- a/agents/meshinstall-linux.sh +++ b/agents/meshinstall-linux.sh @@ -75,7 +75,15 @@ CheckInstallAgent() { machineid=30 else # Linux x86, 64 bit - machineid=6 + bitlen=$( getconf LONG_BIT ) + if [ $bitlen == '32' ] + then + # 32 bit OS + machineid=5 + else + # 64 bit OS + machineid=6 + fi fi fi if [ $machinetype == 'x86' ] || [ $machinetype == 'i686' ] || [ $machinetype == 'i586' ] diff --git a/agents/modules_meshcmd/amt-wsman-duk.js b/agents/modules_meshcmd/amt-wsman-duk.js index fe6f20dd..dc8ae61e 100644 --- a/agents/modules_meshcmd/amt-wsman-duk.js +++ b/agents/modules_meshcmd/amt-wsman-duk.js @@ -21,8 +21,7 @@ limitations under the License. */ // Construct a WSMAN communication object -function CreateWsmanComm(/*host, port, user, pass, tls, extra*/) -{ +function CreateWsmanComm(/*host, port, user, pass, tls, extra*/) { var obj = {}; obj.PendingAjax = []; // List of pending AJAX calls. When one frees up, another will start. obj.ActiveAjaxCount = 0; // Number of currently active AJAX calls @@ -31,15 +30,13 @@ function CreateWsmanComm(/*host, port, user, pass, tls, extra*/) obj.digest = null; obj.RequestCount = 0; - if (arguments.length == 1 && typeof(arguments[0] == 'object')) - { + if (arguments.length == 1 && typeof (arguments[0] == 'object')) { obj.host = arguments[0].host; obj.port = arguments[0].port; obj.authToken = arguments[0].authToken; obj.tls = arguments[0].tls; } - else - { + else { obj.host = arguments[0]; obj.port = arguments[1]; obj.user = arguments[2]; @@ -75,14 +72,10 @@ function CreateWsmanComm(/*host, port, user, pass, tls, extra*/) if (globalDebugFlags & 1) { console.log("SEND: " + postdata + "\r\n\r\n"); } // DEBUG // We are in a DukTape environement - if (obj.digest == null) - { - if (obj.authToken) - { + if (obj.digest == null) { + if (obj.authToken) { obj.digest = require('http-digest').create({ authToken: obj.authToken }); - } - else - { + } else { obj.digest = require('http-digest').create(obj.user, obj.pass); } obj.digest.http = require('http'); diff --git a/agents/modules_meshcore/smbios.js b/agents/modules_meshcore/smbios.js index b1f5393d..ad8fa8c4 100644 --- a/agents/modules_meshcore/smbios.js +++ b/agents/modules_meshcore/smbios.js @@ -191,6 +191,12 @@ function SMBiosTables() catch(e) { } + try + { + if (JSON.stringify(r).length > 65535) { r = {}; } + } + catch(ee) + {} return r; } this.processorInfo = function processorInfo(data) { diff --git a/agents/modules_meshcore/win-console.js b/agents/modules_meshcore/win-console.js index 82d57e86..32ae289f 100644 --- a/agents/modules_meshcore/win-console.js +++ b/agents/modules_meshcore/win-console.js @@ -145,7 +145,6 @@ function WindowsConsole() this.TrayIcon.remove(); handled = true; } - //if (!handled) { console.log(msg); } } }); retVal.remove = function remove() diff --git a/agents/modules_meshcore/win-terminal.js b/agents/modules_meshcore/win-terminal.js index 29234222..592e61bc 100644 --- a/agents/modules_meshcore/win-terminal.js +++ b/agents/modules_meshcore/win-terminal.js @@ -401,7 +401,8 @@ function windows_terminal() { } } } - this._WriteCharacter = function (key, bControlKey) { + this._WriteCharacter = function (key, bControlKey) + { var rec = GM.CreateVariable(20); rec.Deref(0, 2).toBuffer().writeUInt16LE(KEY_EVENT); // rec.EventType rec.Deref(4, 4).toBuffer().writeUInt16LE(1); // rec.Event.KeyEvent.bKeyDown @@ -410,10 +411,10 @@ function windows_terminal() { rec.Deref(8, 2).toBuffer().writeUInt16LE(1); // rec.Event.KeyEvent.wRepeatCount rec.Deref(10, 2).toBuffer().writeUInt16LE(this._user32.VkKeyScanA(key).Val); // rec.Event.KeyEvent.wVirtualKeyCode rec.Deref(12, 2).toBuffer().writeUInt16LE(this._user32.MapVirtualKeyA(this._user32.VkKeyScanA(key).Val, MAPVK_VK_TO_VSC).Val); - + var dwWritten = GM.CreateVariable(4); if (this._kernel32.WriteConsoleInputA(this._stdinput, rec, 1, dwWritten).Val == 0) { return (false); } - + rec.Deref(4, 4).toBuffer().writeUInt16LE(0); // rec.Event.KeyEvent.bKeyDown return (this._kernel32.WriteConsoleInputA(this._stdinput, rec, 1, dwWritten).Val != 0); } @@ -478,23 +479,28 @@ function windows_terminal() { return (retVal); } - this._SendDataBuffer = function (data) { + this._SendDataBuffer = function (data) + { // { data, attributes, width, height, x, y } - - var dy, line, attr; - for (dy = 0; dy < data.height; ++dy) { - line = data.data[dy]; - attr = data.attributes[dy]; - line.s = line.toString(); - - //line = data.data.slice(data.width * dy, (data.width * dy) + data.width); - //attr = data.attributes.slice(data.width * dy, (data.width * dy) + data.width); - this._stream.push(TranslateLine(data.x + 1, data.y + dy + 1, line, attr)); + if (this._stream != null) + { + var dy, line, attr; + for (dy = 0; dy < data.height; ++dy) + { + line = data.data[dy]; + attr = data.attributes[dy]; + line.s = line.toString(); + + //line = data.data.slice(data.width * dy, (data.width * dy) + data.width); + //attr = data.attributes.slice(data.width * dy, (data.width * dy) + data.width); + this._stream.push(TranslateLine(data.x + 1, data.y + dy + 1, line, attr)); + } } } - this._SendScroll = function _SendScroll(dx, dy) { - if (this._scrollTimer) { return; } + this._SendScroll = function _SendScroll(dx, dy) + { + if (this._scrollTimer || this._stream == null) { return; } var info = GM.CreateVariable(22); if (this._kernel32.GetConsoleScreenBufferInfo(this._stdoutput, info).Val == 0) { throw ('Error getting screen buffer info'); } diff --git a/amt/amt-ider-module.js b/amt/amt-ider-module.js index 0d1f491e..231b8bf3 100644 --- a/amt/amt-ider-module.js +++ b/amt/amt-ider-module.js @@ -607,7 +607,7 @@ module.exports.CreateAmtRemoteIder = function (webserver, meshcentral) { if (g_len > obj.iderinfo.readbfr) { len = obj.iderinfo.readbfr; } g_len -= len; g_lba += len; - var buffer = new Buffer(len); + var buffer = Buffer.alloc(len); fs.read(g_media, buffer, 0, len, lba, function (error, bytesRead, buffer) { obj.SendDataToHost(g_dev, (g_len == 0), buffer.toString('binary'), featureRegister & 1); if ((g_len > 0) && (g_reset == false)) { diff --git a/amt/amt-redir-mesh.js b/amt/amt-redir-mesh.js index 6e84cb28..a4a6206a 100644 --- a/amt/amt-redir-mesh.js +++ b/amt/amt-redir-mesh.js @@ -150,7 +150,8 @@ module.exports.CreateAmtRedirect = function (module, domain, user, webserver, me // TLSSocket to encapsulate TLS communication, which then tunneled via SerialTunnel an then wrapped through CIRA APF const TLSSocket = require('tls').TLSSocket; - const tlsoptions = { secureProtocol: ((obj.tls1only == 1) ? 'TLSv1_method' : 'SSLv23_method'), ciphers: 'RSA+AES:!aNULL:!MD5:!DSS', secureOptions: constants.SSL_OP_NO_SSLv2 | constants.SSL_OP_NO_SSLv3 | constants.SSL_OP_NO_COMPRESSION | constants.SSL_OP_CIPHER_SERVER_PREFERENCE, rejectUnauthorized: false }; + const tlsoptions = { ciphers: 'RSA+AES:!aNULL:!MD5:!DSS', secureOptions: constants.SSL_OP_NO_SSLv2 | constants.SSL_OP_NO_SSLv3 | constants.SSL_OP_NO_COMPRESSION | constants.SSL_OP_CIPHER_SERVER_PREFERENCE, rejectUnauthorized: false }; + if (obj.tls1only == 1) { tlsoptions.secureProtocol = 'TLSv1_method'; } const tlsock = new TLSSocket(ser, tlsoptions); tlsock.on('error', function (err) { Debug(1, "CIRA TLS Connection Error ", err); }); tlsock.on('secureConnect', function () { Debug(2, "CIRA Secure TLS Connection"); ws._socket.resume(); }); @@ -207,7 +208,8 @@ module.exports.CreateAmtRedirect = function (module, domain, user, webserver, me obj.forwardclient.setEncoding('binary'); } else { // If TLS is going to be used, setup a TLS socket - var tlsoptions = { secureProtocol: ((obj.tls1only == 1) ? 'TLSv1_method' : 'SSLv23_method'), ciphers: 'RSA+AES:!aNULL:!MD5:!DSS', secureOptions: constants.SSL_OP_NO_SSLv2 | constants.SSL_OP_NO_SSLv3 | constants.SSL_OP_NO_COMPRESSION | constants.SSL_OP_CIPHER_SERVER_PREFERENCE, rejectUnauthorized: false }; + var tlsoptions = { ciphers: 'RSA+AES:!aNULL:!MD5:!DSS', secureOptions: constants.SSL_OP_NO_SSLv2 | constants.SSL_OP_NO_SSLv3 | constants.SSL_OP_NO_COMPRESSION | constants.SSL_OP_CIPHER_SERVER_PREFERENCE, rejectUnauthorized: false }; + if (obj.tls1only == 1) { tlsoptions.secureProtocol = 'TLSv1_method'; } obj.forwardclient = obj.tls.connect(port, node.host, tlsoptions, function () { // The TLS connection method is the same as TCP, but located a bit differently. Debug(2, 'TLS Intel AMT transport connected to ' + node.host + ':' + port + '.'); diff --git a/amt/amt-wsman-comm.js b/amt/amt-wsman-comm.js index 9c804e5f..8e1c3042 100644 --- a/amt/amt-wsman-comm.js +++ b/amt/amt-wsman-comm.js @@ -167,46 +167,15 @@ var CreateWsmanComm = function (host, port, user, pass, tls, tlsoptions, parent, obj.socketState = 1; obj.kerberosDone = 0; - if (obj.mode==1 ) { //Direct - if (obj.xtls != 1) { - // Connect without TLS - obj.socket = new obj.net.Socket(); - obj.socket.setEncoding('binary'); - obj.socket.setTimeout(6000); // Set socket idle timeout - obj.socket.on('data', obj.xxOnSocketData); - obj.socket.on('close', obj.xxOnSocketClosed); - obj.socket.on('timeout', obj.xxOnSocketClosed); - obj.socket.connect(obj.port, obj.host, obj.xxOnSocketConnected); - } else { - // Connect with TLS - var options = { secureProtocol: ((obj.xtlsMethod == 0) ? 'SSLv23_method' : 'TLSv1_method'), ciphers: 'RSA+AES:!aNULL:!MD5:!DSS', secureOptions: obj.constants.SSL_OP_NO_SSLv2 | obj.constants.SSL_OP_NO_SSLv3 | obj.constants.SSL_OP_NO_COMPRESSION | obj.constants.SSL_OP_CIPHER_SERVER_PREFERENCE, rejectUnauthorized: false }; - if (obj.xtlsoptions) { - if (obj.xtlsoptions.ca) options.ca = obj.xtlsoptions.ca; - if (obj.xtlsoptions.cert) options.cert = obj.xtlsoptions.cert; - if (obj.xtlsoptions.key) options.key = obj.xtlsoptions.key; - obj.xtlsoptions = options; - } - obj.socket = obj.tls.connect(obj.port, obj.host, obj.xtlsoptions, obj.xxOnSocketConnected); - obj.socket.setEncoding('binary'); - obj.socket.setTimeout(6000); // Set socket idle timeout - obj.socket.on('data', obj.xxOnSocketData); - obj.socket.on('close', obj.xxOnSocketClosed); - obj.socket.on('timeout', obj.xxOnSocketClosed); - obj.socket.on('error', function (e) { if (e.message && e.message.indexOf('sslv3 alert bad record mac') >= 0) { obj.xtlsMethod = 1 - obj.xtlsMethod; } }); - } - obj.socket.setNoDelay(true); // Disable nagle. We will encode each WSMAN request as a single send block and want to send it at once. This may help Intel AMT handle pipelining? - } else if (obj.mode==2 || obj.mode==3) { // CIRA and APF - if (obj.mode==2) { // CIRA + if ((obj.parent != null) && (obj.mode === 2) || (obj.mode === 3)) { // CIRA and APF + if (obj.mode == 2) { // CIRA var ciraconn = obj.parent.mpsserver.ciraConnections[obj.host]; obj.socket = obj.parent.mpsserver.SetupCiraChannel(ciraconn, obj.port); - } else { //APF + } else { // APF var apfconn = obj.parent.apfserver.apfConnections[obj.host]; obj.socket = obj.parent.apfserver.SetupCiraChannel(apfconn, obj.port); } - obj.socket.onData = function (ccon, data) { - obj.xxOnSocketData(data); - } - + obj.socket.onData = function (ccon, data) { obj.xxOnSocketData(data); } obj.socket.onStateChange = function (ccon, state) { if (state == 0) { try { @@ -222,6 +191,36 @@ var CreateWsmanComm = function (host, port, user, pass, tls, tlsoptions, parent, obj.xxOnSocketConnected(); } } + } else { + // Direct connection + if (obj.xtls != 1) { + // Connect without TLS + obj.socket = new obj.net.Socket(); + obj.socket.setEncoding('binary'); + obj.socket.setTimeout(6000); // Set socket idle timeout + obj.socket.on('data', obj.xxOnSocketData); + obj.socket.on('close', obj.xxOnSocketClosed); + obj.socket.on('timeout', obj.xxOnSocketClosed); + obj.socket.connect(obj.port, obj.host, obj.xxOnSocketConnected); + } else { + // Connect with TLS + var options = { ciphers: 'RSA+AES:!aNULL:!MD5:!DSS', secureOptions: obj.constants.SSL_OP_NO_SSLv2 | obj.constants.SSL_OP_NO_SSLv3 | obj.constants.SSL_OP_NO_COMPRESSION | obj.constants.SSL_OP_CIPHER_SERVER_PREFERENCE, rejectUnauthorized: false }; + if (obj.xtlsMethod != 0) { options.secureProtocol = 'TLSv1_method'; } + if (obj.xtlsoptions) { + if (obj.xtlsoptions.ca) options.ca = obj.xtlsoptions.ca; + if (obj.xtlsoptions.cert) options.cert = obj.xtlsoptions.cert; + if (obj.xtlsoptions.key) options.key = obj.xtlsoptions.key; + obj.xtlsoptions = options; + } + obj.socket = obj.tls.connect(obj.port, obj.host, obj.xtlsoptions, obj.xxOnSocketConnected); + obj.socket.setEncoding('binary'); + obj.socket.setTimeout(6000); // Set socket idle timeout + obj.socket.on('data', obj.xxOnSocketData); + obj.socket.on('close', obj.xxOnSocketClosed); + obj.socket.on('timeout', obj.xxOnSocketClosed); + obj.socket.on('error', function (e) { if (e.message && e.message.indexOf('sslv3 alert bad record mac') >= 0) { obj.xtlsMethod = 1 - obj.xtlsMethod; } }); + } + obj.socket.setNoDelay(true); // Disable nagle. We will encode each WSMAN request as a single send block and want to send it at once. This may help Intel AMT handle pipelining? } } diff --git a/amt/amt.js b/amt/amt.js index c5164b04..bf19a84d 100644 --- a/amt/amt.js +++ b/amt/amt.js @@ -733,7 +733,7 @@ function AmtStackCreateService(wsmanStack) { e = null; try { es = atob(responses.Body['EventRecords'][i]); - e = new Buffer(es); + e = Buffer.from(es); } catch (ex) { console.log(ex + " " + responses.Body['EventRecords'][i]) } diff --git a/amtscanner.js b/amtscanner.js index 81ac3a67..0da5f5f7 100644 --- a/amtscanner.js +++ b/amtscanner.js @@ -166,7 +166,7 @@ module.exports.CreateAmtScanner = function (parent) { if (err == null && docs.length > 0) { for (var i in docs) { var doc = docs[i], host = doc.host.toLowerCase(); - const ciraConnection = obj.parent.mpsserver.ciraConnections[doc._id]; + const ciraConnection = obj.parent.mpsserver ? obj.parent.mpsserver.ciraConnections[doc._id] : null; if ((host != '127.0.0.1') && (host != '::1') && (host.toLowerCase() != 'localhost') && (ciraConnection == null)) { var scaninfo = obj.scanTable[doc._id]; if (scaninfo == undefined) { @@ -371,7 +371,9 @@ module.exports.CreateAmtScanner = function (parent) { } else { // Connect using TLS, we will switch from default TLS to TLS1-only and back if we get a connection error to support older Intel AMT. if (scaninfo.tlsoption == null) { scaninfo.tlsoption = 0; } - client = obj.tls.connect(port, host, scaninfo.tlsoption == 1 ? { secureProtocol: 'TLSv1_method', rejectUnauthorized: false, ciphers: 'RSA+AES:!aNULL:!MD5:!DSS', secureOptions: constants.SSL_OP_NO_SSLv2 | constants.SSL_OP_NO_SSLv3 | constants.SSL_OP_NO_COMPRESSION | constants.SSL_OP_CIPHER_SERVER_PREFERENCE } : { rejectUnauthorized: false, ciphers: 'RSA+AES:!aNULL:!MD5:!DSS', secureOptions: constants.SSL_OP_NO_SSLv2 | constants.SSL_OP_NO_SSLv3 | constants.SSL_OP_NO_COMPRESSION | constants.SSL_OP_CIPHER_SERVER_PREFERENCE }, function () { this.write('GET / HTTP/1.1\r\nhost: ' + host + '\r\n\r\n'); }); + const tlsOptions = { rejectUnauthorized: false, ciphers: 'RSA+AES:!aNULL:!MD5:!DSS', secureOptions: constants.SSL_OP_NO_SSLv2 | constants.SSL_OP_NO_SSLv3 | constants.SSL_OP_NO_COMPRESSION | constants.SSL_OP_CIPHER_SERVER_PREFERENCE }; + if (scaninfo.tlsoption == 1) { tlsOptions.secureProtocol = 'TLSv1_method'; } + client = obj.tls.connect(port, host, tlsOptions, function () { this.write('GET / HTTP/1.1\r\nhost: ' + host + '\r\n\r\n'); }); } client.scaninfo = scaninfo; client.func = func; diff --git a/certoperations.js b/certoperations.js index 07354d98..d49726ba 100644 --- a/certoperations.js +++ b/certoperations.js @@ -200,12 +200,17 @@ module.exports.CertificateOperations = function (parent) { if (u.protocol == 'https:') { // Read the certificate from HTTPS if (hostname == null) { hostname = u.hostname; } - const tlssocket = obj.tls.connect((u.port ? u.port : 443), u.hostname, { servername: hostname, rejectUnauthorized: false }, function () { this.xxcert = this.getPeerCertificate(); this.end(); }); + parent.debug('cert', "loadCertificate() - Loading certificate from " + u.hostname + ":" + (u.port ? u.port : 443) + ", Hostname: " + hostname + "..."); + const tlssocket = obj.tls.connect((u.port ? u.port : 443), u.hostname, { servername: hostname, rejectUnauthorized: false }, function () { + this.xxcert = this.getPeerCertificate(); + parent.debug('cert', "loadCertificate() - TLS connected, " + ((this.xxcert != null) ? "got certificate." : "no certificate.")); + try { this.destroy(); } catch (ex) { } + this.xxfunc(this.xxurl, (this.xxcert == null)?null:(this.xxcert.raw.toString('binary')), hostname, this.xxtag); + }); tlssocket.xxurl = url; tlssocket.xxfunc = func; tlssocket.xxtag = tag; - tlssocket.on('end', function () { this.xxfunc(this.xxurl, this.xxcert.raw.toString('binary'), hostname, this.xxtag); }); - tlssocket.on('error', function () { this.xxfunc(this.xxurl, null, hostname, this.xxtag); }); + tlssocket.on('error', function (error) { try { this.destroy(); } catch (ex) { } parent.debug('cert', "loadCertificate() - TLS error: " + error); this.xxfunc(this.xxurl, null, hostname, this.xxtag); }); } else if (u.protocol == 'file:') { // Read the certificate from a file obj.fs.readFile(url.substring(7), 'utf8', function (err, data) { @@ -301,10 +306,8 @@ module.exports.CertificateOperations = function (parent) { var cert = obj.pki.createCertificate(); cert.publicKey = keys.publicKey; cert.serialNumber = String(Math.floor((Math.random() * 100000) + 1)); - cert.validity.notBefore = new Date(); - cert.validity.notBefore.setFullYear(cert.validity.notBefore.getFullYear() - 1); // Create a certificate that is valid one year before, to make sure out-of-sync clocks don"t reject this cert. - cert.validity.notAfter = new Date(); - cert.validity.notAfter.setFullYear(cert.validity.notAfter.getFullYear() + 30); + cert.validity.notBefore = new Date(2018, 0, 1); + cert.validity.notAfter = new Date(2049, 11, 31); if (addThumbPrintToName === true) { commonName += '-' + obj.pki.getPublicKeyFingerprint(cert.publicKey, { encoding: 'hex' }).substring(0, 6); } if (country == null) { country = "unknown"; } if (organization == null) { organization = "unknown"; } @@ -325,10 +328,8 @@ module.exports.CertificateOperations = function (parent) { var cert = obj.pki.createCertificate(); cert.publicKey = keys.publicKey; cert.serialNumber = String(Math.floor((Math.random() * 100000) + 1)); - cert.validity.notBefore = new Date(); - cert.validity.notBefore.setFullYear(cert.validity.notAfter.getFullYear() - 1); // Create a certificate that is valid one year before, to make sure out-of-sync clocks don"t reject this cert. - cert.validity.notAfter = new Date(); - cert.validity.notAfter.setFullYear(cert.validity.notAfter.getFullYear() + 30); + cert.validity.notBefore = new Date(2018, 0, 1); + cert.validity.notAfter = new Date(2049, 11, 31); if (addThumbPrintToName === true) { commonName += "-" + obj.pki.getPublicKeyFingerprint(cert.publicKey, { encoding: 'hex' }).substring(0, 6); } var attrs = [{ name: 'commonName', value: commonName }]; if (country != null) { attrs.push({ name: 'countryName', value: country }); } @@ -807,7 +808,7 @@ module.exports.CertificateOperations = function (parent) { accelerator.accid = acceleratorCreateCount; accelerator.on('message', function (message) { acceleratorMessage++; - this.x.func(this.x.tag, message); + if (this.x.func) { this.x.func(this.x.tag, message); } delete this.x; if (pendingAccelerator.length > 0) { this.send(this.x = pendingAccelerator.shift()); } else { freeAccelerators.push(this); } }); @@ -854,5 +855,24 @@ module.exports.CertificateOperations = function (parent) { } }; + // Perform any general operation + obj.acceleratorPerformOperation = function (operation, data, tag, func) { + if (acceleratorTotalCount <= 1) { + // No accelerators available + require(program).processMessage({ action: operation, data: data, tag: tag, func: func }); + } else { + var acc = obj.getAccelerator(); + if (acc == null) { + // Add to pending accelerator workload + acceleratorPerformSignaturePushFuncCall++; + pendingAccelerator.push({ action: operation, data: data, tag: tag, func: func }); + } else { + // Send to accelerator now + acceleratorPerformSignatureRunFuncCall++; + acc.send(acc.x = { action: operation, data: data, tag: tag, func: func }); + } + } + }; + return obj; }; diff --git a/common.js b/common.js index e279a256..a7e0aa5a 100644 --- a/common.js +++ b/common.js @@ -26,8 +26,8 @@ module.exports.ShortToStr = function (v) { return String.fromCharCode((v >> 8) & module.exports.ShortToStrX = function (v) { return String.fromCharCode(v & 0xFF, (v >> 8) & 0xFF); }; module.exports.IntToStr = function (v) { return String.fromCharCode((v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF); }; module.exports.IntToStrX = function (v) { return String.fromCharCode(v & 0xFF, (v >> 8) & 0xFF, (v >> 16) & 0xFF, (v >> 24) & 0xFF); }; -module.exports.MakeToArray = function (v) { if (!v || v == null || typeof v == "object") return v; return [v]; }; -module.exports.SplitArray = function (v) { return v.split(","); }; +module.exports.MakeToArray = function (v) { if (!v || v == null || typeof v == 'object') return v; return [v]; }; +module.exports.SplitArray = function (v) { return v.split(','); }; module.exports.Clone = function (v) { return JSON.parse(JSON.stringify(v)); }; module.exports.IsFilenameValid = (function () { var x1 = /^[^\\/:\*\?"<>\|]+$/, x2 = /^\./, x3 = /^(nul|prn|con|lpt[0-9]|com[0-9])(\.|$)/i; return function isFilenameValid(fname) { return module.exports.validateString(fname, 1, 4096) && x1.test(fname) && !x2.test(fname) && !x3.test(fname) && (fname[0] != '.'); }; })(); module.exports.makeFilename = function (v) { return v.split('\\').join('').split('/').join('').split(':').join('').split('*').join('').split('?').join('').split('"').join('').split('<').join('').split('>').join('').split('|').join('').split(' ').join('').split('\'').join(''); } @@ -122,8 +122,8 @@ module.exports.parseNameValueList = function (list) { // Compute the MD5 digest hash for a set of values module.exports.ComputeDigesthash = function (username, password, realm, method, path, qop, nonce, nc, cnonce) { - var ha1 = crypto.createHash('md5').update(username + ":" + realm + ":" + password).digest("hex"); - var ha2 = crypto.createHash('md5').update(method + ":" + path).digest("hex"); + var ha1 = crypto.createHash('md5').update(username + ":" + realm + ":" + password).digest('hex'); + var ha2 = crypto.createHash('md5').update(method + ":" + path).digest('hex'); return crypto.createHash('md5').update(ha1 + ":" + nonce + ":" + nc + ":" + cnonce + ":" + qop + ":" + ha2).digest("hex"); }; @@ -147,6 +147,7 @@ module.exports.escapeFieldName = function (name) { if ((name.indexOf('%') == -1) module.exports.unEscapeFieldName = function (name) { if (name.indexOf('%') == -1) return name; return name.split('%2E').join('.').split('%24').join('$').split('%25').join('%'); }; // Escape all links +module.exports.escapeLinksFieldNameEx = function (docx) { if (docx.links == null) { return docx; } var doc = Object.assign({}, docx); doc.links = Object.assign({}, doc.links); for (var i in doc.links) { var ue = module.exports.escapeFieldName(i); if (ue !== i) { doc.links[ue] = doc.links[i]; delete doc.links[i]; } } return doc; }; module.exports.escapeLinksFieldName = function (docx) { var doc = Object.assign({}, docx); if (doc.links != null) { doc.links = Object.assign({}, doc.links); for (var i in doc.links) { var ue = module.exports.escapeFieldName(i); if (ue !== i) { doc.links[ue] = doc.links[i]; delete doc.links[i]; } } } return doc; }; module.exports.unEscapeLinksFieldName = function (doc) { if (doc.links != null) { for (var j in doc.links) { var ue = module.exports.unEscapeFieldName(j); if (ue !== j) { doc.links[ue] = doc.links[j]; delete doc.links[j]; } } } return doc; }; //module.exports.escapeAllLinksFieldName = function (docs) { for (var i in docs) { module.exports.escapeLinksFieldName(docs[i]); } return docs; }; @@ -251,7 +252,7 @@ module.exports.translationsToJson = function(t) { for (var i in arr) { var names = [], el = arr[i], el2 = {}; for (var j in el) { names.push(j); } - names.sort(); + names.sort(function (a, b) { if (a == b) { return 0; } if (a == 'xloc') { return 1; } if (b == 'xloc') { return -1; } return a - b }); for (var j in names) { el2[names[j]] = el[names[j]]; } if (el2.xloc != null) { el2.xloc.sort(); } arr2.push(el2); diff --git a/db.js b/db.js index b79b87f6..9d6c0f33 100644 --- a/db.js +++ b/db.js @@ -28,9 +28,9 @@ module.exports.CreateDB = function (parent, func) { var obj = {}; var Datastore = null; - var expireEventsSeconds = (60 * 60 * 24 * 20); // By default, expire events after 20 days. (Seconds * Minutes * Hours * Days) - var expirePowerEventsSeconds = (60 * 60 * 24 * 10); // By default, expire power events after 10 days. (Seconds * Minutes * Hours * Days) - var expireServerStatsSeconds = (60 * 60 * 24 * 30); // By default, expire power events after 30 days. (Seconds * Minutes * Hours * Days) + var expireEventsSeconds = (60 * 60 * 24 * 20); // By default, expire events after 20 days (1728000). (Seconds * Minutes * Hours * Days) + var expirePowerEventsSeconds = (60 * 60 * 24 * 10); // By default, expire power events after 10 days (864000). (Seconds * Minutes * Hours * Days) + var expireServerStatsSeconds = (60 * 60 * 24 * 30); // By default, expire power events after 30 days (2592000). (Seconds * Minutes * Hours * Days) const common = require('./common.js'); obj.identifier = null; obj.dbKey = null; @@ -42,7 +42,8 @@ module.exports.CreateDB = function (parent, func) { // Check if the database unique identifier is present // This is used to check that in server peering mode, everyone is using the same database. obj.Get('DatabaseIdentifier', function (err, docs) { - if ((docs.length == 1) && (docs[0].value != null)) { + if (err != null) { parent.debug('db', 'ERROR (Get DatabaseIdentifier): ' + err); } + if ((err == null) && (docs.length == 1) && (docs[0].value != null)) { obj.identifier = docs[0].value; } else { obj.identifier = Buffer.from(require('crypto').randomBytes(48), 'binary').toString('hex'); @@ -52,8 +53,9 @@ module.exports.CreateDB = function (parent, func) { // Load database schema version and check if we need to update obj.Get('SchemaVersion', function (err, docs) { + if (err != null) { parent.debug('db', 'ERROR (Get SchemaVersion): ' + err); } var ver = 0; - if (docs && docs.length == 1) { ver = docs[0].value; } + if ((err == null) && (docs.length == 1)) { ver = docs[0].value; } if (ver == 1) { console.log('This is an unsupported beta 1 database, delete it to create a new one.'); process.exit(0); } // TODO: Any schema upgrades here... @@ -87,6 +89,7 @@ module.exports.CreateDB = function (parent, func) { // Remove all objects that have a "meshid" that no longer points to a valid mesh. obj.GetAllType('mesh', function (err, docs) { + if (err != null) { parent.debug('db', 'ERROR (GetAll mesh): ' + err); } var meshlist = []; if ((err == null) && (docs.length > 0)) { for (var i in docs) { meshlist.push(docs[i]._id); } } if ((obj.databaseType == 4) || (obj.databaseType == 5)) { @@ -102,7 +105,8 @@ module.exports.CreateDB = function (parent, func) { // Fix all of the creating & login to ticks by seconds, not milliseconds. obj.GetAllType('user', function (err, docs) { - if (err == null && docs.length > 0) { + if (err != null) { parent.debug('db', 'ERROR (GetAll user): ' + err); } + if ((err == null) && (docs.length > 0)) { for (var i in docs) { var fixed = false; @@ -182,14 +186,14 @@ module.exports.CreateDB = function (parent, func) { // MongoDB obj.file.aggregate([{ "$group": { _id: "$type", count: { $sum: 1 } } }]).toArray(function (err, docs) { var counters = {}, totalCount = 0; - for (var i in docs) { if (docs[i]._id != null) { counters[docs[i]._id] = docs[i].count; totalCount += docs[i].count; } } + if (err == null) { for (var i in docs) { if (docs[i]._id != null) { counters[docs[i]._id] = docs[i].count; totalCount += docs[i].count; } } } func(counters); }); } else if (obj.databaseType == 2) { // MongoJS obj.file.aggregate([{ "$group": { _id: "$type", count: { $sum: 1 } } }], function (err, docs) { var counters = {}, totalCount = 0; - for (var i in docs) { if (docs[i]._id != null) { counters[docs[i]._id] = docs[i].count; totalCount += docs[i].count; } } + if (err == null) { for (var i in docs) { if (docs[i]._id != null) { counters[docs[i]._id] = docs[i].count; totalCount += docs[i].count; } } } func(counters); }); } else if (obj.databaseType == 1) { @@ -219,13 +223,14 @@ module.exports.CreateDB = function (parent, func) { } // This is used to rate limit a number of operation per day. Returns a startValue each new days, but you can substract it and save the value in the db. - obj.getValueOfTheDay = function (id, startValue, func) { obj.Get(id, function (err, docs) { var date = new Date(), t = date.toLocaleDateString(); if (docs.length == 1) { var r = docs[0]; if (r.day == t) { func({ _id: id, value: r.value, day: t }); return; } } func({ _id: id, value: startValue, day: t }); }); }; + obj.getValueOfTheDay = function (id, startValue, func) { obj.Get(id, function (err, docs) { var date = new Date(), t = date.toLocaleDateString(); if ((err == null) && (docs.length == 1)) { var r = docs[0]; if (r.day == t) { func({ _id: id, value: r.value, day: t }); return; } } func({ _id: id, value: startValue, day: t }); }); }; obj.escapeBase64 = function escapeBase64(val) { return (val.replace(/\+/g, '@').replace(/\//g, '$')); } // Encrypt an database object obj.performRecordEncryptionRecode = function (func) { var count = 0; obj.GetAllType('user', function (err, docs) { + if (err != null) { parent.debug('db', 'ERROR (performRecordEncryptionRecode): ' + err); } if (err == null) { for (var i in docs) { count++; obj.Set(docs[i]); } } obj.GetAllType('node', function (err, docs) { if (err == null) { for (var i in docs) { count++; obj.Set(docs[i]); } } @@ -236,7 +241,7 @@ module.exports.CreateDB = function (parent, func) { // Encrypt an database object function performTypedRecordDecrypt(data) { - if ((obj.dbRecordsDecryptKey == null) || (typeof data != 'object')) return data; + if ((data == null) || (obj.dbRecordsDecryptKey == null) || (typeof data != 'object')) return data; for (var i in data) { if (data[i].type == 'user') { data[i] = performPartialRecordDecrypt(data[i]); @@ -335,7 +340,9 @@ module.exports.CreateDB = function (parent, func) { } //sqlDbQuery('DROP DATABASE MeshCentral', null, function (err, docs) { console.log('DROP'); }); return; sqlDbQuery('USE meshcentral', null, function (err, docs) { + if (err != null) { parent.debug('db', 'ERROR: USE meshcentral: ' + err); } if (err == null) { setupFunctions(func); } else { + parent.debug('db', 'Creating database...'); sqlDbBatchExec([ 'CREATE DATABASE meshcentral', // Main table @@ -364,7 +371,10 @@ module.exports.CreateDB = function (parent, func) { 'CREATE INDEX ndxsmbiosexpire ON meshcentral.smbios (expire)', // Plugins table 'CREATE TABLE meshcentral.plugin (id INT NOT NULL AUTO_INCREMENT, doc JSON, PRIMARY KEY(id), CHECK (json_valid(doc)))' - ], function (err) { /*if (err != null) { console.log(err); }*/ setupFunctions(func); }); + ], function (err) { + if (err != null) { parent.debug('db', 'BatchSetupDb: ' + err); } + setupFunctions(func); + }); } }); } else if (parent.args.mongodb) { @@ -373,6 +383,7 @@ module.exports.CreateDB = function (parent, func) { require('mongodb').MongoClient.connect(parent.args.mongodb, { useNewUrlParser: true, useUnifiedTopology: true }, function (err, client) { if (err != null) { console.log("Unable to connect to database: " + err); process.exit(); return; } Datastore = client; + parent.debug('db', 'Connected to MongoDB database...'); // Get the database name and setup the database client var dbname = 'meshcentral'; @@ -778,15 +789,31 @@ module.exports.CreateDB = function (parent, func) { // Database actions on the main collection (MariaDB or MySQL) obj.Set = function (value, func) { var extra = null, extraex = null; + value = common.escapeLinksFieldNameEx(value); if (value.meshid) { extra = value.meshid; } else if (value.email) { extra = 'email/' + value.email; } if ((value.type == 'node') && (value.intelamt != null) && (value.intelamt.uuid != null)) { extraex = 'uuid/' + value.intelamt.uuid; } sqlDbQuery('REPLACE INTO meshcentral.main VALUE (?, ?, ?, ?, ?, ?)', [value._id, (value.type ? value.type : null), ((value.domain != null) ? value.domain : null), extra, extraex, JSON.stringify(performTypedRecordEncrypt(value))], func); } - obj.Get = function (_id, func) { sqlDbQuery('SELECT doc FROM meshcentral.main WHERE id = ?', [_id], func); } + obj.Get = function (_id, func) { + sqlDbQuery('SELECT doc FROM meshcentral.main WHERE id = ?', [_id], function (err, docs) { + if ((docs != null) && (docs.length > 0) && (docs[0].links != null)) { docs[0] = common.unEscapeLinksFieldName(docs[0]); } + func(_id, func); + }); + } obj.GetAll = function (func) { sqlDbQuery('SELECT domain, doc FROM meshcentral.main', null, func); } obj.GetHash = function (id, func) { sqlDbQuery('SELECT doc FROM meshcentral.main WHERE id = ?', [id], func); } - obj.GetAllTypeNoTypeField = function (type, domain, func) { sqlDbQuery('SELECT doc FROM meshcentral.main WHERE type = ? AND domain = ?', [type, domain], function (err, docs) { for (var i in docs) { delete docs[i].type } func(err, docs); }); }; - obj.GetAllTypeNoTypeFieldMeshFiltered = function (meshes, domain, type, id, func) { if (id && (id != '')) { sqlDbQuery('SELECT doc FROM meshcentral.main WHERE id = ? AND type = ? AND domain = ? AND extra IN (?)', [id, type, domain, meshes], function (err, docs) { for (var i in docs) { delete docs[i].type } func(err, docs); }); } else { sqlDbQuery('SELECT doc FROM meshcentral.main WHERE type = ? AND domain = ? AND extra IN (?)', [type, domain, meshes], function (err, docs) { for (var i in docs) { delete docs[i].type } func(err, docs); }); } }; + obj.GetAllTypeNoTypeField = function (type, domain, func) { sqlDbQuery('SELECT doc FROM meshcentral.main WHERE type = ? AND domain = ?', [type, domain], function (err, docs) { if (err == null) { for (var i in docs) { delete docs[i].type } } func(err, docs); }); }; + obj.GetAllTypeNoTypeFieldMeshFiltered = function (meshes, extrasids, domain, type, id, func) { + if (id && (id != '')) { + sqlDbQuery('SELECT doc FROM meshcentral.main WHERE id = ? AND type = ? AND domain = ? AND extra IN (?)', [id, type, domain, meshes], function (err, docs) { if (err == null) { for (var i in docs) { delete docs[i].type } } func(err, docs); }); + } else { + if (extrasids == null) { + sqlDbQuery('SELECT doc FROM meshcentral.main WHERE type = ? AND domain = ? AND extra IN (?)', [type, domain, meshes], function (err, docs) { if (err == null) { for (var i in docs) { delete docs[i].type } } func(err, docs); }); + } else { + sqlDbQuery('SELECT doc FROM meshcentral.main WHERE type = ? AND domain = ? AND (extra IN (?) OR id IN (?))', [type, domain, meshes, extrasids], function (err, docs) { if (err == null) { for (var i in docs) { delete docs[i].type } } func(err, docs); }); + } + } + }; obj.GetAllType = function (type, func) { sqlDbQuery('SELECT doc FROM meshcentral.main WHERE type = ?', [type], func); } obj.GetAllIdsOfType = function (ids, domain, type, func) { sqlDbQuery('SELECT doc FROM meshcentral.main WHERE id IN (?) AND domain = ? AND type = ?', [ids, domain, type], func); } obj.GetUserWithEmail = function (domain, email, func) { sqlDbQuery('SELECT doc FROM meshcentral.main WHERE domain = ? AND extra = ?', [domain, 'email/' + email], func); } @@ -796,11 +823,11 @@ module.exports.CreateDB = function (parent, func) { obj.RemoveAllOfType = function (type, func) { sqlDbQuery('DELETE FROM meshcentral.main WHERE type = ?', [type], func); }; obj.InsertMany = function (data, func) { var pendingOps = 0; for (var i in data) { pendingOps++; obj.Set(data[i], function () { if (--pendingOps == 0) { func(); } }); } }; obj.RemoveMeshDocuments = function (id) { sqlDbQuery('DELETE FROM meshcentral.main WHERE extra = ?', [id], function () { sqlDbQuery('DELETE FROM meshcentral.main WHERE id = ?', ['nt' + id], func); } ); }; - obj.MakeSiteAdmin = function (username, domain) { obj.Get('user/' + domain + '/' + username, function (err, docs) { if (docs.length == 1) { docs[0].siteadmin = 0xFFFFFFFF; obj.Set(docs[0]); } }); }; + obj.MakeSiteAdmin = function (username, domain) { obj.Get('user/' + domain + '/' + username, function (err, docs) { if ((err == null) && (docs.length == 1)) { docs[0].siteadmin = 0xFFFFFFFF; obj.Set(docs[0]); } }); }; obj.DeleteDomain = function (domain, func) { sqlDbQuery('DELETE FROM meshcentral.main WHERE domain = ?', [domain], func); }; obj.SetUser = function (user) { if (user.subscriptions != null) { var u = Clone(user); if (u.subscriptions) { delete u.subscriptions; } obj.Set(u); } else { obj.Set(user); } }; obj.dispose = function () { for (var x in obj) { if (obj[x].close) { obj[x].close(); } delete obj[x]; } }; - obj.getLocalAmtNodes = function (func) { sqlDbQuery('SELECT doc FROM meshcentral.main WHERE (type = "node") AND (extraex IS NOT NULL)', null, function (err, docs) { var r = []; for (var i in docs) { if (docs[i].host != null) { r.push(docs[i]); } } func(err, r); }); }; + obj.getLocalAmtNodes = function (func) { sqlDbQuery('SELECT doc FROM meshcentral.main WHERE (type = "node") AND (extraex IS NOT NULL)', null, function (err, docs) { var r = []; if (err == null) { for (var i in docs) { if (docs[i].host != null) { r.push(docs[i]); } } } func(err, r); }); }; obj.getAmtUuidMeshNode = function (meshid, uuid, func) { sqlDbQuery('SELECT doc FROM meshcentral.main WHERE meshid = ? AND extraex = ?', [meshid, 'uuid/' + uuid], func); }; obj.getAmtUuidNode = function (uuid, func) { sqlDbQuery('SELECT doc FROM meshcentral.main WHERE type = "node" AND extraex = ?', ['uuid/' + uuid], func); }; obj.isMaxType = function (max, type, domainid, func) { if (max == null) { func(false); } else { sqlDbExec('SELECT COUNT(id) FROM meshcentral.main WHERE domain = ? AND type = ?', [domainid, type], function (err, response) { func((response['COUNT(id)'] == null) || (response['COUNT(id)'] > max), response['COUNT(id)']) }); } } @@ -904,12 +931,12 @@ module.exports.CreateDB = function (parent, func) { obj.getPlugins = function (func) { sqlDbQuery('SELECT doc FROM meshcentral.plugin', null, func); }; // Get all plugins obj.getPlugin = function (id, func) { sqlDbQuery('SELECT doc FROM meshcentral.plugin WHERE id = ?', [id], func); }; // Get plugin obj.deletePlugin = function (id, func) { sqlDbQuery('DELETE FROM meshcentral.plugin WHERE id = ?', [id], func); }; // Delete plugin - obj.setPluginStatus = function (id, status, func) { obj.getPlugin(id, function (err, docs) { if (docs.length == 1) { docs[0].status = status; obj.updatePlugin(id, docs[0], func); } }); }; + obj.setPluginStatus = function (id, status, func) { obj.getPlugin(id, function (err, docs) { if ((err == null) && (docs.length == 1)) { docs[0].status = status; obj.updatePlugin(id, docs[0], func); } }); }; obj.updatePlugin = function (id, args, func) { delete args._id; sqlDbQuery('REPLACE INTO meshcentral.plugin VALUE (?, ?)', [id, JSON.stringify(args)], func); }; } } else if (obj.databaseType == 3) { // Database actions on the main collection (MongoDB) - obj.Set = function (data, func) { obj.file.replaceOne({ _id: data._id }, performTypedRecordEncrypt(data), { upsert: true }, func); }; + obj.Set = function (data, func) { data = common.escapeLinksFieldNameEx(data); obj.file.replaceOne({ _id: data._id }, performTypedRecordEncrypt(data), { upsert: true }, func); }; obj.Get = function (id, func) { if (arguments.length > 2) { var parms = [func]; @@ -921,15 +948,31 @@ module.exports.CreateDB = function (parent, func) { userCallback.apply(obj, _func2.userArgs); }; func2.userArgs = parms; - obj.file.find({ _id: id }).toArray(function (err, docs) { func2(err, performTypedRecordDecrypt(docs)); }); + obj.file.find({ _id: id }).toArray(function (err, docs) { + if ((docs != null) && (docs.length > 0) && (docs[0].links != null)) { docs[0] = common.unEscapeLinksFieldName(docs[0]); } + func2(err, performTypedRecordDecrypt(docs)); + }); } else { - obj.file.find({ _id: id }).toArray(function (err, docs) { func(err, performTypedRecordDecrypt(docs)); }); + obj.file.find({ _id: id }).toArray(function (err, docs) { + if ((docs != null) && (docs.length > 0) && (docs[0].links != null)) { docs[0] = common.unEscapeLinksFieldName(docs[0]); } + func(err, performTypedRecordDecrypt(docs)); + }); } }; obj.GetAll = function (func) { obj.file.find({}).toArray(function (err, docs) { func(err, performTypedRecordDecrypt(docs)); }); }; obj.GetHash = function (id, func) { obj.file.find({ _id: id }).project({ _id: 0, hash: 1 }).toArray(function (err, docs) { func(err, performTypedRecordDecrypt(docs)); }); }; obj.GetAllTypeNoTypeField = function (type, domain, func) { obj.file.find({ type: type, domain: domain }).project({ type: 0 }).toArray(function (err, docs) { func(err, performTypedRecordDecrypt(docs)); }); }; - obj.GetAllTypeNoTypeFieldMeshFiltered = function (meshes, domain, type, id, func) { var x = { type: type, domain: domain, meshid: { $in: meshes } }; if (id) { x._id = id; } obj.file.find(x, { type: 0 }).toArray(function (err, docs) { func(err, performTypedRecordDecrypt(docs)); }); }; + obj.GetAllTypeNoTypeFieldMeshFiltered = function (meshes, extrasids, domain, type, id, func) { + if (extrasids == null) { + var x = { type: type, domain: domain, meshid: { $in: meshes } }; + if (id) { x._id = id; } + obj.file.find(x, { type: 0 }).toArray(function (err, docs) { func(err, performTypedRecordDecrypt(docs)); }); + } else { + var x = { type: type, domain: domain, $or: [ { meshid: { $in: meshes } }, { _id: { $in: extrasids } } ] }; + if (id) { x._id = id; } + obj.file.find(x, { type: 0 }).toArray(function (err, docs) { func(err, performTypedRecordDecrypt(docs)); }); + } + }; obj.GetAllType = function (type, func) { obj.file.find({ type: type }).toArray(function (err, docs) { func(err, performTypedRecordDecrypt(docs)); }); }; obj.GetAllIdsOfType = function (ids, domain, type, func) { obj.file.find({ type: type, domain: domain, _id: { $in: ids } }).toArray(function (err, docs) { func(err, performTypedRecordDecrypt(docs)); }); }; obj.GetUserWithEmail = function (domain, email, func) { obj.file.find({ type: 'user', domain: domain, email: email }).project({ type: 0 }).toArray(function (err, docs) { func(err, performTypedRecordDecrypt(docs)); }); }; @@ -939,7 +982,7 @@ module.exports.CreateDB = function (parent, func) { obj.RemoveAllOfType = function (type, func) { obj.file.deleteMany({ type: type }, { multi: true }, func); }; obj.InsertMany = function (data, func) { obj.file.insertMany(data, func); }; obj.RemoveMeshDocuments = function (id) { obj.file.deleteMany({ meshid: id }, { multi: true }); obj.file.deleteOne({ _id: 'nt' + id }); }; - obj.MakeSiteAdmin = function (username, domain) { obj.Get('user/' + domain + '/' + username, function (err, docs) { if (docs.length == 1) { docs[0].siteadmin = 0xFFFFFFFF; obj.Set(docs[0]); } }); }; + obj.MakeSiteAdmin = function (username, domain) { obj.Get('user/' + domain + '/' + username, function (err, docs) { if ((err == null) && (docs.length == 1)) { docs[0].siteadmin = 0xFFFFFFFF; obj.Set(docs[0]); } }); }; obj.DeleteDomain = function (domain, func) { obj.file.deleteMany({ domain: domain }, { multi: true }, func); }; obj.SetUser = function (user) { if (user.subscriptions != null) { var u = Clone(user); if (u.subscriptions) { delete u.subscriptions; } obj.Set(u); } else { obj.Set(user); } }; obj.dispose = function () { for (var x in obj) { if (obj[x].close) { obj[x].close(); } delete obj[x]; } }; @@ -1041,7 +1084,7 @@ module.exports.CreateDB = function (parent, func) { } else { // Database actions on the main collection (NeDB and MongoJS) - obj.Set = function (data, func) { var xdata = performTypedRecordEncrypt(data); obj.file.update({ _id: xdata._id }, xdata, { upsert: true }, func); }; + obj.Set = function (data, func) { data = common.escapeLinksFieldNameEx(data); var xdata = performTypedRecordEncrypt(data); obj.file.update({ _id: xdata._id }, xdata, { upsert: true }, func); }; obj.Get = function (id, func) { if (arguments.length > 2) { var parms = [func]; @@ -1053,15 +1096,36 @@ module.exports.CreateDB = function (parent, func) { userCallback.apply(obj, _func2.userArgs); }; func2.userArgs = parms; - obj.file.find({ _id: id }, function (err, docs) { func2(err, performTypedRecordDecrypt(docs)); }); + obj.file.find({ _id: id }, function (err, docs) { + if ((docs != null) && (docs.length > 0) && (docs[0].links != null)) { docs[0] = common.unEscapeLinksFieldName(docs[0]); } + func2(err, performTypedRecordDecrypt(docs)); + }); } else { - obj.file.find({ _id: id }, function (err, docs) { func(err, performTypedRecordDecrypt(docs)); }); + obj.file.find({ _id: id }, function (err, docs) { + if ((docs != null) && (docs.length > 0) && (docs[0].links != null)) { docs[0] = common.unEscapeLinksFieldName(docs[0]); } + func(err, performTypedRecordDecrypt(docs)); + }); } }; obj.GetAll = function (func) { obj.file.find({}, function (err, docs) { func(err, performTypedRecordDecrypt(docs)); }); }; obj.GetHash = function (id, func) { obj.file.find({ _id: id }, { _id: 0, hash: 1 }, func); }; obj.GetAllTypeNoTypeField = function (type, domain, func) { obj.file.find({ type: type, domain: domain }, { type: 0 }, function (err, docs) { func(err, performTypedRecordDecrypt(docs)); }); }; - obj.GetAllTypeNoTypeFieldMeshFiltered = function (meshes, domain, type, id, func) { var x = { type: type, domain: domain, meshid: { $in: meshes } }; if (id) { x._id = id; } obj.file.find(x, { type: 0 }, function (err, docs) { func(err, performTypedRecordDecrypt(docs)); }); }; + //obj.GetAllTypeNoTypeFieldMeshFiltered = function (meshes, domain, type, id, func) { + //var x = { type: type, domain: domain, meshid: { $in: meshes } }; + //if (id) { x._id = id; } + //obj.file.find(x, { type: 0 }, function (err, docs) { func(err, performTypedRecordDecrypt(docs)); }); + //}; + obj.GetAllTypeNoTypeFieldMeshFiltered = function (meshes, extrasids, domain, type, id, func) { + if (extrasids == null) { + var x = { type: type, domain: domain, meshid: { $in: meshes } }; + if (id) { x._id = id; } + obj.file.find(x, { type: 0 }, function (err, docs) { func(err, performTypedRecordDecrypt(docs)); }); + } else { + var x = { type: type, domain: domain, $or: [{ meshid: { $in: meshes } }, { _id: { $in: extrasids } }] }; + if (id) { x._id = id; } + obj.file.find(x, { type: 0 }, function (err, docs) { func(err, performTypedRecordDecrypt(docs)); }); + } + }; obj.GetAllType = function (type, func) { obj.file.find({ type: type }, function (err, docs) { func(err, performTypedRecordDecrypt(docs)); }); }; obj.GetAllIdsOfType = function (ids, domain, type, func) { obj.file.find({ type: type, domain: domain, _id: { $in: ids } }, function (err, docs) { func(err, performTypedRecordDecrypt(docs)); }); }; obj.GetUserWithEmail = function (domain, email, func) { obj.file.find({ type: 'user', domain: domain, email: email }, { type: 0 }, function (err, docs) { func(err, performTypedRecordDecrypt(docs)); }); }; @@ -1071,7 +1135,7 @@ module.exports.CreateDB = function (parent, func) { obj.RemoveAllOfType = function (type, func) { obj.file.remove({ type: type }, { multi: true }, func); }; obj.InsertMany = function (data, func) { obj.file.insert(data, func); }; obj.RemoveMeshDocuments = function (id) { obj.file.remove({ meshid: id }, { multi: true }); obj.file.remove({ _id: 'nt' + id }); }; - obj.MakeSiteAdmin = function (username, domain) { obj.Get('user/' + domain + '/' + username, function (err, docs) { if (docs.length == 1) { docs[0].siteadmin = 0xFFFFFFFF; obj.Set(docs[0]); } }); }; + obj.MakeSiteAdmin = function (username, domain) { obj.Get('user/' + domain + '/' + username, function (err, docs) { if ((err == null) && (docs.length == 1)) { docs[0].siteadmin = 0xFFFFFFFF; obj.Set(docs[0]); } }); }; obj.DeleteDomain = function (domain, func) { obj.file.remove({ domain: domain }, { multi: true }, func); }; obj.SetUser = function (user) { if (user.subscriptions != null) { var u = Clone(user); if (u.subscriptions) { delete u.subscriptions; } obj.Set(u); } else { obj.Set(user); } }; obj.dispose = function () { for (var x in obj) { if (obj[x].close) { obj[x].close(); } delete obj[x]; } }; @@ -1236,7 +1300,7 @@ module.exports.CreateDB = function (parent, func) { var mongoDumpPath = 'mongodump'; if (parent.config.settings.autobackup && parent.config.settings.autobackup.mongodumppath) { mongoDumpPath = parent.config.settings.autobackup.mongodumppath; } const child_process = require('child_process'); - const cmd = '\"' + mongoDumpPath + '\" --db=\"' + dbname + '\" --archive=\"' + newBackupPath + '.archive\"'; + var cmd = '\"' + mongoDumpPath + '\" --db=\"' + dbname + '\" --archive=\"' + newBackupPath + '.archive\"'; if (dburl) { cmd = '\"' + mongoDumpPath + '\" --uri=\"' + dburl + '\" --archive=\"' + newBackupPath + '.archive\"'; } var backupProcess = child_process.exec(cmd, { cwd: backupPath }, function (error, stdout, stderr) { try { @@ -1312,6 +1376,7 @@ module.exports.CreateDB = function (parent, func) { // Called when a node has changed function dbNodeChange(nodeChange, added) { + common.unEscapeLinksFieldName(nodeChange.fullDocument); const node = nodeChange.fullDocument; if (node.intelamt && node.intelamt.pass) { delete node.intelamt.pass; } // Remove the Intel AMT password before eventing this. parent.DispatchEvent(['*', node.meshid], obj, { etype: 'node', action: (added ? 'addnode' : 'changenode'), node: node, nodeid: node._id, domain: node.domain, nolog: 1 }); diff --git a/emails/account-check.html b/emails/account-check.html new file mode 100644 index 00000000..c04a5bcd --- /dev/null +++ b/emails/account-check.html @@ -0,0 +1,15 @@ +
[[[SERVERNAME]]] - Email Verification
+
+ + + + +
+ [[[SERVERNAME]]] - Verification +
+

Hi [[[USERNAME]]], [[[SERVERNAME]]] is requesting email verification, click on the following link to complete the process.

+

+ Click here to verify your e-mail address. +

+ If you did not initiate this request, please ignore this mail. +
\ No newline at end of file diff --git a/emails/account-check.txt b/emails/account-check.txt new file mode 100644 index 00000000..b90c0d2f --- /dev/null +++ b/emails/account-check.txt @@ -0,0 +1,6 @@ +[[[SERVERNAME]]] - Email Verification +Hi [[[USERNAME]]], [[[SERVERNAME]]] ([[[SERVERURL]]]) is performing an e-mail verification. Nagivate to the following link to complete the process: +~ +~[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]] +~ +If you did not initiate this request, please ignore this mail. \ No newline at end of file diff --git a/emails/account-invite.html b/emails/account-invite.html new file mode 100644 index 00000000..be5ca419 --- /dev/null +++ b/emails/account-invite.html @@ -0,0 +1,19 @@ +
[[[SERVERNAME]]] - Account Invitation
+
+ + + + +
+ [[[SERVERNAME]]] - Account Invitation +
+

An account was created for you on server [[[SERVERNAME]]], you can access it now with:

+

+    Username: [[[ACCOUNTNAME]]]
+    Password: [[[PASSWORD]]] +

+ Best regards, +
+ [[[USERNAME]]] +
+
\ No newline at end of file diff --git a/emails/account-invite.txt b/emails/account-invite.txt new file mode 100644 index 00000000..3061a670 --- /dev/null +++ b/emails/account-invite.txt @@ -0,0 +1,5 @@ +[[[SERVERNAME]]] - Account Invitation +An account was created for you on server [[[SERVERNAME]]] ([[[SERVERURL]]]/), you can access it now with username "[[[ACCOUNTNAME]]]" and password "[[[PASSWORD]]]". +~ +Best regards, +~[[[USERNAME]]] \ No newline at end of file diff --git a/emails/account-login.html b/emails/account-login.html new file mode 100644 index 00000000..6b323eb9 --- /dev/null +++ b/emails/account-login.html @@ -0,0 +1,12 @@ +
[[[SERVERNAME]]] - Account Login
+
+ + + + +
+ [[[SERVERNAME]]] - Account Login +
+

Your login token is: [[[TOKEN]]]

+

This token can only be used once and is valid for 5 minutes.

+
\ No newline at end of file diff --git a/emails/account-login.txt b/emails/account-login.txt new file mode 100644 index 00000000..5cf6151e --- /dev/null +++ b/emails/account-login.txt @@ -0,0 +1,4 @@ +[[[SERVERNAME]]] - Account Login +Your login token is: [[[TOKEN]]] +~ +This token can only be used once and is valid for 5 minutes. \ No newline at end of file diff --git a/emails/account-reset.html b/emails/account-reset.html new file mode 100644 index 00000000..df133a67 --- /dev/null +++ b/emails/account-reset.html @@ -0,0 +1,15 @@ +
[[[SERVERNAME]]] - Account Reset
+
+ + + + +
+ [[[SERVERNAME]]] - Verification +
+

Hi [[[USERNAME]]], [[[SERVERNAME]]] is requesting an account password reset, click on the following link to complete the process.

+

+ Click here to reset your account password. +

+ If you did not initiate this request, please ignore this mail. +
\ No newline at end of file diff --git a/emails/account-reset.txt b/emails/account-reset.txt new file mode 100644 index 00000000..8960967d --- /dev/null +++ b/emails/account-reset.txt @@ -0,0 +1,6 @@ +[[[SERVERNAME]]] - Account Reset +Hi [[[USERNAME]]], [[[SERVERNAME]]] ([[[SERVERURL]]]) is requesting an account password reset. Nagivate to the following link to complete the process: +~ +~[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]] +~ +If you did not initiate this request, please ignore this mail. \ No newline at end of file diff --git a/emails/mesh-invite.html b/emails/mesh-invite.html new file mode 100644 index 00000000..a50f42c5 --- /dev/null +++ b/emails/mesh-invite.html @@ -0,0 +1,42 @@ +
[[[SERVERNAME]]] - Invitation
+
+ + + + +
+ [[[SERVERNAME]]] - Agent Installation +
+ +

+ Hello [[[NAME]]], +

+
+

User [[[USERNAME]]] on server [[[SERVERNAME]]] is requesting you to install software to start a remote control session.

+ +

+ Message: [[[MSG]]] +

+
+ +

+ Click here to download the MeshAgent for Windows. +

+
+ +

Click here to download the MeshAgent for Apple OSX.

+
+ +

+ For Linux, cut & paste the following in a terminal to install the agent:
+

wget -q "[[[SERVERURL]]]/meshagents?script=1" --no-check-certificate -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh [[[SERVERURL]]] \'[[[MESHIDHEX]]]\'
+

+
+ +

+ To install the software, click here and follow the instructions. +

+
+

If you did not initiate this request, please ignore this mail.

+ Best regards,
[[[USERNAME]]]
+
\ No newline at end of file diff --git a/emails/mesh-invite.txt b/emails/mesh-invite.txt new file mode 100644 index 00000000..ac8ad99b --- /dev/null +++ b/emails/mesh-invite.txt @@ -0,0 +1,35 @@ +[[[SERVERNAME]]] - Invitation +~ +Hello [[[NAME]]], +~ +User [[[USERNAME]]] on server [[[SERVERNAME]]] ([[[SERVERURL]]]/) is requesting you install software to start the remote control session. +~ +~ +Message: [[[MSG]]] +~ +~ +~ +For Windows, nagivate to the following link to complete the process: +~ +~[[[SERVERURL]]]/meshagents?id=3&meshid=[[[MESHIDHEX]]]&tag=mailto:[[[EMAIL]]]&installflags=[[[INSTALLFLAGS]]] +~ +~ +~ +For Apple OSX, nagivate to the following link to complete the process: +~ +~[[[SERVERURL]]]/meshagents?id=16&meshid=[[[MESHIDHEX]]]&tag=mailto:[[[EMAIL]]]&installflags=[[[INSTALLFLAGS]]] +~ +~ +~ +For Linux, cut & paste the following in a terminal to install the agent: +~ +~wget -q "[[[SERVERURL]]]/meshagents?script=1" --no-check-certificate -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh [[[SERVERURL]]] '[[[MESHIDHEX]]]' +~ +~ +~ +To install the software, navigate to [[[SERVERURL]]][[[LINKURL]]] and follow the instructions. +~ +If you did not initiate this request, please ignore this mail. +~ +Best regards, +~[[[USERNAME]]] \ No newline at end of file diff --git a/emails/translations/account-check_cs.html b/emails/translations/account-check_cs.html new file mode 100644 index 00000000..1a5d3267 --- /dev/null +++ b/emails/translations/account-check_cs.html @@ -0,0 +1,15 @@ +
[[[SERVERNAME]]] - Ověření e-mailem
+
+ + + + +
+ [[[SERVERNAME]]] - Ověření +
+

Ahoj [[[USERNAME]]], [[[SERVERNAME]]] požaduje ověření e-mailem a dokončete proces kliknutím na následující odkaz.

+

+ Kliknutím sem ověřte svou e-mailovou adresu. +

+ Pokud jste tento požadavek nezačali, ignorujte tento e-mail. +
\ No newline at end of file diff --git a/emails/translations/account-check_cs.txt b/emails/translations/account-check_cs.txt new file mode 100644 index 00000000..3079684a --- /dev/null +++ b/emails/translations/account-check_cs.txt @@ -0,0 +1,6 @@ +[[[SERVERNAME]]] - Ověření e-mailem +Ahoj [[[USERNAME]]], [[[SERVERNAME]]] ([[[SERVERURL]]]) provádí ověření e-mailem. Chcete-li proces dokončit, přejděte na následující odkaz: +~ +~[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]] +~ +Pokud jste tento požadavek nezačali, ignorujte tento e-mail. \ No newline at end of file diff --git a/emails/translations/account-check_de.html b/emails/translations/account-check_de.html new file mode 100644 index 00000000..f4a47314 --- /dev/null +++ b/emails/translations/account-check_de.html @@ -0,0 +1,15 @@ +
[[[SERVERNAME]]] - E-Mail-Überprüfung
+
+ + + + +
+ [[[SERVERNAME]]] - Überprüfung +
+

Hallo [[[USERNAME]]], [[[SERVERNAME]]] Wenn Sie eine E-Mail-Bestätigung anfordern, klicken Sie auf den folgenden Link, um den Vorgang abzuschließen.

+

+ Klicken Sie hier, um Ihre E-Mail-Adresse zu bestätigen. +

+ Wenn Sie diese Anfrage nicht initiiert haben, ignorieren Sie diese Mail bitte. +
\ No newline at end of file diff --git a/emails/translations/account-check_de.txt b/emails/translations/account-check_de.txt new file mode 100644 index 00000000..990892ef --- /dev/null +++ b/emails/translations/account-check_de.txt @@ -0,0 +1,6 @@ +[[[SERVERNAME]]] - E-Mail-Überprüfung +Hallo [[[USERNAME]]], [[[SERVERNAME]]] ([[[SERVERURL]]]) führt eine E-Mail-Überprüfung durch. Klicken Sie auf den folgenden Link, um den Vorgang abzuschließen: +~ +~[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]] +~ +Wenn Sie diese Anfrage nicht initiiert haben, ignorieren Sie diese Mail bitte. \ No newline at end of file diff --git a/emails/translations/account-check_es.html b/emails/translations/account-check_es.html new file mode 100644 index 00000000..3b9b08f4 --- /dev/null +++ b/emails/translations/account-check_es.html @@ -0,0 +1,15 @@ +
[[[SERVERNAME]]] - Email Verification
+
+ + + + +
+ [[[SERVERNAME]]] - Verification +
+

Hi [[[USERNAME]]], [[[SERVERNAME]]] is requesting email verification, click on the following link to complete the process.

+

+ Click here to verify your e-mail address. +

+ If you did not initiate this request, please ignore this mail. +
\ No newline at end of file diff --git a/emails/translations/account-check_es.txt b/emails/translations/account-check_es.txt new file mode 100644 index 00000000..b90c0d2f --- /dev/null +++ b/emails/translations/account-check_es.txt @@ -0,0 +1,6 @@ +[[[SERVERNAME]]] - Email Verification +Hi [[[USERNAME]]], [[[SERVERNAME]]] ([[[SERVERURL]]]) is performing an e-mail verification. Nagivate to the following link to complete the process: +~ +~[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]] +~ +If you did not initiate this request, please ignore this mail. \ No newline at end of file diff --git a/emails/translations/account-check_fr.html b/emails/translations/account-check_fr.html new file mode 100644 index 00000000..25d6da9a --- /dev/null +++ b/emails/translations/account-check_fr.html @@ -0,0 +1,15 @@ +
[[[SERVERNAME]]] - Vérification E-mail
+
+ + + + +
+ [[[SERVERNAME]]] - Vérification +
+

Bonjour [[[USERNAME]]], [[[SERVERNAME]]] demande une vérification par e-mail, cliquez sur le lien suivant pour terminer le processus.

+

+ Cliquez ici pour vérifier votre adresse e-mail. +

+ Si vous n'avez pas initié cette demande, veuillez ignorer ce courrier. +
\ No newline at end of file diff --git a/emails/translations/account-check_fr.txt b/emails/translations/account-check_fr.txt new file mode 100644 index 00000000..ec4f641e --- /dev/null +++ b/emails/translations/account-check_fr.txt @@ -0,0 +1,6 @@ +[[[SERVERNAME]]] - Vérification E-mail +Bonjour [[[USERNAME]]], [[[SERVERNAME]]] ([[[SERVERURL]]]) effectue une vérification par e-mail. Accédez au lien suivant pour terminer le processus: +~ +~[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]] +~ +Si vous n'avez pas initié cette demande, veuillez ignorer ce courrier. \ No newline at end of file diff --git a/emails/translations/account-check_hi.html b/emails/translations/account-check_hi.html new file mode 100644 index 00000000..3b9b08f4 --- /dev/null +++ b/emails/translations/account-check_hi.html @@ -0,0 +1,15 @@ +
[[[SERVERNAME]]] - Email Verification
+
+ + + + +
+ [[[SERVERNAME]]] - Verification +
+

Hi [[[USERNAME]]], [[[SERVERNAME]]] is requesting email verification, click on the following link to complete the process.

+

+ Click here to verify your e-mail address. +

+ If you did not initiate this request, please ignore this mail. +
\ No newline at end of file diff --git a/emails/translations/account-check_hi.txt b/emails/translations/account-check_hi.txt new file mode 100644 index 00000000..b90c0d2f --- /dev/null +++ b/emails/translations/account-check_hi.txt @@ -0,0 +1,6 @@ +[[[SERVERNAME]]] - Email Verification +Hi [[[USERNAME]]], [[[SERVERNAME]]] ([[[SERVERURL]]]) is performing an e-mail verification. Nagivate to the following link to complete the process: +~ +~[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]] +~ +If you did not initiate this request, please ignore this mail. \ No newline at end of file diff --git a/emails/translations/account-check_ja.html b/emails/translations/account-check_ja.html new file mode 100644 index 00000000..ac37269f --- /dev/null +++ b/emails/translations/account-check_ja.html @@ -0,0 +1,15 @@ +
[[[SERVERNAME]]]-メールの確認
+
+ + + + +
+ [[[SERVERNAME]]]-確認 +
+

[[[USERNAME]]]様 [[[SERVERNAME]]] がメールの確認をリクエストしている場合は、次のリンクをクリックしてプロセスを完了してください。

+

+ ここをクリックして、電子メールアドレスを確認してください。 +

+ このリクエストを開始していない場合は、このメールを無視してください。 +
\ No newline at end of file diff --git a/emails/translations/account-check_ja.txt b/emails/translations/account-check_ja.txt new file mode 100644 index 00000000..135bcbab --- /dev/null +++ b/emails/translations/account-check_ja.txt @@ -0,0 +1,6 @@ +[[[SERVERNAME]]]-メールの確認 +こんにちは[[[USERNAME]]]、[[[SERVERNAME]]]([[[SERVERURL]]])は電子メールの検証を実行しています。プロセスを完了するには、次のリンクに移動します。 +~ +~[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]] +~ +このリクエストを開始していない場合は、このメールを無視してください。 \ No newline at end of file diff --git a/emails/translations/account-check_ko.html b/emails/translations/account-check_ko.html new file mode 100644 index 00000000..3b9b08f4 --- /dev/null +++ b/emails/translations/account-check_ko.html @@ -0,0 +1,15 @@ +
[[[SERVERNAME]]] - Email Verification
+
+ + + + +
+ [[[SERVERNAME]]] - Verification +
+

Hi [[[USERNAME]]], [[[SERVERNAME]]] is requesting email verification, click on the following link to complete the process.

+

+ Click here to verify your e-mail address. +

+ If you did not initiate this request, please ignore this mail. +
\ No newline at end of file diff --git a/emails/translations/account-check_ko.txt b/emails/translations/account-check_ko.txt new file mode 100644 index 00000000..b90c0d2f --- /dev/null +++ b/emails/translations/account-check_ko.txt @@ -0,0 +1,6 @@ +[[[SERVERNAME]]] - Email Verification +Hi [[[USERNAME]]], [[[SERVERNAME]]] ([[[SERVERURL]]]) is performing an e-mail verification. Nagivate to the following link to complete the process: +~ +~[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]] +~ +If you did not initiate this request, please ignore this mail. \ No newline at end of file diff --git a/emails/translations/account-check_nl.html b/emails/translations/account-check_nl.html new file mode 100644 index 00000000..bb6057f1 --- /dev/null +++ b/emails/translations/account-check_nl.html @@ -0,0 +1,15 @@ +
[[[SERVERNAME]]] - E-mail Verificatie
+
+ + + + +
+ [[[SERVERNAME]]] - Verificatie +
+

Hallo [[[USERNAME]]], [[[SERVERNAME]]] vraagt om e-mailverificatie, klik op de volgende link om het proces te voltooien.

+

+ Klik hier om uw e-mailadres te verifiëren. +

+ Als u dit verzoek niet heeft ingediend, dan kunt u deze e-mail negeren. +
\ No newline at end of file diff --git a/emails/translations/account-check_nl.txt b/emails/translations/account-check_nl.txt new file mode 100644 index 00000000..5b4fcc75 --- /dev/null +++ b/emails/translations/account-check_nl.txt @@ -0,0 +1,6 @@ +[[[SERVERNAME]]] - E-mail Verificatie +Hallo [[[USERNAME]]], [[[SERVERNAME]]] ([[[SERVERURL]]]) voert een e-mailverificatie uit. Ga naar de volgende link om het proces te voltooien: +~ +~[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]] +~ +Als u dit verzoek niet heeft ingediend, dan kunt u deze e-mail negeren. \ No newline at end of file diff --git a/emails/translations/account-check_pt.html b/emails/translations/account-check_pt.html new file mode 100644 index 00000000..3b9b08f4 --- /dev/null +++ b/emails/translations/account-check_pt.html @@ -0,0 +1,15 @@ +
[[[SERVERNAME]]] - Email Verification
+
+ + + + +
+ [[[SERVERNAME]]] - Verification +
+

Hi [[[USERNAME]]], [[[SERVERNAME]]] is requesting email verification, click on the following link to complete the process.

+

+ Click here to verify your e-mail address. +

+ If you did not initiate this request, please ignore this mail. +
\ No newline at end of file diff --git a/emails/translations/account-check_pt.txt b/emails/translations/account-check_pt.txt new file mode 100644 index 00000000..b90c0d2f --- /dev/null +++ b/emails/translations/account-check_pt.txt @@ -0,0 +1,6 @@ +[[[SERVERNAME]]] - Email Verification +Hi [[[USERNAME]]], [[[SERVERNAME]]] ([[[SERVERURL]]]) is performing an e-mail verification. Nagivate to the following link to complete the process: +~ +~[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]] +~ +If you did not initiate this request, please ignore this mail. \ No newline at end of file diff --git a/emails/translations/account-check_ru.html b/emails/translations/account-check_ru.html new file mode 100644 index 00000000..37fdac4d --- /dev/null +++ b/emails/translations/account-check_ru.html @@ -0,0 +1,15 @@ +
[[[SERVERNAME]]] - подтверждение по электронной почте
+
+ + + + +
+ [[[SERVERNAME]]] - Подтверждение +
+

Привет [[[USERNAME]]], [[[SERVERNAME]]] запрашивает подтверждение по электронной почте, нажмите на следующую ссылку, чтобы завершить процесс.

+

+ Нажмите здесь, чтобы подтвердить свой адрес электронной почты. +

+ Если вы не инициировали этот запрос, игнорируйте это письмо. +
\ No newline at end of file diff --git a/emails/translations/account-check_ru.txt b/emails/translations/account-check_ru.txt new file mode 100644 index 00000000..b61b5aee --- /dev/null +++ b/emails/translations/account-check_ru.txt @@ -0,0 +1,6 @@ +[[[SERVERNAME]]] - подтверждение по электронной почте +Здравствуйте, [[[USERNAME]]], [[[SERVERNAME]]] ([[[SERVERURL]]]) выполняет проверку электронной почты. Для завершения процесса перейдите по следующей ссылке: +~ +~[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]] +~ +Если вы не инициировали этот запрос, игнорируйте это письмо. \ No newline at end of file diff --git a/emails/translations/account-check_zh-chs.html b/emails/translations/account-check_zh-chs.html new file mode 100644 index 00000000..32239c1a --- /dev/null +++ b/emails/translations/account-check_zh-chs.html @@ -0,0 +1,15 @@ +
[[[SERVERNAME]]]-电子邮件验证
+
+ + + + +
+ [[[SERVERNAME]]]-验证 +
+

[[[USERNAME]],你好, [[[SERVERNAME]]] 正在请求电子邮件验证,请单击以下链接以完成该过程。

+

+ 单击此处以验证您的电子邮件地址。 +

+ 如果您没有发起此请求,请忽略此邮件。 +
\ No newline at end of file diff --git a/emails/translations/account-check_zh-chs.txt b/emails/translations/account-check_zh-chs.txt new file mode 100644 index 00000000..16cc091b --- /dev/null +++ b/emails/translations/account-check_zh-chs.txt @@ -0,0 +1,6 @@ +[[[SERVERNAME]]]-电子邮件验证 +嗨[[[USERNAME]]],[[[SERVERNAME]]]([[[SERVERURL]]])正在执行电子邮件验证。导航至以下链接以完成该过程: +~ +~[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]] +~ +如果您没有发起此请求,请忽略此邮件。 \ No newline at end of file diff --git a/emails/translations/account-invite_cs.html b/emails/translations/account-invite_cs.html new file mode 100644 index 00000000..f889e5c3 --- /dev/null +++ b/emails/translations/account-invite_cs.html @@ -0,0 +1,19 @@ +
[[[SERVERNAME]]] - Pozvánka na účet
+
+ + + + +
+ [[[SERVERNAME]]] - Pozvánka na účet +
+

Účet byl pro vás vytvořen na serveru [[[SERVERNAME]]], nyní k němu máte přístup:

+

+    Uživatelské jméno: [[[ACCOUNTNAME]]]
+    Heslo: [[[PASSWORD]]] +

+ S pozdravem, +
+ [[[USERNAME]]] +
+
\ No newline at end of file diff --git a/emails/translations/account-invite_cs.txt b/emails/translations/account-invite_cs.txt new file mode 100644 index 00000000..4845c415 --- /dev/null +++ b/emails/translations/account-invite_cs.txt @@ -0,0 +1,5 @@ +[[[SERVERNAME]]] - Pozvánka na účet +An account was created for you on server [[[SERVERNAME]]] ([[[SERVERURL]]]/), you can access it now with username "[[[ACCOUNTNAME]]]" and password "[[[PASSWORD]]]". +~ +S pozdravem, +~[[[USERNAME]]] \ No newline at end of file diff --git a/emails/translations/account-invite_de.html b/emails/translations/account-invite_de.html new file mode 100644 index 00000000..5556e1d0 --- /dev/null +++ b/emails/translations/account-invite_de.html @@ -0,0 +1,19 @@ +
[[[SERVERNAME]]] - Kontoeinladung
+
+ + + + +
+ [[[SERVERNAME]]] - Kontoeinladung +
+

Auf dem Server wurde ein Konto für Sie erstellt [[[SERVERNAME]]]können Sie jetzt darauf zugreifen mit:

+

+    Benutzername: [[[ACCOUNTNAME]]]
+    Passwort: [[[PASSWORD]]] +

+ Freundliche Grüße, +
+ [[[USERNAME]]] +
+
\ No newline at end of file diff --git a/emails/translations/account-invite_de.txt b/emails/translations/account-invite_de.txt new file mode 100644 index 00000000..d0a0b658 --- /dev/null +++ b/emails/translations/account-invite_de.txt @@ -0,0 +1,5 @@ +[[[SERVERNAME]]] - Kontoeinladung +An account was created for you on server [[[SERVERNAME]]] ([[[SERVERURL]]]/), you can access it now with username "[[[ACCOUNTNAME]]]" and password "[[[PASSWORD]]]". +~ +Freundliche Grüße, +~[[[USERNAME]]] \ No newline at end of file diff --git a/emails/translations/account-invite_es.html b/emails/translations/account-invite_es.html new file mode 100644 index 00000000..3ff64009 --- /dev/null +++ b/emails/translations/account-invite_es.html @@ -0,0 +1,19 @@ +
[[[SERVERNAME]]] - Account Invitation
+
+ + + + +
+ [[[SERVERNAME]]] - Account Invitation +
+

An account was created for you on server [[[SERVERNAME]]], you can access it now with:

+

+    Usuario: [[[ACCOUNTNAME]]]
+    Contraseña: [[[PASSWORD]]] +

+ Best regards, +
+ [[[USERNAME]]] +
+
\ No newline at end of file diff --git a/emails/translations/account-invite_es.txt b/emails/translations/account-invite_es.txt new file mode 100644 index 00000000..3061a670 --- /dev/null +++ b/emails/translations/account-invite_es.txt @@ -0,0 +1,5 @@ +[[[SERVERNAME]]] - Account Invitation +An account was created for you on server [[[SERVERNAME]]] ([[[SERVERURL]]]/), you can access it now with username "[[[ACCOUNTNAME]]]" and password "[[[PASSWORD]]]". +~ +Best regards, +~[[[USERNAME]]] \ No newline at end of file diff --git a/emails/translations/account-invite_fr.html b/emails/translations/account-invite_fr.html new file mode 100644 index 00000000..8f4061de --- /dev/null +++ b/emails/translations/account-invite_fr.html @@ -0,0 +1,19 @@ +
[[[SERVERNAME]]] - Invitation au compte
+
+ + + + +
+ [[[SERVERNAME]]] - Invitation au compte +
+

Un compte a été créé pour vous sur le serveur [[[SERVERNAME]]], vous pouvez y accéder maintenant avec:

+

+    Nom d'utilisateur: [[[ACCOUNTNAME]]]
+    Mot de passe: [[[PASSWORD]]] +

+ Meilleures salutations, +
+ [[[USERNAME]]] +
+
\ No newline at end of file diff --git a/emails/translations/account-invite_fr.txt b/emails/translations/account-invite_fr.txt new file mode 100644 index 00000000..97e43db8 --- /dev/null +++ b/emails/translations/account-invite_fr.txt @@ -0,0 +1,5 @@ +[[[SERVERNAME]]] - Invitation au compte +An account was created for you on server [[[SERVERNAME]]] ([[[SERVERURL]]]/), you can access it now with username "[[[ACCOUNTNAME]]]" and password "[[[PASSWORD]]]". +~ +Meilleures salutations, +~[[[USERNAME]]] \ No newline at end of file diff --git a/emails/translations/account-invite_hi.html b/emails/translations/account-invite_hi.html new file mode 100644 index 00000000..103da1ea --- /dev/null +++ b/emails/translations/account-invite_hi.html @@ -0,0 +1,19 @@ +
[[[SERVERNAME]]] - Account Invitation
+
+ + + + +
+ [[[SERVERNAME]]] - Account Invitation +
+

An account was created for you on server [[[SERVERNAME]]], you can access it now with:

+

+    उपयोगकर्ता नाम: [[[ACCOUNTNAME]]]
+    कुंजिका: [[[PASSWORD]]] +

+ Best regards, +
+ [[[USERNAME]]] +
+
\ No newline at end of file diff --git a/emails/translations/account-invite_hi.txt b/emails/translations/account-invite_hi.txt new file mode 100644 index 00000000..3061a670 --- /dev/null +++ b/emails/translations/account-invite_hi.txt @@ -0,0 +1,5 @@ +[[[SERVERNAME]]] - Account Invitation +An account was created for you on server [[[SERVERNAME]]] ([[[SERVERURL]]]/), you can access it now with username "[[[ACCOUNTNAME]]]" and password "[[[PASSWORD]]]". +~ +Best regards, +~[[[USERNAME]]] \ No newline at end of file diff --git a/emails/translations/account-invite_ja.html b/emails/translations/account-invite_ja.html new file mode 100644 index 00000000..d2025f33 --- /dev/null +++ b/emails/translations/account-invite_ja.html @@ -0,0 +1,19 @@ +
[[[SERVERNAME]]]-アカウントの招待
+
+ + + + +
+ [[[SERVERNAME]]]-アカウントの招待 +
+

サーバー上にアカウントが作成されました [[[SERVERNAME]]]、あなたは今それを使ってそれにアクセスできます:

+

+    ユーザー名: [[[ACCOUNTNAME]]]
+    パスワード: [[[PASSWORD]]] +

+ 宜しくお願いします、 +
+ [[[USERNAME]]] +
+
\ No newline at end of file diff --git a/emails/translations/account-invite_ja.txt b/emails/translations/account-invite_ja.txt new file mode 100644 index 00000000..c6bc941a --- /dev/null +++ b/emails/translations/account-invite_ja.txt @@ -0,0 +1,5 @@ +[[[SERVERNAME]]]-アカウントの招待 +An account was created for you on server [[[SERVERNAME]]] ([[[SERVERURL]]]/), you can access it now with username "[[[ACCOUNTNAME]]]" and password "[[[PASSWORD]]]". +~ +宜しくお願いします、 +~[[[USERNAME]]] \ No newline at end of file diff --git a/emails/translations/account-invite_ko.html b/emails/translations/account-invite_ko.html new file mode 100644 index 00000000..6c1b0af5 --- /dev/null +++ b/emails/translations/account-invite_ko.html @@ -0,0 +1,19 @@ +
[[[SERVERNAME]]] - Account Invitation
+
+ + + + +
+ [[[SERVERNAME]]] - Account Invitation +
+

An account was created for you on server [[[SERVERNAME]]], you can access it now with:

+

+    사용자 이름: [[[ACCOUNTNAME]]]
+    암호: [[[PASSWORD]]] +

+ Best regards, +
+ [[[USERNAME]]] +
+
\ No newline at end of file diff --git a/emails/translations/account-invite_ko.txt b/emails/translations/account-invite_ko.txt new file mode 100644 index 00000000..3061a670 --- /dev/null +++ b/emails/translations/account-invite_ko.txt @@ -0,0 +1,5 @@ +[[[SERVERNAME]]] - Account Invitation +An account was created for you on server [[[SERVERNAME]]] ([[[SERVERURL]]]/), you can access it now with username "[[[ACCOUNTNAME]]]" and password "[[[PASSWORD]]]". +~ +Best regards, +~[[[USERNAME]]] \ No newline at end of file diff --git a/emails/translations/account-invite_nl.html b/emails/translations/account-invite_nl.html new file mode 100644 index 00000000..37310ef7 --- /dev/null +++ b/emails/translations/account-invite_nl.html @@ -0,0 +1,19 @@ +
[[[SERVERNAME]]] - Account uitnodiging
+
+ + + + +
+ [[[SERVERNAME]]] - Account uitnodiging +
+

Er is een account voor je aangemaakt op de server [[[SERVERNAME]]], je hebt er nu toegang toe met:

+

+    Gebruikersnaam: [[[ACCOUNTNAME]]]
+    Wachtwoord: [[[PASSWORD]]] +

+ Vriendelijke groeten, +
+ [[[USERNAME]]] +
+
\ No newline at end of file diff --git a/emails/translations/account-invite_nl.txt b/emails/translations/account-invite_nl.txt new file mode 100644 index 00000000..7693c137 --- /dev/null +++ b/emails/translations/account-invite_nl.txt @@ -0,0 +1,5 @@ +[[[SERVERNAME]]] - Account uitnodiging +Er is een account jouw aangemaakt op de server [[[SERVERNAME]]] ([[[SERVERURL]]]/), Je kan inloggen met de gebruikersnaam "[[[ACCOUNTNAME]]]" en wachtwoord "[[[PASSWORD]]]". +~ +Vriendelijke groeten, +~[[[USERNAME]]] \ No newline at end of file diff --git a/emails/translations/account-invite_pt.html b/emails/translations/account-invite_pt.html new file mode 100644 index 00000000..d94a9aab --- /dev/null +++ b/emails/translations/account-invite_pt.html @@ -0,0 +1,19 @@ +
[[[SERVERNAME]]] - Account Invitation
+
+ + + + +
+ [[[SERVERNAME]]] - Account Invitation +
+

An account was created for you on server [[[SERVERNAME]]], you can access it now with:

+

+    Nome de usuário: [[[ACCOUNTNAME]]]
+    Senha: [[[PASSWORD]]] +

+ Best regards, +
+ [[[USERNAME]]] +
+
\ No newline at end of file diff --git a/emails/translations/account-invite_pt.txt b/emails/translations/account-invite_pt.txt new file mode 100644 index 00000000..3061a670 --- /dev/null +++ b/emails/translations/account-invite_pt.txt @@ -0,0 +1,5 @@ +[[[SERVERNAME]]] - Account Invitation +An account was created for you on server [[[SERVERNAME]]] ([[[SERVERURL]]]/), you can access it now with username "[[[ACCOUNTNAME]]]" and password "[[[PASSWORD]]]". +~ +Best regards, +~[[[USERNAME]]] \ No newline at end of file diff --git a/emails/translations/account-invite_ru.html b/emails/translations/account-invite_ru.html new file mode 100644 index 00000000..a80d351d --- /dev/null +++ b/emails/translations/account-invite_ru.html @@ -0,0 +1,19 @@ +
[[[SERVERNAME]]] - приглашение в аккаунт
+
+ + + + +
+ [[[SERVERNAME]]] - приглашение в аккаунт +
+

Учетная запись была создана для вас на сервере [[[SERVERNAME]]]Вы можете получить к нему доступ сейчас:

+

+    Имя пользователя: [[[ACCOUNTNAME]]]
+    Пароль: [[[PASSWORD]]] +

+ С уважением, +
+ [[[USERNAME]]] +
+
\ No newline at end of file diff --git a/emails/translations/account-invite_ru.txt b/emails/translations/account-invite_ru.txt new file mode 100644 index 00000000..7a95ce12 --- /dev/null +++ b/emails/translations/account-invite_ru.txt @@ -0,0 +1,5 @@ +[[[SERVERNAME]]] - приглашение в аккаунт +An account was created for you on server [[[SERVERNAME]]] ([[[SERVERURL]]]/), you can access it now with username "[[[ACCOUNTNAME]]]" and password "[[[PASSWORD]]]". +~ +С уважением, +~[[[USERNAME]]] \ No newline at end of file diff --git a/emails/translations/account-invite_zh-chs.html b/emails/translations/account-invite_zh-chs.html new file mode 100644 index 00000000..46b4d0ae --- /dev/null +++ b/emails/translations/account-invite_zh-chs.html @@ -0,0 +1,19 @@ +
[[[SERVERNAME]]]-帐户邀请
+
+ + + + +
+ [[[SERVERNAME]]]-帐户邀请 +
+

在服务器上为您创建了一个帐户 [[[SERVERNAME]]],您现在可以通过以下方式访问它:

+

+    用戶名: [[[ACCOUNTNAME]]]
+    密碼: [[[PASSWORD]]] +

+ 最好的祝福, +
+ [[[USERNAME]]] +
+
\ No newline at end of file diff --git a/emails/translations/account-invite_zh-chs.txt b/emails/translations/account-invite_zh-chs.txt new file mode 100644 index 00000000..598973ba --- /dev/null +++ b/emails/translations/account-invite_zh-chs.txt @@ -0,0 +1,5 @@ +[[[SERVERNAME]]]-帐户邀请 +An account was created for you on server [[[SERVERNAME]]] ([[[SERVERURL]]]/), you can access it now with username "[[[ACCOUNTNAME]]]" and password "[[[PASSWORD]]]". +~ +最好的祝福, +~[[[USERNAME]]] \ No newline at end of file diff --git a/emails/translations/account-login_cs.html b/emails/translations/account-login_cs.html new file mode 100644 index 00000000..00c8f5e4 --- /dev/null +++ b/emails/translations/account-login_cs.html @@ -0,0 +1,12 @@ +
[[[SERVERNAME]]] - Přihlášení k účtu
+
+ + + + +
+ [[[SERVERNAME]]] - Přihlášení k účtu +
+

Váš přihlašovací token je: [[[TOKEN]]]

+

Tento token lze použít pouze jednou a je platný po dobu 5 minut.

+
\ No newline at end of file diff --git a/emails/translations/account-login_cs.txt b/emails/translations/account-login_cs.txt new file mode 100644 index 00000000..266ad450 --- /dev/null +++ b/emails/translations/account-login_cs.txt @@ -0,0 +1,4 @@ +[[[SERVERNAME]]] - Přihlášení k účtu +Váš přihlašovací token je: [[[TOKEN]]] +~ +Tento token lze použít pouze jednou a je platný po dobu 5 minut. \ No newline at end of file diff --git a/emails/translations/account-login_de.html b/emails/translations/account-login_de.html new file mode 100644 index 00000000..da766021 --- /dev/null +++ b/emails/translations/account-login_de.html @@ -0,0 +1,12 @@ +
[[[SERVERNAME]]] - Konto-Login
+
+ + + + +
+ [[[SERVERNAME]]] - Konto-Login +
+

Ihr Login-Token lautet: [[[TOKEN]]]

+

Dieser Token kann nur einmal verwendet werden und ist 5 Minuten gültig.

+
\ No newline at end of file diff --git a/emails/translations/account-login_de.txt b/emails/translations/account-login_de.txt new file mode 100644 index 00000000..0208acd6 --- /dev/null +++ b/emails/translations/account-login_de.txt @@ -0,0 +1,4 @@ +[[[SERVERNAME]]] - Konto-Login +Ihr Login-Token lautet: [[[TOKEN]]] +~ +Dieser Token kann nur einmal verwendet werden und ist 5 Minuten gültig. \ No newline at end of file diff --git a/emails/translations/account-login_es.html b/emails/translations/account-login_es.html new file mode 100644 index 00000000..a218cade --- /dev/null +++ b/emails/translations/account-login_es.html @@ -0,0 +1,12 @@ +
[[[SERVERNAME]]] - Account Login
+
+ + + + +
+ [[[SERVERNAME]]] - Account Login +
+

Your login token is: [[[TOKEN]]]

+

This token can only be used once and is valid for 5 minutes.

+
\ No newline at end of file diff --git a/emails/translations/account-login_es.txt b/emails/translations/account-login_es.txt new file mode 100644 index 00000000..5cf6151e --- /dev/null +++ b/emails/translations/account-login_es.txt @@ -0,0 +1,4 @@ +[[[SERVERNAME]]] - Account Login +Your login token is: [[[TOKEN]]] +~ +This token can only be used once and is valid for 5 minutes. \ No newline at end of file diff --git a/emails/translations/account-login_fr.html b/emails/translations/account-login_fr.html new file mode 100644 index 00000000..16c14f7d --- /dev/null +++ b/emails/translations/account-login_fr.html @@ -0,0 +1,12 @@ +
[[[SERVERNAME]]] - Connexion au compte
+
+ + + + +
+ [[[SERVERNAME]]] - Connexion au compte +
+

Votre jeton de connexion est: [[[TOKEN]]]

+

Ce jeton ne peut être utilisé qu'une seule fois et est valide pendant 5 minutes.

+
\ No newline at end of file diff --git a/emails/translations/account-login_fr.txt b/emails/translations/account-login_fr.txt new file mode 100644 index 00000000..c1813f23 --- /dev/null +++ b/emails/translations/account-login_fr.txt @@ -0,0 +1,4 @@ +[[[SERVERNAME]]] - Connexion au compte +Votre jeton de connexion est: [[[TOKEN]]] +~ +Ce jeton ne peut être utilisé qu'une seule fois et est valide pendant 5 minutes. \ No newline at end of file diff --git a/emails/translations/account-login_hi.html b/emails/translations/account-login_hi.html new file mode 100644 index 00000000..a218cade --- /dev/null +++ b/emails/translations/account-login_hi.html @@ -0,0 +1,12 @@ +
[[[SERVERNAME]]] - Account Login
+
+ + + + +
+ [[[SERVERNAME]]] - Account Login +
+

Your login token is: [[[TOKEN]]]

+

This token can only be used once and is valid for 5 minutes.

+
\ No newline at end of file diff --git a/emails/translations/account-login_hi.txt b/emails/translations/account-login_hi.txt new file mode 100644 index 00000000..5cf6151e --- /dev/null +++ b/emails/translations/account-login_hi.txt @@ -0,0 +1,4 @@ +[[[SERVERNAME]]] - Account Login +Your login token is: [[[TOKEN]]] +~ +This token can only be used once and is valid for 5 minutes. \ No newline at end of file diff --git a/emails/translations/account-login_ja.html b/emails/translations/account-login_ja.html new file mode 100644 index 00000000..eced7bc8 --- /dev/null +++ b/emails/translations/account-login_ja.html @@ -0,0 +1,12 @@ +
[[[SERVERNAME]]]-アカウントログイン
+
+ + + + +
+ [[[SERVERNAME]]]-アカウントログイン +
+

ログイントークンは次のとおりです:[[[TOKEN]]]

+

このトークンは1回だけ使用でき、5分間有効です。

+
\ No newline at end of file diff --git a/emails/translations/account-login_ja.txt b/emails/translations/account-login_ja.txt new file mode 100644 index 00000000..fc7285cc --- /dev/null +++ b/emails/translations/account-login_ja.txt @@ -0,0 +1,4 @@ +[[[SERVERNAME]]]-アカウントログイン +ログイントークンは次のとおりです:[[[TOKEN]]] +~ +このトークンは1回だけ使用でき、5分間有効です。 \ No newline at end of file diff --git a/emails/translations/account-login_ko.html b/emails/translations/account-login_ko.html new file mode 100644 index 00000000..a218cade --- /dev/null +++ b/emails/translations/account-login_ko.html @@ -0,0 +1,12 @@ +
[[[SERVERNAME]]] - Account Login
+
+ + + + +
+ [[[SERVERNAME]]] - Account Login +
+

Your login token is: [[[TOKEN]]]

+

This token can only be used once and is valid for 5 minutes.

+
\ No newline at end of file diff --git a/emails/translations/account-login_ko.txt b/emails/translations/account-login_ko.txt new file mode 100644 index 00000000..5cf6151e --- /dev/null +++ b/emails/translations/account-login_ko.txt @@ -0,0 +1,4 @@ +[[[SERVERNAME]]] - Account Login +Your login token is: [[[TOKEN]]] +~ +This token can only be used once and is valid for 5 minutes. \ No newline at end of file diff --git a/emails/translations/account-login_nl.html b/emails/translations/account-login_nl.html new file mode 100644 index 00000000..bc5d7e2a --- /dev/null +++ b/emails/translations/account-login_nl.html @@ -0,0 +1,12 @@ +
[[[SERVERNAME]]] - Inloggen account
+
+ + + + +
+ [[[SERVERNAME]]] - Inloggen account +
+

Uw login token is: [[[TOKEN]]]

+

Dit token kan maar één keer worden gebruikt en is 5 minuten geldig.

+
\ No newline at end of file diff --git a/emails/translations/account-login_nl.txt b/emails/translations/account-login_nl.txt new file mode 100644 index 00000000..2aeadd65 --- /dev/null +++ b/emails/translations/account-login_nl.txt @@ -0,0 +1,4 @@ +[[[SERVERNAME]]] - Inloggen account +Uw login token is: [[[TOKEN]]] +~ +Dit token kan maar één keer worden gebruikt en is 5 minuten geldig. \ No newline at end of file diff --git a/emails/translations/account-login_pt.html b/emails/translations/account-login_pt.html new file mode 100644 index 00000000..a218cade --- /dev/null +++ b/emails/translations/account-login_pt.html @@ -0,0 +1,12 @@ +
[[[SERVERNAME]]] - Account Login
+
+ + + + +
+ [[[SERVERNAME]]] - Account Login +
+

Your login token is: [[[TOKEN]]]

+

This token can only be used once and is valid for 5 minutes.

+
\ No newline at end of file diff --git a/emails/translations/account-login_pt.txt b/emails/translations/account-login_pt.txt new file mode 100644 index 00000000..5cf6151e --- /dev/null +++ b/emails/translations/account-login_pt.txt @@ -0,0 +1,4 @@ +[[[SERVERNAME]]] - Account Login +Your login token is: [[[TOKEN]]] +~ +This token can only be used once and is valid for 5 minutes. \ No newline at end of file diff --git a/emails/translations/account-login_ru.html b/emails/translations/account-login_ru.html new file mode 100644 index 00000000..c1b2dd46 --- /dev/null +++ b/emails/translations/account-login_ru.html @@ -0,0 +1,12 @@ +
[[[SERVERNAME]]] - Вход в аккаунт
+
+ + + + +
+ [[[SERVERNAME]]] - Вход в аккаунт +
+

Ваш токен для входа: [[[TOKEN]]]

+

Этот токен может быть использован только один раз и действителен в течение 5 минут.

+
\ No newline at end of file diff --git a/emails/translations/account-login_ru.txt b/emails/translations/account-login_ru.txt new file mode 100644 index 00000000..54fca895 --- /dev/null +++ b/emails/translations/account-login_ru.txt @@ -0,0 +1,4 @@ +[[[SERVERNAME]]] - Вход в аккаунт +Ваш токен для входа: [[[TOKEN]]] +~ +Этот токен может быть использован только один раз и действителен в течение 5 минут. \ No newline at end of file diff --git a/emails/translations/account-login_zh-chs.html b/emails/translations/account-login_zh-chs.html new file mode 100644 index 00000000..6a2e08a5 --- /dev/null +++ b/emails/translations/account-login_zh-chs.html @@ -0,0 +1,12 @@ +
[[[SERVERNAME]]]-帐户登录
+
+ + + + +
+ [[[SERVERNAME]]]-帐户登录 +
+

您的登录令牌为:[[[TOKEN]]]

+

该令牌只能使用一次,有效期为5分钟。

+
\ No newline at end of file diff --git a/emails/translations/account-login_zh-chs.txt b/emails/translations/account-login_zh-chs.txt new file mode 100644 index 00000000..1f293063 --- /dev/null +++ b/emails/translations/account-login_zh-chs.txt @@ -0,0 +1,4 @@ +[[[SERVERNAME]]]-帐户登录 +您的登录令牌为:[[[TOKEN]]] +~ +该令牌只能使用一次,有效期为5分钟。 \ No newline at end of file diff --git a/emails/translations/account-reset_cs.html b/emails/translations/account-reset_cs.html new file mode 100644 index 00000000..43caea34 --- /dev/null +++ b/emails/translations/account-reset_cs.html @@ -0,0 +1,15 @@ +
[[[SERVERNAME]]] - Reset účtu
+
+ + + + +
+ [[[SERVERNAME]]] - Ověření +
+

Ahoj [[[USERNAME]]], [[[SERVERNAME]]] požaduje obnovení hesla k účtu, dokončete proces kliknutím na následující odkaz.

+

+ Kliknutím sem obnovíte heslo svého účtu. +

+ Pokud jste tento požadavek nezačali, ignorujte tento e-mail. +
\ No newline at end of file diff --git a/emails/translations/account-reset_cs.txt b/emails/translations/account-reset_cs.txt new file mode 100644 index 00000000..e56beed7 --- /dev/null +++ b/emails/translations/account-reset_cs.txt @@ -0,0 +1,6 @@ +[[[SERVERNAME]]] - Reset účtu +Ahoj [[[USERNAME]]], [[[SERVERNAME]]] ([[[SERVERURL]]])) požaduje obnovení hesla k účtu. Chcete-li proces dokončit, přejděte na následující odkaz: +~ +~[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]] +~ +Pokud jste tento požadavek nezačali, ignorujte tento e-mail. \ No newline at end of file diff --git a/emails/translations/account-reset_de.html b/emails/translations/account-reset_de.html new file mode 100644 index 00000000..e9085ab4 --- /dev/null +++ b/emails/translations/account-reset_de.html @@ -0,0 +1,15 @@ +
[[[SERVERNAME]]] - Zurücksetzen des Kontos
+
+ + + + +
+ [[[SERVERNAME]]] - Überprüfung +
+

Hallo [[[USERNAME]]], [[[SERVERNAME]]] Wenn Sie ein Zurücksetzen des Kontokennworts anfordern, klicken Sie auf den folgenden Link, um den Vorgang abzuschließen.

+

+ Klicken Sie hier, um Ihr Kontopasswort zurückzusetzen. +

+ Wenn Sie diese Anfrage nicht initiiert haben, ignorieren Sie diese Mail bitte. +
\ No newline at end of file diff --git a/emails/translations/account-reset_de.txt b/emails/translations/account-reset_de.txt new file mode 100644 index 00000000..b735b10f --- /dev/null +++ b/emails/translations/account-reset_de.txt @@ -0,0 +1,6 @@ +[[[SERVERNAME]]] - Zurücksetzen des Kontos +Hallo [[[USERNAME]]], [[[SERVERNAME]]] ([[[SERVERURL]]]) fordert ein Zurücksetzen des Kontokennworts an. Klicken Sie auf den folgenden Link, um den Vorgang abzuschließen: +~ +~[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]] +~ +Wenn Sie diese Anfrage nicht initiiert haben, ignorieren Sie diese Mail bitte. \ No newline at end of file diff --git a/emails/translations/account-reset_es.html b/emails/translations/account-reset_es.html new file mode 100644 index 00000000..dd09c6bd --- /dev/null +++ b/emails/translations/account-reset_es.html @@ -0,0 +1,15 @@ +
[[[SERVERNAME]]] - Account Reset
+
+ + + + +
+ [[[SERVERNAME]]] - Verification +
+

Hi [[[USERNAME]]], [[[SERVERNAME]]] is requesting an account password reset, click on the following link to complete the process.

+

+ Click here to reset your account password. +

+ If you did not initiate this request, please ignore this mail. +
\ No newline at end of file diff --git a/emails/translations/account-reset_es.txt b/emails/translations/account-reset_es.txt new file mode 100644 index 00000000..8960967d --- /dev/null +++ b/emails/translations/account-reset_es.txt @@ -0,0 +1,6 @@ +[[[SERVERNAME]]] - Account Reset +Hi [[[USERNAME]]], [[[SERVERNAME]]] ([[[SERVERURL]]]) is requesting an account password reset. Nagivate to the following link to complete the process: +~ +~[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]] +~ +If you did not initiate this request, please ignore this mail. \ No newline at end of file diff --git a/emails/translations/account-reset_fr.html b/emails/translations/account-reset_fr.html new file mode 100644 index 00000000..c8c30208 --- /dev/null +++ b/emails/translations/account-reset_fr.html @@ -0,0 +1,15 @@ +
[[[SERVERNAME]]] - Réinitialisation du compte
+
+ + + + +
+ [[[SERVERNAME]]] - Vérification +
+

Bonjour [[[USERNAME]]], [[[SERVERNAME]]] demande une réinitialisation du mot de passe du compte, cliquez sur le lien suivant pour terminer le processus.

+

+ Cliquez ici pour réinitialiser le mot de passe de votre compte. +

+ Si vous n'avez pas initié cette demande, veuillez ignorer ce courrier. +
\ No newline at end of file diff --git a/emails/translations/account-reset_fr.txt b/emails/translations/account-reset_fr.txt new file mode 100644 index 00000000..2beddc69 --- /dev/null +++ b/emails/translations/account-reset_fr.txt @@ -0,0 +1,6 @@ +[[[SERVERNAME]]] - Réinitialisation du compte +Bonjour [[[USERNAME]]], [[[SERVERNAME]]] ([[[SERVERURL]]]) demande une réinitialisation du mot de passe du compte. Accédez au lien suivant pour terminer le processus: +~ +~[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]] +~ +Si vous n'avez pas initié cette demande, veuillez ignorer ce courrier. \ No newline at end of file diff --git a/emails/translations/account-reset_hi.html b/emails/translations/account-reset_hi.html new file mode 100644 index 00000000..dd09c6bd --- /dev/null +++ b/emails/translations/account-reset_hi.html @@ -0,0 +1,15 @@ +
[[[SERVERNAME]]] - Account Reset
+
+ + + + +
+ [[[SERVERNAME]]] - Verification +
+

Hi [[[USERNAME]]], [[[SERVERNAME]]] is requesting an account password reset, click on the following link to complete the process.

+

+ Click here to reset your account password. +

+ If you did not initiate this request, please ignore this mail. +
\ No newline at end of file diff --git a/emails/translations/account-reset_hi.txt b/emails/translations/account-reset_hi.txt new file mode 100644 index 00000000..8960967d --- /dev/null +++ b/emails/translations/account-reset_hi.txt @@ -0,0 +1,6 @@ +[[[SERVERNAME]]] - Account Reset +Hi [[[USERNAME]]], [[[SERVERNAME]]] ([[[SERVERURL]]]) is requesting an account password reset. Nagivate to the following link to complete the process: +~ +~[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]] +~ +If you did not initiate this request, please ignore this mail. \ No newline at end of file diff --git a/emails/translations/account-reset_ja.html b/emails/translations/account-reset_ja.html new file mode 100644 index 00000000..284e79a8 --- /dev/null +++ b/emails/translations/account-reset_ja.html @@ -0,0 +1,15 @@ +
[[[SERVERNAME]]]-アカウントのリセット
+
+ + + + +
+ [[[SERVERNAME]]]-確認 +
+

[[[USERNAME]]]様 [[[SERVERNAME]]] がアカウントパスワードのリセットを要求している場合は、次のリンクをクリックしてプロセスを完了します。

+

+ ここをクリックしてアカウントのパスワードをリセットしてください。 +

+ このリクエストを開始していない場合は、このメールを無視してください。 +
\ No newline at end of file diff --git a/emails/translations/account-reset_ja.txt b/emails/translations/account-reset_ja.txt new file mode 100644 index 00000000..44286fb1 --- /dev/null +++ b/emails/translations/account-reset_ja.txt @@ -0,0 +1,6 @@ +[[[SERVERNAME]]]-アカウントのリセット +こんにちは[[[USERNAME]]]、[[[SERVERNAME]]]([[[SERVERURL]]])はアカウントパスワードのリセットをリクエストしています。プロセスを完了するには、次のリンクに移動します。 +~ +~[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]] +~ +このリクエストを開始していない場合は、このメールを無視してください。 \ No newline at end of file diff --git a/emails/translations/account-reset_ko.html b/emails/translations/account-reset_ko.html new file mode 100644 index 00000000..dd09c6bd --- /dev/null +++ b/emails/translations/account-reset_ko.html @@ -0,0 +1,15 @@ +
[[[SERVERNAME]]] - Account Reset
+
+ + + + +
+ [[[SERVERNAME]]] - Verification +
+

Hi [[[USERNAME]]], [[[SERVERNAME]]] is requesting an account password reset, click on the following link to complete the process.

+

+ Click here to reset your account password. +

+ If you did not initiate this request, please ignore this mail. +
\ No newline at end of file diff --git a/emails/translations/account-reset_ko.txt b/emails/translations/account-reset_ko.txt new file mode 100644 index 00000000..8960967d --- /dev/null +++ b/emails/translations/account-reset_ko.txt @@ -0,0 +1,6 @@ +[[[SERVERNAME]]] - Account Reset +Hi [[[USERNAME]]], [[[SERVERNAME]]] ([[[SERVERURL]]]) is requesting an account password reset. Nagivate to the following link to complete the process: +~ +~[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]] +~ +If you did not initiate this request, please ignore this mail. \ No newline at end of file diff --git a/emails/translations/account-reset_nl.html b/emails/translations/account-reset_nl.html new file mode 100644 index 00000000..8faf6eab --- /dev/null +++ b/emails/translations/account-reset_nl.html @@ -0,0 +1,15 @@ +
[[[SERVERNAME]]] - Account Reset
+
+ + + + +
+ [[[SERVERNAME]]] - Verificatie +
+

Hallo [[[USERNAME]]], [[[SERVERNAME]]] vraagt om het opnieuw instellen van het wachtwoord van een account, klik op de volgende link om het proces te voltooien.

+

+ Klik hier om je wachtwoord opnieuw in te stellen. +

+ Als u dit verzoek niet heeft ingediend, dan kunt u deze e-mail negeren. +
\ No newline at end of file diff --git a/emails/translations/account-reset_nl.txt b/emails/translations/account-reset_nl.txt new file mode 100644 index 00000000..0385cd29 --- /dev/null +++ b/emails/translations/account-reset_nl.txt @@ -0,0 +1,6 @@ +[[[SERVERNAME]]] - Account Reset +Hallo [[[USERNAME]]], [[[SERVERNAME]]] ([[[SERVERURL]]]) vraagt om het opnieuw instellen van het account wachtwoord. Ga naar de volgende link om het proces te voltooien: +~ +~[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]] +~ +Als u dit verzoek niet heeft ingediend, dan kunt u deze e-mail negeren. \ No newline at end of file diff --git a/emails/translations/account-reset_pt.html b/emails/translations/account-reset_pt.html new file mode 100644 index 00000000..dd09c6bd --- /dev/null +++ b/emails/translations/account-reset_pt.html @@ -0,0 +1,15 @@ +
[[[SERVERNAME]]] - Account Reset
+
+ + + + +
+ [[[SERVERNAME]]] - Verification +
+

Hi [[[USERNAME]]], [[[SERVERNAME]]] is requesting an account password reset, click on the following link to complete the process.

+

+ Click here to reset your account password. +

+ If you did not initiate this request, please ignore this mail. +
\ No newline at end of file diff --git a/emails/translations/account-reset_pt.txt b/emails/translations/account-reset_pt.txt new file mode 100644 index 00000000..8960967d --- /dev/null +++ b/emails/translations/account-reset_pt.txt @@ -0,0 +1,6 @@ +[[[SERVERNAME]]] - Account Reset +Hi [[[USERNAME]]], [[[SERVERNAME]]] ([[[SERVERURL]]]) is requesting an account password reset. Nagivate to the following link to complete the process: +~ +~[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]] +~ +If you did not initiate this request, please ignore this mail. \ No newline at end of file diff --git a/emails/translations/account-reset_ru.html b/emails/translations/account-reset_ru.html new file mode 100644 index 00000000..da951955 --- /dev/null +++ b/emails/translations/account-reset_ru.html @@ -0,0 +1,15 @@ +
[[[SERVERNAME]]] - Сброс учетной записи
+
+ + + + +
+ [[[SERVERNAME]]] - Подтверждение +
+

Привет [[[USERNAME]]], [[[SERVERNAME]]] запрашивает сброс пароля учетной записи, нажмите на следующую ссылку, чтобы завершить процесс.

+

+ Нажмите здесь, чтобы сбросить пароль учетной записи. +

+ Если вы не инициировали этот запрос, игнорируйте это письмо. +
\ No newline at end of file diff --git a/emails/translations/account-reset_ru.txt b/emails/translations/account-reset_ru.txt new file mode 100644 index 00000000..f851d3d9 --- /dev/null +++ b/emails/translations/account-reset_ru.txt @@ -0,0 +1,6 @@ +[[[SERVERNAME]]] - Сброс учетной записи +Здравствуйте, [[[USERNAME]]], [[[SERVERNAME]]] ([[[SERVERURL]]]) запрашивает сброс пароля учетной записи. Для завершения процесса перейдите по следующей ссылке: +~ +~[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]] +~ +Если вы не инициировали этот запрос, игнорируйте это письмо. \ No newline at end of file diff --git a/emails/translations/account-reset_zh-chs.html b/emails/translations/account-reset_zh-chs.html new file mode 100644 index 00000000..c9728e72 --- /dev/null +++ b/emails/translations/account-reset_zh-chs.html @@ -0,0 +1,15 @@ +
[[[SERVERNAME]]]-帐户重置
+
+ + + + +
+ [[[SERVERNAME]]]-验证 +
+

[[[USERNAME]],你好, [[[SERVERNAME]]] 正在要求重置帐户密码,请单击以下链接以完成该过程。

+

+ 单击此处重置您的帐户密码。 +

+ 如果您没有发起此请求,请忽略此邮件。 +
\ No newline at end of file diff --git a/emails/translations/account-reset_zh-chs.txt b/emails/translations/account-reset_zh-chs.txt new file mode 100644 index 00000000..4de47592 --- /dev/null +++ b/emails/translations/account-reset_zh-chs.txt @@ -0,0 +1,6 @@ +[[[SERVERNAME]]]-帐户重置 +[[[USERNAME]],您好:[[[SERVERNAME]]]([[[SERVERURL]]])正在请求重置帐户密码。导航至以下链接以完成该过程: +~ +~[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]] +~ +如果您没有发起此请求,请忽略此邮件。 \ No newline at end of file diff --git a/emails/translations/mesh-invite_cs.html b/emails/translations/mesh-invite_cs.html new file mode 100644 index 00000000..f6b26e85 --- /dev/null +++ b/emails/translations/mesh-invite_cs.html @@ -0,0 +1,42 @@ +
[[[SERVERNAME]]] - Pozvánka
+
+ + + + +
+ [[[SERVERNAME]]] - Instalace agenta +
+ +

+ Dobrý den, [[[NAME]]], +

+
+

Uživatel [[[USERNAME]]] na serveru [[[SERVERNAME]]] vás žádá o instalaci softwaru pro spuštění relace dálkového ovládání.

+ +

+ Zpráva: [[[MSG]]] +

+
+ +

+ Kliknutím sem stáhnete MeshAgent pro Windows. +

+
+ +

Kliknutím sem stáhnete MeshAgent pro Apple OSX.

+
+ +

+ V případě systému Linux vyjměte a vložte do terminálu a nainstalujte agenta:
+

wget -q "[[[SERVERURL]]]/meshagents?script=1" --no-check-certificate -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh [[[SERVERURL]]] \'[[[MESHIDHEX]]]\'
+

+
+ +

+ Chcete-li nainstalovat software, klikněte zde a postupujte podle pokynů. +

+
+

Pokud jste tento požadavek nezačali, ignorujte tento e-mail.

+ S pozdravem,
[[[USERNAME]]]
+
\ No newline at end of file diff --git a/emails/translations/mesh-invite_cs.txt b/emails/translations/mesh-invite_cs.txt new file mode 100644 index 00000000..253dcb9e --- /dev/null +++ b/emails/translations/mesh-invite_cs.txt @@ -0,0 +1,35 @@ +[[[SERVERNAME]]] - Pozvánka +~ +Dobrý den, [[[NAME]]], +~ +Uživatel [[[USERNAME]]] na serveru [[[SERVERNAME]]] ([[[SERVERURL]]]/) požaduje instalaci softwaru k zahájení relace vzdáleného řízení. +~ +~ +Zpráva: [[[MSG]]] +~ +~ +~ +V případě systému Windows dokončete proces pomocí následujícího odkazu: +~ +~[[[SERVERURL]]]/meshagents?id=3&meshid=[[[MESHIDHEX]]]&tag=mailto:[[[EMAIL]]]&installflags=[[[INSTALLFLAGS]]] +~ +~ +~ +V případě systému Apple OSX dokončete proces pomocí následujícího odkazu: +~ +~[[[SERVERURL]]]/meshagents?id=16&meshid=[[[MESHIDHEX]]]&tag=mailto:[[[EMAIL]]]&installflags=[[[INSTALLFLAGS]]] +~ +~ +~ +V případě systému Linux vyjměte a vložte do terminálu a nainstalujte agenta: +~ +~wget -q "[[[SERVERURL]]]/meshagents?script=1" --no-check-certificate -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh [[[SERVERURL]]] '[[[MESHIDHEX]]]' +~ +~ +~ +Chcete-li nainstalovat software, přejděte na [[[SERVERURL]]][[[LINKURL]]] a postupujte podle pokynů. +~ +Pokud jste tento požadavek nezačali, ignorujte tento e-mail. +~ +S pozdravem, +~[[[USERNAME]]] \ No newline at end of file diff --git a/emails/translations/mesh-invite_de.html b/emails/translations/mesh-invite_de.html new file mode 100644 index 00000000..191cd45b --- /dev/null +++ b/emails/translations/mesh-invite_de.html @@ -0,0 +1,42 @@ +
[[[SERVERNAME]]] - Einladung
+
+ + + + +
+ [[[SERVERNAME]]] - Agenteninstallation +
+ +

+ Hallo [[[NAME]]], +

+
+

Benutzer [[[USERNAME]]] auf dem Server [[[SERVERNAME]]] fordert Sie auf, Software zu installieren, um eine Fernsteuerungssitzung zu starten.

+ +

+ Botschaft: [[[MSG]]] +

+
+ +

+ Klicken Sie hier, um den MeshAgent für Windows herunterzuladen. +

+
+ +

Klicken Sie hier, um den MeshAgent für Apple OSX herunterzuladen.

+
+ +

+ Schneiden Sie unter Linux Folgendes aus und fügen Sie es in ein Terminal ein, um den Agenten zu installieren:
+

wget -q "[[[SERVERURL]]]/meshagents?script=1" --no-check-certificate -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh [[[SERVERURL]]] \'[[[MESHIDHEX]]]\'
+

+
+ +

+ Um die Software zu installieren, hier klicken und folgen Sie den Anweisungen. +

+
+

Wenn Sie diese Anfrage nicht initiiert haben, ignorieren Sie diese Mail bitte.

+ Freundliche Grüße,
[[[USERNAME]]]
+
\ No newline at end of file diff --git a/emails/translations/mesh-invite_de.txt b/emails/translations/mesh-invite_de.txt new file mode 100644 index 00000000..5727e1bd --- /dev/null +++ b/emails/translations/mesh-invite_de.txt @@ -0,0 +1,35 @@ +[[[SERVERNAME]]] - Einladung +~ +Hallo [[[NAME]]], +~ +Benutzer [[[USERNAME]]] auf dem Server [[[SERVERNAME]]] ([[[SERVERURL]]]/) fordert Sie auf, Software zu installieren, um die Fernsteuerungssitzung zu starten. +~ +~ +Nachricht: [[[MSG]]] +~ +~ +~ +Nagivieren Sie unter Windows den folgenden Link, um den Vorgang abzuschließen: +~ +~[[[SERVERURL]]]/meshagents?id=3&meshid=[[[MESHIDHEX]]]&tag=mailto:[[[EMAIL]]]&installflags=[[[INSTALLFLAGS]]] +~ +~ +~ +Nagivieren Sie unter Apple OSX den folgenden Link, um den Vorgang abzuschließen: +~ +~[[[SERVERURL]]]/meshagents?id=16&meshid=[[[MESHIDHEX]]]&tag=mailto:[[[EMAIL]]]&installflags=[[[INSTALLFLAGS]]] +~ +~ +~ +Schneiden Sie unter Linux Folgendes aus und fügen Sie es in ein Terminal ein, um den Agenten zu installieren: +~ +~wget -q "[[[SERVERURL]]]/meshagents?script=1" --no-check-certificate -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh [[[SERVERURL]]] '[[[MESHIDHEX]]]' +~ +~ +~ +Navigieren Sie zum Installieren der Software zu [[[SERVERURL]]][[[LINKURL]]] und befolgen Sie die Anweisungen. +~ +Wenn Sie diese Anfrage nicht initiiert haben, ignorieren Sie diese Mail bitte. +~ +Freundliche Grüße, +~[[[USERNAME]]] \ No newline at end of file diff --git a/emails/translations/mesh-invite_es.html b/emails/translations/mesh-invite_es.html new file mode 100644 index 00000000..b2db0760 --- /dev/null +++ b/emails/translations/mesh-invite_es.html @@ -0,0 +1,42 @@ +
[[[SERVERNAME]]] - Invitation
+
+ + + + +
+ [[[SERVERNAME]]] - Agent Installation +
+ +

+ Hello [[[NAME]]], +

+
+

User [[[USERNAME]]] on server [[[SERVERNAME]]] is requesting you to install software to start a remote control session.

+ +

+ Message: [[[MSG]]] +

+
+ +

+ Click here to download the MeshAgent for Windows. +

+
+ +

Click here to download the MeshAgent for Apple OSX.

+
+ +

+ For Linux, cut & paste the following in a terminal to install the agent:
+

wget -q "[[[SERVERURL]]]/meshagents?script=1" --no-check-certificate -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh [[[SERVERURL]]] \'[[[MESHIDHEX]]]\'
+

+
+ +

+ To install the software, click here and follow the instructions. +

+
+

If you did not initiate this request, please ignore this mail.

+ Best regards,
[[[USERNAME]]]
+
\ No newline at end of file diff --git a/emails/translations/mesh-invite_es.txt b/emails/translations/mesh-invite_es.txt new file mode 100644 index 00000000..ac8ad99b --- /dev/null +++ b/emails/translations/mesh-invite_es.txt @@ -0,0 +1,35 @@ +[[[SERVERNAME]]] - Invitation +~ +Hello [[[NAME]]], +~ +User [[[USERNAME]]] on server [[[SERVERNAME]]] ([[[SERVERURL]]]/) is requesting you install software to start the remote control session. +~ +~ +Message: [[[MSG]]] +~ +~ +~ +For Windows, nagivate to the following link to complete the process: +~ +~[[[SERVERURL]]]/meshagents?id=3&meshid=[[[MESHIDHEX]]]&tag=mailto:[[[EMAIL]]]&installflags=[[[INSTALLFLAGS]]] +~ +~ +~ +For Apple OSX, nagivate to the following link to complete the process: +~ +~[[[SERVERURL]]]/meshagents?id=16&meshid=[[[MESHIDHEX]]]&tag=mailto:[[[EMAIL]]]&installflags=[[[INSTALLFLAGS]]] +~ +~ +~ +For Linux, cut & paste the following in a terminal to install the agent: +~ +~wget -q "[[[SERVERURL]]]/meshagents?script=1" --no-check-certificate -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh [[[SERVERURL]]] '[[[MESHIDHEX]]]' +~ +~ +~ +To install the software, navigate to [[[SERVERURL]]][[[LINKURL]]] and follow the instructions. +~ +If you did not initiate this request, please ignore this mail. +~ +Best regards, +~[[[USERNAME]]] \ No newline at end of file diff --git a/emails/translations/mesh-invite_fr.html b/emails/translations/mesh-invite_fr.html new file mode 100644 index 00000000..f1415af5 --- /dev/null +++ b/emails/translations/mesh-invite_fr.html @@ -0,0 +1,42 @@ +
[[[SERVERNAME]]] - Invitation
+
+ + + + +
+ [[[SERVERNAME]]] - Installation de l'agent +
+ +

+ Bonjour [[[NAME]]], +

+
+

Utilisateur [[[USERNAME]]] sur le serveur [[[SERVERNAME]]] vous demande d'installer un logiciel pour démarrer une session de contrôle à distance.

+ +

+ Message: [[[MSG]]] +

+
+ +

+ Cliquez ici pour télécharger le MeshAgent pour Windows. +

+
+ +

Cliquez ici pour télécharger le MeshAgent pour Apple OSX.

+
+ +

+ Pour Linux, copiez et collez les éléments suivants dans un terminal pour installer l'agent:
+

wget -q "[[[SERVERURL]]]/meshagents?script=1" --no-check-certificate -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh [[[SERVERURL]]] \'[[[MESHIDHEX]]]\'
+

+
+ +

+ Pour installer le logiciel, cliquez ici et suivez les instructions. +

+
+

Si vous n'avez pas initié cette demande, veuillez ignorer ce courrier.

+ Meilleures salutations,
[[[USERNAME]]]
+
\ No newline at end of file diff --git a/emails/translations/mesh-invite_fr.txt b/emails/translations/mesh-invite_fr.txt new file mode 100644 index 00000000..9625b4c4 --- /dev/null +++ b/emails/translations/mesh-invite_fr.txt @@ -0,0 +1,35 @@ +[[[SERVERNAME]]] - Invitation +~ +Bonjour [[[NAME]]], +~ +L'utilisateur [[[USERNAME]]] sur le serveur [[[SERVERNAME]]] ([[[SERVERURL]]]/) vous demande d'installer un logiciel pour démarrer la session de contrôle à distance. +~ +~ +Message: [[[MSG]]] +~ +~ +~ +Pour Windows, accédez au lien suivant pour terminer le processus: +~ +~[[[SERVERURL]]]/meshagents?id=3&meshid=[[[MESHIDHEX]]]&tag=mailto:[[[EMAIL]]]&installflags=[[[INSTALLFLAGS]]] +~ +~ +~ +Pour Apple OSX, accédez au lien suivant pour terminer le processus: +~ +~[[[SERVERURL]]]/meshagents?id=16&meshid=[[[MESHIDHEX]]]&tag=mailto:[[[EMAIL]]]&installflags=[[[INSTALLFLAGS]]] +~ +~ +~ +Pour Linux, copiez et collez les éléments suivants dans un terminal pour installer l'agent: +~ +~wget -q "[[[SERVERURL]]]/meshagents?script=1" --no-check-certificate -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh [[[SERVERURL]]] '[[[MESHIDHEX]]]' +~ +~ +~ +Pour installer le logiciel, accédez à [[[SERVERURL]]][[[LINKURL]]] et suivez les instructions. +~ +Si vous n'avez pas initié cette demande, veuillez ignorer ce courrier. +~ +Meilleures salutations, +~[[[USERNAME]]] \ No newline at end of file diff --git a/emails/translations/mesh-invite_hi.html b/emails/translations/mesh-invite_hi.html new file mode 100644 index 00000000..b2db0760 --- /dev/null +++ b/emails/translations/mesh-invite_hi.html @@ -0,0 +1,42 @@ +
[[[SERVERNAME]]] - Invitation
+
+ + + + +
+ [[[SERVERNAME]]] - Agent Installation +
+ +

+ Hello [[[NAME]]], +

+
+

User [[[USERNAME]]] on server [[[SERVERNAME]]] is requesting you to install software to start a remote control session.

+ +

+ Message: [[[MSG]]] +

+
+ +

+ Click here to download the MeshAgent for Windows. +

+
+ +

Click here to download the MeshAgent for Apple OSX.

+
+ +

+ For Linux, cut & paste the following in a terminal to install the agent:
+

wget -q "[[[SERVERURL]]]/meshagents?script=1" --no-check-certificate -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh [[[SERVERURL]]] \'[[[MESHIDHEX]]]\'
+

+
+ +

+ To install the software, click here and follow the instructions. +

+
+

If you did not initiate this request, please ignore this mail.

+ Best regards,
[[[USERNAME]]]
+
\ No newline at end of file diff --git a/emails/translations/mesh-invite_hi.txt b/emails/translations/mesh-invite_hi.txt new file mode 100644 index 00000000..ac8ad99b --- /dev/null +++ b/emails/translations/mesh-invite_hi.txt @@ -0,0 +1,35 @@ +[[[SERVERNAME]]] - Invitation +~ +Hello [[[NAME]]], +~ +User [[[USERNAME]]] on server [[[SERVERNAME]]] ([[[SERVERURL]]]/) is requesting you install software to start the remote control session. +~ +~ +Message: [[[MSG]]] +~ +~ +~ +For Windows, nagivate to the following link to complete the process: +~ +~[[[SERVERURL]]]/meshagents?id=3&meshid=[[[MESHIDHEX]]]&tag=mailto:[[[EMAIL]]]&installflags=[[[INSTALLFLAGS]]] +~ +~ +~ +For Apple OSX, nagivate to the following link to complete the process: +~ +~[[[SERVERURL]]]/meshagents?id=16&meshid=[[[MESHIDHEX]]]&tag=mailto:[[[EMAIL]]]&installflags=[[[INSTALLFLAGS]]] +~ +~ +~ +For Linux, cut & paste the following in a terminal to install the agent: +~ +~wget -q "[[[SERVERURL]]]/meshagents?script=1" --no-check-certificate -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh [[[SERVERURL]]] '[[[MESHIDHEX]]]' +~ +~ +~ +To install the software, navigate to [[[SERVERURL]]][[[LINKURL]]] and follow the instructions. +~ +If you did not initiate this request, please ignore this mail. +~ +Best regards, +~[[[USERNAME]]] \ No newline at end of file diff --git a/emails/translations/mesh-invite_ja.html b/emails/translations/mesh-invite_ja.html new file mode 100644 index 00000000..64eb7a88 --- /dev/null +++ b/emails/translations/mesh-invite_ja.html @@ -0,0 +1,42 @@ +
[[[SERVERNAME]]]-招待
+
+ + + + +
+ [[[SERVERNAME]]]-エージェントのインストール +
+ +

+ [[[NAME]]]様 +

+
+

サーバー上のユーザー[[[USERNAME]]] [[[SERVERNAME]]] リモートコントロールセッションを開始するソフトウェアをインストールするように要求しています。

+ +

+ メッセージ: [[[MSG]]] +

+
+ +

+ Windows用のMeshAgentをダウンロードするには、ここをクリックしてください。 +

+
+ +

ここをクリックして、Apple OSX用のMeshAgentをダウンロードしてください。

+
+ +

+ Linuxの場合は、ターミナルで以下をカットアンドペーストしてエージェントをインストールします。
+

wget -q "[[[SERVERURL]]]/meshagents?script=1" --no-check-certificate -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh [[[SERVERURL]]] \'[[[MESHIDHEX]]]\'
+

+
+ +

+ ソフトウェアをインストールするには、 ここをクリック 指示に従ってください。 +

+
+

このリクエストを開始していない場合は、このメールを無視してください。

+ 宜しくお願いします、
[[[USERNAME]]]
+
\ No newline at end of file diff --git a/emails/translations/mesh-invite_ja.txt b/emails/translations/mesh-invite_ja.txt new file mode 100644 index 00000000..5ea5b9d5 --- /dev/null +++ b/emails/translations/mesh-invite_ja.txt @@ -0,0 +1,35 @@ +[[[SERVERNAME]]]-招待 +~ +[[[NAME]]]様 +~ +サーバー[[[SERVERNAME]]]([[[SERVERURL]]]/)のユーザー[[[USERNAME]]]が、リモートコントロールセッションを開始するためのソフトウェアのインストールを要求しています。 +~ +~ +メッセージ:[[[MSG]]] +~ +~ +~ +Windowsの場合、次のリンクに移動してプロセスを完了します。 +~ +~[[[SERVERURL]]]/meshagents?id=3&meshid=[[[MESHIDHEX]]]&tag=mailto:[[[EMAIL]]]&installflags=[[[INSTALLFLAGS]]] +~ +~ +~ +Apple OSXの場合、次のリンクに移動してプロセスを完了します。 +~ +~[[[SERVERURL]]]/meshagents?id=16&meshid=[[[MESHIDHEX]]]&tag=mailto:[[[EMAIL]]]&installflags=[[[INSTALLFLAGS]]] +~ +~ +~ +Linuxの場合は、ターミナルで以下をカットアンドペーストしてエージェントをインストールします。 +~ +~wget -q "[[[SERVERURL]]]/meshagents?script=1" --no-check-certificate -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh [[[SERVERURL]]] '[[[MESHIDHEX]]]' +~ +~ +~ +ソフトウェアをインストールするには、[[[SERVERURL]]][[[LINKURL]]]に移動し、指示に従います。 +~ +このリクエストを開始していない場合は、このメールを無視してください。 +~ +宜しくお願いします、 +~[[[USERNAME]]] \ No newline at end of file diff --git a/emails/translations/mesh-invite_ko.html b/emails/translations/mesh-invite_ko.html new file mode 100644 index 00000000..b2db0760 --- /dev/null +++ b/emails/translations/mesh-invite_ko.html @@ -0,0 +1,42 @@ +
[[[SERVERNAME]]] - Invitation
+
+ + + + +
+ [[[SERVERNAME]]] - Agent Installation +
+ +

+ Hello [[[NAME]]], +

+
+

User [[[USERNAME]]] on server [[[SERVERNAME]]] is requesting you to install software to start a remote control session.

+ +

+ Message: [[[MSG]]] +

+
+ +

+ Click here to download the MeshAgent for Windows. +

+
+ +

Click here to download the MeshAgent for Apple OSX.

+
+ +

+ For Linux, cut & paste the following in a terminal to install the agent:
+

wget -q "[[[SERVERURL]]]/meshagents?script=1" --no-check-certificate -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh [[[SERVERURL]]] \'[[[MESHIDHEX]]]\'
+

+
+ +

+ To install the software, click here and follow the instructions. +

+
+

If you did not initiate this request, please ignore this mail.

+ Best regards,
[[[USERNAME]]]
+
\ No newline at end of file diff --git a/emails/translations/mesh-invite_ko.txt b/emails/translations/mesh-invite_ko.txt new file mode 100644 index 00000000..ac8ad99b --- /dev/null +++ b/emails/translations/mesh-invite_ko.txt @@ -0,0 +1,35 @@ +[[[SERVERNAME]]] - Invitation +~ +Hello [[[NAME]]], +~ +User [[[USERNAME]]] on server [[[SERVERNAME]]] ([[[SERVERURL]]]/) is requesting you install software to start the remote control session. +~ +~ +Message: [[[MSG]]] +~ +~ +~ +For Windows, nagivate to the following link to complete the process: +~ +~[[[SERVERURL]]]/meshagents?id=3&meshid=[[[MESHIDHEX]]]&tag=mailto:[[[EMAIL]]]&installflags=[[[INSTALLFLAGS]]] +~ +~ +~ +For Apple OSX, nagivate to the following link to complete the process: +~ +~[[[SERVERURL]]]/meshagents?id=16&meshid=[[[MESHIDHEX]]]&tag=mailto:[[[EMAIL]]]&installflags=[[[INSTALLFLAGS]]] +~ +~ +~ +For Linux, cut & paste the following in a terminal to install the agent: +~ +~wget -q "[[[SERVERURL]]]/meshagents?script=1" --no-check-certificate -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh [[[SERVERURL]]] '[[[MESHIDHEX]]]' +~ +~ +~ +To install the software, navigate to [[[SERVERURL]]][[[LINKURL]]] and follow the instructions. +~ +If you did not initiate this request, please ignore this mail. +~ +Best regards, +~[[[USERNAME]]] \ No newline at end of file diff --git a/emails/translations/mesh-invite_nl.html b/emails/translations/mesh-invite_nl.html new file mode 100644 index 00000000..2fa8ec54 --- /dev/null +++ b/emails/translations/mesh-invite_nl.html @@ -0,0 +1,42 @@ +
[[[SERVERNAME]]] - Uitnodiging
+
+ + + + +
+ [[[SERVERNAME]]] - Agent installatie +
+ +

+ Hallo [[[NAME]]], +

+
+

Gebruiker [[[USERNAME]]] op server [[[SERVERNAME]]] vraagt u om de software te installeren om een ondersteunings sessie te starten.

+ +

+ Bericht: [[[MSG]]] +

+
+ +

+ Klik hier om de MeshAgent te downloaden voor Windows. +

+
+ +

Klik hier om de MeshAgent te downloaden voor Apple OSX.

+
+ +

+ Voor Linux, knip het volgende en plak dit in een terminal om de agent te installeren:
+

wget -q "[[[SERVERURL]]]/meshagents?script=1" --no-check-certificate -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh [[[SERVERURL]]] \'[[[MESHIDHEX]]]\'
+

+
+ +

+ Om de software te installeren, Klik hier en volg de instructies. +

+
+

Als u dit verzoek niet heeft ingediend, dan kunt u deze e-mail negeren.

+ Vriendelijke groeten,
[[[USERNAME]]]
+
\ No newline at end of file diff --git a/emails/translations/mesh-invite_nl.txt b/emails/translations/mesh-invite_nl.txt new file mode 100644 index 00000000..58db26e2 --- /dev/null +++ b/emails/translations/mesh-invite_nl.txt @@ -0,0 +1,35 @@ +[[[SERVERNAME]]] - Uitnodiging +~ +Hallo [[[NAME]]], +~ +Gebruiker [[[USERNAME]]] op server [[[SERVERNAME]]] ([[[SERVERURL]]] /) vraagt u de software te installeren om de sessie voor afstandsbediening te starten. +~ +~ +Bericht: [[[MSG]]] +~ +~ +~ +Voor Windows, ga je naar de volgende link om het proces te voltooien: +~ +~[[[SERVERURL]]]/meshagents?id=3&meshid=[[[MESHIDHEX]]]&tag=mailto:[[[EMAIL]]]&installflags=[[[INSTALLFLAGS]]] +~ +~ +~ +Voor Apple OSX ga je naar de volgende link om het proces te voltooien: +~ +~[[[SERVERURL]]]/meshagents?id=16&meshid=[[[MESHIDHEX]]]&tag=mailto:[[[EMAIL]]]&installflags=[[[INSTALLFLAGS]]] +~ +~ +~ +Voor Linux, knip het volgende en plak dit in een terminal om de agent te installeren: +~ +~wget -q "[[[SERVERURL]]]/meshagents?script=1" --no-check-certificate -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh [[[SERVERURL]]] '[[[MESHIDHEX]]]' +~ +~ +~ +Om de software te installeren, navigeert u naar [[[SERVERURL]]] [[[LINKURL]]] en volgt u de instructies. +~ +Als u dit verzoek niet heeft ingediend, dan kunt u deze e-mail negeren. +~ +Vriendelijke groeten, +~[[[USERNAME]]] \ No newline at end of file diff --git a/emails/translations/mesh-invite_pt.html b/emails/translations/mesh-invite_pt.html new file mode 100644 index 00000000..b2db0760 --- /dev/null +++ b/emails/translations/mesh-invite_pt.html @@ -0,0 +1,42 @@ +
[[[SERVERNAME]]] - Invitation
+
+ + + + +
+ [[[SERVERNAME]]] - Agent Installation +
+ +

+ Hello [[[NAME]]], +

+
+

User [[[USERNAME]]] on server [[[SERVERNAME]]] is requesting you to install software to start a remote control session.

+ +

+ Message: [[[MSG]]] +

+
+ +

+ Click here to download the MeshAgent for Windows. +

+
+ +

Click here to download the MeshAgent for Apple OSX.

+
+ +

+ For Linux, cut & paste the following in a terminal to install the agent:
+

wget -q "[[[SERVERURL]]]/meshagents?script=1" --no-check-certificate -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh [[[SERVERURL]]] \'[[[MESHIDHEX]]]\'
+

+
+ +

+ To install the software, click here and follow the instructions. +

+
+

If you did not initiate this request, please ignore this mail.

+ Best regards,
[[[USERNAME]]]
+
\ No newline at end of file diff --git a/emails/translations/mesh-invite_pt.txt b/emails/translations/mesh-invite_pt.txt new file mode 100644 index 00000000..ac8ad99b --- /dev/null +++ b/emails/translations/mesh-invite_pt.txt @@ -0,0 +1,35 @@ +[[[SERVERNAME]]] - Invitation +~ +Hello [[[NAME]]], +~ +User [[[USERNAME]]] on server [[[SERVERNAME]]] ([[[SERVERURL]]]/) is requesting you install software to start the remote control session. +~ +~ +Message: [[[MSG]]] +~ +~ +~ +For Windows, nagivate to the following link to complete the process: +~ +~[[[SERVERURL]]]/meshagents?id=3&meshid=[[[MESHIDHEX]]]&tag=mailto:[[[EMAIL]]]&installflags=[[[INSTALLFLAGS]]] +~ +~ +~ +For Apple OSX, nagivate to the following link to complete the process: +~ +~[[[SERVERURL]]]/meshagents?id=16&meshid=[[[MESHIDHEX]]]&tag=mailto:[[[EMAIL]]]&installflags=[[[INSTALLFLAGS]]] +~ +~ +~ +For Linux, cut & paste the following in a terminal to install the agent: +~ +~wget -q "[[[SERVERURL]]]/meshagents?script=1" --no-check-certificate -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh [[[SERVERURL]]] '[[[MESHIDHEX]]]' +~ +~ +~ +To install the software, navigate to [[[SERVERURL]]][[[LINKURL]]] and follow the instructions. +~ +If you did not initiate this request, please ignore this mail. +~ +Best regards, +~[[[USERNAME]]] \ No newline at end of file diff --git a/emails/translations/mesh-invite_ru.html b/emails/translations/mesh-invite_ru.html new file mode 100644 index 00000000..95b8634c --- /dev/null +++ b/emails/translations/mesh-invite_ru.html @@ -0,0 +1,42 @@ +
[[[SERVERNAME]]] - Приглашение
+
+ + + + +
+ [[[SERVERNAME]]] - Установка агента +
+ +

+ Здравствуйте, [[[NAME]]], +

+
+

Пользователь [[[USERNAME]]] на сервере [[[SERVERNAME]]] просит вас установить программное обеспечение, чтобы начать сеанс удаленного управления.

+ +

+ Сообщение: [[[MSG]]] +

+
+ +

+ Нажмите здесь, чтобы загрузить MeshAgent для Windows. +

+
+ +

Нажмите здесь, чтобы загрузить MeshAgent для Apple OSX.

+
+ +

+ Для Linux вырезайте и вставляйте в терминал следующее, чтобы установить агент:
+

wget -q "[[[SERVERURL]]]/meshagents?script=1" --no-check-certificate -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh [[[SERVERURL]]] \'[[[MESHIDHEX]]]\'
+

+
+ +

+ Чтобы установить программное обеспечение, кликните сюда и следуйте инструкциям. +

+
+

Если вы не инициировали этот запрос, игнорируйте это письмо.

+ С уважением,
[[[USERNAME]]]
+
\ No newline at end of file diff --git a/emails/translations/mesh-invite_ru.txt b/emails/translations/mesh-invite_ru.txt new file mode 100644 index 00000000..073b9717 --- /dev/null +++ b/emails/translations/mesh-invite_ru.txt @@ -0,0 +1,35 @@ +[[[SERVERNAME]]] - Приглашение +~ +Здравствуйте, [[[NAME]]], +~ +Пользователь [[[USERNAME]]] на сервере [[[SERVERNAME]]] ([[[SERVERURL]]]/) запрашивает установку программного обеспечения для запуска сеанса удаленного управления. +~ +~ +Сообщение: [[[MSG]]] +~ +~ +~ +Для Windows откройте следующую ссылку, чтобы завершить процесс: +~ +~[[[SERVERURL]]]/meshagents?id=3&meshid=[[[MESHIDHEX]]]&tag=mailto:[[[EMAIL]]]&installflags=[[[INSTALLFLAGS]]] +~ +~ +~ +Для Apple OSX перейдите по следующей ссылке, чтобы завершить процесс: +~ +~[[[SERVERURL]]]/meshagents?id=16&meshid=[[[MESHIDHEX]]]&tag=mailto:[[[EMAIL]]]&installflags=[[[INSTALLFLAGS]]] +~ +~ +~ +Для Linux вырезайте и вставляйте в терминал следующее, чтобы установить агент: +~ +~wget -q "[[[SERVERURL]]]/meshagents?script=1" --no-check-certificate -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh [[[SERVERURL]]] '[[[MESHIDHEX]]]' +~ +~ +~ +Для установки программного обеспечения перейдите к [[[SERVERURL]]][[[LINKURL]]] и следуйте инструкциям. +~ +Если вы не инициировали этот запрос, игнорируйте это письмо. +~ +С уважением, +~[[[USERNAME]]] \ No newline at end of file diff --git a/emails/translations/mesh-invite_zh-chs.html b/emails/translations/mesh-invite_zh-chs.html new file mode 100644 index 00000000..22419e7f --- /dev/null +++ b/emails/translations/mesh-invite_zh-chs.html @@ -0,0 +1,42 @@ +
[[[SERVERNAME]]]-邀请
+
+ + + + +
+ [[[SERVERNAME]]]-代理程序安装 +
+ +

+ 您好[[[NAME]]], +

+
+

伺服器上的使用者[[[USERNAME]]] [[[SERVERNAME]]] 正在要求您安装软件以启动远程控制会话。

+ +

+ 信息: [[[MSG]]] +

+
+ +

+ 单击此处下载适用于Windows的MeshAgent。 +

+
+ +

单击此处下载适用于Apple OSX的MeshAgent。

+
+ +

+ 对于Linux,将以下内容剪切并粘贴到终端中以安装代理程序:
+

wget -q "[[[SERVERURL]]]/meshagents?script=1" --no-check-certificate -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh [[[SERVERURL]]] \'[[[MESHIDHEX]]]\'
+

+
+ +

+ 要安装软件, 点击这里 并按照说明进行操作。 +

+
+

如果您没有发起此请求,请忽略此邮件。

+ 最好的祝福,
[[[USERNAME]]]
+
\ No newline at end of file diff --git a/emails/translations/mesh-invite_zh-chs.txt b/emails/translations/mesh-invite_zh-chs.txt new file mode 100644 index 00000000..e4346a53 --- /dev/null +++ b/emails/translations/mesh-invite_zh-chs.txt @@ -0,0 +1,35 @@ +[[[SERVERNAME]]]-邀请 +~ +您好[[[NAME]]], +~ +服务器[[[SERVERNAME]]]([[[SERVERURL]]]/)上的用户[[[USERNAME]]]请求您安装软件以启动远程控制会话。 +~ +~ +讯息:[[[MSG]]] +~ +~ +~ +对于Windows,请导航至以下链接以完成该过程: +~ +~[[[SERVERURL]]]/meshagents?id=3&meshid=[[[MESHIDHEX]]]&tag=mailto:[[[EMAIL]]]&installflags=[[[INSTALLFLAGS]]] +~ +~ +~ +对于Apple OSX,请导航至以下链接以完成该过程: +~ +~[[[SERVERURL]]]/meshagents?id=16&meshid=[[[MESHIDHEX]]]&tag=mailto:[[[EMAIL]]]&installflags=[[[INSTALLFLAGS]]] +~ +~ +~ +对于Linux,将以下内容剪切并粘贴到终端中以安装代理程序: +~ +~wget -q "[[[SERVERURL]]]/meshagents?script=1" --no-check-certificate -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh [[[SERVERURL]]] '[[[MESHIDHEX]]]' +~ +~ +~ +要安装软件,请导航至[[[SERVERURL]]][[[LINKURL]]],然后按照说明进行操作。 +~ +如果您没有发起此请求,请忽略此邮件。 +~ +最好的祝福, +~[[[USERNAME]]] \ No newline at end of file diff --git a/letsEncrypt.js b/letsEncrypt.js index d2eda15d..2a8ae3f8 100644 --- a/letsEncrypt.js +++ b/letsEncrypt.js @@ -14,293 +14,220 @@ /*jshint esversion: 6 */ 'use strict'; +// ACME-Client Implementation var globalLetsEncrypt = null; - module.exports.CreateLetsEncrypt = function (parent) { - try { - // Get the GreenLock version - var greenLockVersion = null; - try { greenLockVersion = require('greenlock/package.json').version; } catch (ex) { } - if (greenLockVersion == null) { - parent.debug('cert', "Initializing Let's Encrypt support"); + const acme = require('acme-client'); + + var obj = {}; + obj.fs = require('fs'); + obj.path = require('path'); + obj.parent = parent; + obj.forge = obj.parent.certificateOperations.forge; + obj.leDomains = null; + obj.challenges = {}; + obj.runAsProduction = false; + obj.redirWebServerHooked = false; + obj.configErr = null; + obj.configOk = false; + obj.pendingRequest = false; + + // Let's Encrypt debug logging + obj.log = function (str) { + parent.debug('cert', 'LE: ' + str); + var d = new Date(); + obj.events.push(d.toLocaleDateString() + ' ' + d.toLocaleTimeString() + ' - ' + str); + while (obj.events.length > 200) { obj.events.shift(); } // Keep only 200 last events. + } + obj.events = []; + + // Setup the certificate storage paths + obj.certPath = obj.path.join(obj.parent.datapath, 'letsencrypt-certs'); + try { obj.parent.fs.mkdirSync(obj.certPath); } catch (e) { } + + // Hook up GreenLock to the redirection server + if (obj.parent.config.settings.rediraliasport === 80) { obj.redirWebServerHooked = true; } + else if ((obj.parent.config.settings.rediraliasport == null) && (obj.parent.redirserver.port == 80)) { obj.redirWebServerHooked = true; } + + // Deal with HTTP challenges + function challengeCreateFn(authz, challenge, keyAuthorization) { if (challenge.type === 'http-01') { obj.challenges[challenge.token] = keyAuthorization; } } + function challengeRemoveFn(authz, challenge, keyAuthorization) { if (challenge.type === 'http-01') { delete obj.challenges[challenge.token]; } } + obj.challenge = function (token, hostname, func) { if (obj.challenges[token] != null) { obj.log("Succesful response to challenge."); } else { obj.log("Failed to respond to challenge, token: " + token + ", table: " + JSON.stringify(obj.challenges) + "."); } func(obj.challenges[token]); } + + // Get the current certificate + obj.getCertificate = function(certs, func) { + obj.runAsProduction = (obj.parent.config.letsencrypt.production === true); + obj.log("Getting certs from local store (" + (obj.runAsProduction ? "Production" : "Staging") + ")"); + if (certs.CommonName.indexOf('.') == -1) { obj.configErr = "ERROR: Use --cert to setup the default server name before using Let's Encrypt."; obj.log(obj.configErr); console.log(obj.configErr); func(certs); return; } + if (obj.parent.config.letsencrypt == null) { obj.configErr = "No Let's Encrypt configuration"; obj.log(obj.configErr); console.log(obj.configErr); func(certs); return; } + if (obj.parent.config.letsencrypt.email == null) { obj.configErr = "ERROR: Let's Encrypt email address not specified."; obj.log(obj.configErr); console.log(obj.configErr); func(certs); return; } + if ((obj.parent.redirserver == null) || ((typeof obj.parent.config.settings.rediraliasport === 'number') && (obj.parent.config.settings.rediraliasport !== 80)) || ((obj.parent.config.settings.rediraliasport == null) && (obj.parent.redirserver.port !== 80))) { obj.configErr = "ERROR: Redirection web server must be active on port 80 for Let's Encrypt to work."; obj.log(obj.configErr); console.log(obj.configErr); func(certs); return; } + if (obj.redirWebServerHooked !== true) { obj.configErr = "ERROR: Redirection web server not setup for Let's Encrypt to work."; obj.log(obj.configErr); console.log(obj.configErr); func(certs); return; } + if ((obj.parent.config.letsencrypt.rsakeysize != null) && (obj.parent.config.letsencrypt.rsakeysize !== 2048) && (obj.parent.config.letsencrypt.rsakeysize !== 3072)) { obj.configErr = "ERROR: Invalid Let's Encrypt certificate key size, must be 2048 or 3072."; obj.log(obj.configErr); console.log(obj.configErr); func(certs); return; } + if (obj.checkInterval == null) { obj.checkInterval = setInterval(obj.checkRenewCertificate, 86400000); } // Call certificate check every 24 hours. + obj.configOk = true; + + // Get the list of domains + obj.leDomains = [ certs.CommonName ]; + if (obj.parent.config.letsencrypt.names != null) { + if (typeof obj.parent.config.letsencrypt.names == 'string') { obj.parent.config.letsencrypt.names = obj.parent.config.letsencrypt.names.split(','); } + obj.parent.config.letsencrypt.names.map(function (s) { return s.trim(); }); // Trim each name + if ((typeof obj.parent.config.letsencrypt.names != 'object') || (obj.parent.config.letsencrypt.names.length == null)) { console.log("ERROR: Let's Encrypt names must be an array in config.json."); func(certs); return; } + obj.leDomains = obj.parent.config.letsencrypt.names; + } + + // Read TLS certificate from the configPath + var certFile = obj.path.join(obj.certPath, (obj.runAsProduction ? 'production.crt' : 'staging.crt')); + var keyFile = obj.path.join(obj.certPath, (obj.runAsProduction ? 'production.key' : 'staging.key')); + if (obj.fs.existsSync(certFile) && obj.fs.existsSync(keyFile)) { + obj.log("Reading certificate files"); + + // Read the certificate and private key + var certPem = obj.fs.readFileSync(certFile).toString('utf8'); + var cert = obj.forge.pki.certificateFromPem(certPem); + var keyPem = obj.fs.readFileSync(keyFile).toString('utf8'); + var key = obj.forge.pki.privateKeyFromPem(keyPem); + + // Decode the certificate common and alt names + obj.certNames = [cert.subject.getField('CN').value]; + var altNames = cert.getExtension('subjectAltName'); + if (altNames) { for (i = 0; i < altNames.altNames.length; i++) { var acn = altNames.altNames[i].value.toLowerCase(); if (obj.certNames.indexOf(acn) == -1) { obj.certNames.push(acn); } } } + + // Decode the certificate expire time + obj.certExpire = cert.validity.notAfter; + + // Use this certificate when possible on any domain + if (obj.certNames.indexOf(certs.CommonName) >= 0) { + obj.log("Setting LE cert for default domain."); + certs.web.cert = certPem; + certs.web.key = keyPem; + //certs.web.ca = [results.pems.chain]; + } + for (var i in obj.parent.config.domains) { + if ((obj.parent.config.domains[i].dns != null) && (obj.parent.certificateOperations.compareCertificateNames(obj.certNames, obj.parent.config.domains[i].dns))) { + obj.log("Setting LE cert for domain " + i + "."); + certs.dns[i].cert = certPem; + certs.dns[i].key = keyPem; + //certs.dns[i].ca = [results.pems.chain]; + } + } } else { - parent.debug('cert', "Initializing Let's Encrypt support, using GreenLock v" + greenLockVersion); + obj.log("No certificate files found"); } + func(certs); + setTimeout(obj.checkRenewCertificate, 5000); // Hold 5 seconds and check if we need to request a certificate. + } - // Check the current node version and support for generateKeyPair - if (require('crypto').generateKeyPair == null) { return null; } - if (Number(process.version.match(/^v(\d+\.\d+)/)[1]) < 10) { return null; } - - // Try to delete the "./ursa-optional" or "./node_modules/ursa-optional" folder if present. - // This is an optional module that GreenLock uses that causes issues. - try { - const fs = require('fs'); - if (fs.existsSync(parent.path.join(__dirname, 'ursa-optional'))) { fs.unlinkSync(obj.path.join(__dirname, 'ursa-optional')); } - if (fs.existsSync(parent.path.join(__dirname, 'node_modules', 'ursa-optional'))) { fs.unlinkSync(obj.path.join(__dirname, 'node_modules', 'ursa-optional')); } - } catch (ex) { } - - // Get GreenLock setup and running. - const greenlock = require('greenlock'); - var obj = {}; - globalLetsEncrypt = obj; - obj.parent = parent; - obj.path = require('path'); - obj.redirWebServerHooked = false; - obj.leDomains = null; - obj.leResults = null; - obj.leResultsStaging = null; - obj.performRestart = false; // Indicates we need to restart the server - obj.performMoveToProduction = false; // Indicates we just got a staging certificate and need to move to production - obj.runAsProduction = false; // This starts at false and moves to true if staging cert is ok. - - // Setup the certificate storage paths - obj.configPath = obj.path.join(obj.parent.datapath, 'letsencrypt3'); - try { obj.parent.fs.mkdirSync(obj.configPath); } catch (e) { } - obj.configPathStaging = obj.path.join(obj.parent.datapath, 'letsencrypt3-staging'); - try { obj.parent.fs.mkdirSync(obj.configPathStaging); } catch (e) { } - - // Setup Let's Encrypt default configuration - obj.leDefaults = { agreeToTerms: true, store: { module: 'greenlock-store-fs', basePath: obj.configPath } }; - obj.leDefaultsStaging = { agreeToTerms: true, store: { module: 'greenlock-store-fs', basePath: obj.configPathStaging } }; - - // Get package and maintainer email - const pkg = require('./package.json'); - var maintainerEmail = null; - if (typeof pkg.author == 'string') { - // Older NodeJS - maintainerEmail = pkg.author; - var i = maintainerEmail.indexOf('<'); - if (i >= 0) { maintainerEmail = maintainerEmail.substring(i + 1); } - var i = maintainerEmail.indexOf('>'); - if (i >= 0) { maintainerEmail = maintainerEmail.substring(0, i); } - } else if (typeof pkg.author == 'object') { - // Latest NodeJS - maintainerEmail = pkg.author.email; - } - - // Check if we need to be in debug mode - var ledebug = false; - try { ledebug = ((obj.parent.args.debug != null) || (obj.parent.args.debug.indexOf('cert'))); } catch (ex) { } - - // Create the main GreenLock code module for production. - var greenlockargs = { - parent: obj, - packageRoot: __dirname, - packageAgent: pkg.name + '/' + pkg.version, - manager: obj.path.join(__dirname, 'letsencrypt.js'), - maintainerEmail: maintainerEmail, - notify: function (ev, args) { if (typeof args == 'string') { parent.debug('cert', ev + ': ' + args); } else { parent.debug('cert', ev + ': ' + JSON.stringify(args)); } }, - staging: false, - debug: ledebug - }; - if (obj.parent.args.debug == null) { greenlockargs.log = function (debug) { }; } // If not in debug mode, ignore all console output from greenlock (makes things clean). - obj.le = greenlock.create(greenlockargs); - - // Create the main GreenLock code module for staging. - var greenlockargsstaging = { - parent: obj, - packageRoot: __dirname, - packageAgent: pkg.name + '/' + pkg.version, - manager: obj.path.join(__dirname, 'letsencrypt.js'), - maintainerEmail: maintainerEmail, - notify: function (ev, args) { if (typeof args == 'string') { parent.debug('cert', 'Notify: ' + ev + ': ' + args); } else { parent.debug('cert', 'Notify: ' + ev + ': ' + JSON.stringify(args)); } }, - staging: true, - debug: ledebug - }; - if (obj.parent.args.debug == null) { greenlockargsstaging.log = function (debug) { }; } // If not in debug mode, ignore all console output from greenlock (makes things clean). - obj.leStaging = greenlock.create(greenlockargsstaging); - - // Hook up GreenLock to the redirection server - if (obj.parent.config.settings.rediraliasport === 80) { obj.redirWebServerHooked = true; } - else if ((obj.parent.config.settings.rediraliasport == null) && (obj.parent.redirserver.port == 80)) { obj.redirWebServerHooked = true; } - - // Respond to a challenge - obj.challenge = function (token, hostname, func) { - if (obj.runAsProduction === true) { - // Production - parent.debug('cert', "Challenge " + hostname + "/" + token); - obj.le.challenges.get({ type: 'http-01', servername: hostname, token: token }) - .then(function (results) { func(results.keyAuthorization); }) - .catch(function (e) { console.log('LE-ERROR', e); func(null); }); // unexpected error, not related to renewal + // Check if we need to get a new certificate + // Return 0 = CertOK, 1 = Request:NoCert, 2 = Request:Expire, 3 = Request:MissingNames + obj.checkRenewCertificate = function () { + if (obj.pendingRequest == true) { obj.log("Request for certificate is in process."); return 4; } + if (obj.certNames == null) { + obj.log("Got no certificates, asking for one now."); + obj.requestCertificate(); + return 1; + } else { + // Look at the existing certificate to see if we need to renew it + var daysLeft = Math.floor((obj.certExpire - new Date()) / 86400000); + obj.log("Certificate has " + daysLeft + " day(s) left."); + if (daysLeft < 45) { + obj.log("Asking for new certificate because of expire time."); + obj.requestCertificate(); + return 2; } else { - // Staging - parent.debug('cert', "Challenge " + hostname + "/" + token); - obj.leStaging.challenges.get({ type: 'http-01', servername: hostname, token: token }) - .then(function (results) { func(results.keyAuthorization); }) - .catch(function (e) { console.log('LE-ERROR', e); func(null); }); // unexpected error, not related to renewal - } - } - - obj.getCertificate = function(certs, func) { - parent.debug('cert', "Getting certs from local store"); - if (certs.CommonName.indexOf('.') == -1) { console.log("ERROR: Use --cert to setup the default server name before using Let's Encrypt."); func(certs); return; } - if (obj.parent.config.letsencrypt == null) { func(certs); return; } - if (obj.parent.config.letsencrypt.email == null) { console.log("ERROR: Let's Encrypt email address not specified."); func(certs); return; } - if ((obj.parent.redirserver == null) || ((typeof obj.parent.config.settings.rediraliasport === 'number') && (obj.parent.config.settings.rediraliasport !== 80)) || ((obj.parent.config.settings.rediraliasport == null) && (obj.parent.redirserver.port !== 80))) { console.log("ERROR: Redirection web server must be active on port 80 for Let's Encrypt to work."); func(certs); return; } - if (obj.redirWebServerHooked !== true) { console.log("ERROR: Redirection web server not setup for Let's Encrypt to work."); func(certs); return; } - if ((obj.parent.config.letsencrypt.rsakeysize != null) && (obj.parent.config.letsencrypt.rsakeysize !== 2048) && (obj.parent.config.letsencrypt.rsakeysize !== 3072)) { console.log("ERROR: Invalid Let's Encrypt certificate key size, must be 2048 or 3072."); func(certs); return; } - - // Get the list of domains - obj.leDomains = [ certs.CommonName ]; - if (obj.parent.config.letsencrypt.names != null) { - if (typeof obj.parent.config.letsencrypt.names == 'string') { obj.parent.config.letsencrypt.names = obj.parent.config.letsencrypt.names.split(','); } - obj.parent.config.letsencrypt.names.map(function (s) { return s.trim(); }); // Trim each name - if ((typeof obj.parent.config.letsencrypt.names != 'object') || (obj.parent.config.letsencrypt.names.length == null)) { console.log("ERROR: Let's Encrypt names must be an array in config.json."); func(certs); return; } - obj.leDomains = obj.parent.config.letsencrypt.names; - } - - if (obj.parent.config.letsencrypt.production !== true) { - // We are in staging mode, just go ahead - obj.getCertificateEx(certs, func); - } else { - // We are really in production mode - if (obj.runAsProduction === true) { - // Staging cert check must have been done already, move to production - obj.getCertificateEx(certs, func); + var missingDomain = false; + for (var i in obj.leDomains) { + if (obj.parent.certificateOperations.compareCertificateNames(obj.certNames, obj.leDomains[i]) == false) { + obj.log("Missing name \"" + obj.leDomains[i] + "\"."); + missingDomain = true; + } + } + if (missingDomain) { + obj.log("Asking for new certificate because of missing names."); + obj.requestCertificate(); + return 3; } else { - // Perform staging certificate check - parent.debug('cert', "Checking staging certificate " + obj.leDomains[0] + "..."); - obj.leStaging.get({ servername: obj.leDomains[0] }) - .then(function (results) { - if (results != null) { - // We have a staging certificate, move to production for real - parent.debug('cert', "Staging certificate is present, moving to production..."); - obj.runAsProduction = true; - obj.getCertificateEx(certs, func); - } else { - // No staging certificate - parent.debug('cert', "No staging certificate present"); - func(certs); - setTimeout(obj.checkRenewCertificate, 10000); // Check the certificate in 10 seconds. - } - }) - .catch(function (e) { - // No staging certificate - parent.debug('cert', "No staging certificate present"); - func(certs); - setTimeout(obj.checkRenewCertificate, 10000); // Check the certificate in 10 seconds. - }); + obj.log("Certificate is ok."); } } } + return 0; + } - obj.getCertificateEx = function (certs, func) { - // Get the Let's Encrypt certificate from our own storage - const xle = (obj.runAsProduction === true)? obj.le : obj.leStaging; - xle.get({ servername: obj.leDomains[0] }) - .then(function (results) { - // If we already have real certificates, use them - if (results) { - if (results.site.altnames.indexOf(certs.CommonName) >= 0) { - certs.web.cert = results.pems.cert; - certs.web.key = results.pems.privkey; - certs.web.ca = [results.pems.chain]; - } - for (var i in obj.parent.config.domains) { - if ((obj.parent.config.domains[i].dns != null) && (obj.parent.certificateOperations.compareCertificateNames(results.site.altnames, obj.parent.config.domains[i].dns))) { - certs.dns[i].cert = results.pems.cert; - certs.dns[i].key = results.pems.privkey; - certs.dns[i].ca = [results.pems.chain]; - } - } - } - parent.debug('cert', "Got certs from local store (" + (obj.runAsProduction ? "Production" : "Staging") + ")"); - func(certs); + obj.requestCertificate = function () { + if (obj.pendingRequest == true) return; + if (obj.configOk == false) { obj.log("Can't request cert, invalid configuration.");return; } + obj.pendingRequest = true; - // Check if the Let's Encrypt certificate needs to be renewed. - setTimeout(obj.checkRenewCertificate, 60000); // Check in 1 minute. - setInterval(obj.checkRenewCertificate, 86400000); // Check again in 24 hours and every 24 hours. - return; - }) - .catch(function (e) { - parent.debug('cert', "Unable to get certs from local store (" + (obj.runAsProduction ? "Production" : "Staging") + ")"); - setTimeout(obj.checkRenewCertificate, 10000); // Check the certificate in 10 seconds. - func(certs); + // Create a private key + obj.log("Generating private key..."); + acme.forge.createPrivateKey().then(function (accountKey) { + // Create the ACME client + obj.log("Setting up ACME client..."); + obj.client = new acme.Client({ + directoryUrl: obj.runAsProduction ? acme.directory.letsencrypt.production : acme.directory.letsencrypt.staging, + accountKey: accountKey + }); + + // Create Certificate Request (CSR) + obj.log("Creating certificate request..."); + acme.forge.createCsr({ + commonName: obj.leDomains[0], + altNames: obj.leDomains + }).then(function (r) { + var csr = r[1]; + obj.tempPrivateKey = r[0]; + obj.log("Requesting certificate from Let's Encrypt..."); + obj.client.auto({ + csr, + email: obj.parent.config.letsencrypt.email, + termsOfServiceAgreed: true, + challengeCreateFn, + challengeRemoveFn + }).then(function (cert) { + obj.log("Got certificate."); + + // Save certificate and private key to PEM files + var certFile = obj.path.join(obj.certPath, (obj.runAsProduction ? 'production.crt' : 'staging.crt')); + var keyFile = obj.path.join(obj.certPath, (obj.runAsProduction ? 'production.key' : 'staging.key')); + obj.fs.writeFileSync(certFile, cert); + obj.fs.writeFileSync(keyFile, obj.tempPrivateKey); + delete obj.tempPrivateKey; + + // Cause a server restart + obj.log("Performing server restart..."); + obj.parent.performServerCertUpdate(); + }, function (err) { + obj.log("Failed to obtain certificate: " + err.message); + obj.pendingRequest = false; + delete obj.client; }); - } + }, function (err) { + obj.log("Failed to generate certificate request: " + err.message); + obj.pendingRequest = false; + delete obj.client; + }); + }, function (err) { + obj.log("Failed to generate private key: " + err.message); + obj.pendingRequest = false; + delete obj.client; + }); + } - // Check if we need to renew the certificate, call this every day. - obj.checkRenewCertificate = function () { - parent.debug('cert', "Checking certificate for " + obj.leDomains[0] + " (" + (obj.runAsProduction ? "Production" : "Staging") + ")"); - - // Setup renew options - obj.certCheckStart = Date.now(); - const xle = (obj.runAsProduction === true) ? obj.le : obj.leStaging; - var renewOptions = { servername: obj.leDomains[0], altnames: obj.leDomains }; - try { - xle.renew(renewOptions) - .then(function (results) { - if ((results == null) || (typeof results != 'object') || (results.length == 0) || (results[0].error != null)) { - parent.debug('cert', "Unable to get a certificate (" + (obj.runAsProduction ? "Production" : "Staging") + ", " + (Date.now() - obj.certCheckStart) + "ms): " + JSON.stringify(results)); - } else { - parent.debug('cert', "Checks completed (" + (obj.runAsProduction ? "Production" : "Staging") + ", " + (Date.now() - obj.certCheckStart) + "ms): " + JSON.stringify(results)); - if (obj.performRestart === true) { parent.debug('cert', "Certs changed, restarting..."); obj.parent.performServerCertUpdate(); } // Reset the server, TODO: Reset all peers - else if (obj.performMoveToProduction == true) { - parent.debug('cert', "Staging certificate received, moving to production..."); - obj.runAsProduction = true; - obj.performMoveToProduction = false; - obj.performRestart = true; - setTimeout(obj.checkRenewCertificate, 10000); // Check the certificate in 10 seconds. - } - } - }) - .catch(function (ex) { - parent.debug('cert', "checkCertificate exception: (" + JSON.stringify(ex) + ")"); - console.log(ex); - }); - } catch (ex) { - parent.debug('cert', "checkCertificate main exception: (" + JSON.stringify(ex) + ")"); - console.log(ex); - } - } - - return obj; - } catch (ex) { console.log(ex); } // Unable to start Let's Encrypt - return null; -}; - -// GreenLock v3 Manager -module.exports.create = function (options) { - var manager = { parent: globalLetsEncrypt }; - manager.find = async function (options) { - //console.log('LE-FIND', options); - return Promise.resolve([{ subject: options.servername, altnames: options.altnames }]); - }; - - manager.set = function (options) { - manager.parent.parent.debug('cert', "Certificate has been set: " + JSON.stringify(options)); - if (manager.parent.parent.config.letsencrypt.production == manager.parent.runAsProduction) { manager.parent.performRestart = true; } - else if ((manager.parent.parent.config.letsencrypt.production === true) && (manager.parent.runAsProduction === false)) { manager.parent.performMoveToProduction = true; } - return null; - }; - - manager.remove = function (options) { - manager.parent.parent.debug('cert', "Certificate has been removed: " + JSON.stringify(options)); - if (manager.parent.parent.config.letsencrypt.production == manager.parent.runAsProduction) { manager.parent.performRestart = true; } - else if ((manager.parent.parent.config.letsencrypt.production === true) && (manager.parent.runAsProduction === false)) { manager.parent.performMoveToProduction = true; } - return null; - }; - - // set the global config - manager.defaults = async function (options) { - var r; - if (manager.parent.runAsProduction === true) { - // Production - //console.log('LE-DEFAULTS-Production', options); - if (options != null) { for (var i in options) { if (manager.parent.leDefaults[i] == null) { manager.parent.leDefaults[i] = options[i]; } } } - r = manager.parent.leDefaults; - r.subscriberEmail = manager.parent.parent.config.letsencrypt.email; - r.sites = { mainsite: { subject: manager.parent.leDomains[0], altnames: manager.parent.leDomains } }; - } else { - // Staging - //console.log('LE-DEFAULTS-Staging', options); - if (options != null) { for (var i in options) { if (manager.parent.leDefaultsStaging[i] == null) { manager.parent.leDefaultsStaging[i] = options[i]; } } } - r = manager.parent.leDefaultsStaging; - r.subscriberEmail = manager.parent.parent.config.letsencrypt.email; - r.sites = { mainsite: { subject: manager.parent.leDomains[0], altnames: manager.parent.leDomains } }; - } + // Return the status of this module + obj.getStats = function () { + var r = { + configOk: obj.configOk, + leDomains: obj.leDomains, + challenges: obj.challenges, + production: obj.runAsProduction, + webServer: obj.redirWebServerHooked, + certPath: obj.certPath + }; + if (obj.configErr) { r.error = obj.configErr; } + if (obj.certExpire) { r.cert = 'Present'; r.daysLeft = Math.floor((obj.certExpire - new Date()) / 86400000); } else { r.cert = 'None'; } return r; - }; + } - return manager; -}; \ No newline at end of file + return obj; +} \ No newline at end of file diff --git a/mcrec.js b/mcrec.js new file mode 100644 index 00000000..51fc7927 --- /dev/null +++ b/mcrec.js @@ -0,0 +1,334 @@ +/** +* @description MeshCentral MeshAgent +* @author Ylian Saint-Hilaire +* @copyright Intel Corporation 2019-2020 +* @license Apache-2.0 +* @version v0.0.1 +*/ + +var fs = require('fs'); +var path = require('path'); + +var worker = null; +const NodeJSVer = Number(process.version.match(/^v(\d+\.\d+)/)[1]); +var directRun = (require.main === module); +function log() { if (directRun) { console.log(...arguments); } /*else { if (worker != null) { worker.parentPort.postMessage({ msg: arguments[0] }); } } */ } +if (directRun && (NodeJSVer >= 12)) { const xworker = require('worker_threads'); try { if (xworker.isMainThread == false) { worker = xworker; } } catch (ex) { log(ex); } } +function start() { startEx(process.argv); } +if (directRun) { setup(); } + +function setup() { InstallModules(['image-size'], start); } +function start() { startEx(process.argv); } +function startEx(argv) { + if (argv.length > 2) { indexFile(argv[2]); } else { + log("MeshCentral Session Recodings Processor"); + log("This tool will index a .mcrec file so that the player can seek thru the file."); + log(""); + log(" Usage: node mcrec [file]"); + } +} + +function indexFile(infile) { + var state = { recFileName: null, recFile: null, recFileSize: 0, recFilePtr: 0 }; + if (fs.existsSync(infile) == false) { log("Missing file: " + infile); return; } + state.recFileName = infile; + state.recFileSize = fs.statSync(infile).size; + if (state.recFileSize < 32) { log("Invalid file: " + infile); return; } + log("Processing file: " + infile + ", " + state.recFileSize + " bytes."); + state.recFile = fs.openSync(infile, 'r+'); + state.indexTime = 10; // Interval between indexes in seconds + state.lastIndex = 0; // Last time an index was writen in seconds + state.indexes = []; + state.width = 0; + state.height = 0; + state.basePtr = null; + readLastBlock(state, function (state, result, time, extras) { + if (result == false) { log("Invalid file: " + infile); return; } + if (extras != null) { log("File already indexed: " + infile); return; } + state.lastTimeStamp = time; + readNextBlock(state, processBlock); + }); +} + +function createIndex(state, ptr) { + var index = []; + for (var i in state.screen) { if (index.indexOf(state.screen[i]) == -1) { index.push(state.screen[i]); } } + index.sort(function (a, b) { return a - b }); + index.unshift(state.height); + index.unshift(state.width); + index.unshift(ptr - state.basePtr); + state.indexes.push(index); // Index = [ Ptr, Width, Height, Block Pointers... ] + //log('Index', state.lastIndex, index.length); + //log('Index', index); + state.lastIndex += 10; +} + +function processBlock(state, block, err) { + if (err != null) { + // Error reading the next block, exit now. + fs.close(state.recFile, function () { + for (var i in state) { delete state[i]; } // Clear the state. + log("Error."); + }); + return; + } + if (block == null) { + // We are done, close this file. + writeIndex(state, function () { + fs.close(state.recFile, function () { + for (var i in state) { delete state[i]; } // Clear the state. + log("Done."); + }); + }); + return; + } + var elapseMilliSeconds = 0; + if (state.startTime != null) { elapseMilliSeconds = (block.time - state.startTime); } + var flagBinary = (block.flags & 1) != 0; + var flagUser = (block.flags & 2) != 0; + + // Start indexing at the first type 2 block + if ((state.basePtr == null) && (block.type == 2)) { state.basePtr = block.ptr; state.startTime = block.time; } + + // Check if we need to create one or more indexes + while (((state.lastIndex + state.indexTime) * 1000) < elapseMilliSeconds) { createIndex(state, block.ptr); } + + if (block.type == 1) { + // Metadata + state.metadata = JSON.parse(block.data.toString()); + if (state.metadata.indexInterval != null) { log("This file is already indexed."); return; } + if (state.metadata.protocol != 2) { log("Only remote desktop sessions can currently be indexed."); return; } + state.metadataFlags = block.flags; + state.metadataTime = block.time; + state.recFileProtocol = state.metadata.protocol; + state.dataStartPtr = state.recFilePtr; + if (typeof state.recFileProtocol == 'string') { state.recFileProtocol = parseInt(state.recFileProtocol); } + } else if ((block.type == 2) && flagBinary && !flagUser) { + // Device --> User data + if (state.recFileProtocol == 1) { + // MeshCentral Terminal + // TODO + log('Terminal'); + } else if (state.recFileProtocol == 2) { + // MeshCentral Remote Desktop + // TODO + if (block.data.length >= 4) { + var command = block.data.readUInt16BE(0); + var cmdsize = block.data.readUInt16BE(2); + if ((command == 27) && (cmdsize == 8)) { + // Jumbo packet + if (block.data.length >= 12) { + command = block.data.readUInt16BE(8); + cmdsize = block.data.readUInt32BE(4); + if (block.data.length == (cmdsize + 8)) { + block.data = block.data.slice(8, block.data.length); + } else { + console.log('TODO-PARTIAL-JUMBO', command, cmdsize, block.data.length); + return; // TODO + } + } + } + + switch (command) { + case 3: // Tile + var x = block.data.readUInt16BE(4); + var y = block.data.readUInt16BE(6); + var dimensions = require('image-size')(block.data.slice(8)); + //log("Tile", x, y, dimensions.width, dimensions.height, block.ptr); + //console.log(elapseSeconds); + + // Update the screen with the correct pointers. + var sx = x/16, sy = y/16, sw = dimensions.width/16, sh = dimensions.height/16; + for (var i = 0; i < sw; i++) { + for (var j = 0; j < sh; j++) { + var k = ((state.swidth * (j + sy)) + (i + sx)); + state.screen[k] = (block.ptr - state.basePtr); + } + } + + break; + case 4: // Tile copy + var x = block.data.readUInt16BE(4); + var y = block.data.readUInt16BE(6); + //log("TileCopy", x, y); + break; + case 7: // Screen Size, clear the screen state and computer the tile count + state.width = block.data.readUInt16BE(4); + state.height = block.data.readUInt16BE(6); + state.swidth = state.width / 16; + state.sheight = state.height / 16; + if (Math.floor(state.swidth) != state.swidth) { state.swidth = Math.floor(state.swidth) + 1; } + if (Math.floor(state.sheight) != state.sheight) { state.sheight = Math.floor(state.sheight) + 1; } + state.screen = {}; + //log("ScreenSize", state.width, state.height, state.swidth, state.sheight, state.swidth * state.sheight); + break; + } + + //log('Desktop', command, cmdsize); + } + } else if (state.recFileProtocol == 101) { + // Intel AMT KVM + // TODO + log('AMTKVM'); + } + } else if ((block.type == 2) && flagBinary && flagUser) { + // User --> Device data + if (state.recFileProtocol == 101) { + // Intel AMT KVM + //if (rstr2hex(data) == '0000000008080001000700070003050200000000') { amtDesktop.bpp = 1; } // Switch to 1 byte per pixel. + } + } + + //console.log(block); + readNextBlock(state, processBlock); +} + +function writeIndex(state, func) { + // Add the new indexes in extra metadata at the end of the file. + var extraMetadata = {}; + extraMetadata.indexInterval = state.indexTime; + extraMetadata.indexStartTime = state.startTime; + extraMetadata.indexes = state.indexes; + recordingEntry(state.recFile, 4, 0, state.lastTimeStamp, JSON.stringify(extraMetadata), function (state, len) { + recordingEntry(state.recFile, 3, 0, state.recFileSize - 32, 'MeshCentralMCNDX', function (state) { + func(state); + }, state, state.recFileSize - 32 + len); + }, state, state.recFileSize - 32); +} + +// Record a new entry in a recording log +function recordingEntry(fd, type, flags, time, data, func, tag, position) { + try { + if (typeof data == 'string') { + // String write + var blockData = Buffer.from(data), header = Buffer.alloc(16); // Header: Type (2) + Flags (2) + Size(4) + Time(8) + header.writeInt16BE(type, 0); // Type (1 = Header, 2 = Network Data, 3 = End, 4 = Extra Metadata) + header.writeInt16BE(flags, 2); // Flags (1 = Binary, 2 = User) + header.writeInt32BE(blockData.length, 4); // Size + header.writeIntBE(time, 10, 6); // Time + var block = Buffer.concat([header, blockData]); + if (typeof position == 'number') { + fs.write(fd, block, 0, block.length, position, function () { func(tag, block.length); }); + } else { + fs.write(fd, block, 0, block.length, function () { func(tag, block.length); }); + } + } else { + // Binary write + var header = Buffer.alloc(16); // Header: Type (2) + Flags (2) + Size(4) + Time(8) + header.writeInt16BE(type, 0); // Type (1 = Header, 2 = Network Data, 3 = End, 4 = Extra Metadata) + header.writeInt16BE(flags | 1, 2); // Flags (1 = Binary, 2 = User) + header.writeInt32BE(data.length, 4); // Size + header.writeIntBE(time, 10, 6); // Time + var block = Buffer.concat([header, data]); + if (typeof position == 'number') { + fs.write(fd, block, 0, block.length, position, function () { func(tag, block.length); }); + } else { + fs.write(fd, block, 0, block.length, function () { func(tag, block.length); }); + } + } + } catch (ex) { console.log(ex); func(tag); } +} + +function readLastBlock(state, func) { + var buf = Buffer.alloc(32); + fs.read(state.recFile, buf, 0, 32, state.recFileSize - 32, function (err, bytesRead, buf) { + var type = buf.readUInt16BE(0); // Type (1 = Header, 2 = Network Data) + var flags = buf.readUInt16BE(2); // Flags (1 = Binary, 2 = User) + var size = buf.readUInt32BE(4); // Size + var time = buf.readUIntBE(10, 6); // Time + var magic = buf.toString('utf8', 16, 32); + if ((type == 3) && (size == 16) && (magic == 'MeshCentralMCNDX')) { + // Extra metadata present, lets read it. + extraMetadata = null; + var buf2 = Buffer.alloc(16); + fs.read(state.recFile, buf2, 0, 16, time, function (err, bytesRead, buf2) { + var xtype = buf2.readUInt16BE(0); // Type (1 = Header, 2 = Network Data, 3 = End, 4 = Extra Metadata) + var xflags = buf2.readUInt16BE(2); // Flags (1 = Binary, 2 = User) + var xsize = buf2.readUInt32BE(4); // Size + var xtime = buf.readUIntBE(10, 6); // Time + var buf3 = Buffer.alloc(xsize); + fs.read(state.recFile, buf3, 0, xsize, time + 16, function (err, bytesRead, buf3) { + func(state, true, xtime, JSON.parse(buf3.toString())); + }); + }); + } else { + // No extra metadata or fail + func(state, (type == 3) && (size == 16) && (magic == 'MeshCentralMCREC'), time, null); + } + }); +} + +function readNextBlock(state, func) { + if ((state.recFilePtr + 16) > state.recFileSize) { func(state, null); return; } + var r = {}, buf = Buffer.alloc(16); + fs.read(state.recFile, buf, 0, 16, state.recFilePtr, function (err, bytesRead, buf) { + if (bytesRead != 16) { func(state, null, true); return; } // Error + try { + r.type = buf.readUInt16BE(0); // Type (1 = Header, 2 = Network Data, 3 = End, 4 = Extra Metadata) + r.flags = buf.readUInt16BE(2); // Flags (1 = Binary, 2 = User) + r.size = buf.readUInt32BE(4); // Size + r.time = buf.readUIntBE(10, 6); // Time + r.date = new Date(r.time); + r.ptr = state.recFilePtr; + if ((state.recFilePtr + 16 + r.size) > state.recFileSize) { func(state, null, true); return; } // Error + if (r.size == 0) { + r.data = null; + func(state, r); + } else { + r.data = Buffer.alloc(r.size); + fs.read(state.recFile, r.data, 0, r.size, state.recFilePtr + 16, function (err, bytesRead, buf) { + state.recFilePtr += (16 + r.size); + func(state, r); + }); + } + } catch (ex) { func(state, null, true); return; } // Error + }); +} + +function isNumber(x) { return (('' + parseInt(x)) === x) || (('' + parseFloat(x)) === x); } +function format(format) { var args = Array.prototype.slice.call(arguments, 1); return format.replace(/{(\d+)}/g, function (match, number) { return typeof args[number] != 'undefined' ? args[number] : match; }); }; + +// Check if a list of modules are present and install any missing ones +var InstallModuleChildProcess = null; +var previouslyInstalledModules = {}; +function InstallModules(modules, func) { + var missingModules = []; + if (previouslyInstalledModules == null) { previouslyInstalledModules = {}; } + if (modules.length > 0) { + for (var i in modules) { + try { + var xxmodule = require(modules[i]); + } catch (e) { + if (previouslyInstalledModules[modules[i]] !== true) { missingModules.push(modules[i]); } + } + } + if (missingModules.length > 0) { InstallModule(missingModules.shift(), InstallModules, modules, func); } else { func(); } + } +} + +// Check if a module is present and install it if missing +function InstallModule(modulename, func, tag1, tag2) { + log('Installing ' + modulename + '...'); + var child_process = require('child_process'); + var parentpath = __dirname; + + // Get the working directory + if ((__dirname.endsWith('/node_modules/meshcentral')) || (__dirname.endsWith('\\node_modules\\meshcentral')) || (__dirname.endsWith('/node_modules/meshcentral/')) || (__dirname.endsWith('\\node_modules\\meshcentral\\'))) { parentpath = require('path').join(__dirname, '../..'); } + + // Looks like we need to keep a global reference to the child process object for this to work correctly. + InstallModuleChildProcess = child_process.exec('npm install --no-optional --save ' + modulename, { maxBuffer: 512000, timeout: 120000, cwd: parentpath }, function (error, stdout, stderr) { + InstallModuleChildProcess = null; + if ((error != null) && (error != '')) { + log('ERROR: Unable to install required module "' + modulename + '". May not have access to npm, or npm may not have suffisent rights to load the new module. Try "npm install ' + modulename + '" to manualy install this module.\r\n'); + process.exit(); + return; + } + previouslyInstalledModules[modulename] = true; + func(tag1, tag2); + return; + }); +} + +// Export table +module.exports.startEx = startEx; +module.exports.indexFile = indexFile; \ No newline at end of file diff --git a/meshaccelerator.js b/meshaccelerator.js index 4432c951..bd7635c3 100644 --- a/meshaccelerator.js +++ b/meshaccelerator.js @@ -21,7 +21,10 @@ var certStore = null; process.on('disconnect', function () { process.exit(); }); // Handle parent messages -process.on('message', function (message) { +process.on('message', function (message) { module.exports.processMessage(message); }); + +// Process an incoming message +module.exports.processMessage = function(message) { switch (message.action) { case 'sign': { if (typeof message.key == 'number') { message.key = certStore[message.key].key; } @@ -36,9 +39,14 @@ process.on('message', function (message) { certStore = message.certs; break; } + case 'indexMcRec': { + //console.log('indexMcRec', message.data); + require(require('path').join(__dirname, 'mcrec.js')).indexFile(message.data); + break; + } default: { console.log('Unknown accelerator action: ' + message.action + '.'); break; } } -}); \ No newline at end of file +} \ No newline at end of file diff --git a/meshagent.js b/meshagent.js index 49f85aa9..60736866 100644 --- a/meshagent.js +++ b/meshagent.js @@ -72,7 +72,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { db.removeAllPowerEventsForNode(obj.dbNodeKey); // Remove all power events for this node // Event node deletion - parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(obj.dbMeshKey), obj, { etype: 'node', action: 'removenode', nodeid: obj.dbNodeKey, domain: domain.id, nolog: 1 }); + parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(obj.dbMeshKey, [obj.dbNodeKey]), obj, { etype: 'node', action: 'removenode', nodeid: obj.dbNodeKey, domain: domain.id, nolog: 1 }); // Disconnect all connections if needed const state = parent.parent.GetConnectivityState(obj.dbNodeKey); @@ -214,7 +214,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { obj.sendBinary(common.ShortToStr(10) + common.ShortToStr(0)); // Command 10, ask mesh agent to clear the core } else { // Update new core - if (parent.parent.meshAgentsArchitectureNumbers[obj.agentInfo.agentId].amt == true) { + if ((parent.parent.meshAgentsArchitectureNumbers[obj.agentInfo.agentId] != null) && (parent.parent.meshAgentsArchitectureNumbers[obj.agentInfo.agentId].amt == true)) { obj.sendBinary(common.ShortToStr(10) + common.ShortToStr(0) + parent.parent.defaultMeshCoreHash + parent.parent.defaultMeshCore); // Command 10, ask mesh agent to set the core (with MEI support) } else { obj.sendBinary(common.ShortToStr(10) + common.ShortToStr(0) + parent.parent.defaultMeshCoreNoMeiHash + parent.parent.defaultMeshCoreNoMei); // Command 10, ask mesh agent to set the core (No MEI) @@ -398,7 +398,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { parent.parent.updateProxyCertificates(false); } parent.agentStats.agentBadWebCertHashCount++; - console.log('Agent bad web cert hash (Agent:' + (Buffer.from(msg.substring(2, 50), 'binary').toString('hex').substring(0, 10)) + ' != Server:' + (Buffer.from(getWebCertHash(domain), 'binary').toString('hex').substring(0, 10)) + ' or ' + (new Buffer(getWebCertFullHash(domain), 'binary').toString('hex').substring(0, 10)) + '), holding connection (' + obj.remoteaddrport + ').'); + console.log('Agent bad web cert hash (Agent:' + (Buffer.from(msg.substring(2, 50), 'binary').toString('hex').substring(0, 10)) + ' != Server:' + (Buffer.from(getWebCertHash(domain), 'binary').toString('hex').substring(0, 10)) + ' or ' + (Buffer.from(getWebCertFullHash(domain), 'binary').toString('hex').substring(0, 10)) + '), holding connection (' + obj.remoteaddrport + ').'); console.log('Agent reported web cert hash:' + (Buffer.from(msg.substring(2, 50), 'binary').toString('hex')) + '.'); return; } @@ -549,18 +549,18 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { const links = {}; links[adminUser._id] = { name: adminUser.name, rights: 0xFFFFFFFF }; mesh = { type: 'mesh', _id: obj.dbMeshKey, name: meshname, mtype: 2, desc: '', domain: domain.id, links: links }; - db.Set(common.escapeLinksFieldName(mesh)); + db.Set(mesh); parent.meshes[obj.dbMeshKey] = mesh; if (adminUser.links == null) adminUser.links = {}; adminUser.links[obj.dbMeshKey] = { rights: 0xFFFFFFFF }; db.SetUser(adminUser); - parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(obj.dbMeshKey, [adminUser._id]), obj, { etype: 'mesh', username: adminUser.name, meshid: obj.dbMeshKey, name: meshname, mtype: 2, desc: '', action: 'createmesh', links: links, msg: 'Mesh created: ' + obj.meshid, domain: domain.id }); + parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(obj.dbMeshKey, [adminUser._id, obj.dbNodeKey]), obj, { etype: 'mesh', username: adminUser.name, meshid: obj.dbMeshKey, name: meshname, mtype: 2, desc: '', action: 'createmesh', links: links, msg: 'Mesh created: ' + obj.meshid, domain: domain.id }); } } else { if ((mesh != null) && (mesh.deleted != null) && (mesh.links)) { // Must un-delete this mesh - var ids = parent.CreateMeshDispatchTargets(mesh._id); + var ids = parent.CreateMeshDispatchTargets(mesh._id, [obj.dbNodeKey]); // See if users still exists, if so, add links to the mesh for (var userid in mesh.links) { @@ -580,7 +580,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { // Mark the mesh as active delete mesh.deleted; - db.Set(common.escapeLinksFieldName(mesh)); + db.Set(mesh); } } return mesh; @@ -638,15 +638,15 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { var links = {}; links[user._id] = { name: adminUser.name, rights: 0xFFFFFFFF }; mesh = { type: 'mesh', _id: obj.dbMeshKey, name: obj.meshid, mtype: 2, desc: '', domain: domain.id, links: links }; - db.Set(common.escapeLinksFieldName(mesh)); + db.Set(mesh); parent.meshes[obj.meshid] = mesh; - parent.parent.AddEventDispatch(parent.CreateMeshDispatchTargets(obj.meshid), ws); + parent.parent.AddEventDispatch(parent.CreateMeshDispatchTargets(obj.meshid, [obj.dbNodeKey]), ws); if (adminUser.links == null) user.links = {}; adminUser.links[obj.meshid] = { rights: 0xFFFFFFFF }; //adminUser.subscriptions = parent.subscribe(adminUser._id, ws); db.SetUser(user); - parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(meshid, [user._id]), obj, { etype: 'mesh', username: user.name, meshid: obj.meshid, name: obj.meshid, mtype: 2, desc: '', action: 'createmesh', links: links, msg: 'Mesh created: ' + obj.meshid, domain: domain.id }); + parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(meshid, [user._id, obj.dbNodeKey]), obj, { etype: 'mesh', username: user.name, meshid: obj.meshid, name: obj.meshid, mtype: 2, desc: '', action: 'createmesh', links: links, msg: 'Mesh created: ' + obj.meshid, domain: domain.id }); } } @@ -687,7 +687,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { device = nodes[0]; // This device exists, meshid given by the device must be ignored, use the server side one. - if (device.meshid != obj.dbMeshKey) { + if ((device.meshid != null) && (device.meshid != obj.dbMeshKey)) { obj.dbMeshKey = device.meshid; obj.meshid = device.meshid.split('/')[2]; } @@ -709,7 +709,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { parent.agentStats.invalidMeshType2Count++; console.log('Agent connected with invalid mesh type, holding connection (' + obj.remoteaddrport + ').'); return; - } + } // Mark when this device connected obj.connectTime = Date.now(); @@ -741,7 +741,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { var event = { etype: 'node', action: 'changenode', nodeid: obj.dbNodeKey, domain: domain.id, node: parent.CloneSafeNode(device) }; if (log == 0) { event.nolog = 1; } else { event.msg = 'Changed device ' + device.name + ' from group ' + mesh.name + ': ' + changes.join(', '); } if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the node. Another event will come. - parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(device.meshid), obj, event); + parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(device.meshid, [obj.dbNodeKey]), obj, event); } } @@ -781,9 +781,9 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { // Event the new node if (obj.agentInfo.capabilities & 0x20) { // This is a temporary agent, don't log. - parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(obj.dbMeshKey), obj, { etype: 'node', action: 'addnode', node: device, domain: domain.id, nolog: 1 }); + parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(obj.dbMeshKey, [obj.dbNodeKey]), obj, { etype: 'node', action: 'addnode', node: device, domain: domain.id, nolog: 1 }); } else { - parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(obj.dbMeshKey), obj, { etype: 'node', action: 'addnode', node: device, msg: ('Added device ' + obj.agentInfo.computerName + ' to mesh ' + mesh.name), domain: domain.id }); + parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(obj.dbMeshKey, [obj.dbNodeKey]), obj, { etype: 'node', action: 'addnode', node: device, msg: ('Added device ' + obj.agentInfo.computerName + ' to mesh ' + mesh.name), domain: domain.id }); } completeAgentConnection3(device, mesh); @@ -907,10 +907,8 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { //console.log('recoveryAgentCoreIsStable()'); // Fetch the the real agent nodeid - db.Get('da' + obj.dbNodeKey, function (err, nodes, self) - { - if ((nodes != null) && (nodes.length == 1)) - { + db.Get('da' + obj.dbNodeKey, function (err, nodes, self) { + if ((nodes != null) && (nodes.length == 1)) { self.realNodeKey = nodes[0].raid; // Get agent connection state @@ -919,8 +917,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { if (state) { agentConnected = ((state.connectivity & 1) != 0) } self.send(JSON.stringify({ action: 'diagnostic', value: { command: 'query', value: self.realNodeKey, agent: agentConnected } })); - } else - { + } else { self.send(JSON.stringify({ action: 'diagnostic', value: { command: 'query', value: null } })); } }, obj); @@ -1051,7 +1048,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { // Not a valid signature parent.agentStats.invalidPkcsSignatureCount++; return false; - } + } } catch (ex) { }; } } @@ -1114,7 +1111,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { } catch (ex) { } // Event the node interface information change (This is a lot of traffic, probably don't need this). - //parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(obj.meshid), obj, { action: 'smBiosChange', nodeid: obj.dbNodeKey, domain: domain.id, smbios: command.value, nolog: 1 }); + //parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(obj.meshid, [obj.dbNodeKey]), obj, { action: 'smBiosChange', nodeid: obj.dbNodeKey, domain: domain.id, smbios: command.value, nolog: 1 }); break; } @@ -1128,7 +1125,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { db.Set(command); // Event the node interface information change - parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(obj.meshid), obj, { action: 'ifchange', nodeid: obj.dbNodeKey, domain: domain.id, nolog: 1 }); + parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(obj.meshid, [obj.dbNodeKey]), obj, { action: 'ifchange', nodeid: obj.dbNodeKey, domain: domain.id, nolog: 1 }); break; } @@ -1167,7 +1164,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { // Event node deletion const change = 'Migrated device ' + node.name; - parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(node.meshid), obj, { etype: 'node', action: 'removenode', nodeid: node._id, msg: change, domain: node.domain }); + parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(node.meshid, [obj.dbNodeKey]), obj, { etype: 'node', action: 'removenode', nodeid: node._id, msg: change, domain: node.domain }); } }); break; @@ -1183,7 +1180,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { // Log a value in the event log if ((typeof command.msg == 'string') && (command.msg.length < 4096)) { var event = { etype: 'node', action: 'agentlog', nodeid: obj.dbNodeKey, domain: domain.id, msg: command.msg }; - var targets = parent.CreateMeshDispatchTargets(obj.dbMeshKey); + var targets = parent.CreateMeshDispatchTargets(obj.dbMeshKey, [obj.dbNodeKey]); if (typeof command.userid == 'string') { var loguser = parent.users[command.userid]; if (loguser) { event.userid = command.userid; event.username = loguser.name; targets.push(command.userid); } @@ -1227,7 +1224,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { // Log this activation event var event = { etype: 'node', action: 'amtactivate', nodeid: obj.dbNodeKey, domain: domain.id, msg: 'Device requested Intel AMT ACM activation, FQDN: ' + command.fqdn, ip: obj.remoteaddrport }; if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the node. Another event will come. - parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(obj.dbMeshKey), obj, event); + parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(obj.dbMeshKey, [obj.dbNodeKey]), obj, event); // Update the device Intel AMT information ChangeAgentCoreInfo({ "intelamt": { user: 'admin', pass: amtpassword, uuid: command.uuid, realm: command.realm } }); @@ -1243,8 +1240,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { switch (command.value.command) { case 'register': { // Only main agent can do this - if (((obj.agentInfo.capabilities & 0x40) == 0) && (typeof command.value.value == 'string') && (command.value.value.length == 64)) - { + if (((obj.agentInfo.capabilities & 0x40) == 0) && (typeof command.value.value == 'string') && (command.value.value.length == 64)) { // Store links to diagnostic agent id var daNodeKey = 'node/' + domain.id + '/' + db.escapeBase64(command.value.value); db.Set({ _id: 'da' + daNodeKey, domain: domain.id, time: obj.connectTime, raid: obj.dbNodeKey }); // DiagnosticAgent --> Agent @@ -1276,8 +1272,8 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { case 'log': { if (((obj.agentInfo.capabilities & 0x40) != 0) && (typeof command.value.value == 'string') && (command.value.value.length < 256)) { // If this is a diagnostic agent, log the event in the log of the main agent - var event = { etype: 'node', action: 'diagnostic', nodeid: obj.realNodeKey, domain: domain.id, msg: command.value.value }; - parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(obj.dbMeshKey), obj, event); + var event = { etype: 'node', action: 'diagnostic', nodeid: obj.realNodeKey, snodeid: obj.dbNodeKey, domain: domain.id, msg: command.value.value }; + parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(obj.dbMeshKey, [obj.dbNodeKey]), obj, event); } break; } @@ -1295,7 +1291,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { // Event the new sysinfo hash, this will notify everyone that the sysinfo document was changed var event = { etype: 'node', action: 'sysinfohash', nodeid: obj.dbNodeKey, domain: domain.id, hash: command.data.hash, nolog: 1 }; - parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(obj.dbMeshKey), obj, event); + parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(obj.dbMeshKey, [obj.dbNodeKey]), obj, event); } break; } @@ -1308,7 +1304,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { } case 'plugin': { if ((parent.parent.pluginHandler == null) || (typeof command.plugin != 'string')) break; - try { + try { parent.parent.pluginHandler.plugins[command.plugin].serveraction(command, obj, parent); } catch (e) { console.log('Error loading plugin handler (' + e + ')'); @@ -1316,7 +1312,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { break; } default: { - parent.agentStats.unknownAgentActionCount++; + parent.agentStats.unknownAgentActionCount++; console.log('Unknown agent action (' + obj.remoteaddrport + '): ' + command.action + '.'); break; } @@ -1394,7 +1390,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { if (changes.length > 0) { event.msg = 'Changed device ' + device.name + ' from group ' + mesh.name + ': ' + changes.join(', '); } if ((log == 0) || ((obj.agentInfo) && (obj.agentInfo.capabilities) && (obj.agentInfo.capabilities & 0x20)) || (changes.length == 0)) { event.nolog = 1; } // If this is a temporary device, don't log changes if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the node. Another event will come. - parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(device.meshid), obj, event); + parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(device.meshid, [obj.dbNodeKey]), obj, event); } } }); @@ -1435,7 +1431,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { var event = { etype: 'node', action: 'changenode', nodeid: obj.dbNodeKey, domain: domain.id, node: parent.CloneSafeNode(device), msg: 'Changed device ' + device.name + ' from group ' + mesh.name + ': ' + changes.join(', ') }; if (obj.agentInfo.capabilities & 0x20) { event.nolog = 1; } // If this is a temporary device, don't log changes if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the node. Another event will come. - parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(device.meshid), obj, event); + parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(device.meshid, [obj.dbNodeKey]), obj, event); } } }); @@ -1453,7 +1449,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { if (device.agent.tag != tag) { // Do some clean up if needed, these values should not be in the database. if (device.conn != null) { delete device.conn; } - if (device.pwr != null) { delete device.pwr; } + if (device.pwr != null) { delete device.pwr; } if (device.agct != null) { delete device.agct; } if (device.cict != null) { delete device.cict; } @@ -1464,7 +1460,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { // Event the node change var event = { etype: 'node', action: 'changenode', nodeid: obj.dbNodeKey, domain: domain.id, node: parent.CloneSafeNode(device), nolog: 1 }; if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the node. Another event will come. - parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(device.meshid), obj, event); + parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(device.meshid, [obj.dbNodeKey]), obj, event); } } }); diff --git a/meshcentral.js b/meshcentral.js index 109085c4..d1301793 100644 --- a/meshcentral.js +++ b/meshcentral.js @@ -70,6 +70,7 @@ function CreateMeshCentralServer(config, args) { obj.serverWarnings = []; // List of warnings that should be shown to administrators obj.cookieUseOnceTable = {}; // List of cookies that are already expired obj.cookieUseOnceTableCleanCounter = 0; // Clean the cookieUseOnceTable each 20 additions + obj.firstStats = true; // True until this server saves it's not stats to the database // Server version obj.currentVer = null; @@ -83,20 +84,24 @@ function CreateMeshCentralServer(config, args) { obj.filespath = obj.path.join(__dirname, '../../meshcentral-files'); obj.backuppath = obj.path.join(__dirname, '../../meshcentral-backup'); obj.recordpath = obj.path.join(__dirname, '../../meshcentral-recordings'); - obj.webPublicPath = obj.path.join(__dirname, 'public'); obj.webViewsPath = obj.path.join(__dirname, 'views'); + obj.webPublicPath = obj.path.join(__dirname, 'public'); + obj.webEmailsPath = obj.path.join(__dirname, 'emails'); if (obj.fs.existsSync(obj.path.join(__dirname, '../../meshcentral-web/views'))) { obj.webViewsOverridePath = obj.path.join(__dirname, '../../meshcentral-web/views'); } if (obj.fs.existsSync(obj.path.join(__dirname, '../../meshcentral-web/public'))) { obj.webPublicOverridePath = obj.path.join(__dirname, '../../meshcentral-web/public'); } + if (obj.fs.existsSync(obj.path.join(__dirname, '../../meshcentral-web/emails'))) { obj.webEmailsOverridePath = obj.path.join(__dirname, '../../meshcentral-web/emails'); } } else { obj.parentpath = __dirname; obj.datapath = obj.path.join(__dirname, '../meshcentral-data'); obj.filespath = obj.path.join(__dirname, '../meshcentral-files'); obj.backuppath = obj.path.join(__dirname, '../meshcentral-backups'); obj.recordpath = obj.path.join(__dirname, '../meshcentral-recordings'); - obj.webPublicPath = obj.path.join(__dirname, 'public'); obj.webViewsPath = obj.path.join(__dirname, 'views'); + obj.webPublicPath = obj.path.join(__dirname, 'public'); + obj.webEmailsPath = obj.path.join(__dirname, 'emails'); if (obj.fs.existsSync(obj.path.join(__dirname, '../meshcentral-web/views'))) { obj.webViewsOverridePath = obj.path.join(__dirname, '../meshcentral-web/views'); } if (obj.fs.existsSync(obj.path.join(__dirname, '../meshcentral-web/public'))) { obj.webPublicOverridePath = obj.path.join(__dirname, '../meshcentral-web/public'); } + if (obj.fs.existsSync(obj.path.join(__dirname, '../meshcentral-web/emails'))) { obj.webEmailsOverridePath = obj.path.join(__dirname, '../meshcentral-web/emails'); } } // Look to see if data and/or file path is specified @@ -123,7 +128,7 @@ function CreateMeshCentralServer(config, args) { try { require('./pass').hash('test', function () { }, 0); } catch (e) { console.log('Old version of node, must upgrade.'); return; } // TODO: Not sure if this test works or not. // Check for invalid arguments - var validArguments = ['_', 'notls', 'user', 'port', 'aliasport', 'mpsport', 'mpsaliasport', 'redirport', 'rediraliasport', 'cert', 'mpscert', 'deletedomain', 'deletedefaultdomain', 'showall', 'showusers', 'showusergroups', 'shownodes', 'showmeshes', 'showevents', 'showsmbios', 'showpower', 'clearpower', 'showiplocations', 'help', 'exactports', 'xinstall', 'xuninstall', 'install', 'uninstall', 'start', 'stop', 'restart', 'debug', 'filespath', 'datapath', 'noagentupdate', 'launch', 'noserverbackup', 'mongodb', 'mongodbcol', 'wanonly', 'lanonly', 'nousers', 'mpspass', 'ciralocalfqdn', 'dbexport', 'dbexportmin', 'dbimport', 'dbmerge', 'dbencryptkey', 'selfupdate', 'tlsoffload', 'userallowedip', 'userblockedip', 'swarmallowedip', 'agentallowedip', 'agentblockedip', 'fastcert', 'swarmport', 'logintoken', 'logintokenkey', 'logintokengen', 'logintokengen', 'mailtokengen', 'admin', 'unadmin', 'sessionkey', 'sessiontime', 'minify', 'minifycore', 'dblistconfigfiles', 'dbshowconfigfile', 'dbpushconfigfiles', 'dbpullconfigfiles', 'dbdeleteconfigfiles', 'vaultpushconfigfiles', 'vaultpullconfigfiles', 'vaultdeleteconfigfiles', 'configkey', 'loadconfigfromdb', 'npmpath', 'memorytracking', 'serverid', 'recordencryptionrecode', 'vault', 'token', 'unsealkey', 'name', 'log', 'dbstats', 'translate']; + var validArguments = ['_', 'notls', 'user', 'port', 'aliasport', 'mpsport', 'mpsaliasport', 'redirport', 'rediraliasport', 'cert', 'mpscert', 'deletedomain', 'deletedefaultdomain', 'showall', 'showusers', 'listuserids', 'showusergroups', 'shownodes', 'showmeshes', 'showevents', 'showsmbios', 'showpower', 'clearpower', 'showiplocations', 'help', 'exactports', 'xinstall', 'xuninstall', 'install', 'uninstall', 'start', 'stop', 'restart', 'debug', 'filespath', 'datapath', 'noagentupdate', 'launch', 'noserverbackup', 'mongodb', 'mongodbcol', 'wanonly', 'lanonly', 'nousers', 'mpspass', 'ciralocalfqdn', 'dbexport', 'dbexportmin', 'dbimport', 'dbmerge', 'dbencryptkey', 'selfupdate', 'tlsoffload', 'userallowedip', 'userblockedip', 'swarmallowedip', 'agentallowedip', 'agentblockedip', 'fastcert', 'swarmport', 'logintoken', 'logintokenkey', 'logintokengen', 'logintokengen', 'mailtokengen', 'admin', 'unadmin', 'sessionkey', 'sessiontime', 'minify', 'minifycore', 'dblistconfigfiles', 'dbshowconfigfile', 'dbpushconfigfiles', 'dbpullconfigfiles', 'dbdeleteconfigfiles', 'vaultpushconfigfiles', 'vaultpullconfigfiles', 'vaultdeleteconfigfiles', 'configkey', 'loadconfigfromdb', 'npmpath', 'memorytracking', 'serverid', 'recordencryptionrecode', 'vault', 'token', 'unsealkey', 'name', 'log', 'dbstats', 'translate', 'resetaccount', 'pass', 'adminaccount']; for (var arg in obj.args) { obj.args[arg.toLocaleLowerCase()] = obj.args[arg]; if (validArguments.indexOf(arg.toLocaleLowerCase()) == -1) { console.log('Invalid argument "' + arg + '", use --help.'); return; } } if (obj.args.mongodb == true) { console.log('Must specify: --mongodb [connectionstring] \r\nSee https://docs.mongodb.com/manual/reference/connection-string/ for MongoDB connection string.'); return; } for (i in obj.config.settings) { obj.args[i] = obj.config.settings[i]; } // Place all settings into arguments, arguments have already been placed into settings so arguments take precedence. @@ -139,14 +144,15 @@ function CreateMeshCentralServer(config, args) { console.log(''); console.log('Run standalone, console application'); } - console.log(' --notls Use HTTP instead of HTTPS for the main web server.'); console.log(' --user [username] Always login as [username] if account exists.'); console.log(' --port [number] Web server port number.'); console.log(' --mpsport [number] Intel AMT server port number.'); console.log(' --redirport [number] Creates an additional HTTP server to redirect users to the HTTPS server.'); console.log(' --exactports Server must run with correct ports or exit.'); console.log(' --noagentupdate Server will not update mesh agent native binaries.'); - console.log(' --fastcert Generate weaker RSA2048 certificates.'); + console.log(' --listuserids Show a list of a user identifiers in the database.'); + console.log(' --resetaccount [userid] Unlock an account, disable 2FA and set a new account password.'); + console.log(' --adminaccount [userid] Promote account to site administrator.'); console.log(' --cert [name], (country), (org) Create a web server certificate with [name] server name.'); console.log(' country and organization can optionaly be set.'); return; @@ -176,7 +182,7 @@ function CreateMeshCentralServer(config, args) { didSomething = true; } - // Check is "meshcentral-web" exists, if so, translate all pages in that folder. + // Check if "meshcentral-web" exists, if so, translate all pages in that folder. if (obj.webViewsOverridePath != null) { didSomething = true; var files = obj.fs.readdirSync(obj.webViewsOverridePath); @@ -212,6 +218,19 @@ function CreateMeshCentralServer(config, args) { return; } + // Setup the Node+NPM path if possible, this makes it possible to update the server even if NodeJS and NPM are not in default paths. + if (obj.args.npmpath == null) { + try { + var nodepath = process.argv[0]; + var npmpath = obj.path.join(obj.path.dirname(process.argv[0]), 'npm'); + if (obj.fs.existsSync(nodepath) && obj.fs.existsSync(npmpath)) { + if (nodepath.indexOf(' ') >= 0) { nodepath = '"' + nodepath + '"'; } + if (npmpath.indexOf(' ') >= 0) { npmpath = '"' + npmpath + '"'; } + if (obj.platform == 'win32') { obj.args.npmpath = npmpath; } else { obj.args.npmpath = (nodepath + ' ' + npmpath); } + } + } catch (ex) { } + } + // Linux background service systemd handling if (obj.platform == 'linux') { if (obj.args.install == true) { @@ -528,7 +547,7 @@ function CreateMeshCentralServer(config, args) { // Lower case all keys in the config file try { - require('./common.js').objKeysToLower(config2, ["ldapoptions"]); + require('./common.js').objKeysToLower(config2, ['ldapoptions', 'defaultuserwebstate', 'forceduserwebstate']); } catch (ex) { console.log('CRITICAL ERROR: Unable to access the file \"./common.js\".\r\nCheck folder & file permissions.'); process.exit(); @@ -555,6 +574,24 @@ function CreateMeshCentralServer(config, args) { //var wincmd = require('node-windows'); //wincmd.list(function (svc) { console.log(svc); }, true); + // Setup syslog support + if ((require('os').platform() != 'win32') && ((config.settings.syslog != null) || (config.settings.syslogjson != null))) { + if (config.settings.syslog === true) { config.settings.syslog = 'meshcentral'; } + if (config.settings.syslogjson === true) { config.settings.syslogjson = 'meshcentral-json'; } + if (typeof config.settings.syslog == 'string') { + obj.syslog = require('modern-syslog'); + console.log('Starting ' + config.settings.syslog + ' syslog.'); + obj.syslog.init(config.settings.syslog, obj.syslog.LOG_PID | obj.syslog.LOG_ODELAY, obj.syslog.LOG_LOCAL0); + obj.syslog.log(obj.syslog.LOG_INFO, "MeshCentral v" + getCurrentVerion() + " Server Start"); + } + if (typeof config.settings.syslogjson == 'string') { + obj.syslogjson = require('modern-syslog'); + console.log('Starting ' + config.settings.syslogjson + ' JSON syslog.'); + obj.syslogjson.init(config.settings.syslogjson, obj.syslogjson.LOG_PID | obj.syslogjson.LOG_ODELAY, obj.syslogjson.LOG_LOCAL0); + obj.syslogjson.log(obj.syslogjson.LOG_INFO, "MeshCentral v" + getCurrentVerion() + " Server Start"); + } + } + // Check top level configuration for any unreconized values if (config) { for (var i in config) { if ((typeof i == 'string') && (i.length > 0) && (i[0] != '_') && (['settings', 'domains', 'configfiles', 'smtp', 'letsencrypt', 'peers'].indexOf(i) == -1)) { addServerWarning('Unrecognized configuration option \"' + i + '\".'); } } } @@ -579,6 +616,7 @@ function CreateMeshCentralServer(config, args) { if (obj.args.deletedefaultdomain) { obj.db.DeleteDomain('', function () { console.log('Deleted default domain.'); process.exit(); }); return; } if (obj.args.showall) { obj.db.GetAll(function (err, docs) { console.log(docs); process.exit(); }); return; } if (obj.args.showusers) { obj.db.GetAllType('user', function (err, docs) { console.log(docs); process.exit(); }); return; } + if (obj.args.listuserids) { obj.db.GetAllType('user', function (err, docs) { for (var i in docs) { console.log(docs[i]._id); } process.exit(); }); return; } if (obj.args.showusergroups) { obj.db.GetAllType('ugrp', function (err, docs) { console.log(docs); process.exit(); }); return; } if (obj.args.shownodes) { obj.db.GetAllType('node', function (err, docs) { console.log(docs); process.exit(); }); return; } if (obj.args.showmeshes) { obj.db.GetAllType('mesh', function (err, docs) { console.log(docs); process.exit(); }); return; } @@ -591,6 +629,25 @@ function CreateMeshCentralServer(config, args) { if (obj.args.logintokenkey) { obj.showLoginTokenKey(function (r) { console.log(r); process.exit(); }); return; } if (obj.args.recordencryptionrecode) { obj.db.performRecordEncryptionRecode(function (count) { console.log('Re-encoded ' + count + ' record(s).'); process.exit(); }); return; } if (obj.args.dbstats) { obj.db.getDbStats(function (stats) { console.log(stats); process.exit(); }); return; } + if (obj.args.resetaccount) { + if ((obj.args.pass == null) || (obj.args.pass == '') || (obj.args.resetaccount.startsWith('user/') == false)) { console.log('Usage: --resetaccount [userid] --pass [password].'); process.exit(); return; } + obj.db.Get(obj.args.resetaccount, function (err, docs) { + if ((err != null) || (docs == null) || (docs.length == 0)) { console.log('Unknown userid, usage: --resetaccount [userid] --pass [password].'); process.exit(); return; } + var user = docs[0]; if ((user.siteadmin) && (user.siteadmin != 0xFFFFFFFF) && (user.siteadmin & 32) != 0) { user.siteadmin -= 32; } // Unlock the account. + delete user.otpekey; delete user.otpsecret; delete user.otpkeys; delete user.otphkeys; // Disable 2FA + require('./pass').hash(obj.args.pass, user.salt, function (err, hash, tag) { if (err) { console.log('Unable to reset password: ' + err); process.exit(); return; } user.hash = hash; obj.db.Set(user, function () { console.log('Done.'); process.exit(); return; }); }, 0); + }); + return; + } + if (obj.args.adminaccount) { + if (obj.args.resetaccount.startsWith('user/') == false) { console.log('Invalid userid, usage: --adminaccount [userid].'); process.exit(); return; } + obj.db.Get(obj.args.adminaccount, function (err, docs) { + if ((err != null) || (docs == null) || (docs.length == 0)) { console.log('Unknown userid, usage: --adminaccount [userid].'); process.exit(); return; } + docs[0].siteadmin = 0xFFFFFFFF; // Set user as site administrator + obj.db.Set(docs[0], function () { console.log('Done.'); process.exit(); return; }); + }); + return; + } // Show a list of all configuration files in the database if (obj.args.dblistconfigfiles) { @@ -780,8 +837,8 @@ function CreateMeshCentralServer(config, args) { objectToAdd.push(newobj); // Add this user } } else if (newobj.type == 'mesh') { - // Add this object after escaping - objectToAdd.push(obj.common.escapeLinksFieldName(newobj)); + // Add this object + objectToAdd.push(newobj); } // Don't add nodes. } console.log('Importing ' + objectToAdd.length + ' object(s)...'); @@ -817,7 +874,7 @@ function CreateMeshCentralServer(config, args) { // Lower case all keys in the config file try { - require('./common.js').objKeysToLower(config2, ['ldapoptions']); + require('./common.js').objKeysToLower(config2, ['ldapoptions', 'defaultuserwebstate', 'forceduserwebstate']); } catch (ex) { console.log("CRITICAL ERROR: Unable to access the file \"./common.js\".\r\nCheck folder & file permissions."); process.exit(); @@ -848,6 +905,13 @@ function CreateMeshCentralServer(config, args) { obj.StartEx1b = function () { var i; + // Linux format /var/log/auth.log + if (obj.config.settings.authlog != null) { + obj.fs.open(obj.config.settings.authlog, 'a', function (err, fd) { + if (err == null) { obj.authlog = fd; } else { console.log('ERROR: Unable to open: ' + obj.config.settings.authlog); } + }) + } + // Check if self update is allowed. If running as a Windows service, self-update is not possible. if (obj.fs.existsSync(obj.path.join(__dirname, 'daemon'))) { obj.serverSelfWriteAllowed = false; } @@ -888,6 +952,7 @@ function CreateMeshCentralServer(config, args) { var bannedDomains = ['public', 'private', 'images', 'scripts', 'styles', 'views']; // List of banned domains for (i in obj.config.domains) { for (var j in bannedDomains) { if (i == bannedDomains[j]) { console.log("ERROR: Domain '" + i + "' is not allowed domain name in config.json."); return; } } } for (i in obj.config.domains) { + if (typeof obj.config.domains[i] != 'object') { console.log("ERROR: Invalid domain configuration in config.json."); process.exit(); return; } if ((i.length > 0) && (i[0] == '_')) { delete obj.config.domains[i]; continue; } // Remove any domains with names that start with _ if (typeof config.domains[i].auth == 'string') { config.domains[i].auth = config.domains[i].auth.toLowerCase(); } if (obj.config.domains[i].limits == null) { obj.config.domains[i].limits = {}; } @@ -930,6 +995,17 @@ function CreateMeshCentralServer(config, args) { obj.config.domains[i].newaccountsrights = newAccRights; } if (obj.config.domains[i].newaccountsrights && (typeof (obj.config.domains[i].newaccountsrights) != 'number')) { delete obj.config.domains[i].newaccountsrights; } + + // Check if there is a web views path and/or web public path for this domain + if ((__dirname.endsWith('/node_modules/meshcentral')) || (__dirname.endsWith('\\node_modules\\meshcentral')) || (__dirname.endsWith('/node_modules/meshcentral/')) || (__dirname.endsWith('\\node_modules\\meshcentral\\'))) { + if ((obj.config.domains[i].webviewspath == null) && (obj.fs.existsSync(obj.path.join(__dirname, '../../meshcentral-web-' + i + '/views')))) { obj.config.domains[i].webviewspath = obj.path.join(__dirname, '../../meshcentral-web-' + i + '/views'); } + if ((obj.config.domains[i].webpublicpath == null) && (obj.fs.existsSync(obj.path.join(__dirname, '../../meshcentral-web-' + i + '/public')))) { obj.config.domains[i].webpublicpath = obj.path.join(__dirname, '../../meshcentral-web-' + i + '/public'); } + if ((obj.config.domains[i].webemailspath == null) && (obj.fs.existsSync(obj.path.join(__dirname, '../../meshcentral-web-' + i + '/emails')))) { obj.config.domains[i].webemailspath = obj.path.join(__dirname, '../../meshcentral-web-' + i + '/emails'); } + } else { + if ((obj.config.domains[i].webviewspath == null) && (obj.fs.existsSync(obj.path.join(__dirname, '../meshcentral-web-' + i + '/views')))) { obj.config.domains[i].webviewspath = obj.path.join(__dirname, '../meshcentral-web-' + i + '/views'); } + if ((obj.config.domains[i].webpublicpath == null) && (obj.fs.existsSync(obj.path.join(__dirname, '../meshcentral-web-' + i + '/public')))) { obj.config.domains[i].webpublicpath = obj.path.join(__dirname, '../meshcentral-web-' + i + '/public'); } + if ((obj.config.domains[i].webemailspath == null) && (obj.fs.existsSync(obj.path.join(__dirname, '../meshcentral-web-' + i + '/emails')))) { obj.config.domains[i].webemailspath = obj.path.join(__dirname, '../meshcentral-web-' + i + '/emails'); } + } } // Log passed arguments into Windows Service Log @@ -1018,10 +1094,10 @@ function CreateMeshCentralServer(config, args) { } // Start plugin manager if configuration allows this. - if ((obj.config) && (obj.config.settings) && (obj.config.settings.plugins != null)) { + if ((obj.config) && (obj.config.settings) && (obj.config.settings.plugins != null) && (obj.config.settings.plugins != false) && ((typeof obj.config.settings.plugins != 'object') || (obj.config.settings.plugins.enabled != false))) { const nodeVersion = Number(process.version.match(/^v(\d+\.\d+)/)[1]); if (nodeVersion < 7) { - addServerWarning("Plugin support requires Node v7.0 or higher."); + addServerWarning("Plugin support requires Node v7.x or higher."); delete obj.config.settings.plugins; } else { obj.pluginHandler = require('./pluginHandler.js').pluginHandler(obj); @@ -1048,7 +1124,7 @@ function CreateMeshCentralServer(config, args) { obj.certificateOperations.GetMeshServerCertificate(obj.args, obj.config, function (certs) { // Get the current node version const nodeVersion = Number(process.version.match(/^v(\d+\.\d+)/)[1]); - if ((nodeVersion < 8) || (require('crypto').generateKeyPair == null) || (obj.config.letsencrypt == null) || (obj.redirserver == null)) { + if ((obj.config.letsencrypt == null) || (obj.redirserver == null) || (nodeVersion < 8)) { obj.StartEx3(certs); // Just use the configured certificates } else if ((obj.config.letsencrypt != null) && (obj.config.letsencrypt.nochecks == true)) { // Use Let's Encrypt with no checking @@ -1059,12 +1135,13 @@ function CreateMeshCentralServer(config, args) { var leok = true; if (typeof obj.config.letsencrypt.email != 'string') { leok = false; addServerWarning("Missing Let's Encrypt email address."); } else if (typeof obj.config.letsencrypt.names != 'string') { leok = false; addServerWarning("Invalid Let's Encrypt host names."); } + else if (obj.config.letsencrypt.names.indexOf('*') >= 0) { leok = false; addServerWarning("Invalid Let's Encrypt names, can't contain a *."); } else if (obj.config.letsencrypt.email.split('@').length != 2) { leok = false; addServerWarning("Invalid Let's Encrypt email address."); } else if (obj.config.letsencrypt.email.trim() !== obj.config.letsencrypt.email) { leok = false; addServerWarning("Invalid Let's Encrypt email address."); } else { var le = require('./letsencrypt.js'); - try { obj.letsencrypt = le.CreateLetsEncrypt(obj); } catch (ex) { } - if (obj.letsencrypt == null) { addServerWarning("Unable to setup GreenLock module."); leok = false; } + try { obj.letsencrypt = le.CreateLetsEncrypt(obj); } catch (ex) { console.log(ex); } + if (obj.letsencrypt == null) { addServerWarning("Unable to setup Let's Encrypt module."); leok = false; } } if (leok == true) { // Check that the email address domain MX resolves. @@ -1197,10 +1274,17 @@ function CreateMeshCentralServer(config, args) { obj.DispatchEvent(['*'], obj, { etype: 'server', action: 'started', msg: 'Server started' }); // Plugin hook. Need to run something at server startup? This is the place. - if (obj.pluginHandler) { obj.pluginHandler.callHook("server_startup"); } + if (obj.pluginHandler) { obj.pluginHandler.callHook('server_startup'); } - // Load the login cookie encryption key from the database if allowed - if ((obj.config) && (obj.config.settings) && (obj.config.settings.allowlogintoken == true)) { + // Setup the login cookie encryption key + if ((obj.config) && (obj.config.settings) && (typeof obj.config.settings.logincookieencryptionkey == 'string')) { + // We have a string, hash it and use that as a key + try { obj.loginCookieEncryptionKey = Buffer.from(obj.config.settings.logincookieencryptionkey, 'hex'); } catch (ex) { } + if ((obj.loginCookieEncryptionKey == null) || (obj.loginCookieEncryptionKey.length != 80)) { addServerWarning("Invalid \"LoginCookieEncryptionKey\" in config.json."); obj.loginCookieEncryptionKey = null; } + } + + // Login cookie encryption key not set, use one from the database + if (obj.loginCookieEncryptionKey == null) { obj.db.Get('LoginCookieEncryptionKey', function (err, docs) { if ((docs.length > 0) && (docs[0].key != null) && (obj.args.logintokengen == null) && (docs[0].key.length >= 160)) { obj.loginCookieEncryptionKey = Buffer.from(docs[0].key, 'hex'); @@ -1244,6 +1328,7 @@ function CreateMeshCentralServer(config, args) { } }; if (obj.mpsserver != null) { data.conn.am = Object.keys(obj.mpsserver.ciraConnections).length; } + if (obj.firstStats === true) { delete obj.firstStats; data.first = true; } obj.db.SetServerStats(data); // Save the stats to the database obj.DispatchEvent(['*'], obj, { action: 'servertimelinestats', data: data }); // Event the server stats }, 300000); @@ -1261,18 +1346,9 @@ function CreateMeshCentralServer(config, args) { setInterval(obj.db.performBackup, obj.config.settings.autobackup.backupintervalhours * 60 * 60 * 1000); } - // Setup the Node+NPM path if possible, this makes it possible to update the server even if NodeJS and NPM are not in default paths. - if (obj.args.npmpath == null) { - try { - var nodepath = process.argv[0]; - var npmpath = obj.path.join(obj.path.dirname(process.argv[0]), 'npm'); - if (obj.fs.existsSync(nodepath) && obj.fs.existsSync(npmpath)) { - if (nodepath.indexOf(' ') >= 0) { nodepath = '"' + nodepath + '"'; } - if (npmpath.indexOf(' ') >= 0) { npmpath = '"' + npmpath + '"'; } - if (obj.platform == 'win32') { obj.args.npmpath = npmpath; } else { obj.args.npmpath = (nodepath + ' ' + npmpath); } - } - } catch (ex) { } - } + // Setup users that can see all device groups + obj.config.settings.managealldevicegroups = []; + for (i in obj.config.domains) { if (Array.isArray(obj.config.domains[i].managealldevicegroups)) { for (var j in obj.config.domains[i].managealldevicegroups) { if (typeof obj.config.domains[i].managealldevicegroups[j] == 'string') { obj.config.settings.managealldevicegroups.push('user/' + i + '/' + obj.config.domains[i].managealldevicegroups[j]); } } } } }); }); }; @@ -1417,6 +1493,10 @@ function CreateMeshCentralServer(config, args) { // If the database is not setup, exit now. if (!obj.db) return; + // Send event to syslog is needed + if (obj.syslog && event.msg) { obj.syslog.log(obj.syslog.LOG_INFO, event.msg); } + if (obj.syslogjson) { obj.syslogjson.log(obj.syslogjson.LOG_INFO, JSON.stringify(event)); } + obj.debug('dispatch', 'DispatchEvent', ids); if ((typeof event == 'object') && (!event.nolog)) { event.time = new Date(); @@ -1499,7 +1579,7 @@ function CreateMeshCentralServer(config, args) { // Event any changes on this server only if ((newConnectivity != oldPowerState) || (newPowerState != oldPowerState)) { - obj.DispatchEvent(obj.webserver.CreateMeshDispatchTargets(meshid), obj, { action: 'nodeconnect', meshid: meshid, nodeid: nodeid, conn: newConnectivity, pwr: newPowerState, nolog: 1, nopeers: 1 }); + obj.DispatchEvent(obj.webserver.CreateMeshDispatchTargets(meshid, [nodeid]), obj, { action: 'nodeconnect', meshid: meshid, nodeid: nodeid, conn: newConnectivity, pwr: newPowerState, nolog: 1, nopeers: 1 }); } } }; @@ -1547,7 +1627,7 @@ function CreateMeshCentralServer(config, args) { } // Event the node connection change - if (eventConnectChange == 1) { obj.DispatchEvent(obj.webserver.CreateMeshDispatchTargets(meshid), obj, { action: 'nodeconnect', meshid: meshid, nodeid: nodeid, conn: state.connectivity, pwr: state.powerState, ct: connectTime, nolog: 1, nopeers: 1 }); } + if (eventConnectChange == 1) { obj.DispatchEvent(obj.webserver.CreateMeshDispatchTargets(meshid, [nodeid]), obj, { action: 'nodeconnect', meshid: meshid, nodeid: nodeid, conn: state.connectivity, pwr: state.powerState, ct: connectTime, nolog: 1, nopeers: 1 }); } } else { // Multi server mode @@ -1603,13 +1683,13 @@ function CreateMeshCentralServer(config, args) { state.connectivity -= connectType; // If the node is completely disconnected, clean it up completely - if (state.connectivity == 0) { delete obj.connectivityByNode[nodeid]; state.powerState = 0; } + if (state.connectivity == 0) { delete obj.connectivityByNode[nodeid]; } eventConnectChange = 1; } // Clear node power state + var oldPowerState = state.powerState, powerState = 0; if (connectType == 1) { state.agentPower = 0; } else if (connectType == 2) { state.ciraPower = 0; } else if (connectType == 4) { state.amtPower = 0; } - var powerState = 0, oldPowerState = state.powerState; if ((state.connectivity & 1) != 0) { powerState = state.agentPower; } else if ((state.connectivity & 2) != 0) { powerState = state.ciraPower; } else if ((state.connectivity & 4) != 0) { powerState = state.amtPower; } if ((state.powerState == null) || (state.powerState != powerState)) { state.powerState = powerState; @@ -1620,7 +1700,7 @@ function CreateMeshCentralServer(config, args) { } // Event the node connection change - if (eventConnectChange == 1) { obj.DispatchEvent(obj.webserver.CreateMeshDispatchTargets(meshid), obj, { action: 'nodeconnect', meshid: meshid, nodeid: nodeid, conn: state.connectivity, pwr: state.powerState, nolog: 1, nopeers: 1 }); } + if (eventConnectChange == 1) { obj.DispatchEvent(obj.webserver.CreateMeshDispatchTargets(meshid, [nodeid]), obj, { action: 'nodeconnect', meshid: meshid, nodeid: nodeid, conn: state.connectivity, pwr: state.powerState, nolog: 1, nopeers: 1 }); } } else { // Multi server mode @@ -2181,6 +2261,15 @@ function CreateMeshCentralServer(config, args) { obj.getServerWarnings = function () { return serverWarnings; } obj.addServerWarning = function(msg, print) { serverWarnings.push(msg); if (print !== false) { console.log("WARNING: " + msg); } } + // auth.log functions + obj.authLog = function(server, msg) { + if (obj.authlog == null) return; + var d = new Date(); + var month = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'][d.getMonth()]; + var msg = month + ' ' + d.getDate() + ' ' + obj.common.zeroPad(d.getHours(),2) + ':' + obj.common.zeroPad(d.getMinutes(),2) + ':' + d.getSeconds() + ' meshcentral ' + server + '[' + process.pid + ']: ' + msg + ((obj.platform == 'win32')?'\r\n':'\n'); + obj.fs.write(obj.authlog, msg, function (err, written, string) { }); + } + // Return the path of a file into the meshcentral-data path obj.getConfigFilePath = function (filename) { if ((obj.config != null) && (obj.config.configfiles != null) && (obj.config.configfiles[filename] != null) && (typeof obj.config.configfiles[filename] == 'string')) { @@ -2239,7 +2328,7 @@ function getConfig(createSampleConfig) { // Lower case all keys in the config file try { - require('./common.js').objKeysToLower(config, ["ldapoptions"]); + require('./common.js').objKeysToLower(config, ['ldapoptions', 'defaultuserwebstate', 'forceduserwebstate']); } catch (ex) { console.log('CRITICAL ERROR: Unable to access the file \"./common.js\".\r\nCheck folder & file permissions.'); process.exit(); @@ -2252,11 +2341,11 @@ function getConfig(createSampleConfig) { function InstallModules(modules, func) { var missingModules = []; if (modules.length > 0) { - var dependencies = require("./package.json").dependencies; + var dependencies = require('./package.json').dependencies; for (var i in modules) { // Modules may contain a version tag (foobar@1.0.0), remove it so the module can be found using require var moduleNameAndVersion = modules[i]; - var moduleInfo = moduleNameAndVersion.split("@", 2); + var moduleInfo = moduleNameAndVersion.split('@', 2); var moduleName = moduleInfo[0]; var moduleVersion = moduleInfo[1]; try { @@ -2286,7 +2375,7 @@ function InstallModule(modulename, func, tag1, tag2) { // Get the working directory if ((__dirname.endsWith('/node_modules/meshcentral')) || (__dirname.endsWith('\\node_modules\\meshcentral')) || (__dirname.endsWith('/node_modules/meshcentral/')) || (__dirname.endsWith('\\node_modules\\meshcentral\\'))) { parentpath = require('path').join(__dirname, '../..'); } - child_process.exec(`npm install --no-optional ${modulename}`, { maxBuffer: 512000, timeout: 120000, cwd: parentpath }, function (error, stdout, stderr) { + child_process.exec(npmpath + ` install --no-optional ${modulename}`, { maxBuffer: 512000, timeout: 120000, cwd: parentpath }, function (error, stdout, stderr) { if ((error != null) && (error != '')) { console.log('ERROR: Unable to install required module "' + modulename + '". MeshCentral may not have access to npm, or npm may not have suffisent rights to load the new module. Try "npm install ' + modulename + '" to manualy install this module.\r\n'); process.exit(); @@ -2306,6 +2395,7 @@ var serverWarnings = []; function addServerWarning(msg, print) { serverWarnings.push(msg); if (print !== false) { console.log("WARNING: " + msg); } } // Load the really basic modules +var npmpath = 'npm'; var meshserver = null; var childProcess = null; var previouslyInstalledModules = {}; @@ -2321,6 +2411,21 @@ function mainStart() { // Parse inbound arguments var args = require('minimist')(process.argv.slice(2)); + // Setup the NPM path + if (args.npmpath == null) { + try { + var xnodepath = process.argv[0]; + var xnpmpath = require('path').join(require('path').dirname(process.argv[0]), 'npm'); + if (require('fs').existsSync(xnodepath) && require('fs').existsSync(xnpmpath)) { + if (xnodepath.indexOf(' ') >= 0) { xnodepath = '"' + xnodepath + '"'; } + if (xnpmpath.indexOf(' ') >= 0) { xnpmpath = '"' + xnpmpath + '"'; } + if (require('os').platform() == 'win32') { npmpath = xnpmpath; } else { npmpath = (xnodepath + ' ' + xnpmpath); } + } + } catch (ex) { console.log(ex); } + } else { + npmpath = args.npmpath; + } + // Get the server configuration var config = getConfig(false); if (config == null) { process.exit(); } @@ -2328,17 +2433,19 @@ function mainStart() { // Lowercase the auth value if present for (var i in config.domains) { if (typeof config.domains[i].auth == 'string') { config.domains[i].auth = config.domains[i].auth.toLowerCase(); } } - // Check is Windows SSPI and YubiKey OTP will be used + // Check if Windows SSPI and YubiKey OTP will be used var sspi = false; var ldap = false; var allsspi = true; var yubikey = false; + var recordingIndex = false; var domainCount = 0; if (require('os').platform() == 'win32') { for (var i in config.domains) { domainCount++; if (config.domains[i].auth == 'sspi') { sspi = true; } else { allsspi = false; } } } else { allsspi = false; } if (domainCount == 0) { allsspi = false; } for (var i in config.domains) { if (config.domains[i].yubikey != null) { yubikey = true; } if (config.domains[i].auth == 'ldap') { ldap = true; } + if ((config.domains[i].sessionrecording != null) && (config.domains[i].sessionrecording.index == true)) { recordingIndex = true; } } // Get the current node version @@ -2348,7 +2455,14 @@ function mainStart() { var modules = ['ws', 'cbor', 'nedb', 'https', 'yauzl', 'xmldom', 'ipcheck', 'express', 'archiver', 'multiparty', 'node-forge', 'express-ws', 'compression', 'body-parser', 'connect-redis', 'cookie-session', 'express-handlebars']; if (require('os').platform() == 'win32') { modules.push('node-windows'); if (sspi == true) { modules.push('node-sspi'); } } // Add Windows modules if (ldap == true) { modules.push('ldapauth-fork'); } - if (config.letsencrypt != null) { if ((nodeVersion < 10) || (require('crypto').generateKeyPair == null)) { addServerWarning("Let's Encrypt support requires Node v10.12 or higher.", !args.launch); } else { modules.push('greenlock'); } } // Add Greenlock Module + if (recordingIndex == true) { modules.push('image-size'); } // Need to get the remote desktop JPEG sizes to index the recodring file. + if (config.letsencrypt != null) { + if (config.letsencrypt.lib == 'greenlock') { + if ((nodeVersion < 10) || (require('crypto').generateKeyPair == null)) { addServerWarning("Let's Encrypt support requires Node v10.12 or higher.", !args.launch); } else { modules.push('greenlock@4.0.4'); } + } else { + if (nodeVersion < 8) { addServerWarning("Let's Encrypt support requires Node v8.x or higher.", !args.launch); } else { modules.push('acme-client'); } + } + } // Add Greenlock Module or acme-client module if (config.settings.mqtt != null) { modules.push('aedes'); } // Add MQTT Modules if (config.settings.mysql != null) { modules.push('mysql'); } // Add MySQL, official driver. if (config.settings.mongodb != null) { modules.push('mongodb'); } // Add MongoDB, official driver. @@ -2370,14 +2484,21 @@ function mainStart() { if (config.settings.no2factorauth !== true) { // Setup YubiKey OTP if configured if (yubikey == true) { modules.push('yubikeyotp'); } // Add YubiKey OTP support - if (allsspi == false) { modules.push('otplib'); } // Google Authenticator support + if (allsspi == false) { modules.push('otplib@10.2.3'); } // Google Authenticator support (v10 supports older NodeJS versions). } + // Syslog support + if ((require('os').platform() != 'win32') && (config.settings.syslog || config.settings.syslogjson)) { modules.push('modern-syslog'); } + + // Setup heapdump support if needed, useful for memory leak debugging + // https://www.arbazsiddiqui.me/a-practical-guide-to-memory-leaks-in-nodejs/ + if (config.settings.heapdump === true) { modules.push('heapdump'); } + // Install any missing modules and launch the server InstallModules(modules, function () { meshserver = CreateMeshCentralServer(config, args); meshserver.Start(); }); // On exit, also terminate the child process if applicable - process.on("exit", function () { if (childProcess) { childProcess.kill(); childProcess = null; } }); + process.on('exit', function () { if (childProcess) { childProcess.kill(); childProcess = null; } }); // If our parent exits, we also exit if (args.launch) { diff --git a/meshctrl.js b/meshctrl.js index 85f8849e..484a7ddd 100644 --- a/meshctrl.js +++ b/meshctrl.js @@ -3,7 +3,7 @@ const crypto = require('crypto'); var settings = {}; const args = require('minimist')(process.argv.slice(2)); -const possibleCommands = ['listusers', 'listdevicegroups', 'listdevices', 'listusersofdevicegroup', 'serverinfo', 'userinfo', 'adduser', 'removeuser', 'adddevicegroup', 'removedevicegroup', 'broadcast', 'addusertodevicegroup', 'removeuserfromdevicegroup', 'sendinviteemail', 'generateinvitelink', 'config']; +const possibleCommands = ['listusers', 'listdevicegroups', 'listdevices', 'listusersofdevicegroup', 'serverinfo', 'userinfo', 'adduser', 'removeuser', 'adddevicegroup', 'removedevicegroup', 'broadcast', 'showevents', 'addusertodevicegroup', 'removeuserfromdevicegroup', 'addusertodevice', 'removeuserfromdevice', 'sendinviteemail', 'generateinvitelink', 'config']; //console.log(args); if (args['_'].length == 0) { @@ -25,9 +25,12 @@ if (args['_'].length == 0) { console.log(" RemoveDeviceGroup - Delete a device group."); console.log(" AddUserToDeviceGroup - Add a user to a device group."); console.log(" RemoveUserFromDeviceGroup - Remove a user from a device group."); + console.log(" AddUserToDevice - Add a user to a device."); + console.log(" RemoveUserFromDevice - Remove a user from a device."); console.log(" SendInviteEmail - Send an agent install invitation email."); console.log(" GenerateInviteLink - Create an invitation link."); console.log(" Broadcast - Display a message to all online users."); + console.log(" ShowEvents - Display real-time server events in JSON format."); console.log("\r\nSupported login arguments:"); console.log(" --url [wss://server] - Server url, wss://localhost:443 is default."); console.log(" --loginuser [username] - Login username, admin is default."); @@ -56,14 +59,26 @@ if (args['_'].length == 0) { break; } case 'addusertodevicegroup': { - if (args.userid == null) { console.log("Add user to group missing useid, use --userid [userid]"); } - else if (args.id == null) { console.log("Add user to group missing group id, use --id [groupid]"); } + if ((args.id == null) && (args.group == null)) { console.log("Device group identifier missing, use --id [groupid] or --group [groupname]"); } + else if (args.userid == null) { console.log("Add user to group missing useid, use --userid [userid]"); } else { ok = true; } break; } case 'removeuserfromdevicegroup': { - if (args.userid == null) { console.log("Remove user from group missing useid, use --userid [userid]"); } - else if (args.id == null) { console.log("Remove user from group missing group id, use --id [groupid]"); } + if ((args.id == null) && (args.group == null)) { console.log("Device group identifier missing, use --id [groupid] or --group [groupname]"); } + else if (args.userid == null) { console.log("Remove user from group missing useid, use --userid [userid]"); } + else { ok = true; } + break; + } + case 'addusertodevice': { + if (args.userid == null) { console.log("Add user to device missing useid, use --userid [userid]"); } + else if (args.id == null) { console.log("Add user to device missing device id, use --id [deviceid]"); } + else { ok = true; } + break; + } + case 'removeuserfromdevice': { + if (args.userid == null) { console.log("Remove user from device missing useid, use --userid [userid]"); } + else if (args.id == null) { console.log("Remove user from device missing device id, use --id [deviceid]"); } else { ok = true; } break; } @@ -73,7 +88,7 @@ if (args['_'].length == 0) { break; } case 'removedevicegroup': { - if (args.id == null) { console.log("Message group identifier, use --id [identifier]"); } + if ((args.id == null) && (args.group == null)) { console.log("Device group identifier missing, use --id [groupid] or --group [groupname]"); } else { ok = true; } break; } @@ -82,6 +97,10 @@ if (args['_'].length == 0) { else { ok = true; } break; } + case 'showevents': { + ok = true; + break; + } case 'adduser': { if (args.user == null) { console.log("New account name missing, use --user [name]"); } else if ((args.pass == null) && (args.randompass == null)) { console.log("New account password missing, use --pass [password] or --randompass"); } @@ -94,13 +113,13 @@ if (args['_'].length == 0) { break; } case 'sendinviteemail': { - if (args.id == null) { console.log("Device group identifier id missing, use --id [groupid]"); } + if ((args.id == null) && (args.group == null)) { console.log("Device group identifier missing, use --id [groupid] or --group [groupname]"); } else if (args.email == null) { console.log("Device email is missing, use --email [email]"); } - else { ok = true; } + else { ok = true; } break; } case 'generateinvitelink': { - if (args.id == null) { console.log("Device group identifier id missing, use --id [groupid]"); } + if ((args.id == null) && (args.group == null)) { console.log("Device group identifier missing, use --id [groupid] or --group [groupname]"); } else if (args.hours == null) { console.log("Invitation validity period missing, use --hours [hours]"); } else { ok = true; } break; @@ -116,18 +135,24 @@ if (args['_'].length == 0) { } case 'sendinviteemail': { console.log("Send invitation email with instructions on how to install the mesh agent for a specific device group. Example usage:\r\n"); - console.log(" MeshCtrl SendInviteEmail --id devicegroupid --email user@sample.com"); + console.log(" MeshCtrl SendInviteEmail --id devicegroupid --message \"msg\" --email user@sample.com"); + console.log(" MeshCtrl SendInviteEmail --group \"My Computers\" --name \"Jack\" --email user@sample.com"); console.log("\r\nRequired arguments:\r\n"); - console.log(" --id [groupid] - Device group identifier."); + console.log(" --id [groupid] - Device group identifier (or --group)."); + console.log(" --group [groupname] - Device group name (or --id)."); console.log(" --email [email] - Email address."); + console.log("\r\nOptional arguments:\r\n"); + console.log(" --name (name) - Name of recipient to be included in the email."); + console.log(" --message (msg) - Message to be included in the email."); break; } case 'generateinvitelink': { console.log("Generate a agent invitation URL for a given group. Example usage:\r\n"); console.log(" MeshCtrl GenerateInviteLink --id devicegroupid --hours 24"); - console.log(" MeshCtrl GenerateInviteLink --id devicegroupid --hours 0"); + console.log(" MeshCtrl GenerateInviteLink --group \"My Computers\" --hours 0"); console.log("\r\nRequired arguments:\r\n"); - console.log(" --id [groupid] - Device group identifier."); + console.log(" --id [groupid] - Device group identifier (or --group)."); + console.log(" --group [groupname] - Device group name (or --id)."); console.log(" --hours [hours] - Validity period in hours or 0 for infinit."); break; } @@ -232,15 +257,17 @@ if (args['_'].length == 0) { console.log("Remove a device group, Example usages:\r\n"); console.log(" MeshCtrl RemoveDeviceGroup --id groupid"); console.log("\r\nRequired arguments:\r\n"); - console.log(" --id [groupid] - The group identifier."); + console.log(" --id [groupid] - Device group identifier (or --group)."); + console.log(" --group [groupname] - Device group name (or --id)."); break; } case 'addusertodevicegroup': { console.log("Add a user to a device group, Example usages:\r\n"); console.log(" MeshCtrl AddUserToDeviceGroup --id groupid --userid userid --fullrights"); - console.log(" MeshCtrl AddUserToDeviceGroup --id groupid --userid userid --editgroup --manageusers"); + console.log(" MeshCtrl AddUserToDeviceGroup --group groupname --userid userid --editgroup --manageusers"); console.log("\r\nRequired arguments:\r\n"); - console.log(" --id [groupid] - The group identifier."); + console.log(" --id [groupid] - Device group identifier (or --group)."); + console.log(" --group [groupname] - Device group name (or --id)."); console.log(" --userid [userid] - The user identifier."); console.log("\r\nOptional arguments:\r\n"); console.log(" --fullrights - Allow full rights over this device group."); @@ -257,13 +284,54 @@ if (args['_'].length == 0) { console.log(" --noterminal - Hide the terminal tab from this user."); console.log(" --nofiles - Hide the files tab from this user."); console.log(" --noamt - Hide the Intel AMT tab from this user."); + console.log(" --limitedevents - User can only see his own events."); + console.log(" --chatnotify - Allow chat and notification options."); + console.log(" --uninstall - Allow remote uninstall of the agent."); + if (args.limiteddesktop) { meshrights |= 4096; } + if (args.limitedevents) { meshrights |= 8192; } + if (args.chatnotify) { meshrights |= 16384; } + if (args.uninstall) { meshrights |= 32768; } + break; } case 'removeuserfromdevicegroup': { console.log("Remove a user from a device group, Example usages:\r\n"); console.log(" MeshCtrl RemoveuserFromDeviceGroup --id groupid --userid userid"); console.log("\r\nRequired arguments:\r\n"); - console.log(" --id [groupid] - The group identifier."); + console.log(" --id [groupid] - Device group identifier (or --group)."); + console.log(" --group [groupname] - Device group name (or --id)."); + console.log(" --userid [userid] - The user identifier."); + break; + } + case 'addusertodevice': { + console.log("Add a user to a device, Example usages:\r\n"); + console.log(" MeshCtrl AddUserToDevice --id deviceid --userid userid --fullrights"); + console.log(" MeshCtrl AddUserToDevice --id deviceid --userid userid --remotecontrol"); + console.log("\r\nRequired arguments:\r\n"); + console.log(" --id [deviceid] - The device identifier."); + console.log(" --userid [userid] - The user identifier."); + console.log("\r\nOptional arguments:\r\n"); + console.log(" --fullrights - Allow full rights over this device."); + console.log(" --remotecontrol - Allow device remote control operations."); + console.log(" --agentconsole - Allow agent console operations."); + console.log(" --serverfiles - Allow access to group server files."); + console.log(" --wakedevices - Allow device wake operation."); + console.log(" --notes - Allow editing of device notes."); + console.log(" --desktopviewonly - Restrict user to view-only remote desktop."); + console.log(" --limiteddesktop - Limit remote desktop keys."); + console.log(" --noterminal - Hide the terminal tab from this user."); + console.log(" --nofiles - Hide the files tab from this user."); + console.log(" --noamt - Hide the Intel AMT tab from this user."); + console.log(" --limitedevents - User can only see his own events."); + console.log(" --chatnotify - Allow chat and notification options."); + console.log(" --uninstall - Allow remote uninstall of the agent."); + break; + } + case 'removeuserfromdevice': { + console.log("Remove a user from a device, Example usages:\r\n"); + console.log(" MeshCtrl RemoveuserFromDeviceGroup --id deviceid --userid userid"); + console.log("\r\nRequired arguments:\r\n"); + console.log(" --id [deviceid] - The device identifier."); console.log(" --userid [userid] - The user identifier."); break; } @@ -271,7 +339,7 @@ if (args['_'].length == 0) { console.log("Display a message to all logged in users, Example usages:\r\n"); console.log(" MeshCtrl Broadcast --msg \"This is a test\""); console.log("\r\nRequired arguments:\r\n"); - console.log(" --msg [message] - Message to display."); + console.log(" --msg [message] - Message to display."); break; } default: { @@ -507,7 +575,8 @@ function serverConnect() { break; } case 'removedevicegroup': { - var op = { action: 'deletemesh', meshid: args.id, responseid: 'meshctrl' }; + var op = { action: 'deletemesh', responseid: 'meshctrl' }; + if (args.id) { op.meshid = args.id; } else if (args.group) { op.meshname = args.group; } ws.send(JSON.stringify(op)); break; } @@ -527,22 +596,56 @@ function serverConnect() { if (args.nofiles) { meshrights |= 1024; } if (args.noamt) { meshrights |= 2048; } if (args.limiteddesktop) { meshrights |= 4096; } - var op = { action: 'addmeshuser', meshid: args.id, usernames: [args.userid], meshadmin: meshrights, responseid: 'meshctrl' }; + if (args.limitedevents) { meshrights |= 8192; } + if (args.chatnotify) { meshrights |= 16384; } + if (args.uninstall) { meshrights |= 32768; } + var op = { action: 'addmeshuser', usernames: [args.userid], meshadmin: meshrights, responseid: 'meshctrl' }; + if (args.id) { op.meshid = args.id; } else if (args.group) { op.meshname = args.group; } ws.send(JSON.stringify(op)); break; } case 'removeuserfromdevicegroup': { - var op = { action: 'removemeshuser', meshid: args.id, userid: args.userid, responseid: 'meshctrl' }; + var op = { action: 'removemeshuser', userid: args.userid, responseid: 'meshctrl' }; + if (args.id) { op.meshid = args.id; } else if (args.group) { op.meshname = args.group; } + ws.send(JSON.stringify(op)); + break; + } + case 'addusertodevice': { + var meshrights = 0; + if (args.fullrights) { meshrights = (8 + 16 + 32 + 64 + 128 + 16384 + 32768); } + if (args.remotecontrol) { meshrights |= 8; } + if (args.agentconsole) { meshrights |= 16; } + if (args.serverfiles) { meshrights |= 32; } + if (args.wakedevices) { meshrights |= 64; } + if (args.notes) { meshrights |= 128; } + if (args.desktopviewonly) { meshrights |= 256; } + if (args.noterminal) { meshrights |= 512; } + if (args.nofiles) { meshrights |= 1024; } + if (args.noamt) { meshrights |= 2048; } + if (args.limiteddesktop) { meshrights |= 4096; } + if (args.limitedevents) { meshrights |= 8192; } + if (args.chatnotify) { meshrights |= 16384; } + if (args.uninstall) { meshrights |= 32768; } + var op = { action: 'adddeviceuser', nodeid: args.id, usernames: [args.userid], rights: meshrights, responseid: 'meshctrl' }; + ws.send(JSON.stringify(op)); + break; + } + case 'removeuserfromdevice': { + var op = { action: 'adddeviceuser', nodeid: args.id, usernames: [args.userid], rights: 0, responseid: 'meshctrl' }; ws.send(JSON.stringify(op)); break; } case 'sendinviteemail': { - var op = { action: "inviteAgent", meshid: args.id, email: args.email, name: "", os: "0", responseid: 'meshctrl' } + var op = { action: 'inviteAgent', email: args.email, name: '', os: '0', responseid: 'meshctrl' } + if (args.id) { op.meshid = args.id; } else if (args.group) { op.meshname = args.group; } + if (args.name) { op.name = args.name; } + if (args.message) { op.msg = args.message; } ws.send(JSON.stringify(op)); break; } case 'generateinvitelink': { - var op = { action: "createInviteLink", meshid: args.id, expire: args.hours, flags: 0, responseid: 'meshctrl' } + var op = { action: 'createInviteLink', expire: args.hours, flags: 0, responseid: 'meshctrl' } + if (args.id) { op.meshid = args.id; } else if (args.group) { op.meshname = args.group; } ws.send(JSON.stringify(op)); break; } @@ -551,6 +654,10 @@ function serverConnect() { ws.send(JSON.stringify(op)); break; } + case 'showevents': { + console.log('Connected. Press ctrl-c to end.'); + break; + } } }); @@ -561,6 +668,10 @@ function serverConnect() { var data = null; try { data = JSON.parse(rawdata); } catch (ex) { } if (data == null) { console.log('Unable to parse data: ' + rawdata); } + if (settings.cmd == 'showevents') { + console.log(data); + return; + } switch (data.action) { case 'serverinfo': { // SERVERINFO if (settings.cmd == 'serverinfo') { @@ -591,6 +702,7 @@ function serverConnect() { case 'addmeshuser': // case 'removemeshuser': // case 'inviteAgent': // + case 'adddeviceuser': // case 'userbroadcast': { // BROADCAST if (data.responseid == 'meshctrl') { if (data.meshid) { console.log(data.result, data.meshid); } diff --git a/meshmail.js b/meshmail.js index f4dfdb03..7227ec9e 100644 --- a/meshmail.js +++ b/meshmail.js @@ -24,7 +24,7 @@ module.exports.CreateMeshMail = function (parent) { obj.retry = 0; obj.sendingMail = false; obj.mailCookieEncryptionKey = null; - obj.mailTemplates = {}; + //obj.mailTemplates = {}; const constants = (obj.parent.crypto.constants ? obj.parent.crypto.constants : require('constants')); // require('constants') is deprecated in Node 11.10, use require('crypto').constants instead. const nodemailer = require('nodemailer'); @@ -40,51 +40,57 @@ module.exports.CreateMeshMail = function (parent) { if ((parent.config.smtp.user != null) && (parent.config.smtp.pass != null)) { options.auth = { user: parent.config.smtp.user, pass: parent.config.smtp.pass }; } obj.smtpServer = nodemailer.createTransport(options); - // Set default mail templates - // You can override these by placing a file with the same name in "meshcentral-data/mail" - // If the server hash many domains, just add the domainid to the file like this: 'account-check-customer1.html', 'mesh-invite-customer1.txt'. - obj.mailTemplates['account-invite.html'] = '[[[SERVERNAME]]] - Account Invitation\r\n
[[[SERVERNAME]]] - Account Invitation

An account was created for you on server [[[SERVERNAME]]], you can access it now with:

   Username: [[[ACCOUNTNAME]]]
   Password: [[[PASSWORD]]]

Best regards,
[[[USERNAME]]]
'; - obj.mailTemplates['account-check.html'] = '[[[SERVERNAME]]] - Email Verification\r\n
[[[SERVERNAME]]] - Verification

Hi [[[USERNAME]]], [[[SERVERNAME]]] is requesting email verification, click on the following link to complete the process.

Click here to verify your e-mail address.

If you did not initiate this request, please ignore this mail.
'; - obj.mailTemplates['account-reset.html'] = '[[[SERVERNAME]]] - Account Reset\r\n
[[[SERVERNAME]]] - Verification

Hi [[[USERNAME]]], [[[SERVERNAME]]] is requesting an account password reset, click on the following link to complete the process.

Click here to reset your account password.

If you did not initiate this request, please ignore this mail.
'; - obj.mailTemplates['mesh-invite.html'] = '[[[SERVERNAME]]] - Invitation\r\n
[[[SERVERNAME]]] - Agent Installation
[[[AREA-NAME]]]

Hello [[[NAME]]],

[[[/AREA-NAME]]]

User [[[USERNAME]]] on server [[[SERVERNAME]]] is requesting you to install software to start a remote control session.

[[[AREA-MSG]]]

Message: [[[MSG]]]

[[[/AREA-MSG]]][[[AREA-WINDOWS]]]

Click here to download the MeshAgent for Windows.

[[[/AREA-WINDOWS]]][[[AREA-OSX]]]

Click here to download the MeshAgent for Apple OSX.

[[[/AREA-OSX]]][[[AREA-LINUX]]]

For Linux, cut & paste the following in a terminal to install the agent:

wget -q "[[[SERVERURL]]]/meshagents?script=1" --no-check-certificate -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh [[[SERVERURL]]] \'[[[MESHIDHEX]]]\'

[[[/AREA-LINUX]]][[[AREA-LINK]]]

To install the software, click here and follow the instructions.

[[[/AREA-LINK]]]

If you did not initiate this request, please ignore this mail.

Best regards,
[[[USERNAME]]]
'; + // Get the correct mail template object + function getTemplate(name, domain, lang) { + parent.debug('email', 'Getting mail template for: ' + name + ', lang: ' + lang); + if (Array.isArray(lang)) { lang = lang[0]; } // TODO: For now, we only use the first language given. - obj.mailTemplates['account-invite.txt'] = '[[[SERVERNAME]]] - Account Invitation\r\nAn account was created for you on server [[[SERVERNAME]]] ([[[SERVERURL]]]/), you can access it now with username \"[[[ACCOUNTNAME]]]\" and password \"[[[PASSWORD]]]\".\r\n\r\nBest regards,\r\n[[[USERNAME]]]'; - obj.mailTemplates['account-check.txt'] = '[[[SERVERNAME]]] - Email Verification\r\nHi [[[USERNAME]]], [[[SERVERNAME]]] ([[[SERVERURL]]]) is performing an e-mail verification. Nagivate to the following link to complete the process:\r\n\r\n[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]]\r\n\r\nIf you did not initiate this request, please ignore this mail.\r\n'; - obj.mailTemplates['account-reset.txt'] = '[[[SERVERNAME]]] - Account Reset\r\nHi [[[USERNAME]]], [[[SERVERNAME]]] ([[[SERVERURL]]]) is requesting an account password reset. Nagivate to the following link to complete the process:\r\n\r\n[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]]\r\n\r\nIf you did not initiate this request, please ignore this mail.'; - obj.mailTemplates['mesh-invite.txt'] = '[[[SERVERNAME]]] - Invitation\r\n[[[AREA-NAME]]]Hello [[[NAME]]],\r\n\r\n[[[/AREA-NAME]]]User [[[USERNAME]]] on server [[[SERVERNAME]]] ([[[SERVERURL]]]/) is requesting you install software to start the remote control session.[[[AREA-MSG]]]\r\n\r\nMessage: [[[MSG]]]\r\n\r\n[[[/AREA-MSG]]][[[AREA-WINDOWS]]]For Windows, nagivate to the following link to complete the process:\r\n\r\n[[[SERVERURL]]]/meshagents?id=3&meshid=[[[MESHIDHEX]]]&tag=mailto:[[[EMAIL]]]&installflags=[[[INSTALLFLAGS]]]\r\n\r\n[[[/AREA-WINDOWS]]][[[AREA-OSX]]]For Apple OSX, nagivate to the following link to complete the process:\r\n\r\n[[[SERVERURL]]]/meshagents?id=16&meshid=[[[MESHIDHEX]]]&tag=mailto:[[[EMAIL]]]&installflags=[[[INSTALLFLAGS]]]\r\n\r\n[[[/AREA-OSX]]][[[AREA-LINUX]]]For Linux, cut & paste the following in a terminal to install the agent:\r\n\r\nwget -q "[[[SERVERURL]]]/meshagents?script=1" --no-check-certificate -O ./meshinstall.sh && chmod 755 ./meshinstall.sh && sudo ./meshinstall.sh [[[SERVERURL]]] \'[[[MESHIDHEX]]]\'\r\n\r\n[[[/AREA-LINUX]]][[[AREA-LINK]]]To install the software, navigate to [[[SERVERURL]]][[[LINKURL]]] and follow the instructions.\r\n\r\n[[[/AREA-LINK]]]If you did not initiate this request, please ignore this mail.\r\n\r\nBest regards,\r\n[[[USERNAME]]]'; + var r = {}, emailsPath = null; + if ((domain != null) && (domain.webemailspath != null)) { emailsPath = domain.webemailspath; } + else if (obj.parent.webEmailsOverridePath != null) { emailsPath = obj.parent.webEmailsOverridePath; } + else if (obj.parent.webEmailsPath != null) { emailsPath = obj.parent.webEmailsPath; } + if ((emailsPath == null) || (obj.parent.fs.existsSync(emailsPath) == false)) { return null } - // Load all of the mail templates if present - if (obj.parent.fs.existsSync(obj.parent.path.join(obj.parent.datapath, 'mail-templates'))) { - var mailDir = null; - try { mailDir = obj.parent.fs.readdirSync(obj.parent.path.join(obj.parent.datapath, 'mail-templates')); } catch (e) { } - if (mailDir != null) { - // Load all mail templates - for (var i in mailDir) { - var templateName = mailDir[i].toLowerCase(); - if (templateName.endsWith('.html') || templateName.endsWith('.txt')) { obj.mailTemplates[templateName] = obj.parent.fs.readFileSync(obj.parent.path.join(obj.parent.datapath, 'mail-templates', mailDir[i])).toString(); } + // Get the non-english email if needed + var htmlfile = null, txtfile = null; + if ((lang != null) && (lang != 'en')) { + var translationsPath = obj.parent.path.join(emailsPath, 'translations'); + var translationsPathHtml = obj.parent.path.join(emailsPath, 'translations', name + '_' + lang + '.html'); + var translationsPathTxt = obj.parent.path.join(emailsPath, 'translations', name + '_' + lang + '.txt'); + if (obj.parent.fs.existsSync(translationsPath) && obj.parent.fs.existsSync(translationsPathHtml) && obj.parent.fs.existsSync(translationsPathTxt)) { + htmlfile = obj.parent.fs.readFileSync(translationsPathHtml).toString(); + txtfile = obj.parent.fs.readFileSync(translationsPathTxt).toString(); } } - } else { - // Save the default templates - try { - obj.parent.fs.mkdirSync(obj.parent.path.join(obj.parent.datapath, 'mail-templates')); - for (var i in obj.mailTemplates) { obj.parent.fs.writeFileSync(obj.parent.path.join(obj.parent.datapath, 'mail-templates', i), obj.mailTemplates[i], 'utf8'); } - } catch (e) { console.error(e); } - } - // Get the correct mail template - function getTemplate(name, domain, html) { - if (domain != null) { var r = obj.mailTemplates[name + '-' + domain.id + (html ? '.html' : '.txt')]; if (r) return r; } - return obj.mailTemplates[name + (html ? '.html' : '.txt')]; - } + // Get the english email + if ((htmlfile == null) || (txtfile == null)) { + var pathHtml = obj.parent.path.join(emailsPath, name + '.html'); + var pathTxt = obj.parent.path.join(emailsPath, name + '.txt'); + if (obj.parent.fs.existsSync(pathHtml) && obj.parent.fs.existsSync(pathTxt)) { + htmlfile = obj.parent.fs.readFileSync(pathHtml).toString(); + txtfile = obj.parent.fs.readFileSync(pathTxt).toString(); + } + } + + // No email templates + if ((htmlfile == null) || (txtfile == null)) { return null; } + + // Decode the HTML file + htmlfile = htmlfile.split('').join('').split('').join('').split('').join('').split('').join('').split('').join('').split('').join('').split(' notrans="1"').join(''); + var lines = htmlfile.split('\r\n').join('\n').split('\n'); + r.htmlSubject = lines.shift(); + if (r.htmlSubject.startsWith('
')) { r.htmlSubject = r.htmlSubject.substring(5); } + if (r.htmlSubject.endsWith('
')) { r.htmlSubject = r.htmlSubject.substring(0, r.htmlSubject.length - 6); } + r.html = lines.join('\r\n'); + + // Decode the TXT file + lines = txtfile.split('\r\n').join('\n').split('\n'); + r.txtSubject = lines.shift(); + var txtbody = []; + for (var i in lines) { var line = lines[i]; if ((line.length > 0) && (line[0] == '~')) { txtbody.push(line.substring(1)); } else { txtbody.push(line); } } + r.txt = txtbody.join('\r\n'); - // Get the correct mail template object - function getTemplateEx(name, domain) { - var r = {}, txt = getTemplate(name, domain, 0), html = getTemplate(name, domain, 1); - r.txtSubject = txt.split('\r\n')[0]; - r.htmlSubject = getStrBetween(html, '', '\r\n'); - r.txt = txt.substring(txt.indexOf('\r\n') + 2); - r.html = html.substring(html.indexOf('\r\n') + 2); return r; } @@ -102,11 +108,19 @@ module.exports.CreateMeshMail = function (parent) { return str.substring(0, si) + str.substring(ei + end.length); } - // Keep or remove the string between two markers + // Keep or remove all lines between two lines with markers function strZone(str, marker, keep) { - marker = marker.toUpperCase(); - if (keep) { return str.split('[[[AREA-' + marker + ']]]').join('').split('[[[/AREA-' + marker + ']]]').join(''); } - return removeStrBetween(str, '[[[AREA-' + marker + ']]]', '[[[/AREA-' + marker + ']]]'); + var lines = str.split('\r\n'), linesEx = [], removing = false; + const startMarker = '', endMarker = ''; + for (var i in lines) { + var line = lines[i]; + if (removing) { + if (line.indexOf(endMarker) >= 0) { removing = false; } else { if (keep) { linesEx.push(line); } } + } else { + if (line.indexOf(startMarker) >= 0) { removing = true; } else { linesEx.push(line); } + } + } + return linesEx.join('\r\n'); } // Perform all e-mail substitution @@ -121,75 +135,158 @@ module.exports.CreateMeshMail = function (parent) { } if (options.serverurl.endsWith('/')) { options.serverurl = options.serverurl.substring(0, options.serverurl.length - 1); } // Remove the ending / if present for (var i in options) { - text = strZone(text, i.toUpperCase(), options[i]); // Adjust this text area + text = strZone(text, i.toLowerCase(), options[i]); // Adjust this text area text = text.split('[[[' + i.toUpperCase() + ']]]').join(options[i]); // Replace this value } return text; } - // Send a mail + // Send a generic email obj.sendMail = function (to, subject, text, html) { obj.pendingMails.push({ to: to, from: parent.config.smtp.from, subject: subject, text: text, html: html }); sendNextMail(); }; + // Send account login mail / 2 factor token + obj.sendAccountLoginMail = function (domain, email, token, language) { + obj.checkEmail(email, function (checked) { + if (checked) { + parent.debug('email', "Sending login token to " + email); + + if ((parent.certificates == null) || (parent.certificates.CommonName == null) || (parent.certificates.CommonName.indexOf('.') == -1)) { + parent.debug('email', "Error: Server name not set."); // If the server name is not set, email not possible. + return; + } + + var template = getTemplate('account-login', domain, language); + if ((template == null) || (template.htmlSubject == null) || (template.txtSubject == null)) { + parent.debug('email', "Error: Failed to get mail template."); // Not email template found + return; + } + + // Set all the options. + var options = { email: email, servername: domain.title ? domain.title : 'MeshCentral', token: token }; + + // Send the email + obj.pendingMails.push({ to: email, from: parent.config.smtp.from, subject: mailReplacements(template.htmlSubject, domain, options), text: mailReplacements(template.txt, domain, options), html: mailReplacements(template.html, domain, options) }); + sendNextMail(); + } + }); + }; + // Send account invitation mail - obj.sendAccountInviteMail = function (domain, username, accountname, email, password) { - var template = getTemplateEx('account-invite', domain); - if ((template == null) || (template.htmlSubject == null) || (template.txtSubject == null) || (parent.certificates == null) || (parent.certificates.CommonName == null) || (parent.certificates.CommonName.indexOf('.') == -1)) return; // If the server name is not set, invitation not possible. + obj.sendAccountInviteMail = function (domain, username, accountname, email, password, language) { + obj.checkEmail(email, function (checked) { + if (checked) { + parent.debug('email', "Sending account invitation to " + email); - // Set all the options. - var options = { username: username, accountname: accountname, email: email, servername: domain.title ? domain.title : 'MeshCentral', password: password }; + if ((parent.certificates == null) || (parent.certificates.CommonName == null) || (parent.certificates.CommonName.indexOf('.') == -1)) { + parent.debug('email', "Error: Server name not set."); // If the server name is not set, email not possible. + return; + } - // Send the email - obj.pendingMails.push({ to: email, from: parent.config.smtp.from, subject: mailReplacements(template.htmlSubject, domain, options), text: mailReplacements(template.txt, domain, options), html: mailReplacements(template.html, domain, options) }); - sendNextMail(); + var template = getTemplate('account-invite', domain, language); + if ((template == null) || (template.htmlSubject == null) || (template.txtSubject == null)) { + parent.debug('email', "Error: Failed to get mail template."); // Not email template found + return; + } + + // Set all the options. + var options = { username: username, accountname: accountname, email: email, servername: domain.title ? domain.title : 'MeshCentral', password: password }; + + // Send the email + obj.pendingMails.push({ to: email, from: parent.config.smtp.from, subject: mailReplacements(template.htmlSubject, domain, options), text: mailReplacements(template.txt, domain, options), html: mailReplacements(template.html, domain, options) }); + sendNextMail(); + } + }); }; // Send account check mail - obj.sendAccountCheckMail = function (domain, username, email) { - var template = getTemplateEx('account-check', domain); - if ((template == null) || (template.htmlSubject == null) || (template.txtSubject == null) || (parent.certificates == null) || (parent.certificates.CommonName == null) || (parent.certificates.CommonName.indexOf('.') == -1)) return; // If the server name is not set, no reset possible. + obj.sendAccountCheckMail = function (domain, username, email, language) { + obj.checkEmail(email, function (checked) { + if (checked) { + parent.debug('email', "Sending email verification to " + email); - // Set all the options. - var options = { username: username, email: email, servername: domain.title ? domain.title : 'MeshCentral' }; - options.cookie = obj.parent.encodeCookie({ u: domain.id + '/' + username.toLowerCase(), e: email, a: 1 }, obj.mailCookieEncryptionKey); + if ((parent.certificates == null) || (parent.certificates.CommonName == null) || (parent.certificates.CommonName.indexOf('.') == -1)) { + parent.debug('email', "Error: Server name not set."); // If the server name is not set, email not possible. + return; + } - // Send the email - obj.pendingMails.push({ to: email, from: parent.config.smtp.from, subject: mailReplacements(template.htmlSubject, domain, options), text: mailReplacements(template.txt, domain, options), html: mailReplacements(template.html, domain, options) }); - sendNextMail(); + var template = getTemplate('account-check', domain, language); + if ((template == null) || (template.htmlSubject == null) || (template.txtSubject == null)) { + parent.debug('email', "Error: Failed to get mail template."); // Not email template found + return; + } + + // Set all the options. + var options = { username: username, email: email, servername: domain.title ? domain.title : 'MeshCentral' }; + options.cookie = obj.parent.encodeCookie({ u: domain.id + '/' + username.toLowerCase(), e: email, a: 1 }, obj.mailCookieEncryptionKey); + + // Send the email + obj.pendingMails.push({ to: email, from: parent.config.smtp.from, subject: mailReplacements(template.htmlSubject, domain, options), text: mailReplacements(template.txt, domain, options), html: mailReplacements(template.html, domain, options) }); + sendNextMail(); + } + }); }; // Send account reset mail - obj.sendAccountResetMail = function (domain, username, email) { - var template = getTemplateEx('account-reset', domain); - if ((template == null) || (template.htmlSubject == null) || (template.txtSubject == null) || (parent.certificates == null) || (parent.certificates.CommonName == null) || (parent.certificates.CommonName.indexOf('.') == -1)) return; // If the server name is not set, don't validate the email address. + obj.sendAccountResetMail = function (domain, username, email, language) { + obj.checkEmail(email, function (checked) { + if (checked) { + parent.debug('email', "Sending account password reset to " + email); - // Set all the options. - var options = { username: username, email: email, servername: domain.title ? domain.title : 'MeshCentral' }; - options.cookie = obj.parent.encodeCookie({ u: domain.id + '/' + username, e: email, a: 2 }, obj.mailCookieEncryptionKey); + if ((parent.certificates == null) || (parent.certificates.CommonName == null) || (parent.certificates.CommonName.indexOf('.') == -1)) { + parent.debug('email', "Error: Server name not set."); // If the server name is not set, email not possible. + return; + } - // Send the email - obj.pendingMails.push({ to: email, from: parent.config.smtp.from, subject: mailReplacements(template.htmlSubject, domain, options), text: mailReplacements(template.txt, domain, options), html: mailReplacements(template.html, domain, options) }); - sendNextMail(); + var template = getTemplate('account-reset', domain, language); + if ((template == null) || (template.htmlSubject == null) || (template.txtSubject == null)) { + parent.debug('email', "Error: Failed to get mail template."); // Not email template found + return; + } + + // Set all the options. + var options = { username: username, email: email, servername: domain.title ? domain.title : 'MeshCentral' }; + options.cookie = obj.parent.encodeCookie({ u: domain.id + '/' + username, e: email, a: 2 }, obj.mailCookieEncryptionKey); + + // Send the email + obj.pendingMails.push({ to: email, from: parent.config.smtp.from, subject: mailReplacements(template.htmlSubject, domain, options), text: mailReplacements(template.txt, domain, options), html: mailReplacements(template.html, domain, options) }); + sendNextMail(); + } + }); }; // Send agent invite mail - obj.sendAgentInviteMail = function (domain, username, email, meshid, name, os, msg, flags, expirehours) { - var template = getTemplateEx('mesh-invite', domain); - if ((template == null) || (template.htmlSubject == null) || (template.txtSubject == null) || (parent.certificates == null) || (parent.certificates.CommonName == null) || (parent.certificates.CommonName.indexOf('.') == -1)) return; // If the server name is not set, don't validate the email address. + obj.sendAgentInviteMail = function (domain, username, email, meshid, name, os, msg, flags, expirehours, language) { + obj.checkEmail(email, function (checked) { + if (checked) { + parent.debug('email', "Sending agent install invitation to " + email); - // Set all the template replacement options and generate the final email text (both in txt and html formats). - var options = { username: username, name: name, email: email, installflags: flags, msg: msg, meshid: meshid, meshidhex: meshid.split('/')[2], servername: domain.title ? domain.title : 'MeshCentral' }; - options.windows = ((os == 0) || (os == 1)) ? 1 : 0; - options.linux = ((os == 0) || (os == 2)) ? 1 : 0; - options.osx = ((os == 0) || (os == 3)) ? 1 : 0; - options.link = (os == 4) ? 1 : 0; - options.linkurl = createInviteLink(domain, meshid, flags, expirehours); + if ((parent.certificates == null) || (parent.certificates.CommonName == null) || (parent.certificates.CommonName.indexOf('.') == -1)) { + parent.debug('email', "Error: Server name not set."); // If the server name is not set, email not possible. + return; + } - // Send the email - obj.pendingMails.push({ to: email, from: parent.config.smtp.from, subject: mailReplacements(template.htmlSubject, domain, options), text: mailReplacements(template.txt, domain, options), html: mailReplacements(template.html, domain, options) }); - sendNextMail(); + var template = getTemplate('mesh-invite', domain, language); + if ((template == null) || (template.htmlSubject == null) || (template.txtSubject == null)) { + parent.debug('email', "Error: Failed to get mail template."); // Not email template found + return; + } + + // Set all the template replacement options and generate the final email text (both in txt and html formats). + var options = { username: username, name: name, email: email, installflags: flags, msg: msg, meshid: meshid, meshidhex: meshid.split('/')[2], servername: domain.title ? domain.title : 'MeshCentral' }; + options.windows = ((os == 0) || (os == 1)) ? 1 : 0; + options.linux = ((os == 0) || (os == 2)) ? 1 : 0; + options.osx = ((os == 0) || (os == 3)) ? 1 : 0; + options.link = (os == 4) ? 1 : 0; + options.linkurl = createInviteLink(domain, meshid, flags, expirehours); + + // Send the email + obj.pendingMails.push({ to: email, from: parent.config.smtp.from, subject: mailReplacements(template.htmlSubject, domain, options), text: mailReplacements(template.txt, domain, options), html: mailReplacements(template.html, domain, options) }); + sendNextMail(); + } + }); }; // Send out the next mail in the pending list @@ -198,9 +295,9 @@ module.exports.CreateMeshMail = function (parent) { var mailToSend = obj.pendingMails[0]; obj.sendingMail = true; - //console.log('SMTP sending mail to ' + mailToSend.to + '.'); + parent.debug('email', 'SMTP sending mail to ' + mailToSend.to + '.'); obj.smtpServer.sendMail(mailToSend, function (err, info) { - //console.log(JSON.stringify(err), JSON.stringify(info)); + parent.debug('email', 'SMTP response: ' + JSON.stringify(err) + ', ' + JSON.stringify(info)); obj.sendingMail = false; if (err == null) { obj.pendingMails.shift(); @@ -208,6 +305,7 @@ module.exports.CreateMeshMail = function (parent) { sendNextMail(); // Send the next mail } else { obj.retry++; + parent.debug('email', 'SMTP server failed: ' + JSON.stringify(err)); console.log('SMTP server failed: ' + JSON.stringify(err)); if (obj.retry < 6) { setTimeout(sendNextMail, 60000); } // Wait and try again } @@ -223,6 +321,7 @@ module.exports.CreateMeshMail = function (parent) { // Remove all non-object types from error to avoid a JSON stringify error. var err2 = {}; for (var i in err) { if (typeof (err[i]) != 'object') { err2[i] = err[i]; } } + parent.debug('email', 'SMTP mail server ' + parent.config.smtp.host + ' failed: ' + JSON.stringify(err2)); console.log('SMTP mail server ' + parent.config.smtp.host + ' failed: ' + JSON.stringify(err2)); } }); @@ -245,5 +344,18 @@ module.exports.CreateMeshMail = function (parent) { return '/agentinvite?c=' + parent.encodeCookie({ a: 4, mid: meshid, f: flags, expire: expirehours * 60 }, parent.invitationLinkEncryptionKey); } + // Check the email domain DNS MX record. + obj.approvedEmailDomains = {}; + obj.checkEmail = function (email, func) { + var emailSplit = email.split('@'); + if (emailSplit.length != 2) { func(false); return; } + if (obj.approvedEmailDomains[emailSplit[1]] === true) { func(true); return; } + require('dns').resolveMx(emailSplit[1], function (err, addresses) { + parent.debug('email', "checkEmail: " + email + ", " + (err == null)); + if (err == null) { obj.approvedEmailDomains[emailSplit[1]] = true; } + func(err == null); + }); + } + return obj; }; \ No newline at end of file diff --git a/meshrelay.js b/meshrelay.js index 4d8617e9..ab593a8b 100644 --- a/meshrelay.js +++ b/meshrelay.js @@ -80,7 +80,7 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie var agent = parent.wsagents[command.nodeid]; if (agent != null) { // Check if we have permission to send a message to that node - rights = user.links[agent.dbMeshKey]; // TODO: Need to include user group / node rights + rights = parent.GetNodeRights(user, agent.dbMeshKey, agent.dbNodeKey); mesh = parent.meshes[agent.dbMeshKey]; if ((rights != null) && (mesh != null) || ((rights & 16) != 0)) { // TODO: 16 is console permission, may need more gradular permission checking if (ws.sessionId) { command.sessionid = ws.sessionId; } // Set the session id, required for responses. @@ -98,7 +98,7 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie var routing = parent.parent.GetRoutingServerId(command.nodeid, 1); // 1 = MeshAgent routing type if (routing != null) { // Check if we have permission to send a message to that node - rights = user.links[routing.meshid]; // TODO: Need to include user groups / node rights + rights = parent.GetNodeRights(user, routing.meshid, command.nodeid); mesh = parent.meshes[routing.meshid]; if (rights != null || ((rights & 16) != 0)) { // TODO: 16 is console permission, may need more gradular permission checking if (ws.sessionId) { command.fromSessionid = ws.sessionId; } // Set the session id, required for responses. @@ -227,8 +227,8 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie var metadata = { magic: 'MeshCentralRelaySession', ver: 1, userid: sessionUser._id, username: sessionUser.name, sessionid: obj.id, ipaddr1: cleanRemoteAddr(obj.req.ip), ipaddr2: cleanRemoteAddr(obj.peer.req.ip), time: new Date().toLocaleString(), protocol: (((obj.req == null) || (obj.req.query == null)) ? null : obj.req.query.p), nodeid: (((obj.req == null) || (obj.req.query == null)) ? null : obj.req.query.nodeid ) }; if (xdevicename2 != null) { metadata.devicename = xdevicename2; } var firstBlock = JSON.stringify(metadata); - recordingEntry(fd, 1, ((obj.req.query.browser) ? 2 : 0), firstBlock, function () { - try { relayinfo.peer1.ws.logfile = ws.logfile = { fd: fd, lock: false }; } catch (ex) { + recordingEntry(fd, 1, 0, firstBlock, function () { + try { relayinfo.peer1.ws.logfile = ws.logfile = { fd: fd, lock: false, filename: recFullFilename }; } catch (ex) { try { ws.send('c'); } catch (ex) { } // Send connect to both peers, 'cr' indicates the session is being recorded. try { relayinfo.peer1.ws.send('c'); } catch (ex) { } return; @@ -330,9 +330,6 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie if (relayinfo.state == 2) { var peer = (relayinfo.peer1 == obj) ? relayinfo.peer2 : relayinfo.peer1; - // Close the recording file - if (ws.logfile != null) { recordingEntry(ws.logfile.fd, 3, 0, 'MeshCentralMCREC', function (fd, tag) { parent.parent.fs.close(fd); tag.ws.logfile = null; tag.pws.logfile = null; }, { ws: ws, pws: peer.ws }); } - // Disconnect the peer try { if (peer.relaySessionCounted) { parent.relaySessionCount--; delete peer.relaySessionCounted; } } catch (ex) { console.log(ex); } parent.parent.debug('relay', 'Relay disconnect: ' + obj.id + ' (' + cleanRemoteAddr(obj.req.ip) + ' --> ' + cleanRemoteAddr(peer.req.ip) + ')'); @@ -361,6 +358,19 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie } else { parent.parent.debug('relay', 'Relay disconnect: ' + obj.id + ' (' + cleanRemoteAddr(obj.req.ip) + ')'); } + + // Close the recording file if needed + if (ws.logfile != null) { + var logfile = ws.logfile; + delete ws.logfile; + if (peer.ws) { delete peer.ws.logfile; } + recordingEntry(logfile.fd, 3, 0, 'MeshCentralMCREC', function (fd, tag) { + parent.parent.fs.close(fd); + // Now that the recording file is closed, check if we need to index this file. + if (domain.sessionrecording.index !== false) { parent.parent.certificateOperations.acceleratorPerformOperation('indexMcRec', tag.logfile.filename); } + }, { ws: ws, pws: peer.ws, logfile: logfile }); + } + try { ws.close(); } catch (ex) { } delete parent.wsrelays[obj.id]; } @@ -409,8 +419,7 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie const node = docs[0]; // Check if this user has permission to manage this computer - const meshlinks = user.links[node.meshid]; - if ((!meshlinks) || (!meshlinks.rights) || ((meshlinks.rights & MESHRIGHT_REMOTECONTROL) == 0)) { console.log('ERR: Access denied (2)'); try { obj.close(); } catch (e) { } return; } + if ((parent.GetNodeRights(user, node.meshid, node._id) & MESHRIGHT_REMOTECONTROL) == 0) { console.log('ERR: Access denied (1)'); try { obj.close(); } catch (e) { } return; } // Send connection request to agent const rcookie = parent.parent.encodeCookie({ ruserid: user._id }, parent.parent.loginCookieEncryptionKey); @@ -428,8 +437,7 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie const node = docs[0]; // Check if this user has permission to manage this computer - const meshlinks = user.links[node.meshid]; - if ((!meshlinks) || (!meshlinks.rights) || ((meshlinks.rights & MESHRIGHT_REMOTECONTROL) == 0)) { console.log('ERR: Access denied (2)'); try { obj.close(); } catch (e) { } return; } + if ((parent.GetNodeRights(user, node.meshid, node._id) & MESHRIGHT_REMOTECONTROL) == 0) { console.log('ERR: Access denied (2)'); try { obj.close(); } catch (e) { } return; } // Send connection request to agent if (obj.id == null) { obj.id = ('' + Math.random()).substring(2); } // If there is no connection id, generate one. diff --git a/meshuser.js b/meshuser.js index e9cb200b..c016e087 100644 --- a/meshuser.js +++ b/meshuser.js @@ -162,8 +162,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use var agent = parent.wsagents[command.nodeid]; if (agent != null) { // Check if we have permission to send a message to that node - var meshrights = parent.GetMeshRights(user, agent.dbMeshKey); // TODO: We will need to get the rights for this specific node. + //var meshrights = parent.GetMeshRights(user, agent.dbMeshKey); // TODO: We will need to get the rights for this specific node. var mesh = parent.meshes[agent.dbMeshKey]; + var meshrights = parent.GetNodeRights(user, mesh, agent.dbNodeKey); if ((mesh != null) && ((meshrights & MESHRIGHT_REMOTECONTROL) || (meshrights & MESHRIGHT_REMOTEVIEWONLY))) { // 8 is remote control permission, 256 is desktop read only command.sessionid = ws.sessionId; // Set the session id, required for responses command.rights = meshrights; // Add user rights flags to the message @@ -181,8 +182,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use var routing = parent.parent.GetRoutingServerId(command.nodeid, 1); // 1 = MeshAgent routing type if (routing != null) { // Check if we have permission to send a message to that node - var meshrights = parent.GetMeshRights(user, routing.meshid); + //var meshrights = parent.GetMeshRights(user, routing.meshid); // TODO: We will need to get the rights for this specific node. var mesh = parent.meshes[routing.meshid]; + var meshrights = parent.GetNodeRights(user, mesh, agent.dbNodeKey); if ((mesh != null) && ((meshrights & MESHRIGHT_REMOTECONTROL) || (meshrights & MESHRIGHT_REMOTEVIEWONLY))) { // 8 is remote control permission command.fromSessionid = ws.sessionId; // Set the session id, required for responses command.rights = meshrights; // Add user rights flags to the message @@ -370,7 +372,11 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use try { ws.send(JSON.stringify({ action: 'serverinfo', serverinfo: serverinfo })); } catch (ex) { } // Send user information to web socket, this is the first thing we send - try { ws.send(JSON.stringify({ action: 'userinfo', userinfo: parent.CloneSafeUser(parent.users[user._id]) })); } catch (ex) { } + try { + var xuserinfo = parent.CloneSafeUser(parent.users[user._id]); + if ((user.siteadmin == 0xFFFFFFFF) && (parent.parent.config.settings.managealldevicegroups.indexOf(user._id) >= 0)) { xuserinfo.manageAllDeviceGroups = true; } + ws.send(JSON.stringify({ action: 'userinfo', userinfo: xuserinfo })); + } catch (ex) { } if (user.siteadmin == 0xFFFFFFFF) { // Send server tracing information @@ -469,11 +475,14 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use } case 'nodes': { - var links = [], err = null; + var links = [], extraids = null, err = null; try { if (command.meshid == null) { // Request a list of all meshes this user as rights to links = parent.GetAllMeshIdWithRights(user); + + // Add any nodes with direct rights + if (obj.user.links != null) { for (var i in obj.user.links) { if (i.startsWith('node/')) { if (extraids == null) { extraids = []; } extraids.push(i); } } } } else { // Request list of all nodes for one specific meshid meshid = command.meshid; @@ -491,12 +500,15 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use } // Request a list of all nodes - db.GetAllTypeNoTypeFieldMeshFiltered(links, domain.id, 'node', command.id, function (err, docs) { + db.GetAllTypeNoTypeFieldMeshFiltered(links, extraids, domain.id, 'node', command.id, function (err, docs) { if (docs == null) { docs = []; } var r = {}; for (i in docs) { + // Check device links, if a link points to an unknown user, remove it. + parent.cleanDevice(docs[i]); + // Remove any connectivity and power state information, that should not be in the database anyway. - // TODO: Find why these are sometimes saves in the db. + // TODO: Find why these are sometimes saved in the db. if (docs[i].conn != null) { delete docs[i].conn; } if (docs[i].pwr != null) { delete docs[i].pwr; } if (docs[i].agct != null) { delete docs[i].agct; } @@ -685,7 +697,8 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use switch (cmd) { case 'help': { - var fin = '', f = '', availcommands = 'help,info,versions,args,resetserver,showconfig,usersessions,closeusersessions,tasklimiter,setmaxtasks,cores,migrationagents,agentstats,webstats,mpsstats,swarmstats,acceleratorsstats,updatecheck,serverupdate,nodeconfig,heapdump,relays,autobackup,backupconfig,dupagents,dispatchtable,badlogins,showpaths'; + var fin = '', f = '', availcommands = 'help,info,versions,args,resetserver,showconfig,usersessions,closeusersessions,tasklimiter,setmaxtasks,cores,migrationagents,agentstats,webstats,mpsstats,swarmstats,acceleratorsstats,updatecheck,serverupdate,nodeconfig,heapdump,relays,autobackup,backupconfig,dupagents,dispatchtable,badlogins,showpaths,le,lecheck,leevents,dbstats'; + if (parent.parent.config.settings.heapdump === true) { availcommands += ',heapdump'; } availcommands = availcommands.split(',').sort(); while (availcommands.length > 0) { if (f.length > 80) { fin += (f + ',\r\n'); f = ''; } @@ -695,27 +708,79 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use r = 'Available commands: \r\n' + fin + '.'; break; } - case 'badlogins': { - if (typeof parent.parent.config.settings.maxinvalidlogin.coolofftime == 'number') { - r = "Max is " + parent.parent.config.settings.maxinvalidlogin.count + " bad login(s) in " + parent.parent.config.settings.maxinvalidlogin.time + " minute(s), " + parent.parent.config.settings.maxinvalidlogin.coolofftime + " minute(s) cooloff.\r\n"; + case 'heapdump': { + // Heapdump support, see example at: + // https://www.arbazsiddiqui.me/a-practical-guide-to-memory-leaks-in-nodejs/ + if (parent.parent.config.settings.heapdump === true) { + var dumpFileName = parent.path.join(parent.parent.datapath, `heapDump-${Date.now()}.heapsnapshot`); + try { ws.send(JSON.stringify({ action: 'serverconsole', value: "Generating dump file at: " + dumpFileName, tag: command.tag })); } catch (ex) { } + require('heapdump').writeSnapshot(dumpFileName, (err, filename) => { + try { ws.send(JSON.stringify({ action: 'serverconsole', value: "Done.", tag: command.tag })); } catch (ex) { } + }); } else { - r = "Max is " + parent.parent.config.settings.maxinvalidlogin.count + " bad login(s) in " + parent.parent.config.settings.maxinvalidlogin.time + " minute(s).\r\n"; + r = "Heapdump not supported, add \"heapdump\":true to settings section of config.json."; } - var badLoginCount = 0; - parent.cleanBadLoginTable(); - for (var i in parent.badLoginTable) { - badLoginCount++; - if (typeof parent.badLoginTable[i] == 'number') { - r += "Cooloff for " + Math.floor((parent.badLoginTable[i] - Date.now()) / 60000) + " minute(s)\r\n"; - } else { - if (parent.badLoginTable[i].length > 1) { - r += (i + ' - ' + parent.badLoginTable[i].length + " records\r\n"); + break; + } + case 'le': { + if (parent.parent.letsencrypt == null) { + r = "Let's Encrypt not in use."; + } else { + r = JSON.stringify(parent.parent.letsencrypt.getStats(), null, 4); + } + break; + } + case 'lecheck': { + if (parent.parent.letsencrypt == null) { + r = "Let's Encrypt not in use."; + } else { + r = ["CertOK", "Request:NoCert", "Request:Expire", "Request:MissingNames"][parent.parent.letsencrypt.checkRenewCertificate()]; + } + break; + } + case 'leevents': { + if (parent.parent.letsencrypt == null) { + r = "Let's Encrypt not in use."; + } else { + r = parent.parent.letsencrypt.events.join('\r\n'); + } + break; + } + case 'badlogins': { + if (parent.parent.config.settings.maxinvalidlogin == false) { + r = 'Bad login filter is disabled.'; + } else { + if (cmdargs['_'] == 'reset') { + // Reset bad login table + parent.badLoginTable = {}; + parent.badLoginTableLastClean = 0; + r = 'Done.' + } else if (cmdargs['_'] == '') { + // Show current bad login table + if (typeof parent.parent.config.settings.maxinvalidlogin.coolofftime == 'number') { + r = "Max is " + parent.parent.config.settings.maxinvalidlogin.count + " bad login(s) in " + parent.parent.config.settings.maxinvalidlogin.time + " minute(s), " + parent.parent.config.settings.maxinvalidlogin.coolofftime + " minute(s) cooloff.\r\n"; } else { - r += (i + ' - ' + parent.badLoginTable[i].length + " record\r\n"); + r = "Max is " + parent.parent.config.settings.maxinvalidlogin.count + " bad login(s) in " + parent.parent.config.settings.maxinvalidlogin.time + " minute(s).\r\n"; } + var badLoginCount = 0; + parent.cleanBadLoginTable(); + for (var i in parent.badLoginTable) { + badLoginCount++; + if (typeof parent.badLoginTable[i] == 'number') { + r += "Cooloff for " + Math.floor((parent.badLoginTable[i] - Date.now()) / 60000) + " minute(s)\r\n"; + } else { + if (parent.badLoginTable[i].length > 1) { + r += (i + ' - ' + parent.badLoginTable[i].length + " records\r\n"); + } else { + r += (i + ' - ' + parent.badLoginTable[i].length + " record\r\n"); + } + } + } + if (badLoginCount == 0) { r += 'No bad logins.'; } + } else { + r = 'Usage: badlogin [reset]'; } } - if (badLoginCount == 0) { r += 'No bad logins.'; } break; } case 'dispatchtable': { @@ -760,6 +825,14 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use } break; } + case 'dbstats': { + parent.parent.db.getStats(function (stats) { + var r2 = ''; + for (var i in stats) { r2 += (i + ': ' + stats[i] + '\r\n'); } + try { ws.send(JSON.stringify({ action: 'serverconsole', value: r2, tag: command.tag })); } catch (ex) { } + }) + break; + } case 'serverupdate': { r = 'Performing server update...'; if (parent.parent.performServerUpdate() == false) { r = 'Server self-update not possible.'; } @@ -776,22 +849,23 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use if (error != null) { r2 += 'Exception: ' + error + '\r\n'; } try { ws.send(JSON.stringify({ action: 'serverconsole', value: r2, tag: command.tag })); } catch (ex) { } }); - r = 'Checking server update...'; + r = "Checking server update..."; break; } case 'info': { var info = process.memoryUsage(); info.dbType = ['None', 'NeDB', 'MongoJS', 'MongoDB'][parent.db.databaseType]; if (parent.db.databaseType == 3) { info.dbChangeStream = parent.db.changeStream; } - try { info.nodeVersion = Number(process.version.match(/^v(\d+\.\d+)/)[1]); } catch (ex) { } - try { info.currentVer = parent.parent.currentVer; } catch (ex) { } + if (parent.parent.pluginHandler != null) { info.plugins = []; for (var i in parent.parent.pluginHandler.plugins) { info.plugins.push(i); } } + try { info.nodeVersion = process.version; } catch (ex) { } + try { info.meshVersion = parent.parent.currentVer; } catch (ex) { } try { info.platform = process.platform; } catch (ex) { } try { info.arch = process.arch; } catch (ex) { } try { info.pid = process.pid; } catch (ex) { } try { info.uptime = process.uptime(); } catch (ex) { } - try { info.version = process.version; } catch (ex) { } try { info.cpuUsage = process.cpuUsage(); } catch (ex) { } try { info.warnings = parent.parent.getServerWarnings(); } catch (ex) { } + try { info.database = ["Unknown", "NeDB", "MongoJS", "MongoDB", "MariaDB", "MySQL"][parent.parent.db.databaseType]; } catch (ex) { } r = JSON.stringify(info, null, 4); break; } @@ -1133,7 +1207,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use parent.parent.DispatchEvent(targets, obj, message); // Send the verification email - if (parent.parent.mailserver != null) { parent.parent.mailserver.sendAccountCheckMail(domain, user.name, user.email); } + if (parent.parent.mailserver != null) { parent.parent.mailserver.sendAccountCheckMail(domain, user.name, user.email, parent.getLanguageCodes(req)); } } }); } @@ -1150,7 +1224,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use if ((parent.parent.mailserver != null) && (obj.user.email.toLowerCase() == command.email)) { // Send the verification email - parent.parent.mailserver.sendAccountCheckMail(domain, user.name, user.email); + parent.parent.mailserver.sendAccountCheckMail(domain, user.name, user.email, parent.getLanguageCodes(req)); } break; } @@ -1208,7 +1282,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use deluser = parent.users[deluserid]; if (deluser == null) { err = 'User does not exists'; } else if ((delusersplit.length != 3) || (delusersplit[1] != domain.id)) { err = 'Invalid domain'; } // Invalid domain, operation only valid for current domain - else if ((deluser.siteadmin != null) && (deluser.siteadmin > 0) && (user.siteadmin != 0xFFFFFFFF)) { err = 'Permission denied'; } // Need full admin to remote another administrator + else if ((deluser.siteadmin == 0xFFFFFFFF) && (user.siteadmin != 0xFFFFFFFF)) { err = 'Permission denied'; } // Need full admin to remote another administrator else if ((user.groups != null) && (user.groups.length > 0) && ((deluser.groups == null) || (findOne(deluser.groups, user.groups) == false))) { err = 'Invalid user group'; } // Can only perform this operation on other users of our group. } } catch (ex) { err = 'Validation exception: ' + ex; } @@ -1219,19 +1293,37 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use break; } - // Remove all the mesh links to this user + // Remove all links to this user if (deluser.links != null) { - for (meshid in deluser.links) { - // Get the mesh - mesh = parent.meshes[meshid]; - if (mesh) { - // Remove user from the mesh - if (mesh.links[deluser._id] != null) { delete mesh.links[deluser._id]; parent.db.Set(common.escapeLinksFieldName(mesh)); } - // Notify mesh change - change = 'Removed user ' + deluser.name + ' from group ' + mesh.name; - var event = { etype: 'mesh', userid: user._id, username: user.name, meshid: mesh._id, name: mesh.name, mtype: mesh.mtype, desc: mesh.desc, action: 'meshchange', links: mesh.links, msg: change, domain: domain.id }; - if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the mesh. Another event will come. - parent.parent.DispatchEvent(['*', mesh._id, deluser._id, user._id], obj, event); + for (var i in deluser.links) { + if (i.startsWith('mesh/')) { + // Get the device group + mesh = parent.meshes[i]; + if (mesh) { + // Remove user from the mesh + if (mesh.links[deluser._id] != null) { delete mesh.links[deluser._id]; parent.db.Set(mesh); } + + // Notify mesh change + change = 'Removed user ' + deluser.name + ' from group ' + mesh.name; + var event = { etype: 'mesh', userid: user._id, username: user.name, meshid: mesh._id, name: mesh.name, mtype: mesh.mtype, desc: mesh.desc, action: 'meshchange', links: mesh.links, msg: change, domain: domain.id, invite: mesh.invite }; + if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the mesh. Another event will come. + parent.parent.DispatchEvent(['*', mesh._id, deluser._id, user._id], obj, event); + } + } else if (i.startsWith('node/')) { + // Get the node and the rights for this node + parent.GetNodeWithRights(domain, deluser, i, function (node, rights, visible) { + if ((node == null) || (node.links == null) || (node.links[deluser._id] == null)) return; + + // Remove the link and save the node to the database + delete node.links[deluser._id]; + if (Object.keys(node.links).length == 0) { delete node.links; } + db.Set(parent.cleanDevice(node)); + + // Event the node change + var event = { etype: 'node', userid: user._id, username: user.name, action: 'changenode', nodeid: node._id, domain: domain.id, msg: (command.rights == 0) ? ('Removed user device rights for ' + node.name) : ('Changed user device rights for ' + node.name), node: parent.CloneSafeNode(node) } + if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the mesh. Another event will come. + parent.parent.DispatchEvent(['*', node.meshid, node._id], obj, event); + }); } } } @@ -1400,7 +1492,12 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use // Handle any errors if (err != null) { - if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'adduser', responseid: command.responseid, result: err })); } catch (ex) { } } + if (command.responseid != null) { + try { ws.send(JSON.stringify({ action: 'adduser', responseid: command.responseid, result: err })); } catch (ex) { } + } else { + // Send error back, user not found. + displayNotificationMessage(err, 'New Account', 'ServerNotify'); + } break; } @@ -1453,7 +1550,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use // Perform email invitation if ((command.emailInvitation == true) && (command.emailVerified == true) && command.email && parent.parent.mailserver) { - parent.parent.mailserver.sendAccountInviteMail(domain, user.name, newusername, command.email.toLowerCase(), command.pass); + parent.parent.mailserver.sendAccountInviteMail(domain, user.name, newusername, command.email.toLowerCase(), command.pass, parent.getLanguageCodes(req)); } // OK Response @@ -1622,10 +1719,10 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use if (xmesh && xmesh.links) { ugrp.links[i] = { rights: cgroup.links[i].rights }; xmesh.links[ugrpid] = { rights: cgroup.links[i].rights }; - db.Set(common.escapeLinksFieldName(xmesh)); + db.Set(xmesh); // Notify mesh change - var event = { etype: 'mesh', userid: user._id, username: user.name, meshid: xmesh._id, name: xmesh.name, mtype: xmesh.mtype, desc: xmesh.desc, action: 'meshchange', links: xmesh.links, msg: 'Added group ' + ugrp.name + ' to mesh ' + xmesh.name, domain: domain.id }; + var event = { etype: 'mesh', userid: user._id, username: user.name, meshid: xmesh._id, name: xmesh.name, mtype: xmesh.mtype, desc: xmesh.desc, action: 'meshchange', links: xmesh.links, msg: 'Added group ' + ugrp.name + ' to mesh ' + xmesh.name, domain: domain.id, invite: mesh.invite }; if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the mesh. Another event will come. //parent.parent.DispatchEvent(['*', xmesh._id, user._id], obj, event); pendingDispatchEvents.push([['*', xmesh._id, user._id], obj, event]); @@ -1636,7 +1733,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use } // Save the new group - db.Set(common.escapeLinksFieldName(ugrp)); + db.Set(ugrp); if (db.changeStream == false) { parent.userGroups[ugrpid] = ugrp; } // Event the device group creation @@ -1661,7 +1758,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use db.Get(command.ugrpid, function (err, groups) { if ((err != null) || (groups.length != 1)) return; - var group = common.unEscapeLinksFieldName(groups[0]); + var group = groups[0]; // Unlink any user and meshes that have a link to this group if (group.links) { @@ -1683,10 +1780,10 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use var xmesh = parent.meshes[i]; if (xmesh && xmesh.links) { delete xmesh.links[group._id]; - db.Set(common.escapeLinksFieldName(xmesh)); + db.Set(xmesh); // Notify mesh change - var event = { etype: 'mesh', userid: user._id, username: user.name, meshid: xmesh._id, name: xmesh.name, mtype: xmesh.mtype, desc: xmesh.desc, action: 'meshchange', links: xmesh.links, msg: 'Removed group ' + group.name + ' from mesh ' + xmesh.name, domain: domain.id }; + var event = { etype: 'mesh', userid: user._id, username: user.name, meshid: xmesh._id, name: xmesh.name, mtype: xmesh.mtype, desc: xmesh.desc, action: 'meshchange', links: xmesh.links, msg: 'Removed group ' + group.name + ' from mesh ' + xmesh.name, domain: domain.id, invite: mesh.invite }; if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the mesh. Another event will come. parent.parent.DispatchEvent(['*', xmesh._id, user._id], obj, event); } @@ -1720,7 +1817,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use if ((common.validateString(command.name, 1, 64) == true) && (command.name != group.name) && (command.name.indexOf(' ') == -1)) { change = 'User group name changed from "' + group.name + '" to "' + command.name + '"'; group.name = command.name; } if ((common.validateString(command.desc, 0, 1024) == true) && (command.desc != group.desc)) { if (change != '') change += ' and description changed'; else change += 'User group "' + group.name + '" description changed'; group.desc = command.desc; } if (change != '') { - db.Set(common.escapeLinksFieldName(group)); + db.Set(group); var event = { etype: 'ugrp', userid: user._id, username: user.name, ugrpid: group._id, name: group.name, desc: group.desc, action: 'usergroupchange', links: group.links, msg: change, domain: domain.id }; if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the mesh. Another event will come. parent.parent.DispatchEvent(['*', group._id, user._id], obj, event); @@ -1780,7 +1877,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use if (addedCount > 0) { // Save the new group to the database - db.Set(common.escapeLinksFieldName(group)); + db.Set(group); // Notify user group change var event = { etype: 'ugrp', userid: user._id, username: user.name, ugrpid: group._id, name: group.name, desc: group.desc, action: 'usergroupchange', links: group.links, msg: 'Added user ' + chguser.name + ' to user group ' + group.name, domain: domain.id }; @@ -1842,7 +1939,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use if ((group.links != null) && (group.links[command.userid] != null)) { change = true; delete group.links[command.userid]; - db.Set(common.escapeLinksFieldName(group)); + db.Set(group); // Notify user group change if (change) { @@ -1941,7 +2038,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use case 'changeuserpass': { // Change a user's password - if (user.siteadmin != 0xFFFFFFFF) break; + if ((user.siteadmin & 2) == 0) break; if (common.validateString(command.userid, 1, 256) == false) break; if (common.validateString(command.pass, 0, 256) == false) break; if ((command.hint != null) && (common.validateString(command.hint, 0, 256) == false)) break; @@ -1950,6 +2047,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use var chguser = parent.users[command.userid]; if (chguser) { + // If we are not full administrator, we can't change anything on a different full administrator + if ((user.siteadmin != 0xFFFFFFFF) & (chguser.siteadmin == 0xFFFFFFFF)) break; + // Can only perform this operation on other users of our group. if ((user.groups != null) && (user.groups.length > 0) && ((chguser.groups == null) || (findOne(chguser.groups, user.groups) == false))) break; @@ -1965,6 +2065,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use if (command.resetNextLogin === true) { chguser.passchange = -1; } else { chguser.passchange = Math.floor(Date.now() / 1000); } delete chguser.passtype; // Remove the password type if one was present. if (command.removeMultiFactor == true) { + if (chguser.otpekey) { delete chguser.otpekey; } if (chguser.otpsecret) { delete chguser.otpsecret; } if (chguser.otphkeys) { delete chguser.otphkeys; } if (chguser.otpkeys) { delete chguser.otpkeys; } @@ -2112,7 +2213,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use var links = {}; links[user._id] = { name: user.name, rights: 4294967295 }; mesh = { type: 'mesh', _id: meshid, name: command.meshname, mtype: command.meshtype, desc: command.desc, domain: domain.id, links: links }; - db.Set(common.escapeLinksFieldName(mesh)); + db.Set(mesh); parent.meshes[meshid] = mesh; parent.parent.AddEventDispatch([meshid], ws); @@ -2140,6 +2241,17 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use case 'deletemesh': { var err = null; + + // Resolve the device group name if needed + if ((typeof command.meshname == 'string') && (command.meshid == null)) { + for (var i in parent.meshes) { + var m = parent.meshes[i]; + if ((m.mtype == 2) && (m.name == command.meshname) && parent.IsMeshViewable(user, m)) { + if (command.meshid == null) { command.meshid = m._id; } else { err = 'Duplicate device groups found'; } + } + } + } + try { // Delete a mesh and all computers within it if (common.validateString(command.meshid, 1, 1024) == false) { err = 'Invalid group identifier'; } // Check the meshid @@ -2184,7 +2296,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use var xgroup = parent.userGroups[j]; if (xgroup && xgroup.links) { delete xgroup.links[mesh._id]; - db.Set(common.escapeLinksFieldName(xgroup)); + db.Set(xgroup); // Notify user group change var targets = ['*', 'server-ugroups', user._id, xgroup._id]; @@ -2205,10 +2317,11 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use // Mark the mesh as deleted mesh.deleted = new Date(); // Mark the time this mesh was deleted, we can expire it at some point. - db.Set(common.escapeLinksFieldName(mesh)); // We don't really delete meshes because if a device connects to is again, we will un-delete it. + db.Set(mesh); // We don't really delete meshes because if a device connects to is again, we will un-delete it. // Delete all devices attached to this mesh in the database db.RemoveMeshDocuments(command.meshid); + // TODO: We are possibly deleting devices that users will have links to. We need to clean up the broken links from on occasion. if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'deletemesh', responseid: command.responseid, result: 'ok' })); } catch (ex) { } } break; @@ -2229,9 +2342,37 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use if ((common.validateString(command.desc, 0, 1024) == true) && (command.desc != mesh.desc)) { if (change != '') change += ' and description changed'; else change += 'Group "' + mesh.name + '" description changed'; mesh.desc = command.desc; } if ((common.validateInt(command.flags) == true) && (command.flags != mesh.flags)) { if (change != '') change += ' and flags changed'; else change += 'Group "' + mesh.name + '" flags changed'; mesh.flags = command.flags; } if ((common.validateInt(command.consent) == true) && (command.consent != mesh.consent)) { if (change != '') change += ' and consent changed'; else change += 'Group "' + mesh.name + '" consent changed'; mesh.consent = command.consent; } + + // See if we need to change device group invitation codes + if (mesh.mtype == 2) { + if (command.invite === '*') { + // Clear invite codes + if (mesh.invite != null) { delete mesh.invite; } + if (change != '') { change += ' and invite code changed'; } else { change += 'Group "' + mesh.name + '" invite code changed'; } + } else if (typeof command.invite === 'object') { + // Set invite codes + if ((mesh.invite == null) || (mesh.invite.codes != command.invite.codes) || (mesh.invite.flags != command.invite.flags)) { + // Check if an invite code is not already in use. + var dup = null; + for (var i in command.invite.codes) { + for (var j in parent.meshes) { + if ((j != command.meshid) && (parent.meshes[j].invite != null) && (parent.meshes[j].invite.codes.indexOf(command.invite.codes[i]) >= 0)) { dup = command.invite.codes[i]; break; } + } + } + if (dup != null) { + // A duplicate was found, don't allow this change. + displayNotificationMessage('Error, invite code \"' + dup + '\" already in use.', 'Invite Codes'); + return; + } + mesh.invite = { codes: command.invite.codes, flags: command.invite.flags }; + if (change != '') { change += ' and invite code changed'; } else { change += 'Group "' + mesh.name + '" invite code changed'; } + } + } + } + if (change != '') { - db.Set(common.escapeLinksFieldName(mesh)); - var event = { etype: 'mesh', userid: user._id, username: user.name, meshid: mesh._id, name: mesh.name, mtype: mesh.mtype, desc: mesh.desc, flags: mesh.flags, consent: mesh.consent, action: 'meshchange', links: mesh.links, msg: change, domain: domain.id }; + db.Set(mesh); + var event = { etype: 'mesh', userid: user._id, username: user.name, meshid: mesh._id, name: mesh.name, mtype: mesh.mtype, desc: mesh.desc, flags: mesh.flags, consent: mesh.consent, action: 'meshchange', links: mesh.links, msg: change, domain: domain.id, invite: mesh.invite }; if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the mesh. Another event will come. parent.parent.DispatchEvent(['*', mesh._id, user._id], obj, event); } @@ -2240,8 +2381,19 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use } case 'addmeshuser': { - if (typeof command.userid == 'string') { command.userids = [ command.userid ]; } var err = null; + if (typeof command.userid == 'string') { command.userids = [command.userid]; } + + // Resolve the device group name if needed + if ((typeof command.meshname == 'string') && (command.meshid == null)) { + for (var i in parent.meshes) { + var m = parent.meshes[i]; + if ((m.mtype == 2) && (m.name == command.meshname) && parent.IsMeshViewable(user, m)) { + if (command.meshid == null) { command.meshid = m._id; } else { err = 'Duplicate device groups found'; } + } + } + } + try { if (common.validateString(command.meshid, 1, 1024) == false) { err = 'Invalid groupid'; } // Check the meshid else if (common.validateInt(command.meshadmin) == false) { err = 'Invalid group rights'; } // Mesh rights must be an integer @@ -2267,22 +2419,28 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use for (var i in command.usernames) { command.userids.push('user/' + domain.id + '/' + command.usernames[i].toLowerCase()); } } - var unknownUsers = [], removedCount = 0, failCount = 0; + var unknownUsers = [], successCount = 0, failCount = 0, msgs = []; for (var i in command.userids) { // Check if the user exists var newuserid = command.userids[i], newuser = null; if (newuserid.startsWith('user/')) { newuser = parent.users[newuserid]; } else if (newuserid.startsWith('ugrp/')) { newuser = parent.userGroups[newuserid]; } + // Search for a user name in that windows domain is the username starts with *\ + if ((newuser == null) && (newuserid.startsWith('user/' + domain.id + '/*\\')) == true) { + var search = newuserid.split('/')[2].substring(1); + for (var i in parent.users) { if (i.endsWith(search) && (parent.users[i].domain == domain.id)) { newuser = parent.users[i]; command.userids[i] = newuserid = parent.users[i]._id; break; } } + } + if (newuser != null) { // Can't add or modify self - if (newuserid == obj.user._id) { continue; } + if (newuserid == obj.user._id) { errors.push("Can't add self."); continue; } // Add mesh to user or user group if (newuser.links == null) { newuser.links = {}; } if (newuser.links[command.meshid]) { newuser.links[command.meshid].rights = command.meshadmin; } else { newuser.links[command.meshid] = { rights: command.meshadmin }; } if (newuserid.startsWith('user/')) { db.SetUser(newuser); } - else if (newuserid.startsWith('ugrp/')) { db.Set(common.escapeLinksFieldName(newuser)); } + else if (newuserid.startsWith('ugrp/')) { db.Set(newuser); } parent.parent.DispatchEvent([newuser._id], obj, 'resubscribe'); if (newuserid.startsWith('user/')) { @@ -2301,30 +2459,148 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use // Add userid to the mesh mesh.links[newuserid] = { name: newuser.name, rights: command.meshadmin }; - db.Set(common.escapeLinksFieldName(mesh)); + db.Set(mesh); // Notify mesh change - var event = { etype: 'mesh', username: newuser.name, userid: user._id, meshid: mesh._id, name: mesh.name, mtype: mesh.mtype, desc: mesh.desc, action: 'meshchange', links: mesh.links, msg: 'Added user ' + newuser.name + ' to mesh ' + mesh.name, domain: domain.id }; + var event = { etype: 'mesh', username: newuser.name, userid: user._id, meshid: mesh._id, name: mesh.name, mtype: mesh.mtype, desc: mesh.desc, action: 'meshchange', links: mesh.links, msg: 'Added user ' + newuser.name + ' to mesh ' + mesh.name, domain: domain.id, invite: mesh.invite }; if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the mesh. Another event will come. parent.parent.DispatchEvent(['*', mesh._id, user._id, newuserid], obj, event); - removedCount++; + msgs.push("Added user " + newuserid.split('/')[2]); + successCount++; } else { - unknownUsers.push(command.userids[i]); + msgs.push("Unknown user " + newuserid.split('/')[2]); + unknownUsers.push(newuserid.split('/')[2]); failCount++; } } + if ((successCount == 0) && (failCount == 0)) { msgs.push("Nothing done"); } + if (unknownUsers.length > 0) { // Send error back, user not found. displayNotificationMessage('User' + ((unknownUsers.length > 1) ? 's' : '') + ' ' + EscapeHtml(unknownUsers.join(', ')) + ' not found.', 'Device Group', 'ServerNotify'); } - if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'addmeshuser', responseid: command.responseid, result: 'ok', removed: removedCount, failed: failCount })); } catch (ex) { } } + if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'addmeshuser', responseid: command.responseid, result: msgs.join(', '), success: successCount, failed: failCount })); } catch (ex) { } } break; } + case 'adddeviceuser': { + if (typeof command.userid == 'string') { command.userids = [command.userid]; } + var err = null; + try { + if (common.validateString(command.nodeid, 1, 1024) == false) { err = 'Invalid nodeid'; } // Check the nodeid + else if (common.validateInt(command.rights) == false) { err = 'Invalid rights'; } // Device rights must be an integer + else if ((command.rights & 7) != 0) { err = 'Invalid rights'; } // EDITMESH, MANAGEUSERS or MANAGECOMPUTERS rights can't be assigned to a user to device link + else if ((common.validateStrArray(command.usernames, 1, 64) == false) && (common.validateStrArray(command.userids, 1, 128) == false)) { err = 'Invalid usernames'; } // Username is between 1 and 64 characters + else { + if (command.nodeid.indexOf('/') == -1) { command.nodeid = 'node/' + domain.id + '/' + command.nodeid; } + else if ((command.nodeid.split('/').length != 3) || (command.nodeid.split('/')[1] != domain.id)) { err = 'Invalid domain'; } // Invalid domain, operation only valid for current domain + } + } catch (ex) { err = 'Validation exception: ' + ex; } + + // Handle any errors + if (err != null) { + if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'adddeviceuser', responseid: command.responseid, result: err })); } catch (ex) { } } + break; + } + + // Convert user names to userid's + if (command.userids == null) { + command.userids = []; + for (var i in command.usernames) { command.userids.push('user/' + domain.id + '/' + command.usernames[i].toLowerCase()); } + } + + // Get the node and the rights for this node + parent.GetNodeWithRights(domain, user, command.nodeid, function (node, rights, visible) { + // Check if already in the right mesh + if ((node == null) || (node.meshid == command.meshid)) return; + var dispatchTargets = ['*', node.meshid, node._id]; + + // Check that we have rights to manage users on this device + if ((rights & MESHRIGHT_MANAGEUSERS) == 0) return; + + // Add the new link to the users + var nodeChanged = false; + for (var i in command.userids) { + var newuserid = command.userids[i]; + var newuser = parent.users[newuserid]; + + // Search for a user name in that windows domain is the username starts with *\ + if ((newuser == null) && (newuserid.startsWith('user/' + domain.id + '/*\\')) == true) { + var search = newuserid.split('/')[2].substring(1); + for (var i in parent.users) { if (i.endsWith(search) && (parent.users[i].domain == domain.id)) { newuser = parent.users[i]; command.userids[i] = newuserid = newuser._id; break; } } + } + + if (newuser != null) { + // Add this user to the dispatch target list + dispatchTargets.push(newuser._id); + + if (command.rights == 0) { + // Remove link to this user + if (newuser.links != null) { + delete newuser.links[command.nodeid]; + if (Object.keys(newuser.links).length == 0) { delete newuser.links; } + } + + // Remove link to this device + if (node.links != null) { + delete node.links[newuserid]; + nodeChanged = true; + if (Object.keys(node.links).length == 0) { delete node.links; } + } + } else { + // Add the new link to this user + if (newuser.links == null) { newuser.links = {}; } + newuser.links[command.nodeid] = { rights: command.rights }; + + // Add the new link to the device + if (node.links == null) { node.links = {}; } + node.links[newuserid] = { rights: command.rights } + nodeChanged = true; + } + + // Save the user to the database + db.SetUser(newuser); + parent.parent.DispatchEvent([newuser], obj, 'resubscribe'); + + // Notify user change + var targets = ['*', 'server-users', newuserid]; + var event = { etype: 'user', userid: user._id, username: user.name, action: 'accountchange', msg: (command.rights == 0) ? ('Removed user device rights for ' + newuser.name) : ('Changed user device rights for ' + newuser.name), domain: domain.id, account: parent.CloneSafeUser(newuser), nodeListChange: newuserid }; + if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the user. Another event will come. + parent.parent.DispatchEvent(targets, obj, event); + } + } + + // Save the device + if (nodeChanged == true) { + // Save the node to the database + db.Set(parent.cleanDevice(node)); + + // Event the node change + var event = { etype: 'node', userid: user._id, username: user.name, action: 'changenode', nodeid: node._id, domain: domain.id, msg: (command.rights == 0) ? ('Removed user device rights for ' + node.name) : ('Changed user device rights for ' + node.name), node: parent.CloneSafeNode(node) } + if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the mesh. Another event will come. + parent.parent.DispatchEvent(dispatchTargets, obj, event); + } + + if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'adddeviceuser', responseid: command.responseid, result: 'ok' })); } catch (ex) { } } + }); + + break; + } case 'removemeshuser': { var err = null; + + // Resolve the device group name if needed + if ((typeof command.meshname == 'string') && (command.meshid == null)) { + for (var i in parent.meshes) { + var m = parent.meshes[i]; + if ((m.mtype == 2) && (m.name == command.meshname) && parent.IsMeshViewable(user, m)) { + if (command.meshid == null) { command.meshid = m._id; } else { err = 'Duplicate device groups found'; } + } + } + } + try { if (common.validateString(command.userid, 1, 1024) == false) { err = "Invalid userid"; } // Check userid if (common.validateString(command.meshid, 1, 1024) == false) { err = "Invalid groupid"; } // Check meshid @@ -2350,6 +2626,13 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use var deluserid = command.userid, deluser = null; if (deluserid.startsWith('user/')) { deluser = parent.users[deluserid]; } else if (deluserid.startsWith('ugrp/')) { deluser = parent.userGroups[deluserid]; } + + // Search for a user name in that windows domain is the username starts with *\ + if ((deluser == null) && (deluserid.startsWith('user/' + domain.id + '/*\\')) == true) { + var search = deluserid.split('/')[2].substring(1); + for (var i in parent.users) { if (i.endsWith(search) && (parent.users[i].domain == domain.id)) { deluser = parent.users[i]; command.userid = deluserid = deluser._id; break; } } + } + if (deluser != null) { // Remove mesh from user if (deluser.links != null && deluser.links[command.meshid] != null) { @@ -2357,7 +2640,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use if ((delmeshrights == 0xFFFFFFFF) && (mesh.links[deluserid].rights != 0xFFFFFFFF)) return; // A non-admin can't kick out an admin delete deluser.links[command.meshid]; if (deluserid.startsWith('user/')) { db.SetUser(deluser); } - else if (deluserid.startsWith('ugrp/')) { db.Set(common.escapeLinksFieldName(deluser)); } + else if (deluserid.startsWith('ugrp/')) { db.Set(deluser); } parent.parent.DispatchEvent([deluser._id], obj, 'resubscribe'); if (deluserid.startsWith('user/')) { @@ -2379,14 +2662,14 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use // Remove user from the mesh if (mesh.links[command.userid] != null) { delete mesh.links[command.userid]; - db.Set(common.escapeLinksFieldName(mesh)); + db.Set(mesh); // Notify mesh change var event; if (deluser != null) { - event = { etype: 'mesh', username: user.name, userid: deluser.name, meshid: mesh._id, name: mesh.name, mtype: mesh.mtype, desc: mesh.desc, action: 'meshchange', links: mesh.links, msg: 'Removed user ' + deluser.name + ' from group ' + mesh.name, domain: domain.id }; + event = { etype: 'mesh', username: user.name, userid: deluser.name, meshid: mesh._id, name: mesh.name, mtype: mesh.mtype, desc: mesh.desc, action: 'meshchange', links: mesh.links, msg: 'Removed user ' + deluser.name + ' from group ' + mesh.name, domain: domain.id, invite: mesh.invite }; } else { - event = { etype: 'mesh', username: user.name, userid: (deluserid.split('/')[2]), meshid: mesh._id, name: mesh.name, mtype: mesh.mtype, desc: mesh.desc, action: 'meshchange', links: mesh.links, msg: 'Removed user ' + (deluserid.split('/')[2]) + ' from group ' + mesh.name, domain: domain.id }; + event = { etype: 'mesh', username: user.name, userid: (deluserid.split('/')[2]), meshid: mesh._id, name: mesh.name, mtype: mesh.mtype, desc: mesh.desc, action: 'meshchange', links: mesh.links, msg: 'Removed user ' + (deluserid.split('/')[2]) + ' from group ' + mesh.name, domain: domain.id, invite: mesh.invite }; } parent.parent.DispatchEvent(['*', mesh._id, user._id, command.userid], obj, event); if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'removemeshuser', responseid: command.responseid, result: 'ok' })); } catch (ex) { } } @@ -2424,10 +2707,10 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use if (command.amtpolicy.type === 2) { amtpolicy = { type: command.amtpolicy.type, password: command.amtpolicy.password, badpass: command.amtpolicy.badpass, cirasetup: command.amtpolicy.cirasetup }; } else if (command.amtpolicy.type === 3) { amtpolicy = { type: command.amtpolicy.type, password: command.amtpolicy.password, cirasetup: command.amtpolicy.cirasetup }; } mesh.amt = amtpolicy; - db.Set(common.escapeLinksFieldName(mesh)); + db.Set(mesh); var amtpolicy2 = Object.assign({}, amtpolicy); // Shallow clone delete amtpolicy2.password; - var event = { etype: 'mesh', userid: user._id, username: user.name, meshid: mesh._id, amt: amtpolicy2, action: 'meshchange', links: mesh.links, msg: change, domain: domain.id }; + var event = { etype: 'mesh', userid: user._id, username: user.name, meshid: mesh._id, amt: amtpolicy2, action: 'meshchange', links: mesh.links, msg: change, domain: domain.id, invite: mesh.invite }; if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the mesh. Another event will come. parent.parent.DispatchEvent(['*', mesh._id, user._id], obj, event); @@ -2473,7 +2756,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use db.Set(device); // Event the new node - parent.parent.DispatchEvent(['*', command.meshid], obj, { etype: 'node', userid: user._id, username: user.name, action: 'addnode', node: parent.CloneSafeNode(device), msg: 'Added device ' + command.devicename + ' to mesh ' + mesh.name, domain: domain.id }); + parent.parent.DispatchEvent(['*', command.meshid, nodeid], obj, { etype: 'node', userid: user._id, username: user.name, action: 'addnode', node: parent.CloneSafeNode(device), msg: 'Added device ' + command.devicename + ' to mesh ' + mesh.name, domain: domain.id }); }); } break; @@ -2513,7 +2796,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use // Perform the switch, start by saving the node with the new meshid. const oldMeshId = node.meshid; node.meshid = command.meshid; - db.Set(node); + db.Set(parent.cleanDevice(node)); // If the device is connected on this server, switch it now. var agentSession = parent.wsagents[node._id]; @@ -2542,7 +2825,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use var newMesh = parent.meshes[command.meshid]; var event = { etype: 'node', userid: user._id, username: user.name, action: 'nodemeshchange', nodeid: node._id, node: node, oldMeshId: oldMeshId, newMeshId: command.meshid, msg: 'Moved device ' + node.name + ' to group ' + newMesh.name, domain: domain.id }; if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the mesh. Another event will come. - parent.parent.DispatchEvent(['*', oldMeshId, command.meshid], obj, event); + parent.parent.DispatchEvent(['*', oldMeshId, command.meshid, node._id], obj, event); }); } break; @@ -2570,11 +2853,32 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use db.Remove('ra' + node._id); // Remove real agent to diagnostic agent link }); + // Remove any user node links + if (node.links != null) { + for (var i in node.links) { + if (i.startsWith('user/')) { + var cuser = parent.users[i]; + if ((cuser != null) && (cuser.links != null) && (cuser.links[node._id] != null)) { + // Remove the user link & save the user + delete cuser.links[node._id]; + if (Object.keys(cuser.links).length == 0) { delete cuser.links; } + db.SetUser(cuser); + + // Notify user change + var targets = ['*', 'server-users', cuser._id]; + var event = { etype: 'user', userid: cuser._id, username: cuser.name, action: 'accountchange', msg: 'Removed user device rights for ' + cuser.name, domain: domain.id, account: parent.CloneSafeUser(cuser) }; + if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the user. Another event will come. + parent.parent.DispatchEvent(targets, obj, event); + } + } + } + } + // Event node deletion var event = { etype: 'node', userid: user._id, username: user.name, action: 'removenode', nodeid: node._id, msg: 'Removed device ' + node.name + ' from group ' + parent.meshes[node.meshid].name, domain: domain.id }; // TODO: We can't use the changeStream for node delete because we will not know the meshid the device was in. //if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to remove the node. Another event will come. - parent.parent.DispatchEvent(['*', node.meshid], obj, event); + parent.parent.DispatchEvent(['*', node.meshid, node._id], obj, event); // Disconnect all connections if needed var state = parent.parent.GetConnectivityState(nodeid); @@ -2736,6 +3040,13 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use if (command.icon && (command.icon != node.icon)) { change = 1; node.icon = command.icon; changes.push('icon'); } if (command.name && (command.name != node.name)) { change = 1; node.name = command.name; changes.push('name'); } if (command.host && (command.host != node.host)) { change = 1; node.host = command.host; changes.push('host'); } + if ((typeof command.rdpport == 'number') && (command.rdpport > 0) && (command.rdpport < 65536)) { + if ((command.rdpport == 3389) && (node.rdpport != null)) { + delete node.rdpport; change = 1; changes.push('rdpport'); // Delete the RDP port + } else { + node.rdpport = command.rdpport; change = 1; changes.push('rdpport'); // Set the RDP port + } + } if (domain.geolocation && command.userloc && ((node.userloc == null) || (command.userloc[0] != node.userloc[0]) || (command.userloc[1] != node.userloc[1]))) { change = 1; if ((command.userloc.length == 0) && (node.userloc)) { @@ -2750,7 +3061,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use if (command.desc != null && (command.desc != node.desc)) { change = 1; node.desc = command.desc; changes.push('description'); } if (command.intelamt != null) { if ((command.intelamt.user != null) && (command.intelamt.pass != undefined) && ((command.intelamt.user != node.intelamt.user) || (command.intelamt.pass != node.intelamt.pass))) { change = 1; node.intelamt.user = command.intelamt.user; node.intelamt.pass = command.intelamt.pass; changes.push('Intel AMT credentials'); } - if (command.intelamt.tls && (command.intelamt.tls != node.intelamt.tls)) { change = 1; node.intelamt.tls = command.intelamt.tls; changes.push('Intel AMT TLS'); } + if ((command.intelamt.tls != null) && (command.intelamt.tls != node.intelamt.tls)) { change = 1; node.intelamt.tls = command.intelamt.tls; changes.push('Intel AMT TLS'); } } if (command.tags) { // Node grouping tag, this is a array of strings that can't be empty and can't contain a comma var ok = true, group2 = []; @@ -2762,13 +3073,14 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use if (change == 1) { // Save the node - db.Set(node); + db.Set(parent.cleanDevice(node)); // Event the node change. Only do this if the database will not do it. event.msg = 'Changed device ' + node.name + ' from group ' + mesh.name + ': ' + changes.join(', '); event.node = parent.CloneSafeNode(node); + if (command.rdpport == 3389) { event.node.rdpport = 3389; } if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the node. Another event will come. - parent.parent.DispatchEvent(['*', node.meshid, user._id], obj, event); + parent.parent.DispatchEvent(['*', node.meshid, user._id, node._id], obj, event); } }); break; @@ -2838,6 +3150,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use if (command.tcpaddr) { cookieContent.tcpaddr = command.tcpaddr; } // Indicates the browser want to agent to TCP connect to a remote address if (command.tcpport) { cookieContent.tcpport = command.tcpport; } // Indicates the browser want to agent to TCP connect to a remote port command.cookie = parent.parent.encodeCookie(cookieContent, parent.parent.loginCookieEncryptionKey); + command.trustedCert = parent.isTrustedCert(domain); try { ws.send(JSON.stringify(command)); } catch (ex) { } } } @@ -2847,6 +3160,17 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use case 'inviteAgent': { var err = null, mesh = null; + + // Resolve the device group name if needed + if ((typeof command.meshname == 'string') && (command.meshid == null)) { + for (var i in parent.meshes) { + var m = parent.meshes[i]; + if ((m.mtype == 2) && (m.name == command.meshname) && parent.IsMeshViewable(user, m)) { + if (command.meshid == null) { command.meshid = m._id; } else { err = 'Duplicate device groups found'; } + } + } + } + try { if ((parent.parent.mailserver == null) || (args.lanonly == true)) { err = 'Unsupported feature'; } // This operation requires the email server else if ((parent.parent.certificates.CommonName == null) || (parent.parent.certificates.CommonName.indexOf('.') == -1)) { err = 'Unsupported feature'; } // Server name must be configured @@ -2872,7 +3196,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use } // Perform email invitation - parent.parent.mailserver.sendAgentInviteMail(domain, user.name, command.email.toLowerCase(), command.meshid, command.name, command.os, command.msg, command.flags, command.expire); + parent.parent.mailserver.sendAgentInviteMail(domain, user.name, command.email.toLowerCase(), command.meshid, command.name, command.os, command.msg, command.flags, command.expire, parent.getLanguageCodes(req)); // Send a response if needed if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'inviteAgent', responseid: command.responseid, result: 'ok' })); } catch (ex) { } } @@ -2888,7 +3212,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use if (rights == 0) return; // Add an event for this device - var targets = ['*', 'server-users', user._id, node.meshid]; + var targets = ['*', 'server-users', user._id, node.meshid, node._id]; var event = { etype: 'node', userid: user._id, username: user.name, nodeid: node._id, action: 'manual', msg: decodeURIComponent(command.msg), domain: domain.id }; parent.parent.DispatchEvent(targets, obj, event); }); @@ -2942,11 +3266,33 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use } } + break; + } + case 'otpemail': + { + // Check input + if (typeof command.enabled != 'boolean') return; + + // See if we really need to change the state + if ((command.enabled === true) && (user.otpekey != null)) return; + if ((command.enabled === false) && (user.otpekey == null)) return; + + // Change the email 2FA of this user + if (command.enabled === true) { user.otpekey = {}; } else { delete user.otpekey; } + parent.db.SetUser(user); + ws.send(JSON.stringify({ action: 'otpemail', success: true, enabled: command.enabled })); // Report success + + // Notify change + var targets = ['*', 'server-users', user._id]; + if (user.groups) { for (var i in user.groups) { targets.push('server-users:' + i); } } + var event = { etype: 'user', userid: user._id, username: user.name, account: parent.CloneSafeUser(user), action: 'accountchange', msg: command.enabled ? "Enabled email two-factor authentication." :"Disabled email two-factor authentication.", domain: domain.id }; + if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the user. Another event will come. + parent.parent.DispatchEvent(targets, obj, event); break; } case 'otpauth-request': { - // Check is 2-step login is supported + // Check if 2-step login is supported const twoStepLoginSupported = ((parent.parent.config.settings.no2factorauth !== true) && (domain.auth != 'sspi') && (parent.parent.certificates.CommonName.indexOf('.') != -1) && (args.nousers !== true)); if (twoStepLoginSupported) { // Request a one time password to be setup @@ -2960,7 +3306,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use } case 'otpauth-setup': { - // Check is 2-step login is supported + // Check if 2-step login is supported const twoStepLoginSupported = ((parent.parent.config.settings.no2factorauth !== true) && (domain.auth != 'sspi') && (parent.parent.certificates.CommonName.indexOf('.') != -1) && (args.nousers !== true)); if (twoStepLoginSupported) { // Perform the one time password setup @@ -2988,7 +3334,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use } case 'otpauth-clear': { - // Check is 2-step login is supported + // Check if 2-step login is supported const twoStepLoginSupported = ((parent.parent.config.settings.no2factorauth !== true) && (domain.auth != 'sspi') && (parent.parent.certificates.CommonName.indexOf('.') != -1) && (args.nousers !== true)); if (twoStepLoginSupported) { // Clear the one time password secret @@ -3011,7 +3357,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use } case 'otpauth-getpasswords': { - // Check is 2-step login is supported + // Check if 2-step login is supported const twoStepLoginSupported = ((parent.parent.config.settings.no2factorauth !== true) && (domain.auth != 'sspi') && (parent.parent.certificates.CommonName.indexOf('.') != -1) && (args.nousers !== true)); if (twoStepLoginSupported == false) break; @@ -3050,7 +3396,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use } case 'otp-hkey-get': { - // Check is 2-step login is supported + // Check if 2-step login is supported const twoStepLoginSupported = ((parent.parent.config.settings.no2factorauth !== true) && (domain.auth != 'sspi') && (parent.parent.certificates.CommonName.indexOf('.') != -1) && (args.nousers !== true)); if (twoStepLoginSupported == false) break; @@ -3063,7 +3409,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use } case 'otp-hkey-remove': { - // Check is 2-step login is supported + // Check if 2-step login is supported const twoStepLoginSupported = ((parent.parent.config.settings.no2factorauth !== true) && (domain.auth != 'sspi') && (parent.parent.certificates.CommonName.indexOf('.') != -1) && (args.nousers !== true)); if (twoStepLoginSupported == false || command.index == null) break; @@ -3089,7 +3435,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use var yubikeyotp = null; try { yubikeyotp = require('yubikeyotp'); } catch (ex) { } - // Check is 2-step login is supported + // Check if 2-step login is supported const twoStepLoginSupported = ((parent.parent.config.settings.no2factorauth !== true) && (domain.auth != 'sspi') && (parent.parent.certificates.CommonName.indexOf('.') != -1) && (args.nousers !== true)); if ((yubikeyotp == null) || (twoStepLoginSupported == false) || (typeof command.otp != 'string')) { ws.send(JSON.stringify({ action: 'otp-hkey-yubikey-add', result: false, name: command.name })); @@ -3138,7 +3484,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use } case 'webauthn-startregister': { - // Check is 2-step login is supported + // Check if 2-step login is supported const twoStepLoginSupported = ((parent.parent.config.settings.no2factorauth !== true) && (domain.auth != 'sspi') && (parent.parent.certificates.CommonName.indexOf('.') != -1) && (args.nousers !== true)); if ((twoStepLoginSupported == false) || (command.name == null)) break; @@ -3272,12 +3618,28 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use } case 'createInviteLink': { var err = null; + + // Resolve the device group name if needed + if ((typeof command.meshname == 'string') && (command.meshid == null)) { + for (var i in parent.meshes) { + var m = parent.meshes[i]; + if ((m.mtype == 2) && (m.name == command.meshname) && parent.IsMeshViewable(user, m)) { + if (command.meshid == null) { command.meshid = m._id; } else { err = 'Duplicate device groups found'; } + } + } + } + if (common.validateString(command.meshid, 8, 128) == false) { err = 'Invalid group id'; } // Check the meshid else if (common.validateInt(command.expire, 0, 99999) == false) { err = 'Invalid expire time'; } // Check the expire time in hours - else if (common.validateInt(command.flags, 0, 256) == false) { err = 'Invalid flags'; }; // Check the flags - if (command.meshid.split('/').length == 1) { command.meshid = 'mesh/' + domain.id + '/' + command.meshid; } - var smesh = command.meshid.split('/'); - if ((smesh.length != 3) || (smesh[0] != 'mesh') || (smesh[1] != domain.id)) { err = 'Invalid group id'; } + else if (common.validateInt(command.flags, 0, 256) == false) { err = 'Invalid flags'; } // Check the flags + else if (common.validateString(command.meshid, 1, 1024) == false) { err = 'Invalid group identifier'; } // Check meshid + else { + if (command.meshid.split('/').length == 1) { command.meshid = 'mesh/' + domain.id + '/' + command.meshid; } + var smesh = command.meshid.split('/'); + if ((smesh.length != 3) || (smesh[0] != 'mesh') || (smesh[1] != domain.id)) { err = 'Invalid group id'; } + mesh = parent.meshes[command.meshid]; + if ((mesh == null) || (parent.IsMeshViewable(user, mesh) == false)) { err = 'Invalid group id'; } + } var serverName = parent.getWebServerName(domain); // Handle any errors @@ -3286,8 +3648,6 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use break; } - mesh = parent.meshes[command.meshid]; - if (mesh == null) { if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'createInviteLink', responseid: command.responseid, result: 'Unable to find this device group id' })); } catch (ex) { } } break; } const inviteCookie = parent.parent.encodeCookie({ a: 4, mid: command.meshid, f: command.flags, expire: command.expire * 60 }, parent.parent.invitationLinkEncryptionKey); if (inviteCookie == null) { if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'createInviteLink', responseid: command.responseid, result: 'Unable to generate invitation cookie' })); } catch (ex) { } } break; } diff --git a/mpsserver.js b/mpsserver.js index eb1bd4a0..22098c19 100644 --- a/mpsserver.js +++ b/mpsserver.js @@ -40,7 +40,11 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) { obj.server.on('resumeSession', function (id, cb) { cb(null, tlsSessionStore[id.toString('hex')] || null); }); } - obj.server.listen(args.mpsport, function () { console.log("MeshCentral Intel(R) AMT server running on " + certificates.AmtMpsName + ":" + args.mpsport + ((args.mpsaliasport != null) ? (", alias port " + args.mpsaliasport) : "") + "."); }).on("error", function (err) { console.error("ERROR: MeshCentral Intel(R) AMT server port " + args.mpsport + " is not available."); if (args.exactports) { process.exit(); } }); + obj.server.listen(args.mpsport, function () { + console.log("MeshCentral Intel(R) AMT server running on " + certificates.AmtMpsName + ":" + args.mpsport + ((args.mpsaliasport != null) ? (", alias port " + args.mpsaliasport) : "") + "."); + obj.parent.authLog('mps', 'Server listening on 0.0.0.0 port ' + args.mpsport + '.'); + }).on("error", function (err) { console.error("ERROR: MeshCentral Intel(R) AMT server port " + args.mpsport + " is not available."); if (args.exactports) { process.exit(); } }); + obj.server.on('tlsClientError', function (err, tlssocket) { if (args.mpsdebug) { var remoteAddress = tlssocket.remoteAddress; if (tlssocket.remoteFamily == 'IPv6') { remoteAddress = '[' + remoteAddress + ']'; } console.log('MPS:Invalid TLS connection from ' + remoteAddress + ':' + tlssocket.remotePort + '.'); } }); obj.parent.updateServerState('mps-port', args.mpsport); obj.parent.updateServerState('mps-name', certificates.AmtMpsName); diff --git a/mqttbroker.js b/mqttbroker.js index 4008e236..baebf21b 100644 --- a/mqttbroker.js +++ b/mqttbroker.js @@ -124,7 +124,7 @@ module.exports.CreateMQTTBroker = function (parent, db, args) { // Look for any MQTT connections to send this to var clients = obj.connections[nodeid]; if (clients == null) return; - if (typeof message == 'string') { message = new Buffer(message); } + if (typeof message == 'string') { message = Buffer.from(message); } for (var i in clients) { // Only publish to client that subscribe to the topic if (clients[i].subscriptions[topic] != null) { clients[i].publish({ cmd: 'publish', qos: 0, topic: topic, payload: message, retain: false }); } diff --git a/package.json b/package.json index ce3aeae7..9e024683 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "meshcentral", - "version": "0.4.8-u", + "version": "0.5.1-k", "keywords": [ "Remote Management", "Intel AMT", @@ -9,7 +9,7 @@ ], "homepage": "http://meshcommander.com", "description": "Web based remote computer management and file server", - "author": "Ylian Saint-Hilaire ", + "author": "Ylian Saint-Hilaire ", "main": "meshcentral.js", "bin": { "meshcentral": "./bin/meshcentral" @@ -20,6 +20,7 @@ "amt", "bin", "views", + "emails", "agents", "public", "translate", diff --git a/pluginHandler.js b/pluginHandler.js index a6779f7a..3d79c421 100644 --- a/pluginHandler.js +++ b/pluginHandler.js @@ -274,6 +274,19 @@ module.exports.pluginHandler = function (parent) { }) }; + // MeshCentral doesn't adhere to semantic versioning (due to the - at the end of the version) + // Convert 1.2.3-a to 1.2.3-3 where the letter is converted to a number. + obj.versionToNumber = function(ver) { var x = ver.split('-'); if (x.length != 2) return ver; x[1] = x[1].toLowerCase().charCodeAt(0) - 96; return x.join('.'); } + + // Check if the current version of MeshCentral is at least the minimal required. + obj.versionCompare = function(current, minimal) { + if (minimal.startsWith('>=')) { minimal = minimal.substring(2); } + var c = obj.versionToNumber(current).split('.'), m = obj.versionToNumber(minimal).split('.'); + if (c.length != m.length) return false; + for (var i = 0; i < c.length; i++) { var cx = parseInt(c[i]), cm = parseInt(m[i]); if (cx > cm) { return true; } if (cx < cm) { return false; } } + return true; + } + obj.getPluginLatest = function () { return new Promise(function (resolve, reject) { parent.db.getPlugins(function (err, plugins) { @@ -294,16 +307,12 @@ module.exports.pluginHandler = function (parent) { }); if (curconf == null) reject("Some plugin configs could not be parsed"); var s = require('semver'); - // MeshCentral doesn't adhere to semantic versioning (due to the - at the end of the version) - // Convert the letter to ASCII for a "true" version number comparison - var mcCurVer = parent.currentVer.replace(/-(.)$/, (m, p1) => { return ("000" + p1.charCodeAt(0)).substr(-3,3); }); - var piCompatVer = newconf.meshCentralCompat.replace(/-(.)\b/g, (m, p1) => { return ("000" + p1.charCodeAt(0)).substr(-3,3); }); latestRet.push({ 'id': curconf._id, 'installedVersion': curconf.version, 'version': newconf.version, 'hasUpdate': s.gt(newconf.version, curconf.version), - 'meshCentralCompat': s.satisfies(mcCurVer, piCompatVer), + 'meshCentralCompat': obj.versionCompare(parent.currentVer, newconf.meshCentralCompat), 'changelogUrl': curconf.changelogUrl, 'status': curconf.status }); @@ -377,7 +386,7 @@ module.exports.pluginHandler = function (parent) { response.pipe(file); file.on('finish', function () { file.close(function () { - var yauzl = require("yauzl"); + var yauzl = require('yauzl'); if (!obj.fs.existsSync(obj.pluginPath)) { obj.fs.mkdirSync(obj.pluginPath); } diff --git a/plugin_development.md b/plugin_development.md index 17e6a890..e45c1769 100644 --- a/plugin_development.md +++ b/plugin_development.md @@ -49,7 +49,7 @@ A valid JSON object within a file named `config.json` in the root folder of your | repository.type | Yes | string | valid values are `git` and in the future, `npm` will also be supported in the future | repository.url | Yes | string | the URL to the project's repository | versionHistoryUrl | No | string | the URL to the project's versions/tags -| meshCentralCompat | Yes | string | the semantic version string of required compatibility with the MeshCentral server +| meshCentralCompat | Yes | string | the minimum version string of required compatibility with the MeshCentral server, can be formatted as "0.1.2-c" or ">=0.1.2-c". Currently only supports minimum version, not full semantic checking. ## Plugin Hooks These are separated into the following categories depending on the type of functionality the plugin should offer. diff --git a/public/images/details/amt64.png b/public/images/details/amt64.png new file mode 100644 index 00000000..9637bf0d Binary files /dev/null and b/public/images/details/amt64.png differ diff --git a/public/images/details/chip64.png b/public/images/details/chip64.png new file mode 100644 index 00000000..5579e29e Binary files /dev/null and b/public/images/details/chip64.png differ diff --git a/public/images/details/meshagent64.png b/public/images/details/meshagent64.png new file mode 100644 index 00000000..d4da9d2b Binary files /dev/null and b/public/images/details/meshagent64.png differ diff --git a/public/images/details/motherboard64.png b/public/images/details/motherboard64.png new file mode 100644 index 00000000..0aede2d9 Binary files /dev/null and b/public/images/details/motherboard64.png differ diff --git a/public/images/details/networking64.png b/public/images/details/networking64.png new file mode 100644 index 00000000..10861d22 Binary files /dev/null and b/public/images/details/networking64.png differ diff --git a/public/images/details/ram64.png b/public/images/details/ram64.png new file mode 100644 index 00000000..6d584386 Binary files /dev/null and b/public/images/details/ram64.png differ diff --git a/public/images/details/software64.png b/public/images/details/software64.png new file mode 100644 index 00000000..fceb8d07 Binary files /dev/null and b/public/images/details/software64.png differ diff --git a/public/scripts/agent-desktop-0.0.2.js b/public/scripts/agent-desktop-0.0.2.js index 07857d6b..2d58dd3d 100644 --- a/public/scripts/agent-desktop-0.0.2.js +++ b/public/scripts/agent-desktop-0.0.2.js @@ -55,8 +55,7 @@ var CreateAgentRemoteDesktop = function (canvasid, scrolldiv) { obj.onDisplayinfo = null; obj.accumulator = null; - var mouseCursors = ['default', 'progress', 'crosshair', 'pointer', 'help', 'text', 'no-drop', 'move', 'nesw-resize', 'ns-resize', 'nwse-resize', 'w-resize', 'alias', 'wait', 'none']; - + var mouseCursors = ['default', 'progress', 'crosshair', 'pointer', 'help', 'text', 'no-drop', 'move', 'nesw-resize', 'ns-resize', 'nwse-resize', 'w-resize', 'alias', 'wait', 'none', 'not-allowed', 'col-resize', 'row-resize', 'copy', 'zoom-in', 'zoom-out']; obj.Start = function () { obj.State = 0; obj.accumulator = null; @@ -516,7 +515,7 @@ var CreateAgentRemoteDesktop = function (canvasid, scrolldiv) { } obj.GetDisplayNumbers = function () { obj.send(String.fromCharCode(0x00, 0x0B, 0x00, 0x04)); } // Get Terminal display - obj.SetDisplay = function (number) { console.log('Set display', number); obj.send(String.fromCharCode(0x00, 0x0C, 0x00, 0x06, number >> 8, number & 0xFF)); } // Set Terminal display + obj.SetDisplay = function (number) { /*console.log('Set display', number);*/ obj.send(String.fromCharCode(0x00, 0x0C, 0x00, 0x06, number >> 8, number & 0xFF)); } // Set Terminal display obj.intToStr = function (x) { return String.fromCharCode((x >> 24) & 0xFF, (x >> 16) & 0xFF, (x >> 8) & 0xFF, x & 0xFF); } obj.shortToStr = function (x) { return String.fromCharCode((x >> 8) & 0xFF, x & 0xFF); } diff --git a/public/scripts/amt-0.2.0.js b/public/scripts/amt-0.2.0.js index 9fefec20..4cce0d0f 100644 --- a/public/scripts/amt-0.2.0.js +++ b/public/scripts/amt-0.2.0.js @@ -760,7 +760,7 @@ function AmtStackCreateService(wsmanStack) { // ###BEGIN###{Certificates} // Forge MD5 -function hex_md5(str) { return forge.md.md5.create().update(str).digest().toHex(); } +function hex_md5(str) { if (str == null) { str = ''; } return forge.md.md5.create().update(str).digest().toHex(); } // ###END###{Certificates} @@ -774,6 +774,7 @@ for (var i = 0; i < 64;) { md5_k[i] = 0 | (Math.abs(Math.sin(++i)) * 4294967296) // Perform MD5 on raw string and return hex function hex_md5(str) { + if (str == null) { str = ''; } var b, c, d, j, x = [], str2 = unescape(encodeURI(str)), diff --git a/public/scripts/amt-terminal-0.0.2.js b/public/scripts/amt-terminal-0.0.2.js index e888ce8a..1c157468 100644 --- a/public/scripts/amt-terminal-0.0.2.js +++ b/public/scripts/amt-terminal-0.0.2.js @@ -644,8 +644,8 @@ var CreateAmtRemoteTerminal = function (divid, options) { } } - obj.TermSendKeys = function (keys) { if (obj.debugmode == 2) { console.log("TSend(" + keys.length + "): " + rstr2hex(keys), keys); } obj.parent.sendText(keys); } - obj.TermSendKey = function (key) { if (obj.debugmode == 2) { console.log("TSend(1): " + rstr2hex(String.fromCharCode(key)), key); } obj.parent.sendText(String.fromCharCode(key)); } + obj.TermSendKeys = function (keys) { if (obj.debugmode == 2) { console.log("TSend(" + keys.length + "): " + rstr2hex(keys), keys); } obj.parent.send(keys); } + obj.TermSendKey = function (key) { if (obj.debugmode == 2) { console.log("TSend(1): " + rstr2hex(String.fromCharCode(key)), key); } obj.parent.send(String.fromCharCode(key)); } function _TermMoveUp(linecount) { var x, y; diff --git a/public/scripts/amt-wsman-ws-0.2.0.js b/public/scripts/amt-wsman-ws-0.2.0.js index 05c15369..b74a0a08 100644 --- a/public/scripts/amt-wsman-ws-0.2.0.js +++ b/public/scripts/amt-wsman-ws-0.2.0.js @@ -80,12 +80,12 @@ var CreateWsmanComm = function (host, port, user, pass, tls) { // Websocket relay specific private method (Content Length Encoding) obj.sendRequest = function (postdata, url, action) { - url = url ? url : "/wsman"; - action = action ? action : "POST"; - var h = action + " " + url + " HTTP/1.1\r\n"; + url = url ? url : '/wsman'; + action = action ? action : 'POST'; + var h = action + ' ' + url + ' HTTP/1.1\r\n'; if (obj.challengeParams != null) { - var response = hex_md5(hex_md5(obj.user + ':' + obj.challengeParams["realm"] + ':' + obj.pass) + ':' + obj.challengeParams["nonce"] + ':' + obj.noncecounter + ':' + obj.cnonce + ':' + obj.challengeParams["qop"] + ':' + hex_md5(action + ':' + url)); - h += 'Authorization: ' + obj.renderDigest({ "username": obj.user, "realm": obj.challengeParams["realm"], "nonce": obj.challengeParams["nonce"], "uri": url, "qop": obj.challengeParams["qop"], "response": response, "nc": obj.noncecounter++, "cnonce": obj.cnonce }) + '\r\n'; + var response = hex_md5(hex_md5(obj.user + ':' + obj.challengeParams['realm'] + ':' + obj.pass) + ':' + obj.challengeParams['nonce'] + ':' + obj.noncecounter + ':' + obj.cnonce + ':' + obj.challengeParams['qop'] + ':' + hex_md5(action + ':' + url + ((obj.challengeParams['qop'] == 'auth-int') ? (':' + hex_md5(postdata)) : ''))); + h += 'Authorization: ' + obj.renderDigest({ 'username': obj.user, 'realm': obj.challengeParams['realm'], 'nonce': obj.challengeParams['nonce'], 'uri': url, 'qop': obj.challengeParams['qop'], 'response': response, 'nc': obj.noncecounter++, 'cnonce': obj.cnonce }) + '\r\n'; } //h += 'Host: ' + obj.host + ':' + obj.port + '\r\nContent-Length: ' + postdata.length + '\r\n\r\n' + postdata; // Use Content-Length h += 'Host: ' + obj.host + ':' + obj.port + '\r\nTransfer-Encoding: chunked\r\n\r\n' + postdata.length.toString(16).toUpperCase() + '\r\n' + postdata + '\r\n0\r\n\r\n'; // Use Chunked-Encoding @@ -93,12 +93,11 @@ var CreateWsmanComm = function (host, port, user, pass, tls) { //obj.Debug("SEND: " + h); // Display send packet } - // Websocket relay specific private method - obj.parseDigest = function (header) { - var t = header.substring(7).split(','); - for (i in t) t[i] = t[i].trim(); - return t.reduce(function (obj, s) { var parts = s.split('='); obj[parts[0]] = parts[1].replace(/"/g, ''); return obj; }, {}) - } + // Parse the HTTP digest header and return a list of key & values. + obj.parseDigest = function (header) { return correctedQuoteSplit(header.substring(7)).reduce(function (obj, s) { var parts = s.trim().split('='); obj[parts[0]] = parts[1].replace(new RegExp('\"', 'g'), ''); return obj; }, {}) } + + // Split a string on quotes but do not do it when in quotes + function correctedQuoteSplit(str) { return str.split(',').reduce(function (a, c) { if (a.ic) { a.st[a.st.length - 1] += ',' + c } else { a.st.push(c) } if (c.split('"').length % 2 == 0) { a.ic = !a.ic } return a; }, { st: [], ic: false }).st } // Websocket relay specific private method obj.renderDigest = function (params) { @@ -117,7 +116,7 @@ var CreateWsmanComm = function (host, port, user, pass, tls) { obj.socketState = 1; console.log(obj.tlsv1only); - obj.socket = new WebSocket(window.location.protocol.replace("http", "ws") + "//" + window.location.host + window.location.pathname.substring(0, window.location.pathname.lastIndexOf('/')) + "/webrelay.ashx?p=1&host=" + obj.host + "&port=" + obj.port + "&tls=" + obj.tls + "&tlsv1only=" + obj.tlsv1only + ((user == '*') ? "&serverauth=1" : "") + ((typeof pass === "undefined") ? ("&serverauth=1&user=" + user) : "")); // The "p=1" indicates to the relay that this is a WSMAN session + obj.socket = new WebSocket(window.location.protocol.replace('http', 'ws') + '//' + window.location.host + window.location.pathname.substring(0, window.location.pathname.lastIndexOf('/')) + '/webrelay.ashx?p=1&host=' + obj.host + '&port=' + obj.port + '&tls=' + obj.tls + '&tlsv1only=' + obj.tlsv1only + ((user == '*') ? '&serverauth=1' : '') + ((typeof pass === 'undefined') ? ('&serverauth=1&user=' + user) : '')); // The "p=1" indicates to the relay that this is a WSMAN session obj.socket.onopen = _OnSocketConnected; obj.socket.onmessage = _OnMessage; obj.socket.onclose = _OnSocketClosed; @@ -154,7 +153,7 @@ var CreateWsmanComm = function (host, port, user, pass, tls) { fileReader.readAsArrayBuffer(e.data); } else { // IE10, readAsBinaryString does not exist, use an alternative. - var binary = "", bytes = new Uint8Array(e.data), length = bytes.byteLength; + var binary = '', bytes = new Uint8Array(e.data), length = bytes.byteLength; for (var i = 0; i < length; i++) { binary += String.fromCharCode(bytes[i]); } _OnSocketData(binary); } @@ -169,7 +168,7 @@ var CreateWsmanComm = function (host, port, user, pass, tls) { if (typeof data === 'object') { // This is an ArrayBuffer, convert it to a string array (used in IE) - var binary = "", bytes = new Uint8Array(data), length = bytes.byteLength; + var binary = '', bytes = new Uint8Array(data), length = bytes.byteLength; for (var i = 0; i < length; i++) { binary += String.fromCharCode(bytes[i]); } data = binary; } @@ -180,10 +179,10 @@ var CreateWsmanComm = function (host, port, user, pass, tls) { obj.socketAccumulator += data; while (true) { if (obj.socketParseState == 0) { - var headersize = obj.socketAccumulator.indexOf("\r\n\r\n"); + var headersize = obj.socketAccumulator.indexOf('\r\n\r\n'); if (headersize < 0) return; //obj.Debug(obj.socketAccumulator.substring(0, headersize)); // Display received HTTP header - obj.socketHeader = obj.socketAccumulator.substring(0, headersize).split("\r\n"); + obj.socketHeader = obj.socketAccumulator.substring(0, headersize).split('\r\n'); obj.socketAccumulator = obj.socketAccumulator.substring(headersize + 4); obj.socketParseState = 1; obj.socketData = ''; @@ -197,12 +196,12 @@ var CreateWsmanComm = function (host, port, user, pass, tls) { } if (obj.socketParseState == 1) { var csize = -1; - if ((obj.socketXHeader["connection"] != undefined) && (obj.socketXHeader["connection"].toLowerCase() == 'close') && ((obj.socketXHeader["transfer-encoding"] == undefined) || (obj.socketXHeader["transfer-encoding"].toLowerCase() != 'chunked'))) { + if ((obj.socketXHeader['connection'] != undefined) && (obj.socketXHeader['connection'].toLowerCase() == 'close') && ((obj.socketXHeader["transfer-encoding"] == undefined) || (obj.socketXHeader["transfer-encoding"].toLowerCase() != 'chunked'))) { // The body ends with a close, in this case, we will only process the header csize = 0; - } else if (obj.socketXHeader["content-length"] != undefined) { + } else if (obj.socketXHeader['content-length'] != undefined) { // The body length is specified by the content-length - csize = parseInt(obj.socketXHeader["content-length"]); + csize = parseInt(obj.socketXHeader['content-length']); if (obj.socketAccumulator.length < csize) return; var data = obj.socketAccumulator.substring(0, csize); obj.socketAccumulator = obj.socketAccumulator.substring(csize); @@ -239,6 +238,11 @@ var CreateWsmanComm = function (host, port, user, pass, tls) { if (isNaN(s)) s = 602; if (s == 401 && ++(obj.authcounter) < 3) { obj.challengeParams = obj.parseDigest(header['www-authenticate']); // Set the digest parameters, after this, the socket will close and we will auto-retry + if (obj.challengeParams['qop'] != null) { + var qopList = obj.challengeParams['qop'].split(','); + for (var i in qopList) { qopList[i] = qopList[i].trim(); } + if (qopList.indexOf('auth-int') >= 0) { obj.challengeParams['qop'] = 'auth-int'; } else { obj.challengeParams['qop'] = 'auth'; } + } } else { var r = obj.pendingAjaxCall.shift(); // if (s != 200) { obj.Debug("Error, status=" + s + "\r\n\r\nreq=" + r[0] + "\r\n\r\nresp=" + data); } // Debug: Display the request & response if something did not work. diff --git a/public/scripts/xterm-addon-fit.js.map b/public/scripts/xterm-addon-fit.js.map new file mode 100644 index 00000000..b080faac --- /dev/null +++ b/public/scripts/xterm-addon-fit.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack://FitAddon/webpack/universalModuleDefinition","webpack://FitAddon/webpack/bootstrap","webpack://FitAddon/./src/FitAddon.ts"],"names":["root","factory","exports","module","define","amd","window","installedModules","__webpack_require__","moduleId","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","activate","terminal","this","_terminal","dispose","fit","dims","proposeDimensions","core","_core","rows","cols","_renderService","clear","resize","element","parentElement","parentElementStyle","getComputedStyle","parentElementHeight","parseInt","getPropertyValue","parentElementWidth","Math","max","elementStyle","availableHeight","availableWidth","viewport","scrollBarWidth","floor","dimensions","actualCellWidth","actualCellHeight","FitAddon"],"mappings":"CAAA,SAA2CA,EAAMC,GAC1B,iBAAZC,SAA0C,iBAAXC,OACxCA,OAAOD,QAAUD,IACQ,mBAAXG,QAAyBA,OAAOC,IAC9CD,OAAO,GAAIH,GACe,iBAAZC,QACdA,QAAkB,SAAID,IAEtBD,EAAe,SAAIC,IARrB,CASGK,OAAQ,WACX,O,YCTE,IAAIC,EAAmB,GAGvB,SAASC,EAAoBC,GAG5B,GAAGF,EAAiBE,GACnB,OAAOF,EAAiBE,GAAUP,QAGnC,IAAIC,EAASI,EAAiBE,GAAY,CACzCC,EAAGD,EACHE,GAAG,EACHT,QAAS,IAUV,OANAU,EAAQH,GAAUI,KAAKV,EAAOD,QAASC,EAAQA,EAAOD,QAASM,GAG/DL,EAAOQ,GAAI,EAGJR,EAAOD,QA0Df,OArDAM,EAAoBM,EAAIF,EAGxBJ,EAAoBO,EAAIR,EAGxBC,EAAoBQ,EAAI,SAASd,EAASe,EAAMC,GAC3CV,EAAoBW,EAAEjB,EAASe,IAClCG,OAAOC,eAAenB,EAASe,EAAM,CAAEK,YAAY,EAAMC,IAAKL,KAKhEV,EAAoBgB,EAAI,SAAStB,GACX,oBAAXuB,QAA0BA,OAAOC,aAC1CN,OAAOC,eAAenB,EAASuB,OAAOC,YAAa,CAAEC,MAAO,WAE7DP,OAAOC,eAAenB,EAAS,aAAc,CAAEyB,OAAO,KAQvDnB,EAAoBoB,EAAI,SAASD,EAAOE,GAEvC,GADU,EAAPA,IAAUF,EAAQnB,EAAoBmB,IAC/B,EAAPE,EAAU,OAAOF,EACpB,GAAW,EAAPE,GAA8B,iBAAVF,GAAsBA,GAASA,EAAMG,WAAY,OAAOH,EAChF,IAAII,EAAKX,OAAOY,OAAO,MAGvB,GAFAxB,EAAoBgB,EAAEO,GACtBX,OAAOC,eAAeU,EAAI,UAAW,CAAET,YAAY,EAAMK,MAAOA,IACtD,EAAPE,GAA4B,iBAATF,EAAmB,IAAI,IAAIM,KAAON,EAAOnB,EAAoBQ,EAAEe,EAAIE,EAAK,SAASA,GAAO,OAAON,EAAMM,IAAQC,KAAK,KAAMD,IAC9I,OAAOF,GAIRvB,EAAoB2B,EAAI,SAAShC,GAChC,IAAIe,EAASf,GAAUA,EAAO2B,WAC7B,WAAwB,OAAO3B,EAAgB,SAC/C,WAA8B,OAAOA,GAEtC,OADAK,EAAoBQ,EAAEE,EAAQ,IAAKA,GAC5BA,GAIRV,EAAoBW,EAAI,SAASiB,EAAQC,GAAY,OAAOjB,OAAOkB,UAAUC,eAAe1B,KAAKuB,EAAQC,IAGzG7B,EAAoBgC,EAAI,GAIjBhC,EAAoBA,EAAoBiC,EAAI,G,gFC/DrD,IAGA,aAGE,cAwDF,OAtDS,YAAAC,SAAP,SAAgBC,GACdC,KAAKC,UAAYF,GAGZ,YAAAG,QAAP,aAEO,YAAAC,IAAP,WACE,IAAMC,EAAOJ,KAAKK,oBAClB,GAAKD,GAASJ,KAAKC,UAAnB,CAKA,IAAMK,EAAaN,KAAKC,UAAWM,MAG/BP,KAAKC,UAAUO,OAASJ,EAAKI,MAAQR,KAAKC,UAAUQ,OAASL,EAAKK,OACpEH,EAAKI,eAAeC,QACpBX,KAAKC,UAAUW,OAAOR,EAAKK,KAAML,EAAKI,SAInC,YAAAH,kBAAP,WACE,GAAKL,KAAKC,WAILD,KAAKC,UAAUY,SAAYb,KAAKC,UAAUY,QAAQC,cAAvD,CAKA,IAAMR,EAAaN,KAAKC,UAAWM,MAE7BQ,EAAqBrD,OAAOsD,iBAAiBhB,KAAKC,UAAUY,QAAQC,eACpEG,EAAsBC,SAASH,EAAmBI,iBAAiB,WACnEC,EAAqBC,KAAKC,IAAI,EAAGJ,SAASH,EAAmBI,iBAAiB,WAC9EI,EAAe7D,OAAOsD,iBAAiBhB,KAAKC,UAAUY,SAStDW,EAAkBP,GAPjBC,SAASK,EAAaJ,iBAAiB,gBACpCD,SAASK,EAAaJ,iBAAiB,oBAO3CM,EAAiBL,GANdF,SAASK,EAAaJ,iBAAiB,kBACxCD,SAASK,EAAaJ,iBAAiB,kBAKiBb,EAAKoB,SAASC,eAK9E,MAJiB,CACflB,KAAMY,KAAKC,IAzDI,EAyDcD,KAAKO,MAAMH,EAAiBnB,EAAKI,eAAemB,WAAWC,kBACxFtB,KAAMa,KAAKC,IAzDI,EAyDcD,KAAKO,MAAMJ,EAAkBlB,EAAKI,eAAemB,WAAWE,sBAI/F,EA3DA,GAAa,EAAAC","file":"xterm-addon-fit.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"FitAddon\"] = factory();\n\telse\n\t\troot[\"FitAddon\"] = factory();\n})(window, function() {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 0);\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { Terminal, ITerminalAddon } from 'xterm';\n\ninterface ITerminalDimensions {\n /**\n * The number of rows in the terminal.\n */\n rows: number;\n\n /**\n * The number of columns in the terminal.\n */\n cols: number;\n}\n\nconst MINIMUM_COLS = 2;\nconst MINIMUM_ROWS = 1;\n\nexport class FitAddon implements ITerminalAddon {\n private _terminal: Terminal | undefined;\n\n constructor() {}\n\n public activate(terminal: Terminal): void {\n this._terminal = terminal;\n }\n\n public dispose(): void {}\n\n public fit(): void {\n const dims = this.proposeDimensions();\n if (!dims || !this._terminal) {\n return;\n }\n\n // TODO: Remove reliance on private API\n const core = (this._terminal)._core;\n\n // Force a full render\n if (this._terminal.rows !== dims.rows || this._terminal.cols !== dims.cols) {\n core._renderService.clear();\n this._terminal.resize(dims.cols, dims.rows);\n }\n }\n\n public proposeDimensions(): ITerminalDimensions | undefined {\n if (!this._terminal) {\n return undefined;\n }\n\n if (!this._terminal.element || !this._terminal.element.parentElement) {\n return undefined;\n }\n\n // TODO: Remove reliance on private API\n const core = (this._terminal)._core;\n\n const parentElementStyle = window.getComputedStyle(this._terminal.element.parentElement);\n const parentElementHeight = parseInt(parentElementStyle.getPropertyValue('height'));\n const parentElementWidth = Math.max(0, parseInt(parentElementStyle.getPropertyValue('width')));\n const elementStyle = window.getComputedStyle(this._terminal.element);\n const elementPadding = {\n top: parseInt(elementStyle.getPropertyValue('padding-top')),\n bottom: parseInt(elementStyle.getPropertyValue('padding-bottom')),\n right: parseInt(elementStyle.getPropertyValue('padding-right')),\n left: parseInt(elementStyle.getPropertyValue('padding-left'))\n };\n const elementPaddingVer = elementPadding.top + elementPadding.bottom;\n const elementPaddingHor = elementPadding.right + elementPadding.left;\n const availableHeight = parentElementHeight - elementPaddingVer;\n const availableWidth = parentElementWidth - elementPaddingHor - core.viewport.scrollBarWidth;\n const geometry = {\n cols: Math.max(MINIMUM_COLS, Math.floor(availableWidth / core._renderService.dimensions.actualCellWidth)),\n rows: Math.max(MINIMUM_ROWS, Math.floor(availableHeight / core._renderService.dimensions.actualCellHeight))\n };\n return geometry;\n }\n}\n"],"sourceRoot":""} \ No newline at end of file diff --git a/public/scripts/xterm.js b/public/scripts/xterm.js index aebe9e9f..cccd5fd9 100644 --- a/public/scripts/xterm.js +++ b/public/scripts/xterm.js @@ -1,2 +1,2 @@ -!function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var r=t();for(var i in r)("object"==typeof exports?exports:e)[i]=r[i]}}(window,function(){return function(e){var t={};function r(i){if(t[i])return t[i].exports;var n=t[i]={i:i,l:!1,exports:{}};return e[i].call(n.exports,n,n.exports,r),n.l=!0,n.exports}return r.m=e,r.c=t,r.d=function(e,t,i){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(r.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var n in e)r.d(i,n,function(t){return e[t]}.bind(null,n));return i},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=33)}([function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=r(14);t.IBufferService=i.createDecorator("BufferService"),t.ICoreMouseService=i.createDecorator("CoreMouseService"),t.ICoreService=i.createDecorator("CoreService"),t.IDirtyRowService=i.createDecorator("DirtyRowService"),t.IInstantiationService=i.createDecorator("InstantiationService"),t.ILogService=i.createDecorator("LogService"),t.IOptionsService=i.createDecorator("OptionsService")},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=function(){function e(){this._listeners=[],this._disposed=!1}return Object.defineProperty(e.prototype,"event",{get:function(){var e=this;return this._event||(this._event=function(t){return e._listeners.push(t),{dispose:function(){if(!e._disposed)for(var r=0;r>22},t.prototype.getChars=function(){return 2097152&this.content?this.combinedData:2097151&this.content?o.stringFromCodePoint(2097151&this.content):""},t.prototype.getCode=function(){return this.isCombined()?this.combinedData.charCodeAt(this.combinedData.length-1):2097151&this.content},t.prototype.setFromCharData=function(e){this.fg=e[s.CHAR_DATA_ATTR_INDEX],this.bg=0;var t=!1;if(e[s.CHAR_DATA_CHAR_INDEX].length>2)t=!0;else if(2===e[s.CHAR_DATA_CHAR_INDEX].length){var r=e[s.CHAR_DATA_CHAR_INDEX].charCodeAt(0);if(55296<=r&&r<=56319){var i=e[s.CHAR_DATA_CHAR_INDEX].charCodeAt(1);56320<=i&&i<=57343?this.content=1024*(r-55296)+i-56320+65536|e[s.CHAR_DATA_WIDTH_INDEX]<<22:t=!0}else t=!0}else this.content=e[s.CHAR_DATA_CHAR_INDEX].charCodeAt(0)|e[s.CHAR_DATA_WIDTH_INDEX]<<22;t&&(this.combinedData=e[s.CHAR_DATA_CHAR_INDEX],this.content=2097152|e[s.CHAR_DATA_WIDTH_INDEX]<<22)},t.prototype.getAsCharData=function(){return[this.fg,this.getChars(),this.getWidth(),this.getCode()]},t}(r(6).AttributeData);t.CellData=a},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=function(){function e(){this.fg=0,this.bg=0}return e.toColorRGB=function(e){return[e>>>16&255,e>>>8&255,255&e]},e.fromColorRGB=function(e){return(255&e[0])<<16|(255&e[1])<<8|255&e[2]},e.prototype.clone=function(){var t=new e;return t.fg=this.fg,t.bg=this.bg,t},e.prototype.isInverse=function(){return 67108864&this.fg},e.prototype.isBold=function(){return 134217728&this.fg},e.prototype.isUnderline=function(){return 268435456&this.fg},e.prototype.isBlink=function(){return 536870912&this.fg},e.prototype.isInvisible=function(){return 1073741824&this.fg},e.prototype.isItalic=function(){return 67108864&this.bg},e.prototype.isDim=function(){return 134217728&this.bg},e.prototype.getFgColorMode=function(){return 50331648&this.fg},e.prototype.getBgColorMode=function(){return 50331648&this.bg},e.prototype.isFgRGB=function(){return 50331648==(50331648&this.fg)},e.prototype.isBgRGB=function(){return 50331648==(50331648&this.bg)},e.prototype.isFgPalette=function(){return 16777216==(50331648&this.fg)||33554432==(50331648&this.fg)},e.prototype.isBgPalette=function(){return 16777216==(50331648&this.bg)||33554432==(50331648&this.bg)},e.prototype.isFgDefault=function(){return 0==(50331648&this.fg)},e.prototype.isBgDefault=function(){return 0==(50331648&this.bg)},e.prototype.getFgColor=function(){switch(50331648&this.fg){case 16777216:case 33554432:return 255&this.fg;case 50331648:return 16777215&this.fg;default:return-1}},e.prototype.getBgColor=function(){switch(50331648&this.bg){case 16777216:case 33554432:return 255&this.bg;case 50331648:return 16777215&this.bg;default:return-1}},e}();t.AttributeData=i},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.addDisposableDomListener=function(e,t,r,i){return e.addEventListener(t,r,i),{dispose:function(){r&&e.removeEventListener(t,r,i)}}}},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.stringFromCodePoint=function(e){return e>65535?(e-=65536,String.fromCharCode(55296+(e>>10))+String.fromCharCode(e%1024+56320)):String.fromCharCode(e)},t.utf32ToString=function(e,t,r){void 0===t&&(t=0),void 0===r&&(r=e.length);for(var i="",n=t;n65535?(o-=65536,i+=String.fromCharCode(55296+(o>>10))+String.fromCharCode(o%1024+56320)):i+=String.fromCharCode(o)}return i};var i=function(){function e(){this._interim=0}return e.prototype.clear=function(){this._interim=0},e.prototype.decode=function(e,t){var r=e.length;if(!r)return 0;var i=0,n=0;this._interim&&(56320<=(a=e.charCodeAt(n++))&&a<=57343?t[i++]=1024*(this._interim-55296)+a-56320+65536:(t[i++]=this._interim,t[i++]=a),this._interim=0);for(var o=n;o=r)return this._interim=s,i;var a;56320<=(a=e.charCodeAt(o))&&a<=57343?t[i++]=1024*(s-55296)+a-56320+65536:(t[i++]=s,t[i++]=a)}else t[i++]=s}return i},e}();t.StringToUtf32=i;var n=function(){function e(){this.interim=new Uint8Array(3)}return e.prototype.clear=function(){this.interim.fill(0)},e.prototype.decode=function(e,t){var r=e.length;if(!r)return 0;var i,n,o,s,a=0,c=0,l=0;if(this.interim[0]){var h=!1,u=this.interim[0];u&=192==(224&u)?31:224==(240&u)?15:7;for(var f=0,_=void 0;(_=63&this.interim[++f])&&f<4;)u<<=6,u|=_;for(var d=192==(224&this.interim[0])?2:224==(240&this.interim[0])?3:4,p=d-f;l=r)return 0;if(128!=(192&(_=e[l++]))){l--,h=!0;break}this.interim[f++]=_,u<<=6,u|=63&_}h||(2===d?u<128?l--:t[a++]=u:3===d?u<2048||u>=55296&&u<=57343||(t[a++]=u):u<65536||u>1114111||(t[a++]=u)),this.interim.fill(0)}for(var v=r-4,g=l;g=r)return this.interim[0]=i,a;if(128!=(192&(n=e[g++]))){g--;continue}if((c=(31&i)<<6|63&n)<128){g--;continue}t[a++]=c}else if(224==(240&i)){if(g>=r)return this.interim[0]=i,a;if(128!=(192&(n=e[g++]))){g--;continue}if(g>=r)return this.interim[0]=i,this.interim[1]=n,a;if(128!=(192&(o=e[g++]))){g--;continue}if((c=(15&i)<<12|(63&n)<<6|63&o)<2048||c>=55296&&c<=57343)continue;t[a++]=c}else if(240==(248&i)){if(g>=r)return this.interim[0]=i,a;if(128!=(192&(n=e[g++]))){g--;continue}if(g>=r)return this.interim[0]=i,this.interim[1]=n,a;if(128!=(192&(o=e[g++]))){g--;continue}if(g>=r)return this.interim[0]=i,this.interim[1]=n,this.interim[2]=o,a;if(128!=(192&(s=e[g++]))){g--;continue}if((c=(7&i)<<18|(63&n)<<12|(63&o)<<6|63&s)<65536||c>1114111)continue;t[a++]=c}}return a},e}();t.Utf8ToUtf32=n},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.INVERTED_DEFAULT_COLOR=257,t.DIM_OPACITY=.5,t.CHAR_ATLAS_CELL_SPACING=1},function(e,t,r){"use strict";function i(e){var t=e.toString(16);return t.length<2?"0"+t:t}function n(e,t,r,n){return void 0!==n?"#"+i(e)+i(t)+i(r)+i(n):"#"+i(e)+i(t)+i(r)}function o(e,t,r,i){return void 0===i&&(i=255),(e<<24|t<<16|r<<8|i)>>>0}function s(e){return[e>>24&255,e>>16&255,e>>8&255,255&e]}function a(e){return c(e>>16&255,e>>8&255,255&e)}function c(e,t,r){var i=e/255,n=t/255,o=r/255;return.2126*(i<=.03928?i/12.92:Math.pow((i+.055)/1.055,2.4))+.7152*(n<=.03928?n/12.92:Math.pow((n+.055)/1.055,2.4))+.0722*(o<=.03928?o/12.92:Math.pow((o+.055)/1.055,2.4))}function l(e,t){return e>8),n=a(t>>8);if(l(i,n)>24&255,n=e>>16&255,o=e>>8&255,s=t>>24&255,a=t>>16&255,h=t>>8&255,u=l(c(s,h,a),c(i,n,o));u0||a>0||h>0);)s-=Math.max(0,Math.ceil(.1*s)),a-=Math.max(0,Math.ceil(.1*a)),u=l(c(s,h-=Math.max(0,Math.ceil(.1*h)),a),c(i,n,o));return(s<<24|a<<16|h<<8|255)>>>0}function _(e,t,r){for(var i=e>>24&255,n=e>>16&255,o=e>>8&255,s=t>>24&255,a=t>>16&255,h=t>>8&255,u=l(c(s,h,a),c(i,n,o));u>>0}Object.defineProperty(t,"__esModule",{value:!0}),t.blend=function(e,t){var r=(255&t.rgba)/255;if(1===r)return{css:t.css,rgba:t.rgba};var i=t.rgba>>24&255,s=t.rgba>>16&255,a=t.rgba>>8&255,c=e.rgba>>24&255,l=e.rgba>>16&255,h=e.rgba>>8&255,u=c+Math.round((i-c)*r),f=l+Math.round((s-l)*r),_=h+Math.round((a-h)*r);return{css:n(u,f,_),rgba:o(u,f,_)}},t.fromCss=function(e){return{css:e,rgba:(parseInt(e.slice(1),16)<<8|255)>>>0}},t.toPaddedHex=i,t.toCss=n,t.toRgba=o,t.fromRgba=s,t.opaque=function(e){var t=(255|e.rgba)>>>0,r=s(t);return{css:n(r[0],r[1],r[2]),rgba:t}},t.rgbRelativeLuminance=a,t.rgbRelativeLuminance2=c,t.contrastRatio=l,t.rgbaToColor=h,t.ensureContrastRatioRgba=u,t.ensureContrastRatio=function(e,t,r){var i=u(e.rgba,t.rgba,r);if(i)return h(i>>24&255,i>>16&255,i>>8&255)},t.reduceLuminance=f,t.increaseLuminance=_},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i="undefined"==typeof navigator,n=i?"node":navigator.userAgent,o=i?"node":navigator.platform;function s(e,t){return e.indexOf(t)>=0}t.isFirefox=!!~n.indexOf("Firefox"),t.isSafari=/^((?!chrome|android).)*safari/i.test(n),t.isMac=s(["Macintosh","MacIntel","MacPPC","Mac68K"],o),t.isIpad="iPad"===o,t.isIphone="iPhone"===o,t.isWindows=s(["Windows","Win16","Win32","WinCE"],o),t.isLinux=o.indexOf("Linux")>=0},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),function(e){e.NUL="\0",e.SOH="",e.STX="",e.ETX="",e.EOT="",e.ENQ="",e.ACK="",e.BEL="",e.BS="\b",e.HT="\t",e.LF="\n",e.VT="\v",e.FF="\f",e.CR="\r",e.SO="",e.SI="",e.DLE="",e.DC1="",e.DC2="",e.DC3="",e.DC4="",e.NAK="",e.SYN="",e.ETB="",e.CAN="",e.EM="",e.SUB="",e.ESC="",e.FS="",e.GS="",e.RS="",e.US="",e.SP=" ",e.DEL=""}(t.C0||(t.C0={})),function(e){e.PAD="€",e.HOP="",e.BPH="‚",e.NBH="ƒ",e.IND="„",e.NEL="…",e.SSA="†",e.ESA="‡",e.HTS="ˆ",e.HTJ="‰",e.VTS="Š",e.PLD="‹",e.PLU="Œ",e.RI="",e.SS2="Ž",e.SS3="",e.DCS="",e.PU1="‘",e.PU2="’",e.STS="“",e.CCH="”",e.MW="•",e.SPA="–",e.EPA="—",e.SOS="˜",e.SGCI="™",e.SCI="š",e.CSI="›",e.ST="œ",e.OSC="",e.PM="ž",e.APC="Ÿ"}(t.C1||(t.C1={}))},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=r(3),n=r(9),o=r(24),s=r(6),a=r(27),c=r(10),l=function(){function e(e,t,r,i,n,o,s,a){this._container=e,this._alpha=i,this._colors=n,this._rendererId=o,this._bufferService=s,this._optionsService=a,this._scaledCharWidth=0,this._scaledCharHeight=0,this._scaledCellWidth=0,this._scaledCellHeight=0,this._scaledCharLeft=0,this._scaledCharTop=0,this._currentGlyphIdentifier={chars:"",code:0,bg:0,fg:0,bold:!1,dim:!1,italic:!1},this._canvas=document.createElement("canvas"),this._canvas.classList.add("xterm-"+t+"-layer"),this._canvas.style.zIndex=r.toString(),this._initCanvas(),this._container.appendChild(this._canvas)}return e.prototype.dispose=function(){var e;this._container.removeChild(this._canvas),null===(e=this._charAtlas)||void 0===e||e.dispose()},e.prototype._initCanvas=function(){this._ctx=a.throwIfFalsy(this._canvas.getContext("2d",{alpha:this._alpha})),this._alpha||this._clearAll()},e.prototype.onOptionsChanged=function(){},e.prototype.onBlur=function(){},e.prototype.onFocus=function(){},e.prototype.onCursorMove=function(){},e.prototype.onGridChanged=function(e,t){},e.prototype.onSelectionChanged=function(e,t,r){void 0===r&&(r=!1)},e.prototype.setColors=function(e){this._refreshCharAtlas(e)},e.prototype._setTransparency=function(e){if(e!==this._alpha){var t=this._canvas;this._alpha=e,this._canvas=this._canvas.cloneNode(),this._initCanvas(),this._container.replaceChild(this._canvas,t),this._refreshCharAtlas(this._colors),this.onGridChanged(0,this._bufferService.rows-1)}},e.prototype._refreshCharAtlas=function(e){this._scaledCharWidth<=0&&this._scaledCharHeight<=0||(this._charAtlas=o.acquireCharAtlas(this._optionsService.options,this._rendererId,e,this._scaledCharWidth,this._scaledCharHeight),this._charAtlas.warmUp())},e.prototype.resize=function(e){this._scaledCellWidth=e.scaledCellWidth,this._scaledCellHeight=e.scaledCellHeight,this._scaledCharWidth=e.scaledCharWidth,this._scaledCharHeight=e.scaledCharHeight,this._scaledCharLeft=e.scaledCharLeft,this._scaledCharTop=e.scaledCharTop,this._canvas.width=e.scaledCanvasWidth,this._canvas.height=e.scaledCanvasHeight,this._canvas.style.width=e.canvasWidth+"px",this._canvas.style.height=e.canvasHeight+"px",this._alpha||this._clearAll(),this._refreshCharAtlas(this._colors)},e.prototype._fillCells=function(e,t,r,i){this._ctx.fillRect(e*this._scaledCellWidth,t*this._scaledCellHeight,r*this._scaledCellWidth,i*this._scaledCellHeight)},e.prototype._fillBottomLineAtCells=function(e,t,r){void 0===r&&(r=1),this._ctx.fillRect(e*this._scaledCellWidth,(t+1)*this._scaledCellHeight-window.devicePixelRatio-1,r*this._scaledCellWidth,window.devicePixelRatio)},e.prototype._fillLeftLineAtCell=function(e,t){this._ctx.fillRect(e*this._scaledCellWidth,t*this._scaledCellHeight,window.devicePixelRatio,this._scaledCellHeight)},e.prototype._strokeRectAtCell=function(e,t,r,i){this._ctx.lineWidth=window.devicePixelRatio,this._ctx.strokeRect(e*this._scaledCellWidth+window.devicePixelRatio/2,t*this._scaledCellHeight+window.devicePixelRatio/2,r*this._scaledCellWidth-window.devicePixelRatio,i*this._scaledCellHeight-window.devicePixelRatio)},e.prototype._clearAll=function(){this._alpha?this._ctx.clearRect(0,0,this._canvas.width,this._canvas.height):(this._ctx.fillStyle=this._colors.background.css,this._ctx.fillRect(0,0,this._canvas.width,this._canvas.height))},e.prototype._clearCells=function(e,t,r,i){this._alpha?this._ctx.clearRect(e*this._scaledCellWidth,t*this._scaledCellHeight,r*this._scaledCellWidth,i*this._scaledCellHeight):(this._ctx.fillStyle=this._colors.background.css,this._ctx.fillRect(e*this._scaledCellWidth,t*this._scaledCellHeight,r*this._scaledCellWidth,i*this._scaledCellHeight))},e.prototype._fillCharTrueColor=function(e,t,r){this._ctx.font=this._getFont(!1,!1),this._ctx.textBaseline="middle",this._clipRow(r),this._ctx.fillText(e.getChars(),t*this._scaledCellWidth+this._scaledCharLeft,r*this._scaledCellHeight+this._scaledCharTop+this._scaledCharHeight/2)},e.prototype._drawChars=function(e,t,r){var o,s,a=this._getContrastColor(e);a||e.isFgRGB()||e.isBgRGB()?this._drawUncachedChars(e,t,r,a):(e.isInverse()?(o=e.isBgDefault()?n.INVERTED_DEFAULT_COLOR:e.getBgColor(),s=e.isFgDefault()?n.INVERTED_DEFAULT_COLOR:e.getFgColor()):(s=e.isBgDefault()?i.DEFAULT_COLOR:e.getBgColor(),o=e.isFgDefault()?i.DEFAULT_COLOR:e.getFgColor()),o+=this._optionsService.options.drawBoldTextInBrightColors&&e.isBold()&&o<8?8:0,this._currentGlyphIdentifier.chars=e.getChars()||i.WHITESPACE_CELL_CHAR,this._currentGlyphIdentifier.code=e.getCode()||i.WHITESPACE_CELL_CODE,this._currentGlyphIdentifier.bg=s,this._currentGlyphIdentifier.fg=o,this._currentGlyphIdentifier.bold=!!e.isBold(),this._currentGlyphIdentifier.dim=!!e.isDim(),this._currentGlyphIdentifier.italic=!!e.isItalic(),this._charAtlas&&this._charAtlas.draw(this._ctx,this._currentGlyphIdentifier,t*this._scaledCellWidth+this._scaledCharLeft,r*this._scaledCellHeight+this._scaledCharTop)||this._drawUncachedChars(e,t,r))},e.prototype._drawUncachedChars=function(e,t,r,i){if(this._ctx.save(),this._ctx.font=this._getFont(!!e.isBold(),!!e.isItalic()),this._ctx.textBaseline="middle",e.isInverse())if(i)this._ctx.fillStyle=i.css;else if(e.isBgDefault())this._ctx.fillStyle=c.opaque(this._colors.background).css;else if(e.isBgRGB())this._ctx.fillStyle="rgb("+s.AttributeData.toColorRGB(e.getBgColor()).join(",")+")";else{var o=e.getBgColor();this._optionsService.options.drawBoldTextInBrightColors&&e.isBold()&&o<8&&(o+=8),this._ctx.fillStyle=this._colors.ansi[o].css}else if(i)this._ctx.fillStyle=i.css;else if(e.isFgDefault())this._ctx.fillStyle=this._colors.foreground.css;else if(e.isFgRGB())this._ctx.fillStyle="rgb("+s.AttributeData.toColorRGB(e.getFgColor()).join(",")+")";else{var a=e.getFgColor();this._optionsService.options.drawBoldTextInBrightColors&&e.isBold()&&a<8&&(a+=8),this._ctx.fillStyle=this._colors.ansi[a].css}this._clipRow(r),e.isDim()&&(this._ctx.globalAlpha=n.DIM_OPACITY),this._ctx.fillText(e.getChars(),t*this._scaledCellWidth+this._scaledCharLeft,r*this._scaledCellHeight+this._scaledCharTop+this._scaledCharHeight/2),this._ctx.restore()},e.prototype._clipRow=function(e){this._ctx.beginPath(),this._ctx.rect(0,e*this._scaledCellHeight,this._bufferService.cols*this._scaledCellWidth,this._scaledCellHeight),this._ctx.clip()},e.prototype._getFont=function(e,t){return(t?"italic":"")+" "+(e?this._optionsService.options.fontWeightBold:this._optionsService.options.fontWeight)+" "+this._optionsService.options.fontSize*window.devicePixelRatio+"px "+this._optionsService.options.fontFamily},e.prototype._getContrastColor=function(e){if(1!==this._optionsService.options.minimumContrastRatio){var t=this._colors.contrastCache.getColor(e.bg,e.fg);if(void 0!==t)return t||void 0;var r=e.getFgColor(),i=e.getFgColorMode(),n=e.getBgColor(),o=e.getBgColorMode(),s=!!e.isInverse(),a=!!e.isInverse();if(s){var l=r;r=n,n=l;var h=i;i=o,o=h}var u=this._resolveBackgroundRgba(o,n,s),f=this._resolveForegroundRgba(i,r,s,a),_=c.ensureContrastRatioRgba(u,f,this._optionsService.options.minimumContrastRatio);if(_){var d={css:c.toCss(_>>24&255,_>>16&255,_>>8&255),rgba:_};return this._colors.contrastCache.setColor(e.bg,e.fg,d),d}this._colors.contrastCache.setColor(e.bg,e.fg,null)}},e.prototype._resolveBackgroundRgba=function(e,t,r){switch(e){case 16777216:case 33554432:return this._colors.ansi[t].rgba;case 50331648:return t<<8;case 0:default:return r?this._colors.foreground.rgba:this._colors.background.rgba}},e.prototype._resolveForegroundRgba=function(e,t,r,i){switch(e){case 16777216:case 33554432:return this._optionsService.options.drawBoldTextInBrightColors&&i&&t<8&&(t+=8),this._colors.ansi[t].rgba;case 50331648:return t<<8;case 0:default:return r?this._colors.background.rgba:this._colors.foreground.rgba}},e}();t.BaseRenderLayer=l},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i="di$target",n="di$dependencies";function o(e,t,r){t[i]===t?t[n].push({id:e,index:r}):(t[n]=[{id:e,index:r}],t[i]=t)}t.serviceRegistry=new Map,t.getServiceDependencies=function(e){return e[n]||[]},t.createDecorator=function(e){if(t.serviceRegistry.has(e))return t.serviceRegistry.get(e);var r=function(e,t,i){if(3!==arguments.length)throw new Error("@IServiceName-decorator can only be used to decorate a parameter");o(r,e,i)};return r.toString=function(){return e},t.serviceRegistry.set(e,r),r}},function(e,t,r){"use strict";function i(e,t,r,i){if(void 0===r&&(r=0),void 0===i&&(i=e.length),r>=e.length)return e;r=(e.length+r)%e.length,i=i>=e.length?e.length:(e.length+i)%e.length;for(var n=r;n>22,2097152&t?this._combined[e].charCodeAt(this._combined[e].length-1):r]},e.prototype.set=function(e,t){this._data[e*a+1]=t[n.CHAR_DATA_ATTR_INDEX],t[n.CHAR_DATA_CHAR_INDEX].length>1?(this._combined[e]=t[1],this._data[e*a+0]=2097152|e|t[n.CHAR_DATA_WIDTH_INDEX]<<22):this._data[e*a+0]=t[n.CHAR_DATA_CHAR_INDEX].charCodeAt(0)|t[n.CHAR_DATA_WIDTH_INDEX]<<22},e.prototype.getWidth=function(e){return this._data[e*a+0]>>22},e.prototype.hasWidth=function(e){return 12582912&this._data[e*a+0]},e.prototype.getFg=function(e){return this._data[e*a+1]},e.prototype.getBg=function(e){return this._data[e*a+2]},e.prototype.hasContent=function(e){return 4194303&this._data[e*a+0]},e.prototype.getCodePoint=function(e){var t=this._data[e*a+0];return 2097152&t?this._combined[e].charCodeAt(this._combined[e].length-1):2097151&t},e.prototype.isCombined=function(e){return 2097152&this._data[e*a+0]},e.prototype.getString=function(e){var t=this._data[e*a+0];return 2097152&t?this._combined[e]:2097151&t?i.stringFromCodePoint(2097151&t):""},e.prototype.loadCell=function(e,t){var r=e*a;return t.content=this._data[r+0],t.fg=this._data[r+1],t.bg=this._data[r+2],2097152&t.content&&(t.combinedData=this._combined[e]),t},e.prototype.setCell=function(e,t){2097152&t.content&&(this._combined[e]=t.combinedData),this._data[e*a+0]=t.content,this._data[e*a+1]=t.fg,this._data[e*a+2]=t.bg},e.prototype.setCellFromCodePoint=function(e,t,r,i,n){this._data[e*a+0]=t|r<<22,this._data[e*a+1]=i,this._data[e*a+2]=n},e.prototype.addCodepointToCell=function(e,t){var r=this._data[e*a+0];2097152&r?this._combined[e]+=i.stringFromCodePoint(t):(2097151&r?(this._combined[e]=i.stringFromCodePoint(2097151&r)+i.stringFromCodePoint(t),r&=-2097152,r|=2097152):r=t|1<<22,this._data[e*a+0]=r)},e.prototype.insertCells=function(e,t,r){if(e%=this.length,t=0;--n)this.setCell(e+t+n,this.loadCell(e+n,i));for(n=0;nthis.length){var r=new Uint32Array(e*a);this.length&&(e*a=e&&delete this._combined[o]}}else this._data=new Uint32Array(0),this._combined={};this.length=e}},e.prototype.fill=function(e){this._combined={};for(var t=0;t=0;--e)if(4194303&this._data[e*a+0])return e+(this._data[e*a+0]>>22);return 0},e.prototype.copyCellsFrom=function(e,t,r,i,n){var o=e._data;if(n)for(var s=i-1;s>=0;s--)for(var c=0;c=t&&(this._combined[h-t+r]=e._combined[h])}},e.prototype.translateToString=function(e,t,r){void 0===e&&(e=!1),void 0===t&&(t=0),void 0===r&&(r=this.length),e&&(r=Math.min(r,this.getTrimmedLength()));for(var o="";t>22||1}return o},e}();t.BufferLine=c},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.promptLabel="Terminal input",t.tooMuchOutput="Too much output to announce, navigate to rows manually to read"},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.CHARSETS={},t.DEFAULT_CHARSET=t.CHARSETS.B,t.CHARSETS[0]={"`":"◆",a:"▒",b:"\t",c:"\f",d:"\r",e:"\n",f:"°",g:"±",h:"␤",i:"\v",j:"┘",k:"┐",l:"┌",m:"└",n:"┼",o:"⎺",p:"⎻",q:"─",r:"⎼",s:"⎽",t:"├",u:"┤",v:"┴",w:"┬",x:"│",y:"≤",z:"≥","{":"π","|":"≠","}":"£","~":"·"},t.CHARSETS.A={"#":"£"},t.CHARSETS.B=null,t.CHARSETS[4]={"#":"£","@":"¾","[":"ij","\\":"½","]":"|","{":"¨","|":"f","}":"¼","~":"´"},t.CHARSETS.C=t.CHARSETS[5]={"[":"Ä","\\":"Ö","]":"Å","^":"Ü","`":"é","{":"ä","|":"ö","}":"å","~":"ü"},t.CHARSETS.R={"#":"£","@":"à","[":"°","\\":"ç","]":"§","{":"é","|":"ù","}":"è","~":"¨"},t.CHARSETS.Q={"@":"à","[":"â","\\":"ç","]":"ê","^":"î","`":"ô","{":"é","|":"ù","}":"è","~":"û"},t.CHARSETS.K={"@":"§","[":"Ä","\\":"Ö","]":"Ü","{":"ä","|":"ö","}":"ü","~":"ß"},t.CHARSETS.Y={"#":"£","@":"§","[":"°","\\":"ç","]":"é","`":"ù","{":"à","|":"ò","}":"è","~":"ì"},t.CHARSETS.E=t.CHARSETS[6]={"@":"Ä","[":"Æ","\\":"Ø","]":"Å","^":"Ü","`":"ä","{":"æ","|":"ø","}":"å","~":"ü"},t.CHARSETS.Z={"#":"£","@":"§","[":"¡","\\":"Ñ","]":"¿","{":"°","|":"ñ","}":"ç"},t.CHARSETS.H=t.CHARSETS[7]={"@":"É","[":"Ä","\\":"Ö","]":"Å","^":"Ü","`":"é","{":"ä","|":"ö","}":"å","~":"ü"},t.CHARSETS["="]={"#":"ù","@":"à","[":"é","\\":"ç","]":"ê","^":"î",_:"è","`":"ô","{":"ä","|":"ö","}":"ü","~":"û"}},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=r(15);t.wcwidth=function(e){var t=[[768,879],[1155,1158],[1160,1161],[1425,1469],[1471,1471],[1473,1474],[1476,1477],[1479,1479],[1536,1539],[1552,1557],[1611,1630],[1648,1648],[1750,1764],[1767,1768],[1770,1773],[1807,1807],[1809,1809],[1840,1866],[1958,1968],[2027,2035],[2305,2306],[2364,2364],[2369,2376],[2381,2381],[2385,2388],[2402,2403],[2433,2433],[2492,2492],[2497,2500],[2509,2509],[2530,2531],[2561,2562],[2620,2620],[2625,2626],[2631,2632],[2635,2637],[2672,2673],[2689,2690],[2748,2748],[2753,2757],[2759,2760],[2765,2765],[2786,2787],[2817,2817],[2876,2876],[2879,2879],[2881,2883],[2893,2893],[2902,2902],[2946,2946],[3008,3008],[3021,3021],[3134,3136],[3142,3144],[3146,3149],[3157,3158],[3260,3260],[3263,3263],[3270,3270],[3276,3277],[3298,3299],[3393,3395],[3405,3405],[3530,3530],[3538,3540],[3542,3542],[3633,3633],[3636,3642],[3655,3662],[3761,3761],[3764,3769],[3771,3772],[3784,3789],[3864,3865],[3893,3893],[3895,3895],[3897,3897],[3953,3966],[3968,3972],[3974,3975],[3984,3991],[3993,4028],[4038,4038],[4141,4144],[4146,4146],[4150,4151],[4153,4153],[4184,4185],[4448,4607],[4959,4959],[5906,5908],[5938,5940],[5970,5971],[6002,6003],[6068,6069],[6071,6077],[6086,6086],[6089,6099],[6109,6109],[6155,6157],[6313,6313],[6432,6434],[6439,6440],[6450,6450],[6457,6459],[6679,6680],[6912,6915],[6964,6964],[6966,6970],[6972,6972],[6978,6978],[7019,7027],[7616,7626],[7678,7679],[8203,8207],[8234,8238],[8288,8291],[8298,8303],[8400,8431],[12330,12335],[12441,12442],[43014,43014],[43019,43019],[43045,43046],[64286,64286],[65024,65039],[65056,65059],[65279,65279],[65529,65531]],r=[[68097,68099],[68101,68102],[68108,68111],[68152,68154],[68159,68159],[119143,119145],[119155,119170],[119173,119179],[119210,119213],[119362,119364],[917505,917505],[917536,917631],[917760,917999]];var n=0|e.control,o=new Uint8Array(65536);i.fill(o,1),o[0]=e.nul,i.fill(o,e.control,1,32),i.fill(o,e.control,127,160),i.fill(o,2,4352,4448),o[9001]=2,o[9002]=2,i.fill(o,2,11904,42192),o[12351]=1,i.fill(o,2,44032,55204),i.fill(o,2,63744,64256),i.fill(o,2,65040,65050),i.fill(o,2,65072,65136),i.fill(o,2,65280,65377),i.fill(o,2,65504,65511);for(var s=0;st[n][1])return!1;for(;n>=i;)if(e>t[r=i+n>>1][1])i=r+1;else{if(!(e=131072&&t<=196605||t>=196608&&t<=262141?2:1;var t}}({nul:0,control:0}),t.getStringCellWidth=function(e){for(var r=0,i=e.length,n=0;n=i)return r+t.wcwidth(o);var s=e.charCodeAt(n);56320<=s&&s<=57343?o=1024*(o-55296)+s-56320+65536:r+=t.wcwidth(s)}r+=t.wcwidth(o)}return r}},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=256,n=function(){function e(e,t){if(void 0===e&&(e=32),void 0===t&&(t=32),this.maxLength=e,this.maxSubParamsLength=t,t>i)throw new Error("maxSubParamsLength must not be greater than 256");this.params=new Int32Array(e),this.length=0,this._subParams=new Int32Array(t),this._subParamsLength=0,this._subParamsIdx=new Uint16Array(e),this._rejectDigits=!1,this._rejectSubDigits=!1,this._digitIsSub=!1}return e.fromArray=function(t){var r=new e;if(!t.length)return r;for(var i=t[0]instanceof Array?1:0;i>8,i=255&this._subParamsIdx[t];i-r>0&&e.push(Array.prototype.slice.call(this._subParams,r,i))}return e},e.prototype.reset=function(){this.length=0,this._subParamsLength=0,this._rejectDigits=!1,this._rejectSubDigits=!1,this._digitIsSub=!1},e.prototype.addParam=function(e){if(this._digitIsSub=!1,this.length>=this.maxLength)this._rejectDigits=!0;else{if(e<-1)throw new Error("values lesser than -1 are not allowed");this._subParamsIdx[this.length]=this._subParamsLength<<8|this._subParamsLength,this.params[this.length++]=e>2147483647?2147483647:e}},e.prototype.addSubParam=function(e){if(this._digitIsSub=!0,this.length)if(this._rejectDigits||this._subParamsLength>=this.maxSubParamsLength)this._rejectSubDigits=!0;else{if(e<-1)throw new Error("values lesser than -1 are not allowed");this._subParams[this._subParamsLength++]=e>2147483647?2147483647:e,this._subParamsIdx[this.length-1]++}},e.prototype.hasSubParams=function(e){return(255&this._subParamsIdx[e])-(this._subParamsIdx[e]>>8)>0},e.prototype.getSubParams=function(e){var t=this._subParamsIdx[e]>>8,r=255&this._subParamsIdx[e];return r-t>0?this._subParams.subarray(t,r):null},e.prototype.getSubParamsAll=function(){for(var e={},t=0;t>8,i=255&this._subParamsIdx[t];i-r>0&&(e[t]=this._subParams.slice(r,i))}return e},e.prototype.addDigit=function(e){var t;if(!(this._rejectDigits||!(t=this._digitIsSub?this._subParamsLength:this.length)||this._digitIsSub&&this._rejectSubDigits)){var r=this._digitIsSub?this._subParams:this.params,i=r[t-1];r[t-1]=~i?Math.min(10*i+e,2147483647):e}},e}();t.Params=n},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=r(22),n=r(8),o=function(){function e(){this._state=0,this._id=-1,this._handlers=Object.create(null),this._handlerFb=function(){}}return e.prototype.addHandler=function(e,t){void 0===this._handlers[e]&&(this._handlers[e]=[]);var r=this._handlers[e];return r.push(t),{dispose:function(){var e=r.indexOf(t);-1!==e&&r.splice(e,1)}}},e.prototype.setHandler=function(e,t){this._handlers[e]=[t]},e.prototype.clearHandler=function(e){this._handlers[e]&&delete this._handlers[e]},e.prototype.setHandlerFallback=function(e){this._handlerFb=e},e.prototype.dispose=function(){this._handlers=Object.create(null),this._handlerFb=function(){}},e.prototype.reset=function(){2===this._state&&this.end(!1),this._id=-1,this._state=0},e.prototype._start=function(){var e=this._handlers[this._id];if(e)for(var t=e.length-1;t>=0;t--)e[t].start();else this._handlerFb(this._id,"START")},e.prototype._put=function(e,t,r){var i=this._handlers[this._id];if(i)for(var o=i.length-1;o>=0;o--)i[o].put(e,t,r);else this._handlerFb(this._id,"PUT",n.utf32ToString(e,t,r))},e.prototype._end=function(e){var t=this._handlers[this._id];if(t){for(var r=t.length-1;r>=0&&!1===t[r].end(e);r--);for(r--;r>=0;r--)t[r].end(!1)}else this._handlerFb(this._id,"END",e)},e.prototype.start=function(){this.reset(),this._id=-1,this._state=1},e.prototype.put=function(e,t,r){if(3!==this._state){if(1===this._state)for(;t0&&this._put(e,t,r)}},e.prototype.end=function(e){0!==this._state&&(3!==this._state&&(1===this._state&&this._start(),this._end(e)),this._id=-1,this._state=0)},e}();t.OscParser=o;var s=function(){function e(e){this._handler=e,this._data="",this._hitLimit=!1}return e.prototype.start=function(){this._data="",this._hitLimit=!1},e.prototype.put=function(e,t,r){this._hitLimit||(this._data+=n.utf32ToString(e,t,r),this._data.length>i.PAYLOAD_LIMIT&&(this._data="",this._hitLimit=!0))},e.prototype.end=function(e){var t;return this._hitLimit?t=!1:e&&(t=this._handler(this._data)),this._data="",this._hitLimit=!1,t},e}();t.OscHandler=s},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.PAYLOAD_LIMIT=1e7},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=r(8),n=r(20),o=r(22),s=[],a=function(){function e(){this._handlers=Object.create(null),this._active=s,this._ident=0,this._handlerFb=function(){}}return e.prototype.dispose=function(){this._handlers=Object.create(null),this._handlerFb=function(){}},e.prototype.addHandler=function(e,t){void 0===this._handlers[e]&&(this._handlers[e]=[]);var r=this._handlers[e];return r.push(t),{dispose:function(){var e=r.indexOf(t);-1!==e&&r.splice(e,1)}}},e.prototype.setHandler=function(e,t){this._handlers[e]=[t]},e.prototype.clearHandler=function(e){this._handlers[e]&&delete this._handlers[e]},e.prototype.setHandlerFallback=function(e){this._handlerFb=e},e.prototype.reset=function(){this._active.length&&this.unhook(!1),this._active=s,this._ident=0},e.prototype.hook=function(e,t){if(this.reset(),this._ident=e,this._active=this._handlers[e]||s,this._active.length)for(var r=this._active.length-1;r>=0;r--)this._active[r].hook(t);else this._handlerFb(this._ident,"HOOK",t)},e.prototype.put=function(e,t,r){if(this._active.length)for(var n=this._active.length-1;n>=0;n--)this._active[n].put(e,t,r);else this._handlerFb(this._ident,"PUT",i.utf32ToString(e,t,r))},e.prototype.unhook=function(e){if(this._active.length){for(var t=this._active.length-1;t>=0&&!1===this._active[t].unhook(e);t--);for(t--;t>=0;t--)this._active[t].unhook(!1)}else this._handlerFb(this._ident,"UNHOOK",e);this._active=s,this._ident=0},e}();t.DcsParser=a;var c=function(){function e(e){this._handler=e,this._data="",this._hitLimit=!1}return e.prototype.hook=function(e){this._params=e.clone(),this._data="",this._hitLimit=!1},e.prototype.put=function(e,t,r){this._hitLimit||(this._data+=i.utf32ToString(e,t,r),this._data.length>o.PAYLOAD_LIMIT&&(this._data="",this._hitLimit=!0))},e.prototype.unhook=function(e){var t;return this._hitLimit?t=!1:e&&(t=this._handler(this._data,this._params?this._params:new n.Params)),this._params=void 0,this._data="",this._hitLimit=!1,t},e}();t.DcsHandler=c},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=r(25),n=r(43),o=[];t.acquireCharAtlas=function(e,t,r,s,a){for(var c=i.generateConfig(s,a,e,r),l=0;l=0){if(i.configEquals(u.config,c))return u.atlas;1===u.ownedBy.length?(u.atlas.dispose(),o.splice(l,1)):u.ownedBy.splice(h,1);break}}for(l=0;l>12&15),s=16*(h>>8&15),a=16*(h>>4&15),c=16*(15&h),l=i.toRgba(o,s,a,c)}else o=(l=parseInt(e.substr(1),16))>>24&255,s=l>>16&255,a=l>>8&255,c=255&l;return{rgba:l,css:i.toCss(o,s,a,c)}}return{css:e,rgba:i.toRgba(n[0],n[1],n[2],n[3])}},e}();t.ColorManager=h},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.throwIfFalsy=function(e){if(!e)throw new Error("value must not be falsy");return e}},function(e,t,r){"use strict";var i,n=this&&this.__extends||(i=function(e,t){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])})(e,t)},function(e,t){function r(){this.constructor=e}i(e,t),e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)});Object.defineProperty(t,"__esModule",{value:!0});var o=r(6),s=r(3),a=r(5),c=function(e){function t(t,r,i){var n=e.call(this)||this;return n.content=0,n.combinedData="",n.fg=t.fg,n.bg=t.bg,n.combinedData=r,n._width=i,n}return n(t,e),t.prototype.isCombined=function(){return 2097152},t.prototype.getWidth=function(){return this._width},t.prototype.getChars=function(){return this.combinedData},t.prototype.getCode=function(){return 2097151},t.prototype.setFromCharData=function(e){throw new Error("not implemented")},t.prototype.getAsCharData=function(){return[this.fg,this.getChars(),this.getWidth(),this.getCode()]},t}(o.AttributeData);t.JoinedCellData=c;var l=function(){function e(e){this._bufferService=e,this._characterJoiners=[],this._nextCharacterJoinerId=0,this._workCell=new a.CellData}return e.prototype.registerCharacterJoiner=function(e){var t={id:this._nextCharacterJoinerId++,handler:e};return this._characterJoiners.push(t),t.id},e.prototype.deregisterCharacterJoiner=function(e){for(var t=0;t1)for(var u=this._getJoinedRanges(i,a,o,t,n),f=0;f1)for(u=this._getJoinedRanges(i,a,o,t,n),f=0;f=this._line.length))return new l(this._line,e)},e.prototype.translateToString=function(e,t,r){return this._line.translateToString(e,t,r)},e}(),l=function(){function e(e,t){this._line=e,this._x=t}return Object.defineProperty(e.prototype,"char",{get:function(){return this._line.getString(this._x)},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"width",{get:function(){return this._line.getWidth(this._x)},enumerable:!0,configurable:!0}),e}(),h=function(){function e(e){this._core=e}return e.prototype.addCsiHandler=function(e,t){return this._core.addCsiHandler(e,function(e){return t(e.toArray())})},e.prototype.addDcsHandler=function(e,t){return this._core.addDcsHandler(e,function(e,r){return t(e,r.toArray())})},e.prototype.addEscHandler=function(e,t){return this._core.addEscHandler(e,t)},e.prototype.addOscHandler=function(e,t){return this._core.addOscHandler(e,t)},e}()},function(e,t,r){"use strict";var i,n=this&&this.__extends||(i=function(e,t){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])})(e,t)},function(e,t){function r(){this.constructor=e}i(e,t),e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)});Object.defineProperty(t,"__esModule",{value:!0});var o=r(35),s=r(36),a=r(37),c=r(12),l=r(38),h=r(40),u=r(50),f=r(51),_=r(11),d=r(7),p=r(17),v=r(54),g=r(55),y=r(56),b=r(57),m=r(59),C=r(1),S=r(16),w=r(60),E=r(26),L=r(61),A=r(0),R=r(62),x=r(4),k=r(63),D=r(64),T=r(2),M=r(70),O=r(71),P=r(72),H=r(73),I=r(74),B=r(75),F=r(76),j=r(77),q="undefined"!=typeof window?window.document:null,W=function(e){function t(t){void 0===t&&(t={});var r=e.call(this)||this;return r.browser=_,r.mouseEvents=0,r._keyDownHandled=!1,r._blankLine=null,r._onCursorMove=new C.EventEmitter,r._onData=new C.EventEmitter,r._onBinary=new C.EventEmitter,r._onKey=new C.EventEmitter,r._onLineFeed=new C.EventEmitter,r._onRender=new C.EventEmitter,r._onResize=new C.EventEmitter,r._onScroll=new C.EventEmitter,r._onSelectionChange=new C.EventEmitter,r._onTitleChange=new C.EventEmitter,r._onFocus=new C.EventEmitter,r._onBlur=new C.EventEmitter,r.onA11yCharEmitter=new C.EventEmitter,r.onA11yTabEmitter=new C.EventEmitter,r._instantiationService=new I.InstantiationService,r.optionsService=new R.OptionsService(t),r._instantiationService.setService(A.IOptionsService,r.optionsService),r._bufferService=r._instantiationService.createInstance(D.BufferService),r._instantiationService.setService(A.IBufferService,r._bufferService),r._logService=r._instantiationService.createInstance(P.LogService),r._instantiationService.setService(A.ILogService,r._logService),r._coreService=r._instantiationService.createInstance(O.CoreService,function(){return r.scrollToBottom()}),r._instantiationService.setService(A.ICoreService,r._coreService),r._coreService.onData(function(e){return r._onData.fire(e)}),r._coreService.onBinary(function(e){return r._onBinary.fire(e)}),r._coreMouseService=r._instantiationService.createInstance(B.CoreMouseService),r._instantiationService.setService(A.ICoreMouseService,r._coreMouseService),r._dirtyRowService=r._instantiationService.createInstance(H.DirtyRowService),r._instantiationService.setService(A.IDirtyRowService,r._dirtyRowService),r._setupOptionsListeners(),r._setup(),r._writeBuffer=new F.WriteBuffer(function(e){return r._inputHandler.parse(e)}),r}return n(t,e),Object.defineProperty(t.prototype,"options",{get:function(){return this.optionsService.options},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"cols",{get:function(){return this._bufferService.cols},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"rows",{get:function(){return this._bufferService.rows},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"onCursorMove",{get:function(){return this._onCursorMove.event},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"onData",{get:function(){return this._onData.event},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"onBinary",{get:function(){return this._onBinary.event},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"onKey",{get:function(){return this._onKey.event},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"onLineFeed",{get:function(){return this._onLineFeed.event},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"onRender",{get:function(){return this._onRender.event},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"onResize",{get:function(){return this._onResize.event},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"onScroll",{get:function(){return this._onScroll.event},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"onSelectionChange",{get:function(){return this._onSelectionChange.event},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"onTitleChange",{get:function(){return this._onTitleChange.event},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"onFocus",{get:function(){return this._onFocus.event},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"onBlur",{get:function(){return this._onBlur.event},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"onA11yChar",{get:function(){return this.onA11yCharEmitter.event},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"onA11yTab",{get:function(){return this.onA11yTabEmitter.event},enumerable:!0,configurable:!0}),t.prototype.dispose=function(){var t,r,i,n;this._isDisposed||(e.prototype.dispose.call(this),null===(t=this._windowsMode)||void 0===t||t.dispose(),this._windowsMode=void 0,null===(r=this._renderService)||void 0===r||r.dispose(),this._customKeyEventHandler=null,this.write=function(){},null===(n=null===(i=this.element)||void 0===i?void 0:i.parentNode)||void 0===n||n.removeChild(this.element))},t.prototype._setup=function(){var e=this;this._parent=q?q.body:null,this._customKeyEventHandler=null,this.applicationKeypad=!1,this.originMode=!1,this.insertMode=!1,this.wraparoundMode=!0,this.bracketedPasteMode=!1,this.charset=null,this.gcharset=null,this.glevel=0,this.charsets=[null],this.curAttrData=S.DEFAULT_ATTR_DATA.clone(),this._eraseAttrData=S.DEFAULT_ATTR_DATA.clone(),this.params=[],this.currentParam=0,this._userScrolling=!1,this._inputHandler=new l.InputHandler(this,this._bufferService,this._coreService,this._dirtyRowService,this._logService,this.optionsService,this._coreMouseService),this._inputHandler.onCursorMove(function(){return e._onCursorMove.fire()}),this._inputHandler.onLineFeed(function(){return e._onLineFeed.fire()}),this.register(this._inputHandler),this.linkifier=this.linkifier||new u.Linkifier(this._bufferService,this._logService),this.options.windowsMode&&this._enableWindowsMode()},t.prototype._enableWindowsMode=function(){this._windowsMode||(this._windowsMode=this.onLineFeed(w.handleWindowsModeLineFeed.bind(null,this._bufferService)))},Object.defineProperty(t.prototype,"buffer",{get:function(){return this.buffers.active},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"buffers",{get:function(){return this._bufferService.buffers},enumerable:!0,configurable:!0}),t.prototype.eraseAttrData=function(){return this._eraseAttrData.bg&=-67108864,this._eraseAttrData.bg|=67108863&this.curAttrData.bg,this._eraseAttrData},t.prototype.focus=function(){this.textarea&&this.textarea.focus({preventScroll:!0})},t.prototype._setupOptionsListeners=function(){var e=this;this.optionsService.onOptionChange(function(t){var r,i,n,o,s;switch(t){case"fontFamily":case"fontSize":null===(r=e._renderService)||void 0===r||r.clear(),null===(i=e._charSizeService)||void 0===i||i.measure();break;case"drawBoldTextInBrightColors":case"letterSpacing":case"lineHeight":case"fontWeight":case"fontWeightBold":case"minimumContrastRatio":e._renderService&&(e._renderService.clear(),e._renderService.onResize(e.cols,e.rows),e.refresh(0,e.rows-1));break;case"rendererType":e._renderService&&(e._renderService.setRenderer(e._createRenderer()),e._renderService.onResize(e.cols,e.rows));break;case"scrollback":e.buffers.resize(e.cols,e.rows),null===(n=e.viewport)||void 0===n||n.syncScrollArea();break;case"screenReaderMode":e.optionsService.options.screenReaderMode?!e._accessibilityManager&&e._renderService&&(e._accessibilityManager=new y.AccessibilityManager(e,e._renderService)):(null===(o=e._accessibilityManager)||void 0===o||o.dispose(),e._accessibilityManager=null);break;case"tabStopWidth":e.buffers.setupTabStops();break;case"theme":e._setTheme(e.optionsService.options.theme);break;case"windowsMode":e.optionsService.options.windowsMode?e._enableWindowsMode():(null===(s=e._windowsMode)||void 0===s||s.dispose(),e._windowsMode=void 0)}})},t.prototype._onTextAreaFocus=function(e){this.sendFocus&&this._coreService.triggerDataEvent(c.C0.ESC+"[I"),this.updateCursorStyle(e),this.element.classList.add("focus"),this.showCursor(),this._onFocus.fire()},t.prototype.blur=function(){return this.textarea.blur()},t.prototype._onTextAreaBlur=function(){this.textarea.value="",this.refresh(this.buffer.y,this.buffer.y),this.sendFocus&&this._coreService.triggerDataEvent(c.C0.ESC+"[O"),this.element.classList.remove("focus"),this._onBlur.fire()},t.prototype._initGlobal=function(){var e=this;this._bindKeys(),this.register(d.addDisposableDomListener(this.element,"copy",function(t){e.hasSelection()&&a.copyHandler(t,e._selectionService)}));var t=function(t){return a.handlePasteEvent(t,e.textarea,e.bracketedPasteMode,e._coreService)};this.register(d.addDisposableDomListener(this.textarea,"paste",t)),this.register(d.addDisposableDomListener(this.element,"paste",t)),_.isFirefox?this.register(d.addDisposableDomListener(this.element,"mousedown",function(t){2===t.button&&a.rightClickHandler(t,e.textarea,e.screenElement,e._selectionService,e.options.rightClickSelectsWord)})):this.register(d.addDisposableDomListener(this.element,"contextmenu",function(t){a.rightClickHandler(t,e.textarea,e.screenElement,e._selectionService,e.options.rightClickSelectsWord)})),_.isLinux&&this.register(d.addDisposableDomListener(this.element,"auxclick",function(t){1===t.button&&a.moveTextAreaUnderMouseCursor(t,e.textarea,e.screenElement)}))},t.prototype._bindKeys=function(){var e=this;this.register(d.addDisposableDomListener(this.textarea,"keyup",function(t){return e._keyUp(t)},!0)),this.register(d.addDisposableDomListener(this.textarea,"keydown",function(t){return e._keyDown(t)},!0)),this.register(d.addDisposableDomListener(this.textarea,"keypress",function(t){return e._keyPress(t)},!0)),this.register(d.addDisposableDomListener(this.textarea,"compositionstart",function(){return e._compositionHelper.compositionstart()})),this.register(d.addDisposableDomListener(this.textarea,"compositionupdate",function(t){return e._compositionHelper.compositionupdate(t)})),this.register(d.addDisposableDomListener(this.textarea,"compositionend",function(){return e._compositionHelper.compositionend()})),this.register(this.onRender(function(){return e._compositionHelper.updateCompositionElements()})),this.register(this.onRender(function(t){return e._queueLinkification(t.start,t.end)}))},t.prototype.open=function(e){var t=this;if(this._parent=e||this._parent,!this._parent)throw new Error("Terminal requires a parent element.");q.body.contains(e)||this._logService.warn("Terminal.open was called on an element that was not attached to the DOM"),this._document=this._parent.ownerDocument,this.element=this._document.createElement("div"),this.element.dir="ltr",this.element.classList.add("terminal"),this.element.classList.add("xterm"),this.element.setAttribute("tabindex","0"),this._parent.appendChild(this.element);var r=q.createDocumentFragment();this._viewportElement=q.createElement("div"),this._viewportElement.classList.add("xterm-viewport"),r.appendChild(this._viewportElement),this._viewportScrollArea=q.createElement("div"),this._viewportScrollArea.classList.add("xterm-scroll-area"),this._viewportElement.appendChild(this._viewportScrollArea),this.screenElement=q.createElement("div"),this.screenElement.classList.add("xterm-screen"),this._helperContainer=q.createElement("div"),this._helperContainer.classList.add("xterm-helpers"),this.screenElement.appendChild(this._helperContainer),r.appendChild(this.screenElement),this.textarea=q.createElement("textarea"),this.textarea.classList.add("xterm-helper-textarea"),this.textarea.setAttribute("aria-label",p.promptLabel),this.textarea.setAttribute("aria-multiline","false"),this.textarea.setAttribute("autocorrect","off"),this.textarea.setAttribute("autocapitalize","off"),this.textarea.setAttribute("spellcheck","false"),this.textarea.tabIndex=0,this.register(d.addDisposableDomListener(this.textarea,"focus",function(e){return t._onTextAreaFocus(e)})),this.register(d.addDisposableDomListener(this.textarea,"blur",function(){return t._onTextAreaBlur()})),this._helperContainer.appendChild(this.textarea);var i=this._instantiationService.createInstance(j.CoreBrowserService,this.textarea);this._instantiationService.setService(x.ICoreBrowserService,i),this._charSizeService=this._instantiationService.createInstance(k.CharSizeService,this._document,this._helperContainer),this._instantiationService.setService(x.ICharSizeService,this._charSizeService),this._compositionView=q.createElement("div"),this._compositionView.classList.add("composition-view"),this._compositionHelper=this._instantiationService.createInstance(o.CompositionHelper,this.textarea,this._compositionView),this._helperContainer.appendChild(this._compositionView),this.element.appendChild(r),this._theme=this.options.theme||this._theme,this.options.theme=void 0,this._colorManager=new E.ColorManager(q,this.options.allowTransparency),this.optionsService.onOptionChange(function(e){return t._colorManager.onOptionsChange(e)}),this._colorManager.setTheme(this._theme);var n=this._createRenderer();this._renderService=this._instantiationService.createInstance(L.RenderService,n,this.rows,this.screenElement),this._instantiationService.setService(x.IRenderService,this._renderService),this._renderService.onRender(function(e){return t._onRender.fire(e)}),this.onResize(function(e){return t._renderService.resize(e.cols,e.rows)}),this._soundService=this._instantiationService.createInstance(v.SoundService),this._instantiationService.setService(x.ISoundService,this._soundService),this._mouseService=this._instantiationService.createInstance(M.MouseService),this._instantiationService.setService(x.IMouseService,this._mouseService),this.viewport=this._instantiationService.createInstance(s.Viewport,function(e,r){return t.scrollLines(e,r)},this._viewportElement,this._viewportScrollArea),this.viewport.onThemeChange(this._colorManager.colors),this.register(this.viewport),this.register(this.onCursorMove(function(){return t._renderService.onCursorMove()})),this.register(this.onResize(function(){return t._renderService.onResize(t.cols,t.rows)})),this.register(this.onBlur(function(){return t._renderService.onBlur()})),this.register(this.onFocus(function(){return t._renderService.onFocus()})),this.register(this._renderService.onDimensionsChange(function(){return t.viewport.syncScrollArea()})),this._selectionService=this._instantiationService.createInstance(f.SelectionService,function(e,r){return t.scrollLines(e,r)},this.element,this.screenElement),this._instantiationService.setService(x.ISelectionService,this._selectionService),this.register(this._selectionService.onSelectionChange(function(){return t._onSelectionChange.fire()})),this.register(this._selectionService.onRedrawRequest(function(e){return t._renderService.onSelectionChanged(e.start,e.end,e.columnSelectMode)})),this.register(this._selectionService.onLinuxMouseSelection(function(e){t.textarea.value=e,t.textarea.focus(),t.textarea.select()})),this.register(this.onScroll(function(){t.viewport.syncScrollArea(),t._selectionService.refresh()})),this.register(d.addDisposableDomListener(this._viewportElement,"scroll",function(){return t._selectionService.refresh()})),this._mouseZoneManager=this._instantiationService.createInstance(g.MouseZoneManager,this.element,this.screenElement),this.register(this._mouseZoneManager),this.register(this.onScroll(function(){return t._mouseZoneManager.clearAll()})),this.linkifier.attachToDom(this.element,this._mouseZoneManager),this.register(d.addDisposableDomListener(this.element,"mousedown",function(e){return t._selectionService.onMouseDown(e)})),this.mouseEvents?(this._selectionService.disable(),this.element.classList.add("enable-mouse-events")):this._selectionService.enable(),this.options.screenReaderMode&&(this._accessibilityManager=new y.AccessibilityManager(this,this._renderService)),this._charSizeService.measure(),this.refresh(0,this.rows-1),this._initGlobal(),this.bindMouse()},t.prototype._createRenderer=function(){switch(this.options.rendererType){case"canvas":return this._instantiationService.createInstance(h.Renderer,this._colorManager.colors,this.screenElement,this.linkifier);case"dom":return this._instantiationService.createInstance(b.DomRenderer,this._colorManager.colors,this.element,this.screenElement,this._viewportElement,this.linkifier);default:throw new Error('Unrecognized rendererType "'+this.options.rendererType+'"')}},t.prototype._setTheme=function(e){var t,r,i;this._theme=e,null===(t=this._colorManager)||void 0===t||t.setTheme(e),null===(r=this._renderService)||void 0===r||r.setColors(this._colorManager.colors),null===(i=this.viewport)||void 0===i||i.onThemeChange(this._colorManager.colors)},t.prototype.bindMouse=function(){var e=this,t=this,r=this.element;function i(e){var r,i,n;if(!(r=t._mouseService.getRawByteCoords(e,t.screenElement,t.cols,t.rows)))return!1;switch(e.overrideType||e.type){case"mousemove":n=32,void 0===e.buttons?(i=3,void 0!==e.button&&(i=e.button<3?e.button:3)):i=1&e.buttons?0:4&e.buttons?1:2&e.buttons?2:3;break;case"mouseup":n=0,i=e.button<3?e.button:3;break;case"mousedown":n=1,i=e.button<3?e.button:3;break;case"wheel":0!==e.deltaY&&(n=e.deltaY<0?0:1),i=4;break;default:return!1}return!(void 0===n||void 0===i||i>4)&&t._coreMouseService.triggerMouseEvent({col:r.x-33,row:r.y-33,button:i,action:n,ctrl:e.ctrlKey,alt:e.altKey,shift:e.shiftKey})}var n={mouseup:null,wheel:null,mousedrag:null,mousemove:null},o=function(t){return i(t),t.buttons||(e._document.removeEventListener("mouseup",n.mouseup),n.mousedrag&&e._document.removeEventListener("mousemove",n.mousedrag)),e.cancel(t)},s=function(t){return i(t),t.preventDefault(),e.cancel(t)},a=function(e){e.buttons&&i(e)},l=function(e){e.buttons||i(e)};this._coreMouseService.onProtocolChange(function(t){e.mouseEvents=t,t?("debug"===e.optionsService.options.logLevel&&e._logService.debug("Binding to mouse events:",e._coreMouseService.explainEvents(t)),e.element.classList.add("enable-mouse-events"),e._selectionService.disable()):(e._logService.debug("Unbinding from mouse events."),e.element.classList.remove("enable-mouse-events"),e._selectionService.enable()),8&t?n.mousemove||(r.addEventListener("mousemove",l),n.mousemove=l):(r.removeEventListener("mousemove",n.mousemove),n.mousemove=null),16&t?n.wheel||(r.addEventListener("wheel",s),n.wheel=s):(r.removeEventListener("wheel",n.wheel),n.wheel=null),2&t?n.mouseup||(n.mouseup=o):(e._document.removeEventListener("mouseup",n.mouseup),n.mouseup=null),4&t?n.mousedrag||(n.mousedrag=a):(e._document.removeEventListener("mousemove",n.mousedrag),n.mousedrag=null)}),this._coreMouseService.activeProtocol=this._coreMouseService.activeProtocol,this.register(d.addDisposableDomListener(r,"mousedown",function(t){if(t.preventDefault(),e.focus(),e.mouseEvents&&!e._selectionService.shouldForceSelection(t))return i(t),n.mouseup&&e._document.addEventListener("mouseup",n.mouseup),n.mousedrag&&e._document.addEventListener("mousemove",n.mousedrag),e.cancel(t)})),this.register(d.addDisposableDomListener(r,"wheel",function(t){if(n.wheel);else if(!e.buffer.hasScrollback){var r=e.viewport.getLinesScrolled(t);if(0===r)return;for(var i=c.C0.ESC+(e._coreService.decPrivateModes.applicationCursorKeys?"O":"[")+(t.deltaY<0?"A":"B"),o="",s=0;s=this.buffer.ybase&&(this._userScrolling=!1);var r=this.buffer.ydisp;this.buffer.ydisp=Math.max(Math.min(this.buffer.ydisp+e,this.buffer.ybase),0),r!==this.buffer.ydisp&&(t||this._onScroll.fire(this.buffer.ydisp),this.refresh(0,this.rows-1))},t.prototype.scrollPages=function(e){this.scrollLines(e*(this.rows-1))},t.prototype.scrollToTop=function(){this.scrollLines(-this.buffer.ydisp)},t.prototype.scrollToBottom=function(){this.scrollLines(this.buffer.ybase-this.buffer.ydisp)},t.prototype.scrollToLine=function(e){var t=e-this.buffer.ydisp;0!==t&&this.scrollLines(t)},t.prototype.paste=function(e){a.paste(e,this.textarea,this.bracketedPasteMode,this._coreService)},t.prototype.attachCustomKeyEventHandler=function(e){this._customKeyEventHandler=e},t.prototype.addEscHandler=function(e,t){return this._inputHandler.addEscHandler(e,t)},t.prototype.addDcsHandler=function(e,t){return this._inputHandler.addDcsHandler(e,t)},t.prototype.addCsiHandler=function(e,t){return this._inputHandler.addCsiHandler(e,t)},t.prototype.addOscHandler=function(e,t){return this._inputHandler.addOscHandler(e,t)},t.prototype.registerLinkMatcher=function(e,t,r){var i=this.linkifier.registerLinkMatcher(e,t,r);return this.refresh(0,this.rows-1),i},t.prototype.deregisterLinkMatcher=function(e){this.linkifier.deregisterLinkMatcher(e)&&this.refresh(0,this.rows-1)},t.prototype.registerCharacterJoiner=function(e){var t=this._renderService.registerCharacterJoiner(e);return this.refresh(0,this.rows-1),t},t.prototype.deregisterCharacterJoiner=function(e){this._renderService.deregisterCharacterJoiner(e)&&this.refresh(0,this.rows-1)},Object.defineProperty(t.prototype,"markers",{get:function(){return this.buffer.markers},enumerable:!0,configurable:!0}),t.prototype.addMarker=function(e){if(this.buffer===this.buffers.normal)return this.buffer.addMarker(this.buffer.ybase+this.buffer.y+e)},t.prototype.hasSelection=function(){return!!this._selectionService&&this._selectionService.hasSelection},t.prototype.select=function(e,t,r){this._selectionService.setSelection(e,t,r)},t.prototype.getSelection=function(){return this._selectionService?this._selectionService.selectionText:""},t.prototype.getSelectionPosition=function(){if(this._selectionService.hasSelection)return{startColumn:this._selectionService.selectionStart[0],startRow:this._selectionService.selectionStart[1],endColumn:this._selectionService.selectionEnd[0],endRow:this._selectionService.selectionEnd[1]}},t.prototype.clearSelection=function(){var e;null===(e=this._selectionService)||void 0===e||e.clearSelection()},t.prototype.selectAll=function(){var e;null===(e=this._selectionService)||void 0===e||e.selectAll()},t.prototype.selectLines=function(e,t){var r;null===(r=this._selectionService)||void 0===r||r.selectLines(e,t)},t.prototype._keyDown=function(e){if(this._keyDownHandled=!1,this._customKeyEventHandler&&!1===this._customKeyEventHandler(e))return!1;if(!this._compositionHelper.keydown(e))return this.buffer.ybase!==this.buffer.ydisp&&this.scrollToBottom(),!1;var t=m.evaluateKeyboardEvent(e,this._coreService.decPrivateModes.applicationCursorKeys,this.browser.isMac,this.options.macOptionIsMeta);if(this.updateCursorStyle(e),3===t.type||2===t.type){var r=this.rows-1;return this.scrollLines(2===t.type?-r:r),this.cancel(e,!0)}return 1===t.type&&this.selectAll(),!!this._isThirdLevelShift(this.browser,e)||(t.cancel&&this.cancel(e,!0),!t.key||(t.key!==c.C0.ETX&&t.key!==c.C0.CR||(this.textarea.value=""),this._onKey.fire({key:t.key,domEvent:e}),this.showCursor(),this._coreService.triggerDataEvent(t.key,!0),this.optionsService.options.screenReaderMode?void(this._keyDownHandled=!0):this.cancel(e,!0)))},t.prototype._isThirdLevelShift=function(e,t){var r=e.isMac&&!this.options.macOptionIsMeta&&t.altKey&&!t.ctrlKey&&!t.metaKey||e.isWindows&&t.altKey&&t.ctrlKey&&!t.metaKey;return"keypress"===t.type?r:r&&(!t.keyCode||t.keyCode>47)},t.prototype.setgLevel=function(e){this.glevel=e,this.charset=this.charsets[e]},t.prototype.setgCharset=function(e,t){this.charsets[e]=t,this.glevel===e&&(this.charset=t)},t.prototype._keyUp=function(e){this._customKeyEventHandler&&!1===this._customKeyEventHandler(e)||(function(e){return 16===e.keyCode||17===e.keyCode||18===e.keyCode}(e)||this.focus(),this.updateCursorStyle(e))},t.prototype._keyPress=function(e){var t;if(this._keyDownHandled)return!1;if(this._customKeyEventHandler&&!1===this._customKeyEventHandler(e))return!1;if(this.cancel(e),e.charCode)t=e.charCode;else if(null===e.which||void 0===e.which)t=e.keyCode;else{if(0===e.which||0===e.charCode)return!1;t=e.which}return!(!t||(e.altKey||e.ctrlKey||e.metaKey)&&!this._isThirdLevelShift(this.browser,e))&&(t=String.fromCharCode(t),this._onKey.fire({key:t,domEvent:e}),this.showCursor(),this._coreService.triggerDataEvent(t,!0),!0)},t.prototype.bell=function(){var e=this;this._soundBell()&&this._soundService.playBellSound(),this._visualBell()&&(this.element.classList.add("visual-bell-active"),clearTimeout(this._visualBellTimer),this._visualBellTimer=window.setTimeout(function(){e.element.classList.remove("visual-bell-active")},200))},t.prototype.resize=function(e,t){var r;isNaN(e)||isNaN(t)||(e!==this.cols||t!==this.rows?(e=0;a--)(n=e[a])&&(s=(o<3?n(s):o>3?n(t,r,s):n(t,r))||s);return o>3&&s&&Object.defineProperty(t,r,s),s},n=this&&this.__param||function(e,t){return function(r,i){t(r,i,e)}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(4),s=r(0),a=function(){function e(e,t,r,i,n,o){this._textarea=e,this._compositionView=t,this._bufferService=r,this._optionsService=i,this._charSizeService=n,this._coreService=o,this._isComposing=!1,this._isSendingComposition=!1,this._compositionPosition={start:0,end:0}}return e.prototype.compositionstart=function(){this._isComposing=!0,this._compositionPosition.start=this._textarea.value.length,this._compositionView.textContent="",this._compositionView.classList.add("active")},e.prototype.compositionupdate=function(e){var t=this;this._compositionView.textContent=e.data,this.updateCompositionElements(),setTimeout(function(){t._compositionPosition.end=t._textarea.value.length},0)},e.prototype.compositionend=function(){this._finalizeComposition(!0)},e.prototype.keydown=function(e){if(this._isComposing||this._isSendingComposition){if(229===e.keyCode)return!1;if(16===e.keyCode||17===e.keyCode||18===e.keyCode)return!1;this._finalizeComposition(!1)}return 229!==e.keyCode||(this._handleAnyTextareaChanges(),!1)},e.prototype._finalizeComposition=function(e){var t=this;if(this._compositionView.classList.remove("active"),this._isComposing=!1,this._clearTextareaPosition(),e){var r={start:this._compositionPosition.start,end:this._compositionPosition.end};this._isSendingComposition=!0,setTimeout(function(){if(t._isSendingComposition){t._isSendingComposition=!1;var e=void 0;e=t._isComposing?t._textarea.value.substring(r.start,r.end):t._textarea.value.substring(r.start),t._coreService.triggerDataEvent(e,!0)}},0)}else{this._isSendingComposition=!1;var i=this._textarea.value.substring(this._compositionPosition.start,this._compositionPosition.end);this._coreService.triggerDataEvent(i,!0)}},e.prototype._handleAnyTextareaChanges=function(){var e=this,t=this._textarea.value;setTimeout(function(){if(!e._isComposing){var r=e._textarea.value.replace(t,"");r.length>0&&e._coreService.triggerDataEvent(r,!0)}},0)},e.prototype.updateCompositionElements=function(e){var t=this;if(this._isComposing){if(this._bufferService.buffer.isCursorInViewport){var r=Math.ceil(this._charSizeService.height*this._optionsService.options.lineHeight),i=this._bufferService.buffer.y*r,n=this._bufferService.buffer.x*this._charSizeService.width;this._compositionView.style.left=n+"px",this._compositionView.style.top=i+"px",this._compositionView.style.height=r+"px",this._compositionView.style.lineHeight=r+"px",this._compositionView.style.fontFamily=this._optionsService.options.fontFamily,this._compositionView.style.fontSize=this._optionsService.options.fontSize+"px";var o=this._compositionView.getBoundingClientRect();this._textarea.style.left=n+"px",this._textarea.style.top=i+"px",this._textarea.style.width=o.width+"px",this._textarea.style.height=o.height+"px",this._textarea.style.lineHeight=o.height+"px"}e||setTimeout(function(){return t.updateCompositionElements(!0)},0)}},e.prototype._clearTextareaPosition=function(){this._textarea.style.left="",this._textarea.style.top=""},e=i([n(2,s.IBufferService),n(3,s.IOptionsService),n(4,o.ICharSizeService),n(5,s.ICoreService)],e)}();t.CompositionHelper=a},function(e,t,r){"use strict";var i,n=this&&this.__extends||(i=function(e,t){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])})(e,t)},function(e,t){function r(){this.constructor=e}i(e,t),e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)}),o=this&&this.__decorate||function(e,t,r,i){var n,o=arguments.length,s=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,r,i);else for(var a=e.length-1;a>=0;a--)(n=e[a])&&(s=(o<3?n(s):o>3?n(t,r,s):n(t,r))||s);return o>3&&s&&Object.defineProperty(t,r,s),s},s=this&&this.__param||function(e,t){return function(r,i){t(r,i,e)}};Object.defineProperty(t,"__esModule",{value:!0});var a=r(2),c=r(7),l=r(4),h=r(0),u=15,f=function(e){function t(t,r,i,n,o,s,a){var l=e.call(this)||this;return l._scrollLines=t,l._viewportElement=r,l._scrollArea=i,l._bufferService=n,l._optionsService=o,l._charSizeService=s,l._renderService=a,l.scrollBarWidth=0,l._currentRowHeight=0,l._lastRecordedBufferLength=0,l._lastRecordedViewportHeight=0,l._lastRecordedBufferHeight=0,l._lastTouchY=0,l._lastScrollTop=0,l._wheelPartialScroll=0,l._refreshAnimationFrame=null,l._ignoreNextScrollEvent=!1,l.scrollBarWidth=l._viewportElement.offsetWidth-l._scrollArea.offsetWidth||u,l.register(c.addDisposableDomListener(l._viewportElement,"scroll",l._onScroll.bind(l))),setTimeout(function(){return l.syncScrollArea()},0),l}return n(t,e),t.prototype.onThemeChange=function(e){this._viewportElement.style.backgroundColor=e.background.css},t.prototype._refresh=function(e){var t=this;if(e)return this._innerRefresh(),void(null!==this._refreshAnimationFrame&&cancelAnimationFrame(this._refreshAnimationFrame));null===this._refreshAnimationFrame&&(this._refreshAnimationFrame=requestAnimationFrame(function(){return t._innerRefresh()}))},t.prototype._innerRefresh=function(){if(this._charSizeService.height>0){this._currentRowHeight=this._renderService.dimensions.scaledCellHeight/window.devicePixelRatio,this._lastRecordedViewportHeight=this._viewportElement.offsetHeight;var e=Math.round(this._currentRowHeight*this._lastRecordedBufferLength)+(this._lastRecordedViewportHeight-this._renderService.dimensions.canvasHeight);this._lastRecordedBufferHeight!==e&&(this._lastRecordedBufferHeight=e,this._scrollArea.style.height=this._lastRecordedBufferHeight+"px")}var t=this._bufferService.buffer.ydisp*this._currentRowHeight;this._viewportElement.scrollTop!==t&&(this._ignoreNextScrollEvent=!0,this._viewportElement.scrollTop=t),this._refreshAnimationFrame=null},t.prototype.syncScrollArea=function(e){if(void 0===e&&(e=!1),this._lastRecordedBufferLength!==this._bufferService.buffer.lines.length)return this._lastRecordedBufferLength=this._bufferService.buffer.lines.length,void this._refresh(e);if(this._lastRecordedViewportHeight===this._renderService.dimensions.canvasHeight){var t=this._bufferService.buffer.ydisp*this._currentRowHeight;this._lastScrollTop===t&&this._lastScrollTop===this._viewportElement.scrollTop&&this._renderService.dimensions.scaledCellHeight/window.devicePixelRatio===this._currentRowHeight||this._refresh(e)}else this._refresh(e)},t.prototype._onScroll=function(e){if(this._lastScrollTop=this._viewportElement.scrollTop,this._viewportElement.offsetParent)if(this._ignoreNextScrollEvent)this._ignoreNextScrollEvent=!1;else{var t=Math.round(this._lastScrollTop/this._currentRowHeight)-this._bufferService.buffer.ydisp;this._scrollLines(t,!0)}},t.prototype._bubbleScroll=function(e,t){var r=this._viewportElement.scrollTop+this._lastRecordedViewportHeight;return!(t<0&&0!==this._viewportElement.scrollTop||t>0&&r0?1:-1),this._wheelPartialScroll%=1):e.deltaMode===WheelEvent.DOM_DELTA_PAGE&&(t*=this._bufferService.rows),t},t.prototype._applyScrollModifier=function(e,t){var r=this._optionsService.options.fastScrollModifier;return"alt"===r&&t.altKey||"ctrl"===r&&t.ctrlKey||"shift"===r&&t.shiftKey?e*this._optionsService.options.fastScrollSensitivity*this._optionsService.options.scrollSensitivity:e*this._optionsService.options.scrollSensitivity},t.prototype.onTouchStart=function(e){this._lastTouchY=e.touches[0].pageY},t.prototype.onTouchMove=function(e){var t=this._lastTouchY-e.touches[0].pageY;return this._lastTouchY=e.touches[0].pageY,0!==t&&(this._viewportElement.scrollTop+=t,this._bubbleScroll(e,t))},t=o([s(3,h.IBufferService),s(4,h.IOptionsService),s(5,l.ICharSizeService),s(6,l.IRenderService)],t)}(a.Disposable);t.Viewport=f},function(e,t,r){"use strict";function i(e){return e.replace(/\r?\n/g,"\r")}function n(e,t){return t?"[200~"+e+"[201~":e}function o(e,t,r,o){e=n(e=i(e),r),o.triggerDataEvent(e,!0),t.value=""}function s(e,t,r){var i=r.getBoundingClientRect(),n=e.clientX-i.left-10,o=e.clientY-i.top-10;t.style.position="absolute",t.style.width="20px",t.style.height="20px",t.style.left=n+"px",t.style.top=o+"px",t.style.zIndex="1000",t.focus(),setTimeout(function(){t.style.position="",t.style.width="",t.style.height="",t.style.left="",t.style.top="",t.style.zIndex=""},200)}Object.defineProperty(t,"__esModule",{value:!0}),t.prepareTextForTerminal=i,t.bracketTextForPaste=n,t.copyHandler=function(e,t){e.clipboardData&&e.clipboardData.setData("text/plain",t.selectionText),e.preventDefault()},t.handlePasteEvent=function(e,t,r,i){e.stopPropagation(),e.clipboardData&&o(e.clipboardData.getData("text/plain"),t,r,i)},t.paste=o,t.moveTextAreaUnderMouseCursor=s,t.rightClickHandler=function(e,t,r,i,n){s(e,t,r),n&&!i.isClickInSelection(e)&&i.selectWordAtCursor(e),t.value=i.selectionText,t.select()}},function(e,t,r){"use strict";var i,n=this&&this.__extends||(i=function(e,t){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])})(e,t)},function(e,t){function r(){this.constructor=e}i(e,t),e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)});Object.defineProperty(t,"__esModule",{value:!0});var o=r(12),s=r(18),a=r(19),c=r(39),l=r(2),h=r(15),u=r(8),f=r(16),_=r(1),d=r(3),p=r(5),v=r(6),g=r(21),y=r(23),b={"(":0,")":1,"*":2,"+":3,"-":1,".":2},m=function(){function e(e,t,r,i){this._bufferService=e,this._coreService=t,this._logService=r,this._optionsService=i,this._data=new Uint32Array(0)}return e.prototype.hook=function(e){this._data=new Uint32Array(0)},e.prototype.put=function(e,t,r){this._data=h.concat(this._data,e.subarray(t,r))},e.prototype.unhook=function(e){if(e){var t=u.utf32ToString(this._data);switch(this._data=new Uint32Array(0),t){case'"q':return this._coreService.triggerDataEvent(o.C0.ESC+'P1$r0"q'+o.C0.ESC+"\\");case'"p':return this._coreService.triggerDataEvent(o.C0.ESC+'P1$r61"p'+o.C0.ESC+"\\");case"r":var r=this._bufferService.buffer.scrollTop+1+";"+(this._bufferService.buffer.scrollBottom+1)+"r";return this._coreService.triggerDataEvent(o.C0.ESC+"P1$r"+r+o.C0.ESC+"\\");case"m":return this._coreService.triggerDataEvent(o.C0.ESC+"P1$r0m"+o.C0.ESC+"\\");case" q":var i={block:2,underline:4,bar:6}[this._optionsService.options.cursorStyle];return i-=this._optionsService.options.cursorBlink?1:0,this._coreService.triggerDataEvent(o.C0.ESC+"P1$r"+i+" q"+o.C0.ESC+"\\");default:this._logService.debug("Unknown DCS $q %s",t),this._coreService.triggerDataEvent(o.C0.ESC+"P0$r"+o.C0.ESC+"\\")}}else this._data=new Uint32Array(0)},e}(),C=function(e){function t(t,r,i,n,a,l,h,f){void 0===f&&(f=new c.EscapeSequenceParser);var d=e.call(this)||this;d._terminal=t,d._bufferService=r,d._coreService=i,d._dirtyRowService=n,d._logService=a,d._optionsService=l,d._coreMouseService=h,d._parser=f,d._parseBuffer=new Uint32Array(4096),d._stringDecoder=new u.StringToUtf32,d._utf8Decoder=new u.Utf8ToUtf32,d._workCell=new p.CellData,d._onCursorMove=new _.EventEmitter,d._onLineFeed=new _.EventEmitter,d._onScroll=new _.EventEmitter,d.register(d._parser),d._parser.setCsiHandlerFallback(function(e,t){d._logService.debug("Unknown CSI code: ",{identifier:d._parser.identToString(e),params:t.toArray()})}),d._parser.setEscHandlerFallback(function(e){d._logService.debug("Unknown ESC code: ",{identifier:d._parser.identToString(e)})}),d._parser.setExecuteHandlerFallback(function(e){d._logService.debug("Unknown EXECUTE code: ",{code:e})}),d._parser.setOscHandlerFallback(function(e,t,r){d._logService.debug("Unknown OSC code: ",{identifier:e,action:t,data:r})}),d._parser.setDcsHandlerFallback(function(e,t,r){"HOOK"===t&&(r=r.toArray()),d._logService.debug("Unknown DCS code: ",{identifier:d._parser.identToString(e),action:t,payload:r})}),d._parser.setPrintHandler(function(e,t,r){return d.print(e,t,r)}),d._parser.setCsiHandler({final:"@"},function(e){return d.insertChars(e)}),d._parser.setCsiHandler({intermediates:" ",final:"@"},function(e){return d.scrollLeft(e)}),d._parser.setCsiHandler({final:"A"},function(e){return d.cursorUp(e)}),d._parser.setCsiHandler({intermediates:" ",final:"A"},function(e){return d.scrollRight(e)}),d._parser.setCsiHandler({final:"B"},function(e){return d.cursorDown(e)}),d._parser.setCsiHandler({final:"C"},function(e){return d.cursorForward(e)}),d._parser.setCsiHandler({final:"D"},function(e){return d.cursorBackward(e)}),d._parser.setCsiHandler({final:"E"},function(e){return d.cursorNextLine(e)}),d._parser.setCsiHandler({final:"F"},function(e){return d.cursorPrecedingLine(e)}),d._parser.setCsiHandler({final:"G"},function(e){return d.cursorCharAbsolute(e)}),d._parser.setCsiHandler({final:"H"},function(e){return d.cursorPosition(e)}),d._parser.setCsiHandler({final:"I"},function(e){return d.cursorForwardTab(e)}),d._parser.setCsiHandler({final:"J"},function(e){return d.eraseInDisplay(e)}),d._parser.setCsiHandler({prefix:"?",final:"J"},function(e){return d.eraseInDisplay(e)}),d._parser.setCsiHandler({final:"K"},function(e){return d.eraseInLine(e)}),d._parser.setCsiHandler({prefix:"?",final:"K"},function(e){return d.eraseInLine(e)}),d._parser.setCsiHandler({final:"L"},function(e){return d.insertLines(e)}),d._parser.setCsiHandler({final:"M"},function(e){return d.deleteLines(e)}),d._parser.setCsiHandler({final:"P"},function(e){return d.deleteChars(e)}),d._parser.setCsiHandler({final:"S"},function(e){return d.scrollUp(e)}),d._parser.setCsiHandler({final:"T"},function(e){return d.scrollDown(e)}),d._parser.setCsiHandler({final:"X"},function(e){return d.eraseChars(e)}),d._parser.setCsiHandler({final:"Z"},function(e){return d.cursorBackwardTab(e)}),d._parser.setCsiHandler({final:"`"},function(e){return d.charPosAbsolute(e)}),d._parser.setCsiHandler({final:"a"},function(e){return d.hPositionRelative(e)}),d._parser.setCsiHandler({final:"b"},function(e){return d.repeatPrecedingCharacter(e)}),d._parser.setCsiHandler({final:"c"},function(e){return d.sendDeviceAttributesPrimary(e)}),d._parser.setCsiHandler({prefix:">",final:"c"},function(e){return d.sendDeviceAttributesSecondary(e)}),d._parser.setCsiHandler({final:"d"},function(e){return d.linePosAbsolute(e)}),d._parser.setCsiHandler({final:"e"},function(e){return d.vPositionRelative(e)}),d._parser.setCsiHandler({final:"f"},function(e){return d.hVPosition(e)}),d._parser.setCsiHandler({final:"g"},function(e){return d.tabClear(e)}),d._parser.setCsiHandler({final:"h"},function(e){return d.setMode(e)}),d._parser.setCsiHandler({prefix:"?",final:"h"},function(e){return d.setModePrivate(e)}),d._parser.setCsiHandler({final:"l"},function(e){return d.resetMode(e)}),d._parser.setCsiHandler({prefix:"?",final:"l"},function(e){return d.resetModePrivate(e)}),d._parser.setCsiHandler({final:"m"},function(e){return d.charAttributes(e)}),d._parser.setCsiHandler({final:"n"},function(e){return d.deviceStatus(e)}),d._parser.setCsiHandler({prefix:"?",final:"n"},function(e){return d.deviceStatusPrivate(e)}),d._parser.setCsiHandler({intermediates:"!",final:"p"},function(e){return d.softReset(e)}),d._parser.setCsiHandler({intermediates:" ",final:"q"},function(e){return d.setCursorStyle(e)}),d._parser.setCsiHandler({final:"r"},function(e){return d.setScrollRegion(e)}),d._parser.setCsiHandler({final:"s"},function(e){return d.saveCursor(e)}),d._parser.setCsiHandler({final:"u"},function(e){return d.restoreCursor(e)}),d._parser.setCsiHandler({intermediates:"'",final:"}"},function(e){return d.insertColumns(e)}),d._parser.setCsiHandler({intermediates:"'",final:"~"},function(e){return d.deleteColumns(e)}),d._parser.setExecuteHandler(o.C0.BEL,function(){return d.bell()}),d._parser.setExecuteHandler(o.C0.LF,function(){return d.lineFeed()}),d._parser.setExecuteHandler(o.C0.VT,function(){return d.lineFeed()}),d._parser.setExecuteHandler(o.C0.FF,function(){return d.lineFeed()}),d._parser.setExecuteHandler(o.C0.CR,function(){return d.carriageReturn()}),d._parser.setExecuteHandler(o.C0.BS,function(){return d.backspace()}),d._parser.setExecuteHandler(o.C0.HT,function(){return d.tab()}),d._parser.setExecuteHandler(o.C0.SO,function(){return d.shiftOut()}),d._parser.setExecuteHandler(o.C0.SI,function(){return d.shiftIn()}),d._parser.setExecuteHandler(o.C1.IND,function(){return d.index()}),d._parser.setExecuteHandler(o.C1.NEL,function(){return d.nextLine()}),d._parser.setExecuteHandler(o.C1.HTS,function(){return d.tabSet()}),d._parser.setOscHandler(0,new g.OscHandler(function(e){return d.setTitle(e)})),d._parser.setOscHandler(2,new g.OscHandler(function(e){return d.setTitle(e)})),d._parser.setEscHandler({final:"7"},function(){return d.saveCursor()}),d._parser.setEscHandler({final:"8"},function(){return d.restoreCursor()}),d._parser.setEscHandler({final:"D"},function(){return d.index()}),d._parser.setEscHandler({final:"E"},function(){return d.nextLine()}),d._parser.setEscHandler({final:"H"},function(){return d.tabSet()}),d._parser.setEscHandler({final:"M"},function(){return d.reverseIndex()}),d._parser.setEscHandler({final:"="},function(){return d.keypadApplicationMode()}),d._parser.setEscHandler({final:">"},function(){return d.keypadNumericMode()}),d._parser.setEscHandler({final:"c"},function(){return d.reset()}),d._parser.setEscHandler({final:"n"},function(){return d.setgLevel(2)}),d._parser.setEscHandler({final:"o"},function(){return d.setgLevel(3)}),d._parser.setEscHandler({final:"|"},function(){return d.setgLevel(3)}),d._parser.setEscHandler({final:"}"},function(){return d.setgLevel(2)}),d._parser.setEscHandler({final:"~"},function(){return d.setgLevel(1)}),d._parser.setEscHandler({intermediates:"%",final:"@"},function(){return d.selectDefaultCharset()}),d._parser.setEscHandler({intermediates:"%",final:"G"},function(){return d.selectDefaultCharset()});var v=function(e){y._parser.setEscHandler({intermediates:"(",final:e},function(){return d.selectCharset("("+e)}),y._parser.setEscHandler({intermediates:")",final:e},function(){return d.selectCharset(")"+e)}),y._parser.setEscHandler({intermediates:"*",final:e},function(){return d.selectCharset("*"+e)}),y._parser.setEscHandler({intermediates:"+",final:e},function(){return d.selectCharset("+"+e)}),y._parser.setEscHandler({intermediates:"-",final:e},function(){return d.selectCharset("-"+e)}),y._parser.setEscHandler({intermediates:".",final:e},function(){return d.selectCharset("."+e)}),y._parser.setEscHandler({intermediates:"/",final:e},function(){return d.selectCharset("/"+e)})},y=this;for(var b in s.CHARSETS)v(b);return d._parser.setEscHandler({intermediates:"#",final:"8"},function(){return d.screenAlignmentPattern()}),d._parser.setErrorHandler(function(e){return d._logService.error("Parsing error: ",e),e}),d._parser.setDcsHandler({intermediates:"$",final:"q"},new m(d._bufferService,d._coreService,d._logService,d._optionsService)),d}return n(t,e),Object.defineProperty(t.prototype,"onCursorMove",{get:function(){return this._onCursorMove.event},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"onLineFeed",{get:function(){return this._onLineFeed.event},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"onScroll",{get:function(){return this._onScroll.event},enumerable:!0,configurable:!0}),t.prototype.dispose=function(){e.prototype.dispose.call(this)},t.prototype.parse=function(e){var t=this._bufferService.buffer,r=t.x,i=t.y;if(this._logService.debug("parsing data",e),this._parseBuffer.length131072)for(var n=0;n=l)if(h)o.x=0,o.y++,o.y===o.scrollBottom+1?(o.y--,this._terminal.scroll(!0)):(o.y>=this._bufferService.rows&&(o.y=this._bufferService.rows-1),o.lines.get(o.y).isWrapped=!0),p=o.lines.get(o.y+o.ybase);else if(o.x=l-1,2===n)continue;if(f&&(p.insertCells(o.x,n,o.getNullCell(_)),2===p.getWidth(l-1)&&p.setCellFromCodePoint(l-1,d.NULL_CELL_CODE,d.NULL_CELL_WIDTH,_.fg,_.bg)),p.setCellFromCodePoint(o.x++,i,n,_.fg,_.bg),n>0)for(;--n;)p.setCellFromCodePoint(o.x++,0,0,_.fg,_.bg)}else p.getWidth(o.x-1)?p.addCodepointToCell(o.x-1,i):p.addCodepointToCell(o.x-2,i)}r&&(p.loadCell(o.x-1,this._workCell),2===this._workCell.getWidth()||this._workCell.getCode()>65535?this._parser.precedingCodepoint=0:this._workCell.isCombined()?this._parser.precedingCodepoint=this._workCell.getChars().charCodeAt(0):this._parser.precedingCodepoint=this._workCell.content),this._dirtyRowService.markDirty(o.y)},t.prototype.addCsiHandler=function(e,t){return this._parser.addCsiHandler(e,t)},t.prototype.addDcsHandler=function(e,t){return this._parser.addDcsHandler(e,new y.DcsHandler(t))},t.prototype.addEscHandler=function(e,t){return this._parser.addEscHandler(e,t)},t.prototype.addOscHandler=function(e,t){return this._parser.addOscHandler(e,new g.OscHandler(t))},t.prototype.bell=function(){this._terminal.bell()},t.prototype.lineFeed=function(){var e=this._bufferService.buffer;this._dirtyRowService.markDirty(e.y),this._optionsService.options.convertEol&&(e.x=0),e.y++,e.y===e.scrollBottom+1?(e.y--,this._terminal.scroll()):e.y>=this._bufferService.rows&&(e.y=this._bufferService.rows-1),e.x>=this._bufferService.cols&&e.x--,this._dirtyRowService.markDirty(e.y),this._onLineFeed.fire()},t.prototype.carriageReturn=function(){this._bufferService.buffer.x=0},t.prototype.backspace=function(){this._restrictCursor(),this._bufferService.buffer.x>0&&this._bufferService.buffer.x--},t.prototype.tab=function(){if(!(this._bufferService.buffer.x>=this._bufferService.cols)){var e=this._bufferService.buffer.x;this._bufferService.buffer.x=this._bufferService.buffer.nextStop(),this._optionsService.options.screenReaderMode&&this._terminal.onA11yTabEmitter.fire(this._bufferService.buffer.x-e)}},t.prototype.shiftOut=function(){this._terminal.setgLevel(1)},t.prototype.shiftIn=function(){this._terminal.setgLevel(0)},t.prototype._restrictCursor=function(){this._bufferService.buffer.x=Math.min(this._bufferService.cols-1,Math.max(0,this._bufferService.buffer.x)),this._bufferService.buffer.y=this._terminal.originMode?Math.min(this._bufferService.buffer.scrollBottom,Math.max(this._bufferService.buffer.scrollTop,this._bufferService.buffer.y)):Math.min(this._bufferService.rows-1,Math.max(0,this._bufferService.buffer.y)),this._dirtyRowService.markDirty(this._bufferService.buffer.y)},t.prototype._setCursor=function(e,t){this._dirtyRowService.markDirty(this._bufferService.buffer.y),this._terminal.originMode?(this._bufferService.buffer.x=e,this._bufferService.buffer.y=this._bufferService.buffer.scrollTop+t):(this._bufferService.buffer.x=e,this._bufferService.buffer.y=t),this._restrictCursor(),this._dirtyRowService.markDirty(this._bufferService.buffer.y)},t.prototype._moveCursor=function(e,t){this._restrictCursor(),this._setCursor(this._bufferService.buffer.x+e,this._bufferService.buffer.y+t)},t.prototype.cursorUp=function(e){var t=this._bufferService.buffer.y-this._bufferService.buffer.scrollTop;t>=0?this._moveCursor(0,-Math.min(t,e.params[0]||1)):this._moveCursor(0,-(e.params[0]||1))},t.prototype.cursorDown=function(e){var t=this._bufferService.buffer.scrollBottom-this._bufferService.buffer.y;t>=0?this._moveCursor(0,Math.min(t,e.params[0]||1)):this._moveCursor(0,e.params[0]||1)},t.prototype.cursorForward=function(e){this._moveCursor(e.params[0]||1,0)},t.prototype.cursorBackward=function(e){this._moveCursor(-(e.params[0]||1),0)},t.prototype.cursorNextLine=function(e){this.cursorDown(e),this._bufferService.buffer.x=0},t.prototype.cursorPrecedingLine=function(e){this.cursorUp(e),this._bufferService.buffer.x=0},t.prototype.cursorCharAbsolute=function(e){this._setCursor((e.params[0]||1)-1,this._bufferService.buffer.y)},t.prototype.cursorPosition=function(e){this._setCursor(e.length>=2?(e.params[1]||1)-1:0,(e.params[0]||1)-1)},t.prototype.charPosAbsolute=function(e){this._setCursor((e.params[0]||1)-1,this._bufferService.buffer.y)},t.prototype.hPositionRelative=function(e){this._moveCursor(e.params[0]||1,0)},t.prototype.linePosAbsolute=function(e){this._setCursor(this._bufferService.buffer.x,(e.params[0]||1)-1)},t.prototype.vPositionRelative=function(e){this._moveCursor(0,e.params[0]||1)},t.prototype.hVPosition=function(e){this.cursorPosition(e)},t.prototype.tabClear=function(e){var t=e.params[0];0===t?delete this._bufferService.buffer.tabs[this._bufferService.buffer.x]:3===t&&(this._bufferService.buffer.tabs={})},t.prototype.cursorForwardTab=function(e){if(!(this._bufferService.buffer.x>=this._bufferService.cols))for(var t=e.params[0]||1;t--;)this._bufferService.buffer.x=this._bufferService.buffer.nextStop()},t.prototype.cursorBackwardTab=function(e){if(!(this._bufferService.buffer.x>=this._bufferService.cols))for(var t=e.params[0]||1,r=this._bufferService.buffer;t--;)r.x=r.prevStop()},t.prototype._eraseInBufferLine=function(e,t,r,i){void 0===i&&(i=!1);var n=this._bufferService.buffer.lines.get(this._bufferService.buffer.ybase+e);n.replaceCells(t,r,this._bufferService.buffer.getNullCell(this._terminal.eraseAttrData())),i&&(n.isWrapped=!1)},t.prototype._resetBufferLine=function(e){var t=this._bufferService.buffer.lines.get(this._bufferService.buffer.ybase+e);t.fill(this._bufferService.buffer.getNullCell(this._terminal.eraseAttrData())),t.isWrapped=!1},t.prototype.eraseInDisplay=function(e){var t;switch(this._restrictCursor(),e.params[0]){case 0:for(t=this._bufferService.buffer.y,this._dirtyRowService.markDirty(t),this._eraseInBufferLine(t++,this._bufferService.buffer.x,this._bufferService.cols,0===this._bufferService.buffer.x);t=this._bufferService.cols&&(this._bufferService.buffer.lines.get(t+1).isWrapped=!1);t--;)this._resetBufferLine(t);this._dirtyRowService.markDirty(0);break;case 2:for(t=this._bufferService.rows,this._dirtyRowService.markDirty(t-1);t--;)this._resetBufferLine(t);this._dirtyRowService.markDirty(0);break;case 3:var r=this._bufferService.buffer.lines.length-this._bufferService.rows;r>0&&(this._bufferService.buffer.lines.trimStart(r),this._bufferService.buffer.ybase=Math.max(this._bufferService.buffer.ybase-r,0),this._bufferService.buffer.ydisp=Math.max(this._bufferService.buffer.ydisp-r,0),this._onScroll.fire(0))}},t.prototype.eraseInLine=function(e){switch(this._restrictCursor(),e.params[0]){case 0:this._eraseInBufferLine(this._bufferService.buffer.y,this._bufferService.buffer.x,this._bufferService.cols);break;case 1:this._eraseInBufferLine(this._bufferService.buffer.y,0,this._bufferService.buffer.x+1);break;case 2:this._eraseInBufferLine(this._bufferService.buffer.y,0,this._bufferService.cols)}this._dirtyRowService.markDirty(this._bufferService.buffer.y)},t.prototype.insertLines=function(e){this._restrictCursor();var t=e.params[0]||1,r=this._bufferService.buffer;if(!(r.y>r.scrollBottom||r.yr.scrollBottom||r.yt.scrollBottom||t.yt.scrollBottom||t.yt.scrollBottom||t.yt.scrollBottom||t.y0||(this._terminal.is("xterm")||this._terminal.is("rxvt-unicode")||this._terminal.is("screen")?this._coreService.triggerDataEvent(o.C0.ESC+"[?1;2c"):this._terminal.is("linux")&&this._coreService.triggerDataEvent(o.C0.ESC+"[?6c"))},t.prototype.sendDeviceAttributesSecondary=function(e){e.params[0]>0||(this._terminal.is("xterm")?this._coreService.triggerDataEvent(o.C0.ESC+"[>0;276;0c"):this._terminal.is("rxvt-unicode")?this._coreService.triggerDataEvent(o.C0.ESC+"[>85;95;0c"):this._terminal.is("linux")?this._coreService.triggerDataEvent(e.params[0]+"c"):this._terminal.is("screen")&&this._coreService.triggerDataEvent(o.C0.ESC+"[>83;40003;0c"))},t.prototype.setMode=function(e){for(var t=0;t=2||2===i[1]&&o+n>=5)break;i[1]&&(n=1)}while(++o+t=30&&t<=37?(i.fg&=-50331904,i.fg|=16777216|t-30):t>=40&&t<=47?(i.bg&=-50331904,i.bg|=16777216|t-40):t>=90&&t<=97?(i.fg&=-50331904,i.fg|=16777224|t-90):t>=100&&t<=107?(i.bg&=-50331904,i.bg|=16777224|t-100):0===t?(i.fg=f.DEFAULT_ATTR_DATA.fg,i.bg=f.DEFAULT_ATTR_DATA.bg):1===t?i.fg|=134217728:3===t?i.bg|=67108864:4===t?i.fg|=268435456:5===t?i.fg|=536870912:7===t?i.fg|=67108864:8===t?i.fg|=1073741824:2===t?i.bg|=134217728:22===t?(i.fg&=-134217729,i.bg&=-134217729):23===t?i.bg&=-67108865:24===t?i.fg&=-268435457:25===t?i.fg&=-536870913:27===t?i.fg&=-67108865:28===t?i.fg&=-1073741825:39===t?(i.fg&=-67108864,i.fg|=16777215&f.DEFAULT_ATTR_DATA.fg):49===t?(i.bg&=-67108864,i.bg|=16777215&f.DEFAULT_ATTR_DATA.bg):38===t||48===t?n+=this._extractColor(e,n,i):100===t?(i.fg&=-67108864,i.fg|=16777215&f.DEFAULT_ATTR_DATA.fg,i.bg&=-67108864,i.bg|=16777215&f.DEFAULT_ATTR_DATA.bg):this._logService.debug("Unknown SGR attribute: %d.",t)},t.prototype.deviceStatus=function(e){switch(e.params[0]){case 5:this._coreService.triggerDataEvent(o.C0.ESC+"[0n");break;case 6:var t=this._bufferService.buffer.y+1,r=this._bufferService.buffer.x+1;this._coreService.triggerDataEvent(o.C0.ESC+"["+t+";"+r+"R")}},t.prototype.deviceStatusPrivate=function(e){switch(e.params[0]){case 6:var t=this._bufferService.buffer.y+1,r=this._bufferService.buffer.x+1;this._coreService.triggerDataEvent(o.C0.ESC+"[?"+t+";"+r+"R")}},t.prototype.softReset=function(e){this._coreService.isCursorHidden=!1,this._terminal.insertMode=!1,this._terminal.originMode=!1,this._terminal.wraparoundMode=!0,this._terminal.applicationKeypad=!1,this._terminal.viewport&&this._terminal.viewport.syncScrollArea(),this._coreService.decPrivateModes.applicationCursorKeys=!1,this._bufferService.buffer.scrollTop=0,this._bufferService.buffer.scrollBottom=this._bufferService.rows-1,this._terminal.curAttrData=f.DEFAULT_ATTR_DATA.clone(),this._bufferService.buffer.x=this._bufferService.buffer.y=0,this._terminal.charset=null,this._terminal.glevel=0,this._terminal.charsets=[null]},t.prototype.setCursorStyle=function(e){var t=e.params[0]||1;switch(t){case 1:case 2:this._optionsService.options.cursorStyle="block";break;case 3:case 4:this._optionsService.options.cursorStyle="underline";break;case 5:case 6:this._optionsService.options.cursorStyle="bar"}var r=t%2==1;this._optionsService.options.cursorBlink=r},t.prototype.setScrollRegion=function(e){var t,r=e.params[0]||1;(e.length<2||(t=e.params[1])>this._bufferService.rows||0===t)&&(t=this._bufferService.rows),t>r&&(this._bufferService.buffer.scrollTop=r-1,this._bufferService.buffer.scrollBottom=t-1,this._setCursor(0,0))},t.prototype.saveCursor=function(e){this._bufferService.buffer.savedX=this._bufferService.buffer.x,this._bufferService.buffer.savedY=this._bufferService.buffer.ybase+this._bufferService.buffer.y,this._bufferService.buffer.savedCurAttrData.fg=this._terminal.curAttrData.fg,this._bufferService.buffer.savedCurAttrData.bg=this._terminal.curAttrData.bg,this._bufferService.buffer.savedCharset=this._terminal.charset},t.prototype.restoreCursor=function(e){this._bufferService.buffer.x=this._bufferService.buffer.savedX||0,this._bufferService.buffer.y=Math.max(this._bufferService.buffer.savedY-this._bufferService.buffer.ybase,0),this._terminal.curAttrData.fg=this._bufferService.buffer.savedCurAttrData.fg,this._terminal.curAttrData.bg=this._bufferService.buffer.savedCurAttrData.bg,this._terminal.charset=this._savedCharset,this._bufferService.buffer.savedCharset&&(this._terminal.charset=this._bufferService.buffer.savedCharset),this._restrictCursor()},t.prototype.setTitle=function(e){this._terminal.handleTitle(e)},t.prototype.nextLine=function(){this._bufferService.buffer.x=0,this.index()},t.prototype.keypadApplicationMode=function(){this._logService.debug("Serial port requested application keypad."),this._terminal.applicationKeypad=!0,this._terminal.viewport&&this._terminal.viewport.syncScrollArea()},t.prototype.keypadNumericMode=function(){this._logService.debug("Switching back to normal keypad."),this._terminal.applicationKeypad=!1,this._terminal.viewport&&this._terminal.viewport.syncScrollArea()},t.prototype.selectDefaultCharset=function(){this._terminal.setgLevel(0),this._terminal.setgCharset(0,s.DEFAULT_CHARSET)},t.prototype.selectCharset=function(e){2===e.length?"/"!==e[0]&&this._terminal.setgCharset(b[e[0]],s.CHARSETS[e[1]]||s.DEFAULT_CHARSET):this.selectDefaultCharset()},t.prototype.index=function(){this._restrictCursor();var e=this._bufferService.buffer;this._bufferService.buffer.y++,e.y===e.scrollBottom+1?(e.y--,this._terminal.scroll()):e.y>=this._bufferService.rows&&(e.y=this._bufferService.rows-1),this._restrictCursor()},t.prototype.tabSet=function(){this._bufferService.buffer.tabs[this._bufferService.buffer.x]=!0},t.prototype.reverseIndex=function(){this._restrictCursor();var e=this._bufferService.buffer;if(e.y===e.scrollTop){var t=e.scrollBottom-e.scrollTop;e.lines.shiftElements(e.y+e.ybase,t,1),e.lines.set(e.y+e.ybase,e.getBlankLine(this._terminal.eraseAttrData())),this._dirtyRowService.markRangeDirty(e.scrollTop,e.scrollBottom)}else e.y--,this._restrictCursor()},t.prototype.reset=function(){this._parser.reset(),this._terminal.reset()},t.prototype.setgLevel=function(e){this._terminal.setgLevel(e)},t.prototype.screenAlignmentPattern=function(){var e=new p.CellData;e.content=1<<22|"E".charCodeAt(0),e.fg=this._terminal.curAttrData.fg,e.bg=this._terminal.curAttrData.bg;var t=this._bufferService.buffer;this._setCursor(0,0);for(var r=0;r1)throw new Error("only one byte as prefix supported");if((r=e.prefix.charCodeAt(0))&&60>r||r>63)throw new Error("prefix must be in range 0x3c .. 0x3f")}if(e.intermediates){if(e.intermediates.length>2)throw new Error("only two bytes as intermediates are supported");for(var i=0;in||n>47)throw new Error("intermediate must be in range 0x20 .. 0x2f");r<<=8,r|=n}}if(1!==e.final.length)throw new Error("final must be a single byte");var o=e.final.charCodeAt(0);if(t[0]>o||o>t[1])throw new Error("final must be in range "+t[0]+" .. "+t[1]);return r<<=8,r|=o},r.prototype.identToString=function(e){for(var t=[];e;)t.push(String.fromCharCode(255&e)),e>>=8;return t.reverse().join("")},r.prototype.dispose=function(){this._csiHandlers=Object.create(null),this._executeHandlers=Object.create(null),this._escHandlers=Object.create(null),this._oscParser.dispose(),this._dcsParser.dispose()},r.prototype.setPrintHandler=function(e){this._printHandler=e},r.prototype.clearPrintHandler=function(){this._printHandler=this._printHandlerFb},r.prototype.addEscHandler=function(e,t){var r=this._identifier(e,[48,126]);void 0===this._escHandlers[r]&&(this._escHandlers[r]=[]);var i=this._escHandlers[r];return i.push(t),{dispose:function(){var e=i.indexOf(t);-1!==e&&i.splice(e,1)}}},r.prototype.setEscHandler=function(e,t){this._escHandlers[this._identifier(e,[48,126])]=[t]},r.prototype.clearEscHandler=function(e){this._escHandlers[this._identifier(e,[48,126])]&&delete this._escHandlers[this._identifier(e,[48,126])]},r.prototype.setEscHandlerFallback=function(e){this._escHandlerFb=e},r.prototype.setExecuteHandler=function(e,t){this._executeHandlers[e.charCodeAt(0)]=t},r.prototype.clearExecuteHandler=function(e){this._executeHandlers[e.charCodeAt(0)]&&delete this._executeHandlers[e.charCodeAt(0)]},r.prototype.setExecuteHandlerFallback=function(e){this._executeHandlerFb=e},r.prototype.addCsiHandler=function(e,t){var r=this._identifier(e);void 0===this._csiHandlers[r]&&(this._csiHandlers[r]=[]);var i=this._csiHandlers[r];return i.push(t),{dispose:function(){var e=i.indexOf(t);-1!==e&&i.splice(e,1)}}},r.prototype.setCsiHandler=function(e,t){this._csiHandlers[this._identifier(e)]=[t]},r.prototype.clearCsiHandler=function(e){this._csiHandlers[this._identifier(e)]&&delete this._csiHandlers[this._identifier(e)]},r.prototype.setCsiHandlerFallback=function(e){this._csiHandlerFb=e},r.prototype.addDcsHandler=function(e,t){return this._dcsParser.addHandler(this._identifier(e),t)},r.prototype.setDcsHandler=function(e,t){this._dcsParser.setHandler(this._identifier(e),t)},r.prototype.clearDcsHandler=function(e){this._dcsParser.clearHandler(this._identifier(e))},r.prototype.setDcsHandlerFallback=function(e){this._dcsParser.setHandlerFallback(e)},r.prototype.addOscHandler=function(e,t){return this._oscParser.addHandler(e,t)},r.prototype.setOscHandler=function(e,t){this._oscParser.setHandler(e,t)},r.prototype.clearOscHandler=function(e){this._oscParser.clearHandler(e)},r.prototype.setOscHandlerFallback=function(e){this._oscParser.setHandlerFallback(e)},r.prototype.setErrorHandler=function(e){this._errorHandler=e},r.prototype.clearErrorHandler=function(){this._errorHandler=this._errorHandlerFb},r.prototype.reset=function(){this.currentState=this.initialState,this._oscParser.reset(),this._dcsParser.reset(),this._params.reset(),this._params.addParam(0),this._collect=0,this.precedingCodepoint=0},r.prototype.parse=function(e,t){for(var r=0,i=0,n=this.currentState,o=this._oscParser,s=this._dcsParser,a=this._collect,c=this._params,l=this.TRANSITIONS.table,h=0;h>4){case 2:for(var u=h+1;;++u){if(u>=t||(r=e[u])<32||r>126&&r<160){this._printHandler(e,h,u),h=u-1;break}if(++u>=t||(r=e[u])<32||r>126&&r<160){this._printHandler(e,h,u),h=u-1;break}if(++u>=t||(r=e[u])<32||r>126&&r<160){this._printHandler(e,h,u),h=u-1;break}if(++u>=t||(r=e[u])<32||r>126&&r<160){this._printHandler(e,h,u),h=u-1;break}}break;case 3:this._executeHandlers[r]?this._executeHandlers[r]():this._executeHandlerFb(r),this.precedingCodepoint=0;break;case 0:break;case 1:if(this._errorHandler({position:h,code:r,currentState:n,collect:a,params:c,abort:!1}).abort)return;break;case 7:for(var f=this._csiHandlers[a<<8|r],_=f?f.length-1:-1;_>=0&&!1===f[_](c);_--);_<0&&this._csiHandlerFb(a<<8|r,c),this.precedingCodepoint=0;break;case 8:do{switch(r){case 59:c.addParam(0);break;case 58:c.addSubParam(-1);break;default:c.addDigit(r-48)}}while(++h47&&r<60);h--;break;case 9:a<<=8,a|=r;break;case 10:for(var d=this._escHandlers[a<<8|r],p=d?d.length-1:-1;p>=0&&!1===d[p]();p--);p<0&&this._escHandlerFb(a<<8|r),this.precedingCodepoint=0;break;case 11:c.reset(),c.addParam(0),a=0;break;case 12:s.hook(a<<8|r,c);break;case 13:for(var v=h+1;;++v)if(v>=t||24===(r=e[v])||26===r||27===r||r>127&&r<160){s.put(e,h,v),h=v-1;break}break;case 14:s.unhook(24!==r&&26!==r),27===r&&(i|=1),c.reset(),c.addParam(0),a=0,this.precedingCodepoint=0;break;case 4:o.start();break;case 5:for(var g=h+1;;g++)if(g>=t||(r=e[g])<32||r>127&&r<=159){o.put(e,h,g),h=g-1;break}break;case 6:o.end(24!==r&&26!==r),27===r&&(i|=1),c.reset(),c.addParam(0),a=0,this.precedingCodepoint=0}n=15&i}this._collect=a,this.currentState=n},r}(o.Disposable);t.EscapeSequenceParser=u},function(e,t,r){"use strict";var i,n=this&&this.__extends||(i=function(e,t){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])})(e,t)},function(e,t){function r(){this.constructor=e}i(e,t),e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)}),o=this&&this.__decorate||function(e,t,r,i){var n,o=arguments.length,s=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,r,i);else for(var a=e.length-1;a>=0;a--)(n=e[a])&&(s=(o<3?n(s):o>3?n(t,r,s):n(t,r))||s);return o>3&&s&&Object.defineProperty(t,r,s),s},s=this&&this.__param||function(e,t){return function(r,i){t(r,i,e)}};Object.defineProperty(t,"__esModule",{value:!0});var a=r(41),c=r(47),l=r(48),h=r(49),u=r(28),f=r(2),_=r(4),d=r(0),p=r(24),v=r(1),g=1,y=function(e){function t(t,r,i,n,o,s,f,_){var d=e.call(this)||this;d._colors=t,d._screenElement=r,d._linkifier=i,d._bufferService=n,d._charSizeService=o,d._optionsService=s,d.coreService=f,d.coreBrowserService=_,d._id=g++,d._onRequestRefreshRows=new v.EventEmitter;var p=d._optionsService.options.allowTransparency;return d._characterJoinerRegistry=new u.CharacterJoinerRegistry(d._bufferService),d._renderLayers=[new a.TextRenderLayer(d._screenElement,0,d._colors,d._characterJoinerRegistry,p,d._id,d._bufferService,s),new c.SelectionRenderLayer(d._screenElement,1,d._colors,d._id,d._bufferService,s),new h.LinkRenderLayer(d._screenElement,2,d._colors,d._id,d._linkifier,d._bufferService,s),new l.CursorRenderLayer(d._screenElement,3,d._colors,d._id,d._onRequestRefreshRows,d._bufferService,s,f,_)],d.dimensions={scaledCharWidth:0,scaledCharHeight:0,scaledCellWidth:0,scaledCellHeight:0,scaledCharLeft:0,scaledCharTop:0,scaledCanvasWidth:0,scaledCanvasHeight:0,canvasWidth:0,canvasHeight:0,actualCellWidth:0,actualCellHeight:0},d._devicePixelRatio=window.devicePixelRatio,d._updateDimensions(),d.onOptionsChanged(),d}return n(t,e),Object.defineProperty(t.prototype,"onRequestRefreshRows",{get:function(){return this._onRequestRefreshRows.event},enumerable:!0,configurable:!0}),t.prototype.dispose=function(){e.prototype.dispose.call(this),this._renderLayers.forEach(function(e){return e.dispose()}),p.removeTerminalFromCache(this._id)},t.prototype.onDevicePixelRatioChange=function(){this._devicePixelRatio!==window.devicePixelRatio&&(this._devicePixelRatio=window.devicePixelRatio,this.onResize(this._bufferService.cols,this._bufferService.rows))},t.prototype.setColors=function(e){var t=this;this._colors=e,this._renderLayers.forEach(function(e){e.setColors(t._colors),e.reset()})},t.prototype.onResize=function(e,t){var r=this;this._updateDimensions(),this._renderLayers.forEach(function(e){return e.resize(r.dimensions)}),this._screenElement.style.width=this.dimensions.canvasWidth+"px",this._screenElement.style.height=this.dimensions.canvasHeight+"px"},t.prototype.onCharSizeChanged=function(){this.onResize(this._bufferService.cols,this._bufferService.rows)},t.prototype.onBlur=function(){this._runOperation(function(e){return e.onBlur()})},t.prototype.onFocus=function(){this._runOperation(function(e){return e.onFocus()})},t.prototype.onSelectionChanged=function(e,t,r){void 0===r&&(r=!1),this._runOperation(function(i){return i.onSelectionChanged(e,t,r)})},t.prototype.onCursorMove=function(){this._runOperation(function(e){return e.onCursorMove()})},t.prototype.onOptionsChanged=function(){this._runOperation(function(e){return e.onOptionsChanged()})},t.prototype.clear=function(){this._runOperation(function(e){return e.reset()})},t.prototype._runOperation=function(e){this._renderLayers.forEach(function(t){return e(t)})},t.prototype.renderRows=function(e,t){this._renderLayers.forEach(function(r){return r.onGridChanged(e,t)})},t.prototype._updateDimensions=function(){this._charSizeService.hasValidSize&&(this.dimensions.scaledCharWidth=Math.floor(this._charSizeService.width*window.devicePixelRatio),this.dimensions.scaledCharHeight=Math.ceil(this._charSizeService.height*window.devicePixelRatio),this.dimensions.scaledCellHeight=Math.floor(this.dimensions.scaledCharHeight*this._optionsService.options.lineHeight),this.dimensions.scaledCharTop=1===this._optionsService.options.lineHeight?0:Math.round((this.dimensions.scaledCellHeight-this.dimensions.scaledCharHeight)/2),this.dimensions.scaledCellWidth=this.dimensions.scaledCharWidth+Math.round(this._optionsService.options.letterSpacing),this.dimensions.scaledCharLeft=Math.floor(this._optionsService.options.letterSpacing/2),this.dimensions.scaledCanvasHeight=this._bufferService.rows*this.dimensions.scaledCellHeight,this.dimensions.scaledCanvasWidth=this._bufferService.cols*this.dimensions.scaledCellWidth,this.dimensions.canvasHeight=Math.round(this.dimensions.scaledCanvasHeight/window.devicePixelRatio),this.dimensions.canvasWidth=Math.round(this.dimensions.scaledCanvasWidth/window.devicePixelRatio),this.dimensions.actualCellHeight=this.dimensions.canvasHeight/this._bufferService.rows,this.dimensions.actualCellWidth=this.dimensions.canvasWidth/this._bufferService.cols)},t.prototype.registerCharacterJoiner=function(e){return this._characterJoinerRegistry.registerCharacterJoiner(e)},t.prototype.deregisterCharacterJoiner=function(e){return this._characterJoinerRegistry.deregisterCharacterJoiner(e)},t=o([s(3,d.IBufferService),s(4,_.ICharSizeService),s(5,d.IOptionsService),s(6,d.ICoreService),s(7,_.ICoreBrowserService)],t)}(f.Disposable);t.Renderer=y},function(e,t,r){"use strict";var i,n=this&&this.__extends||(i=function(e,t){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])})(e,t)},function(e,t){function r(){this.constructor=e}i(e,t),e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)});Object.defineProperty(t,"__esModule",{value:!0});var o=r(42),s=r(13),a=r(6),c=r(3),l=r(28),h=r(5),u=function(e){function t(t,r,i,n,s,a,c,l){var u=e.call(this,t,"text",r,s,i,a,c,l)||this;return u.bufferService=c,u.optionsService=l,u._characterWidth=0,u._characterFont="",u._characterOverlapCache={},u._workCell=new h.CellData,u._state=new o.GridCache,u._characterJoinerRegistry=n,u}return n(t,e),t.prototype.resize=function(t){e.prototype.resize.call(this,t);var r=this._getFont(!1,!1);this._characterWidth===t.scaledCharWidth&&this._characterFont===r||(this._characterWidth=t.scaledCharWidth,this._characterFont=r,this._characterOverlapCache={}),this._state.clear(),this._state.resize(this._bufferService.cols,this._bufferService.rows)},t.prototype.reset=function(){this._state.clear(),this._clearAll()},t.prototype._forEachCell=function(e,t,r,i){for(var n=e;n<=t;n++)for(var o=n+this._bufferService.buffer.ydisp,s=this._bufferService.buffer.lines.get(o),a=r?r.getJoinedCharacters(o):[],h=0;h0&&h===a[0][0]){f=!0;var d=a.shift();u=new l.JoinedCellData(this._workCell,s.translateToString(!0,d[0],d[1]),d[1]-d[0]),_=d[1]-1}!f&&this._isOverlapping(u)&&_this._characterWidth;return this._ctx.restore(),this._characterOverlapCache[t]=r,r},t}(s.BaseRenderLayer);t.TextRenderLayer=u},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=function(){function e(){this.cache=[]}return e.prototype.resize=function(e,t){for(var r=0;r>>24,n=t.rgba>>>16&255,o=t.rgba>>>8&255,s=0;s=this.capacity)r=this._head,this._unlinkNode(r),delete this._map[r.key],r.key=e,r.value=t,this._map[e]=r;else{var i=this._nodePool;i.length>0?((r=i.pop()).key=e,r.value=t):r={prev:null,next:null,key:e,value:t},this._map[e]=r,this.size++}this._appendNode(r)},e}();t.LRUMap=i},function(e,t,r){"use strict";var i,n=this&&this.__extends||(i=function(e,t){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])})(e,t)},function(e,t){function r(){this.constructor=e}i(e,t),e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)});Object.defineProperty(t,"__esModule",{value:!0});var o=function(e){function t(t,r,i,n,o,s){var a=e.call(this,t,"selection",r,!0,i,n,o,s)||this;return a.bufferService=o,a.optionsService=s,a._clearState(),a}return n(t,e),t.prototype._clearState=function(){this._state={start:void 0,end:void 0,columnSelectMode:void 0,ydisp:void 0}},t.prototype.resize=function(t){e.prototype.resize.call(this,t),this._clearState()},t.prototype.reset=function(){this._state.start&&this._state.end&&(this._clearState(),this._clearAll())},t.prototype.onSelectionChanged=function(e,t,r){if(this._didStateChange(e,t,r,this._bufferService.buffer.ydisp))if(this._clearAll(),e&&t){var i=e[1]-this._bufferService.buffer.ydisp,n=t[1]-this._bufferService.buffer.ydisp,o=Math.max(i,0),s=Math.min(n,this._bufferService.rows-1);if(!(o>=this._bufferService.rows||s<0)){if(this._ctx.fillStyle=this._colors.selection.css,r){var a=e[0],c=t[0]-a,l=s-o+1;this._fillCells(a,o,c,l)}else{a=i===o?e[0]:0;var h=o===s?t[0]:this._bufferService.cols;this._fillCells(a,o,h-a,1);var u=Math.max(s-o-1,0);if(this._fillCells(0,o+1,this._bufferService.cols,u),o!==s){var f=n===s?t[0]:this._bufferService.cols;this._fillCells(0,s,f,1)}}this._state.start=[e[0],e[1]],this._state.end=[t[0],t[1]],this._state.columnSelectMode=r,this._state.ydisp=this._bufferService.buffer.ydisp}}else this._clearState()},t.prototype._didStateChange=function(e,t,r,i){return!this._areCoordinatesEqual(e,this._state.start)||!this._areCoordinatesEqual(t,this._state.end)||r!==this._state.columnSelectMode||i!==this._state.ydisp},t.prototype._areCoordinatesEqual=function(e,t){return!(!e||!t)&&(e[0]===t[0]&&e[1]===t[1])},t}(r(13).BaseRenderLayer);t.SelectionRenderLayer=o},function(e,t,r){"use strict";var i,n=this&&this.__extends||(i=function(e,t){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])})(e,t)},function(e,t){function r(){this.constructor=e}i(e,t),e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)});Object.defineProperty(t,"__esModule",{value:!0});var o=r(13),s=r(5),a=function(e){function t(t,r,i,n,o,a,c,l,h){var u=e.call(this,t,"cursor",r,!0,i,n,a,c)||this;return u._onRequestRefreshRowsEvent=o,u.bufferService=a,u.optionsService=c,u._coreService=l,u._coreBrowserService=h,u._cell=new s.CellData,u._state={x:0,y:0,isFocused:!1,style:"",width:0},u._cursorRenderers={bar:u._renderBarCursor.bind(u),block:u._renderBlockCursor.bind(u),underline:u._renderUnderlineCursor.bind(u)},u}return n(t,e),t.prototype.resize=function(t){e.prototype.resize.call(this,t),this._state={x:0,y:0,isFocused:!1,style:"",width:0}},t.prototype.reset=function(){this._clearCursor(),this._cursorBlinkStateManager&&(this._cursorBlinkStateManager.dispose(),this._cursorBlinkStateManager=void 0,this.onOptionsChanged())},t.prototype.onBlur=function(){this._cursorBlinkStateManager&&this._cursorBlinkStateManager.pause(),this._onRequestRefreshRowsEvent.fire({start:this._bufferService.buffer.y,end:this._bufferService.buffer.y})},t.prototype.onFocus=function(){this._cursorBlinkStateManager?this._cursorBlinkStateManager.resume():this._onRequestRefreshRowsEvent.fire({start:this._bufferService.buffer.y,end:this._bufferService.buffer.y})},t.prototype.onOptionsChanged=function(){var e,t=this;this._optionsService.options.cursorBlink?this._cursorBlinkStateManager||(this._cursorBlinkStateManager=new c(this._coreBrowserService.isFocused,function(){t._render(!0)})):(null===(e=this._cursorBlinkStateManager)||void 0===e||e.dispose(),this._cursorBlinkStateManager=void 0),this._onRequestRefreshRowsEvent.fire({start:this._bufferService.buffer.y,end:this._bufferService.buffer.y})},t.prototype.onCursorMove=function(){this._cursorBlinkStateManager&&this._cursorBlinkStateManager.restartBlinkAnimation()},t.prototype.onGridChanged=function(e,t){!this._cursorBlinkStateManager||this._cursorBlinkStateManager.isPaused?this._render(!1):this._cursorBlinkStateManager.restartBlinkAnimation()},t.prototype._render=function(e){if(this._coreService.isCursorInitialized&&!this._coreService.isCursorHidden){var t=this._bufferService.buffer.ybase+this._bufferService.buffer.y,r=t-this._bufferService.buffer.ydisp;if(r<0||r>=this._bufferService.rows)this._clearCursor();else if(this._bufferService.buffer.lines.get(t).loadCell(this._bufferService.buffer.x,this._cell),void 0!==this._cell.content){if(!this._coreBrowserService.isFocused){this._clearCursor(),this._ctx.save(),this._ctx.fillStyle=this._colors.cursor.css;var i=this._optionsService.options.cursorStyle;return i&&"block"!==i?this._cursorRenderers[i](this._bufferService.buffer.x,r,this._cell):this._renderBlurCursor(this._bufferService.buffer.x,r,this._cell),this._ctx.restore(),this._state.x=this._bufferService.buffer.x,this._state.y=r,this._state.isFocused=!1,this._state.style=i,void(this._state.width=this._cell.getWidth())}if(!this._cursorBlinkStateManager||this._cursorBlinkStateManager.isCursorVisible){if(this._state){if(this._state.x===this._bufferService.buffer.x&&this._state.y===r&&this._state.isFocused===this._coreBrowserService.isFocused&&this._state.style===this._optionsService.options.cursorStyle&&this._state.width===this._cell.getWidth())return;this._clearCursor()}this._ctx.save(),this._cursorRenderers[this._optionsService.options.cursorStyle||"block"](this._bufferService.buffer.x,r,this._cell),this._ctx.restore(),this._state.x=this._bufferService.buffer.x,this._state.y=r,this._state.isFocused=!1,this._state.style=this._optionsService.options.cursorStyle,this._state.width=this._cell.getWidth()}else this._clearCursor()}}else this._clearCursor()},t.prototype._clearCursor=function(){this._state&&(this._clearCells(this._state.x,this._state.y,this._state.width,1),this._state={x:0,y:0,isFocused:!1,style:"",width:0})},t.prototype._renderBarCursor=function(e,t,r){this._ctx.save(),this._ctx.fillStyle=this._colors.cursor.css,this._fillLeftLineAtCell(e,t),this._ctx.restore()},t.prototype._renderBlockCursor=function(e,t,r){this._ctx.save(),this._ctx.fillStyle=this._colors.cursor.css,this._fillCells(e,t,r.getWidth(),1),this._ctx.fillStyle=this._colors.cursorAccent.css,this._fillCharTrueColor(r,e,t),this._ctx.restore()},t.prototype._renderUnderlineCursor=function(e,t,r){this._ctx.save(),this._ctx.fillStyle=this._colors.cursor.css,this._fillBottomLineAtCells(e,t),this._ctx.restore()},t.prototype._renderBlurCursor=function(e,t,r){this._ctx.save(),this._ctx.strokeStyle=this._colors.cursor.css,this._strokeRectAtCell(e,t,r.getWidth(),1),this._ctx.restore()},t}(o.BaseRenderLayer);t.CursorRenderLayer=a;var c=function(){function e(e,t){this._renderCallback=t,this.isCursorVisible=!0,e&&this._restartInterval()}return Object.defineProperty(e.prototype,"isPaused",{get:function(){return!(this._blinkStartTimeout||this._blinkInterval)},enumerable:!0,configurable:!0}),e.prototype.dispose=function(){this._blinkInterval&&(window.clearInterval(this._blinkInterval),this._blinkInterval=void 0),this._blinkStartTimeout&&(window.clearTimeout(this._blinkStartTimeout),this._blinkStartTimeout=void 0),this._animationFrame&&(window.cancelAnimationFrame(this._animationFrame),this._animationFrame=void 0)},e.prototype.restartBlinkAnimation=function(){var e=this;this.isPaused||(this._animationTimeRestarted=Date.now(),this.isCursorVisible=!0,this._animationFrame||(this._animationFrame=window.requestAnimationFrame(function(){e._renderCallback(),e._animationFrame=void 0})))},e.prototype._restartInterval=function(e){var t=this;void 0===e&&(e=600),this._blinkInterval&&window.clearInterval(this._blinkInterval),this._blinkStartTimeout=setTimeout(function(){if(t._animationTimeRestarted){var e=600-(Date.now()-t._animationTimeRestarted);if(t._animationTimeRestarted=void 0,e>0)return void t._restartInterval(e)}t.isCursorVisible=!1,t._animationFrame=window.requestAnimationFrame(function(){t._renderCallback(),t._animationFrame=void 0}),t._blinkInterval=setInterval(function(){if(t._animationTimeRestarted){var e=600-(Date.now()-t._animationTimeRestarted);return t._animationTimeRestarted=void 0,void t._restartInterval(e)}t.isCursorVisible=!t.isCursorVisible,t._animationFrame=window.requestAnimationFrame(function(){t._renderCallback(),t._animationFrame=void 0})},600)},e)},e.prototype.pause=function(){this.isCursorVisible=!0,this._blinkInterval&&(window.clearInterval(this._blinkInterval),this._blinkInterval=void 0),this._blinkStartTimeout&&(window.clearTimeout(this._blinkStartTimeout),this._blinkStartTimeout=void 0),this._animationFrame&&(window.cancelAnimationFrame(this._animationFrame),this._animationFrame=void 0)},e.prototype.resume=function(){this._animationTimeRestarted=void 0,this._restartInterval(),this.restartBlinkAnimation()},e}()},function(e,t,r){"use strict";var i,n=this&&this.__extends||(i=function(e,t){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])})(e,t)},function(e,t){function r(){this.constructor=e}i(e,t),e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)});Object.defineProperty(t,"__esModule",{value:!0});var o=r(13),s=r(9),a=r(25),c=function(e){function t(t,r,i,n,o,s,a){var c=e.call(this,t,"link",r,!0,i,n,s,a)||this;return c.bufferService=s,c.optionsService=a,o.onLinkHover(function(e){return c._onLinkHover(e)}),o.onLinkLeave(function(e){return c._onLinkLeave(e)}),c}return n(t,e),t.prototype.resize=function(t){e.prototype.resize.call(this,t),this._state=void 0},t.prototype.reset=function(){this._clearCurrentLink()},t.prototype._clearCurrentLink=function(){if(this._state){this._clearCells(this._state.x1,this._state.y1,this._state.cols-this._state.x1,1);var e=this._state.y2-this._state.y1-1;e>0&&this._clearCells(0,this._state.y1+1,this._state.cols,e),this._clearCells(0,this._state.y2,this._state.x2,1),this._state=void 0}},t.prototype._onLinkHover=function(e){if(e.fg===s.INVERTED_DEFAULT_COLOR?this._ctx.fillStyle=this._colors.background.css:e.fg&&a.is256Color(e.fg)?this._ctx.fillStyle=this._colors.ansi[e.fg].css:this._ctx.fillStyle=this._colors.foreground.css,e.y1===e.y2)this._fillBottomLineAtCells(e.x1,e.y1,e.x2-e.x1);else{this._fillBottomLineAtCells(e.x1,e.y1,e.cols-e.x1);for(var t=e.y1+1;t=e.lines.length)){for(var r=e.ydisp+Math.min(this._rowsToLinkify.end,this._bufferService.rows)+1,i=Math.ceil(2e3/this._bufferService.cols),n=this._bufferService.buffer.iterator(!1,t,r,i,i);n.hasNext();)for(var o=n.next(),s=0;s=0;t--)if(e.priority<=this._linkMatchers[t].priority)return void this._linkMatchers.splice(t+1,0,e);this._linkMatchers.splice(0,0,e)}else this._linkMatchers.push(e)},e.prototype.deregisterLinkMatcher=function(e){for(var t=0;t>9&511:void 0;r.validationCallback?r.validationCallback(a,function(e){n._rowsTimeoutId||e&&n._addLink(l[1],l[0]-n._bufferService.buffer.ydisp,a,r,f)}):c._addLink(l[1],l[0]-c._bufferService.buffer.ydisp,a,r,f)},c=this;null!==(i=o.exec(t));){if("break"===a())break}},e.prototype._addLink=function(e,t,r,n,o){var a=this;if(this._mouseZoneManager&&this._element){var c=i.getStringCellWidth(r),l=e%this._bufferService.cols,h=t+Math.floor(e/this._bufferService.cols),u=(l+c)%this._bufferService.cols,f=h+Math.floor((l+c)/this._bufferService.cols);0===u&&(u=this._bufferService.cols,f--),this._mouseZoneManager.add(new s(l+1,h+1,u+1,f+1,function(e){if(n.handler)return n.handler(e,r);window.open(r,"_blank")},function(){a._onLinkHover.fire(a._createLinkHoverEvent(l,h,u,f,o)),a._element.classList.add("xterm-cursor-pointer")},function(e){a._onLinkTooltip.fire(a._createLinkHoverEvent(l,h,u,f,o)),n.hoverTooltipCallback&&n.hoverTooltipCallback(e,r,{start:{x:l,y:h},end:{x:u,y:f}})},function(){a._onLinkLeave.fire(a._createLinkHoverEvent(l,h,u,f,o)),a._element.classList.remove("xterm-cursor-pointer"),n.hoverLeaveCallback&&n.hoverLeaveCallback()},function(e){return!n.willLinkActivate||n.willLinkActivate(e,r)}))}},e.prototype._createLinkHoverEvent=function(e,t,r,i,n){return{x1:e,y1:t,x2:r,y2:i,cols:this._bufferService.cols,fg:n}},e._timeBeforeLatency=200,e}();t.Linkifier=o;var s=function(e,t,r,i,n,o,s,a,c){this.x1=e,this.y1=t,this.x2=r,this.y2=i,this.clickCallback=n,this.hoverCallback=o,this.tooltipCallback=s,this.leaveCallback=a,this.willLinkActivate=c};t.MouseZone=s},function(e,t,r){"use strict";var i=this&&this.__decorate||function(e,t,r,i){var n,o=arguments.length,s=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,r,i);else for(var a=e.length-1;a>=0;a--)(n=e[a])&&(s=(o<3?n(s):o>3?n(t,r,s):n(t,r))||s);return o>3&&s&&Object.defineProperty(t,r,s),s},n=this&&this.__param||function(e,t){return function(r,i){t(r,i,e)}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(11),s=r(52),a=r(5),c=r(1),l=r(4),h=r(0),u=r(29),f=r(53),_=String.fromCharCode(160),d=new RegExp(_,"g"),p=function(){function e(e,t,r,i,n,o,l,h){var u=this;this._scrollLines=e,this._element=t,this._screenElement=r,this._charSizeService=i,this._bufferService=n,this._coreService=o,this._mouseService=l,this._optionsService=h,this._dragScrollAmount=0,this._enabled=!0,this._workCell=new a.CellData,this._mouseDownTimeStamp=0,this._onLinuxMouseSelection=new c.EventEmitter,this._onRedrawRequest=new c.EventEmitter,this._onSelectionChange=new c.EventEmitter,this._mouseMoveListener=function(e){return u._onMouseMove(e)},this._mouseUpListener=function(e){return u._onMouseUp(e)},this._coreService.onUserInput(function(){u.hasSelection&&u.clearSelection()}),this._trimListener=this._bufferService.buffer.lines.onTrim(function(e){return u._onTrim(e)}),this._bufferService.buffers.onBufferActivate(function(e){return u._onBufferActivate(e)}),this.enable(),this._model=new s.SelectionModel(this._bufferService),this._activeSelectionMode=0}return Object.defineProperty(e.prototype,"onLinuxMouseSelection",{get:function(){return this._onLinuxMouseSelection.event},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"onRedrawRequest",{get:function(){return this._onRedrawRequest.event},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"onSelectionChange",{get:function(){return this._onSelectionChange.event},enumerable:!0,configurable:!0}),e.prototype.dispose=function(){this._removeMouseDownListeners()},e.prototype.reset=function(){this.clearSelection()},e.prototype.disable=function(){this.clearSelection(),this._enabled=!1},e.prototype.enable=function(){this._enabled=!0},Object.defineProperty(e.prototype,"selectionStart",{get:function(){return this._model.finalSelectionStart},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"selectionEnd",{get:function(){return this._model.finalSelectionEnd},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"hasSelection",{get:function(){var e=this._model.finalSelectionStart,t=this._model.finalSelectionEnd;return!(!e||!t)&&(e[0]!==t[0]||e[1]!==t[1])},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"selectionText",{get:function(){var e=this._model.finalSelectionStart,t=this._model.finalSelectionEnd;if(!e||!t)return"";var r=this._bufferService.buffer,i=[];if(3===this._activeSelectionMode){if(e[0]===t[0])return"";for(var n=e[1];n<=t[1];n++){var s=r.translateBufferLineToString(n,!0,e[0],t[0]);i.push(s)}}else{var a=e[1]===t[1]?t[0]:void 0;i.push(r.translateBufferLineToString(e[1],!0,e[0],a));for(n=e[1]+1;n<=t[1]-1;n++){var c=r.lines.get(n);s=r.translateBufferLineToString(n,!0);c&&c.isWrapped?i[i.length-1]+=s:i.push(s)}if(e[1]!==t[1]){c=r.lines.get(t[1]),s=r.translateBufferLineToString(t[1],!0,0,t[0]);c&&c.isWrapped?i[i.length-1]+=s:i.push(s)}}return i.map(function(e){return e.replace(d," ")}).join(o.isWindows?"\r\n":"\n")},enumerable:!0,configurable:!0}),e.prototype.clearSelection=function(){this._model.clearSelection(),this._removeMouseDownListeners(),this.refresh(),this._onSelectionChange.fire()},e.prototype.refresh=function(e){var t=this;(this._refreshAnimationFrame||(this._refreshAnimationFrame=window.requestAnimationFrame(function(){return t._refresh()})),o.isLinux&&e)&&(this.selectionText.length&&this._onLinuxMouseSelection.fire(this.selectionText))},e.prototype._refresh=function(){this._refreshAnimationFrame=void 0,this._onRedrawRequest.fire({start:this._model.finalSelectionStart,end:this._model.finalSelectionEnd,columnSelectMode:3===this._activeSelectionMode})},e.prototype.isClickInSelection=function(e){var t=this._getMouseBufferCoords(e),r=this._model.finalSelectionStart,i=this._model.finalSelectionEnd;return!!(r&&i&&t)&&this._areCoordsInSelection(t,r,i)},e.prototype._areCoordsInSelection=function(e,t,r){return e[1]>t[1]&&e[1]=t[0]&&e[0]=t[0]},e.prototype.selectWordAtCursor=function(e){var t=this._getMouseBufferCoords(e);t&&(this._selectWordAt(t,!1),this._model.selectionEnd=void 0,this.refresh(!0))},e.prototype.selectAll=function(){this._model.isSelectAllActive=!0,this.refresh(),this._onSelectionChange.fire()},e.prototype.selectLines=function(e,t){this._model.clearSelection(),e=Math.max(e,0),t=Math.min(t,this._bufferService.buffer.lines.length-1),this._model.selectionStart=[0,e],this._model.selectionEnd=[this._bufferService.cols,t],this.refresh(),this._onSelectionChange.fire()},e.prototype._onTrim=function(e){this._model.onTrim(e)&&this.refresh()},e.prototype._getMouseBufferCoords=function(e){var t=this._mouseService.getCoords(e,this._screenElement,this._bufferService.cols,this._bufferService.rows,!0);if(t)return t[0]--,t[1]--,t[1]+=this._bufferService.buffer.ydisp,t},e.prototype._getMouseEventScrollAmount=function(e){var t=u.getCoordsRelativeToElement(e,this._screenElement)[1],r=this._bufferService.rows*Math.ceil(this._charSizeService.height*this._optionsService.options.lineHeight);return t>=0&&t<=r?0:(t>r&&(t-=r),t=Math.min(Math.max(t,-50),50),(t/=50)/Math.abs(t)+Math.round(14*t))},e.prototype.shouldForceSelection=function(e){return o.isMac?e.altKey&&this._optionsService.options.macOptionClickForcesSelection:e.shiftKey},e.prototype.onMouseDown=function(e){if(this._mouseDownTimeStamp=e.timeStamp,(2!==e.button||!this.hasSelection)&&0===e.button){if(!this._enabled){if(!this.shouldForceSelection(e))return;e.stopPropagation()}e.preventDefault(),this._dragScrollAmount=0,this._enabled&&e.shiftKey?this._onIncrementalClick(e):1===e.detail?this._onSingleClick(e):2===e.detail?this._onDoubleClick(e):3===e.detail&&this._onTripleClick(e),this._addMouseDownListeners(),this.refresh(!0)}},e.prototype._addMouseDownListeners=function(){var e=this;this._screenElement.ownerDocument&&(this._screenElement.ownerDocument.addEventListener("mousemove",this._mouseMoveListener),this._screenElement.ownerDocument.addEventListener("mouseup",this._mouseUpListener)),this._dragScrollIntervalTimer=window.setInterval(function(){return e._dragScroll()},50)},e.prototype._removeMouseDownListeners=function(){this._screenElement.ownerDocument&&(this._screenElement.ownerDocument.removeEventListener("mousemove",this._mouseMoveListener),this._screenElement.ownerDocument.removeEventListener("mouseup",this._mouseUpListener)),clearInterval(this._dragScrollIntervalTimer),this._dragScrollIntervalTimer=void 0},e.prototype._onIncrementalClick=function(e){this._model.selectionStart&&(this._model.selectionEnd=this._getMouseBufferCoords(e))},e.prototype._onSingleClick=function(e){if(this._model.selectionStartLength=0,this._model.isSelectAllActive=!1,this._activeSelectionMode=this.shouldColumnSelect(e)?3:0,this._model.selectionStart=this._getMouseBufferCoords(e),this._model.selectionStart){this._model.selectionEnd=void 0;var t=this._bufferService.buffer.lines.get(this._model.selectionStart[1]);t&&t.length!==this._model.selectionStart[0]&&0===t.hasWidth(this._model.selectionStart[0])&&this._model.selectionStart[0]++}},e.prototype._onDoubleClick=function(e){var t=this._getMouseBufferCoords(e);t&&(this._activeSelectionMode=1,this._selectWordAt(t,!0))},e.prototype._onTripleClick=function(e){var t=this._getMouseBufferCoords(e);t&&(this._activeSelectionMode=2,this._selectLineAt(t[1]))},e.prototype.shouldColumnSelect=function(e){return e.altKey&&!(o.isMac&&this._optionsService.options.macOptionClickForcesSelection)},e.prototype._onMouseMove=function(e){if(e.stopImmediatePropagation(),this._model.selectionStart){var t=this._model.selectionEnd?[this._model.selectionEnd[0],this._model.selectionEnd[1]]:null;if(this._model.selectionEnd=this._getMouseBufferCoords(e),this._model.selectionEnd){2===this._activeSelectionMode?this._model.selectionEnd[1]0?this._model.selectionEnd[0]=this._bufferService.cols:this._dragScrollAmount<0&&(this._model.selectionEnd[0]=0));var r=this._bufferService.buffer;if(this._model.selectionEnd[1]0?(3!==this._activeSelectionMode&&(this._model.selectionEnd[0]=this._bufferService.cols),this._model.selectionEnd[1]=Math.min(e.ydisp+this._bufferService.rows,e.lines.length-1)):(3!==this._activeSelectionMode&&(this._model.selectionEnd[0]=0),this._model.selectionEnd[1]=e.ydisp),this.refresh()}},e.prototype._onMouseUp=function(e){var t=e.timeStamp-this._mouseDownTimeStamp;if(this._removeMouseDownListeners(),this.selectionText.length<=1&&t<500){if(e.altKey&&this._bufferService.buffer.ybase===this._bufferService.buffer.ydisp){var r=this._mouseService.getCoords(e,this._element,this._bufferService.cols,this._bufferService.rows,!1);if(r&&void 0!==r[0]&&void 0!==r[1]){var i=f.moveToCellSequence(r[0]-1,r[1]-1,this._bufferService,this._coreService.decPrivateModes.applicationCursorKeys);this._coreService.triggerDataEvent(i,!0)}}}else this.hasSelection&&this._onSelectionChange.fire()},e.prototype._onBufferActivate=function(e){var t=this;this.clearSelection(),this._trimListener.dispose(),this._trimListener=e.activeBuffer.lines.onTrim(function(e){return t._onTrim(e)})},e.prototype._convertViewportColToCharacterIndex=function(e,t){for(var r=t[0],i=0;t[0]>=i;i++){var n=e.loadCell(i,this._workCell).getChars().length;0===this._workCell.getWidth()?r--:n>1&&t[0]!==i&&(r+=n-1)}return r},e.prototype.setSelection=function(e,t,r){this._model.clearSelection(),this._removeMouseDownListeners(),this._model.selectionStart=[e,t],this._model.selectionStartLength=r,this.refresh()},e.prototype._getWordAt=function(e,t,r,i){if(void 0===r&&(r=!0),void 0===i&&(i=!0),!(e[0]>=this._bufferService.cols)){var n=this._bufferService.buffer,o=n.lines.get(e[1]);if(o){var s=n.translateBufferLineToString(e[1],!1),a=this._convertViewportColToCharacterIndex(o,e),c=a,l=e[0]-a,h=0,u=0,f=0,_=0;if(" "===s.charAt(a)){for(;a>0&&" "===s.charAt(a-1);)a--;for(;c1&&(_+=v-1,c+=v-1);d>0&&a>0&&!this._isCharWordSeparator(o.loadCell(d-1,this._workCell));){o.loadCell(d-1,this._workCell);var g=this._workCell.getChars().length;0===this._workCell.getWidth()?(h++,d--):g>1&&(f+=g-1,a-=g-1),a--,d--}for(;p1&&(_+=y-1,c+=y-1),c++,p++}}c++;var b=a+l-h+f,m=Math.min(this._bufferService.cols,c-a+h+u-f-_);if(t||""!==s.slice(a,c).trim()){if(r&&0===b&&32!==o.getCodePoint(0)){var C=n.lines.get(e[1]-1);if(C&&o.isWrapped&&32!==C.getCodePoint(this._bufferService.cols-1)){var S=this._getWordAt([this._bufferService.cols-1,e[1]-1],!1,!0,!1);if(S){var w=this._bufferService.cols-S.start;b-=w,m+=w}}}if(i&&b+m===this._bufferService.cols&&32!==o.getCodePoint(this._bufferService.cols-1)){var E=n.lines.get(e[1]+1);if(E&&E.isWrapped&&32!==E.getCodePoint(0)){var L=this._getWordAt([0,e[1]+1],!1,!1,!0);L&&(m+=L.length)}}return{start:b,length:m}}}}},e.prototype._selectWordAt=function(e,t){var r=this._getWordAt(e,t);if(r){for(;r.start<0;)r.start+=this._bufferService.cols,e[1]--;this._model.selectionStart=[r.start,e[1]],this._model.selectionStartLength=r.length}},e.prototype._selectToWordAt=function(e){var t=this._getWordAt(e,!0);if(t){for(var r=e[1];t.start<0;)t.start+=this._bufferService.cols,r--;if(!this._model.areSelectionValuesReversed())for(;t.start+t.length>this._bufferService.cols;)t.length-=this._bufferService.cols,r++;this._model.selectionEnd=[this._model.areSelectionValuesReversed()?t.start:t.start+t.length,r]}},e.prototype._isCharWordSeparator=function(e){return 0!==e.getWidth()&&this._optionsService.options.wordSeparator.indexOf(e.getChars())>=0},e.prototype._selectLineAt=function(e){var t=this._bufferService.buffer.getWrappedRangeForLine(e);this._model.selectionStart=[0,t.first],this._model.selectionEnd=[this._bufferService.cols,t.last],this._model.selectionStartLength=0},e=i([n(3,l.ICharSizeService),n(4,h.IBufferService),n(5,h.ICoreService),n(6,l.IMouseService),n(7,h.IOptionsService)],e)}();t.SelectionService=p},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=function(){function e(e){this._bufferService=e,this.isSelectAllActive=!1,this.selectionStartLength=0}return e.prototype.clearSelection=function(){this.selectionStart=void 0,this.selectionEnd=void 0,this.isSelectAllActive=!1,this.selectionStartLength=0},Object.defineProperty(e.prototype,"finalSelectionStart",{get:function(){return this.isSelectAllActive?[0,0]:this.selectionEnd&&this.selectionStart&&this.areSelectionValuesReversed()?this.selectionEnd:this.selectionStart},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"finalSelectionEnd",{get:function(){if(this.isSelectAllActive)return[this._bufferService.cols,this._bufferService.buffer.ybase+this._bufferService.rows-1];if(this.selectionStart){if(!this.selectionEnd||this.areSelectionValuesReversed()){var e=this.selectionStart[0]+this.selectionStartLength;return e>this._bufferService.cols?[e%this._bufferService.cols,this.selectionStart[1]+Math.floor(e/this._bufferService.cols)]:[e,this.selectionStart[1]]}return this.selectionStartLength&&this.selectionEnd[1]===this.selectionStart[1]?[Math.max(this.selectionStart[0]+this.selectionStartLength,this.selectionEnd[0]),this.selectionEnd[1]]:this.selectionEnd}},enumerable:!0,configurable:!0}),e.prototype.areSelectionValuesReversed=function(){var e=this.selectionStart,t=this.selectionEnd;return!(!e||!t)&&(e[1]>t[1]||e[1]===t[1]&&e[0]>t[0])},e.prototype.onTrim=function(e){return this.selectionStart&&(this.selectionStart[1]-=e),this.selectionEnd&&(this.selectionEnd[1]-=e),this.selectionEnd&&this.selectionEnd[1]<0?(this.clearSelection(),!0):(this.selectionStart&&this.selectionStart[1]<0&&(this.selectionStart[1]=0),!1)},e}();t.SelectionModel=i},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=r(12);function n(e,t,r,i){var n=e-o(r,e),s=t-o(r,t);return h(Math.abs(n-s)-function(e,t,r){for(var i=0,n=e-o(r,e),s=t-o(r,t),c=0;c=0&&t0?i-o(s,i):t,e=r&&ct?"A":"B"}function c(e,t,r,i,n,o){for(var s=e,a=t,c="";s!==r||a!==i;)s+=n?1:-1,n&&s>o.cols-1?(c+=o.buffer.translateBufferLineToString(a,!1,e,s),s=0,e=0,a++):!n&&s<0&&(c+=o.buffer.translateBufferLineToString(a,!1,0,e+1),e=s=o.cols-1,a--);return c+o.buffer.translateBufferLineToString(a,!1,e,s)}function l(e,t){var r=t?"O":"[";return i.C0.ESC+r+e}function h(e,t){e=Math.floor(e);for(var r="",i=0;i0?i-o(a,i):t;var _=i,d=s(e,t,r,i,a,u);return h(c(e,f,r,_,"C"===d,a).length,l(d,u))}(a,u,e,t,r,i)}},function(e,t,r){"use strict";var i=this&&this.__decorate||function(e,t,r,i){var n,o=arguments.length,s=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,r,i);else for(var a=e.length-1;a>=0;a--)(n=e[a])&&(s=(o<3?n(s):o>3?n(t,r,s):n(t,r))||s);return o>3&&s&&Object.defineProperty(t,r,s),s},n=this&&this.__param||function(e,t){return function(r,i){t(r,i,e)}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(0),s=function(){function e(e){this._optionsService=e}return Object.defineProperty(e,"audioContext",{get:function(){if(!e._audioContext){var t=window.AudioContext||window.webkitAudioContext;if(!t)return console.warn("Web Audio API is not supported by this browser. Consider upgrading to the latest version"),null;e._audioContext=new t}return e._audioContext},enumerable:!0,configurable:!0}),e.prototype.playBellSound=function(){var t=e.audioContext;if(t){var r=t.createBufferSource();t.decodeAudioData(this._base64ToArrayBuffer(this._removeMimeType(this._optionsService.options.bellSound)),function(e){r.buffer=e,r.connect(t.destination),r.start(0)})}},e.prototype._base64ToArrayBuffer=function(e){for(var t=window.atob(e),r=t.length,i=new Uint8Array(r),n=0;n=0;a--)(n=e[a])&&(s=(o<3?n(s):o>3?n(t,r,s):n(t,r))||s);return o>3&&s&&Object.defineProperty(t,r,s),s},s=this&&this.__param||function(e,t){return function(r,i){t(r,i,e)}};Object.defineProperty(t,"__esModule",{value:!0});var a=r(2),c=r(7),l=r(4),h=r(0),u=function(e){function t(t,r,i,n,o){var s=e.call(this)||this;return s._element=t,s._screenElement=r,s._bufferService=i,s._mouseService=n,s._selectionService=o,s._zones=[],s._areZonesActive=!1,s._lastHoverCoords=[void 0,void 0],s._initialSelectionLength=0,s.register(c.addDisposableDomListener(s._element,"mousedown",function(e){return s._onMouseDown(e)})),s._mouseMoveListener=function(e){return s._onMouseMove(e)},s._mouseLeaveListener=function(e){return s._onMouseLeave(e)},s._clickListener=function(e){return s._onClick(e)},s}return n(t,e),t.prototype.dispose=function(){e.prototype.dispose.call(this),this._deactivate()},t.prototype.add=function(e){this._zones.push(e),1===this._zones.length&&this._activate()},t.prototype.clearAll=function(e,t){if(0!==this._zones.length){e&&t||(e=0,t=this._bufferService.rows-1);for(var r=0;re&&i.y1<=t+1||i.y2>e&&i.y2<=t+1||i.y1t+1)&&(this._currentZone&&this._currentZone===i&&(this._currentZone.leaveCallback(),this._currentZone=void 0),this._zones.splice(r--,1))}0===this._zones.length&&this._deactivate()}},t.prototype._activate=function(){this._areZonesActive||(this._areZonesActive=!0,this._element.addEventListener("mousemove",this._mouseMoveListener),this._element.addEventListener("mouseleave",this._mouseLeaveListener),this._element.addEventListener("click",this._clickListener))},t.prototype._deactivate=function(){this._areZonesActive&&(this._areZonesActive=!1,this._element.removeEventListener("mousemove",this._mouseMoveListener),this._element.removeEventListener("mouseleave",this._mouseLeaveListener),this._element.removeEventListener("click",this._clickListener))},t.prototype._onMouseMove=function(e){this._lastHoverCoords[0]===e.pageX&&this._lastHoverCoords[1]===e.pageY||(this._onHover(e),this._lastHoverCoords=[e.pageX,e.pageY])},t.prototype._onHover=function(e){var t=this,r=this._findZoneEventAt(e);r!==this._currentZone&&(this._currentZone&&(this._currentZone.leaveCallback(),this._currentZone=void 0,this._tooltipTimeout&&clearTimeout(this._tooltipTimeout)),r&&(this._currentZone=r,r.hoverCallback&&r.hoverCallback(e),this._tooltipTimeout=setTimeout(function(){return t._onTooltip(e)},500)))},t.prototype._onTooltip=function(e){this._tooltipTimeout=void 0;var t=this._findZoneEventAt(e);t&&t.tooltipCallback&&t.tooltipCallback(e)},t.prototype._onMouseDown=function(e){var t;(this._initialSelectionLength=this._getSelectionLength(),this._areZonesActive)&&((null===(t=this._findZoneEventAt(e))||void 0===t?void 0:t.willLinkActivate(e))&&(e.preventDefault(),e.stopImmediatePropagation()))},t.prototype._onMouseLeave=function(e){this._currentZone&&(this._currentZone.leaveCallback(),this._currentZone=void 0,this._tooltipTimeout&&clearTimeout(this._tooltipTimeout))},t.prototype._onClick=function(e){var t=this._findZoneEventAt(e),r=this._getSelectionLength();t&&r===this._initialSelectionLength&&(t.clickCallback(e),e.preventDefault(),e.stopImmediatePropagation())},t.prototype._getSelectionLength=function(){var e=this._selectionService.selectionText;return e?e.length:0},t.prototype._findZoneEventAt=function(e){var t=this._mouseService.getCoords(e,this._screenElement,this._bufferService.cols,this._bufferService.rows);if(t)for(var r=t[0],i=t[1],n=0;n=o.x1&&r=o.x1||i===o.y2&&ro.y1&&ie;)this._rowContainer.removeChild(this._rowElements.pop());this._rowElements[this._rowElements.length-1].addEventListener("focus",this._bottomBoundaryFocusListener),this._refreshRowsDimensions()},t.prototype._createAccessibilityTreeNode=function(){var e=document.createElement("div");return e.setAttribute("role","listitem"),e.tabIndex=-1,this._refreshRowDimensions(e),e},t.prototype._onTab=function(e){for(var t=0;t0)this._charsToConsume.shift()!==e&&(this._charsToAnnounce+=e);else this._charsToAnnounce+=e;"\n"===e&&(this._liveRegionLineCount++,21===this._liveRegionLineCount&&(this._liveRegion.textContent+=o.tooMuchOutput)),s.isMac&&this._liveRegion.textContent&&this._liveRegion.textContent.length>0&&!this._liveRegion.parentNode&&setTimeout(function(){t._accessibilityTreeRoot.appendChild(t._liveRegion)},0)}},t.prototype._clearLiveRegion=function(){this._liveRegion.textContent="",this._liveRegionLineCount=0,s.isMac&&this._liveRegion.parentNode&&this._accessibilityTreeRoot.removeChild(this._liveRegion)},t.prototype._onKey=function(e){this._clearLiveRegion(),this._charsToConsume.push(e)},t.prototype._refreshRows=function(e,t){this._renderRowsDebouncer.refresh(e,t,this._terminal.rows)},t.prototype._renderRows=function(e,t){for(var r=this._terminal.buffer,i=r.lines.length.toString(),n=e;n<=t;n++){var o=r.translateBufferLineToString(r.ydisp+n,!0),s=(r.ydisp+n+1).toString(),a=this._rowElements[n];a&&(0===o.length?a.innerHTML=" ":a.textContent=o,a.setAttribute("aria-posinset",s),a.setAttribute("aria-setsize",i))}this._announceCharacters()},t.prototype._refreshRowsDimensions=function(){if(this._renderService.dimensions.actualCellHeight){this._rowElements.length!==this._terminal.rows&&this._onResize(this._terminal.rows);for(var e=0;e=0;a--)(n=e[a])&&(s=(o<3?n(s):o>3?n(t,r,s):n(t,r))||s);return o>3&&s&&Object.defineProperty(t,r,s),s},s=this&&this.__param||function(e,t){return function(r,i){t(r,i,e)}};Object.defineProperty(t,"__esModule",{value:!0});var a=r(58),c=r(9),l=r(2),h=r(4),u=r(0),f=r(1),_=r(10),d="xterm-dom-renderer-owner-",p="xterm-rows",v="xterm-selection",g=1,y=function(e){function t(t,r,i,n,o,s,c,l){var h=e.call(this)||this;return h._colors=t,h._element=r,h._screenElement=i,h._viewportElement=n,h._linkifier=o,h._charSizeService=s,h._optionsService=c,h._bufferService=l,h._terminalClass=g++,h._rowElements=[],h._onRequestRefreshRows=new f.EventEmitter,h._rowContainer=document.createElement("div"),h._rowContainer.classList.add(p),h._rowContainer.style.lineHeight="normal",h._rowContainer.setAttribute("aria-hidden","true"),h._refreshRowElements(h._bufferService.cols,h._bufferService.rows),h._selectionContainer=document.createElement("div"),h._selectionContainer.classList.add(v),h._selectionContainer.setAttribute("aria-hidden","true"),h.dimensions={scaledCharWidth:0,scaledCharHeight:0,scaledCellWidth:0,scaledCellHeight:0,scaledCharLeft:0,scaledCharTop:0,scaledCanvasWidth:0,scaledCanvasHeight:0,canvasWidth:0,canvasHeight:0,actualCellWidth:0,actualCellHeight:0},h._updateDimensions(),h._injectCss(),h._rowFactory=new a.DomRendererRowFactory(document,h._optionsService,h._colors),h._element.classList.add(d+h._terminalClass),h._screenElement.appendChild(h._rowContainer),h._screenElement.appendChild(h._selectionContainer),h._linkifier.onLinkHover(function(e){return h._onLinkHover(e)}),h._linkifier.onLinkLeave(function(e){return h._onLinkLeave(e)}),h}return n(t,e),Object.defineProperty(t.prototype,"onRequestRefreshRows",{get:function(){return this._onRequestRefreshRows.event},enumerable:!0,configurable:!0}),t.prototype.dispose=function(){this._element.classList.remove(d+this._terminalClass),this._screenElement.removeChild(this._rowContainer),this._screenElement.removeChild(this._selectionContainer),this._screenElement.removeChild(this._themeStyleElement),this._screenElement.removeChild(this._dimensionsStyleElement),e.prototype.dispose.call(this)},t.prototype._updateDimensions=function(){var e=this;this.dimensions.scaledCharWidth=this._charSizeService.width*window.devicePixelRatio,this.dimensions.scaledCharHeight=Math.ceil(this._charSizeService.height*window.devicePixelRatio),this.dimensions.scaledCellWidth=this.dimensions.scaledCharWidth+Math.round(this._optionsService.options.letterSpacing),this.dimensions.scaledCellHeight=Math.floor(this.dimensions.scaledCharHeight*this._optionsService.options.lineHeight),this.dimensions.scaledCharLeft=0,this.dimensions.scaledCharTop=0,this.dimensions.scaledCanvasWidth=this.dimensions.scaledCellWidth*this._bufferService.cols,this.dimensions.scaledCanvasHeight=this.dimensions.scaledCellHeight*this._bufferService.rows,this.dimensions.canvasWidth=Math.round(this.dimensions.scaledCanvasWidth/window.devicePixelRatio),this.dimensions.canvasHeight=Math.round(this.dimensions.scaledCanvasHeight/window.devicePixelRatio),this.dimensions.actualCellWidth=this.dimensions.canvasWidth/this._bufferService.cols,this.dimensions.actualCellHeight=this.dimensions.canvasHeight/this._bufferService.rows,this._rowElements.forEach(function(t){t.style.width=e.dimensions.canvasWidth+"px",t.style.height=e.dimensions.actualCellHeight+"px",t.style.lineHeight=e.dimensions.actualCellHeight+"px",t.style.overflow="hidden"}),this._dimensionsStyleElement||(this._dimensionsStyleElement=document.createElement("style"),this._screenElement.appendChild(this._dimensionsStyleElement));var t=this._terminalSelector+" ."+p+" span { display: inline-block; height: 100%; vertical-align: top; width: "+this.dimensions.actualCellWidth+"px}";this._dimensionsStyleElement.innerHTML=t,this._selectionContainer.style.height=this._viewportElement.style.height,this._screenElement.style.width=this.dimensions.canvasWidth+"px",this._screenElement.style.height=this.dimensions.canvasHeight+"px"},t.prototype.setColors=function(e){this._colors=e,this._injectCss()},t.prototype._injectCss=function(){var e=this;this._themeStyleElement||(this._themeStyleElement=document.createElement("style"),this._screenElement.appendChild(this._themeStyleElement));var t=this._terminalSelector+" ."+p+" { color: "+this._colors.foreground.css+"; background-color: "+this._colors.background.css+"; font-family: "+this._optionsService.options.fontFamily+"; font-size: "+this._optionsService.options.fontSize+"px;}";t+=this._terminalSelector+" span:not(."+a.BOLD_CLASS+") { font-weight: "+this._optionsService.options.fontWeight+";}"+this._terminalSelector+" span."+a.BOLD_CLASS+" { font-weight: "+this._optionsService.options.fontWeightBold+";}"+this._terminalSelector+" span."+a.ITALIC_CLASS+" { font-style: italic;}",t+="@keyframes blink_box_shadow { 50% { box-shadow: none; }}",t+="@keyframes blink_block { 0% { background-color: "+this._colors.cursor.css+"; color: "+this._colors.cursorAccent.css+"; } 50% { background-color: "+this._colors.cursorAccent.css+"; color: "+this._colors.cursor.css+"; }}",t+=this._terminalSelector+" ."+p+":not(.xterm-focus) ."+a.CURSOR_CLASS+"."+a.CURSOR_STYLE_BLOCK_CLASS+" { outline: 1px solid "+this._colors.cursor.css+"; outline-offset: -1px;}"+this._terminalSelector+" ."+p+".xterm-focus ."+a.CURSOR_CLASS+"."+a.CURSOR_BLINK_CLASS+":not(."+a.CURSOR_STYLE_BLOCK_CLASS+") { animation: blink_box_shadow 1s step-end infinite;}"+this._terminalSelector+" ."+p+".xterm-focus ."+a.CURSOR_CLASS+"."+a.CURSOR_BLINK_CLASS+"."+a.CURSOR_STYLE_BLOCK_CLASS+" { animation: blink_block 1s step-end infinite;}"+this._terminalSelector+" ."+p+".xterm-focus ."+a.CURSOR_CLASS+"."+a.CURSOR_STYLE_BLOCK_CLASS+" { background-color: "+this._colors.cursor.css+"; color: "+this._colors.cursorAccent.css+";}"+this._terminalSelector+" ."+p+" ."+a.CURSOR_CLASS+"."+a.CURSOR_STYLE_BAR_CLASS+" { box-shadow: 1px 0 0 "+this._colors.cursor.css+" inset;}"+this._terminalSelector+" ."+p+" ."+a.CURSOR_CLASS+"."+a.CURSOR_STYLE_UNDERLINE_CLASS+" { box-shadow: 0 -1px 0 "+this._colors.cursor.css+" inset;}",t+=this._terminalSelector+" ."+v+" { position: absolute; top: 0; left: 0; z-index: 1; pointer-events: none;}"+this._terminalSelector+" ."+v+" div { position: absolute; background-color: "+this._colors.selection.css+";}",this._colors.ansi.forEach(function(r,i){t+=e._terminalSelector+" .xterm-fg-"+i+" { color: "+r.css+"; }"+e._terminalSelector+" .xterm-bg-"+i+" { background-color: "+r.css+"; }"}),t+=this._terminalSelector+" .xterm-fg-"+c.INVERTED_DEFAULT_COLOR+" { color: "+_.opaque(this._colors.background).css+"; }"+this._terminalSelector+" .xterm-bg-"+c.INVERTED_DEFAULT_COLOR+" { background-color: "+this._colors.foreground.css+"; }",this._themeStyleElement.innerHTML=t},t.prototype.onDevicePixelRatioChange=function(){this._updateDimensions()},t.prototype._refreshRowElements=function(e,t){for(var r=this._rowElements.length;r<=t;r++){var i=document.createElement("div");this._rowContainer.appendChild(i),this._rowElements.push(i)}for(;this._rowElements.length>t;)this._rowContainer.removeChild(this._rowElements.pop())},t.prototype.onResize=function(e,t){this._refreshRowElements(e,t),this._updateDimensions()},t.prototype.onCharSizeChanged=function(){this._updateDimensions()},t.prototype.onBlur=function(){this._rowContainer.classList.remove("xterm-focus")},t.prototype.onFocus=function(){this._rowContainer.classList.add("xterm-focus")},t.prototype.onSelectionChanged=function(e,t,r){for(;this._selectionContainer.children.length;)this._selectionContainer.removeChild(this._selectionContainer.children[0]);if(e&&t){var i=e[1]-this._bufferService.buffer.ydisp,n=t[1]-this._bufferService.buffer.ydisp,o=Math.max(i,0),s=Math.min(n,this._bufferService.rows-1);if(!(o>=this._bufferService.rows||s<0)){var a=document.createDocumentFragment();if(r)a.appendChild(this._createSelectionElement(o,e[0],t[0],s-o+1));else{var c=i===o?e[0]:0,l=o===s?t[0]:this._bufferService.cols;a.appendChild(this._createSelectionElement(o,c,l));var h=s-o-1;if(a.appendChild(this._createSelectionElement(o+1,0,this._bufferService.cols,h)),o!==s){var u=n===s?t[0]:this._bufferService.cols;a.appendChild(this._createSelectionElement(s,0,u))}}this._selectionContainer.appendChild(a)}}},t.prototype._createSelectionElement=function(e,t,r,i){void 0===i&&(i=1);var n=document.createElement("div");return n.style.height=i*this.dimensions.actualCellHeight+"px",n.style.top=e*this.dimensions.actualCellHeight+"px",n.style.left=t*this.dimensions.actualCellWidth+"px",n.style.width=this.dimensions.actualCellWidth*(r-t)+"px",n},t.prototype.onCursorMove=function(){},t.prototype.onOptionsChanged=function(){this._updateDimensions(),this._injectCss()},t.prototype.clear=function(){this._rowElements.forEach(function(e){return e.innerHTML=""})},t.prototype.renderRows=function(e,t){for(var r=this._bufferService.buffer.ybase+this._bufferService.buffer.y,i=this._bufferService.buffer.x,n=this._optionsService.options.cursorBlink,o=e;o<=t;o++){var s=this._rowElements[o];s.innerHTML="";var a=o+this._bufferService.buffer.ydisp,c=this._bufferService.buffer.lines.get(a),l=this._optionsService.options.cursorStyle;s.appendChild(this._rowFactory.createRow(c,a===r,l,i,n,this.dimensions.actualCellWidth,this._bufferService.cols))}},Object.defineProperty(t.prototype,"_terminalSelector",{get:function(){return"."+d+this._terminalClass},enumerable:!0,configurable:!0}),t.prototype.registerCharacterJoiner=function(e){return-1},t.prototype.deregisterCharacterJoiner=function(e){return!1},t.prototype._onLinkHover=function(e){this._setCellUnderline(e.x1,e.x2,e.y1,e.y2,e.cols,!0)},t.prototype._onLinkLeave=function(e){this._setCellUnderline(e.x1,e.x2,e.y1,e.y2,e.cols,!1)},t.prototype._setCellUnderline=function(e,t,r,i,n,o){for(;e!==t||r!==i;){var s=this._rowElements[r];if(!s)return;var a=s.children[e];a&&(a.style.textDecoration=o?"underline":"none"),++e>=n&&(e=0,r++)}},t=o([s(5,h.ICharSizeService),s(6,u.IOptionsService),s(7,u.IBufferService)],t)}(l.Disposable);t.DomRenderer=y},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=r(9),n=r(3),o=r(5),s=r(10);t.BOLD_CLASS="xterm-bold",t.DIM_CLASS="xterm-dim",t.ITALIC_CLASS="xterm-italic",t.UNDERLINE_CLASS="xterm-underline",t.CURSOR_CLASS="xterm-cursor",t.CURSOR_BLINK_CLASS="xterm-cursor-blink",t.CURSOR_STYLE_BLOCK_CLASS="xterm-cursor-block",t.CURSOR_STYLE_BAR_CLASS="xterm-cursor-bar",t.CURSOR_STYLE_UNDERLINE_CLASS="xterm-cursor-underline";var a=function(){function e(e,t,r){this._document=e,this._optionsService=t,this._colors=r,this._workCell=new o.CellData}return e.prototype.setColors=function(e){this._colors=e},e.prototype.createRow=function(e,r,o,a,l,h,u){for(var f=this._document.createDocumentFragment(),_=0,d=Math.min(e.length,u)-1;d>=0;d--)if(e.loadCell(d,this._workCell).getCode()!==n.NULL_CELL_CODE||r&&d===a){_=d+1;break}for(d=0;d<_;d++){e.loadCell(d,this._workCell);var p=this._workCell.getWidth();if(0!==p){var v=this._document.createElement("span");if(p>1&&(v.style.width=h*p+"px"),r&&d===a)switch(v.classList.add(t.CURSOR_CLASS),l&&v.classList.add(t.CURSOR_BLINK_CLASS),o){case"bar":v.classList.add(t.CURSOR_STYLE_BAR_CLASS);break;case"underline":v.classList.add(t.CURSOR_STYLE_UNDERLINE_CLASS);break;default:v.classList.add(t.CURSOR_STYLE_BLOCK_CLASS)}this._workCell.isBold()&&v.classList.add(t.BOLD_CLASS),this._workCell.isItalic()&&v.classList.add(t.ITALIC_CLASS),this._workCell.isDim()&&v.classList.add(t.DIM_CLASS),this._workCell.isUnderline()&&v.classList.add(t.UNDERLINE_CLASS),v.textContent=this._workCell.getChars()||n.WHITESPACE_CELL_CHAR;var g=this._workCell.getFgColor(),y=this._workCell.getFgColorMode(),b=this._workCell.getBgColor(),m=this._workCell.getBgColorMode(),C=!!this._workCell.isInverse();if(C){var S=g;g=b,b=S;var w=y;y=m,m=w}switch(y){case 16777216:case 33554432:this._workCell.isBold()&&g<8&&this._optionsService.options.drawBoldTextInBrightColors&&(g+=8),this._applyMinimumContrast(v,this._colors.background,this._colors.ansi[g])||v.classList.add("xterm-fg-"+g);break;case 50331648:var E=s.rgbaToColor(g>>16&255,g>>8&255,255&g);this._applyMinimumContrast(v,this._colors.background,E)||this._addStyle(v,"color:#"+c(g.toString(16),"0",6));break;case 0:default:this._applyMinimumContrast(v,this._colors.background,this._colors.foreground)||C&&v.classList.add("xterm-fg-"+i.INVERTED_DEFAULT_COLOR)}switch(m){case 16777216:case 33554432:v.classList.add("xterm-bg-"+b);break;case 50331648:this._addStyle(v,"background-color:#"+c(b.toString(16),"0",6));break;case 0:default:C&&v.classList.add("xterm-bg-"+i.INVERTED_DEFAULT_COLOR)}f.appendChild(v)}}return f},e.prototype._applyMinimumContrast=function(e,t,r){if(1===this._optionsService.options.minimumContrastRatio)return!1;var i=this._colors.contrastCache.getColor(this._workCell.bg,this._workCell.fg);return void 0===i&&(i=s.ensureContrastRatio(t,r,this._optionsService.options.minimumContrastRatio),this._colors.contrastCache.setColor(this._workCell.bg,this._workCell.fg,null!=i?i:null)),!!i&&(this._addStyle(e,"color:"+i.css),!0)},e.prototype._addStyle=function(e,t){e.setAttribute("style",""+(e.getAttribute("style")||"")+t+";")},e}();function c(e,t,r){for(;e.length"],191:["/","?"],192:["`","~"],219:["[","{"],220:["\\","|"],221:["]","}"],222:["'",'"']};t.evaluateKeyboardEvent=function(e,t,r,o){var s={type:0,cancel:!1,key:void 0},a=(e.shiftKey?1:0)|(e.altKey?2:0)|(e.ctrlKey?4:0)|(e.metaKey?8:0);switch(e.keyCode){case 0:"UIKeyInputUpArrow"===e.key?s.key=t?i.C0.ESC+"OA":i.C0.ESC+"[A":"UIKeyInputLeftArrow"===e.key?s.key=t?i.C0.ESC+"OD":i.C0.ESC+"[D":"UIKeyInputRightArrow"===e.key?s.key=t?i.C0.ESC+"OC":i.C0.ESC+"[C":"UIKeyInputDownArrow"===e.key&&(s.key=t?i.C0.ESC+"OB":i.C0.ESC+"[B");break;case 8:if(e.shiftKey){s.key=i.C0.BS;break}if(e.altKey){s.key=i.C0.ESC+i.C0.DEL;break}s.key=i.C0.DEL;break;case 9:if(e.shiftKey){s.key=i.C0.ESC+"[Z";break}s.key=i.C0.HT,s.cancel=!0;break;case 13:s.key=i.C0.CR,s.cancel=!0;break;case 27:s.key=i.C0.ESC,s.cancel=!0;break;case 37:if(e.metaKey)break;a?(s.key=i.C0.ESC+"[1;"+(a+1)+"D",s.key===i.C0.ESC+"[1;3D"&&(s.key=i.C0.ESC+(r?"b":"[1;5D"))):s.key=t?i.C0.ESC+"OD":i.C0.ESC+"[D";break;case 39:if(e.metaKey)break;a?(s.key=i.C0.ESC+"[1;"+(a+1)+"C",s.key===i.C0.ESC+"[1;3C"&&(s.key=i.C0.ESC+(r?"f":"[1;5C"))):s.key=t?i.C0.ESC+"OC":i.C0.ESC+"[C";break;case 38:if(e.metaKey)break;a?(s.key=i.C0.ESC+"[1;"+(a+1)+"A",r||s.key!==i.C0.ESC+"[1;3A"||(s.key=i.C0.ESC+"[1;5A")):s.key=t?i.C0.ESC+"OA":i.C0.ESC+"[A";break;case 40:if(e.metaKey)break;a?(s.key=i.C0.ESC+"[1;"+(a+1)+"B",r||s.key!==i.C0.ESC+"[1;3B"||(s.key=i.C0.ESC+"[1;5B")):s.key=t?i.C0.ESC+"OB":i.C0.ESC+"[B";break;case 45:e.shiftKey||e.ctrlKey||(s.key=i.C0.ESC+"[2~");break;case 46:s.key=a?i.C0.ESC+"[3;"+(a+1)+"~":i.C0.ESC+"[3~";break;case 36:s.key=a?i.C0.ESC+"[1;"+(a+1)+"H":t?i.C0.ESC+"OH":i.C0.ESC+"[H";break;case 35:s.key=a?i.C0.ESC+"[1;"+(a+1)+"F":t?i.C0.ESC+"OF":i.C0.ESC+"[F";break;case 33:e.shiftKey?s.type=2:s.key=i.C0.ESC+"[5~";break;case 34:e.shiftKey?s.type=3:s.key=i.C0.ESC+"[6~";break;case 112:s.key=a?i.C0.ESC+"[1;"+(a+1)+"P":i.C0.ESC+"OP";break;case 113:s.key=a?i.C0.ESC+"[1;"+(a+1)+"Q":i.C0.ESC+"OQ";break;case 114:s.key=a?i.C0.ESC+"[1;"+(a+1)+"R":i.C0.ESC+"OR";break;case 115:s.key=a?i.C0.ESC+"[1;"+(a+1)+"S":i.C0.ESC+"OS";break;case 116:s.key=a?i.C0.ESC+"[15;"+(a+1)+"~":i.C0.ESC+"[15~";break;case 117:s.key=a?i.C0.ESC+"[17;"+(a+1)+"~":i.C0.ESC+"[17~";break;case 118:s.key=a?i.C0.ESC+"[18;"+(a+1)+"~":i.C0.ESC+"[18~";break;case 119:s.key=a?i.C0.ESC+"[19;"+(a+1)+"~":i.C0.ESC+"[19~";break;case 120:s.key=a?i.C0.ESC+"[20;"+(a+1)+"~":i.C0.ESC+"[20~";break;case 121:s.key=a?i.C0.ESC+"[21;"+(a+1)+"~":i.C0.ESC+"[21~";break;case 122:s.key=a?i.C0.ESC+"[23;"+(a+1)+"~":i.C0.ESC+"[23~";break;case 123:s.key=a?i.C0.ESC+"[24;"+(a+1)+"~":i.C0.ESC+"[24~";break;default:if(!e.ctrlKey||e.shiftKey||e.altKey||e.metaKey)if(r&&!o||!e.altKey||e.metaKey)r&&!e.altKey&&!e.ctrlKey&&e.metaKey?65===e.keyCode&&(s.type=1):e.key&&!e.ctrlKey&&!e.altKey&&!e.metaKey&&e.keyCode>=48&&1===e.key.length?s.key=e.key:e.key&&e.ctrlKey&&"_"===e.key&&(s.key=i.C0.US);else{var c=n[e.keyCode],l=c&&c[e.shiftKey?1:0];if(l)s.key=i.C0.ESC+l;else if(e.keyCode>=65&&e.keyCode<=90){var h=e.ctrlKey?e.keyCode-64:e.keyCode+32;s.key=i.C0.ESC+String.fromCharCode(h)}}else e.keyCode>=65&&e.keyCode<=90?s.key=String.fromCharCode(e.keyCode-64):32===e.keyCode?s.key=i.C0.NUL:e.keyCode>=51&&e.keyCode<=55?s.key=String.fromCharCode(e.keyCode-51+27):56===e.keyCode?s.key=i.C0.DEL:219===e.keyCode?s.key=i.C0.ESC:220===e.keyCode?s.key=i.C0.FS:221===e.keyCode&&(s.key=i.C0.GS)}return s}},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=r(3);t.handleWindowsModeLineFeed=function(e){var t,r=null===(t=e.buffer.lines.get(e.buffer.ybase+e.buffer.y-1))||void 0===t?void 0:t.get(e.cols-1),n=e.buffer.lines.get(e.buffer.ybase+e.buffer.y);n&&r&&(n.isWrapped=r[i.CHAR_DATA_CODE_INDEX]!==i.NULL_CELL_CODE&&r[i.CHAR_DATA_CODE_INDEX]!==i.WHITESPACE_CELL_CODE)}},function(e,t,r){"use strict";var i,n=this&&this.__extends||(i=function(e,t){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])})(e,t)},function(e,t){function r(){this.constructor=e}i(e,t),e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)}),o=this&&this.__decorate||function(e,t,r,i){var n,o=arguments.length,s=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,r,i);else for(var a=e.length-1;a>=0;a--)(n=e[a])&&(s=(o<3?n(s):o>3?n(t,r,s):n(t,r))||s);return o>3&&s&&Object.defineProperty(t,r,s),s},s=this&&this.__param||function(e,t){return function(r,i){t(r,i,e)}};Object.defineProperty(t,"__esModule",{value:!0});var a=r(30),c=r(1),l=r(2),h=r(31),u=r(7),f=r(0),_=r(4),d=function(e){function t(t,r,i,n,o){var s=e.call(this)||this;if(s._renderer=t,s._rowCount=r,s.screenElement=i,s.optionsService=n,s.charSizeService=o,s._isPaused=!1,s._needsFullRefresh=!1,s._canvasWidth=0,s._canvasHeight=0,s._onDimensionsChange=new c.EventEmitter,s._onRender=new c.EventEmitter,s._onRefreshRequest=new c.EventEmitter,s._renderDebouncer=new a.RenderDebouncer(function(e,t){return s._renderRows(e,t)}),s.register(s._renderDebouncer),s._screenDprMonitor=new h.ScreenDprMonitor,s._screenDprMonitor.setListener(function(){return s.onDevicePixelRatioChange()}),s.register(s._screenDprMonitor),s.register(n.onOptionChange(function(){return s._renderer.onOptionsChanged()})),s.register(o.onCharSizeChange(function(){return s.onCharSizeChanged()})),s._renderer.onRequestRefreshRows(function(e){return s.refreshRows(e.start,e.end)}),s.register(u.addDisposableDomListener(window,"resize",function(){return s.onDevicePixelRatioChange()})),"IntersectionObserver"in window){var l=new IntersectionObserver(function(e){return s._onIntersectionChange(e[e.length-1])},{threshold:0});l.observe(i),s.register({dispose:function(){return l.disconnect()}})}return s}return n(t,e),Object.defineProperty(t.prototype,"onDimensionsChange",{get:function(){return this._onDimensionsChange.event},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"onRender",{get:function(){return this._onRender.event},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"onRefreshRequest",{get:function(){return this._onRefreshRequest.event},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"dimensions",{get:function(){return this._renderer.dimensions},enumerable:!0,configurable:!0}),t.prototype._onIntersectionChange=function(e){this._isPaused=0===e.intersectionRatio,!this._isPaused&&this._needsFullRefresh&&(this.refreshRows(0,this._rowCount-1),this._needsFullRefresh=!1)},t.prototype.refreshRows=function(e,t){this._isPaused?this._needsFullRefresh=!0:this._renderDebouncer.refresh(e,t,this._rowCount)},t.prototype._renderRows=function(e,t){this._renderer.renderRows(e,t),this._onRender.fire({start:e,end:t})},t.prototype.resize=function(e,t){this._rowCount=t,this._fireOnCanvasResize()},t.prototype.changeOptions=function(){this._renderer.onOptionsChanged(),this.refreshRows(0,this._rowCount-1),this._fireOnCanvasResize()},t.prototype._fireOnCanvasResize=function(){this._renderer.dimensions.canvasWidth===this._canvasWidth&&this._renderer.dimensions.canvasHeight===this._canvasHeight||this._onDimensionsChange.fire(this._renderer.dimensions)},t.prototype.dispose=function(){this._renderer.dispose(),e.prototype.dispose.call(this)},t.prototype.setRenderer=function(e){var t=this;this._renderer.dispose(),this._renderer=e,this._renderer.onRequestRefreshRows(function(e){return t.refreshRows(e.start,e.end)}),this.refreshRows(0,this._rowCount-1)},t.prototype._fullRefresh=function(){this._isPaused?this._needsFullRefresh=!0:this.refreshRows(0,this._rowCount-1)},t.prototype.setColors=function(e){this._renderer.setColors(e),this._fullRefresh()},t.prototype.onDevicePixelRatioChange=function(){this._renderer.onDevicePixelRatioChange(),this.refreshRows(0,this._rowCount-1)},t.prototype.onResize=function(e,t){this._renderer.onResize(e,t),this._fullRefresh()},t.prototype.onCharSizeChanged=function(){this._renderer.onCharSizeChanged()},t.prototype.onBlur=function(){this._renderer.onBlur()},t.prototype.onFocus=function(){this._renderer.onFocus()},t.prototype.onSelectionChanged=function(e,t,r){this._renderer.onSelectionChanged(e,t,r)},t.prototype.onCursorMove=function(){this._renderer.onCursorMove()},t.prototype.clear=function(){this._renderer.clear()},t.prototype.registerCharacterJoiner=function(e){return this._renderer.registerCharacterJoiner(e)},t.prototype.deregisterCharacterJoiner=function(e){return this._renderer.deregisterCharacterJoiner(e)},t=o([s(3,f.IOptionsService),s(4,_.ICharSizeService)],t)}(l.Disposable);t.RenderService=d},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=r(1),n=r(11),o=r(32);t.DEFAULT_BELL_SOUND="data:audio/mp3;base64,SUQzBAAAAAAAI1RTU0UAAAAPAAADTGF2ZjU4LjMyLjEwNAAAAAAAAAAAAAAA//tQxAADB8AhSmxhIIEVCSiJrDCQBTcu3UrAIwUdkRgQbFAZC1CQEwTJ9mjRvBA4UOLD8nKVOWfh+UlK3z/177OXrfOdKl7pyn3Xf//WreyTRUoAWgBgkOAGbZHBgG1OF6zM82DWbZaUmMBptgQhGjsyYqc9ae9XFz280948NMBWInljyzsNRFLPWdnZGWrddDsjK1unuSrVN9jJsK8KuQtQCtMBjCEtImISdNKJOopIpBFpNSMbIHCSRpRR5iakjTiyzLhchUUBwCgyKiweBv/7UsQbg8isVNoMPMjAAAA0gAAABEVFGmgqK////9bP/6XCykxBTUUzLjEwMKqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq",t.DEFAULT_OPTIONS=Object.freeze({cols:80,rows:24,cursorBlink:!1,cursorStyle:"block",bellSound:t.DEFAULT_BELL_SOUND,bellStyle:"none",drawBoldTextInBrightColors:!0,fastScrollModifier:"alt",fastScrollSensitivity:5,fontFamily:"courier-new, courier, monospace",fontSize:15,fontWeight:"normal",fontWeightBold:"bold",lineHeight:1,letterSpacing:0,logLevel:"info",scrollback:1e3,scrollSensitivity:1,screenReaderMode:!1,macOptionIsMeta:!1,macOptionClickForcesSelection:!1,minimumContrastRatio:1,disableStdin:!1,allowTransparency:!1,tabStopWidth:8,theme:{},rightClickSelectsWord:n.isMac,rendererType:"canvas",windowsMode:!1,convertEol:!1,termName:"xterm",screenKeys:!1,cancelEvents:!1,useFlowControl:!1,wordSeparator:" ()[]{}',:;\"`"});var s=["cols","rows"],a=function(){function e(e){var r=this;this._onOptionChange=new i.EventEmitter,this.options=o.clone(t.DEFAULT_OPTIONS),Object.keys(e).forEach(function(t){if(t in r.options){var i=e[t];r.options[t]=i}})}return Object.defineProperty(e.prototype,"onOptionChange",{get:function(){return this._onOptionChange.event},enumerable:!0,configurable:!0}),e.prototype.setOption=function(e,r){if(!(e in t.DEFAULT_OPTIONS))throw new Error('No option with key "'+e+'"');if(-1!==s.indexOf(e))throw new Error('Option "'+e+'" can only be set in the constructor');this.options[e]!==r&&(r=this._sanitizeAndValidateOption(e,r),this.options[e]!==r&&(this.options[e]=r,this._onOptionChange.fire(e)))},e.prototype._sanitizeAndValidateOption=function(e,r){switch(e){case"bellStyle":case"cursorStyle":case"fontWeight":case"fontWeightBold":case"rendererType":case"wordSeparator":r||(r=t.DEFAULT_OPTIONS[e]);break;case"lineHeight":case"tabStopWidth":if(r<1)throw new Error(e+" cannot be less than 1, value: "+r);break;case"minimumContrastRatio":r=Math.max(1,Math.min(21,Math.round(10*r)/10));case"scrollback":if((r=Math.min(r,4294967295))<0)throw new Error(e+" cannot be less than 0, value: "+r);break;case"fastScrollSensitivity":case"scrollSensitivity":if(r<=0)throw new Error(e+" cannot be less than or equal to 0, value: "+r)}return r},e.prototype.getOption=function(e){if(!(e in t.DEFAULT_OPTIONS))throw new Error('No option with key "'+e+'"');return this.options[e]},e}();t.OptionsService=a},function(e,t,r){"use strict";var i=this&&this.__decorate||function(e,t,r,i){var n,o=arguments.length,s=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,r,i);else for(var a=e.length-1;a>=0;a--)(n=e[a])&&(s=(o<3?n(s):o>3?n(t,r,s):n(t,r))||s);return o>3&&s&&Object.defineProperty(t,r,s),s},n=this&&this.__param||function(e,t){return function(r,i){t(r,i,e)}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(0),s=r(1),a=function(){function e(e,t,r){this.document=e,this.parentElement=t,this._optionsService=r,this.width=0,this.height=0,this._onCharSizeChange=new s.EventEmitter,this._measureStrategy=new c(e,t,this._optionsService)}return Object.defineProperty(e.prototype,"hasValidSize",{get:function(){return this.width>0&&this.height>0},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"onCharSizeChange",{get:function(){return this._onCharSizeChange.event},enumerable:!0,configurable:!0}),e.prototype.measure=function(){var e=this._measureStrategy.measure();e.width===this.width&&e.height===this.height||(this.width=e.width,this.height=e.height,this._onCharSizeChange.fire())},e=i([n(2,o.IOptionsService)],e)}();t.CharSizeService=a;var c=function(){function e(e,t,r){this._document=e,this._parentElement=t,this._optionsService=r,this._result={width:0,height:0},this._measureElement=this._document.createElement("span"),this._measureElement.classList.add("xterm-char-measure-element"),this._measureElement.textContent="W",this._measureElement.setAttribute("aria-hidden","true"),this._parentElement.appendChild(this._measureElement)}return e.prototype.measure=function(){this._measureElement.style.fontFamily=this._optionsService.options.fontFamily,this._measureElement.style.fontSize=this._optionsService.options.fontSize+"px";var e=this._measureElement.getBoundingClientRect();return 0!==e.width&&0!==e.height&&(this._result.width=e.width,this._result.height=Math.ceil(e.height)),this._result},e}()},function(e,t,r){"use strict";var i=this&&this.__decorate||function(e,t,r,i){var n,o=arguments.length,s=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,r,i);else for(var a=e.length-1;a>=0;a--)(n=e[a])&&(s=(o<3?n(s):o>3?n(t,r,s):n(t,r))||s);return o>3&&s&&Object.defineProperty(t,r,s),s},n=this&&this.__param||function(e,t){return function(r,i){t(r,i,e)}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(0),s=r(65);t.MINIMUM_COLS=2,t.MINIMUM_ROWS=1;var a=function(){function e(e){this._optionsService=e,this.cols=Math.max(e.options.cols,t.MINIMUM_COLS),this.rows=Math.max(e.options.rows,t.MINIMUM_ROWS),this.buffers=new s.BufferSet(e,this)}return Object.defineProperty(e.prototype,"buffer",{get:function(){return this.buffers.active},enumerable:!0,configurable:!0}),e.prototype.resize=function(e,t){this.cols=e,this.rows=t},e.prototype.reset=function(){this.buffers=new s.BufferSet(this._optionsService,this)},e=i([n(0,o.IOptionsService)],e)}();t.BufferService=a},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=r(66),n=r(1),o=function(){function e(e,t){this.optionsService=e,this.bufferService=t,this._onBufferActivate=new n.EventEmitter,this._normal=new i.Buffer(!0,e,t),this._normal.fillViewportRows(),this._alt=new i.Buffer(!1,e,t),this._activeBuffer=this._normal,this.setupTabStops()}return Object.defineProperty(e.prototype,"onBufferActivate",{get:function(){return this._onBufferActivate.event},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"alt",{get:function(){return this._alt},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"active",{get:function(){return this._activeBuffer},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"normal",{get:function(){return this._normal},enumerable:!0,configurable:!0}),e.prototype.activateNormalBuffer=function(){this._activeBuffer!==this._normal&&(this._normal.x=this._alt.x,this._normal.y=this._alt.y,this._alt.clear(),this._activeBuffer=this._normal,this._onBufferActivate.fire({activeBuffer:this._normal,inactiveBuffer:this._alt}))},e.prototype.activateAltBuffer=function(e){this._activeBuffer!==this._alt&&(this._alt.fillViewportRows(e),this._alt.x=this._normal.x,this._alt.y=this._normal.y,this._activeBuffer=this._alt,this._onBufferActivate.fire({activeBuffer:this._alt,inactiveBuffer:this._normal}))},e.prototype.resize=function(e,t){this._normal.resize(e,t),this._alt.resize(e,t)},e.prototype.setupTabStops=function(e){this._normal.setupTabStops(e),this._alt.setupTabStops(e)},e}();t.BufferSet=o},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=r(67),n=r(16),o=r(5),s=r(3),a=r(68),c=r(69),l=r(18);t.MAX_BUFFER_SIZE=4294967295;var h=function(){function e(e,t,r){this._hasScrollback=e,this._optionsService=t,this._bufferService=r,this.ydisp=0,this.ybase=0,this.y=0,this.x=0,this.savedY=0,this.savedX=0,this.savedCurAttrData=n.DEFAULT_ATTR_DATA.clone(),this.savedCharset=l.DEFAULT_CHARSET,this.markers=[],this._nullCell=o.CellData.fromCharData([0,s.NULL_CELL_CHAR,s.NULL_CELL_WIDTH,s.NULL_CELL_CODE]),this._whitespaceCell=o.CellData.fromCharData([0,s.WHITESPACE_CELL_CHAR,s.WHITESPACE_CELL_WIDTH,s.WHITESPACE_CELL_CODE]),this._cols=this._bufferService.cols,this._rows=this._bufferService.rows,this.lines=new i.CircularList(this._getCorrectBufferLength(this._rows)),this.scrollTop=0,this.scrollBottom=this._rows-1,this.setupTabStops()}return e.prototype.getNullCell=function(e){return e?(this._nullCell.fg=e.fg,this._nullCell.bg=e.bg):(this._nullCell.fg=0,this._nullCell.bg=0),this._nullCell},e.prototype.getWhitespaceCell=function(e){return e?(this._whitespaceCell.fg=e.fg,this._whitespaceCell.bg=e.bg):(this._whitespaceCell.fg=0,this._whitespaceCell.bg=0),this._whitespaceCell},e.prototype.getBlankLine=function(e,t){return new n.BufferLine(this._bufferService.cols,this.getNullCell(e),t)},Object.defineProperty(e.prototype,"hasScrollback",{get:function(){return this._hasScrollback&&this.lines.maxLength>this._rows},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"isCursorInViewport",{get:function(){var e=this.ybase+this.y-this.ydisp;return e>=0&&et.MAX_BUFFER_SIZE?t.MAX_BUFFER_SIZE:r},e.prototype.fillViewportRows=function(e){if(0===this.lines.length){void 0===e&&(e=n.DEFAULT_ATTR_DATA);for(var t=this._rows;t--;)this.lines.push(this.getBlankLine(e))}},e.prototype.clear=function(){this.ydisp=0,this.ybase=0,this.y=0,this.x=0,this.lines=new i.CircularList(this._getCorrectBufferLength(this._rows)),this.scrollTop=0,this.scrollBottom=this._rows-1,this.setupTabStops()},e.prototype.resize=function(e,t){var r=this.getNullCell(n.DEFAULT_ATTR_DATA),i=this._getCorrectBufferLength(t);if(i>this.lines.maxLength&&(this.lines.maxLength=i),this.lines.length>0){if(this._cols0&&this.lines.length<=this.ybase+this.y+s+1?(this.ybase--,s++,this.ydisp>0&&this.ydisp--):this.lines.push(new n.BufferLine(e,r)));else for(a=this._rows;a>t;a--)this.lines.length>t+this.ybase&&(this.lines.length>this.ybase+this.y+1?this.lines.pop():(this.ybase++,this.ydisp++));if(i0&&(this.lines.trimStart(c),this.ybase=Math.max(this.ybase-c,0),this.ydisp=Math.max(this.ydisp-c,0),this.savedY=Math.max(this.savedY-c,0)),this.lines.maxLength=i}this.x=Math.min(this.x,e-1),this.y=Math.min(this.y,t-1),s&&(this.y+=s),this.savedX=Math.min(this.savedX,e-1),this.scrollTop=0}if(this.scrollBottom=t-1,this._isReflowEnabled&&(this._reflow(e,t),this._cols>e))for(o=0;othis._cols?this._reflowLarger(e,t):this._reflowSmaller(e,t))},e.prototype._reflowLarger=function(e,t){var r=a.reflowLargerGetLinesToRemove(this.lines,this._cols,e,this.ybase+this.y,this.getNullCell(n.DEFAULT_ATTR_DATA));if(r.length>0){var i=a.reflowLargerCreateNewLayout(this.lines,r);a.reflowLargerApplyNewLayout(this.lines,i.layout),this._reflowLargerAdjustViewport(e,t,i.countRemoved)}},e.prototype._reflowLargerAdjustViewport=function(e,t,r){for(var i=this.getNullCell(n.DEFAULT_ATTR_DATA),o=r;o-- >0;)0===this.ybase?(this.y>0&&this.y--,this.lines.length=0;s--){var c=this.lines.get(s);if(!(!c||!c.isWrapped&&c.getTrimmedLength()<=e)){for(var l=[c];c.isWrapped&&s>0;)c=this.lines.get(--s),l.unshift(c);var h=this.ybase+this.y;if(!(h>=s&&h0&&(i.push({start:s+l.length+o,newLines:p}),o+=p.length),l.push.apply(l,p);var y=f.length-1,b=f[y];0===b&&(b=f[--y]);for(var m=l.length-_-1,C=u;m>=0;){var S=Math.min(C,b);if(l[y].copyCellsFrom(l[m],C-S,b-S,S,!0),0===(b-=S)&&(b=f[--y]),0===(C-=S)){m--;var w=Math.max(m,0);C=a.getWrappedLineTrimmedLength(l,w,this._cols)}}for(v=0;v0;)0===this.ybase?this.y0){var L=[],A=[];for(v=0;v=0;v--)if(D&&D.start>x+T){for(var M=D.newLines.length-1;M>=0;M--)this.lines.set(v--,D.newLines[M]);v++,L.push({index:x+1,amount:D.newLines.length}),T+=D.newLines.length,D=i[++k]}else this.lines.set(v,A[x--]);var O=0;for(v=L.length-1;v>=0;v--)L[v].index+=O,this.lines.onInsertEmitter.fire(L[v]),O+=L[v].amount;var P=Math.max(0,R+o-this.lines.maxLength);P>0&&this.lines.onTrimEmitter.fire(P)}},e.prototype.stringIndexToBufferIndex=function(e,t,r){for(void 0===r&&(r=!1);t;){var i=this.lines.get(e);if(!i)return[-1,-1];for(var n=r?i.getTrimmedLength():i.length,o=0;o0&&this.lines.get(t).isWrapped;)t--;for(;r+10;);return e>=this._cols?this._cols-1:e<0?0:e},e.prototype.nextStop=function(e){for(null==e&&(e=this.x);!this.tabs[++e]&&e=this._cols?this._cols-1:e<0?0:e},e.prototype.addMarker=function(e){var t=this,r=new c.Marker(e);return this.markers.push(r),r.register(this.lines.onTrim(function(e){r.line-=e,r.line<0&&r.dispose()})),r.register(this.lines.onInsert(function(e){r.line>=e.index&&(r.line+=e.amount)})),r.register(this.lines.onDelete(function(e){r.line>=e.index&&r.linee.index&&(r.line-=e.amount)})),r.register(r.onDispose(function(){return t._removeMarker(r)})),r},e.prototype._removeMarker=function(e){this.markers.splice(this.markers.indexOf(e),1)},e.prototype.iterator=function(e,t,r,i,n){return new u(this,e,t,r,i,n)},e}();t.Buffer=h;var u=function(){function e(e,t,r,i,n,o){void 0===r&&(r=0),void 0===i&&(i=e.lines.length),void 0===n&&(n=0),void 0===o&&(o=0),this._buffer=e,this._trimRight=t,this._startIndex=r,this._endIndex=i,this._startOverscan=n,this._endOverscan=o,this._startIndex<0&&(this._startIndex=0),this._endIndex>this._buffer.lines.length&&(this._endIndex=this._buffer.lines.length),this._current=this._startIndex}return e.prototype.hasNext=function(){return this._currentthis._endIndex+this._endOverscan&&(e.last=this._endIndex+this._endOverscan),e.first=Math.max(e.first,0),e.last=Math.min(e.last,this._buffer.lines.length);for(var t="",r=e.first;r<=e.last;++r)t+=this._buffer.translateBufferLineToString(r,this._trimRight);return this._current=e.last+1,{range:e,content:t}},e}();t.BufferStringIterator=u},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=r(1),n=function(){function e(e){this._maxLength=e,this.onDeleteEmitter=new i.EventEmitter,this.onInsertEmitter=new i.EventEmitter,this.onTrimEmitter=new i.EventEmitter,this._array=new Array(this._maxLength),this._startIndex=0,this._length=0}return Object.defineProperty(e.prototype,"onDelete",{get:function(){return this.onDeleteEmitter.event},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"onInsert",{get:function(){return this.onInsertEmitter.event},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"onTrim",{get:function(){return this.onTrimEmitter.event},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"maxLength",{get:function(){return this._maxLength},set:function(e){if(this._maxLength!==e){for(var t=new Array(e),r=0;rthis._length)for(var t=this._length;t=e;n--)this._array[this._getCyclicIndex(n+r.length)]=this._array[this._getCyclicIndex(n)];for(n=0;nthis._maxLength){var o=this._length+r.length-this._maxLength;this._startIndex+=o,this._length=this._maxLength,this.onTrimEmitter.fire(o)}else this._length+=r.length},e.prototype.trimStart=function(e){e>this._length&&(e=this._length),this._startIndex+=e,this._length-=e,this.onTrimEmitter.fire(e)},e.prototype.shiftElements=function(e,t,r){if(!(t<=0)){if(e<0||e>=this._length)throw new Error("start argument out of range");if(e+r<0)throw new Error("Cannot shift elements in list beyond index 0");if(r>0){for(var i=t-1;i>=0;i--)this.set(e+i+r,this.get(e+i));var n=e+t+r-this._length;if(n>0)for(this._length+=n;this._length>this._maxLength;)this._length--,this._startIndex++,this.onTrimEmitter.fire(1)}else for(i=0;i=a&&n0&&(m>u||0===h[m].getTrimmedLength());m--)b++;b>0&&(s.push(a+h.length-b),s.push(b)),a+=h.length-1}}}return s},t.reflowLargerCreateNewLayout=function(e,t){for(var r=[],i=0,n=t[i],o=0,s=0;sl&&(s-=l,a++);var h=2===e[a].getWidth(s-1);h&&s--;var u=h?r-1:r;n.push(u),c+=u}return n},t.getWrappedLineTrimmedLength=i},function(e,t,r){"use strict";var i,n=this&&this.__extends||(i=function(e,t){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])})(e,t)},function(e,t){function r(){this.constructor=e}i(e,t),e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)});Object.defineProperty(t,"__esModule",{value:!0});var o=r(1),s=function(e){function t(r){var i=e.call(this)||this;return i.line=r,i._id=t._nextId++,i.isDisposed=!1,i._onDispose=new o.EventEmitter,i}return n(t,e),Object.defineProperty(t.prototype,"id",{get:function(){return this._id},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"onDispose",{get:function(){return this._onDispose.event},enumerable:!0,configurable:!0}),t.prototype.dispose=function(){this.isDisposed||(this.isDisposed=!0,this.line=-1,this._onDispose.fire())},t._nextId=1,t}(r(2).Disposable);t.Marker=s},function(e,t,r){"use strict";var i=this&&this.__decorate||function(e,t,r,i){var n,o=arguments.length,s=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,r,i);else for(var a=e.length-1;a>=0;a--)(n=e[a])&&(s=(o<3?n(s):o>3?n(t,r,s):n(t,r))||s);return o>3&&s&&Object.defineProperty(t,r,s),s},n=this&&this.__param||function(e,t){return function(r,i){t(r,i,e)}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(4),s=r(29),a=function(){function e(e,t){this._renderService=e,this._charSizeService=t}return e.prototype.getCoords=function(e,t,r,i,n){return s.getCoords(e,t,r,i,this._charSizeService.hasValidSize,this._renderService.dimensions.actualCellWidth,this._renderService.dimensions.actualCellHeight,n)},e.prototype.getRawByteCoords=function(e,t,r,i){var n=this.getCoords(e,t,r,i);return s.getRawByteCoords(n)},e=i([n(0,o.IRenderService),n(1,o.ICharSizeService)],e)}();t.MouseService=a},function(e,t,r){"use strict";var i=this&&this.__decorate||function(e,t,r,i){var n,o=arguments.length,s=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,r,i);else for(var a=e.length-1;a>=0;a--)(n=e[a])&&(s=(o<3?n(s):o>3?n(t,r,s):n(t,r))||s);return o>3&&s&&Object.defineProperty(t,r,s),s},n=this&&this.__param||function(e,t){return function(r,i){t(r,i,e)}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(0),s=r(1),a=r(32),c=Object.freeze({applicationCursorKeys:!1}),l=function(){function e(e,t,r,i){this._scrollToBottom=e,this._bufferService=t,this._logService=r,this._optionsService=i,this.isCursorInitialized=!1,this.isCursorHidden=!1,this._onData=new s.EventEmitter,this._onUserInput=new s.EventEmitter,this._onBinary=new s.EventEmitter,this.decPrivateModes=a.clone(c)}return Object.defineProperty(e.prototype,"onData",{get:function(){return this._onData.event},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"onUserInput",{get:function(){return this._onUserInput.event},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"onBinary",{get:function(){return this._onBinary.event},enumerable:!0,configurable:!0}),e.prototype.reset=function(){this.decPrivateModes=a.clone(c)},e.prototype.triggerDataEvent=function(e,t){if(void 0===t&&(t=!1),!this._optionsService.options.disableStdin){var r=this._bufferService.buffer;r.ybase!==r.ydisp&&this._scrollToBottom(),t&&this._onUserInput.fire(),this._logService.debug('sending data "'+e+'"',function(){return e.split("").map(function(e){return e.charCodeAt(0)})}),this._onData.fire(e)}},e.prototype.triggerBinaryEvent=function(e){this._optionsService.options.disableStdin||(this._logService.debug('sending binary "'+e+'"',function(){return e.split("").map(function(e){return e.charCodeAt(0)})}),this._onBinary.fire(e))},e=i([n(1,o.IBufferService),n(2,o.ILogService),n(3,o.IOptionsService)],e)}();t.CoreService=l},function(e,t,r){"use strict";var i=this&&this.__decorate||function(e,t,r,i){var n,o=arguments.length,s=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,r,i);else for(var a=e.length-1;a>=0;a--)(n=e[a])&&(s=(o<3?n(s):o>3?n(t,r,s):n(t,r))||s);return o>3&&s&&Object.defineProperty(t,r,s),s},n=this&&this.__param||function(e,t){return function(r,i){t(r,i,e)}},o=this&&this.__spreadArrays||function(){for(var e=0,t=0,r=arguments.length;t=0;a--)(n=e[a])&&(s=(o<3?n(s):o>3?n(t,r,s):n(t,r))||s);return o>3&&s&&Object.defineProperty(t,r,s),s},n=this&&this.__param||function(e,t){return function(r,i){t(r,i,e)}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(0),s=function(){function e(e){this._bufferService=e,this.clearRange()}return Object.defineProperty(e.prototype,"start",{get:function(){return this._start},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"end",{get:function(){return this._end},enumerable:!0,configurable:!0}),e.prototype.clearRange=function(){this._start=this._bufferService.buffer.y,this._end=this._bufferService.buffer.y},e.prototype.markDirty=function(e){ethis._end&&(this._end=e)},e.prototype.markRangeDirty=function(e,t){if(e>t){var r=e;e=t,t=r}ethis._end&&(this._end=t)},e.prototype.markAllDirty=function(){this.markRangeDirty(0,this._bufferService.rows-1)},e=i([n(0,o.IBufferService)],e)}();t.DirtyRowService=s},function(e,t,r){"use strict";var i=this&&this.__spreadArrays||function(){for(var e=0,t=0,r=arguments.length;t0?n[0].index:t.length;if(t.length!==u)throw new Error("[createInstance] First service dependency of "+e.name+" at position "+(u+1)+" conflicts with "+t.length+" static arguments");return new(e.bind.apply(e,i([void 0],i(t,s))))},e}();t.InstantiationService=a},function(e,t,r){"use strict";var i=this&&this.__decorate||function(e,t,r,i){var n,o=arguments.length,s=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,r,i);else for(var a=e.length-1;a>=0;a--)(n=e[a])&&(s=(o<3?n(s):o>3?n(t,r,s):n(t,r))||s);return o>3&&s&&Object.defineProperty(t,r,s),s},n=this&&this.__param||function(e,t){return function(r,i){t(r,i,e)}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(0),s=r(1),a={NONE:{events:0,restrict:function(){return!1}},X10:{events:1,restrict:function(e){return 4!==e.button&&1===e.action&&(e.ctrl=!1,e.alt=!1,e.shift=!1,!0)}},VT200:{events:19,restrict:function(e){return 32!==e.action}},DRAG:{events:23,restrict:function(e){return 32!==e.action||3!==e.button}},ANY:{events:31,restrict:function(e){return!0}}};function c(e,t){var r=(e.ctrl?16:0)|(e.shift?4:0)|(e.alt?8:0);return 4===e.button?(r|=64,r|=e.action):(r|=3&e.button,4&e.button&&(r|=64),8&e.button&&(r|=128),32===e.action?r|=32:0!==e.action||t||(r|=3)),r}var l=String.fromCharCode,h={DEFAULT:function(e){var t=[c(e,!1)+32,e.col+32,e.row+32];return t[0]>255||t[1]>255||t[2]>255?"":""+l(t[0])+l(t[1])+l(t[2])},SGR:function(e){var t=0===e.action&&4!==e.button?"m":"M";return"[<"+c(e,!0)+";"+e.col+";"+e.row+t}},u=function(){function e(e,t){var r=this;this._bufferService=e,this._coreService=t,this._protocols={},this._encodings={},this._activeProtocol="",this._activeEncoding="",this._onProtocolChange=new s.EventEmitter,this._lastEvent=null,Object.keys(a).forEach(function(e){return r.addProtocol(e,a[e])}),Object.keys(h).forEach(function(e){return r.addEncoding(e,h[e])}),this.reset()}return e.prototype.addProtocol=function(e,t){this._protocols[e]=t},e.prototype.addEncoding=function(e,t){this._encodings[e]=t},Object.defineProperty(e.prototype,"activeProtocol",{get:function(){return this._activeProtocol},set:function(e){if(!this._protocols[e])throw new Error('unknown protocol "'+e+'"');this._activeProtocol=e,this._onProtocolChange.fire(this._protocols[e].events)},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"activeEncoding",{get:function(){return this._activeEncoding},set:function(e){if(!this._encodings[e])throw new Error('unknown encoding "'+e+'"');this._activeEncoding=e},enumerable:!0,configurable:!0}),e.prototype.reset=function(){this.activeProtocol="NONE",this.activeEncoding="DEFAULT",this._lastEvent=null},Object.defineProperty(e.prototype,"onProtocolChange",{get:function(){return this._onProtocolChange.event},enumerable:!0,configurable:!0}),e.prototype.triggerMouseEvent=function(e){if(e.col<0||e.col>=this._bufferService.cols||e.row<0||e.row>=this._bufferService.rows)return!1;if(4===e.button&&32===e.action)return!1;if(3===e.button&&32!==e.action)return!1;if(4!==e.button&&(2===e.action||3===e.action))return!1;if(e.col++,e.row++,32===e.action&&this._lastEvent&&this._compareEvents(this._lastEvent,e))return!1;if(!this._protocols[this._activeProtocol].restrict(e))return!1;var t=this._encodings[this._activeEncoding](e);return t&&("DEFAULT"===this._activeEncoding?this._coreService.triggerBinaryEvent(t):this._coreService.triggerDataEvent(t,!0)),this._lastEvent=e,!0},e.prototype.explainEvents=function(e){return{DOWN:!!(1&e),UP:!!(2&e),DRAG:!!(4&e),MOVE:!!(8&e),WHEEL:!!(16&e)}},e.prototype._compareEvents=function(e,t){return e.col===t.col&&(e.row===t.row&&(e.button===t.button&&(e.action===t.action&&(e.ctrl===t.ctrl&&(e.alt===t.alt&&e.shift===t.shift)))))},e=i([n(0,o.IBufferService),n(1,o.ICoreService)],e)}();t.CoreMouseService=u},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=function(){function e(e){this._action=e,this._writeBuffer=[],this._callbacks=[],this._pendingData=0,this._bufferOffset=0}return e.prototype.writeSync=function(e){if(this._writeBuffer.length){for(var t=this._bufferOffset;t5e7)throw new Error("write data discarded, use flow control to avoid losing data");this._writeBuffer.length||(this._bufferOffset=0,setTimeout(function(){return r._innerWrite()})),this._pendingData+=e.length,this._writeBuffer.push(e),this._callbacks.push(t)},e.prototype._innerWrite=function(){for(var e=this,t=Date.now();this._writeBuffer.length>this._bufferOffset;){var r=this._writeBuffer[this._bufferOffset],i=this._callbacks[this._bufferOffset];if(this._bufferOffset++,this._action(r),this._pendingData-=r.length,i&&i(),Date.now()-t>=12)break}this._writeBuffer.length>this._bufferOffset?(this._bufferOffset>50&&(this._writeBuffer=this._writeBuffer.slice(this._bufferOffset),this._callbacks=this._callbacks.slice(this._bufferOffset),this._bufferOffset=0),setTimeout(function(){return e._innerWrite()},0)):(this._writeBuffer=[],this._callbacks=[],this._pendingData=0,this._bufferOffset=0)},e}();t.WriteBuffer=i},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=function(){function e(e){this._textarea=e}return Object.defineProperty(e.prototype,"isFocused",{get:function(){return document.activeElement===this._textarea&&document.hasFocus()},enumerable:!0,configurable:!0}),e}();t.CoreBrowserService=i},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=function(){function e(){this._addons=[]}return e.prototype.dispose=function(){for(var e=this._addons.length-1;e>=0;e--)this._addons[e].instance.dispose()},e.prototype.loadAddon=function(e,t){var r=this,i={instance:t,dispose:t.dispose,isDisposed:!1};this._addons.push(i),t.dispose=function(){return r._wrappedAddonDispose(i)},t.activate(e)},e.prototype._wrappedAddonDispose=function(e){if(!e.isDisposed){for(var t=-1,r=0;r>22},t.prototype.getChars=function(){return 2097152&this.content?this.combinedData:2097151&this.content?o.stringFromCodePoint(2097151&this.content):""},t.prototype.getCode=function(){return this.isCombined()?this.combinedData.charCodeAt(this.combinedData.length-1):2097151&this.content},t.prototype.setFromCharData=function(e){this.fg=e[s.CHAR_DATA_ATTR_INDEX],this.bg=0;var t=!1;if(e[s.CHAR_DATA_CHAR_INDEX].length>2)t=!0;else if(2===e[s.CHAR_DATA_CHAR_INDEX].length){var r=e[s.CHAR_DATA_CHAR_INDEX].charCodeAt(0);if(55296<=r&&r<=56319){var i=e[s.CHAR_DATA_CHAR_INDEX].charCodeAt(1);56320<=i&&i<=57343?this.content=1024*(r-55296)+i-56320+65536|e[s.CHAR_DATA_WIDTH_INDEX]<<22:t=!0}else t=!0}else this.content=e[s.CHAR_DATA_CHAR_INDEX].charCodeAt(0)|e[s.CHAR_DATA_WIDTH_INDEX]<<22;t&&(this.combinedData=e[s.CHAR_DATA_CHAR_INDEX],this.content=2097152|e[s.CHAR_DATA_WIDTH_INDEX]<<22)},t.prototype.getAsCharData=function(){return[this.fg,this.getChars(),this.getWidth(),this.getCode()]},t}(r(6).AttributeData);t.CellData=a},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=function(){function e(){this.fg=0,this.bg=0}return e.toColorRGB=function(e){return[e>>>16&255,e>>>8&255,255&e]},e.fromColorRGB=function(e){return(255&e[0])<<16|(255&e[1])<<8|255&e[2]},e.prototype.clone=function(){var t=new e;return t.fg=this.fg,t.bg=this.bg,t},e.prototype.isInverse=function(){return 67108864&this.fg},e.prototype.isBold=function(){return 134217728&this.fg},e.prototype.isUnderline=function(){return 268435456&this.fg},e.prototype.isBlink=function(){return 536870912&this.fg},e.prototype.isInvisible=function(){return 1073741824&this.fg},e.prototype.isItalic=function(){return 67108864&this.bg},e.prototype.isDim=function(){return 134217728&this.bg},e.prototype.getFgColorMode=function(){return 50331648&this.fg},e.prototype.getBgColorMode=function(){return 50331648&this.bg},e.prototype.isFgRGB=function(){return 50331648==(50331648&this.fg)},e.prototype.isBgRGB=function(){return 50331648==(50331648&this.bg)},e.prototype.isFgPalette=function(){return 16777216==(50331648&this.fg)||33554432==(50331648&this.fg)},e.prototype.isBgPalette=function(){return 16777216==(50331648&this.bg)||33554432==(50331648&this.bg)},e.prototype.isFgDefault=function(){return 0==(50331648&this.fg)},e.prototype.isBgDefault=function(){return 0==(50331648&this.bg)},e.prototype.isAttributeDefault=function(){return 0===this.fg&&0===this.bg},e.prototype.getFgColor=function(){switch(50331648&this.fg){case 16777216:case 33554432:return 255&this.fg;case 50331648:return 16777215&this.fg;default:return-1}},e.prototype.getBgColor=function(){switch(50331648&this.bg){case 16777216:case 33554432:return 255&this.bg;case 50331648:return 16777215&this.bg;default:return-1}},e}();t.AttributeData=i},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.stringFromCodePoint=function(e){return e>65535?(e-=65536,String.fromCharCode(55296+(e>>10))+String.fromCharCode(e%1024+56320)):String.fromCharCode(e)},t.utf32ToString=function(e,t,r){void 0===t&&(t=0),void 0===r&&(r=e.length);for(var i="",n=t;n65535?(o-=65536,i+=String.fromCharCode(55296+(o>>10))+String.fromCharCode(o%1024+56320)):i+=String.fromCharCode(o)}return i};var i=function(){function e(){this._interim=0}return e.prototype.clear=function(){this._interim=0},e.prototype.decode=function(e,t){var r=e.length;if(!r)return 0;var i=0,n=0;this._interim&&(56320<=(a=e.charCodeAt(n++))&&a<=57343?t[i++]=1024*(this._interim-55296)+a-56320+65536:(t[i++]=this._interim,t[i++]=a),this._interim=0);for(var o=n;o=r)return this._interim=s,i;var a;56320<=(a=e.charCodeAt(o))&&a<=57343?t[i++]=1024*(s-55296)+a-56320+65536:(t[i++]=s,t[i++]=a)}else t[i++]=s}return i},e}();t.StringToUtf32=i;var n=function(){function e(){this.interim=new Uint8Array(3)}return e.prototype.clear=function(){this.interim.fill(0)},e.prototype.decode=function(e,t){var r=e.length;if(!r)return 0;var i,n,o,s,a=0,c=0,l=0;if(this.interim[0]){var h=!1,u=this.interim[0];u&=192==(224&u)?31:224==(240&u)?15:7;for(var f=0,_=void 0;(_=63&this.interim[++f])&&f<4;)u<<=6,u|=_;for(var d=192==(224&this.interim[0])?2:224==(240&this.interim[0])?3:4,p=d-f;l=r)return 0;if(128!=(192&(_=e[l++]))){l--,h=!0;break}this.interim[f++]=_,u<<=6,u|=63&_}h||(2===d?u<128?l--:t[a++]=u:3===d?u<2048||u>=55296&&u<=57343||(t[a++]=u):u<65536||u>1114111||(t[a++]=u)),this.interim.fill(0)}for(var v=r-4,g=l;g=r)return this.interim[0]=i,a;if(128!=(192&(n=e[g++]))){g--;continue}if((c=(31&i)<<6|63&n)<128){g--;continue}t[a++]=c}else if(224==(240&i)){if(g>=r)return this.interim[0]=i,a;if(128!=(192&(n=e[g++]))){g--;continue}if(g>=r)return this.interim[0]=i,this.interim[1]=n,a;if(128!=(192&(o=e[g++]))){g--;continue}if((c=(15&i)<<12|(63&n)<<6|63&o)<2048||c>=55296&&c<=57343)continue;t[a++]=c}else if(240==(248&i)){if(g>=r)return this.interim[0]=i,a;if(128!=(192&(n=e[g++]))){g--;continue}if(g>=r)return this.interim[0]=i,this.interim[1]=n,a;if(128!=(192&(o=e[g++]))){g--;continue}if(g>=r)return this.interim[0]=i,this.interim[1]=n,this.interim[2]=o,a;if(128!=(192&(s=e[g++]))){g--;continue}if((c=(7&i)<<18|(63&n)<<12|(63&o)<<6|63&s)<65536||c>1114111)continue;t[a++]=c}}return a},e}();t.Utf8ToUtf32=n},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.addDisposableDomListener=function(e,t,r,i){e.addEventListener(t,r,i);var n=!1;return{dispose:function(){n&&(n=!0,e.removeEventListener(t,r,i))}}}},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.INVERTED_DEFAULT_COLOR=257,t.DIM_OPACITY=.5,t.CHAR_ATLAS_CELL_SPACING=1},function(e,t,r){"use strict";var i,n,o,s;function a(e){var t=e.toString(16);return t.length<2?"0"+t:t}function c(e,t){return e>>0}}(i=t.channels||(t.channels={})),(n=t.color||(t.color={})).blend=function(e,t){var r=(255&t.rgba)/255;if(1===r)return{css:t.css,rgba:t.rgba};var n=t.rgba>>24&255,o=t.rgba>>16&255,s=t.rgba>>8&255,a=e.rgba>>24&255,c=e.rgba>>16&255,l=e.rgba>>8&255,h=a+Math.round((n-a)*r),u=c+Math.round((o-c)*r),f=l+Math.round((s-l)*r);return{css:i.toCss(h,u,f),rgba:i.toRgba(h,u,f)}},n.ensureContrastRatio=function(e,t,r){var i=s.ensureContrastRatio(e.rgba,t.rgba,r);if(i)return s.toColor(i>>24&255,i>>16&255,i>>8&255)},n.opaque=function(e){var t=(255|e.rgba)>>>0,r=s.toChannels(t),n=r[0],o=r[1],a=r[2];return{css:i.toCss(n,o,a),rgba:t}},(t.css||(t.css={})).toColor=function(e){return{css:e,rgba:(parseInt(e.slice(1),16)<<8|255)>>>0}},function(e){function t(e,t,r){var i=e/255,n=t/255,o=r/255;return.2126*(i<=.03928?i/12.92:Math.pow((i+.055)/1.055,2.4))+.7152*(n<=.03928?n/12.92:Math.pow((n+.055)/1.055,2.4))+.0722*(o<=.03928?o/12.92:Math.pow((o+.055)/1.055,2.4))}e.relativeLuminance=function(e){return t(e>>16&255,e>>8&255,255&e)},e.relativeLuminance2=t}(o=t.rgb||(t.rgb={})),function(e){function t(e,t,r){for(var i=e>>24&255,n=e>>16&255,s=e>>8&255,a=t>>24&255,l=t>>16&255,h=t>>8&255,u=c(o.relativeLuminance2(a,h,l),o.relativeLuminance2(i,n,s));u0||l>0||h>0);)a-=Math.max(0,Math.ceil(.1*a)),l-=Math.max(0,Math.ceil(.1*l)),h-=Math.max(0,Math.ceil(.1*h)),u=c(o.relativeLuminance2(a,h,l),o.relativeLuminance2(i,n,s));return(a<<24|l<<16|h<<8|255)>>>0}function r(e,t,r){for(var i=e>>24&255,n=e>>16&255,s=e>>8&255,a=t>>24&255,l=t>>16&255,h=t>>8&255,u=c(o.relativeLuminance2(a,h,l),o.relativeLuminance2(i,n,s));u>>0}e.ensureContrastRatio=function(e,i,n){var s=o.relativeLuminance(e>>8),a=o.relativeLuminance(i>>8);if(c(s,a)>24&255,e>>16&255,e>>8&255,255&e]},e.toColor=function(e,t,r){return{css:i.toCss(e,t,r),rgba:i.toRgba(e,t,r)}}}(s=t.rgba||(t.rgba={})),t.toPaddedHex=a,t.contrastRatio=c},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i="undefined"==typeof navigator,n=i?"node":navigator.userAgent,o=i?"node":navigator.platform;function s(e,t){return e.indexOf(t)>=0}t.isFirefox=!!~n.indexOf("Firefox"),t.isSafari=/^((?!chrome|android).)*safari/i.test(n),t.isMac=s(["Macintosh","MacIntel","MacPPC","Mac68K"],o),t.isIpad="iPad"===o,t.isIphone="iPhone"===o,t.isWindows=s(["Windows","Win16","Win32","WinCE"],o),t.isLinux=o.indexOf("Linux")>=0},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),function(e){e.NUL="\0",e.SOH="",e.STX="",e.ETX="",e.EOT="",e.ENQ="",e.ACK="",e.BEL="",e.BS="\b",e.HT="\t",e.LF="\n",e.VT="\v",e.FF="\f",e.CR="\r",e.SO="",e.SI="",e.DLE="",e.DC1="",e.DC2="",e.DC3="",e.DC4="",e.NAK="",e.SYN="",e.ETB="",e.CAN="",e.EM="",e.SUB="",e.ESC="",e.FS="",e.GS="",e.RS="",e.US="",e.SP=" ",e.DEL=""}(t.C0||(t.C0={})),function(e){e.PAD="€",e.HOP="",e.BPH="‚",e.NBH="ƒ",e.IND="„",e.NEL="…",e.SSA="†",e.ESA="‡",e.HTS="ˆ",e.HTJ="‰",e.VTS="Š",e.PLD="‹",e.PLU="Œ",e.RI="",e.SS2="Ž",e.SS3="",e.DCS="",e.PU1="‘",e.PU2="’",e.STS="“",e.CCH="”",e.MW="•",e.SPA="–",e.EPA="—",e.SOS="˜",e.SGCI="™",e.SCI="š",e.CSI="›",e.ST="œ",e.OSC="",e.PM="ž",e.APC="Ÿ"}(t.C1||(t.C1={}))},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=r(3),n=r(9),o=r(23),s=r(6),a=r(26),c=r(10),l=function(){function e(e,t,r,i,n,o,s,a){this._container=e,this._alpha=i,this._colors=n,this._rendererId=o,this._bufferService=s,this._optionsService=a,this._scaledCharWidth=0,this._scaledCharHeight=0,this._scaledCellWidth=0,this._scaledCellHeight=0,this._scaledCharLeft=0,this._scaledCharTop=0,this._currentGlyphIdentifier={chars:"",code:0,bg:0,fg:0,bold:!1,dim:!1,italic:!1},this._canvas=document.createElement("canvas"),this._canvas.classList.add("xterm-"+t+"-layer"),this._canvas.style.zIndex=r.toString(),this._initCanvas(),this._container.appendChild(this._canvas)}return e.prototype.dispose=function(){var e;this._container.removeChild(this._canvas),null===(e=this._charAtlas)||void 0===e||e.dispose()},e.prototype._initCanvas=function(){this._ctx=a.throwIfFalsy(this._canvas.getContext("2d",{alpha:this._alpha})),this._alpha||this._clearAll()},e.prototype.onOptionsChanged=function(){},e.prototype.onBlur=function(){},e.prototype.onFocus=function(){},e.prototype.onCursorMove=function(){},e.prototype.onGridChanged=function(e,t){},e.prototype.onSelectionChanged=function(e,t,r){void 0===r&&(r=!1)},e.prototype.setColors=function(e){this._refreshCharAtlas(e)},e.prototype._setTransparency=function(e){if(e!==this._alpha){var t=this._canvas;this._alpha=e,this._canvas=this._canvas.cloneNode(),this._initCanvas(),this._container.replaceChild(this._canvas,t),this._refreshCharAtlas(this._colors),this.onGridChanged(0,this._bufferService.rows-1)}},e.prototype._refreshCharAtlas=function(e){this._scaledCharWidth<=0&&this._scaledCharHeight<=0||(this._charAtlas=o.acquireCharAtlas(this._optionsService.options,this._rendererId,e,this._scaledCharWidth,this._scaledCharHeight),this._charAtlas.warmUp())},e.prototype.resize=function(e){this._scaledCellWidth=e.scaledCellWidth,this._scaledCellHeight=e.scaledCellHeight,this._scaledCharWidth=e.scaledCharWidth,this._scaledCharHeight=e.scaledCharHeight,this._scaledCharLeft=e.scaledCharLeft,this._scaledCharTop=e.scaledCharTop,this._canvas.width=e.scaledCanvasWidth,this._canvas.height=e.scaledCanvasHeight,this._canvas.style.width=e.canvasWidth+"px",this._canvas.style.height=e.canvasHeight+"px",this._alpha||this._clearAll(),this._refreshCharAtlas(this._colors)},e.prototype._fillCells=function(e,t,r,i){this._ctx.fillRect(e*this._scaledCellWidth,t*this._scaledCellHeight,r*this._scaledCellWidth,i*this._scaledCellHeight)},e.prototype._fillBottomLineAtCells=function(e,t,r){void 0===r&&(r=1),this._ctx.fillRect(e*this._scaledCellWidth,(t+1)*this._scaledCellHeight-window.devicePixelRatio-1,r*this._scaledCellWidth,window.devicePixelRatio)},e.prototype._fillLeftLineAtCell=function(e,t,r){this._ctx.fillRect(e*this._scaledCellWidth,t*this._scaledCellHeight,window.devicePixelRatio*r,this._scaledCellHeight)},e.prototype._strokeRectAtCell=function(e,t,r,i){this._ctx.lineWidth=window.devicePixelRatio,this._ctx.strokeRect(e*this._scaledCellWidth+window.devicePixelRatio/2,t*this._scaledCellHeight+window.devicePixelRatio/2,r*this._scaledCellWidth-window.devicePixelRatio,i*this._scaledCellHeight-window.devicePixelRatio)},e.prototype._clearAll=function(){this._alpha?this._ctx.clearRect(0,0,this._canvas.width,this._canvas.height):(this._ctx.fillStyle=this._colors.background.css,this._ctx.fillRect(0,0,this._canvas.width,this._canvas.height))},e.prototype._clearCells=function(e,t,r,i){this._alpha?this._ctx.clearRect(e*this._scaledCellWidth,t*this._scaledCellHeight,r*this._scaledCellWidth,i*this._scaledCellHeight):(this._ctx.fillStyle=this._colors.background.css,this._ctx.fillRect(e*this._scaledCellWidth,t*this._scaledCellHeight,r*this._scaledCellWidth,i*this._scaledCellHeight))},e.prototype._fillCharTrueColor=function(e,t,r){this._ctx.font=this._getFont(!1,!1),this._ctx.textBaseline="middle",this._clipRow(r),this._ctx.fillText(e.getChars(),t*this._scaledCellWidth+this._scaledCharLeft,r*this._scaledCellHeight+this._scaledCharTop+this._scaledCharHeight/2)},e.prototype._drawChars=function(e,t,r){var o,s,a=this._getContrastColor(e);a||e.isFgRGB()||e.isBgRGB()?this._drawUncachedChars(e,t,r,a):(e.isInverse()?(o=e.isBgDefault()?n.INVERTED_DEFAULT_COLOR:e.getBgColor(),s=e.isFgDefault()?n.INVERTED_DEFAULT_COLOR:e.getFgColor()):(s=e.isBgDefault()?i.DEFAULT_COLOR:e.getBgColor(),o=e.isFgDefault()?i.DEFAULT_COLOR:e.getFgColor()),o+=this._optionsService.options.drawBoldTextInBrightColors&&e.isBold()&&o<8?8:0,this._currentGlyphIdentifier.chars=e.getChars()||i.WHITESPACE_CELL_CHAR,this._currentGlyphIdentifier.code=e.getCode()||i.WHITESPACE_CELL_CODE,this._currentGlyphIdentifier.bg=s,this._currentGlyphIdentifier.fg=o,this._currentGlyphIdentifier.bold=!!e.isBold(),this._currentGlyphIdentifier.dim=!!e.isDim(),this._currentGlyphIdentifier.italic=!!e.isItalic(),this._charAtlas&&this._charAtlas.draw(this._ctx,this._currentGlyphIdentifier,t*this._scaledCellWidth+this._scaledCharLeft,r*this._scaledCellHeight+this._scaledCharTop)||this._drawUncachedChars(e,t,r))},e.prototype._drawUncachedChars=function(e,t,r,i){if(this._ctx.save(),this._ctx.font=this._getFont(!!e.isBold(),!!e.isItalic()),this._ctx.textBaseline="middle",e.isInverse())if(i)this._ctx.fillStyle=i.css;else if(e.isBgDefault())this._ctx.fillStyle=c.color.opaque(this._colors.background).css;else if(e.isBgRGB())this._ctx.fillStyle="rgb("+s.AttributeData.toColorRGB(e.getBgColor()).join(",")+")";else{var o=e.getBgColor();this._optionsService.options.drawBoldTextInBrightColors&&e.isBold()&&o<8&&(o+=8),this._ctx.fillStyle=this._colors.ansi[o].css}else if(i)this._ctx.fillStyle=i.css;else if(e.isFgDefault())this._ctx.fillStyle=this._colors.foreground.css;else if(e.isFgRGB())this._ctx.fillStyle="rgb("+s.AttributeData.toColorRGB(e.getFgColor()).join(",")+")";else{var a=e.getFgColor();this._optionsService.options.drawBoldTextInBrightColors&&e.isBold()&&a<8&&(a+=8),this._ctx.fillStyle=this._colors.ansi[a].css}this._clipRow(r),e.isDim()&&(this._ctx.globalAlpha=n.DIM_OPACITY),this._ctx.fillText(e.getChars(),t*this._scaledCellWidth+this._scaledCharLeft,r*this._scaledCellHeight+this._scaledCharTop+this._scaledCharHeight/2),this._ctx.restore()},e.prototype._clipRow=function(e){this._ctx.beginPath(),this._ctx.rect(0,e*this._scaledCellHeight,this._bufferService.cols*this._scaledCellWidth,this._scaledCellHeight),this._ctx.clip()},e.prototype._getFont=function(e,t){return(t?"italic":"")+" "+(e?this._optionsService.options.fontWeightBold:this._optionsService.options.fontWeight)+" "+this._optionsService.options.fontSize*window.devicePixelRatio+"px "+this._optionsService.options.fontFamily},e.prototype._getContrastColor=function(e){if(1!==this._optionsService.options.minimumContrastRatio){var t=this._colors.contrastCache.getColor(e.bg,e.fg);if(void 0!==t)return t||void 0;var r=e.getFgColor(),i=e.getFgColorMode(),n=e.getBgColor(),o=e.getBgColorMode(),s=!!e.isInverse(),a=!!e.isInverse();if(s){var l=r;r=n,n=l;var h=i;i=o,o=h}var u=this._resolveBackgroundRgba(o,n,s),f=this._resolveForegroundRgba(i,r,s,a),_=c.rgba.ensureContrastRatio(u,f,this._optionsService.options.minimumContrastRatio);if(_){var d={css:c.channels.toCss(_>>24&255,_>>16&255,_>>8&255),rgba:_};return this._colors.contrastCache.setColor(e.bg,e.fg,d),d}this._colors.contrastCache.setColor(e.bg,e.fg,null)}},e.prototype._resolveBackgroundRgba=function(e,t,r){switch(e){case 16777216:case 33554432:return this._colors.ansi[t].rgba;case 50331648:return t<<8;case 0:default:return r?this._colors.foreground.rgba:this._colors.background.rgba}},e.prototype._resolveForegroundRgba=function(e,t,r,i){switch(e){case 16777216:case 33554432:return this._optionsService.options.drawBoldTextInBrightColors&&i&&t<8&&(t+=8),this._colors.ansi[t].rgba;case 50331648:return t<<8;case 0:default:return r?this._colors.background.rgba:this._colors.foreground.rgba}},e}();t.BaseRenderLayer=l},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i="di$target",n="di$dependencies";function o(e,t,r){t[i]===t?t[n].push({id:e,index:r}):(t[n]=[{id:e,index:r}],t[i]=t)}t.serviceRegistry=new Map,t.getServiceDependencies=function(e){return e[n]||[]},t.createDecorator=function(e){if(t.serviceRegistry.has(e))return t.serviceRegistry.get(e);var r=function(e,t,i){if(3!==arguments.length)throw new Error("@IServiceName-decorator can only be used to decorate a parameter");o(r,e,i)};return r.toString=function(){return e},t.serviceRegistry.set(e,r),r}},function(e,t,r){"use strict";function i(e,t,r,i){if(void 0===r&&(r=0),void 0===i&&(i=e.length),r>=e.length)return e;r=(e.length+r)%e.length,i=i>=e.length?e.length:(e.length+i)%e.length;for(var n=r;n>22,2097152&t?this._combined[e].charCodeAt(this._combined[e].length-1):r]},e.prototype.set=function(e,t){this._data[e*a+1]=t[n.CHAR_DATA_ATTR_INDEX],t[n.CHAR_DATA_CHAR_INDEX].length>1?(this._combined[e]=t[1],this._data[e*a+0]=2097152|e|t[n.CHAR_DATA_WIDTH_INDEX]<<22):this._data[e*a+0]=t[n.CHAR_DATA_CHAR_INDEX].charCodeAt(0)|t[n.CHAR_DATA_WIDTH_INDEX]<<22},e.prototype.getWidth=function(e){return this._data[e*a+0]>>22},e.prototype.hasWidth=function(e){return 12582912&this._data[e*a+0]},e.prototype.getFg=function(e){return this._data[e*a+1]},e.prototype.getBg=function(e){return this._data[e*a+2]},e.prototype.hasContent=function(e){return 4194303&this._data[e*a+0]},e.prototype.getCodePoint=function(e){var t=this._data[e*a+0];return 2097152&t?this._combined[e].charCodeAt(this._combined[e].length-1):2097151&t},e.prototype.isCombined=function(e){return 2097152&this._data[e*a+0]},e.prototype.getString=function(e){var t=this._data[e*a+0];return 2097152&t?this._combined[e]:2097151&t?i.stringFromCodePoint(2097151&t):""},e.prototype.loadCell=function(e,t){var r=e*a;return t.content=this._data[r+0],t.fg=this._data[r+1],t.bg=this._data[r+2],2097152&t.content&&(t.combinedData=this._combined[e]),t},e.prototype.setCell=function(e,t){2097152&t.content&&(this._combined[e]=t.combinedData),this._data[e*a+0]=t.content,this._data[e*a+1]=t.fg,this._data[e*a+2]=t.bg},e.prototype.setCellFromCodePoint=function(e,t,r,i,n){this._data[e*a+0]=t|r<<22,this._data[e*a+1]=i,this._data[e*a+2]=n},e.prototype.addCodepointToCell=function(e,t){var r=this._data[e*a+0];2097152&r?this._combined[e]+=i.stringFromCodePoint(t):(2097151&r?(this._combined[e]=i.stringFromCodePoint(2097151&r)+i.stringFromCodePoint(t),r&=-2097152,r|=2097152):r=t|1<<22,this._data[e*a+0]=r)},e.prototype.insertCells=function(e,t,r,i){var n,s,a,c;if((e%=this.length)&&2===this.getWidth(e-1)&&this.setCellFromCodePoint(e-1,0,1,(null===(n=i)||void 0===n?void 0:n.fg)||0,(null===(s=i)||void 0===s?void 0:s.bg)||0),t=0;--h)this.setCell(e+t+h,this.loadCell(e+h,l));for(h=0;hthis.length){var r=new Uint32Array(e*a);this.length&&(e*a=e&&delete this._combined[o]}}else this._data=new Uint32Array(0),this._combined={};this.length=e}},e.prototype.fill=function(e){this._combined={};for(var t=0;t=0;--e)if(4194303&this._data[e*a+0])return e+(this._data[e*a+0]>>22);return 0},e.prototype.copyCellsFrom=function(e,t,r,i,n){var o=e._data;if(n)for(var s=i-1;s>=0;s--)for(var c=0;c=t&&(this._combined[h-t+r]=e._combined[h])}},e.prototype.translateToString=function(e,t,r){void 0===e&&(e=!1),void 0===t&&(t=0),void 0===r&&(r=this.length),e&&(r=Math.min(r,this.getTrimmedLength()));for(var o="";t>22||1}return o},e}();t.BufferLine=c},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.promptLabel="Terminal input",t.tooMuchOutput="Too much output to announce, navigate to rows manually to read"},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.CHARSETS={},t.DEFAULT_CHARSET=t.CHARSETS.B,t.CHARSETS[0]={"`":"◆",a:"▒",b:"␉",c:"␌",d:"␍",e:"␊",f:"°",g:"±",h:"␤",i:"␋",j:"┘",k:"┐",l:"┌",m:"└",n:"┼",o:"⎺",p:"⎻",q:"─",r:"⎼",s:"⎽",t:"├",u:"┤",v:"┴",w:"┬",x:"│",y:"≤",z:"≥","{":"π","|":"≠","}":"£","~":"·"},t.CHARSETS.A={"#":"£"},t.CHARSETS.B=null,t.CHARSETS[4]={"#":"£","@":"¾","[":"ij","\\":"½","]":"|","{":"¨","|":"f","}":"¼","~":"´"},t.CHARSETS.C=t.CHARSETS[5]={"[":"Ä","\\":"Ö","]":"Å","^":"Ü","`":"é","{":"ä","|":"ö","}":"å","~":"ü"},t.CHARSETS.R={"#":"£","@":"à","[":"°","\\":"ç","]":"§","{":"é","|":"ù","}":"è","~":"¨"},t.CHARSETS.Q={"@":"à","[":"â","\\":"ç","]":"ê","^":"î","`":"ô","{":"é","|":"ù","}":"è","~":"û"},t.CHARSETS.K={"@":"§","[":"Ä","\\":"Ö","]":"Ü","{":"ä","|":"ö","}":"ü","~":"ß"},t.CHARSETS.Y={"#":"£","@":"§","[":"°","\\":"ç","]":"é","`":"ù","{":"à","|":"ò","}":"è","~":"ì"},t.CHARSETS.E=t.CHARSETS[6]={"@":"Ä","[":"Æ","\\":"Ø","]":"Å","^":"Ü","`":"ä","{":"æ","|":"ø","}":"å","~":"ü"},t.CHARSETS.Z={"#":"£","@":"§","[":"¡","\\":"Ñ","]":"¿","{":"°","|":"ñ","}":"ç"},t.CHARSETS.H=t.CHARSETS[7]={"@":"É","[":"Ä","\\":"Ö","]":"Å","^":"Ü","`":"é","{":"ä","|":"ö","}":"å","~":"ü"},t.CHARSETS["="]={"#":"ù","@":"à","[":"é","\\":"ç","]":"ê","^":"î",_:"è","`":"ô","{":"ä","|":"ö","}":"ü","~":"û"}},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=256,n=function(){function e(e,t){if(void 0===e&&(e=32),void 0===t&&(t=32),this.maxLength=e,this.maxSubParamsLength=t,t>i)throw new Error("maxSubParamsLength must not be greater than 256");this.params=new Int32Array(e),this.length=0,this._subParams=new Int32Array(t),this._subParamsLength=0,this._subParamsIdx=new Uint16Array(e),this._rejectDigits=!1,this._rejectSubDigits=!1,this._digitIsSub=!1}return e.fromArray=function(t){var r=new e;if(!t.length)return r;for(var i=t[0]instanceof Array?1:0;i>8,i=255&this._subParamsIdx[t];i-r>0&&e.push(Array.prototype.slice.call(this._subParams,r,i))}return e},e.prototype.reset=function(){this.length=0,this._subParamsLength=0,this._rejectDigits=!1,this._rejectSubDigits=!1,this._digitIsSub=!1},e.prototype.addParam=function(e){if(this._digitIsSub=!1,this.length>=this.maxLength)this._rejectDigits=!0;else{if(e<-1)throw new Error("values lesser than -1 are not allowed");this._subParamsIdx[this.length]=this._subParamsLength<<8|this._subParamsLength,this.params[this.length++]=e>2147483647?2147483647:e}},e.prototype.addSubParam=function(e){if(this._digitIsSub=!0,this.length)if(this._rejectDigits||this._subParamsLength>=this.maxSubParamsLength)this._rejectSubDigits=!0;else{if(e<-1)throw new Error("values lesser than -1 are not allowed");this._subParams[this._subParamsLength++]=e>2147483647?2147483647:e,this._subParamsIdx[this.length-1]++}},e.prototype.hasSubParams=function(e){return(255&this._subParamsIdx[e])-(this._subParamsIdx[e]>>8)>0},e.prototype.getSubParams=function(e){var t=this._subParamsIdx[e]>>8,r=255&this._subParamsIdx[e];return r-t>0?this._subParams.subarray(t,r):null},e.prototype.getSubParamsAll=function(){for(var e={},t=0;t>8,i=255&this._subParamsIdx[t];i-r>0&&(e[t]=this._subParams.slice(r,i))}return e},e.prototype.addDigit=function(e){var t;if(!(this._rejectDigits||!(t=this._digitIsSub?this._subParamsLength:this.length)||this._digitIsSub&&this._rejectSubDigits)){var r=this._digitIsSub?this._subParams:this.params,i=r[t-1];r[t-1]=~i?Math.min(10*i+e,2147483647):e}},e}();t.Params=n},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=r(21),n=r(7),o=function(){function e(){this._state=0,this._id=-1,this._handlers=Object.create(null),this._handlerFb=function(){}}return e.prototype.addHandler=function(e,t){void 0===this._handlers[e]&&(this._handlers[e]=[]);var r=this._handlers[e];return r.push(t),{dispose:function(){var e=r.indexOf(t);-1!==e&&r.splice(e,1)}}},e.prototype.setHandler=function(e,t){this._handlers[e]=[t]},e.prototype.clearHandler=function(e){this._handlers[e]&&delete this._handlers[e]},e.prototype.setHandlerFallback=function(e){this._handlerFb=e},e.prototype.dispose=function(){this._handlers=Object.create(null),this._handlerFb=function(){}},e.prototype.reset=function(){2===this._state&&this.end(!1),this._id=-1,this._state=0},e.prototype._start=function(){var e=this._handlers[this._id];if(e)for(var t=e.length-1;t>=0;t--)e[t].start();else this._handlerFb(this._id,"START")},e.prototype._put=function(e,t,r){var i=this._handlers[this._id];if(i)for(var o=i.length-1;o>=0;o--)i[o].put(e,t,r);else this._handlerFb(this._id,"PUT",n.utf32ToString(e,t,r))},e.prototype._end=function(e){var t=this._handlers[this._id];if(t){for(var r=t.length-1;r>=0&&!1===t[r].end(e);r--);for(r--;r>=0;r--)t[r].end(!1)}else this._handlerFb(this._id,"END",e)},e.prototype.start=function(){this.reset(),this._id=-1,this._state=1},e.prototype.put=function(e,t,r){if(3!==this._state){if(1===this._state)for(;t0&&this._put(e,t,r)}},e.prototype.end=function(e){0!==this._state&&(3!==this._state&&(1===this._state&&this._start(),this._end(e)),this._id=-1,this._state=0)},e}();t.OscParser=o;var s=function(){function e(e){this._handler=e,this._data="",this._hitLimit=!1}return e.prototype.start=function(){this._data="",this._hitLimit=!1},e.prototype.put=function(e,t,r){this._hitLimit||(this._data+=n.utf32ToString(e,t,r),this._data.length>i.PAYLOAD_LIMIT&&(this._data="",this._hitLimit=!0))},e.prototype.end=function(e){var t;return this._hitLimit?t=!1:e&&(t=this._handler(this._data)),this._data="",this._hitLimit=!1,t},e}();t.OscHandler=s},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.PAYLOAD_LIMIT=1e7},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=r(7),n=r(19),o=r(21),s=[],a=function(){function e(){this._handlers=Object.create(null),this._active=s,this._ident=0,this._handlerFb=function(){}}return e.prototype.dispose=function(){this._handlers=Object.create(null),this._handlerFb=function(){}},e.prototype.addHandler=function(e,t){void 0===this._handlers[e]&&(this._handlers[e]=[]);var r=this._handlers[e];return r.push(t),{dispose:function(){var e=r.indexOf(t);-1!==e&&r.splice(e,1)}}},e.prototype.setHandler=function(e,t){this._handlers[e]=[t]},e.prototype.clearHandler=function(e){this._handlers[e]&&delete this._handlers[e]},e.prototype.setHandlerFallback=function(e){this._handlerFb=e},e.prototype.reset=function(){this._active.length&&this.unhook(!1),this._active=s,this._ident=0},e.prototype.hook=function(e,t){if(this.reset(),this._ident=e,this._active=this._handlers[e]||s,this._active.length)for(var r=this._active.length-1;r>=0;r--)this._active[r].hook(t);else this._handlerFb(this._ident,"HOOK",t)},e.prototype.put=function(e,t,r){if(this._active.length)for(var n=this._active.length-1;n>=0;n--)this._active[n].put(e,t,r);else this._handlerFb(this._ident,"PUT",i.utf32ToString(e,t,r))},e.prototype.unhook=function(e){if(this._active.length){for(var t=this._active.length-1;t>=0&&!1===this._active[t].unhook(e);t--);for(t--;t>=0;t--)this._active[t].unhook(!1)}else this._handlerFb(this._ident,"UNHOOK",e);this._active=s,this._ident=0},e}();t.DcsParser=a;var c=function(){function e(e){this._handler=e,this._data="",this._hitLimit=!1}return e.prototype.hook=function(e){this._params=e.clone(),this._data="",this._hitLimit=!1},e.prototype.put=function(e,t,r){this._hitLimit||(this._data+=i.utf32ToString(e,t,r),this._data.length>o.PAYLOAD_LIMIT&&(this._data="",this._hitLimit=!0))},e.prototype.unhook=function(e){var t;return this._hitLimit?t=!1:e&&(t=this._handler(this._data,this._params?this._params:new n.Params)),this._params=void 0,this._data="",this._hitLimit=!1,t},e}();t.DcsHandler=c},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=r(24),n=r(42),o=[];t.acquireCharAtlas=function(e,t,r,s,a){for(var c=i.generateConfig(s,a,e,r),l=0;l=0){if(i.configEquals(u.config,c))return u.atlas;1===u.ownedBy.length?(u.atlas.dispose(),o.splice(l,1)):u.ownedBy.splice(h,1);break}}for(l=0;l1)for(var u=this._getJoinedRanges(i,a,o,t,n),f=0;f1)for(u=this._getJoinedRanges(i,a,o,t,n),f=0;f=this._line.length))return t?(this._line.loadCell(e,t),t):this._line.loadCell(e,new i.CellData)},e.prototype.translateToString=function(e,t,r){return this._line.translateToString(e,t,r)},e}(),h=function(){function e(e){this._core=e}return e.prototype.registerCsiHandler=function(e,t){return this._core.addCsiHandler(e,function(e){return t(e.toArray())})},e.prototype.addCsiHandler=function(e,t){return this.registerCsiHandler(e,t)},e.prototype.registerDcsHandler=function(e,t){return this._core.addDcsHandler(e,function(e,r){return t(e,r.toArray())})},e.prototype.addDcsHandler=function(e,t){return this.registerDcsHandler(e,t)},e.prototype.registerEscHandler=function(e,t){return this._core.addEscHandler(e,t)},e.prototype.addEscHandler=function(e,t){return this.registerEscHandler(e,t)},e.prototype.registerOscHandler=function(e,t){return this._core.addOscHandler(e,t)},e.prototype.addOscHandler=function(e,t){return this.registerOscHandler(e,t)},e}(),u=function(){function e(e){this._core=e}return e.prototype.register=function(e){this._core.unicodeService.register(e)},Object.defineProperty(e.prototype,"versions",{get:function(){return this._core.unicodeService.versions},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"activeVersion",{get:function(){return this._core.unicodeService.activeVersion},set:function(e){this._core.unicodeService.activeVersion=e},enumerable:!0,configurable:!0}),e}()},function(e,t,r){"use strict";var i,n=this&&this.__extends||(i=function(e,t){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])})(e,t)},function(e,t){function r(){this.constructor=e}i(e,t),e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)});Object.defineProperty(t,"__esModule",{value:!0});var o=r(34),s=r(35),a=r(36),c=r(12),l=r(37),h=r(39),u=r(49),f=r(50),_=r(11),d=r(8),p=r(17),v=r(53),g=r(54),y=r(55),b=r(56),m=r(58),S=r(1),C=r(16),w=r(59),E=r(25),L=r(60),A=r(0),R=r(61),x=r(4),k=r(62),D=r(63),T=r(2),O=r(69),M=r(70),P=r(71),H=r(72),I=r(73),B=r(74),F=r(75),j=r(76),W=r(77),q=r(79),U="undefined"!=typeof window?window.document:null,N=function(e){function t(t){void 0===t&&(t={});var r=e.call(this)||this;return r.browser=_,r.mouseEvents=0,r._keyDownHandled=!1,r._blankLine=null,r._onCursorMove=new S.EventEmitter,r._onData=new S.EventEmitter,r._onBinary=new S.EventEmitter,r._onKey=new S.EventEmitter,r._onLineFeed=new S.EventEmitter,r._onRender=new S.EventEmitter,r._onResize=new S.EventEmitter,r._onScroll=new S.EventEmitter,r._onSelectionChange=new S.EventEmitter,r._onTitleChange=new S.EventEmitter,r._onFocus=new S.EventEmitter,r._onBlur=new S.EventEmitter,r.onA11yCharEmitter=new S.EventEmitter,r.onA11yTabEmitter=new S.EventEmitter,r._instantiationService=new I.InstantiationService,r.optionsService=new R.OptionsService(t),r._instantiationService.setService(A.IOptionsService,r.optionsService),r._bufferService=r._instantiationService.createInstance(D.BufferService),r._instantiationService.setService(A.IBufferService,r._bufferService),r._logService=r._instantiationService.createInstance(P.LogService),r._instantiationService.setService(A.ILogService,r._logService),r._coreService=r._instantiationService.createInstance(M.CoreService,function(){return r.scrollToBottom()}),r._instantiationService.setService(A.ICoreService,r._coreService),r._coreService.onData(function(e){return r._onData.fire(e)}),r._coreService.onBinary(function(e){return r._onBinary.fire(e)}),r._coreMouseService=r._instantiationService.createInstance(B.CoreMouseService),r._instantiationService.setService(A.ICoreMouseService,r._coreMouseService),r._dirtyRowService=r._instantiationService.createInstance(H.DirtyRowService),r._instantiationService.setService(A.IDirtyRowService,r._dirtyRowService),r.unicodeService=r._instantiationService.createInstance(W.UnicodeService),r._instantiationService.setService(A.IUnicodeService,r.unicodeService),r._charsetService=r._instantiationService.createInstance(q.CharsetService),r._instantiationService.setService(A.ICharsetService,r._charsetService),r._setupOptionsListeners(),r._setup(),r._writeBuffer=new F.WriteBuffer(function(e){return r._inputHandler.parse(e)}),r}return n(t,e),Object.defineProperty(t.prototype,"options",{get:function(){return this.optionsService.options},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"cols",{get:function(){return this._bufferService.cols},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"rows",{get:function(){return this._bufferService.rows},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"onCursorMove",{get:function(){return this._onCursorMove.event},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"onData",{get:function(){return this._onData.event},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"onBinary",{get:function(){return this._onBinary.event},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"onKey",{get:function(){return this._onKey.event},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"onLineFeed",{get:function(){return this._onLineFeed.event},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"onRender",{get:function(){return this._onRender.event},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"onResize",{get:function(){return this._onResize.event},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"onScroll",{get:function(){return this._onScroll.event},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"onSelectionChange",{get:function(){return this._onSelectionChange.event},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"onTitleChange",{get:function(){return this._onTitleChange.event},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"onFocus",{get:function(){return this._onFocus.event},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"onBlur",{get:function(){return this._onBlur.event},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"onA11yChar",{get:function(){return this.onA11yCharEmitter.event},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"onA11yTab",{get:function(){return this.onA11yTabEmitter.event},enumerable:!0,configurable:!0}),t.prototype.dispose=function(){var t,r,i,n;this._isDisposed||(e.prototype.dispose.call(this),null===(t=this._windowsMode)||void 0===t||t.dispose(),this._windowsMode=void 0,null===(r=this._renderService)||void 0===r||r.dispose(),this._customKeyEventHandler=null,this.write=function(){},null===(n=null===(i=this.element)||void 0===i?void 0:i.parentNode)||void 0===n||n.removeChild(this.element))},t.prototype._setup=function(){var e=this;this._customKeyEventHandler=null,this.insertMode=!1,this.bracketedPasteMode=!1,this._userScrolling=!1,this._inputHandler?this._inputHandler.reset():(this._inputHandler=new l.InputHandler(this,this._bufferService,this._charsetService,this._coreService,this._dirtyRowService,this._logService,this.optionsService,this._coreMouseService,this.unicodeService,this._instantiationService),this._inputHandler.onRequestBell(function(){return e.bell()}),this._inputHandler.onRequestRefreshRows(function(t,r){return e.refresh(t,r)}),this._inputHandler.onRequestReset(function(){return e.reset()}),this._inputHandler.onCursorMove(function(){return e._onCursorMove.fire()}),this._inputHandler.onLineFeed(function(){return e._onLineFeed.fire()}),this.register(this._inputHandler)),this.linkifier||(this.linkifier=new u.Linkifier(this._bufferService,this._logService,this.optionsService,this.unicodeService)),this.options.windowsMode&&this._enableWindowsMode()},t.prototype._enableWindowsMode=function(){var e=this;if(!this._windowsMode){var t=[];t.push(this.onLineFeed(w.updateWindowsModeWrappedState.bind(null,this._bufferService))),t.push(this.addCsiHandler({final:"H"},function(){return w.updateWindowsModeWrappedState(e._bufferService),!1})),this._windowsMode={dispose:function(){t.forEach(function(e){return e.dispose()})}}}},Object.defineProperty(t.prototype,"buffer",{get:function(){return this.buffers.active},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"buffers",{get:function(){return this._bufferService.buffers},enumerable:!0,configurable:!0}),t.prototype.focus=function(){this.textarea&&this.textarea.focus({preventScroll:!0})},t.prototype._setupOptionsListeners=function(){var e=this;this.optionsService.onOptionChange(function(t){var r,i,n,o,s;switch(t){case"fontFamily":case"fontSize":null===(r=e._renderService)||void 0===r||r.clear(),null===(i=e._charSizeService)||void 0===i||i.measure();break;case"cursorBlink":case"cursorStyle":e.refresh(e.buffer.y,e.buffer.y);break;case"drawBoldTextInBrightColors":case"letterSpacing":case"lineHeight":case"fontWeight":case"fontWeightBold":case"minimumContrastRatio":e._renderService&&(e._renderService.clear(),e._renderService.onResize(e.cols,e.rows),e.refresh(0,e.rows-1));break;case"rendererType":e._renderService&&(e._renderService.setRenderer(e._createRenderer()),e._renderService.onResize(e.cols,e.rows));break;case"scrollback":e.buffers.resize(e.cols,e.rows),null===(n=e.viewport)||void 0===n||n.syncScrollArea();break;case"screenReaderMode":e.optionsService.options.screenReaderMode?!e._accessibilityManager&&e._renderService&&(e._accessibilityManager=new y.AccessibilityManager(e,e._renderService)):(null===(o=e._accessibilityManager)||void 0===o||o.dispose(),e._accessibilityManager=null);break;case"tabStopWidth":e.buffers.setupTabStops();break;case"theme":e._setTheme(e.optionsService.options.theme);break;case"windowsMode":e.optionsService.options.windowsMode?e._enableWindowsMode():(null===(s=e._windowsMode)||void 0===s||s.dispose(),e._windowsMode=void 0)}})},t.prototype._onTextAreaFocus=function(e){this.sendFocus&&this._coreService.triggerDataEvent(c.C0.ESC+"[I"),this.updateCursorStyle(e),this.element.classList.add("focus"),this.showCursor(),this._onFocus.fire()},t.prototype.blur=function(){return this.textarea.blur()},t.prototype._onTextAreaBlur=function(){this.textarea.value="",this.refresh(this.buffer.y,this.buffer.y),this.sendFocus&&this._coreService.triggerDataEvent(c.C0.ESC+"[O"),this.element.classList.remove("focus"),this._onBlur.fire()},t.prototype._initGlobal=function(){var e=this;this._bindKeys(),this.register(d.addDisposableDomListener(this.element,"copy",function(t){e.hasSelection()&&a.copyHandler(t,e._selectionService)}));var t=function(t){return a.handlePasteEvent(t,e.textarea,e.bracketedPasteMode,e._coreService)};this.register(d.addDisposableDomListener(this.textarea,"paste",t)),this.register(d.addDisposableDomListener(this.element,"paste",t)),_.isFirefox?this.register(d.addDisposableDomListener(this.element,"mousedown",function(t){2===t.button&&a.rightClickHandler(t,e.textarea,e.screenElement,e._selectionService,e.options.rightClickSelectsWord)})):this.register(d.addDisposableDomListener(this.element,"contextmenu",function(t){a.rightClickHandler(t,e.textarea,e.screenElement,e._selectionService,e.options.rightClickSelectsWord)})),_.isLinux&&this.register(d.addDisposableDomListener(this.element,"auxclick",function(t){1===t.button&&a.moveTextAreaUnderMouseCursor(t,e.textarea,e.screenElement)}))},t.prototype._bindKeys=function(){var e=this;this.register(d.addDisposableDomListener(this.textarea,"keyup",function(t){return e._keyUp(t)},!0)),this.register(d.addDisposableDomListener(this.textarea,"keydown",function(t){return e._keyDown(t)},!0)),this.register(d.addDisposableDomListener(this.textarea,"keypress",function(t){return e._keyPress(t)},!0)),this.register(d.addDisposableDomListener(this.textarea,"compositionstart",function(){return e._compositionHelper.compositionstart()})),this.register(d.addDisposableDomListener(this.textarea,"compositionupdate",function(t){return e._compositionHelper.compositionupdate(t)})),this.register(d.addDisposableDomListener(this.textarea,"compositionend",function(){return e._compositionHelper.compositionend()})),this.register(this.onRender(function(){return e._compositionHelper.updateCompositionElements()})),this.register(this.onRender(function(t){return e._queueLinkification(t.start,t.end)}))},t.prototype.open=function(e){var t=this;if(!e)throw new Error("Terminal requires a parent element.");U.body.contains(e)||this._logService.warn("Terminal.open was called on an element that was not attached to the DOM"),this._document=e.ownerDocument,this.element=this._document.createElement("div"),this.element.dir="ltr",this.element.classList.add("terminal"),this.element.classList.add("xterm"),this.element.setAttribute("tabindex","0"),e.appendChild(this.element);var r=U.createDocumentFragment();this._viewportElement=U.createElement("div"),this._viewportElement.classList.add("xterm-viewport"),r.appendChild(this._viewportElement),this._viewportScrollArea=U.createElement("div"),this._viewportScrollArea.classList.add("xterm-scroll-area"),this._viewportElement.appendChild(this._viewportScrollArea),this.screenElement=U.createElement("div"),this.screenElement.classList.add("xterm-screen"),this._helperContainer=U.createElement("div"),this._helperContainer.classList.add("xterm-helpers"),this.screenElement.appendChild(this._helperContainer),r.appendChild(this.screenElement),this.textarea=U.createElement("textarea"),this.textarea.classList.add("xterm-helper-textarea"),this.textarea.setAttribute("aria-label",p.promptLabel),this.textarea.setAttribute("aria-multiline","false"),this.textarea.setAttribute("autocorrect","off"),this.textarea.setAttribute("autocapitalize","off"),this.textarea.setAttribute("spellcheck","false"),this.textarea.tabIndex=0,this.register(d.addDisposableDomListener(this.textarea,"focus",function(e){return t._onTextAreaFocus(e)})),this.register(d.addDisposableDomListener(this.textarea,"blur",function(){return t._onTextAreaBlur()})),this._helperContainer.appendChild(this.textarea);var i=this._instantiationService.createInstance(j.CoreBrowserService,this.textarea);this._instantiationService.setService(x.ICoreBrowserService,i),this._charSizeService=this._instantiationService.createInstance(k.CharSizeService,this._document,this._helperContainer),this._instantiationService.setService(x.ICharSizeService,this._charSizeService),this._compositionView=U.createElement("div"),this._compositionView.classList.add("composition-view"),this._compositionHelper=this._instantiationService.createInstance(o.CompositionHelper,this.textarea,this._compositionView),this._helperContainer.appendChild(this._compositionView),this.element.appendChild(r),this._theme=this.options.theme||this._theme,this.options.theme=void 0,this._colorManager=new E.ColorManager(U,this.options.allowTransparency),this.optionsService.onOptionChange(function(e){return t._colorManager.onOptionsChange(e)}),this._colorManager.setTheme(this._theme);var n=this._createRenderer();this._renderService=this._instantiationService.createInstance(L.RenderService,n,this.rows,this.screenElement),this._instantiationService.setService(x.IRenderService,this._renderService),this._renderService.onRender(function(e){return t._onRender.fire(e)}),this.onResize(function(e){return t._renderService.resize(e.cols,e.rows)}),this._soundService=this._instantiationService.createInstance(v.SoundService),this._instantiationService.setService(x.ISoundService,this._soundService),this._mouseService=this._instantiationService.createInstance(O.MouseService),this._instantiationService.setService(x.IMouseService,this._mouseService),this.viewport=this._instantiationService.createInstance(s.Viewport,function(e,r){return t.scrollLines(e,r)},this._viewportElement,this._viewportScrollArea),this.viewport.onThemeChange(this._colorManager.colors),this.register(this.viewport),this.register(this.onCursorMove(function(){return t._renderService.onCursorMove()})),this.register(this.onResize(function(){return t._renderService.onResize(t.cols,t.rows)})),this.register(this.onBlur(function(){return t._renderService.onBlur()})),this.register(this.onFocus(function(){return t._renderService.onFocus()})),this.register(this._renderService.onDimensionsChange(function(){return t.viewport.syncScrollArea()})),this._selectionService=this._instantiationService.createInstance(f.SelectionService,function(e,r){return t.scrollLines(e,r)},this.element,this.screenElement),this._instantiationService.setService(x.ISelectionService,this._selectionService),this.register(this._selectionService.onSelectionChange(function(){return t._onSelectionChange.fire()})),this.register(this._selectionService.onRedrawRequest(function(e){return t._renderService.onSelectionChanged(e.start,e.end,e.columnSelectMode)})),this.register(this._selectionService.onLinuxMouseSelection(function(e){t.textarea.value=e,t.textarea.focus(),t.textarea.select()})),this.register(this.onScroll(function(){t.viewport.syncScrollArea(),t._selectionService.refresh()})),this.register(d.addDisposableDomListener(this._viewportElement,"scroll",function(){return t._selectionService.refresh()})),this._mouseZoneManager=this._instantiationService.createInstance(g.MouseZoneManager,this.element,this.screenElement),this.register(this._mouseZoneManager),this.register(this.onScroll(function(){return t._mouseZoneManager.clearAll()})),this.linkifier.attachToDom(this.element,this._mouseZoneManager),this.register(d.addDisposableDomListener(this.element,"mousedown",function(e){return t._selectionService.onMouseDown(e)})),this.mouseEvents?(this._selectionService.disable(),this.element.classList.add("enable-mouse-events")):this._selectionService.enable(),this.options.screenReaderMode&&(this._accessibilityManager=new y.AccessibilityManager(this,this._renderService)),this._charSizeService.measure(),this.refresh(0,this.rows-1),this._initGlobal(),this.bindMouse()},t.prototype._createRenderer=function(){switch(this.options.rendererType){case"canvas":return this._instantiationService.createInstance(h.Renderer,this._colorManager.colors,this.screenElement,this.linkifier);case"dom":return this._instantiationService.createInstance(b.DomRenderer,this._colorManager.colors,this.element,this.screenElement,this._viewportElement,this.linkifier);default:throw new Error('Unrecognized rendererType "'+this.options.rendererType+'"')}},t.prototype._setTheme=function(e){var t,r,i;this._theme=e,null===(t=this._colorManager)||void 0===t||t.setTheme(e),null===(r=this._renderService)||void 0===r||r.setColors(this._colorManager.colors),null===(i=this.viewport)||void 0===i||i.onThemeChange(this._colorManager.colors)},t.prototype.bindMouse=function(){var e=this,t=this,r=this.element;function i(e){var r,i,n;if(!(r=t._mouseService.getRawByteCoords(e,t.screenElement,t.cols,t.rows)))return!1;switch(e.overrideType||e.type){case"mousemove":n=32,void 0===e.buttons?(i=3,void 0!==e.button&&(i=e.button<3?e.button:3)):i=1&e.buttons?0:4&e.buttons?1:2&e.buttons?2:3;break;case"mouseup":n=0,i=e.button<3?e.button:3;break;case"mousedown":n=1,i=e.button<3?e.button:3;break;case"wheel":0!==e.deltaY&&(n=e.deltaY<0?0:1),i=4;break;default:return!1}return!(void 0===n||void 0===i||i>4)&&t._coreMouseService.triggerMouseEvent({col:r.x-33,row:r.y-33,button:i,action:n,ctrl:e.ctrlKey,alt:e.altKey,shift:e.shiftKey})}var n={mouseup:null,wheel:null,mousedrag:null,mousemove:null},o=function(t){return i(t),t.buttons||(e._document.removeEventListener("mouseup",n.mouseup),n.mousedrag&&e._document.removeEventListener("mousemove",n.mousedrag)),e.cancel(t)},s=function(t){return i(t),t.preventDefault(),e.cancel(t)},a=function(e){e.buttons&&i(e)},l=function(e){e.buttons||i(e)};this._coreMouseService.onProtocolChange(function(t){e.mouseEvents=t,t?("debug"===e.optionsService.options.logLevel&&e._logService.debug("Binding to mouse events:",e._coreMouseService.explainEvents(t)),e.element.classList.add("enable-mouse-events"),e._selectionService.disable()):(e._logService.debug("Unbinding from mouse events."),e.element.classList.remove("enable-mouse-events"),e._selectionService.enable()),8&t?n.mousemove||(r.addEventListener("mousemove",l),n.mousemove=l):(r.removeEventListener("mousemove",n.mousemove),n.mousemove=null),16&t?n.wheel||(r.addEventListener("wheel",s),n.wheel=s):(r.removeEventListener("wheel",n.wheel),n.wheel=null),2&t?n.mouseup||(n.mouseup=o):(e._document.removeEventListener("mouseup",n.mouseup),n.mouseup=null),4&t?n.mousedrag||(n.mousedrag=a):(e._document.removeEventListener("mousemove",n.mousedrag),n.mousedrag=null)}),this._coreMouseService.activeProtocol=this._coreMouseService.activeProtocol,this.register(d.addDisposableDomListener(r,"mousedown",function(t){if(t.preventDefault(),e.focus(),e.mouseEvents&&!e._selectionService.shouldForceSelection(t))return i(t),n.mouseup&&e._document.addEventListener("mouseup",n.mouseup),n.mousedrag&&e._document.addEventListener("mousemove",n.mousedrag),e.cancel(t)})),this.register(d.addDisposableDomListener(r,"wheel",function(t){if(n.wheel);else if(!e.buffer.hasScrollback){var r=e.viewport.getLinesScrolled(t);if(0===r)return;for(var i=c.C0.ESC+(e._coreService.decPrivateModes.applicationCursorKeys?"O":"[")+(t.deltaY<0?"A":"B"),o="",s=0;s=this.buffer.ybase&&(this._userScrolling=!1);var r=this.buffer.ydisp;this.buffer.ydisp=Math.max(Math.min(this.buffer.ydisp+e,this.buffer.ybase),0),r!==this.buffer.ydisp&&(t||this._onScroll.fire(this.buffer.ydisp),this.refresh(0,this.rows-1))},t.prototype.scrollPages=function(e){this.scrollLines(e*(this.rows-1))},t.prototype.scrollToTop=function(){this.scrollLines(-this.buffer.ydisp)},t.prototype.scrollToBottom=function(){this.scrollLines(this.buffer.ybase-this.buffer.ydisp)},t.prototype.scrollToLine=function(e){var t=e-this.buffer.ydisp;0!==t&&this.scrollLines(t)},t.prototype.paste=function(e){a.paste(e,this.textarea,this.bracketedPasteMode,this._coreService)},t.prototype.attachCustomKeyEventHandler=function(e){this._customKeyEventHandler=e},t.prototype.addEscHandler=function(e,t){return this._inputHandler.addEscHandler(e,t)},t.prototype.addDcsHandler=function(e,t){return this._inputHandler.addDcsHandler(e,t)},t.prototype.addCsiHandler=function(e,t){return this._inputHandler.addCsiHandler(e,t)},t.prototype.addOscHandler=function(e,t){return this._inputHandler.addOscHandler(e,t)},t.prototype.registerLinkMatcher=function(e,t,r){var i=this.linkifier.registerLinkMatcher(e,t,r);return this.refresh(0,this.rows-1),i},t.prototype.deregisterLinkMatcher=function(e){this.linkifier.deregisterLinkMatcher(e)&&this.refresh(0,this.rows-1)},t.prototype.registerCharacterJoiner=function(e){var t=this._renderService.registerCharacterJoiner(e);return this.refresh(0,this.rows-1),t},t.prototype.deregisterCharacterJoiner=function(e){this._renderService.deregisterCharacterJoiner(e)&&this.refresh(0,this.rows-1)},Object.defineProperty(t.prototype,"markers",{get:function(){return this.buffer.markers},enumerable:!0,configurable:!0}),t.prototype.addMarker=function(e){if(this.buffer===this.buffers.normal)return this.buffer.addMarker(this.buffer.ybase+this.buffer.y+e)},t.prototype.hasSelection=function(){return!!this._selectionService&&this._selectionService.hasSelection},t.prototype.select=function(e,t,r){this._selectionService.setSelection(e,t,r)},t.prototype.getSelection=function(){return this._selectionService?this._selectionService.selectionText:""},t.prototype.getSelectionPosition=function(){if(this._selectionService.hasSelection)return{startColumn:this._selectionService.selectionStart[0],startRow:this._selectionService.selectionStart[1],endColumn:this._selectionService.selectionEnd[0],endRow:this._selectionService.selectionEnd[1]}},t.prototype.clearSelection=function(){var e;null===(e=this._selectionService)||void 0===e||e.clearSelection()},t.prototype.selectAll=function(){var e;null===(e=this._selectionService)||void 0===e||e.selectAll()},t.prototype.selectLines=function(e,t){var r;null===(r=this._selectionService)||void 0===r||r.selectLines(e,t)},t.prototype._keyDown=function(e){if(this._keyDownHandled=!1,this._customKeyEventHandler&&!1===this._customKeyEventHandler(e))return!1;if(!this._compositionHelper.keydown(e))return this.buffer.ybase!==this.buffer.ydisp&&this.scrollToBottom(),!1;var t=m.evaluateKeyboardEvent(e,this._coreService.decPrivateModes.applicationCursorKeys,this.browser.isMac,this.options.macOptionIsMeta);if(this.updateCursorStyle(e),3===t.type||2===t.type){var r=this.rows-1;return this.scrollLines(2===t.type?-r:r),this.cancel(e,!0)}return 1===t.type&&this.selectAll(),!!this._isThirdLevelShift(this.browser,e)||(t.cancel&&this.cancel(e,!0),!t.key||(t.key!==c.C0.ETX&&t.key!==c.C0.CR||(this.textarea.value=""),this._onKey.fire({key:t.key,domEvent:e}),this.showCursor(),this._coreService.triggerDataEvent(t.key,!0),this.optionsService.options.screenReaderMode?void(this._keyDownHandled=!0):this.cancel(e,!0)))},t.prototype._isThirdLevelShift=function(e,t){var r=e.isMac&&!this.options.macOptionIsMeta&&t.altKey&&!t.ctrlKey&&!t.metaKey||e.isWindows&&t.altKey&&t.ctrlKey&&!t.metaKey;return"keypress"===t.type?r:r&&(!t.keyCode||t.keyCode>47)},t.prototype._keyUp=function(e){this._customKeyEventHandler&&!1===this._customKeyEventHandler(e)||(function(e){return 16===e.keyCode||17===e.keyCode||18===e.keyCode}(e)||this.focus(),this.updateCursorStyle(e))},t.prototype._keyPress=function(e){var t;if(this._keyDownHandled)return!1;if(this._customKeyEventHandler&&!1===this._customKeyEventHandler(e))return!1;if(this.cancel(e),e.charCode)t=e.charCode;else if(null===e.which||void 0===e.which)t=e.keyCode;else{if(0===e.which||0===e.charCode)return!1;t=e.which}return!(!t||(e.altKey||e.ctrlKey||e.metaKey)&&!this._isThirdLevelShift(this.browser,e))&&(t=String.fromCharCode(t),this._onKey.fire({key:t,domEvent:e}),this.showCursor(),this._coreService.triggerDataEvent(t,!0),!0)},t.prototype.bell=function(){var e=this;this._soundBell()&&this._soundService.playBellSound(),this._visualBell()&&(this.element.classList.add("visual-bell-active"),clearTimeout(this._visualBellTimer),this._visualBellTimer=window.setTimeout(function(){e.element.classList.remove("visual-bell-active")},200))},t.prototype.resize=function(e,t){var r,i;isNaN(e)||isNaN(t)||(e!==this.cols||t!==this.rows?(e=0;a--)(n=e[a])&&(s=(o<3?n(s):o>3?n(t,r,s):n(t,r))||s);return o>3&&s&&Object.defineProperty(t,r,s),s},n=this&&this.__param||function(e,t){return function(r,i){t(r,i,e)}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(4),s=r(0),a=function(){function e(e,t,r,i,n,o){this._textarea=e,this._compositionView=t,this._bufferService=r,this._optionsService=i,this._charSizeService=n,this._coreService=o,this._isComposing=!1,this._isSendingComposition=!1,this._compositionPosition={start:0,end:0}}return e.prototype.compositionstart=function(){this._isComposing=!0,this._compositionPosition.start=this._textarea.value.length,this._compositionView.textContent="",this._compositionView.classList.add("active")},e.prototype.compositionupdate=function(e){var t=this;this._compositionView.textContent=e.data,this.updateCompositionElements(),setTimeout(function(){t._compositionPosition.end=t._textarea.value.length},0)},e.prototype.compositionend=function(){this._finalizeComposition(!0)},e.prototype.keydown=function(e){if(this._isComposing||this._isSendingComposition){if(229===e.keyCode)return!1;if(16===e.keyCode||17===e.keyCode||18===e.keyCode)return!1;this._finalizeComposition(!1)}return 229!==e.keyCode||(this._handleAnyTextareaChanges(),!1)},e.prototype._finalizeComposition=function(e){var t=this;if(this._compositionView.classList.remove("active"),this._isComposing=!1,this._clearTextareaPosition(),e){var r={start:this._compositionPosition.start,end:this._compositionPosition.end};this._isSendingComposition=!0,setTimeout(function(){if(t._isSendingComposition){t._isSendingComposition=!1;var e=void 0;e=t._isComposing?t._textarea.value.substring(r.start,r.end):t._textarea.value.substring(r.start),t._coreService.triggerDataEvent(e,!0)}},0)}else{this._isSendingComposition=!1;var i=this._textarea.value.substring(this._compositionPosition.start,this._compositionPosition.end);this._coreService.triggerDataEvent(i,!0)}},e.prototype._handleAnyTextareaChanges=function(){var e=this,t=this._textarea.value;setTimeout(function(){if(!e._isComposing){var r=e._textarea.value.replace(t,"");r.length>0&&e._coreService.triggerDataEvent(r,!0)}},0)},e.prototype.updateCompositionElements=function(e){var t=this;if(this._isComposing){if(this._bufferService.buffer.isCursorInViewport){var r=Math.ceil(this._charSizeService.height*this._optionsService.options.lineHeight),i=this._bufferService.buffer.y*r,n=this._bufferService.buffer.x*this._charSizeService.width;this._compositionView.style.left=n+"px",this._compositionView.style.top=i+"px",this._compositionView.style.height=r+"px",this._compositionView.style.lineHeight=r+"px",this._compositionView.style.fontFamily=this._optionsService.options.fontFamily,this._compositionView.style.fontSize=this._optionsService.options.fontSize+"px";var o=this._compositionView.getBoundingClientRect();this._textarea.style.left=n+"px",this._textarea.style.top=i+"px",this._textarea.style.width=o.width+"px",this._textarea.style.height=o.height+"px",this._textarea.style.lineHeight=o.height+"px"}e||setTimeout(function(){return t.updateCompositionElements(!0)},0)}},e.prototype._clearTextareaPosition=function(){this._textarea.style.left="",this._textarea.style.top=""},e=i([n(2,s.IBufferService),n(3,s.IOptionsService),n(4,o.ICharSizeService),n(5,s.ICoreService)],e)}();t.CompositionHelper=a},function(e,t,r){"use strict";var i,n=this&&this.__extends||(i=function(e,t){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])})(e,t)},function(e,t){function r(){this.constructor=e}i(e,t),e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)}),o=this&&this.__decorate||function(e,t,r,i){var n,o=arguments.length,s=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,r,i);else for(var a=e.length-1;a>=0;a--)(n=e[a])&&(s=(o<3?n(s):o>3?n(t,r,s):n(t,r))||s);return o>3&&s&&Object.defineProperty(t,r,s),s},s=this&&this.__param||function(e,t){return function(r,i){t(r,i,e)}};Object.defineProperty(t,"__esModule",{value:!0});var a=r(2),c=r(8),l=r(4),h=r(0),u=15,f=function(e){function t(t,r,i,n,o,s,a){var l=e.call(this)||this;return l._scrollLines=t,l._viewportElement=r,l._scrollArea=i,l._bufferService=n,l._optionsService=o,l._charSizeService=s,l._renderService=a,l.scrollBarWidth=0,l._currentRowHeight=0,l._lastRecordedBufferLength=0,l._lastRecordedViewportHeight=0,l._lastRecordedBufferHeight=0,l._lastTouchY=0,l._lastScrollTop=0,l._wheelPartialScroll=0,l._refreshAnimationFrame=null,l._ignoreNextScrollEvent=!1,l.scrollBarWidth=l._viewportElement.offsetWidth-l._scrollArea.offsetWidth||u,l.register(c.addDisposableDomListener(l._viewportElement,"scroll",l._onScroll.bind(l))),setTimeout(function(){return l.syncScrollArea()},0),l}return n(t,e),t.prototype.onThemeChange=function(e){this._viewportElement.style.backgroundColor=e.background.css},t.prototype._refresh=function(e){var t=this;if(e)return this._innerRefresh(),void(null!==this._refreshAnimationFrame&&cancelAnimationFrame(this._refreshAnimationFrame));null===this._refreshAnimationFrame&&(this._refreshAnimationFrame=requestAnimationFrame(function(){return t._innerRefresh()}))},t.prototype._innerRefresh=function(){if(this._charSizeService.height>0){this._currentRowHeight=this._renderService.dimensions.scaledCellHeight/window.devicePixelRatio,this._lastRecordedViewportHeight=this._viewportElement.offsetHeight;var e=Math.round(this._currentRowHeight*this._lastRecordedBufferLength)+(this._lastRecordedViewportHeight-this._renderService.dimensions.canvasHeight);this._lastRecordedBufferHeight!==e&&(this._lastRecordedBufferHeight=e,this._scrollArea.style.height=this._lastRecordedBufferHeight+"px")}var t=this._bufferService.buffer.ydisp*this._currentRowHeight;this._viewportElement.scrollTop!==t&&(this._ignoreNextScrollEvent=!0,this._viewportElement.scrollTop=t),this._refreshAnimationFrame=null},t.prototype.syncScrollArea=function(e){if(void 0===e&&(e=!1),this._lastRecordedBufferLength!==this._bufferService.buffer.lines.length)return this._lastRecordedBufferLength=this._bufferService.buffer.lines.length,void this._refresh(e);if(this._lastRecordedViewportHeight===this._renderService.dimensions.canvasHeight){var t=this._bufferService.buffer.ydisp*this._currentRowHeight;this._lastScrollTop===t&&this._lastScrollTop===this._viewportElement.scrollTop&&this._renderService.dimensions.scaledCellHeight/window.devicePixelRatio===this._currentRowHeight||this._refresh(e)}else this._refresh(e)},t.prototype._onScroll=function(e){if(this._lastScrollTop=this._viewportElement.scrollTop,this._viewportElement.offsetParent)if(this._ignoreNextScrollEvent)this._ignoreNextScrollEvent=!1;else{var t=Math.round(this._lastScrollTop/this._currentRowHeight)-this._bufferService.buffer.ydisp;this._scrollLines(t,!0)}},t.prototype._bubbleScroll=function(e,t){var r=this._viewportElement.scrollTop+this._lastRecordedViewportHeight;return!(t<0&&0!==this._viewportElement.scrollTop||t>0&&r0?1:-1),this._wheelPartialScroll%=1):e.deltaMode===WheelEvent.DOM_DELTA_PAGE&&(t*=this._bufferService.rows),t},t.prototype._applyScrollModifier=function(e,t){var r=this._optionsService.options.fastScrollModifier;return"alt"===r&&t.altKey||"ctrl"===r&&t.ctrlKey||"shift"===r&&t.shiftKey?e*this._optionsService.options.fastScrollSensitivity*this._optionsService.options.scrollSensitivity:e*this._optionsService.options.scrollSensitivity},t.prototype.onTouchStart=function(e){this._lastTouchY=e.touches[0].pageY},t.prototype.onTouchMove=function(e){var t=this._lastTouchY-e.touches[0].pageY;return this._lastTouchY=e.touches[0].pageY,0!==t&&(this._viewportElement.scrollTop+=t,this._bubbleScroll(e,t))},t=o([s(3,h.IBufferService),s(4,h.IOptionsService),s(5,l.ICharSizeService),s(6,l.IRenderService)],t)}(a.Disposable);t.Viewport=f},function(e,t,r){"use strict";function i(e){return e.replace(/\r?\n/g,"\r")}function n(e,t){return t?"[200~"+e+"[201~":e}function o(e,t,r,o){e=n(e=i(e),r),o.triggerDataEvent(e,!0),t.value=""}function s(e,t,r){var i=r.getBoundingClientRect(),n=e.clientX-i.left-10,o=e.clientY-i.top-10;t.style.position="absolute",t.style.width="20px",t.style.height="20px",t.style.left=n+"px",t.style.top=o+"px",t.style.zIndex="1000",t.focus(),setTimeout(function(){t.style.position="",t.style.width="",t.style.height="",t.style.left="",t.style.top="",t.style.zIndex=""},200)}Object.defineProperty(t,"__esModule",{value:!0}),t.prepareTextForTerminal=i,t.bracketTextForPaste=n,t.copyHandler=function(e,t){e.clipboardData&&e.clipboardData.setData("text/plain",t.selectionText),e.preventDefault()},t.handlePasteEvent=function(e,t,r,i){e.stopPropagation(),e.clipboardData&&o(e.clipboardData.getData("text/plain"),t,r,i)},t.paste=o,t.moveTextAreaUnderMouseCursor=s,t.rightClickHandler=function(e,t,r,i,n){s(e,t,r),n&&!i.isClickInSelection(e)&&i.selectWordAtCursor(e),t.value=i.selectionText,t.select()}},function(e,t,r){"use strict";var i,n=this&&this.__extends||(i=function(e,t){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])})(e,t)},function(e,t){function r(){this.constructor=e}i(e,t),e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)});Object.defineProperty(t,"__esModule",{value:!0});var o=r(12),s=r(18),a=r(38),c=r(2),l=r(15),h=r(7),u=r(16),f=r(1),_=r(3),d=r(5),p=r(6),v=r(20),g=r(22),y=r(4),b={"(":0,")":1,"*":2,"+":3,"-":1,".":2};function m(e,t){if(e>24)return t.setWinLines||!1;switch(e){case 1:return!!t.restoreWin;case 2:return!!t.minimizeWin;case 3:return!!t.setWinPosition;case 4:return!!t.setWinSizePixels;case 5:return!!t.raiseWin;case 6:return!!t.lowerWin;case 7:return!!t.refreshWin;case 8:return!!t.setWinSizeChars;case 9:return!!t.maximizeWin;case 10:return!!t.fullscreenWin;case 11:return!!t.getWinState;case 13:return!!t.getWinPosition;case 14:return!!t.getWinSizePixels;case 15:return!!t.getScreenSizePixels;case 16:return!!t.getCellSizePixels;case 18:return!!t.getWinSizeChars;case 19:return!!t.getScreenSizeChars;case 20:return!!t.getIconTitle;case 21:return!!t.getWinTitle;case 22:return!!t.pushTitle;case 23:return!!t.popTitle;case 24:return!!t.setWinLines}return!1}var S=function(){function e(e,t,r,i){this._bufferService=e,this._coreService=t,this._logService=r,this._optionsService=i,this._data=new Uint32Array(0)}return e.prototype.hook=function(e){this._data=new Uint32Array(0)},e.prototype.put=function(e,t,r){this._data=l.concat(this._data,e.subarray(t,r))},e.prototype.unhook=function(e){if(e){var t=h.utf32ToString(this._data);switch(this._data=new Uint32Array(0),t){case'"q':return this._coreService.triggerDataEvent(o.C0.ESC+'P1$r0"q'+o.C0.ESC+"\\");case'"p':return this._coreService.triggerDataEvent(o.C0.ESC+'P1$r61;1"p'+o.C0.ESC+"\\");case"r":var r=this._bufferService.buffer.scrollTop+1+";"+(this._bufferService.buffer.scrollBottom+1)+"r";return this._coreService.triggerDataEvent(o.C0.ESC+"P1$r"+r+o.C0.ESC+"\\");case"m":return this._coreService.triggerDataEvent(o.C0.ESC+"P1$r0m"+o.C0.ESC+"\\");case" q":var i={block:2,underline:4,bar:6}[this._optionsService.options.cursorStyle];return i-=this._optionsService.options.cursorBlink?1:0,this._coreService.triggerDataEvent(o.C0.ESC+"P1$r"+i+" q"+o.C0.ESC+"\\");default:this._logService.debug("Unknown DCS $q %s",t),this._coreService.triggerDataEvent(o.C0.ESC+"P0$r"+o.C0.ESC+"\\")}}else this._data=new Uint32Array(0)},e}(),C=function(e){function t(t,r,i,n,c,l,_,p,g,y,b){void 0===b&&(b=new a.EscapeSequenceParser);var m=e.call(this)||this;m._terminal=t,m._bufferService=r,m._charsetService=i,m._coreService=n,m._dirtyRowService=c,m._logService=l,m._optionsService=_,m._coreMouseService=p,m._unicodeService=g,m._instantiationService=y,m._parser=b,m._parseBuffer=new Uint32Array(4096),m._stringDecoder=new h.StringToUtf32,m._utf8Decoder=new h.Utf8ToUtf32,m._workCell=new d.CellData,m._windowTitle="",m._iconName="",m._windowTitleStack=[],m._iconNameStack=[],m._curAttrData=u.DEFAULT_ATTR_DATA.clone(),m._eraseAttrDataInternal=u.DEFAULT_ATTR_DATA.clone(),m._onRequestRefreshRows=new f.EventEmitter,m._onRequestReset=new f.EventEmitter,m._onRequestBell=new f.EventEmitter,m._onCursorMove=new f.EventEmitter,m._onLineFeed=new f.EventEmitter,m._onScroll=new f.EventEmitter,m.register(m._parser),m._parser.setCsiHandlerFallback(function(e,t){m._logService.debug("Unknown CSI code: ",{identifier:m._parser.identToString(e),params:t.toArray()})}),m._parser.setEscHandlerFallback(function(e){m._logService.debug("Unknown ESC code: ",{identifier:m._parser.identToString(e)})}),m._parser.setExecuteHandlerFallback(function(e){m._logService.debug("Unknown EXECUTE code: ",{code:e})}),m._parser.setOscHandlerFallback(function(e,t,r){m._logService.debug("Unknown OSC code: ",{identifier:e,action:t,data:r})}),m._parser.setDcsHandlerFallback(function(e,t,r){"HOOK"===t&&(r=r.toArray()),m._logService.debug("Unknown DCS code: ",{identifier:m._parser.identToString(e),action:t,payload:r})}),m._parser.setPrintHandler(function(e,t,r){return m.print(e,t,r)}),m._parser.setCsiHandler({final:"@"},function(e){return m.insertChars(e)}),m._parser.setCsiHandler({intermediates:" ",final:"@"},function(e){return m.scrollLeft(e)}),m._parser.setCsiHandler({final:"A"},function(e){return m.cursorUp(e)}),m._parser.setCsiHandler({intermediates:" ",final:"A"},function(e){return m.scrollRight(e)}),m._parser.setCsiHandler({final:"B"},function(e){return m.cursorDown(e)}),m._parser.setCsiHandler({final:"C"},function(e){return m.cursorForward(e)}),m._parser.setCsiHandler({final:"D"},function(e){return m.cursorBackward(e)}),m._parser.setCsiHandler({final:"E"},function(e){return m.cursorNextLine(e)}),m._parser.setCsiHandler({final:"F"},function(e){return m.cursorPrecedingLine(e)}),m._parser.setCsiHandler({final:"G"},function(e){return m.cursorCharAbsolute(e)}),m._parser.setCsiHandler({final:"H"},function(e){return m.cursorPosition(e)}),m._parser.setCsiHandler({final:"I"},function(e){return m.cursorForwardTab(e)}),m._parser.setCsiHandler({final:"J"},function(e){return m.eraseInDisplay(e)}),m._parser.setCsiHandler({prefix:"?",final:"J"},function(e){return m.eraseInDisplay(e)}),m._parser.setCsiHandler({final:"K"},function(e){return m.eraseInLine(e)}),m._parser.setCsiHandler({prefix:"?",final:"K"},function(e){return m.eraseInLine(e)}),m._parser.setCsiHandler({final:"L"},function(e){return m.insertLines(e)}),m._parser.setCsiHandler({final:"M"},function(e){return m.deleteLines(e)}),m._parser.setCsiHandler({final:"P"},function(e){return m.deleteChars(e)}),m._parser.setCsiHandler({final:"S"},function(e){return m.scrollUp(e)}),m._parser.setCsiHandler({final:"T"},function(e){return m.scrollDown(e)}),m._parser.setCsiHandler({final:"X"},function(e){return m.eraseChars(e)}),m._parser.setCsiHandler({final:"Z"},function(e){return m.cursorBackwardTab(e)}),m._parser.setCsiHandler({final:"`"},function(e){return m.charPosAbsolute(e)}),m._parser.setCsiHandler({final:"a"},function(e){return m.hPositionRelative(e)}),m._parser.setCsiHandler({final:"b"},function(e){return m.repeatPrecedingCharacter(e)}),m._parser.setCsiHandler({final:"c"},function(e){return m.sendDeviceAttributesPrimary(e)}),m._parser.setCsiHandler({prefix:">",final:"c"},function(e){return m.sendDeviceAttributesSecondary(e)}),m._parser.setCsiHandler({final:"d"},function(e){return m.linePosAbsolute(e)}),m._parser.setCsiHandler({final:"e"},function(e){return m.vPositionRelative(e)}),m._parser.setCsiHandler({final:"f"},function(e){return m.hVPosition(e)}),m._parser.setCsiHandler({final:"g"},function(e){return m.tabClear(e)}),m._parser.setCsiHandler({final:"h"},function(e){return m.setMode(e)}),m._parser.setCsiHandler({prefix:"?",final:"h"},function(e){return m.setModePrivate(e)}),m._parser.setCsiHandler({final:"l"},function(e){return m.resetMode(e)}),m._parser.setCsiHandler({prefix:"?",final:"l"},function(e){return m.resetModePrivate(e)}),m._parser.setCsiHandler({final:"m"},function(e){return m.charAttributes(e)}),m._parser.setCsiHandler({final:"n"},function(e){return m.deviceStatus(e)}),m._parser.setCsiHandler({prefix:"?",final:"n"},function(e){return m.deviceStatusPrivate(e)}),m._parser.setCsiHandler({intermediates:"!",final:"p"},function(e){return m.softReset(e)}),m._parser.setCsiHandler({intermediates:" ",final:"q"},function(e){return m.setCursorStyle(e)}),m._parser.setCsiHandler({final:"r"},function(e){return m.setScrollRegion(e)}),m._parser.setCsiHandler({final:"s"},function(e){return m.saveCursor(e)}),m._parser.setCsiHandler({final:"t"},function(e){return m.windowOptions(e)}),m._parser.setCsiHandler({final:"u"},function(e){return m.restoreCursor(e)}),m._parser.setCsiHandler({intermediates:"'",final:"}"},function(e){return m.insertColumns(e)}),m._parser.setCsiHandler({intermediates:"'",final:"~"},function(e){return m.deleteColumns(e)}),m._parser.setExecuteHandler(o.C0.BEL,function(){return m.bell()}),m._parser.setExecuteHandler(o.C0.LF,function(){return m.lineFeed()}),m._parser.setExecuteHandler(o.C0.VT,function(){return m.lineFeed()}),m._parser.setExecuteHandler(o.C0.FF,function(){return m.lineFeed()}),m._parser.setExecuteHandler(o.C0.CR,function(){return m.carriageReturn()}),m._parser.setExecuteHandler(o.C0.BS,function(){return m.backspace()}),m._parser.setExecuteHandler(o.C0.HT,function(){return m.tab()}),m._parser.setExecuteHandler(o.C0.SO,function(){return m.shiftOut()}),m._parser.setExecuteHandler(o.C0.SI,function(){return m.shiftIn()}),m._parser.setExecuteHandler(o.C1.IND,function(){return m.index()}),m._parser.setExecuteHandler(o.C1.NEL,function(){return m.nextLine()}),m._parser.setExecuteHandler(o.C1.HTS,function(){return m.tabSet()}),m._parser.setOscHandler(0,new v.OscHandler(function(e){m.setTitle(e),m.setIconName(e)})),m._parser.setOscHandler(1,new v.OscHandler(function(e){return m.setIconName(e)})),m._parser.setOscHandler(2,new v.OscHandler(function(e){return m.setTitle(e)})),m._parser.setEscHandler({final:"7"},function(){return m.saveCursor()}),m._parser.setEscHandler({final:"8"},function(){return m.restoreCursor()}),m._parser.setEscHandler({final:"D"},function(){return m.index()}),m._parser.setEscHandler({final:"E"},function(){return m.nextLine()}),m._parser.setEscHandler({final:"H"},function(){return m.tabSet()}),m._parser.setEscHandler({final:"M"},function(){return m.reverseIndex()}),m._parser.setEscHandler({final:"="},function(){return m.keypadApplicationMode()}),m._parser.setEscHandler({final:">"},function(){return m.keypadNumericMode()}),m._parser.setEscHandler({final:"c"},function(){return m.fullReset()}),m._parser.setEscHandler({final:"n"},function(){return m.setgLevel(2)}),m._parser.setEscHandler({final:"o"},function(){return m.setgLevel(3)}),m._parser.setEscHandler({final:"|"},function(){return m.setgLevel(3)}),m._parser.setEscHandler({final:"}"},function(){return m.setgLevel(2)}),m._parser.setEscHandler({final:"~"},function(){return m.setgLevel(1)}),m._parser.setEscHandler({intermediates:"%",final:"@"},function(){return m.selectDefaultCharset()}),m._parser.setEscHandler({intermediates:"%",final:"G"},function(){return m.selectDefaultCharset()});var C=function(e){w._parser.setEscHandler({intermediates:"(",final:e},function(){return m.selectCharset("("+e)}),w._parser.setEscHandler({intermediates:")",final:e},function(){return m.selectCharset(")"+e)}),w._parser.setEscHandler({intermediates:"*",final:e},function(){return m.selectCharset("*"+e)}),w._parser.setEscHandler({intermediates:"+",final:e},function(){return m.selectCharset("+"+e)}),w._parser.setEscHandler({intermediates:"-",final:e},function(){return m.selectCharset("-"+e)}),w._parser.setEscHandler({intermediates:".",final:e},function(){return m.selectCharset("."+e)}),w._parser.setEscHandler({intermediates:"/",final:e},function(){return m.selectCharset("/"+e)})},w=this;for(var E in s.CHARSETS)C(E);return m._parser.setEscHandler({intermediates:"#",final:"8"},function(){return m.screenAlignmentPattern()}),m._parser.setErrorHandler(function(e){return m._logService.error("Parsing error: ",e),e}),m._parser.setDcsHandler({intermediates:"$",final:"q"},new S(m._bufferService,m._coreService,m._logService,m._optionsService)),m}return n(t,e),Object.defineProperty(t.prototype,"onRequestRefreshRows",{get:function(){return this._onRequestRefreshRows.event},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"onRequestReset",{get:function(){return this._onRequestReset.event},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"onRequestBell",{get:function(){return this._onRequestBell.event},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"onCursorMove",{get:function(){return this._onCursorMove.event},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"onLineFeed",{get:function(){return this._onLineFeed.event},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"onScroll",{get:function(){return this._onScroll.event},enumerable:!0,configurable:!0}),t.prototype.dispose=function(){e.prototype.dispose.call(this)},t.prototype.parse=function(e){var t=this._bufferService.buffer,r=t.x,i=t.y;if(this._logService.debug("parsing data",e),this._parseBuffer.length131072)for(var n=0;n0&&2===d.getWidth(o.x-1)&&d.setCellFromCodePoint(o.x-1,0,1,f.fg,f.bg);for(var p=t;p=c)if(l)o.x=0,o.y++,o.y===o.scrollBottom+1?(o.y--,this._terminal.scroll(this._eraseAttrData(),!0)):(o.y>=this._bufferService.rows&&(o.y=this._bufferService.rows-1),o.lines.get(o.y).isWrapped=!0),d=o.lines.get(o.y+o.ybase);else if(o.x=c-1,2===n)continue;if(u&&(d.insertCells(o.x,n,o.getNullCell(f),f),2===d.getWidth(c-1)&&d.setCellFromCodePoint(c-1,_.NULL_CELL_CODE,_.NULL_CELL_WIDTH,f.fg,f.bg)),d.setCellFromCodePoint(o.x++,i,n,f.fg,f.bg),n>0)for(;--n;)d.setCellFromCodePoint(o.x++,0,0,f.fg,f.bg)}else d.getWidth(o.x-1)?d.addCodepointToCell(o.x-1,i):d.addCodepointToCell(o.x-2,i)}r-t>0&&(d.loadCell(o.x-1,this._workCell),2===this._workCell.getWidth()||this._workCell.getCode()>65535?this._parser.precedingCodepoint=0:this._workCell.isCombined()?this._parser.precedingCodepoint=this._workCell.getChars().charCodeAt(0):this._parser.precedingCodepoint=this._workCell.content),o.x0&&0===d.getWidth(o.x)&&!d.hasContent(o.x)&&d.setCellFromCodePoint(o.x,0,1,f.fg,f.bg),this._dirtyRowService.markDirty(o.y)},t.prototype.addCsiHandler=function(e,t){var r=this;return"t"!==e.final||e.prefix||e.intermediates?this._parser.addCsiHandler(e,t):this._parser.addCsiHandler(e,function(e){return!m(e.params[0],r._optionsService.options.windowOptions)||t(e)})},t.prototype.addDcsHandler=function(e,t){return this._parser.addDcsHandler(e,new g.DcsHandler(t))},t.prototype.addEscHandler=function(e,t){return this._parser.addEscHandler(e,t)},t.prototype.addOscHandler=function(e,t){return this._parser.addOscHandler(e,new v.OscHandler(t))},t.prototype.bell=function(){this._onRequestBell.fire()},t.prototype.lineFeed=function(){var e=this._bufferService.buffer;this._dirtyRowService.markDirty(e.y),this._optionsService.options.convertEol&&(e.x=0),e.y++,e.y===e.scrollBottom+1?(e.y--,this._terminal.scroll(this._eraseAttrData())):e.y>=this._bufferService.rows&&(e.y=this._bufferService.rows-1),e.x>=this._bufferService.cols&&e.x--,this._dirtyRowService.markDirty(e.y),this._onLineFeed.fire()},t.prototype.carriageReturn=function(){this._bufferService.buffer.x=0},t.prototype.backspace=function(){this._restrictCursor(),this._bufferService.buffer.x>0&&this._bufferService.buffer.x--},t.prototype.tab=function(){if(!(this._bufferService.buffer.x>=this._bufferService.cols)){var e=this._bufferService.buffer.x;this._bufferService.buffer.x=this._bufferService.buffer.nextStop(),this._optionsService.options.screenReaderMode&&this._terminal.onA11yTabEmitter.fire(this._bufferService.buffer.x-e)}},t.prototype.shiftOut=function(){this._charsetService.setgLevel(1)},t.prototype.shiftIn=function(){this._charsetService.setgLevel(0)},t.prototype._restrictCursor=function(){this._bufferService.buffer.x=Math.min(this._bufferService.cols-1,Math.max(0,this._bufferService.buffer.x)),this._bufferService.buffer.y=this._coreService.decPrivateModes.origin?Math.min(this._bufferService.buffer.scrollBottom,Math.max(this._bufferService.buffer.scrollTop,this._bufferService.buffer.y)):Math.min(this._bufferService.rows-1,Math.max(0,this._bufferService.buffer.y)),this._dirtyRowService.markDirty(this._bufferService.buffer.y)},t.prototype._setCursor=function(e,t){this._dirtyRowService.markDirty(this._bufferService.buffer.y),this._coreService.decPrivateModes.origin?(this._bufferService.buffer.x=e,this._bufferService.buffer.y=this._bufferService.buffer.scrollTop+t):(this._bufferService.buffer.x=e,this._bufferService.buffer.y=t),this._restrictCursor(),this._dirtyRowService.markDirty(this._bufferService.buffer.y)},t.prototype._moveCursor=function(e,t){this._restrictCursor(),this._setCursor(this._bufferService.buffer.x+e,this._bufferService.buffer.y+t)},t.prototype.cursorUp=function(e){var t=this._bufferService.buffer.y-this._bufferService.buffer.scrollTop;t>=0?this._moveCursor(0,-Math.min(t,e.params[0]||1)):this._moveCursor(0,-(e.params[0]||1))},t.prototype.cursorDown=function(e){var t=this._bufferService.buffer.scrollBottom-this._bufferService.buffer.y;t>=0?this._moveCursor(0,Math.min(t,e.params[0]||1)):this._moveCursor(0,e.params[0]||1)},t.prototype.cursorForward=function(e){this._moveCursor(e.params[0]||1,0)},t.prototype.cursorBackward=function(e){this._moveCursor(-(e.params[0]||1),0)},t.prototype.cursorNextLine=function(e){this.cursorDown(e),this._bufferService.buffer.x=0},t.prototype.cursorPrecedingLine=function(e){this.cursorUp(e),this._bufferService.buffer.x=0},t.prototype.cursorCharAbsolute=function(e){this._setCursor((e.params[0]||1)-1,this._bufferService.buffer.y)},t.prototype.cursorPosition=function(e){this._setCursor(e.length>=2?(e.params[1]||1)-1:0,(e.params[0]||1)-1)},t.prototype.charPosAbsolute=function(e){this._setCursor((e.params[0]||1)-1,this._bufferService.buffer.y)},t.prototype.hPositionRelative=function(e){this._moveCursor(e.params[0]||1,0)},t.prototype.linePosAbsolute=function(e){this._setCursor(this._bufferService.buffer.x,(e.params[0]||1)-1)},t.prototype.vPositionRelative=function(e){this._moveCursor(0,e.params[0]||1)},t.prototype.hVPosition=function(e){this.cursorPosition(e)},t.prototype.tabClear=function(e){var t=e.params[0];0===t?delete this._bufferService.buffer.tabs[this._bufferService.buffer.x]:3===t&&(this._bufferService.buffer.tabs={})},t.prototype.cursorForwardTab=function(e){if(!(this._bufferService.buffer.x>=this._bufferService.cols))for(var t=e.params[0]||1;t--;)this._bufferService.buffer.x=this._bufferService.buffer.nextStop()},t.prototype.cursorBackwardTab=function(e){if(!(this._bufferService.buffer.x>=this._bufferService.cols))for(var t=e.params[0]||1,r=this._bufferService.buffer;t--;)r.x=r.prevStop()},t.prototype._eraseInBufferLine=function(e,t,r,i){void 0===i&&(i=!1);var n=this._bufferService.buffer.lines.get(this._bufferService.buffer.ybase+e);n.replaceCells(t,r,this._bufferService.buffer.getNullCell(this._eraseAttrData()),this._eraseAttrData()),i&&(n.isWrapped=!1)},t.prototype._resetBufferLine=function(e){var t=this._bufferService.buffer.lines.get(this._bufferService.buffer.ybase+e);t.fill(this._bufferService.buffer.getNullCell(this._eraseAttrData())),t.isWrapped=!1},t.prototype.eraseInDisplay=function(e){var t;switch(this._restrictCursor(),e.params[0]){case 0:for(t=this._bufferService.buffer.y,this._dirtyRowService.markDirty(t),this._eraseInBufferLine(t++,this._bufferService.buffer.x,this._bufferService.cols,0===this._bufferService.buffer.x);t=this._bufferService.cols&&(this._bufferService.buffer.lines.get(t+1).isWrapped=!1);t--;)this._resetBufferLine(t);this._dirtyRowService.markDirty(0);break;case 2:for(t=this._bufferService.rows,this._dirtyRowService.markDirty(t-1);t--;)this._resetBufferLine(t);this._dirtyRowService.markDirty(0);break;case 3:var r=this._bufferService.buffer.lines.length-this._bufferService.rows;r>0&&(this._bufferService.buffer.lines.trimStart(r),this._bufferService.buffer.ybase=Math.max(this._bufferService.buffer.ybase-r,0),this._bufferService.buffer.ydisp=Math.max(this._bufferService.buffer.ydisp-r,0),this._onScroll.fire(0))}},t.prototype.eraseInLine=function(e){switch(this._restrictCursor(),e.params[0]){case 0:this._eraseInBufferLine(this._bufferService.buffer.y,this._bufferService.buffer.x,this._bufferService.cols);break;case 1:this._eraseInBufferLine(this._bufferService.buffer.y,0,this._bufferService.buffer.x+1);break;case 2:this._eraseInBufferLine(this._bufferService.buffer.y,0,this._bufferService.cols)}this._dirtyRowService.markDirty(this._bufferService.buffer.y)},t.prototype.insertLines=function(e){this._restrictCursor();var t=e.params[0]||1,r=this._bufferService.buffer;if(!(r.y>r.scrollBottom||r.yr.scrollBottom||r.yt.scrollBottom||t.yt.scrollBottom||t.yt.scrollBottom||t.yt.scrollBottom||t.y0||(this._terminal.is("xterm")||this._terminal.is("rxvt-unicode")||this._terminal.is("screen")?this._coreService.triggerDataEvent(o.C0.ESC+"[?1;2c"):this._terminal.is("linux")&&this._coreService.triggerDataEvent(o.C0.ESC+"[?6c"))},t.prototype.sendDeviceAttributesSecondary=function(e){e.params[0]>0||(this._terminal.is("xterm")?this._coreService.triggerDataEvent(o.C0.ESC+"[>0;276;0c"):this._terminal.is("rxvt-unicode")?this._coreService.triggerDataEvent(o.C0.ESC+"[>85;95;0c"):this._terminal.is("linux")?this._coreService.triggerDataEvent(e.params[0]+"c"):this._terminal.is("screen")&&this._coreService.triggerDataEvent(o.C0.ESC+"[>83;40003;0c"))},t.prototype.setMode=function(e){for(var t=0;t=2||2===i[1]&&o+n>=5)break;i[1]&&(n=1)}while(++o+t=30&&t<=37?(i.fg&=-50331904,i.fg|=16777216|t-30):t>=40&&t<=47?(i.bg&=-50331904,i.bg|=16777216|t-40):t>=90&&t<=97?(i.fg&=-50331904,i.fg|=16777224|t-90):t>=100&&t<=107?(i.bg&=-50331904,i.bg|=16777224|t-100):0===t?(i.fg=u.DEFAULT_ATTR_DATA.fg,i.bg=u.DEFAULT_ATTR_DATA.bg):1===t?i.fg|=134217728:3===t?i.bg|=67108864:4===t?i.fg|=268435456:5===t?i.fg|=536870912:7===t?i.fg|=67108864:8===t?i.fg|=1073741824:2===t?i.bg|=134217728:22===t?(i.fg&=-134217729,i.bg&=-134217729):23===t?i.bg&=-67108865:24===t?i.fg&=-268435457:25===t?i.fg&=-536870913:27===t?i.fg&=-67108865:28===t?i.fg&=-1073741825:39===t?(i.fg&=-67108864,i.fg|=16777215&u.DEFAULT_ATTR_DATA.fg):49===t?(i.bg&=-67108864,i.bg|=16777215&u.DEFAULT_ATTR_DATA.bg):38===t||48===t?n+=this._extractColor(e,n,i):100===t?(i.fg&=-67108864,i.fg|=16777215&u.DEFAULT_ATTR_DATA.fg,i.bg&=-67108864,i.bg|=16777215&u.DEFAULT_ATTR_DATA.bg):this._logService.debug("Unknown SGR attribute: %d.",t)},t.prototype.deviceStatus=function(e){switch(e.params[0]){case 5:this._coreService.triggerDataEvent(o.C0.ESC+"[0n");break;case 6:var t=this._bufferService.buffer.y+1,r=this._bufferService.buffer.x+1;this._coreService.triggerDataEvent(o.C0.ESC+"["+t+";"+r+"R")}},t.prototype.deviceStatusPrivate=function(e){switch(e.params[0]){case 6:var t=this._bufferService.buffer.y+1,r=this._bufferService.buffer.x+1;this._coreService.triggerDataEvent(o.C0.ESC+"[?"+t+";"+r+"R")}},t.prototype.softReset=function(e){var t;this._coreService.isCursorHidden=!1,this._terminal.insertMode=!1,null===(t=this._terminal.viewport)||void 0===t||t.syncScrollArea(),this._bufferService.buffer.scrollTop=0,this._bufferService.buffer.scrollBottom=this._bufferService.rows-1,this._curAttrData=u.DEFAULT_ATTR_DATA.clone(),this._bufferService.buffer.x=this._bufferService.buffer.y=0,this._coreService.reset(),this._charsetService.reset()},t.prototype.setCursorStyle=function(e){var t=e.params[0]||1;switch(t){case 1:case 2:this._optionsService.options.cursorStyle="block";break;case 3:case 4:this._optionsService.options.cursorStyle="underline";break;case 5:case 6:this._optionsService.options.cursorStyle="bar"}var r=t%2==1;this._optionsService.options.cursorBlink=r},t.prototype.setScrollRegion=function(e){var t,r=e.params[0]||1;(e.length<2||(t=e.params[1])>this._bufferService.rows||0===t)&&(t=this._bufferService.rows),t>r&&(this._bufferService.buffer.scrollTop=r-1,this._bufferService.buffer.scrollBottom=t-1,this._setCursor(0,0))},t.prototype.windowOptions=function(e){if(m(e.params[0],this._optionsService.options.windowOptions)){var t=e.length>1?e.params[1]:0,r=this._instantiationService.getService(y.IRenderService);switch(e.params[0]){case 14:if(r&&2!==t){console.log(r.dimensions);var i=r.dimensions.scaledCanvasWidth.toFixed(0),n=r.dimensions.scaledCanvasHeight.toFixed(0);this._coreService.triggerDataEvent(o.C0.ESC+"[4;"+n+";"+i+"t")}break;case 16:if(r){i=r.dimensions.scaledCellWidth.toFixed(0),n=r.dimensions.scaledCellHeight.toFixed(0);this._coreService.triggerDataEvent(o.C0.ESC+"[6;"+n+";"+i+"t")}break;case 18:this._bufferService&&this._coreService.triggerDataEvent(o.C0.ESC+"[8;"+this._bufferService.rows+";"+this._bufferService.cols+"t");break;case 22:0!==t&&2!==t||(this._windowTitleStack.push(this._windowTitle),this._windowTitleStack.length>10&&this._windowTitleStack.shift()),0!==t&&1!==t||(this._iconNameStack.push(this._iconName),this._iconNameStack.length>10&&this._iconNameStack.shift());break;case 23:0!==t&&2!==t||this._windowTitleStack.length&&this.setTitle(this._windowTitleStack.pop()),0!==t&&1!==t||this._iconNameStack.length&&this.setIconName(this._iconNameStack.pop())}}},t.prototype.saveCursor=function(e){this._bufferService.buffer.savedX=this._bufferService.buffer.x,this._bufferService.buffer.savedY=this._bufferService.buffer.ybase+this._bufferService.buffer.y,this._bufferService.buffer.savedCurAttrData.fg=this._curAttrData.fg,this._bufferService.buffer.savedCurAttrData.bg=this._curAttrData.bg,this._bufferService.buffer.savedCharset=this._charsetService.charset},t.prototype.restoreCursor=function(e){this._bufferService.buffer.x=this._bufferService.buffer.savedX||0,this._bufferService.buffer.y=Math.max(this._bufferService.buffer.savedY-this._bufferService.buffer.ybase,0),this._curAttrData.fg=this._bufferService.buffer.savedCurAttrData.fg,this._curAttrData.bg=this._bufferService.buffer.savedCurAttrData.bg,this._charsetService.charset=this._savedCharset,this._bufferService.buffer.savedCharset&&(this._charsetService.charset=this._bufferService.buffer.savedCharset),this._restrictCursor()},t.prototype.setTitle=function(e){this._windowTitle=e,this._terminal.handleTitle(e)},t.prototype.setIconName=function(e){this._iconName=e},t.prototype.nextLine=function(){this._bufferService.buffer.x=0,this.index()},t.prototype.keypadApplicationMode=function(){var e;this._logService.debug("Serial port requested application keypad."),this._coreService.decPrivateModes.applicationKeypad=!0,null===(e=this._terminal.viewport)||void 0===e||e.syncScrollArea()},t.prototype.keypadNumericMode=function(){var e;this._logService.debug("Switching back to normal keypad."),this._coreService.decPrivateModes.applicationKeypad=!1,null===(e=this._terminal.viewport)||void 0===e||e.syncScrollArea()},t.prototype.selectDefaultCharset=function(){this._charsetService.setgLevel(0),this._charsetService.setgCharset(0,s.DEFAULT_CHARSET)},t.prototype.selectCharset=function(e){2===e.length?"/"!==e[0]&&this._charsetService.setgCharset(b[e[0]],s.CHARSETS[e[1]]||s.DEFAULT_CHARSET):this.selectDefaultCharset()},t.prototype.index=function(){this._restrictCursor();var e=this._bufferService.buffer;this._bufferService.buffer.y++,e.y===e.scrollBottom+1?(e.y--,this._terminal.scroll(this._eraseAttrData())):e.y>=this._bufferService.rows&&(e.y=this._bufferService.rows-1),this._restrictCursor()},t.prototype.tabSet=function(){this._bufferService.buffer.tabs[this._bufferService.buffer.x]=!0},t.prototype.reverseIndex=function(){this._restrictCursor();var e=this._bufferService.buffer;if(e.y===e.scrollTop){var t=e.scrollBottom-e.scrollTop;e.lines.shiftElements(e.y+e.ybase,t,1),e.lines.set(e.y+e.ybase,e.getBlankLine(this._eraseAttrData())),this._dirtyRowService.markRangeDirty(e.scrollTop,e.scrollBottom)}else e.y--,this._restrictCursor()},t.prototype.fullReset=function(){this._parser.reset(),this._onRequestReset.fire()},t.prototype.reset=function(){this._curAttrData=u.DEFAULT_ATTR_DATA.clone(),this._eraseAttrDataInternal=u.DEFAULT_ATTR_DATA.clone()},t.prototype._eraseAttrData=function(){return this._eraseAttrDataInternal.bg&=-67108864,this._eraseAttrDataInternal.bg|=67108863&this._curAttrData.bg,this._eraseAttrDataInternal},t.prototype.setgLevel=function(e){this._charsetService.setgLevel(e)},t.prototype.screenAlignmentPattern=function(){var e=new d.CellData;e.content=1<<22|"E".charCodeAt(0),e.fg=this._curAttrData.fg,e.bg=this._curAttrData.bg;var t=this._bufferService.buffer;this._setCursor(0,0);for(var r=0;r1)throw new Error("only one byte as prefix supported");if((r=e.prefix.charCodeAt(0))&&60>r||r>63)throw new Error("prefix must be in range 0x3c .. 0x3f")}if(e.intermediates){if(e.intermediates.length>2)throw new Error("only two bytes as intermediates are supported");for(var i=0;in||n>47)throw new Error("intermediate must be in range 0x20 .. 0x2f");r<<=8,r|=n}}if(1!==e.final.length)throw new Error("final must be a single byte");var o=e.final.charCodeAt(0);if(t[0]>o||o>t[1])throw new Error("final must be in range "+t[0]+" .. "+t[1]);return r<<=8,r|=o},r.prototype.identToString=function(e){for(var t=[];e;)t.push(String.fromCharCode(255&e)),e>>=8;return t.reverse().join("")},r.prototype.dispose=function(){this._csiHandlers=Object.create(null),this._executeHandlers=Object.create(null),this._escHandlers=Object.create(null),this._oscParser.dispose(),this._dcsParser.dispose()},r.prototype.setPrintHandler=function(e){this._printHandler=e},r.prototype.clearPrintHandler=function(){this._printHandler=this._printHandlerFb},r.prototype.addEscHandler=function(e,t){var r=this._identifier(e,[48,126]);void 0===this._escHandlers[r]&&(this._escHandlers[r]=[]);var i=this._escHandlers[r];return i.push(t),{dispose:function(){var e=i.indexOf(t);-1!==e&&i.splice(e,1)}}},r.prototype.setEscHandler=function(e,t){this._escHandlers[this._identifier(e,[48,126])]=[t]},r.prototype.clearEscHandler=function(e){this._escHandlers[this._identifier(e,[48,126])]&&delete this._escHandlers[this._identifier(e,[48,126])]},r.prototype.setEscHandlerFallback=function(e){this._escHandlerFb=e},r.prototype.setExecuteHandler=function(e,t){this._executeHandlers[e.charCodeAt(0)]=t},r.prototype.clearExecuteHandler=function(e){this._executeHandlers[e.charCodeAt(0)]&&delete this._executeHandlers[e.charCodeAt(0)]},r.prototype.setExecuteHandlerFallback=function(e){this._executeHandlerFb=e},r.prototype.addCsiHandler=function(e,t){var r=this._identifier(e);void 0===this._csiHandlers[r]&&(this._csiHandlers[r]=[]);var i=this._csiHandlers[r];return i.push(t),{dispose:function(){var e=i.indexOf(t);-1!==e&&i.splice(e,1)}}},r.prototype.setCsiHandler=function(e,t){this._csiHandlers[this._identifier(e)]=[t]},r.prototype.clearCsiHandler=function(e){this._csiHandlers[this._identifier(e)]&&delete this._csiHandlers[this._identifier(e)]},r.prototype.setCsiHandlerFallback=function(e){this._csiHandlerFb=e},r.prototype.addDcsHandler=function(e,t){return this._dcsParser.addHandler(this._identifier(e),t)},r.prototype.setDcsHandler=function(e,t){this._dcsParser.setHandler(this._identifier(e),t)},r.prototype.clearDcsHandler=function(e){this._dcsParser.clearHandler(this._identifier(e))},r.prototype.setDcsHandlerFallback=function(e){this._dcsParser.setHandlerFallback(e)},r.prototype.addOscHandler=function(e,t){return this._oscParser.addHandler(e,t)},r.prototype.setOscHandler=function(e,t){this._oscParser.setHandler(e,t)},r.prototype.clearOscHandler=function(e){this._oscParser.clearHandler(e)},r.prototype.setOscHandlerFallback=function(e){this._oscParser.setHandlerFallback(e)},r.prototype.setErrorHandler=function(e){this._errorHandler=e},r.prototype.clearErrorHandler=function(){this._errorHandler=this._errorHandlerFb},r.prototype.reset=function(){this.currentState=this.initialState,this._oscParser.reset(),this._dcsParser.reset(),this._params.reset(),this._params.addParam(0),this._collect=0,this.precedingCodepoint=0},r.prototype.parse=function(e,t){for(var r=0,i=0,n=this.currentState,o=this._oscParser,s=this._dcsParser,a=this._collect,c=this._params,l=this.TRANSITIONS.table,h=0;h>4){case 2:for(var u=h+1;;++u){if(u>=t||(r=e[u])<32||r>126&&r<160){this._printHandler(e,h,u),h=u-1;break}if(++u>=t||(r=e[u])<32||r>126&&r<160){this._printHandler(e,h,u),h=u-1;break}if(++u>=t||(r=e[u])<32||r>126&&r<160){this._printHandler(e,h,u),h=u-1;break}if(++u>=t||(r=e[u])<32||r>126&&r<160){this._printHandler(e,h,u),h=u-1;break}}break;case 3:this._executeHandlers[r]?this._executeHandlers[r]():this._executeHandlerFb(r),this.precedingCodepoint=0;break;case 0:break;case 1:if(this._errorHandler({position:h,code:r,currentState:n,collect:a,params:c,abort:!1}).abort)return;break;case 7:for(var f=this._csiHandlers[a<<8|r],_=f?f.length-1:-1;_>=0&&!1===f[_](c);_--);_<0&&this._csiHandlerFb(a<<8|r,c),this.precedingCodepoint=0;break;case 8:do{switch(r){case 59:c.addParam(0);break;case 58:c.addSubParam(-1);break;default:c.addDigit(r-48)}}while(++h47&&r<60);h--;break;case 9:a<<=8,a|=r;break;case 10:for(var d=this._escHandlers[a<<8|r],p=d?d.length-1:-1;p>=0&&!1===d[p]();p--);p<0&&this._escHandlerFb(a<<8|r),this.precedingCodepoint=0;break;case 11:c.reset(),c.addParam(0),a=0;break;case 12:s.hook(a<<8|r,c);break;case 13:for(var v=h+1;;++v)if(v>=t||24===(r=e[v])||26===r||27===r||r>127&&r<160){s.put(e,h,v),h=v-1;break}break;case 14:s.unhook(24!==r&&26!==r),27===r&&(i|=1),c.reset(),c.addParam(0),a=0,this.precedingCodepoint=0;break;case 4:o.start();break;case 5:for(var g=h+1;;g++)if(g>=t||(r=e[g])<32||r>127&&r<=159){o.put(e,h,g),h=g-1;break}break;case 6:o.end(24!==r&&26!==r),27===r&&(i|=1),c.reset(),c.addParam(0),a=0,this.precedingCodepoint=0}n=15&i}this._collect=a,this.currentState=n},r}(o.Disposable);t.EscapeSequenceParser=u},function(e,t,r){"use strict";var i,n=this&&this.__extends||(i=function(e,t){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])})(e,t)},function(e,t){function r(){this.constructor=e}i(e,t),e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)}),o=this&&this.__decorate||function(e,t,r,i){var n,o=arguments.length,s=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,r,i);else for(var a=e.length-1;a>=0;a--)(n=e[a])&&(s=(o<3?n(s):o>3?n(t,r,s):n(t,r))||s);return o>3&&s&&Object.defineProperty(t,r,s),s},s=this&&this.__param||function(e,t){return function(r,i){t(r,i,e)}};Object.defineProperty(t,"__esModule",{value:!0});var a=r(40),c=r(46),l=r(47),h=r(48),u=r(27),f=r(2),_=r(4),d=r(0),p=r(23),v=r(1),g=1,y=function(e){function t(t,r,i,n,o,s,f,_){var d=e.call(this)||this;d._colors=t,d._screenElement=r,d._linkifier=i,d._bufferService=n,d._charSizeService=o,d._optionsService=s,d.coreService=f,d.coreBrowserService=_,d._id=g++,d._onRequestRefreshRows=new v.EventEmitter;var p=d._optionsService.options.allowTransparency;return d._characterJoinerRegistry=new u.CharacterJoinerRegistry(d._bufferService),d._renderLayers=[new a.TextRenderLayer(d._screenElement,0,d._colors,d._characterJoinerRegistry,p,d._id,d._bufferService,s),new c.SelectionRenderLayer(d._screenElement,1,d._colors,d._id,d._bufferService,s),new h.LinkRenderLayer(d._screenElement,2,d._colors,d._id,d._linkifier,d._bufferService,s),new l.CursorRenderLayer(d._screenElement,3,d._colors,d._id,d._onRequestRefreshRows,d._bufferService,s,f,_)],d.dimensions={scaledCharWidth:0,scaledCharHeight:0,scaledCellWidth:0,scaledCellHeight:0,scaledCharLeft:0,scaledCharTop:0,scaledCanvasWidth:0,scaledCanvasHeight:0,canvasWidth:0,canvasHeight:0,actualCellWidth:0,actualCellHeight:0},d._devicePixelRatio=window.devicePixelRatio,d._updateDimensions(),d.onOptionsChanged(),d}return n(t,e),Object.defineProperty(t.prototype,"onRequestRefreshRows",{get:function(){return this._onRequestRefreshRows.event},enumerable:!0,configurable:!0}),t.prototype.dispose=function(){e.prototype.dispose.call(this),this._renderLayers.forEach(function(e){return e.dispose()}),p.removeTerminalFromCache(this._id)},t.prototype.onDevicePixelRatioChange=function(){this._devicePixelRatio!==window.devicePixelRatio&&(this._devicePixelRatio=window.devicePixelRatio,this.onResize(this._bufferService.cols,this._bufferService.rows))},t.prototype.setColors=function(e){var t=this;this._colors=e,this._renderLayers.forEach(function(e){e.setColors(t._colors),e.reset()})},t.prototype.onResize=function(e,t){var r=this;this._updateDimensions(),this._renderLayers.forEach(function(e){return e.resize(r.dimensions)}),this._screenElement.style.width=this.dimensions.canvasWidth+"px",this._screenElement.style.height=this.dimensions.canvasHeight+"px"},t.prototype.onCharSizeChanged=function(){this.onResize(this._bufferService.cols,this._bufferService.rows)},t.prototype.onBlur=function(){this._runOperation(function(e){return e.onBlur()})},t.prototype.onFocus=function(){this._runOperation(function(e){return e.onFocus()})},t.prototype.onSelectionChanged=function(e,t,r){void 0===r&&(r=!1),this._runOperation(function(i){return i.onSelectionChanged(e,t,r)})},t.prototype.onCursorMove=function(){this._runOperation(function(e){return e.onCursorMove()})},t.prototype.onOptionsChanged=function(){this._runOperation(function(e){return e.onOptionsChanged()})},t.prototype.clear=function(){this._runOperation(function(e){return e.reset()})},t.prototype._runOperation=function(e){this._renderLayers.forEach(function(t){return e(t)})},t.prototype.renderRows=function(e,t){this._renderLayers.forEach(function(r){return r.onGridChanged(e,t)})},t.prototype._updateDimensions=function(){this._charSizeService.hasValidSize&&(this.dimensions.scaledCharWidth=Math.floor(this._charSizeService.width*window.devicePixelRatio),this.dimensions.scaledCharHeight=Math.ceil(this._charSizeService.height*window.devicePixelRatio),this.dimensions.scaledCellHeight=Math.floor(this.dimensions.scaledCharHeight*this._optionsService.options.lineHeight),this.dimensions.scaledCharTop=1===this._optionsService.options.lineHeight?0:Math.round((this.dimensions.scaledCellHeight-this.dimensions.scaledCharHeight)/2),this.dimensions.scaledCellWidth=this.dimensions.scaledCharWidth+Math.round(this._optionsService.options.letterSpacing),this.dimensions.scaledCharLeft=Math.floor(this._optionsService.options.letterSpacing/2),this.dimensions.scaledCanvasHeight=this._bufferService.rows*this.dimensions.scaledCellHeight,this.dimensions.scaledCanvasWidth=this._bufferService.cols*this.dimensions.scaledCellWidth,this.dimensions.canvasHeight=Math.round(this.dimensions.scaledCanvasHeight/window.devicePixelRatio),this.dimensions.canvasWidth=Math.round(this.dimensions.scaledCanvasWidth/window.devicePixelRatio),this.dimensions.actualCellHeight=this.dimensions.canvasHeight/this._bufferService.rows,this.dimensions.actualCellWidth=this.dimensions.canvasWidth/this._bufferService.cols)},t.prototype.registerCharacterJoiner=function(e){return this._characterJoinerRegistry.registerCharacterJoiner(e)},t.prototype.deregisterCharacterJoiner=function(e){return this._characterJoinerRegistry.deregisterCharacterJoiner(e)},t=o([s(3,d.IBufferService),s(4,_.ICharSizeService),s(5,d.IOptionsService),s(6,d.ICoreService),s(7,_.ICoreBrowserService)],t)}(f.Disposable);t.Renderer=y},function(e,t,r){"use strict";var i,n=this&&this.__extends||(i=function(e,t){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])})(e,t)},function(e,t){function r(){this.constructor=e}i(e,t),e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)});Object.defineProperty(t,"__esModule",{value:!0});var o=r(41),s=r(13),a=r(6),c=r(3),l=r(27),h=r(5),u=function(e){function t(t,r,i,n,s,a,c,l){var u=e.call(this,t,"text",r,s,i,a,c,l)||this;return u.bufferService=c,u.optionsService=l,u._characterWidth=0,u._characterFont="",u._characterOverlapCache={},u._workCell=new h.CellData,u._state=new o.GridCache,u._characterJoinerRegistry=n,u}return n(t,e),t.prototype.resize=function(t){e.prototype.resize.call(this,t);var r=this._getFont(!1,!1);this._characterWidth===t.scaledCharWidth&&this._characterFont===r||(this._characterWidth=t.scaledCharWidth,this._characterFont=r,this._characterOverlapCache={}),this._state.clear(),this._state.resize(this._bufferService.cols,this._bufferService.rows)},t.prototype.reset=function(){this._state.clear(),this._clearAll()},t.prototype._forEachCell=function(e,t,r,i){for(var n=e;n<=t;n++)for(var o=n+this._bufferService.buffer.ydisp,s=this._bufferService.buffer.lines.get(o),a=r?r.getJoinedCharacters(o):[],h=0;h0&&h===a[0][0]){f=!0;var d=a.shift();u=new l.JoinedCellData(this._workCell,s.translateToString(!0,d[0],d[1]),d[1]-d[0]),_=d[1]-1}!f&&this._isOverlapping(u)&&_this._characterWidth;return this._ctx.restore(),this._characterOverlapCache[t]=r,r},t}(s.BaseRenderLayer);t.TextRenderLayer=u},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=function(){function e(){this.cache=[]}return e.prototype.resize=function(e,t){for(var r=0;r>>24,n=t.rgba>>>16&255,o=t.rgba>>>8&255,s=0;s=this.capacity)r=this._head,this._unlinkNode(r),delete this._map[r.key],r.key=e,r.value=t,this._map[e]=r;else{var i=this._nodePool;i.length>0?((r=i.pop()).key=e,r.value=t):r={prev:null,next:null,key:e,value:t},this._map[e]=r,this.size++}this._appendNode(r)},e}();t.LRUMap=i},function(e,t,r){"use strict";var i,n=this&&this.__extends||(i=function(e,t){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])})(e,t)},function(e,t){function r(){this.constructor=e}i(e,t),e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)});Object.defineProperty(t,"__esModule",{value:!0});var o=function(e){function t(t,r,i,n,o,s){var a=e.call(this,t,"selection",r,!0,i,n,o,s)||this;return a.bufferService=o,a.optionsService=s,a._clearState(),a}return n(t,e),t.prototype._clearState=function(){this._state={start:void 0,end:void 0,columnSelectMode:void 0,ydisp:void 0}},t.prototype.resize=function(t){e.prototype.resize.call(this,t),this._clearState()},t.prototype.reset=function(){this._state.start&&this._state.end&&(this._clearState(),this._clearAll())},t.prototype.onSelectionChanged=function(e,t,r){if(this._didStateChange(e,t,r,this._bufferService.buffer.ydisp))if(this._clearAll(),e&&t){var i=e[1]-this._bufferService.buffer.ydisp,n=t[1]-this._bufferService.buffer.ydisp,o=Math.max(i,0),s=Math.min(n,this._bufferService.rows-1);if(!(o>=this._bufferService.rows||s<0)){if(this._ctx.fillStyle=this._colors.selection.css,r){var a=e[0],c=t[0]-a,l=s-o+1;this._fillCells(a,o,c,l)}else{a=i===o?e[0]:0;var h=o===s?t[0]:this._bufferService.cols;this._fillCells(a,o,h-a,1);var u=Math.max(s-o-1,0);if(this._fillCells(0,o+1,this._bufferService.cols,u),o!==s){var f=n===s?t[0]:this._bufferService.cols;this._fillCells(0,s,f,1)}}this._state.start=[e[0],e[1]],this._state.end=[t[0],t[1]],this._state.columnSelectMode=r,this._state.ydisp=this._bufferService.buffer.ydisp}}else this._clearState()},t.prototype._didStateChange=function(e,t,r,i){return!this._areCoordinatesEqual(e,this._state.start)||!this._areCoordinatesEqual(t,this._state.end)||r!==this._state.columnSelectMode||i!==this._state.ydisp},t.prototype._areCoordinatesEqual=function(e,t){return!(!e||!t)&&(e[0]===t[0]&&e[1]===t[1])},t}(r(13).BaseRenderLayer);t.SelectionRenderLayer=o},function(e,t,r){"use strict";var i,n=this&&this.__extends||(i=function(e,t){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])})(e,t)},function(e,t){function r(){this.constructor=e}i(e,t),e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)});Object.defineProperty(t,"__esModule",{value:!0});var o=r(13),s=r(5),a=function(e){function t(t,r,i,n,o,a,c,l,h){var u=e.call(this,t,"cursor",r,!0,i,n,a,c)||this;return u._onRequestRefreshRowsEvent=o,u.bufferService=a,u.optionsService=c,u._coreService=l,u._coreBrowserService=h,u._cell=new s.CellData,u._state={x:0,y:0,isFocused:!1,style:"",width:0},u._cursorRenderers={bar:u._renderBarCursor.bind(u),block:u._renderBlockCursor.bind(u),underline:u._renderUnderlineCursor.bind(u)},u}return n(t,e),t.prototype.resize=function(t){e.prototype.resize.call(this,t),this._state={x:0,y:0,isFocused:!1,style:"",width:0}},t.prototype.reset=function(){this._clearCursor(),this._cursorBlinkStateManager&&(this._cursorBlinkStateManager.dispose(),this._cursorBlinkStateManager=void 0,this.onOptionsChanged())},t.prototype.onBlur=function(){this._cursorBlinkStateManager&&this._cursorBlinkStateManager.pause(),this._onRequestRefreshRowsEvent.fire({start:this._bufferService.buffer.y,end:this._bufferService.buffer.y})},t.prototype.onFocus=function(){this._cursorBlinkStateManager?this._cursorBlinkStateManager.resume():this._onRequestRefreshRowsEvent.fire({start:this._bufferService.buffer.y,end:this._bufferService.buffer.y})},t.prototype.onOptionsChanged=function(){var e,t=this;this._optionsService.options.cursorBlink?this._cursorBlinkStateManager||(this._cursorBlinkStateManager=new c(this._coreBrowserService.isFocused,function(){t._render(!0)})):(null===(e=this._cursorBlinkStateManager)||void 0===e||e.dispose(),this._cursorBlinkStateManager=void 0),this._onRequestRefreshRowsEvent.fire({start:this._bufferService.buffer.y,end:this._bufferService.buffer.y})},t.prototype.onCursorMove=function(){this._cursorBlinkStateManager&&this._cursorBlinkStateManager.restartBlinkAnimation()},t.prototype.onGridChanged=function(e,t){!this._cursorBlinkStateManager||this._cursorBlinkStateManager.isPaused?this._render(!1):this._cursorBlinkStateManager.restartBlinkAnimation()},t.prototype._render=function(e){if(this._coreService.isCursorInitialized&&!this._coreService.isCursorHidden){var t=this._bufferService.buffer.ybase+this._bufferService.buffer.y,r=t-this._bufferService.buffer.ydisp;if(r<0||r>=this._bufferService.rows)this._clearCursor();else if(this._bufferService.buffer.lines.get(t).loadCell(this._bufferService.buffer.x,this._cell),void 0!==this._cell.content){if(!this._coreBrowserService.isFocused){this._clearCursor(),this._ctx.save(),this._ctx.fillStyle=this._colors.cursor.css;var i=this._optionsService.options.cursorStyle;return i&&"block"!==i?this._cursorRenderers[i](this._bufferService.buffer.x,r,this._cell):this._renderBlurCursor(this._bufferService.buffer.x,r,this._cell),this._ctx.restore(),this._state.x=this._bufferService.buffer.x,this._state.y=r,this._state.isFocused=!1,this._state.style=i,void(this._state.width=this._cell.getWidth())}if(!this._cursorBlinkStateManager||this._cursorBlinkStateManager.isCursorVisible){if(this._state){if(this._state.x===this._bufferService.buffer.x&&this._state.y===r&&this._state.isFocused===this._coreBrowserService.isFocused&&this._state.style===this._optionsService.options.cursorStyle&&this._state.width===this._cell.getWidth())return;this._clearCursor()}this._ctx.save(),this._cursorRenderers[this._optionsService.options.cursorStyle||"block"](this._bufferService.buffer.x,r,this._cell),this._ctx.restore(),this._state.x=this._bufferService.buffer.x,this._state.y=r,this._state.isFocused=!1,this._state.style=this._optionsService.options.cursorStyle,this._state.width=this._cell.getWidth()}else this._clearCursor()}}else this._clearCursor()},t.prototype._clearCursor=function(){this._state&&(this._clearCells(this._state.x,this._state.y,this._state.width,1),this._state={x:0,y:0,isFocused:!1,style:"",width:0})},t.prototype._renderBarCursor=function(e,t,r){this._ctx.save(),this._ctx.fillStyle=this._colors.cursor.css,this._fillLeftLineAtCell(e,t,this._optionsService.options.cursorWidth),this._ctx.restore()},t.prototype._renderBlockCursor=function(e,t,r){this._ctx.save(),this._ctx.fillStyle=this._colors.cursor.css,this._fillCells(e,t,r.getWidth(),1),this._ctx.fillStyle=this._colors.cursorAccent.css,this._fillCharTrueColor(r,e,t),this._ctx.restore()},t.prototype._renderUnderlineCursor=function(e,t,r){this._ctx.save(),this._ctx.fillStyle=this._colors.cursor.css,this._fillBottomLineAtCells(e,t),this._ctx.restore()},t.prototype._renderBlurCursor=function(e,t,r){this._ctx.save(),this._ctx.strokeStyle=this._colors.cursor.css,this._strokeRectAtCell(e,t,r.getWidth(),1),this._ctx.restore()},t}(o.BaseRenderLayer);t.CursorRenderLayer=a;var c=function(){function e(e,t){this._renderCallback=t,this.isCursorVisible=!0,e&&this._restartInterval()}return Object.defineProperty(e.prototype,"isPaused",{get:function(){return!(this._blinkStartTimeout||this._blinkInterval)},enumerable:!0,configurable:!0}),e.prototype.dispose=function(){this._blinkInterval&&(window.clearInterval(this._blinkInterval),this._blinkInterval=void 0),this._blinkStartTimeout&&(window.clearTimeout(this._blinkStartTimeout),this._blinkStartTimeout=void 0),this._animationFrame&&(window.cancelAnimationFrame(this._animationFrame),this._animationFrame=void 0)},e.prototype.restartBlinkAnimation=function(){var e=this;this.isPaused||(this._animationTimeRestarted=Date.now(),this.isCursorVisible=!0,this._animationFrame||(this._animationFrame=window.requestAnimationFrame(function(){e._renderCallback(),e._animationFrame=void 0})))},e.prototype._restartInterval=function(e){var t=this;void 0===e&&(e=600),this._blinkInterval&&window.clearInterval(this._blinkInterval),this._blinkStartTimeout=setTimeout(function(){if(t._animationTimeRestarted){var e=600-(Date.now()-t._animationTimeRestarted);if(t._animationTimeRestarted=void 0,e>0)return void t._restartInterval(e)}t.isCursorVisible=!1,t._animationFrame=window.requestAnimationFrame(function(){t._renderCallback(),t._animationFrame=void 0}),t._blinkInterval=setInterval(function(){if(t._animationTimeRestarted){var e=600-(Date.now()-t._animationTimeRestarted);return t._animationTimeRestarted=void 0,void t._restartInterval(e)}t.isCursorVisible=!t.isCursorVisible,t._animationFrame=window.requestAnimationFrame(function(){t._renderCallback(),t._animationFrame=void 0})},600)},e)},e.prototype.pause=function(){this.isCursorVisible=!0,this._blinkInterval&&(window.clearInterval(this._blinkInterval),this._blinkInterval=void 0),this._blinkStartTimeout&&(window.clearTimeout(this._blinkStartTimeout),this._blinkStartTimeout=void 0),this._animationFrame&&(window.cancelAnimationFrame(this._animationFrame),this._animationFrame=void 0)},e.prototype.resume=function(){this._animationTimeRestarted=void 0,this._restartInterval(),this.restartBlinkAnimation()},e}()},function(e,t,r){"use strict";var i,n=this&&this.__extends||(i=function(e,t){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])})(e,t)},function(e,t){function r(){this.constructor=e}i(e,t),e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)});Object.defineProperty(t,"__esModule",{value:!0});var o=r(13),s=r(9),a=r(24),c=function(e){function t(t,r,i,n,o,s,a){var c=e.call(this,t,"link",r,!0,i,n,s,a)||this;return c.bufferService=s,c.optionsService=a,o.onLinkHover(function(e){return c._onLinkHover(e)}),o.onLinkLeave(function(e){return c._onLinkLeave(e)}),c}return n(t,e),t.prototype.resize=function(t){e.prototype.resize.call(this,t),this._state=void 0},t.prototype.reset=function(){this._clearCurrentLink()},t.prototype._clearCurrentLink=function(){if(this._state){this._clearCells(this._state.x1,this._state.y1,this._state.cols-this._state.x1,1);var e=this._state.y2-this._state.y1-1;e>0&&this._clearCells(0,this._state.y1+1,this._state.cols,e),this._clearCells(0,this._state.y2,this._state.x2,1),this._state=void 0}},t.prototype._onLinkHover=function(e){if(e.fg===s.INVERTED_DEFAULT_COLOR?this._ctx.fillStyle=this._colors.background.css:e.fg&&a.is256Color(e.fg)?this._ctx.fillStyle=this._colors.ansi[e.fg].css:this._ctx.fillStyle=this._colors.foreground.css,e.y1===e.y2)this._fillBottomLineAtCells(e.x1,e.y1,e.x2-e.x1);else{this._fillBottomLineAtCells(e.x1,e.y1,e.cols-e.x1);for(var t=e.y1+1;t=e.lines.length)){for(var r=e.ydisp+Math.min(this._rowsToLinkify.end,this._bufferService.rows)+1,i=Math.ceil(2e3/this._bufferService.cols),n=this._bufferService.buffer.iterator(!1,t,r,i,i);n.hasNext();)for(var o=n.next(),s=0;s=0;t--)if(e.priority<=this._linkMatchers[t].priority)return void this._linkMatchers.splice(t+1,0,e);this._linkMatchers.splice(0,0,e)}else this._linkMatchers.push(e)},e.prototype.deregisterLinkMatcher=function(e){for(var t=0;t>9&511:void 0;r.validationCallback?r.validationCallback(a,function(e){n._rowsTimeoutId||e&&n._addLink(l[1],l[0]-n._bufferService.buffer.ydisp,a,r,f)}):c._addLink(l[1],l[0]-c._bufferService.buffer.ydisp,a,r,f)},c=this;null!==(i=o.exec(t));){if("break"===a())break}},e.prototype._addLink=function(e,t,r,i,n){var s=this;if(this._mouseZoneManager&&this._element){var a=this._unicodeService.getStringCellWidth(r),c=e%this._bufferService.cols,l=t+Math.floor(e/this._bufferService.cols),h=(c+a)%this._bufferService.cols,u=l+Math.floor((c+a)/this._bufferService.cols);0===h&&(h=this._bufferService.cols,u--),this._mouseZoneManager.add(new o(c+1,l+1,h+1,u+1,function(e){if(i.handler)return i.handler(e,r);var t=window.open();t?(t.opener=null,t.location.href=r):console.warn("Opening link blocked as opener could not be cleared")},function(){s._onLinkHover.fire(s._createLinkHoverEvent(c,l,h,u,n)),s._element.classList.add("xterm-cursor-pointer")},function(e){s._onLinkTooltip.fire(s._createLinkHoverEvent(c,l,h,u,n)),i.hoverTooltipCallback&&i.hoverTooltipCallback(e,r,{start:{x:c,y:l},end:{x:h,y:u}})},function(){s._onLinkLeave.fire(s._createLinkHoverEvent(c,l,h,u,n)),s._element.classList.remove("xterm-cursor-pointer"),i.hoverLeaveCallback&&i.hoverLeaveCallback()},function(e){return!i.willLinkActivate||i.willLinkActivate(e,r)}))}},e.prototype._createLinkHoverEvent=function(e,t,r,i,n){return{x1:e,y1:t,x2:r,y2:i,cols:this._bufferService.cols,fg:n}},e._timeBeforeLatency=200,e}();t.Linkifier=n;var o=function(e,t,r,i,n,o,s,a,c){this.x1=e,this.y1=t,this.x2=r,this.y2=i,this.clickCallback=n,this.hoverCallback=o,this.tooltipCallback=s,this.leaveCallback=a,this.willLinkActivate=c};t.MouseZone=o},function(e,t,r){"use strict";var i=this&&this.__decorate||function(e,t,r,i){var n,o=arguments.length,s=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,r,i);else for(var a=e.length-1;a>=0;a--)(n=e[a])&&(s=(o<3?n(s):o>3?n(t,r,s):n(t,r))||s);return o>3&&s&&Object.defineProperty(t,r,s),s},n=this&&this.__param||function(e,t){return function(r,i){t(r,i,e)}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(11),s=r(51),a=r(5),c=r(1),l=r(4),h=r(0),u=r(28),f=r(52),_=String.fromCharCode(160),d=new RegExp(_,"g"),p=function(){function e(e,t,r,i,n,o,l,h){var u=this;this._scrollLines=e,this._element=t,this._screenElement=r,this._charSizeService=i,this._bufferService=n,this._coreService=o,this._mouseService=l,this._optionsService=h,this._dragScrollAmount=0,this._enabled=!0,this._workCell=new a.CellData,this._mouseDownTimeStamp=0,this._onLinuxMouseSelection=new c.EventEmitter,this._onRedrawRequest=new c.EventEmitter,this._onSelectionChange=new c.EventEmitter,this._mouseMoveListener=function(e){return u._onMouseMove(e)},this._mouseUpListener=function(e){return u._onMouseUp(e)},this._coreService.onUserInput(function(){u.hasSelection&&u.clearSelection()}),this._trimListener=this._bufferService.buffer.lines.onTrim(function(e){return u._onTrim(e)}),this._bufferService.buffers.onBufferActivate(function(e){return u._onBufferActivate(e)}),this.enable(),this._model=new s.SelectionModel(this._bufferService),this._activeSelectionMode=0}return Object.defineProperty(e.prototype,"onLinuxMouseSelection",{get:function(){return this._onLinuxMouseSelection.event},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"onRedrawRequest",{get:function(){return this._onRedrawRequest.event},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"onSelectionChange",{get:function(){return this._onSelectionChange.event},enumerable:!0,configurable:!0}),e.prototype.dispose=function(){this._removeMouseDownListeners()},e.prototype.reset=function(){this.clearSelection()},e.prototype.disable=function(){this.clearSelection(),this._enabled=!1},e.prototype.enable=function(){this._enabled=!0},Object.defineProperty(e.prototype,"selectionStart",{get:function(){return this._model.finalSelectionStart},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"selectionEnd",{get:function(){return this._model.finalSelectionEnd},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"hasSelection",{get:function(){var e=this._model.finalSelectionStart,t=this._model.finalSelectionEnd;return!(!e||!t)&&(e[0]!==t[0]||e[1]!==t[1])},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"selectionText",{get:function(){var e=this._model.finalSelectionStart,t=this._model.finalSelectionEnd;if(!e||!t)return"";var r=this._bufferService.buffer,i=[];if(3===this._activeSelectionMode){if(e[0]===t[0])return"";for(var n=e[1];n<=t[1];n++){var s=r.translateBufferLineToString(n,!0,e[0],t[0]);i.push(s)}}else{var a=e[1]===t[1]?t[0]:void 0;i.push(r.translateBufferLineToString(e[1],!0,e[0],a));for(n=e[1]+1;n<=t[1]-1;n++){var c=r.lines.get(n);s=r.translateBufferLineToString(n,!0);c&&c.isWrapped?i[i.length-1]+=s:i.push(s)}if(e[1]!==t[1]){c=r.lines.get(t[1]),s=r.translateBufferLineToString(t[1],!0,0,t[0]);c&&c.isWrapped?i[i.length-1]+=s:i.push(s)}}return i.map(function(e){return e.replace(d," ")}).join(o.isWindows?"\r\n":"\n")},enumerable:!0,configurable:!0}),e.prototype.clearSelection=function(){this._model.clearSelection(),this._removeMouseDownListeners(),this.refresh(),this._onSelectionChange.fire()},e.prototype.refresh=function(e){var t=this;(this._refreshAnimationFrame||(this._refreshAnimationFrame=window.requestAnimationFrame(function(){return t._refresh()})),o.isLinux&&e)&&(this.selectionText.length&&this._onLinuxMouseSelection.fire(this.selectionText))},e.prototype._refresh=function(){this._refreshAnimationFrame=void 0,this._onRedrawRequest.fire({start:this._model.finalSelectionStart,end:this._model.finalSelectionEnd,columnSelectMode:3===this._activeSelectionMode})},e.prototype.isClickInSelection=function(e){var t=this._getMouseBufferCoords(e),r=this._model.finalSelectionStart,i=this._model.finalSelectionEnd;return!!(r&&i&&t)&&this._areCoordsInSelection(t,r,i)},e.prototype._areCoordsInSelection=function(e,t,r){return e[1]>t[1]&&e[1]=t[0]&&e[0]=t[0]},e.prototype.selectWordAtCursor=function(e){var t=this._getMouseBufferCoords(e);t&&(this._selectWordAt(t,!1),this._model.selectionEnd=void 0,this.refresh(!0))},e.prototype.selectAll=function(){this._model.isSelectAllActive=!0,this.refresh(),this._onSelectionChange.fire()},e.prototype.selectLines=function(e,t){this._model.clearSelection(),e=Math.max(e,0),t=Math.min(t,this._bufferService.buffer.lines.length-1),this._model.selectionStart=[0,e],this._model.selectionEnd=[this._bufferService.cols,t],this.refresh(),this._onSelectionChange.fire()},e.prototype._onTrim=function(e){this._model.onTrim(e)&&this.refresh()},e.prototype._getMouseBufferCoords=function(e){var t=this._mouseService.getCoords(e,this._screenElement,this._bufferService.cols,this._bufferService.rows,!0);if(t)return t[0]--,t[1]--,t[1]+=this._bufferService.buffer.ydisp,t},e.prototype._getMouseEventScrollAmount=function(e){var t=u.getCoordsRelativeToElement(e,this._screenElement)[1],r=this._bufferService.rows*Math.ceil(this._charSizeService.height*this._optionsService.options.lineHeight);return t>=0&&t<=r?0:(t>r&&(t-=r),t=Math.min(Math.max(t,-50),50),(t/=50)/Math.abs(t)+Math.round(14*t))},e.prototype.shouldForceSelection=function(e){return o.isMac?e.altKey&&this._optionsService.options.macOptionClickForcesSelection:e.shiftKey},e.prototype.onMouseDown=function(e){if(this._mouseDownTimeStamp=e.timeStamp,(2!==e.button||!this.hasSelection)&&0===e.button){if(!this._enabled){if(!this.shouldForceSelection(e))return;e.stopPropagation()}e.preventDefault(),this._dragScrollAmount=0,this._enabled&&e.shiftKey?this._onIncrementalClick(e):1===e.detail?this._onSingleClick(e):2===e.detail?this._onDoubleClick(e):3===e.detail&&this._onTripleClick(e),this._addMouseDownListeners(),this.refresh(!0)}},e.prototype._addMouseDownListeners=function(){var e=this;this._screenElement.ownerDocument&&(this._screenElement.ownerDocument.addEventListener("mousemove",this._mouseMoveListener),this._screenElement.ownerDocument.addEventListener("mouseup",this._mouseUpListener)),this._dragScrollIntervalTimer=window.setInterval(function(){return e._dragScroll()},50)},e.prototype._removeMouseDownListeners=function(){this._screenElement.ownerDocument&&(this._screenElement.ownerDocument.removeEventListener("mousemove",this._mouseMoveListener),this._screenElement.ownerDocument.removeEventListener("mouseup",this._mouseUpListener)),clearInterval(this._dragScrollIntervalTimer),this._dragScrollIntervalTimer=void 0},e.prototype._onIncrementalClick=function(e){this._model.selectionStart&&(this._model.selectionEnd=this._getMouseBufferCoords(e))},e.prototype._onSingleClick=function(e){if(this._model.selectionStartLength=0,this._model.isSelectAllActive=!1,this._activeSelectionMode=this.shouldColumnSelect(e)?3:0,this._model.selectionStart=this._getMouseBufferCoords(e),this._model.selectionStart){this._model.selectionEnd=void 0;var t=this._bufferService.buffer.lines.get(this._model.selectionStart[1]);t&&t.length!==this._model.selectionStart[0]&&0===t.hasWidth(this._model.selectionStart[0])&&this._model.selectionStart[0]++}},e.prototype._onDoubleClick=function(e){var t=this._getMouseBufferCoords(e);t&&(this._activeSelectionMode=1,this._selectWordAt(t,!0))},e.prototype._onTripleClick=function(e){var t=this._getMouseBufferCoords(e);t&&(this._activeSelectionMode=2,this._selectLineAt(t[1]))},e.prototype.shouldColumnSelect=function(e){return e.altKey&&!(o.isMac&&this._optionsService.options.macOptionClickForcesSelection)},e.prototype._onMouseMove=function(e){if(e.stopImmediatePropagation(),this._model.selectionStart){var t=this._model.selectionEnd?[this._model.selectionEnd[0],this._model.selectionEnd[1]]:null;if(this._model.selectionEnd=this._getMouseBufferCoords(e),this._model.selectionEnd){2===this._activeSelectionMode?this._model.selectionEnd[1]0?this._model.selectionEnd[0]=this._bufferService.cols:this._dragScrollAmount<0&&(this._model.selectionEnd[0]=0));var r=this._bufferService.buffer;if(this._model.selectionEnd[1]0?(3!==this._activeSelectionMode&&(this._model.selectionEnd[0]=this._bufferService.cols),this._model.selectionEnd[1]=Math.min(e.ydisp+this._bufferService.rows,e.lines.length-1)):(3!==this._activeSelectionMode&&(this._model.selectionEnd[0]=0),this._model.selectionEnd[1]=e.ydisp),this.refresh()}},e.prototype._onMouseUp=function(e){var t=e.timeStamp-this._mouseDownTimeStamp;if(this._removeMouseDownListeners(),this.selectionText.length<=1&&t<500){if(e.altKey&&this._bufferService.buffer.ybase===this._bufferService.buffer.ydisp){var r=this._mouseService.getCoords(e,this._element,this._bufferService.cols,this._bufferService.rows,!1);if(r&&void 0!==r[0]&&void 0!==r[1]){var i=f.moveToCellSequence(r[0]-1,r[1]-1,this._bufferService,this._coreService.decPrivateModes.applicationCursorKeys);this._coreService.triggerDataEvent(i,!0)}}}else this.hasSelection&&this._onSelectionChange.fire()},e.prototype._onBufferActivate=function(e){var t=this;this.clearSelection(),this._trimListener.dispose(),this._trimListener=e.activeBuffer.lines.onTrim(function(e){return t._onTrim(e)})},e.prototype._convertViewportColToCharacterIndex=function(e,t){for(var r=t[0],i=0;t[0]>=i;i++){var n=e.loadCell(i,this._workCell).getChars().length;0===this._workCell.getWidth()?r--:n>1&&t[0]!==i&&(r+=n-1)}return r},e.prototype.setSelection=function(e,t,r){this._model.clearSelection(),this._removeMouseDownListeners(),this._model.selectionStart=[e,t],this._model.selectionStartLength=r,this.refresh()},e.prototype._getWordAt=function(e,t,r,i){if(void 0===r&&(r=!0),void 0===i&&(i=!0),!(e[0]>=this._bufferService.cols)){var n=this._bufferService.buffer,o=n.lines.get(e[1]);if(o){var s=n.translateBufferLineToString(e[1],!1),a=this._convertViewportColToCharacterIndex(o,e),c=a,l=e[0]-a,h=0,u=0,f=0,_=0;if(" "===s.charAt(a)){for(;a>0&&" "===s.charAt(a-1);)a--;for(;c1&&(_+=v-1,c+=v-1);d>0&&a>0&&!this._isCharWordSeparator(o.loadCell(d-1,this._workCell));){o.loadCell(d-1,this._workCell);var g=this._workCell.getChars().length;0===this._workCell.getWidth()?(h++,d--):g>1&&(f+=g-1,a-=g-1),a--,d--}for(;p1&&(_+=y-1,c+=y-1),c++,p++}}c++;var b=a+l-h+f,m=Math.min(this._bufferService.cols,c-a+h+u-f-_);if(t||""!==s.slice(a,c).trim()){if(r&&0===b&&32!==o.getCodePoint(0)){var S=n.lines.get(e[1]-1);if(S&&o.isWrapped&&32!==S.getCodePoint(this._bufferService.cols-1)){var C=this._getWordAt([this._bufferService.cols-1,e[1]-1],!1,!0,!1);if(C){var w=this._bufferService.cols-C.start;b-=w,m+=w}}}if(i&&b+m===this._bufferService.cols&&32!==o.getCodePoint(this._bufferService.cols-1)){var E=n.lines.get(e[1]+1);if(E&&E.isWrapped&&32!==E.getCodePoint(0)){var L=this._getWordAt([0,e[1]+1],!1,!1,!0);L&&(m+=L.length)}}return{start:b,length:m}}}}},e.prototype._selectWordAt=function(e,t){var r=this._getWordAt(e,t);if(r){for(;r.start<0;)r.start+=this._bufferService.cols,e[1]--;this._model.selectionStart=[r.start,e[1]],this._model.selectionStartLength=r.length}},e.prototype._selectToWordAt=function(e){var t=this._getWordAt(e,!0);if(t){for(var r=e[1];t.start<0;)t.start+=this._bufferService.cols,r--;if(!this._model.areSelectionValuesReversed())for(;t.start+t.length>this._bufferService.cols;)t.length-=this._bufferService.cols,r++;this._model.selectionEnd=[this._model.areSelectionValuesReversed()?t.start:t.start+t.length,r]}},e.prototype._isCharWordSeparator=function(e){return 0!==e.getWidth()&&this._optionsService.options.wordSeparator.indexOf(e.getChars())>=0},e.prototype._selectLineAt=function(e){var t=this._bufferService.buffer.getWrappedRangeForLine(e);this._model.selectionStart=[0,t.first],this._model.selectionEnd=[this._bufferService.cols,t.last],this._model.selectionStartLength=0},e=i([n(3,l.ICharSizeService),n(4,h.IBufferService),n(5,h.ICoreService),n(6,l.IMouseService),n(7,h.IOptionsService)],e)}();t.SelectionService=p},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=function(){function e(e){this._bufferService=e,this.isSelectAllActive=!1,this.selectionStartLength=0}return e.prototype.clearSelection=function(){this.selectionStart=void 0,this.selectionEnd=void 0,this.isSelectAllActive=!1,this.selectionStartLength=0},Object.defineProperty(e.prototype,"finalSelectionStart",{get:function(){return this.isSelectAllActive?[0,0]:this.selectionEnd&&this.selectionStart&&this.areSelectionValuesReversed()?this.selectionEnd:this.selectionStart},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"finalSelectionEnd",{get:function(){if(this.isSelectAllActive)return[this._bufferService.cols,this._bufferService.buffer.ybase+this._bufferService.rows-1];if(this.selectionStart){if(!this.selectionEnd||this.areSelectionValuesReversed()){var e=this.selectionStart[0]+this.selectionStartLength;return e>this._bufferService.cols?[e%this._bufferService.cols,this.selectionStart[1]+Math.floor(e/this._bufferService.cols)]:[e,this.selectionStart[1]]}return this.selectionStartLength&&this.selectionEnd[1]===this.selectionStart[1]?[Math.max(this.selectionStart[0]+this.selectionStartLength,this.selectionEnd[0]),this.selectionEnd[1]]:this.selectionEnd}},enumerable:!0,configurable:!0}),e.prototype.areSelectionValuesReversed=function(){var e=this.selectionStart,t=this.selectionEnd;return!(!e||!t)&&(e[1]>t[1]||e[1]===t[1]&&e[0]>t[0])},e.prototype.onTrim=function(e){return this.selectionStart&&(this.selectionStart[1]-=e),this.selectionEnd&&(this.selectionEnd[1]-=e),this.selectionEnd&&this.selectionEnd[1]<0?(this.clearSelection(),!0):(this.selectionStart&&this.selectionStart[1]<0&&(this.selectionStart[1]=0),!1)},e}();t.SelectionModel=i},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=r(12);function n(e,t,r,i){var n=e-o(r,e),s=t-o(r,t);return h(Math.abs(n-s)-function(e,t,r){for(var i=0,n=e-o(r,e),s=t-o(r,t),c=0;c=0&&t0?i-o(s,i):t,e=r&&ct?"A":"B"}function c(e,t,r,i,n,o){for(var s=e,a=t,c="";s!==r||a!==i;)s+=n?1:-1,n&&s>o.cols-1?(c+=o.buffer.translateBufferLineToString(a,!1,e,s),s=0,e=0,a++):!n&&s<0&&(c+=o.buffer.translateBufferLineToString(a,!1,0,e+1),e=s=o.cols-1,a--);return c+o.buffer.translateBufferLineToString(a,!1,e,s)}function l(e,t){var r=t?"O":"[";return i.C0.ESC+r+e}function h(e,t){e=Math.floor(e);for(var r="",i=0;i0?i-o(a,i):t;var _=i,d=s(e,t,r,i,a,u);return h(c(e,f,r,_,"C"===d,a).length,l(d,u))}(u,f,e,t,r,i);if(f===t)return a=u>e?"D":"C",h(Math.abs(u-e),l(a,i));a=f>t?"D":"C";var _=Math.abs(f-t);return h(function(e,t){return t.cols-e}(f>t?e:u,r)+(_-1)*r.cols+1+((f>t?u:e)-1),l(a,i))}},function(e,t,r){"use strict";var i=this&&this.__decorate||function(e,t,r,i){var n,o=arguments.length,s=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,r,i);else for(var a=e.length-1;a>=0;a--)(n=e[a])&&(s=(o<3?n(s):o>3?n(t,r,s):n(t,r))||s);return o>3&&s&&Object.defineProperty(t,r,s),s},n=this&&this.__param||function(e,t){return function(r,i){t(r,i,e)}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(0),s=function(){function e(e){this._optionsService=e}return Object.defineProperty(e,"audioContext",{get:function(){if(!e._audioContext){var t=window.AudioContext||window.webkitAudioContext;if(!t)return console.warn("Web Audio API is not supported by this browser. Consider upgrading to the latest version"),null;e._audioContext=new t}return e._audioContext},enumerable:!0,configurable:!0}),e.prototype.playBellSound=function(){var t=e.audioContext;if(t){var r=t.createBufferSource();t.decodeAudioData(this._base64ToArrayBuffer(this._removeMimeType(this._optionsService.options.bellSound)),function(e){r.buffer=e,r.connect(t.destination),r.start(0)})}},e.prototype._base64ToArrayBuffer=function(e){for(var t=window.atob(e),r=t.length,i=new Uint8Array(r),n=0;n=0;a--)(n=e[a])&&(s=(o<3?n(s):o>3?n(t,r,s):n(t,r))||s);return o>3&&s&&Object.defineProperty(t,r,s),s},s=this&&this.__param||function(e,t){return function(r,i){t(r,i,e)}};Object.defineProperty(t,"__esModule",{value:!0});var a=r(2),c=r(8),l=r(4),h=r(0),u=function(e){function t(t,r,i,n,o){var s=e.call(this)||this;return s._element=t,s._screenElement=r,s._bufferService=i,s._mouseService=n,s._selectionService=o,s._zones=[],s._areZonesActive=!1,s._lastHoverCoords=[void 0,void 0],s._initialSelectionLength=0,s.register(c.addDisposableDomListener(s._element,"mousedown",function(e){return s._onMouseDown(e)})),s._mouseMoveListener=function(e){return s._onMouseMove(e)},s._mouseLeaveListener=function(e){return s._onMouseLeave(e)},s._clickListener=function(e){return s._onClick(e)},s}return n(t,e),t.prototype.dispose=function(){e.prototype.dispose.call(this),this._deactivate()},t.prototype.add=function(e){this._zones.push(e),1===this._zones.length&&this._activate()},t.prototype.clearAll=function(e,t){if(0!==this._zones.length){e&&t||(e=0,t=this._bufferService.rows-1);for(var r=0;re&&i.y1<=t+1||i.y2>e&&i.y2<=t+1||i.y1t+1)&&(this._currentZone&&this._currentZone===i&&(this._currentZone.leaveCallback(),this._currentZone=void 0),this._zones.splice(r--,1))}0===this._zones.length&&this._deactivate()}},t.prototype._activate=function(){this._areZonesActive||(this._areZonesActive=!0,this._element.addEventListener("mousemove",this._mouseMoveListener),this._element.addEventListener("mouseleave",this._mouseLeaveListener),this._element.addEventListener("click",this._clickListener))},t.prototype._deactivate=function(){this._areZonesActive&&(this._areZonesActive=!1,this._element.removeEventListener("mousemove",this._mouseMoveListener),this._element.removeEventListener("mouseleave",this._mouseLeaveListener),this._element.removeEventListener("click",this._clickListener))},t.prototype._onMouseMove=function(e){this._lastHoverCoords[0]===e.pageX&&this._lastHoverCoords[1]===e.pageY||(this._onHover(e),this._lastHoverCoords=[e.pageX,e.pageY])},t.prototype._onHover=function(e){var t=this,r=this._findZoneEventAt(e);r!==this._currentZone&&(this._currentZone&&(this._currentZone.leaveCallback(),this._currentZone=void 0,this._tooltipTimeout&&clearTimeout(this._tooltipTimeout)),r&&(this._currentZone=r,r.hoverCallback&&r.hoverCallback(e),this._tooltipTimeout=setTimeout(function(){return t._onTooltip(e)},500)))},t.prototype._onTooltip=function(e){this._tooltipTimeout=void 0;var t=this._findZoneEventAt(e);t&&t.tooltipCallback&&t.tooltipCallback(e)},t.prototype._onMouseDown=function(e){var t;(this._initialSelectionLength=this._getSelectionLength(),this._areZonesActive)&&((null===(t=this._findZoneEventAt(e))||void 0===t?void 0:t.willLinkActivate(e))&&(e.preventDefault(),e.stopImmediatePropagation()))},t.prototype._onMouseLeave=function(e){this._currentZone&&(this._currentZone.leaveCallback(),this._currentZone=void 0,this._tooltipTimeout&&clearTimeout(this._tooltipTimeout))},t.prototype._onClick=function(e){var t=this._findZoneEventAt(e),r=this._getSelectionLength();t&&r===this._initialSelectionLength&&(t.clickCallback(e),e.preventDefault(),e.stopImmediatePropagation())},t.prototype._getSelectionLength=function(){var e=this._selectionService.selectionText;return e?e.length:0},t.prototype._findZoneEventAt=function(e){var t=this._mouseService.getCoords(e,this._screenElement,this._bufferService.cols,this._bufferService.rows);if(t)for(var r=t[0],i=t[1],n=0;n=o.x1&&r=o.x1||i===o.y2&&ro.y1&&ie;)this._rowContainer.removeChild(this._rowElements.pop());this._rowElements[this._rowElements.length-1].addEventListener("focus",this._bottomBoundaryFocusListener),this._refreshRowsDimensions()},t.prototype._createAccessibilityTreeNode=function(){var e=document.createElement("div");return e.setAttribute("role","listitem"),e.tabIndex=-1,this._refreshRowDimensions(e),e},t.prototype._onTab=function(e){for(var t=0;t0)this._charsToConsume.shift()!==e&&(this._charsToAnnounce+=e);else this._charsToAnnounce+=e;"\n"===e&&(this._liveRegionLineCount++,21===this._liveRegionLineCount&&(this._liveRegion.textContent+=o.tooMuchOutput)),s.isMac&&this._liveRegion.textContent&&this._liveRegion.textContent.length>0&&!this._liveRegion.parentNode&&setTimeout(function(){t._accessibilityTreeRoot.appendChild(t._liveRegion)},0)}},t.prototype._clearLiveRegion=function(){this._liveRegion.textContent="",this._liveRegionLineCount=0,s.isMac&&this._liveRegion.parentNode&&this._accessibilityTreeRoot.removeChild(this._liveRegion)},t.prototype._onKey=function(e){this._clearLiveRegion(),this._charsToConsume.push(e)},t.prototype._refreshRows=function(e,t){this._renderRowsDebouncer.refresh(e,t,this._terminal.rows)},t.prototype._renderRows=function(e,t){for(var r=this._terminal.buffer,i=r.lines.length.toString(),n=e;n<=t;n++){var o=r.translateBufferLineToString(r.ydisp+n,!0),s=(r.ydisp+n+1).toString(),a=this._rowElements[n];a&&(0===o.length?a.innerHTML=" ":a.textContent=o,a.setAttribute("aria-posinset",s),a.setAttribute("aria-setsize",i))}this._announceCharacters()},t.prototype._refreshRowsDimensions=function(){if(this._renderService.dimensions.actualCellHeight){this._rowElements.length!==this._terminal.rows&&this._onResize(this._terminal.rows);for(var e=0;e=0;a--)(n=e[a])&&(s=(o<3?n(s):o>3?n(t,r,s):n(t,r))||s);return o>3&&s&&Object.defineProperty(t,r,s),s},s=this&&this.__param||function(e,t){return function(r,i){t(r,i,e)}};Object.defineProperty(t,"__esModule",{value:!0});var a=r(57),c=r(9),l=r(2),h=r(4),u=r(0),f=r(1),_=r(10),d="xterm-dom-renderer-owner-",p="xterm-rows",v="xterm-selection",g=1,y=function(e){function t(t,r,i,n,o,s,c,l){var h=e.call(this)||this;return h._colors=t,h._element=r,h._screenElement=i,h._viewportElement=n,h._linkifier=o,h._charSizeService=s,h._optionsService=c,h._bufferService=l,h._terminalClass=g++,h._rowElements=[],h._onRequestRefreshRows=new f.EventEmitter,h._rowContainer=document.createElement("div"),h._rowContainer.classList.add(p),h._rowContainer.style.lineHeight="normal",h._rowContainer.setAttribute("aria-hidden","true"),h._refreshRowElements(h._bufferService.cols,h._bufferService.rows),h._selectionContainer=document.createElement("div"),h._selectionContainer.classList.add(v),h._selectionContainer.setAttribute("aria-hidden","true"),h.dimensions={scaledCharWidth:0,scaledCharHeight:0,scaledCellWidth:0,scaledCellHeight:0,scaledCharLeft:0,scaledCharTop:0,scaledCanvasWidth:0,scaledCanvasHeight:0,canvasWidth:0,canvasHeight:0,actualCellWidth:0,actualCellHeight:0},h._updateDimensions(),h._injectCss(),h._rowFactory=new a.DomRendererRowFactory(document,h._optionsService,h._colors),h._element.classList.add(d+h._terminalClass),h._screenElement.appendChild(h._rowContainer),h._screenElement.appendChild(h._selectionContainer),h._linkifier.onLinkHover(function(e){return h._onLinkHover(e)}),h._linkifier.onLinkLeave(function(e){return h._onLinkLeave(e)}),h}return n(t,e),Object.defineProperty(t.prototype,"onRequestRefreshRows",{get:function(){return this._onRequestRefreshRows.event},enumerable:!0,configurable:!0}),t.prototype.dispose=function(){this._element.classList.remove(d+this._terminalClass),this._screenElement.removeChild(this._rowContainer),this._screenElement.removeChild(this._selectionContainer),this._screenElement.removeChild(this._themeStyleElement),this._screenElement.removeChild(this._dimensionsStyleElement),e.prototype.dispose.call(this)},t.prototype._updateDimensions=function(){var e=this;this.dimensions.scaledCharWidth=this._charSizeService.width*window.devicePixelRatio,this.dimensions.scaledCharHeight=Math.ceil(this._charSizeService.height*window.devicePixelRatio),this.dimensions.scaledCellWidth=this.dimensions.scaledCharWidth+Math.round(this._optionsService.options.letterSpacing),this.dimensions.scaledCellHeight=Math.floor(this.dimensions.scaledCharHeight*this._optionsService.options.lineHeight),this.dimensions.scaledCharLeft=0,this.dimensions.scaledCharTop=0,this.dimensions.scaledCanvasWidth=this.dimensions.scaledCellWidth*this._bufferService.cols,this.dimensions.scaledCanvasHeight=this.dimensions.scaledCellHeight*this._bufferService.rows,this.dimensions.canvasWidth=Math.round(this.dimensions.scaledCanvasWidth/window.devicePixelRatio),this.dimensions.canvasHeight=Math.round(this.dimensions.scaledCanvasHeight/window.devicePixelRatio),this.dimensions.actualCellWidth=this.dimensions.canvasWidth/this._bufferService.cols,this.dimensions.actualCellHeight=this.dimensions.canvasHeight/this._bufferService.rows,this._rowElements.forEach(function(t){t.style.width=e.dimensions.canvasWidth+"px",t.style.height=e.dimensions.actualCellHeight+"px",t.style.lineHeight=e.dimensions.actualCellHeight+"px",t.style.overflow="hidden"}),this._dimensionsStyleElement||(this._dimensionsStyleElement=document.createElement("style"),this._screenElement.appendChild(this._dimensionsStyleElement));var t=this._terminalSelector+" ."+p+" span { display: inline-block; height: 100%; vertical-align: top; width: "+this.dimensions.actualCellWidth+"px}";this._dimensionsStyleElement.innerHTML=t,this._selectionContainer.style.height=this._viewportElement.style.height,this._screenElement.style.width=this.dimensions.canvasWidth+"px",this._screenElement.style.height=this.dimensions.canvasHeight+"px"},t.prototype.setColors=function(e){this._colors=e,this._injectCss()},t.prototype._injectCss=function(){var e=this;this._themeStyleElement||(this._themeStyleElement=document.createElement("style"),this._screenElement.appendChild(this._themeStyleElement));var t=this._terminalSelector+" ."+p+" { color: "+this._colors.foreground.css+"; background-color: "+this._colors.background.css+"; font-family: "+this._optionsService.options.fontFamily+"; font-size: "+this._optionsService.options.fontSize+"px;}";t+=this._terminalSelector+" span:not(."+a.BOLD_CLASS+") { font-weight: "+this._optionsService.options.fontWeight+";}"+this._terminalSelector+" span."+a.BOLD_CLASS+" { font-weight: "+this._optionsService.options.fontWeightBold+";}"+this._terminalSelector+" span."+a.ITALIC_CLASS+" { font-style: italic;}",t+="@keyframes blink_box_shadow_"+this._terminalClass+" { 50% { box-shadow: none; }}",t+="@keyframes blink_block_"+this._terminalClass+" { 0% { background-color: "+this._colors.cursor.css+"; color: "+this._colors.cursorAccent.css+"; } 50% { background-color: "+this._colors.cursorAccent.css+"; color: "+this._colors.cursor.css+"; }}",t+=this._terminalSelector+" ."+p+":not(.xterm-focus) ."+a.CURSOR_CLASS+"."+a.CURSOR_STYLE_BLOCK_CLASS+" { outline: 1px solid "+this._colors.cursor.css+"; outline-offset: -1px;}"+this._terminalSelector+" ."+p+".xterm-focus ."+a.CURSOR_CLASS+"."+a.CURSOR_BLINK_CLASS+":not(."+a.CURSOR_STYLE_BLOCK_CLASS+") { animation: blink_box_shadow_"+this._terminalClass+" 1s step-end infinite;}"+this._terminalSelector+" ."+p+".xterm-focus ."+a.CURSOR_CLASS+"."+a.CURSOR_BLINK_CLASS+"."+a.CURSOR_STYLE_BLOCK_CLASS+" { animation: blink_block_"+this._terminalClass+" 1s step-end infinite;}"+this._terminalSelector+" ."+p+".xterm-focus ."+a.CURSOR_CLASS+"."+a.CURSOR_STYLE_BLOCK_CLASS+" { background-color: "+this._colors.cursor.css+"; color: "+this._colors.cursorAccent.css+";}"+this._terminalSelector+" ."+p+" ."+a.CURSOR_CLASS+"."+a.CURSOR_STYLE_BAR_CLASS+" { box-shadow: "+this._optionsService.options.cursorWidth+"px 0 0 "+this._colors.cursor.css+" inset;}"+this._terminalSelector+" ."+p+" ."+a.CURSOR_CLASS+"."+a.CURSOR_STYLE_UNDERLINE_CLASS+" { box-shadow: 0 -1px 0 "+this._colors.cursor.css+" inset;}",t+=this._terminalSelector+" ."+v+" { position: absolute; top: 0; left: 0; z-index: 1; pointer-events: none;}"+this._terminalSelector+" ."+v+" div { position: absolute; background-color: "+this._colors.selection.css+";}",this._colors.ansi.forEach(function(r,i){t+=e._terminalSelector+" .xterm-fg-"+i+" { color: "+r.css+"; }"+e._terminalSelector+" .xterm-bg-"+i+" { background-color: "+r.css+"; }"}),t+=this._terminalSelector+" .xterm-fg-"+c.INVERTED_DEFAULT_COLOR+" { color: "+_.color.opaque(this._colors.background).css+"; }"+this._terminalSelector+" .xterm-bg-"+c.INVERTED_DEFAULT_COLOR+" { background-color: "+this._colors.foreground.css+"; }",this._themeStyleElement.innerHTML=t},t.prototype.onDevicePixelRatioChange=function(){this._updateDimensions()},t.prototype._refreshRowElements=function(e,t){for(var r=this._rowElements.length;r<=t;r++){var i=document.createElement("div");this._rowContainer.appendChild(i),this._rowElements.push(i)}for(;this._rowElements.length>t;)this._rowContainer.removeChild(this._rowElements.pop())},t.prototype.onResize=function(e,t){this._refreshRowElements(e,t),this._updateDimensions()},t.prototype.onCharSizeChanged=function(){this._updateDimensions()},t.prototype.onBlur=function(){this._rowContainer.classList.remove("xterm-focus")},t.prototype.onFocus=function(){this._rowContainer.classList.add("xterm-focus")},t.prototype.onSelectionChanged=function(e,t,r){for(;this._selectionContainer.children.length;)this._selectionContainer.removeChild(this._selectionContainer.children[0]);if(e&&t){var i=e[1]-this._bufferService.buffer.ydisp,n=t[1]-this._bufferService.buffer.ydisp,o=Math.max(i,0),s=Math.min(n,this._bufferService.rows-1);if(!(o>=this._bufferService.rows||s<0)){var a=document.createDocumentFragment();if(r)a.appendChild(this._createSelectionElement(o,e[0],t[0],s-o+1));else{var c=i===o?e[0]:0,l=o===s?t[0]:this._bufferService.cols;a.appendChild(this._createSelectionElement(o,c,l));var h=s-o-1;if(a.appendChild(this._createSelectionElement(o+1,0,this._bufferService.cols,h)),o!==s){var u=n===s?t[0]:this._bufferService.cols;a.appendChild(this._createSelectionElement(s,0,u))}}this._selectionContainer.appendChild(a)}}},t.prototype._createSelectionElement=function(e,t,r,i){void 0===i&&(i=1);var n=document.createElement("div");return n.style.height=i*this.dimensions.actualCellHeight+"px",n.style.top=e*this.dimensions.actualCellHeight+"px",n.style.left=t*this.dimensions.actualCellWidth+"px",n.style.width=this.dimensions.actualCellWidth*(r-t)+"px",n},t.prototype.onCursorMove=function(){},t.prototype.onOptionsChanged=function(){this._updateDimensions(),this._injectCss()},t.prototype.clear=function(){this._rowElements.forEach(function(e){return e.innerHTML=""})},t.prototype.renderRows=function(e,t){for(var r=this._bufferService.buffer.ybase+this._bufferService.buffer.y,i=this._bufferService.buffer.x,n=this._optionsService.options.cursorBlink,o=e;o<=t;o++){var s=this._rowElements[o];s.innerHTML="";var a=o+this._bufferService.buffer.ydisp,c=this._bufferService.buffer.lines.get(a),l=this._optionsService.options.cursorStyle;s.appendChild(this._rowFactory.createRow(c,a===r,l,i,n,this.dimensions.actualCellWidth,this._bufferService.cols))}},Object.defineProperty(t.prototype,"_terminalSelector",{get:function(){return"."+d+this._terminalClass},enumerable:!0,configurable:!0}),t.prototype.registerCharacterJoiner=function(e){return-1},t.prototype.deregisterCharacterJoiner=function(e){return!1},t.prototype._onLinkHover=function(e){this._setCellUnderline(e.x1,e.x2,e.y1,e.y2,e.cols,!0)},t.prototype._onLinkLeave=function(e){this._setCellUnderline(e.x1,e.x2,e.y1,e.y2,e.cols,!1)},t.prototype._setCellUnderline=function(e,t,r,i,n,o){for(;e!==t||r!==i;){var s=this._rowElements[r];if(!s)return;var a=s.children[e];a&&(a.style.textDecoration=o?"underline":"none"),++e>=n&&(e=0,r++)}},t=o([s(5,h.ICharSizeService),s(6,u.IOptionsService),s(7,u.IBufferService)],t)}(l.Disposable);t.DomRenderer=y},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=r(9),n=r(3),o=r(5),s=r(10);t.BOLD_CLASS="xterm-bold",t.DIM_CLASS="xterm-dim",t.ITALIC_CLASS="xterm-italic",t.UNDERLINE_CLASS="xterm-underline",t.CURSOR_CLASS="xterm-cursor",t.CURSOR_BLINK_CLASS="xterm-cursor-blink",t.CURSOR_STYLE_BLOCK_CLASS="xterm-cursor-block",t.CURSOR_STYLE_BAR_CLASS="xterm-cursor-bar",t.CURSOR_STYLE_UNDERLINE_CLASS="xterm-cursor-underline";var a=function(){function e(e,t,r){this._document=e,this._optionsService=t,this._colors=r,this._workCell=new o.CellData}return e.prototype.setColors=function(e){this._colors=e},e.prototype.createRow=function(e,r,o,a,l,h,u){for(var f=this._document.createDocumentFragment(),_=0,d=Math.min(e.length,u)-1;d>=0;d--)if(e.loadCell(d,this._workCell).getCode()!==n.NULL_CELL_CODE||r&&d===a){_=d+1;break}for(d=0;d<_;d++){e.loadCell(d,this._workCell);var p=this._workCell.getWidth();if(0!==p){var v=this._document.createElement("span");if(p>1&&(v.style.width=h*p+"px"),r&&d===a)switch(v.classList.add(t.CURSOR_CLASS),l&&v.classList.add(t.CURSOR_BLINK_CLASS),o){case"bar":v.classList.add(t.CURSOR_STYLE_BAR_CLASS);break;case"underline":v.classList.add(t.CURSOR_STYLE_UNDERLINE_CLASS);break;default:v.classList.add(t.CURSOR_STYLE_BLOCK_CLASS)}this._workCell.isBold()&&v.classList.add(t.BOLD_CLASS),this._workCell.isItalic()&&v.classList.add(t.ITALIC_CLASS),this._workCell.isDim()&&v.classList.add(t.DIM_CLASS),this._workCell.isUnderline()&&v.classList.add(t.UNDERLINE_CLASS),this._workCell.isInvisible()?v.textContent=n.WHITESPACE_CELL_CHAR:v.textContent=this._workCell.getChars()||n.WHITESPACE_CELL_CHAR;var g=this._workCell.getFgColor(),y=this._workCell.getFgColorMode(),b=this._workCell.getBgColor(),m=this._workCell.getBgColorMode(),S=!!this._workCell.isInverse();if(S){var C=g;g=b,b=C;var w=y;y=m,m=w}switch(y){case 16777216:case 33554432:this._workCell.isBold()&&g<8&&this._optionsService.options.drawBoldTextInBrightColors&&(g+=8),this._applyMinimumContrast(v,this._colors.background,this._colors.ansi[g])||v.classList.add("xterm-fg-"+g);break;case 50331648:var E=s.rgba.toColor(g>>16&255,g>>8&255,255&g);this._applyMinimumContrast(v,this._colors.background,E)||this._addStyle(v,"color:#"+c(g.toString(16),"0",6));break;case 0:default:this._applyMinimumContrast(v,this._colors.background,this._colors.foreground)||S&&v.classList.add("xterm-fg-"+i.INVERTED_DEFAULT_COLOR)}switch(m){case 16777216:case 33554432:v.classList.add("xterm-bg-"+b);break;case 50331648:this._addStyle(v,"background-color:#"+c(b.toString(16),"0",6));break;case 0:default:S&&v.classList.add("xterm-bg-"+i.INVERTED_DEFAULT_COLOR)}f.appendChild(v)}}return f},e.prototype._applyMinimumContrast=function(e,t,r){if(1===this._optionsService.options.minimumContrastRatio)return!1;var i=this._colors.contrastCache.getColor(this._workCell.bg,this._workCell.fg);return void 0===i&&(i=s.color.ensureContrastRatio(t,r,this._optionsService.options.minimumContrastRatio),this._colors.contrastCache.setColor(this._workCell.bg,this._workCell.fg,null!=i?i:null)),!!i&&(this._addStyle(e,"color:"+i.css),!0)},e.prototype._addStyle=function(e,t){e.setAttribute("style",""+(e.getAttribute("style")||"")+t+";")},e}();function c(e,t,r){for(;e.length"],191:["/","?"],192:["`","~"],219:["[","{"],220:["\\","|"],221:["]","}"],222:["'",'"']};t.evaluateKeyboardEvent=function(e,t,r,o){var s={type:0,cancel:!1,key:void 0},a=(e.shiftKey?1:0)|(e.altKey?2:0)|(e.ctrlKey?4:0)|(e.metaKey?8:0);switch(e.keyCode){case 0:"UIKeyInputUpArrow"===e.key?s.key=t?i.C0.ESC+"OA":i.C0.ESC+"[A":"UIKeyInputLeftArrow"===e.key?s.key=t?i.C0.ESC+"OD":i.C0.ESC+"[D":"UIKeyInputRightArrow"===e.key?s.key=t?i.C0.ESC+"OC":i.C0.ESC+"[C":"UIKeyInputDownArrow"===e.key&&(s.key=t?i.C0.ESC+"OB":i.C0.ESC+"[B");break;case 8:if(e.shiftKey){s.key=i.C0.BS;break}if(e.altKey){s.key=i.C0.ESC+i.C0.DEL;break}s.key=i.C0.DEL;break;case 9:if(e.shiftKey){s.key=i.C0.ESC+"[Z";break}s.key=i.C0.HT,s.cancel=!0;break;case 13:s.key=i.C0.CR,s.cancel=!0;break;case 27:s.key=i.C0.ESC,s.cancel=!0;break;case 37:if(e.metaKey)break;a?(s.key=i.C0.ESC+"[1;"+(a+1)+"D",s.key===i.C0.ESC+"[1;3D"&&(s.key=i.C0.ESC+(r?"b":"[1;5D"))):s.key=t?i.C0.ESC+"OD":i.C0.ESC+"[D";break;case 39:if(e.metaKey)break;a?(s.key=i.C0.ESC+"[1;"+(a+1)+"C",s.key===i.C0.ESC+"[1;3C"&&(s.key=i.C0.ESC+(r?"f":"[1;5C"))):s.key=t?i.C0.ESC+"OC":i.C0.ESC+"[C";break;case 38:if(e.metaKey)break;a?(s.key=i.C0.ESC+"[1;"+(a+1)+"A",r||s.key!==i.C0.ESC+"[1;3A"||(s.key=i.C0.ESC+"[1;5A")):s.key=t?i.C0.ESC+"OA":i.C0.ESC+"[A";break;case 40:if(e.metaKey)break;a?(s.key=i.C0.ESC+"[1;"+(a+1)+"B",r||s.key!==i.C0.ESC+"[1;3B"||(s.key=i.C0.ESC+"[1;5B")):s.key=t?i.C0.ESC+"OB":i.C0.ESC+"[B";break;case 45:e.shiftKey||e.ctrlKey||(s.key=i.C0.ESC+"[2~");break;case 46:s.key=a?i.C0.ESC+"[3;"+(a+1)+"~":i.C0.ESC+"[3~";break;case 36:s.key=a?i.C0.ESC+"[1;"+(a+1)+"H":t?i.C0.ESC+"OH":i.C0.ESC+"[H";break;case 35:s.key=a?i.C0.ESC+"[1;"+(a+1)+"F":t?i.C0.ESC+"OF":i.C0.ESC+"[F";break;case 33:e.shiftKey?s.type=2:s.key=i.C0.ESC+"[5~";break;case 34:e.shiftKey?s.type=3:s.key=i.C0.ESC+"[6~";break;case 112:s.key=a?i.C0.ESC+"[1;"+(a+1)+"P":i.C0.ESC+"OP";break;case 113:s.key=a?i.C0.ESC+"[1;"+(a+1)+"Q":i.C0.ESC+"OQ";break;case 114:s.key=a?i.C0.ESC+"[1;"+(a+1)+"R":i.C0.ESC+"OR";break;case 115:s.key=a?i.C0.ESC+"[1;"+(a+1)+"S":i.C0.ESC+"OS";break;case 116:s.key=a?i.C0.ESC+"[15;"+(a+1)+"~":i.C0.ESC+"[15~";break;case 117:s.key=a?i.C0.ESC+"[17;"+(a+1)+"~":i.C0.ESC+"[17~";break;case 118:s.key=a?i.C0.ESC+"[18;"+(a+1)+"~":i.C0.ESC+"[18~";break;case 119:s.key=a?i.C0.ESC+"[19;"+(a+1)+"~":i.C0.ESC+"[19~";break;case 120:s.key=a?i.C0.ESC+"[20;"+(a+1)+"~":i.C0.ESC+"[20~";break;case 121:s.key=a?i.C0.ESC+"[21;"+(a+1)+"~":i.C0.ESC+"[21~";break;case 122:s.key=a?i.C0.ESC+"[23;"+(a+1)+"~":i.C0.ESC+"[23~";break;case 123:s.key=a?i.C0.ESC+"[24;"+(a+1)+"~":i.C0.ESC+"[24~";break;default:if(!e.ctrlKey||e.shiftKey||e.altKey||e.metaKey)if(r&&!o||!e.altKey||e.metaKey)r&&!e.altKey&&!e.ctrlKey&&e.metaKey?65===e.keyCode&&(s.type=1):e.key&&!e.ctrlKey&&!e.altKey&&!e.metaKey&&e.keyCode>=48&&1===e.key.length?s.key=e.key:e.key&&e.ctrlKey&&"_"===e.key&&(s.key=i.C0.US);else{var c=n[e.keyCode],l=c&&c[e.shiftKey?1:0];if(l)s.key=i.C0.ESC+l;else if(e.keyCode>=65&&e.keyCode<=90){var h=e.ctrlKey?e.keyCode-64:e.keyCode+32;s.key=i.C0.ESC+String.fromCharCode(h)}}else e.keyCode>=65&&e.keyCode<=90?s.key=String.fromCharCode(e.keyCode-64):32===e.keyCode?s.key=i.C0.NUL:e.keyCode>=51&&e.keyCode<=55?s.key=String.fromCharCode(e.keyCode-51+27):56===e.keyCode?s.key=i.C0.DEL:219===e.keyCode?s.key=i.C0.ESC:220===e.keyCode?s.key=i.C0.FS:221===e.keyCode&&(s.key=i.C0.GS)}return s}},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=r(3);t.updateWindowsModeWrappedState=function(e){var t,r=null===(t=e.buffer.lines.get(e.buffer.ybase+e.buffer.y-1))||void 0===t?void 0:t.get(e.cols-1),n=e.buffer.lines.get(e.buffer.ybase+e.buffer.y);n&&r&&(n.isWrapped=r[i.CHAR_DATA_CODE_INDEX]!==i.NULL_CELL_CODE&&r[i.CHAR_DATA_CODE_INDEX]!==i.WHITESPACE_CELL_CODE)}},function(e,t,r){"use strict";var i,n=this&&this.__extends||(i=function(e,t){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])})(e,t)},function(e,t){function r(){this.constructor=e}i(e,t),e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)}),o=this&&this.__decorate||function(e,t,r,i){var n,o=arguments.length,s=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,r,i);else for(var a=e.length-1;a>=0;a--)(n=e[a])&&(s=(o<3?n(s):o>3?n(t,r,s):n(t,r))||s);return o>3&&s&&Object.defineProperty(t,r,s),s},s=this&&this.__param||function(e,t){return function(r,i){t(r,i,e)}};Object.defineProperty(t,"__esModule",{value:!0});var a=r(29),c=r(1),l=r(2),h=r(30),u=r(8),f=r(0),_=r(4),d=function(e){function t(t,r,i,n,o){var s=e.call(this)||this;if(s._renderer=t,s._rowCount=r,s.screenElement=i,s.optionsService=n,s.charSizeService=o,s._isPaused=!1,s._needsFullRefresh=!1,s._canvasWidth=0,s._canvasHeight=0,s._onDimensionsChange=new c.EventEmitter,s._onRender=new c.EventEmitter,s._onRefreshRequest=new c.EventEmitter,s._renderDebouncer=new a.RenderDebouncer(function(e,t){return s._renderRows(e,t)}),s.register(s._renderDebouncer),s._screenDprMonitor=new h.ScreenDprMonitor,s._screenDprMonitor.setListener(function(){return s.onDevicePixelRatioChange()}),s.register(s._screenDprMonitor),s.register(n.onOptionChange(function(){return s._renderer.onOptionsChanged()})),s.register(o.onCharSizeChange(function(){return s.onCharSizeChanged()})),s._renderer.onRequestRefreshRows(function(e){return s.refreshRows(e.start,e.end)}),s.register(u.addDisposableDomListener(window,"resize",function(){return s.onDevicePixelRatioChange()})),"IntersectionObserver"in window){var l=new IntersectionObserver(function(e){return s._onIntersectionChange(e[e.length-1])},{threshold:0});l.observe(i),s.register({dispose:function(){return l.disconnect()}})}return s}return n(t,e),Object.defineProperty(t.prototype,"onDimensionsChange",{get:function(){return this._onDimensionsChange.event},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"onRender",{get:function(){return this._onRender.event},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"onRefreshRequest",{get:function(){return this._onRefreshRequest.event},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"dimensions",{get:function(){return this._renderer.dimensions},enumerable:!0,configurable:!0}),t.prototype._onIntersectionChange=function(e){this._isPaused=0===e.intersectionRatio,!this._isPaused&&this._needsFullRefresh&&(this.refreshRows(0,this._rowCount-1),this._needsFullRefresh=!1)},t.prototype.refreshRows=function(e,t){this._isPaused?this._needsFullRefresh=!0:this._renderDebouncer.refresh(e,t,this._rowCount)},t.prototype._renderRows=function(e,t){this._renderer.renderRows(e,t),this._onRender.fire({start:e,end:t})},t.prototype.resize=function(e,t){this._rowCount=t,this._fireOnCanvasResize()},t.prototype.changeOptions=function(){this._renderer.onOptionsChanged(),this.refreshRows(0,this._rowCount-1),this._fireOnCanvasResize()},t.prototype._fireOnCanvasResize=function(){this._renderer.dimensions.canvasWidth===this._canvasWidth&&this._renderer.dimensions.canvasHeight===this._canvasHeight||this._onDimensionsChange.fire(this._renderer.dimensions)},t.prototype.dispose=function(){this._renderer.dispose(),e.prototype.dispose.call(this)},t.prototype.setRenderer=function(e){var t=this;this._renderer.dispose(),this._renderer=e,this._renderer.onRequestRefreshRows(function(e){return t.refreshRows(e.start,e.end)}),this.refreshRows(0,this._rowCount-1)},t.prototype._fullRefresh=function(){this._isPaused?this._needsFullRefresh=!0:this.refreshRows(0,this._rowCount-1)},t.prototype.setColors=function(e){this._renderer.setColors(e),this._fullRefresh()},t.prototype.onDevicePixelRatioChange=function(){this._renderer.onDevicePixelRatioChange(),this.refreshRows(0,this._rowCount-1)},t.prototype.onResize=function(e,t){this._renderer.onResize(e,t),this._fullRefresh()},t.prototype.onCharSizeChanged=function(){this._renderer.onCharSizeChanged()},t.prototype.onBlur=function(){this._renderer.onBlur()},t.prototype.onFocus=function(){this._renderer.onFocus()},t.prototype.onSelectionChanged=function(e,t,r){this._renderer.onSelectionChanged(e,t,r)},t.prototype.onCursorMove=function(){this._renderer.onCursorMove()},t.prototype.clear=function(){this._renderer.clear()},t.prototype.registerCharacterJoiner=function(e){return this._renderer.registerCharacterJoiner(e)},t.prototype.deregisterCharacterJoiner=function(e){return this._renderer.deregisterCharacterJoiner(e)},t=o([s(3,f.IOptionsService),s(4,_.ICharSizeService)],t)}(l.Disposable);t.RenderService=d},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=r(1),n=r(11),o=r(31);t.DEFAULT_BELL_SOUND="data:audio/mp3;base64,SUQzBAAAAAAAI1RTU0UAAAAPAAADTGF2ZjU4LjMyLjEwNAAAAAAAAAAAAAAA//tQxAADB8AhSmxhIIEVCSiJrDCQBTcu3UrAIwUdkRgQbFAZC1CQEwTJ9mjRvBA4UOLD8nKVOWfh+UlK3z/177OXrfOdKl7pyn3Xf//WreyTRUoAWgBgkOAGbZHBgG1OF6zM82DWbZaUmMBptgQhGjsyYqc9ae9XFz280948NMBWInljyzsNRFLPWdnZGWrddDsjK1unuSrVN9jJsK8KuQtQCtMBjCEtImISdNKJOopIpBFpNSMbIHCSRpRR5iakjTiyzLhchUUBwCgyKiweBv/7UsQbg8isVNoMPMjAAAA0gAAABEVFGmgqK////9bP/6XCykxBTUUzLjEwMKqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq",t.DEFAULT_OPTIONS=Object.freeze({cols:80,rows:24,cursorBlink:!1,cursorStyle:"block",cursorWidth:1,bellSound:t.DEFAULT_BELL_SOUND,bellStyle:"none",drawBoldTextInBrightColors:!0,fastScrollModifier:"alt",fastScrollSensitivity:5,fontFamily:"courier-new, courier, monospace",fontSize:15,fontWeight:"normal",fontWeightBold:"bold",lineHeight:1,letterSpacing:0,logLevel:"info",scrollback:1e3,scrollSensitivity:1,screenReaderMode:!1,macOptionIsMeta:!1,macOptionClickForcesSelection:!1,minimumContrastRatio:1,disableStdin:!1,allowTransparency:!1,tabStopWidth:8,theme:{},rightClickSelectsWord:n.isMac,rendererType:"canvas",windowOptions:{},windowsMode:!1,wordSeparator:" ()[]{}',\"`",convertEol:!1,termName:"xterm",cancelEvents:!1});var s=["cols","rows"],a=function(){function e(e){var r=this;this._onOptionChange=new i.EventEmitter,this.options=o.clone(t.DEFAULT_OPTIONS),Object.keys(e).forEach(function(t){if(t in r.options){var i=e[t];r.options[t]=i}})}return Object.defineProperty(e.prototype,"onOptionChange",{get:function(){return this._onOptionChange.event},enumerable:!0,configurable:!0}),e.prototype.setOption=function(e,r){if(!(e in t.DEFAULT_OPTIONS))throw new Error('No option with key "'+e+'"');if(-1!==s.indexOf(e))throw new Error('Option "'+e+'" can only be set in the constructor');this.options[e]!==r&&(r=this._sanitizeAndValidateOption(e,r),this.options[e]!==r&&(this.options[e]=r,this._onOptionChange.fire(e)))},e.prototype._sanitizeAndValidateOption=function(e,r){switch(e){case"bellStyle":case"cursorStyle":case"fontWeight":case"fontWeightBold":case"rendererType":case"wordSeparator":r||(r=t.DEFAULT_OPTIONS[e]);break;case"cursorWidth":r=Math.floor(r);case"lineHeight":case"tabStopWidth":if(r<1)throw new Error(e+" cannot be less than 1, value: "+r);break;case"minimumContrastRatio":r=Math.max(1,Math.min(21,Math.round(10*r)/10));break;case"scrollback":if((r=Math.min(r,4294967295))<0)throw new Error(e+" cannot be less than 0, value: "+r);break;case"fastScrollSensitivity":case"scrollSensitivity":if(r<=0)throw new Error(e+" cannot be less than or equal to 0, value: "+r)}return r},e.prototype.getOption=function(e){if(!(e in t.DEFAULT_OPTIONS))throw new Error('No option with key "'+e+'"');return this.options[e]},e}();t.OptionsService=a},function(e,t,r){"use strict";var i=this&&this.__decorate||function(e,t,r,i){var n,o=arguments.length,s=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,r,i);else for(var a=e.length-1;a>=0;a--)(n=e[a])&&(s=(o<3?n(s):o>3?n(t,r,s):n(t,r))||s);return o>3&&s&&Object.defineProperty(t,r,s),s},n=this&&this.__param||function(e,t){return function(r,i){t(r,i,e)}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(0),s=r(1),a=function(){function e(e,t,r){this.document=e,this.parentElement=t,this._optionsService=r,this.width=0,this.height=0,this._onCharSizeChange=new s.EventEmitter,this._measureStrategy=new c(e,t,this._optionsService)}return Object.defineProperty(e.prototype,"hasValidSize",{get:function(){return this.width>0&&this.height>0},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"onCharSizeChange",{get:function(){return this._onCharSizeChange.event},enumerable:!0,configurable:!0}),e.prototype.measure=function(){var e=this._measureStrategy.measure();e.width===this.width&&e.height===this.height||(this.width=e.width,this.height=e.height,this._onCharSizeChange.fire())},e=i([n(2,o.IOptionsService)],e)}();t.CharSizeService=a;var c=function(){function e(e,t,r){this._document=e,this._parentElement=t,this._optionsService=r,this._result={width:0,height:0},this._measureElement=this._document.createElement("span"),this._measureElement.classList.add("xterm-char-measure-element"),this._measureElement.textContent="W",this._measureElement.setAttribute("aria-hidden","true"),this._parentElement.appendChild(this._measureElement)}return e.prototype.measure=function(){this._measureElement.style.fontFamily=this._optionsService.options.fontFamily,this._measureElement.style.fontSize=this._optionsService.options.fontSize+"px";var e=this._measureElement.getBoundingClientRect();return 0!==e.width&&0!==e.height&&(this._result.width=e.width,this._result.height=Math.ceil(e.height)),this._result},e}()},function(e,t,r){"use strict";var i=this&&this.__decorate||function(e,t,r,i){var n,o=arguments.length,s=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,r,i);else for(var a=e.length-1;a>=0;a--)(n=e[a])&&(s=(o<3?n(s):o>3?n(t,r,s):n(t,r))||s);return o>3&&s&&Object.defineProperty(t,r,s),s},n=this&&this.__param||function(e,t){return function(r,i){t(r,i,e)}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(0),s=r(64);t.MINIMUM_COLS=2,t.MINIMUM_ROWS=1;var a=function(){function e(e){this._optionsService=e,this.cols=Math.max(e.options.cols,t.MINIMUM_COLS),this.rows=Math.max(e.options.rows,t.MINIMUM_ROWS),this.buffers=new s.BufferSet(e,this)}return Object.defineProperty(e.prototype,"buffer",{get:function(){return this.buffers.active},enumerable:!0,configurable:!0}),e.prototype.resize=function(e,t){this.cols=e,this.rows=t},e.prototype.reset=function(){this.buffers=new s.BufferSet(this._optionsService,this)},e=i([n(0,o.IOptionsService)],e)}();t.BufferService=a},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=r(65),n=r(1),o=function(){function e(e,t){this.optionsService=e,this.bufferService=t,this._onBufferActivate=new n.EventEmitter,this._normal=new i.Buffer(!0,e,t),this._normal.fillViewportRows(),this._alt=new i.Buffer(!1,e,t),this._activeBuffer=this._normal,this.setupTabStops()}return Object.defineProperty(e.prototype,"onBufferActivate",{get:function(){return this._onBufferActivate.event},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"alt",{get:function(){return this._alt},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"active",{get:function(){return this._activeBuffer},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"normal",{get:function(){return this._normal},enumerable:!0,configurable:!0}),e.prototype.activateNormalBuffer=function(){this._activeBuffer!==this._normal&&(this._normal.x=this._alt.x,this._normal.y=this._alt.y,this._alt.clear(),this._activeBuffer=this._normal,this._onBufferActivate.fire({activeBuffer:this._normal,inactiveBuffer:this._alt}))},e.prototype.activateAltBuffer=function(e){this._activeBuffer!==this._alt&&(this._alt.fillViewportRows(e),this._alt.x=this._normal.x,this._alt.y=this._normal.y,this._activeBuffer=this._alt,this._onBufferActivate.fire({activeBuffer:this._alt,inactiveBuffer:this._normal}))},e.prototype.resize=function(e,t){this._normal.resize(e,t),this._alt.resize(e,t)},e.prototype.setupTabStops=function(e){this._normal.setupTabStops(e),this._alt.setupTabStops(e)},e}();t.BufferSet=o},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=r(66),n=r(16),o=r(5),s=r(3),a=r(67),c=r(68),l=r(18);t.MAX_BUFFER_SIZE=4294967295;var h=function(){function e(e,t,r){this._hasScrollback=e,this._optionsService=t,this._bufferService=r,this.ydisp=0,this.ybase=0,this.y=0,this.x=0,this.savedY=0,this.savedX=0,this.savedCurAttrData=n.DEFAULT_ATTR_DATA.clone(),this.savedCharset=l.DEFAULT_CHARSET,this.markers=[],this._nullCell=o.CellData.fromCharData([0,s.NULL_CELL_CHAR,s.NULL_CELL_WIDTH,s.NULL_CELL_CODE]),this._whitespaceCell=o.CellData.fromCharData([0,s.WHITESPACE_CELL_CHAR,s.WHITESPACE_CELL_WIDTH,s.WHITESPACE_CELL_CODE]),this._cols=this._bufferService.cols,this._rows=this._bufferService.rows,this.lines=new i.CircularList(this._getCorrectBufferLength(this._rows)),this.scrollTop=0,this.scrollBottom=this._rows-1,this.setupTabStops()}return e.prototype.getNullCell=function(e){return e?(this._nullCell.fg=e.fg,this._nullCell.bg=e.bg):(this._nullCell.fg=0,this._nullCell.bg=0),this._nullCell},e.prototype.getWhitespaceCell=function(e){return e?(this._whitespaceCell.fg=e.fg,this._whitespaceCell.bg=e.bg):(this._whitespaceCell.fg=0,this._whitespaceCell.bg=0),this._whitespaceCell},e.prototype.getBlankLine=function(e,t){return new n.BufferLine(this._bufferService.cols,this.getNullCell(e),t)},Object.defineProperty(e.prototype,"hasScrollback",{get:function(){return this._hasScrollback&&this.lines.maxLength>this._rows},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"isCursorInViewport",{get:function(){var e=this.ybase+this.y-this.ydisp;return e>=0&&et.MAX_BUFFER_SIZE?t.MAX_BUFFER_SIZE:r},e.prototype.fillViewportRows=function(e){if(0===this.lines.length){void 0===e&&(e=n.DEFAULT_ATTR_DATA);for(var t=this._rows;t--;)this.lines.push(this.getBlankLine(e))}},e.prototype.clear=function(){this.ydisp=0,this.ybase=0,this.y=0,this.x=0,this.lines=new i.CircularList(this._getCorrectBufferLength(this._rows)),this.scrollTop=0,this.scrollBottom=this._rows-1,this.setupTabStops()},e.prototype.resize=function(e,t){var r=this.getNullCell(n.DEFAULT_ATTR_DATA),i=this._getCorrectBufferLength(t);if(i>this.lines.maxLength&&(this.lines.maxLength=i),this.lines.length>0){if(this._cols0&&this.lines.length<=this.ybase+this.y+s+1?(this.ybase--,s++,this.ydisp>0&&this.ydisp--):this.lines.push(new n.BufferLine(e,r)));else for(a=this._rows;a>t;a--)this.lines.length>t+this.ybase&&(this.lines.length>this.ybase+this.y+1?this.lines.pop():(this.ybase++,this.ydisp++));if(i0&&(this.lines.trimStart(c),this.ybase=Math.max(this.ybase-c,0),this.ydisp=Math.max(this.ydisp-c,0),this.savedY=Math.max(this.savedY-c,0)),this.lines.maxLength=i}this.x=Math.min(this.x,e-1),this.y=Math.min(this.y,t-1),s&&(this.y+=s),this.savedX=Math.min(this.savedX,e-1),this.scrollTop=0}if(this.scrollBottom=t-1,this._isReflowEnabled&&(this._reflow(e,t),this._cols>e))for(o=0;othis._cols?this._reflowLarger(e,t):this._reflowSmaller(e,t))},e.prototype._reflowLarger=function(e,t){var r=a.reflowLargerGetLinesToRemove(this.lines,this._cols,e,this.ybase+this.y,this.getNullCell(n.DEFAULT_ATTR_DATA));if(r.length>0){var i=a.reflowLargerCreateNewLayout(this.lines,r);a.reflowLargerApplyNewLayout(this.lines,i.layout),this._reflowLargerAdjustViewport(e,t,i.countRemoved)}},e.prototype._reflowLargerAdjustViewport=function(e,t,r){for(var i=this.getNullCell(n.DEFAULT_ATTR_DATA),o=r;o-- >0;)0===this.ybase?(this.y>0&&this.y--,this.lines.length=0;s--){var c=this.lines.get(s);if(!(!c||!c.isWrapped&&c.getTrimmedLength()<=e)){for(var l=[c];c.isWrapped&&s>0;)c=this.lines.get(--s),l.unshift(c);var h=this.ybase+this.y;if(!(h>=s&&h0&&(i.push({start:s+l.length+o,newLines:p}),o+=p.length),l.push.apply(l,p);var y=f.length-1,b=f[y];0===b&&(b=f[--y]);for(var m=l.length-_-1,S=u;m>=0;){var C=Math.min(S,b);if(l[y].copyCellsFrom(l[m],S-C,b-C,C,!0),0===(b-=C)&&(b=f[--y]),0===(S-=C)){m--;var w=Math.max(m,0);S=a.getWrappedLineTrimmedLength(l,w,this._cols)}}for(v=0;v0;)0===this.ybase?this.y0){var L=[],A=[];for(v=0;v=0;v--)if(D&&D.start>x+T){for(var O=D.newLines.length-1;O>=0;O--)this.lines.set(v--,D.newLines[O]);v++,L.push({index:x+1,amount:D.newLines.length}),T+=D.newLines.length,D=i[++k]}else this.lines.set(v,A[x--]);var M=0;for(v=L.length-1;v>=0;v--)L[v].index+=M,this.lines.onInsertEmitter.fire(L[v]),M+=L[v].amount;var P=Math.max(0,R+o-this.lines.maxLength);P>0&&this.lines.onTrimEmitter.fire(P)}},e.prototype.stringIndexToBufferIndex=function(e,t,r){for(void 0===r&&(r=!1);t;){var i=this.lines.get(e);if(!i)return[-1,-1];for(var n=r?i.getTrimmedLength():i.length,o=0;o0&&this.lines.get(t).isWrapped;)t--;for(;r+10;);return e>=this._cols?this._cols-1:e<0?0:e},e.prototype.nextStop=function(e){for(null==e&&(e=this.x);!this.tabs[++e]&&e=this._cols?this._cols-1:e<0?0:e},e.prototype.addMarker=function(e){var t=this,r=new c.Marker(e);return this.markers.push(r),r.register(this.lines.onTrim(function(e){r.line-=e,r.line<0&&r.dispose()})),r.register(this.lines.onInsert(function(e){r.line>=e.index&&(r.line+=e.amount)})),r.register(this.lines.onDelete(function(e){r.line>=e.index&&r.linee.index&&(r.line-=e.amount)})),r.register(r.onDispose(function(){return t._removeMarker(r)})),r},e.prototype._removeMarker=function(e){this.markers.splice(this.markers.indexOf(e),1)},e.prototype.iterator=function(e,t,r,i,n){return new u(this,e,t,r,i,n)},e}();t.Buffer=h;var u=function(){function e(e,t,r,i,n,o){void 0===r&&(r=0),void 0===i&&(i=e.lines.length),void 0===n&&(n=0),void 0===o&&(o=0),this._buffer=e,this._trimRight=t,this._startIndex=r,this._endIndex=i,this._startOverscan=n,this._endOverscan=o,this._startIndex<0&&(this._startIndex=0),this._endIndex>this._buffer.lines.length&&(this._endIndex=this._buffer.lines.length),this._current=this._startIndex}return e.prototype.hasNext=function(){return this._currentthis._endIndex+this._endOverscan&&(e.last=this._endIndex+this._endOverscan),e.first=Math.max(e.first,0),e.last=Math.min(e.last,this._buffer.lines.length);for(var t="",r=e.first;r<=e.last;++r)t+=this._buffer.translateBufferLineToString(r,this._trimRight);return this._current=e.last+1,{range:e,content:t}},e}();t.BufferStringIterator=u},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=r(1),n=function(){function e(e){this._maxLength=e,this.onDeleteEmitter=new i.EventEmitter,this.onInsertEmitter=new i.EventEmitter,this.onTrimEmitter=new i.EventEmitter,this._array=new Array(this._maxLength),this._startIndex=0,this._length=0}return Object.defineProperty(e.prototype,"onDelete",{get:function(){return this.onDeleteEmitter.event},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"onInsert",{get:function(){return this.onInsertEmitter.event},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"onTrim",{get:function(){return this.onTrimEmitter.event},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"maxLength",{get:function(){return this._maxLength},set:function(e){if(this._maxLength!==e){for(var t=new Array(e),r=0;rthis._length)for(var t=this._length;t=e;n--)this._array[this._getCyclicIndex(n+r.length)]=this._array[this._getCyclicIndex(n)];for(n=0;nthis._maxLength){var o=this._length+r.length-this._maxLength;this._startIndex+=o,this._length=this._maxLength,this.onTrimEmitter.fire(o)}else this._length+=r.length},e.prototype.trimStart=function(e){e>this._length&&(e=this._length),this._startIndex+=e,this._length-=e,this.onTrimEmitter.fire(e)},e.prototype.shiftElements=function(e,t,r){if(!(t<=0)){if(e<0||e>=this._length)throw new Error("start argument out of range");if(e+r<0)throw new Error("Cannot shift elements in list beyond index 0");if(r>0){for(var i=t-1;i>=0;i--)this.set(e+i+r,this.get(e+i));var n=e+t+r-this._length;if(n>0)for(this._length+=n;this._length>this._maxLength;)this._length--,this._startIndex++,this.onTrimEmitter.fire(1)}else for(i=0;i=a&&n0&&(m>u||0===h[m].getTrimmedLength());m--)b++;b>0&&(s.push(a+h.length-b),s.push(b)),a+=h.length-1}}}return s},t.reflowLargerCreateNewLayout=function(e,t){for(var r=[],i=0,n=t[i],o=0,s=0;sl&&(s-=l,a++);var h=2===e[a].getWidth(s-1);h&&s--;var u=h?r-1:r;n.push(u),c+=u}return n},t.getWrappedLineTrimmedLength=i},function(e,t,r){"use strict";var i,n=this&&this.__extends||(i=function(e,t){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])})(e,t)},function(e,t){function r(){this.constructor=e}i(e,t),e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)});Object.defineProperty(t,"__esModule",{value:!0});var o=r(1),s=function(e){function t(r){var i=e.call(this)||this;return i.line=r,i._id=t._nextId++,i.isDisposed=!1,i._onDispose=new o.EventEmitter,i}return n(t,e),Object.defineProperty(t.prototype,"id",{get:function(){return this._id},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"onDispose",{get:function(){return this._onDispose.event},enumerable:!0,configurable:!0}),t.prototype.dispose=function(){this.isDisposed||(this.isDisposed=!0,this.line=-1,this._onDispose.fire())},t._nextId=1,t}(r(2).Disposable);t.Marker=s},function(e,t,r){"use strict";var i=this&&this.__decorate||function(e,t,r,i){var n,o=arguments.length,s=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,r,i);else for(var a=e.length-1;a>=0;a--)(n=e[a])&&(s=(o<3?n(s):o>3?n(t,r,s):n(t,r))||s);return o>3&&s&&Object.defineProperty(t,r,s),s},n=this&&this.__param||function(e,t){return function(r,i){t(r,i,e)}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(4),s=r(28),a=function(){function e(e,t){this._renderService=e,this._charSizeService=t}return e.prototype.getCoords=function(e,t,r,i,n){return s.getCoords(e,t,r,i,this._charSizeService.hasValidSize,this._renderService.dimensions.actualCellWidth,this._renderService.dimensions.actualCellHeight,n)},e.prototype.getRawByteCoords=function(e,t,r,i){var n=this.getCoords(e,t,r,i);return s.getRawByteCoords(n)},e=i([n(0,o.IRenderService),n(1,o.ICharSizeService)],e)}();t.MouseService=a},function(e,t,r){"use strict";var i=this&&this.__decorate||function(e,t,r,i){var n,o=arguments.length,s=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,r,i);else for(var a=e.length-1;a>=0;a--)(n=e[a])&&(s=(o<3?n(s):o>3?n(t,r,s):n(t,r))||s);return o>3&&s&&Object.defineProperty(t,r,s),s},n=this&&this.__param||function(e,t){return function(r,i){t(r,i,e)}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(0),s=r(1),a=r(31),c=Object.freeze({applicationCursorKeys:!1,applicationKeypad:!1,origin:!1,wraparound:!0}),l=function(){function e(e,t,r,i){this._scrollToBottom=e,this._bufferService=t,this._logService=r,this._optionsService=i,this.isCursorInitialized=!1,this.isCursorHidden=!1,this._onData=new s.EventEmitter,this._onUserInput=new s.EventEmitter,this._onBinary=new s.EventEmitter,this.decPrivateModes=a.clone(c)}return Object.defineProperty(e.prototype,"onData",{get:function(){return this._onData.event},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"onUserInput",{get:function(){return this._onUserInput.event},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"onBinary",{get:function(){return this._onBinary.event},enumerable:!0,configurable:!0}),e.prototype.reset=function(){this.decPrivateModes=a.clone(c)},e.prototype.triggerDataEvent=function(e,t){if(void 0===t&&(t=!1),!this._optionsService.options.disableStdin){var r=this._bufferService.buffer;r.ybase!==r.ydisp&&this._scrollToBottom(),t&&this._onUserInput.fire(),this._logService.debug('sending data "'+e+'"',function(){return e.split("").map(function(e){return e.charCodeAt(0)})}),this._onData.fire(e)}},e.prototype.triggerBinaryEvent=function(e){this._optionsService.options.disableStdin||(this._logService.debug('sending binary "'+e+'"',function(){return e.split("").map(function(e){return e.charCodeAt(0)})}),this._onBinary.fire(e))},e=i([n(1,o.IBufferService),n(2,o.ILogService),n(3,o.IOptionsService)],e)}();t.CoreService=l},function(e,t,r){"use strict";var i=this&&this.__decorate||function(e,t,r,i){var n,o=arguments.length,s=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,r,i);else for(var a=e.length-1;a>=0;a--)(n=e[a])&&(s=(o<3?n(s):o>3?n(t,r,s):n(t,r))||s);return o>3&&s&&Object.defineProperty(t,r,s),s},n=this&&this.__param||function(e,t){return function(r,i){t(r,i,e)}},o=this&&this.__spreadArrays||function(){for(var e=0,t=0,r=arguments.length;t=0;a--)(n=e[a])&&(s=(o<3?n(s):o>3?n(t,r,s):n(t,r))||s);return o>3&&s&&Object.defineProperty(t,r,s),s},n=this&&this.__param||function(e,t){return function(r,i){t(r,i,e)}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(0),s=function(){function e(e){this._bufferService=e,this.clearRange()}return Object.defineProperty(e.prototype,"start",{get:function(){return this._start},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"end",{get:function(){return this._end},enumerable:!0,configurable:!0}),e.prototype.clearRange=function(){this._start=this._bufferService.buffer.y,this._end=this._bufferService.buffer.y},e.prototype.markDirty=function(e){ethis._end&&(this._end=e)},e.prototype.markRangeDirty=function(e,t){if(e>t){var r=e;e=t,t=r}ethis._end&&(this._end=t)},e.prototype.markAllDirty=function(){this.markRangeDirty(0,this._bufferService.rows-1)},e=i([n(0,o.IBufferService)],e)}();t.DirtyRowService=s},function(e,t,r){"use strict";var i=this&&this.__spreadArrays||function(){for(var e=0,t=0,r=arguments.length;t0?n[0].index:t.length;if(t.length!==u)throw new Error("[createInstance] First service dependency of "+e.name+" at position "+(u+1)+" conflicts with "+t.length+" static arguments");return new(e.bind.apply(e,i([void 0],i(t,s))))},e}();t.InstantiationService=a},function(e,t,r){"use strict";var i=this&&this.__decorate||function(e,t,r,i){var n,o=arguments.length,s=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,r,i);else for(var a=e.length-1;a>=0;a--)(n=e[a])&&(s=(o<3?n(s):o>3?n(t,r,s):n(t,r))||s);return o>3&&s&&Object.defineProperty(t,r,s),s},n=this&&this.__param||function(e,t){return function(r,i){t(r,i,e)}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(0),s=r(1),a={NONE:{events:0,restrict:function(){return!1}},X10:{events:1,restrict:function(e){return 4!==e.button&&1===e.action&&(e.ctrl=!1,e.alt=!1,e.shift=!1,!0)}},VT200:{events:19,restrict:function(e){return 32!==e.action}},DRAG:{events:23,restrict:function(e){return 32!==e.action||3!==e.button}},ANY:{events:31,restrict:function(e){return!0}}};function c(e,t){var r=(e.ctrl?16:0)|(e.shift?4:0)|(e.alt?8:0);return 4===e.button?(r|=64,r|=e.action):(r|=3&e.button,4&e.button&&(r|=64),8&e.button&&(r|=128),32===e.action?r|=32:0!==e.action||t||(r|=3)),r}var l=String.fromCharCode,h={DEFAULT:function(e){var t=[c(e,!1)+32,e.col+32,e.row+32];return t[0]>255||t[1]>255||t[2]>255?"":""+l(t[0])+l(t[1])+l(t[2])},SGR:function(e){var t=0===e.action&&4!==e.button?"m":"M";return"[<"+c(e,!0)+";"+e.col+";"+e.row+t}},u=function(){function e(e,t){var r=this;this._bufferService=e,this._coreService=t,this._protocols={},this._encodings={},this._activeProtocol="",this._activeEncoding="",this._onProtocolChange=new s.EventEmitter,this._lastEvent=null,Object.keys(a).forEach(function(e){return r.addProtocol(e,a[e])}),Object.keys(h).forEach(function(e){return r.addEncoding(e,h[e])}),this.reset()}return e.prototype.addProtocol=function(e,t){this._protocols[e]=t},e.prototype.addEncoding=function(e,t){this._encodings[e]=t},Object.defineProperty(e.prototype,"activeProtocol",{get:function(){return this._activeProtocol},set:function(e){if(!this._protocols[e])throw new Error('unknown protocol "'+e+'"');this._activeProtocol=e,this._onProtocolChange.fire(this._protocols[e].events)},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"activeEncoding",{get:function(){return this._activeEncoding},set:function(e){if(!this._encodings[e])throw new Error('unknown encoding "'+e+'"');this._activeEncoding=e},enumerable:!0,configurable:!0}),e.prototype.reset=function(){this.activeProtocol="NONE",this.activeEncoding="DEFAULT",this._lastEvent=null},Object.defineProperty(e.prototype,"onProtocolChange",{get:function(){return this._onProtocolChange.event},enumerable:!0,configurable:!0}),e.prototype.triggerMouseEvent=function(e){if(e.col<0||e.col>=this._bufferService.cols||e.row<0||e.row>=this._bufferService.rows)return!1;if(4===e.button&&32===e.action)return!1;if(3===e.button&&32!==e.action)return!1;if(4!==e.button&&(2===e.action||3===e.action))return!1;if(e.col++,e.row++,32===e.action&&this._lastEvent&&this._compareEvents(this._lastEvent,e))return!1;if(!this._protocols[this._activeProtocol].restrict(e))return!1;var t=this._encodings[this._activeEncoding](e);return t&&("DEFAULT"===this._activeEncoding?this._coreService.triggerBinaryEvent(t):this._coreService.triggerDataEvent(t,!0)),this._lastEvent=e,!0},e.prototype.explainEvents=function(e){return{DOWN:!!(1&e),UP:!!(2&e),DRAG:!!(4&e),MOVE:!!(8&e),WHEEL:!!(16&e)}},e.prototype._compareEvents=function(e,t){return e.col===t.col&&(e.row===t.row&&(e.button===t.button&&(e.action===t.action&&(e.ctrl===t.ctrl&&(e.alt===t.alt&&e.shift===t.shift)))))},e=i([n(0,o.IBufferService),n(1,o.ICoreService)],e)}();t.CoreMouseService=u},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=function(){function e(e){this._action=e,this._writeBuffer=[],this._callbacks=[],this._pendingData=0,this._bufferOffset=0}return e.prototype.writeSync=function(e){if(this._writeBuffer.length){for(var t=this._bufferOffset;t5e7)throw new Error("write data discarded, use flow control to avoid losing data");this._writeBuffer.length||(this._bufferOffset=0,setTimeout(function(){return r._innerWrite()})),this._pendingData+=e.length,this._writeBuffer.push(e),this._callbacks.push(t)},e.prototype._innerWrite=function(){for(var e=this,t=Date.now();this._writeBuffer.length>this._bufferOffset;){var r=this._writeBuffer[this._bufferOffset],i=this._callbacks[this._bufferOffset];if(this._bufferOffset++,this._action(r),this._pendingData-=r.length,i&&i(),Date.now()-t>=12)break}this._writeBuffer.length>this._bufferOffset?(this._bufferOffset>50&&(this._writeBuffer=this._writeBuffer.slice(this._bufferOffset),this._callbacks=this._callbacks.slice(this._bufferOffset),this._bufferOffset=0),setTimeout(function(){return e._innerWrite()},0)):(this._writeBuffer=[],this._callbacks=[],this._pendingData=0,this._bufferOffset=0)},e}();t.WriteBuffer=i},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=function(){function e(e){this._textarea=e}return Object.defineProperty(e.prototype,"isFocused",{get:function(){return document.activeElement===this._textarea&&document.hasFocus()},enumerable:!0,configurable:!0}),e}();t.CoreBrowserService=i},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=r(1),n=r(78),o=function(){function e(){this._providers=Object.create(null),this._active="",this._onChange=new i.EventEmitter;var e=new n.UnicodeV6;this.register(e),this._active=e.version,this._activeProvider=e}return Object.defineProperty(e.prototype,"onChange",{get:function(){return this._onChange.event},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"versions",{get:function(){return Object.keys(this._providers)},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"activeVersion",{get:function(){return this._active},set:function(e){if(!this._providers[e])throw new Error('unknown Unicode version "'+e+'"');this._active=e,this._activeProvider=this._providers[e],this._onChange.fire(e)},enumerable:!0,configurable:!0}),e.prototype.register=function(e){this._providers[e.version]=e},e.prototype.wcwidth=function(e){return this._activeProvider.wcwidth(e)},e.prototype.getStringCellWidth=function(e){for(var t=0,r=e.length,i=0;i=r)return t+this.wcwidth(n);var o=e.charCodeAt(i);56320<=o&&o<=57343?n=1024*(n-55296)+o-56320+65536:t+=this.wcwidth(o)}t+=this.wcwidth(n)}return t},e}();t.UnicodeService=o},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i,n=r(15),o=[[768,879],[1155,1158],[1160,1161],[1425,1469],[1471,1471],[1473,1474],[1476,1477],[1479,1479],[1536,1539],[1552,1557],[1611,1630],[1648,1648],[1750,1764],[1767,1768],[1770,1773],[1807,1807],[1809,1809],[1840,1866],[1958,1968],[2027,2035],[2305,2306],[2364,2364],[2369,2376],[2381,2381],[2385,2388],[2402,2403],[2433,2433],[2492,2492],[2497,2500],[2509,2509],[2530,2531],[2561,2562],[2620,2620],[2625,2626],[2631,2632],[2635,2637],[2672,2673],[2689,2690],[2748,2748],[2753,2757],[2759,2760],[2765,2765],[2786,2787],[2817,2817],[2876,2876],[2879,2879],[2881,2883],[2893,2893],[2902,2902],[2946,2946],[3008,3008],[3021,3021],[3134,3136],[3142,3144],[3146,3149],[3157,3158],[3260,3260],[3263,3263],[3270,3270],[3276,3277],[3298,3299],[3393,3395],[3405,3405],[3530,3530],[3538,3540],[3542,3542],[3633,3633],[3636,3642],[3655,3662],[3761,3761],[3764,3769],[3771,3772],[3784,3789],[3864,3865],[3893,3893],[3895,3895],[3897,3897],[3953,3966],[3968,3972],[3974,3975],[3984,3991],[3993,4028],[4038,4038],[4141,4144],[4146,4146],[4150,4151],[4153,4153],[4184,4185],[4448,4607],[4959,4959],[5906,5908],[5938,5940],[5970,5971],[6002,6003],[6068,6069],[6071,6077],[6086,6086],[6089,6099],[6109,6109],[6155,6157],[6313,6313],[6432,6434],[6439,6440],[6450,6450],[6457,6459],[6679,6680],[6912,6915],[6964,6964],[6966,6970],[6972,6972],[6978,6978],[7019,7027],[7616,7626],[7678,7679],[8203,8207],[8234,8238],[8288,8291],[8298,8303],[8400,8431],[12330,12335],[12441,12442],[43014,43014],[43019,43019],[43045,43046],[64286,64286],[65024,65039],[65056,65059],[65279,65279],[65529,65531]],s=[[68097,68099],[68101,68102],[68108,68111],[68152,68154],[68159,68159],[119143,119145],[119155,119170],[119173,119179],[119210,119213],[119362,119364],[917505,917505],[917536,917631],[917760,917999]];var a=function(){function e(){if(this.version="6",!i){i=new Uint8Array(65536),n.fill(i,1),i[0]=0,n.fill(i,0,1,32),n.fill(i,0,127,160),n.fill(i,2,4352,4448),i[9001]=2,i[9002]=2,n.fill(i,2,11904,42192),i[12351]=1,n.fill(i,2,44032,55204),n.fill(i,2,63744,64256),n.fill(i,2,65040,65050),n.fill(i,2,65072,65136),n.fill(i,2,65280,65377),n.fill(i,2,65504,65511);for(var e=0;et[n][1])return!1;for(;n>=i;)if(e>t[r=i+n>>1][1])i=r+1;else{if(!(e=131072&&e<=196605||e>=196608&&e<=262141?2:1},e}();t.UnicodeV6=a},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=function(){function e(){this.charsets=[],this.glevel=0}return e.prototype.reset=function(){this.charset=void 0,this.charsets=[],this.glevel=0},e.prototype.setgLevel=function(e){this.glevel=e,this.charset=this.charsets[e]},e.prototype.setgCharset=function(e,t){this.charsets[e]=t,this.glevel===e&&(this.charset=t)},e}();t.CharsetService=i},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=function(){function e(){this._addons=[]}return e.prototype.dispose=function(){for(var e=this._addons.length-1;e>=0;e--)this._addons[e].instance.dispose()},e.prototype.loadAddon=function(e,t){var r=this,i={instance:t,dispose:t.dispose,isDisposed:!1};this._addons.push(i),t.dispose=function(){return r._wrappedAddonDispose(i)},t.activate(e)},e.prototype._wrappedAddonDispose=function(e){if(!e.isDisposed){for(var t=-1,r=0;r('BufferService');\nexport interface IBufferService {\n serviceBrand: any;\n\n readonly cols: number;\n readonly rows: number;\n readonly buffer: IBuffer;\n readonly buffers: IBufferSet;\n\n // TODO: Move resize event here\n\n resize(cols: number, rows: number): void;\n reset(): void;\n}\n\nexport const ICoreMouseService = createDecorator('CoreMouseService');\nexport interface ICoreMouseService {\n activeProtocol: string;\n activeEncoding: string;\n addProtocol(name: string, protocol: ICoreMouseProtocol): void;\n addEncoding(name: string, encoding: CoreMouseEncoding): void;\n reset(): void;\n\n /**\n * Triggers a mouse event to be sent.\n *\n * Returns true if the event passed all protocol restrictions and a report\n * was sent, otherwise false. The return value may be used to decide whether\n * the default event action in the bowser component should be omitted.\n *\n * Note: The method will change values of the given event object\n * to fullfill protocol and encoding restrictions.\n */\n triggerMouseEvent(event: ICoreMouseEvent): boolean;\n\n /**\n * Event to announce changes in mouse tracking.\n */\n onProtocolChange: IEvent;\n\n /**\n * Human readable version of mouse events.\n */\n explainEvents(events: CoreMouseEventType): {[event: string]: boolean};\n}\n\nexport const ICoreService = createDecorator('CoreService');\nexport interface ICoreService {\n serviceBrand: any;\n\n /**\n * Initially the cursor will not be visible until the first time the terminal\n * is focused.\n */\n isCursorInitialized: boolean;\n isCursorHidden: boolean;\n\n readonly decPrivateModes: IDecPrivateModes;\n\n readonly onData: IEvent;\n readonly onUserInput: IEvent;\n readonly onBinary: IEvent;\n\n reset(): void;\n\n /**\n * Triggers the onData event in the public API.\n * @param data The data that is being emitted.\n * @param wasFromUser Whether the data originated from the user (as opposed to\n * resulting from parsing incoming data). When true this will also:\n * - Scroll to the bottom of the buffer.s\n * - Fire the `onUserInput` event (so selection can be cleared).\n */\n triggerDataEvent(data: string, wasUserInput?: boolean): void;\n\n /**\n * Triggers the onBinary event in the public API.\n * @param data The data that is being emitted.\n */\n triggerBinaryEvent(data: string): void;\n}\n\nexport const ICharsetService = createDecorator('CharsetService');\nexport interface ICharsetService {\n serviceBrand: any;\n\n charset: ICharset | undefined;\n readonly glevel: number;\n readonly charsets: ReadonlyArray;\n\n reset(): void;\n\n /**\n * Set the G level of the terminal.\n * @param g\n */\n setgLevel(g: number): void;\n\n /**\n * Set the charset for the given G level of the terminal.\n * @param g\n * @param charset\n */\n setgCharset(g: number, charset: ICharset): void;\n}\n\nexport const IDirtyRowService = createDecorator('DirtyRowService');\nexport interface IDirtyRowService {\n serviceBrand: any;\n\n readonly start: number;\n readonly end: number;\n\n clearRange(): void;\n markDirty(y: number): void;\n markRangeDirty(y1: number, y2: number): void;\n markAllDirty(): void;\n}\n\nexport interface IServiceIdentifier {\n (...args: any[]): void;\n type: T;\n}\n\nexport interface IConstructorSignature0 {\n new(...services: { serviceBrand: any; }[]): T;\n}\n\nexport interface IConstructorSignature1 {\n new(first: A1, ...services: { serviceBrand: any; }[]): T;\n}\n\nexport interface IConstructorSignature2 {\n new(first: A1, second: A2, ...services: { serviceBrand: any; }[]): T;\n}\n\nexport interface IConstructorSignature3 {\n new(first: A1, second: A2, third: A3, ...services: { serviceBrand: any; }[]): T;\n}\n\nexport interface IConstructorSignature4 {\n new(first: A1, second: A2, third: A3, fourth: A4, ...services: { serviceBrand: any; }[]): T;\n}\n\nexport interface IConstructorSignature5 {\n new(first: A1, second: A2, third: A3, fourth: A4, fifth: A5, ...services: { serviceBrand: any; }[]): T;\n}\n\nexport interface IConstructorSignature6 {\n new(first: A1, second: A2, third: A3, fourth: A4, fifth: A5, sixth: A6, ...services: { serviceBrand: any; }[]): T;\n}\n\nexport interface IConstructorSignature7 {\n new(first: A1, second: A2, third: A3, fourth: A4, fifth: A5, sixth: A6, seventh: A7, ...services: { serviceBrand: any; }[]): T;\n}\n\nexport interface IConstructorSignature8 {\n new(first: A1, second: A2, third: A3, fourth: A4, fifth: A5, sixth: A6, seventh: A7, eigth: A8, ...services: { serviceBrand: any; }[]): T;\n}\n\nexport const IInstantiationService = createDecorator('InstantiationService');\nexport interface IInstantiationService {\n setService(id: IServiceIdentifier, instance: T): void;\n getService(id: IServiceIdentifier): T | undefined;\n\n createInstance(ctor: IConstructorSignature0): T;\n createInstance(ctor: IConstructorSignature1, first: A1): T;\n createInstance(ctor: IConstructorSignature2, first: A1, second: A2): T;\n createInstance(ctor: IConstructorSignature3, first: A1, second: A2, third: A3): T;\n createInstance(ctor: IConstructorSignature4, first: A1, second: A2, third: A3, fourth: A4): T;\n createInstance(ctor: IConstructorSignature5, first: A1, second: A2, third: A3, fourth: A4, fifth: A5): T;\n createInstance(ctor: IConstructorSignature6, first: A1, second: A2, third: A3, fourth: A4, fifth: A5, sixth: A6): T;\n createInstance(ctor: IConstructorSignature7, first: A1, second: A2, third: A3, fourth: A4, fifth: A5, sixth: A6, seventh: A7): T;\n createInstance(ctor: IConstructorSignature8, first: A1, second: A2, third: A3, fourth: A4, fifth: A5, sixth: A6, seventh: A7, eigth: A8): T;\n}\n\nexport const ILogService = createDecorator('LogService');\nexport interface ILogService {\n serviceBrand: any;\n\n debug(message: any, ...optionalParams: any[]): void;\n info(message: any, ...optionalParams: any[]): void;\n warn(message: any, ...optionalParams: any[]): void;\n error(message: any, ...optionalParams: any[]): void;\n}\n\nexport const IOptionsService = createDecorator('OptionsService');\nexport interface IOptionsService {\n serviceBrand: any;\n\n readonly options: ITerminalOptions;\n\n readonly onOptionChange: IEvent;\n\n setOption(key: string, value: T): void;\n getOption(key: string): T | undefined;\n}\n\nexport type FontWeight = 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900';\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'off';\nexport type RendererType = 'dom' | 'canvas';\n\nexport interface IPartialTerminalOptions {\n allowTransparency?: boolean;\n bellSound?: string;\n bellStyle?: 'none' /*| 'visual'*/ | 'sound' /*| 'both'*/;\n cols?: number;\n cursorBlink?: boolean;\n cursorStyle?: 'block' | 'underline' | 'bar';\n cursorWidth?: number;\n disableStdin?: boolean;\n drawBoldTextInBrightColors?: boolean;\n fastScrollModifier?: 'alt' | 'ctrl' | 'shift';\n fastScrollSensitivity?: number;\n fontSize?: number;\n fontFamily?: string;\n fontWeight?: FontWeight;\n fontWeightBold?: FontWeight;\n letterSpacing?: number;\n lineHeight?: number;\n logLevel?: LogLevel;\n macOptionIsMeta?: boolean;\n macOptionClickForcesSelection?: boolean;\n rendererType?: RendererType;\n rightClickSelectsWord?: boolean;\n rows?: number;\n screenReaderMode?: boolean;\n scrollback?: number;\n scrollSensitivity?: number;\n tabStopWidth?: number;\n theme?: ITheme;\n windowsMode?: boolean;\n wordSeparator?: string;\n windowOptions?: IWindowOptions;\n}\n\nexport interface ITerminalOptions {\n allowTransparency: boolean;\n bellSound: string;\n bellStyle: 'none' /*| 'visual'*/ | 'sound' /*| 'both'*/;\n cols: number;\n cursorBlink: boolean;\n cursorStyle: 'block' | 'underline' | 'bar';\n cursorWidth: number;\n disableStdin: boolean;\n drawBoldTextInBrightColors: boolean;\n fastScrollModifier: 'alt' | 'ctrl' | 'shift' | undefined;\n fastScrollSensitivity: number;\n fontSize: number;\n fontFamily: string;\n fontWeight: FontWeight;\n fontWeightBold: FontWeight;\n letterSpacing: number;\n lineHeight: number;\n logLevel: LogLevel;\n macOptionIsMeta: boolean;\n macOptionClickForcesSelection: boolean;\n minimumContrastRatio: number;\n rendererType: RendererType;\n rightClickSelectsWord: boolean;\n rows: number;\n screenReaderMode: boolean;\n scrollback: number;\n scrollSensitivity: number;\n tabStopWidth: number;\n theme: ITheme;\n windowsMode: boolean;\n windowOptions: IWindowOptions;\n wordSeparator: string;\n\n [key: string]: any;\n cancelEvents: boolean;\n convertEol: boolean;\n termName: string;\n}\n\nexport interface ITheme {\n foreground?: string;\n background?: string;\n cursor?: string;\n cursorAccent?: string;\n selection?: string;\n black?: string;\n red?: string;\n green?: string;\n yellow?: string;\n blue?: string;\n magenta?: string;\n cyan?: string;\n white?: string;\n brightBlack?: string;\n brightRed?: string;\n brightGreen?: string;\n brightYellow?: string;\n brightBlue?: string;\n brightMagenta?: string;\n brightCyan?: string;\n brightWhite?: string;\n}\n\nexport const IUnicodeService = createDecorator('UnicodeService');\nexport interface IUnicodeService {\n /** Register an Unicode version provider. */\n register(provider: IUnicodeVersionProvider): void;\n /** Registered Unicode versions. */\n readonly versions: string[];\n /** Currently active version. */\n activeVersion: string;\n /** Event triggered, when activate version changed. */\n readonly onChange: IEvent;\n\n /**\n * Unicode version dependent\n */\n wcwidth(codepoint: number): number;\n getStringCellWidth(s: string): number;\n}\n\nexport interface IUnicodeVersionProvider {\n readonly version: string;\n wcwidth(ucs: number): 0 | 1 | 2;\n}\n","/**\n * Copyright (c) 2019 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { IDisposable } from 'common/Types';\n\ninterface IListener {\n (arg1: T, arg2: U): void;\n}\n\nexport interface IEvent {\n (listener: (arg1: T, arg2: U) => any): IDisposable;\n}\n\nexport interface IEventEmitter {\n event: IEvent;\n fire(arg1: T, arg2: U): void;\n dispose(): void;\n}\n\nexport class EventEmitter implements IEventEmitter {\n private _listeners: IListener[] = [];\n private _event?: IEvent;\n private _disposed: boolean = false;\n\n public get event(): IEvent {\n if (!this._event) {\n this._event = (listener: (arg1: T, arg2: U) => any) => {\n this._listeners.push(listener);\n const disposable = {\n dispose: () => {\n if (!this._disposed) {\n for (let i = 0; i < this._listeners.length; i++) {\n if (this._listeners[i] === listener) {\n this._listeners.splice(i, 1);\n return;\n }\n }\n }\n }\n };\n return disposable;\n };\n }\n return this._event;\n }\n\n public fire(arg1: T, arg2: U): void {\n const queue: IListener[] = [];\n for (let i = 0; i < this._listeners.length; i++) {\n queue.push(this._listeners[i]);\n }\n for (let i = 0; i < queue.length; i++) {\n queue[i].call(undefined, arg1, arg2);\n }\n }\n\n public dispose(): void {\n if (this._listeners) {\n this._listeners.length = 0;\n }\n this._disposed = true;\n }\n}\n","/**\n * Copyright (c) 2018 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { IDisposable } from 'common/Types';\n\n/**\n * A base class that can be extended to provide convenience methods for managing the lifecycle of an\n * object and its components.\n */\nexport abstract class Disposable implements IDisposable {\n protected _disposables: IDisposable[] = [];\n protected _isDisposed: boolean = false;\n\n constructor() {\n }\n\n /**\n * Disposes the object, triggering the `dispose` method on all registered IDisposables.\n */\n public dispose(): void {\n this._isDisposed = true;\n this._disposables.forEach(d => d.dispose());\n this._disposables.length = 0;\n }\n\n /**\n * Registers a disposable object.\n * @param d The disposable to register.\n */\n public register(d: T): void {\n this._disposables.push(d);\n }\n\n /**\n * Unregisters a disposable object if it has been registered, if not do\n * nothing.\n * @param d The disposable to unregister.\n */\n public unregister(d: T): void {\n const index = this._disposables.indexOf(d);\n if (index !== -1) {\n this._disposables.splice(index, 1);\n }\n }\n}\n","/**\n * Copyright (c) 2019 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nexport const DEFAULT_COLOR = 256;\nexport const DEFAULT_ATTR = (0 << 18) | (DEFAULT_COLOR << 9) | (256 << 0);\n\nexport const CHAR_DATA_ATTR_INDEX = 0;\nexport const CHAR_DATA_CHAR_INDEX = 1;\nexport const CHAR_DATA_WIDTH_INDEX = 2;\nexport const CHAR_DATA_CODE_INDEX = 3;\n\n/**\n * Null cell - a real empty cell (containing nothing).\n * Note that code should always be 0 for a null cell as\n * several test condition of the buffer line rely on this.\n */\nexport const NULL_CELL_CHAR = '';\nexport const NULL_CELL_WIDTH = 1;\nexport const NULL_CELL_CODE = 0;\n\n/**\n * Whitespace cell.\n * This is meant as a replacement for empty cells when needed\n * during rendering lines to preserve correct aligment.\n */\nexport const WHITESPACE_CELL_CHAR = ' ';\nexport const WHITESPACE_CELL_WIDTH = 1;\nexport const WHITESPACE_CELL_CODE = 32;\n\n/**\n * Bitmasks for accessing data in `content`.\n */\nexport const enum Content {\n /**\n * bit 1..21 codepoint, max allowed in UTF32 is 0x10FFFF (21 bits taken)\n * read: `codepoint = content & Content.codepointMask;`\n * write: `content |= codepoint & Content.codepointMask;`\n * shortcut if precondition `codepoint <= 0x10FFFF` is met:\n * `content |= codepoint;`\n */\n CODEPOINT_MASK = 0x1FFFFF,\n\n /**\n * bit 22 flag indication whether a cell contains combined content\n * read: `isCombined = content & Content.isCombined;`\n * set: `content |= Content.isCombined;`\n * clear: `content &= ~Content.isCombined;`\n */\n IS_COMBINED_MASK = 0x200000, // 1 << 21\n\n /**\n * bit 1..22 mask to check whether a cell contains any string data\n * we need to check for codepoint and isCombined bits to see\n * whether a cell contains anything\n * read: `isEmpty = !(content & Content.hasContent)`\n */\n HAS_CONTENT_MASK = 0x3FFFFF,\n\n /**\n * bit 23..24 wcwidth value of cell, takes 2 bits (ranges from 0..2)\n * read: `width = (content & Content.widthMask) >> Content.widthShift;`\n * `hasWidth = content & Content.widthMask;`\n * as long as wcwidth is highest value in `content`:\n * `width = content >> Content.widthShift;`\n * write: `content |= (width << Content.widthShift) & Content.widthMask;`\n * shortcut if precondition `0 <= width <= 3` is met:\n * `content |= width << Content.widthShift;`\n */\n WIDTH_MASK = 0xC00000, // 3 << 22\n WIDTH_SHIFT = 22\n}\n\nexport const enum Attributes {\n /**\n * bit 1..8 blue in RGB, color in P256 and P16\n */\n BLUE_MASK = 0xFF,\n BLUE_SHIFT = 0,\n PCOLOR_MASK = 0xFF,\n PCOLOR_SHIFT = 0,\n\n /**\n * bit 9..16 green in RGB\n */\n GREEN_MASK = 0xFF00,\n GREEN_SHIFT = 8,\n\n /**\n * bit 17..24 red in RGB\n */\n RED_MASK = 0xFF0000,\n RED_SHIFT = 16,\n\n /**\n * bit 25..26 color mode: DEFAULT (0) | P16 (1) | P256 (2) | RGB (3)\n */\n CM_MASK = 0x3000000,\n CM_DEFAULT = 0,\n CM_P16 = 0x1000000,\n CM_P256 = 0x2000000,\n CM_RGB = 0x3000000,\n\n /**\n * bit 1..24 RGB room\n */\n RGB_MASK = 0xFFFFFF\n}\n\nexport const enum FgFlags {\n /**\n * bit 27..31 (32th bit unused)\n */\n INVERSE = 0x4000000,\n BOLD = 0x8000000,\n UNDERLINE = 0x10000000,\n BLINK = 0x20000000,\n INVISIBLE = 0x40000000\n}\n\nexport const enum BgFlags {\n /**\n * bit 27..32 (upper 4 unused)\n */\n ITALIC = 0x4000000,\n DIM = 0x8000000\n}\n","/**\n * Copyright (c) 2019 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { IEvent } from 'common/EventEmitter';\nimport { IRenderDimensions, IRenderer, CharacterJoinerHandler } from 'browser/renderer/Types';\nimport { IColorSet } from 'browser/Types';\nimport { ISelectionRedrawRequestEvent } from 'browser/selection/Types';\nimport { createDecorator } from 'common/services/ServiceRegistry';\nimport { IDisposable } from 'common/Types';\n\nexport const ICharSizeService = createDecorator('CharSizeService');\nexport interface ICharSizeService {\n serviceBrand: any;\n\n readonly width: number;\n readonly height: number;\n readonly hasValidSize: boolean;\n\n readonly onCharSizeChange: IEvent;\n\n measure(): void;\n}\n\nexport const ICoreBrowserService = createDecorator('CoreBrowserService');\nexport interface ICoreBrowserService {\n serviceBrand: any;\n\n readonly isFocused: boolean;\n}\n\nexport const IMouseService = createDecorator('MouseService');\nexport interface IMouseService {\n serviceBrand: any;\n\n getCoords(event: {clientX: number, clientY: number}, element: HTMLElement, colCount: number, rowCount: number, isSelection?: boolean): [number, number] | undefined;\n getRawByteCoords(event: MouseEvent, element: HTMLElement, colCount: number, rowCount: number): { x: number, y: number } | undefined;\n}\n\nexport const IRenderService = createDecorator('RenderService');\nexport interface IRenderService extends IDisposable {\n serviceBrand: any;\n\n onDimensionsChange: IEvent;\n onRender: IEvent<{ start: number, end: number }>;\n onRefreshRequest: IEvent<{ start: number, end: number }>;\n\n dimensions: IRenderDimensions;\n\n refreshRows(start: number, end: number): void;\n resize(cols: number, rows: number): void;\n changeOptions(): void;\n setRenderer(renderer: IRenderer): void;\n setColors(colors: IColorSet): void;\n onDevicePixelRatioChange(): void;\n onResize(cols: number, rows: number): void;\n // TODO: Is this useful when we have onResize?\n onCharSizeChanged(): void;\n onBlur(): void;\n onFocus(): void;\n onSelectionChanged(start: [number, number], end: [number, number], columnSelectMode: boolean): void;\n onCursorMove(): void;\n clear(): void;\n registerCharacterJoiner(handler: CharacterJoinerHandler): number;\n deregisterCharacterJoiner(joinerId: number): boolean;\n}\n\nexport const ISelectionService = createDecorator('SelectionService');\nexport interface ISelectionService {\n serviceBrand: any;\n\n readonly selectionText: string;\n readonly hasSelection: boolean;\n readonly selectionStart: [number, number] | undefined;\n readonly selectionEnd: [number, number] | undefined;\n\n readonly onLinuxMouseSelection: IEvent;\n readonly onRedrawRequest: IEvent;\n readonly onSelectionChange: IEvent;\n\n disable(): void;\n enable(): void;\n reset(): void;\n setSelection(row: number, col: number, length: number): void;\n selectAll(): void;\n selectLines(start: number, end: number): void;\n clearSelection(): void;\n isClickInSelection(event: MouseEvent): boolean;\n selectWordAtCursor(event: MouseEvent): void;\n shouldColumnSelect(event: KeyboardEvent | MouseEvent): boolean;\n shouldForceSelection(event: MouseEvent): boolean;\n refresh(isLinuxMouseSelection?: boolean): void;\n onMouseDown(event: MouseEvent): void;\n}\n\nexport const ISoundService = createDecorator('SoundService');\nexport interface ISoundService {\n serviceBrand: any;\n\n playBellSound(): void;\n}\n","/**\n * Copyright (c) 2018 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { CharData, ICellData } from 'common/Types';\nimport { stringFromCodePoint } from 'common/input/TextDecoder';\nimport { CHAR_DATA_CHAR_INDEX, CHAR_DATA_WIDTH_INDEX, CHAR_DATA_ATTR_INDEX, Content } from 'common/buffer/Constants';\nimport { AttributeData } from 'common/buffer/AttributeData';\n\n/**\n * CellData - represents a single Cell in the terminal buffer.\n */\nexport class CellData extends AttributeData implements ICellData {\n /** Helper to create CellData from CharData. */\n public static fromCharData(value: CharData): CellData {\n const obj = new CellData();\n obj.setFromCharData(value);\n return obj;\n }\n /** Primitives from terminal buffer. */\n public content: number = 0;\n public fg: number = 0;\n public bg: number = 0;\n public combinedData: string = '';\n /** Whether cell contains a combined string. */\n public isCombined(): number {\n return this.content & Content.IS_COMBINED_MASK;\n }\n /** Width of the cell. */\n public getWidth(): number {\n return this.content >> Content.WIDTH_SHIFT;\n }\n /** JS string of the content. */\n public getChars(): string {\n if (this.content & Content.IS_COMBINED_MASK) {\n return this.combinedData;\n }\n if (this.content & Content.CODEPOINT_MASK) {\n return stringFromCodePoint(this.content & Content.CODEPOINT_MASK);\n }\n return '';\n }\n /**\n * Codepoint of cell\n * Note this returns the UTF32 codepoint of single chars,\n * if content is a combined string it returns the codepoint\n * of the last char in string to be in line with code in CharData.\n * */\n public getCode(): number {\n return (this.isCombined())\n ? this.combinedData.charCodeAt(this.combinedData.length - 1)\n : this.content & Content.CODEPOINT_MASK;\n }\n /** Set data from CharData */\n public setFromCharData(value: CharData): void {\n this.fg = value[CHAR_DATA_ATTR_INDEX];\n this.bg = 0;\n let combined = false;\n // surrogates and combined strings need special treatment\n if (value[CHAR_DATA_CHAR_INDEX].length > 2) {\n combined = true;\n }\n else if (value[CHAR_DATA_CHAR_INDEX].length === 2) {\n const code = value[CHAR_DATA_CHAR_INDEX].charCodeAt(0);\n // if the 2-char string is a surrogate create single codepoint\n // everything else is combined\n if (0xD800 <= code && code <= 0xDBFF) {\n const second = value[CHAR_DATA_CHAR_INDEX].charCodeAt(1);\n if (0xDC00 <= second && second <= 0xDFFF) {\n this.content = ((code - 0xD800) * 0x400 + second - 0xDC00 + 0x10000) | (value[CHAR_DATA_WIDTH_INDEX] << Content.WIDTH_SHIFT);\n }\n else {\n combined = true;\n }\n }\n else {\n combined = true;\n }\n }\n else {\n this.content = value[CHAR_DATA_CHAR_INDEX].charCodeAt(0) | (value[CHAR_DATA_WIDTH_INDEX] << Content.WIDTH_SHIFT);\n }\n if (combined) {\n this.combinedData = value[CHAR_DATA_CHAR_INDEX];\n this.content = Content.IS_COMBINED_MASK | (value[CHAR_DATA_WIDTH_INDEX] << Content.WIDTH_SHIFT);\n }\n }\n /** Get data as CharData. */\n public getAsCharData(): CharData {\n return [this.fg, this.getChars(), this.getWidth(), this.getCode()];\n }\n}\n","/**\n * Copyright (c) 2018 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { IAttributeData, IColorRGB } from 'common/Types';\nimport { Attributes, FgFlags, BgFlags } from 'common/buffer/Constants';\n\nexport class AttributeData implements IAttributeData {\n static toColorRGB(value: number): IColorRGB {\n return [\n value >>> Attributes.RED_SHIFT & 255,\n value >>> Attributes.GREEN_SHIFT & 255,\n value & 255\n ];\n }\n static fromColorRGB(value: IColorRGB): number {\n return (value[0] & 255) << Attributes.RED_SHIFT | (value[1] & 255) << Attributes.GREEN_SHIFT | value[2] & 255;\n }\n\n public clone(): IAttributeData {\n const newObj = new AttributeData();\n newObj.fg = this.fg;\n newObj.bg = this.bg;\n return newObj;\n }\n\n // data\n public fg: number = 0;\n public bg: number = 0;\n\n // flags\n public isInverse(): number { return this.fg & FgFlags.INVERSE; }\n public isBold(): number { return this.fg & FgFlags.BOLD; }\n public isUnderline(): number { return this.fg & FgFlags.UNDERLINE; }\n public isBlink(): number { return this.fg & FgFlags.BLINK; }\n public isInvisible(): number { return this.fg & FgFlags.INVISIBLE; }\n public isItalic(): number { return this.bg & BgFlags.ITALIC; }\n public isDim(): number { return this.bg & BgFlags.DIM; }\n\n // color modes\n public getFgColorMode(): number { return this.fg & Attributes.CM_MASK; }\n public getBgColorMode(): number { return this.bg & Attributes.CM_MASK; }\n public isFgRGB(): boolean { return (this.fg & Attributes.CM_MASK) === Attributes.CM_RGB; }\n public isBgRGB(): boolean { return (this.bg & Attributes.CM_MASK) === Attributes.CM_RGB; }\n public isFgPalette(): boolean { return (this.fg & Attributes.CM_MASK) === Attributes.CM_P16 || (this.fg & Attributes.CM_MASK) === Attributes.CM_P256; }\n public isBgPalette(): boolean { return (this.bg & Attributes.CM_MASK) === Attributes.CM_P16 || (this.bg & Attributes.CM_MASK) === Attributes.CM_P256; }\n public isFgDefault(): boolean { return (this.fg & Attributes.CM_MASK) === 0; }\n public isBgDefault(): boolean { return (this.bg & Attributes.CM_MASK) === 0; }\n public isAttributeDefault(): boolean { return this.fg === 0 && this.bg === 0; }\n\n // colors\n public getFgColor(): number {\n switch (this.fg & Attributes.CM_MASK) {\n case Attributes.CM_P16:\n case Attributes.CM_P256: return this.fg & Attributes.PCOLOR_MASK;\n case Attributes.CM_RGB: return this.fg & Attributes.RGB_MASK;\n default: return -1; // CM_DEFAULT defaults to -1\n }\n }\n public getBgColor(): number {\n switch (this.bg & Attributes.CM_MASK) {\n case Attributes.CM_P16:\n case Attributes.CM_P256: return this.bg & Attributes.PCOLOR_MASK;\n case Attributes.CM_RGB: return this.bg & Attributes.RGB_MASK;\n default: return -1; // CM_DEFAULT defaults to -1\n }\n }\n}\n","/**\n * Copyright (c) 2019 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\n/**\n * Polyfill - Convert UTF32 codepoint into JS string.\n * Note: The built-in String.fromCodePoint happens to be much slower\n * due to additional sanity checks. We can avoid them since\n * we always operate on legal UTF32 (granted by the input decoders)\n * and use this faster version instead.\n */\nexport function stringFromCodePoint(codePoint: number): string {\n if (codePoint > 0xFFFF) {\n codePoint -= 0x10000;\n return String.fromCharCode((codePoint >> 10) + 0xD800) + String.fromCharCode((codePoint % 0x400) + 0xDC00);\n }\n return String.fromCharCode(codePoint);\n}\n\n/**\n * Convert UTF32 char codes into JS string.\n * Basically the same as `stringFromCodePoint` but for multiple codepoints\n * in a loop (which is a lot faster).\n */\nexport function utf32ToString(data: Uint32Array, start: number = 0, end: number = data.length): string {\n let result = '';\n for (let i = start; i < end; ++i) {\n let codepoint = data[i];\n if (codepoint > 0xFFFF) {\n // JS strings are encoded as UTF16, thus a non BMP codepoint gets converted into a surrogate pair\n // conversion rules:\n // - subtract 0x10000 from code point, leaving a 20 bit number\n // - add high 10 bits to 0xD800 --> first surrogate\n // - add low 10 bits to 0xDC00 --> second surrogate\n codepoint -= 0x10000;\n result += String.fromCharCode((codepoint >> 10) + 0xD800) + String.fromCharCode((codepoint % 0x400) + 0xDC00);\n } else {\n result += String.fromCharCode(codepoint);\n }\n }\n return result;\n}\n\n/**\n * StringToUtf32 - decodes UTF16 sequences into UTF32 codepoints.\n * To keep the decoder in line with JS strings it handles single surrogates as UCS2.\n */\nexport class StringToUtf32 {\n private _interim: number = 0;\n\n /**\n * Clears interim and resets decoder to clean state.\n */\n public clear(): void {\n this._interim = 0;\n }\n\n /**\n * Decode JS string to UTF32 codepoints.\n * The methods assumes stream input and will store partly transmitted\n * surrogate pairs and decode them with the next data chunk.\n * Note: The method does no bound checks for target, therefore make sure\n * the provided input data does not exceed the size of `target`.\n * Returns the number of written codepoints in `target`.\n */\n decode(input: string, target: Uint32Array): number {\n const length = input.length;\n\n if (!length) {\n return 0;\n }\n\n let size = 0;\n let startPos = 0;\n\n // handle leftover surrogate high\n if (this._interim) {\n const second = input.charCodeAt(startPos++);\n if (0xDC00 <= second && second <= 0xDFFF) {\n target[size++] = (this._interim - 0xD800) * 0x400 + second - 0xDC00 + 0x10000;\n } else {\n // illegal codepoint (USC2 handling)\n target[size++] = this._interim;\n target[size++] = second;\n }\n this._interim = 0;\n }\n\n for (let i = startPos; i < length; ++i) {\n const code = input.charCodeAt(i);\n // surrogate pair first\n if (0xD800 <= code && code <= 0xDBFF) {\n if (++i >= length) {\n this._interim = code;\n return size;\n }\n const second = input.charCodeAt(i);\n if (0xDC00 <= second && second <= 0xDFFF) {\n target[size++] = (code - 0xD800) * 0x400 + second - 0xDC00 + 0x10000;\n } else {\n // illegal codepoint (USC2 handling)\n target[size++] = code;\n target[size++] = second;\n }\n continue;\n }\n target[size++] = code;\n }\n return size;\n }\n}\n\n/**\n * Utf8Decoder - decodes UTF8 byte sequences into UTF32 codepoints.\n */\nexport class Utf8ToUtf32 {\n public interim: Uint8Array = new Uint8Array(3);\n\n /**\n * Clears interim bytes and resets decoder to clean state.\n */\n public clear(): void {\n this.interim.fill(0);\n }\n\n /**\n * Decodes UTF8 byte sequences in `input` to UTF32 codepoints in `target`.\n * The methods assumes stream input and will store partly transmitted bytes\n * and decode them with the next data chunk.\n * Note: The method does no bound checks for target, therefore make sure\n * the provided data chunk does not exceed the size of `target`.\n * Returns the number of written codepoints in `target`.\n */\n decode(input: Uint8Array, target: Uint32Array): number {\n const length = input.length;\n\n if (!length) {\n return 0;\n }\n\n let size = 0;\n let byte1: number;\n let byte2: number;\n let byte3: number;\n let byte4: number;\n let codepoint = 0;\n let startPos = 0;\n\n // handle leftover bytes\n if (this.interim[0]) {\n let discardInterim = false;\n let cp = this.interim[0];\n cp &= ((((cp & 0xE0) === 0xC0)) ? 0x1F : (((cp & 0xF0) === 0xE0)) ? 0x0F : 0x07);\n let pos = 0;\n let tmp: number;\n while ((tmp = this.interim[++pos] & 0x3F) && pos < 4) {\n cp <<= 6;\n cp |= tmp;\n }\n // missing bytes - read ahead from input\n const type = (((this.interim[0] & 0xE0) === 0xC0)) ? 2 : (((this.interim[0] & 0xF0) === 0xE0)) ? 3 : 4;\n const missing = type - pos;\n while (startPos < missing) {\n if (startPos >= length) {\n return 0;\n }\n tmp = input[startPos++];\n if ((tmp & 0xC0) !== 0x80) {\n // wrong continuation, discard interim bytes completely\n startPos--;\n discardInterim = true;\n break;\n } else {\n // need to save so we can continue short inputs in next call\n this.interim[pos++] = tmp;\n cp <<= 6;\n cp |= tmp & 0x3F;\n }\n }\n if (!discardInterim) {\n // final test is type dependent\n if (type === 2) {\n if (cp < 0x80) {\n // wrong starter byte\n startPos--;\n } else {\n target[size++] = cp;\n }\n } else if (type === 3) {\n if (cp < 0x0800 || (cp >= 0xD800 && cp <= 0xDFFF)) {\n // illegal codepoint\n } else {\n target[size++] = cp;\n }\n } else {\n if (cp < 0x010000 || cp > 0x10FFFF) {\n // illegal codepoint\n } else {\n target[size++] = cp;\n }\n }\n }\n this.interim.fill(0);\n }\n\n // loop through input\n const fourStop = length - 4;\n let i = startPos;\n while (i < length) {\n /**\n * ASCII shortcut with loop unrolled to 4 consecutive ASCII chars.\n * This is a compromise between speed gain for ASCII\n * and penalty for non ASCII:\n * For best ASCII performance the char should be stored directly into target,\n * but even a single attempt to write to target and compare afterwards\n * penalizes non ASCII really bad (-50%), thus we load the char into byteX first,\n * which reduces ASCII performance by ~15%.\n * This trial for ASCII reduces non ASCII performance by ~10% which seems acceptible\n * compared to the gains.\n * Note that this optimization only takes place for 4 consecutive ASCII chars,\n * for any shorter it bails out. Worst case - all 4 bytes being read but\n * thrown away due to the last being a non ASCII char (-10% performance).\n */\n while (i < fourStop\n && !((byte1 = input[i]) & 0x80)\n && !((byte2 = input[i + 1]) & 0x80)\n && !((byte3 = input[i + 2]) & 0x80)\n && !((byte4 = input[i + 3]) & 0x80))\n {\n target[size++] = byte1;\n target[size++] = byte2;\n target[size++] = byte3;\n target[size++] = byte4;\n i += 4;\n }\n\n // reread byte1\n byte1 = input[i++];\n\n // 1 byte\n if (byte1 < 0x80) {\n target[size++] = byte1;\n\n // 2 bytes\n } else if ((byte1 & 0xE0) === 0xC0) {\n if (i >= length) {\n this.interim[0] = byte1;\n return size;\n }\n byte2 = input[i++];\n if ((byte2 & 0xC0) !== 0x80) {\n // wrong continuation\n i--;\n continue;\n }\n codepoint = (byte1 & 0x1F) << 6 | (byte2 & 0x3F);\n if (codepoint < 0x80) {\n // wrong starter byte\n i--;\n continue;\n }\n target[size++] = codepoint;\n\n // 3 bytes\n } else if ((byte1 & 0xF0) === 0xE0) {\n if (i >= length) {\n this.interim[0] = byte1;\n return size;\n }\n byte2 = input[i++];\n if ((byte2 & 0xC0) !== 0x80) {\n // wrong continuation\n i--;\n continue;\n }\n if (i >= length) {\n this.interim[0] = byte1;\n this.interim[1] = byte2;\n return size;\n }\n byte3 = input[i++];\n if ((byte3 & 0xC0) !== 0x80) {\n // wrong continuation\n i--;\n continue;\n }\n codepoint = (byte1 & 0x0F) << 12 | (byte2 & 0x3F) << 6 | (byte3 & 0x3F);\n if (codepoint < 0x0800 || (codepoint >= 0xD800 && codepoint <= 0xDFFF)) {\n // illegal codepoint, no i-- here\n continue;\n }\n target[size++] = codepoint;\n\n // 4 bytes\n } else if ((byte1 & 0xF8) === 0xF0) {\n if (i >= length) {\n this.interim[0] = byte1;\n return size;\n }\n byte2 = input[i++];\n if ((byte2 & 0xC0) !== 0x80) {\n // wrong continuation\n i--;\n continue;\n }\n if (i >= length) {\n this.interim[0] = byte1;\n this.interim[1] = byte2;\n return size;\n }\n byte3 = input[i++];\n if ((byte3 & 0xC0) !== 0x80) {\n // wrong continuation\n i--;\n continue;\n }\n if (i >= length) {\n this.interim[0] = byte1;\n this.interim[1] = byte2;\n this.interim[2] = byte3;\n return size;\n }\n byte4 = input[i++];\n if ((byte4 & 0xC0) !== 0x80) {\n // wrong continuation\n i--;\n continue;\n }\n codepoint = (byte1 & 0x07) << 18 | (byte2 & 0x3F) << 12 | (byte3 & 0x3F) << 6 | (byte4 & 0x3F);\n if (codepoint < 0x010000 || codepoint > 0x10FFFF) {\n // illegal codepoint, no i-- here\n continue;\n }\n target[size++] = codepoint;\n } else {\n // illegal byte, just skip\n }\n }\n return size;\n }\n}\n","/**\n * Copyright (c) 2018 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { IDisposable } from 'common/Types';\n\n/**\n * Adds a disposable listener to a node in the DOM, returning the disposable.\n * @param type The event type.\n * @param handler The handler for the listener.\n */\nexport function addDisposableDomListener(\n node: Element | Window | Document,\n type: string,\n handler: (e: any) => void,\n useCapture?: boolean\n): IDisposable {\n node.addEventListener(type, handler, useCapture);\n let disposed = false;\n return {\n dispose: () => {\n if (!disposed) {\n return;\n }\n disposed = true;\n node.removeEventListener(type, handler, useCapture);\n }\n };\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nexport const INVERTED_DEFAULT_COLOR = 257;\nexport const DIM_OPACITY = 0.5;\n\nexport const CHAR_ATLAS_CELL_SPACING = 1;\n","/**\n * Copyright (c) 2019 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { IColor } from 'browser/Types';\n\n/**\n * Helper functions where the source type is \"channels\" (individual color channels as numbers).\n */\nexport namespace channels {\n export function toCss(r: number, g: number, b: number, a?: number): string {\n if (a !== undefined) {\n return `#${toPaddedHex(r)}${toPaddedHex(g)}${toPaddedHex(b)}${toPaddedHex(a)}`;\n }\n return `#${toPaddedHex(r)}${toPaddedHex(g)}${toPaddedHex(b)}`;\n }\n\n export function toRgba(r: number, g: number, b: number, a: number = 0xFF): number {\n // >>> 0 forces an unsigned int\n return (r << 24 | g << 16 | b << 8 | a) >>> 0;\n }\n}\n\n/**\n * Helper functions where the source type is `IColor`.\n */\nexport namespace color {\n export function blend(bg: IColor, fg: IColor): IColor {\n const a = (fg.rgba & 0xFF) / 255;\n if (a === 1) {\n return {\n css: fg.css,\n rgba: fg.rgba\n };\n }\n const fgR = (fg.rgba >> 24) & 0xFF;\n const fgG = (fg.rgba >> 16) & 0xFF;\n const fgB = (fg.rgba >> 8) & 0xFF;\n const bgR = (bg.rgba >> 24) & 0xFF;\n const bgG = (bg.rgba >> 16) & 0xFF;\n const bgB = (bg.rgba >> 8) & 0xFF;\n const r = bgR + Math.round((fgR - bgR) * a);\n const g = bgG + Math.round((fgG - bgG) * a);\n const b = bgB + Math.round((fgB - bgB) * a);\n const css = channels.toCss(r, g, b);\n const rgba = channels.toRgba(r, g, b);\n return { css, rgba };\n }\n\n export function ensureContrastRatio(bg: IColor, fg: IColor, ratio: number): IColor | undefined {\n const result = rgba.ensureContrastRatio(bg.rgba, fg.rgba, ratio);\n if (!result) {\n return undefined;\n }\n return rgba.toColor(\n (result >> 24 & 0xFF),\n (result >> 16 & 0xFF),\n (result >> 8 & 0xFF)\n );\n }\n\n export function opaque(color: IColor): IColor {\n const rgbaColor = (color.rgba | 0xFF) >>> 0;\n const [r, g, b] = rgba.toChannels(rgbaColor);\n return {\n css: channels.toCss(r, g, b),\n rgba: rgbaColor\n };\n }\n}\n\n/**\n * Helper functions where the source type is \"css\" (string: '#rgb', '#rgba', '#rrggbb', '#rrggbbaa').\n */\nexport namespace css {\n export function toColor(css: string): IColor {\n return {\n css,\n rgba: (parseInt(css.slice(1), 16) << 8 | 0xFF) >>> 0\n };\n }\n}\n\n/**\n * Helper functions where the source type is \"rgb\" (number: 0xrrggbb).\n */\nexport namespace rgb {\n /**\n * Gets the relative luminance of an RGB color, this is useful in determining the contrast ratio\n * between two colors.\n * @param rgb The color to use.\n * @see https://www.w3.org/TR/WCAG20/#relativeluminancedef\n */\n export function relativeLuminance(rgb: number): number {\n return relativeLuminance2(\n (rgb >> 16) & 0xFF,\n (rgb >> 8 ) & 0xFF,\n (rgb ) & 0xFF);\n }\n\n /**\n * Gets the relative luminance of an RGB color, this is useful in determining the contrast ratio\n * between two colors.\n * @param r The red channel (0x00 to 0xFF).\n * @param g The green channel (0x00 to 0xFF).\n * @param b The blue channel (0x00 to 0xFF).\n * @see https://www.w3.org/TR/WCAG20/#relativeluminancedef\n */\n export function relativeLuminance2(r: number, g: number, b: number): number {\n const rs = r / 255;\n const gs = g / 255;\n const bs = b / 255;\n const rr = rs <= 0.03928 ? rs / 12.92 : Math.pow((rs + 0.055) / 1.055, 2.4);\n const rg = gs <= 0.03928 ? gs / 12.92 : Math.pow((gs + 0.055) / 1.055, 2.4);\n const rb = bs <= 0.03928 ? bs / 12.92 : Math.pow((bs + 0.055) / 1.055, 2.4);\n return rr * 0.2126 + rg * 0.7152 + rb * 0.0722;\n }\n}\n\n/**\n * Helper functions where the source type is \"rgba\" (number: 0xrrggbbaa).\n */\nexport namespace rgba {\n export function ensureContrastRatio(bgRgba: number, fgRgba: number, ratio: number): number | undefined {\n const bgL = rgb.relativeLuminance(bgRgba >> 8);\n const fgL = rgb.relativeLuminance(fgRgba >> 8);\n const cr = contrastRatio(bgL, fgL);\n if (cr < ratio) {\n if (fgL < bgL) {\n return reduceLuminance(bgRgba, fgRgba, ratio);\n }\n return increaseLuminance(bgRgba, fgRgba, ratio);\n }\n return undefined;\n }\n\n export function reduceLuminance(bgRgba: number, fgRgba: number, ratio: number): number {\n // This is a naive but fast approach to reducing luminance as converting to\n // HSL and back is expensive\n const bgR = (bgRgba >> 24) & 0xFF;\n const bgG = (bgRgba >> 16) & 0xFF;\n const bgB = (bgRgba >> 8) & 0xFF;\n let fgR = (fgRgba >> 24) & 0xFF;\n let fgG = (fgRgba >> 16) & 0xFF;\n let fgB = (fgRgba >> 8) & 0xFF;\n let cr = contrastRatio(rgb.relativeLuminance2(fgR, fgB, fgG), rgb.relativeLuminance2(bgR, bgG, bgB));\n while (cr < ratio && (fgR > 0 || fgG > 0 || fgB > 0)) {\n // Reduce by 10% until the ratio is hit\n fgR -= Math.max(0, Math.ceil(fgR * 0.1));\n fgG -= Math.max(0, Math.ceil(fgG * 0.1));\n fgB -= Math.max(0, Math.ceil(fgB * 0.1));\n cr = contrastRatio(rgb.relativeLuminance2(fgR, fgB, fgG), rgb.relativeLuminance2(bgR, bgG, bgB));\n }\n return (fgR << 24 | fgG << 16 | fgB << 8 | 0xFF) >>> 0;\n }\n\n export function increaseLuminance(bgRgba: number, fgRgba: number, ratio: number): number {\n // This is a naive but fast approach to increasing luminance as converting to\n // HSL and back is expensive\n const bgR = (bgRgba >> 24) & 0xFF;\n const bgG = (bgRgba >> 16) & 0xFF;\n const bgB = (bgRgba >> 8) & 0xFF;\n let fgR = (fgRgba >> 24) & 0xFF;\n let fgG = (fgRgba >> 16) & 0xFF;\n let fgB = (fgRgba >> 8) & 0xFF;\n let cr = contrastRatio(rgb.relativeLuminance2(fgR, fgB, fgG), rgb.relativeLuminance2(bgR, bgG, bgB));\n while (cr < ratio && (fgR < 0xFF || fgG < 0xFF || fgB < 0xFF)) {\n // Increase by 10% until the ratio is hit\n fgR = Math.min(0xFF, fgR + Math.ceil((255 - fgR) * 0.1));\n fgG = Math.min(0xFF, fgG + Math.ceil((255 - fgG) * 0.1));\n fgB = Math.min(0xFF, fgB + Math.ceil((255 - fgB) * 0.1));\n cr = contrastRatio(rgb.relativeLuminance2(fgR, fgB, fgG), rgb.relativeLuminance2(bgR, bgG, bgB));\n }\n return (fgR << 24 | fgG << 16 | fgB << 8 | 0xFF) >>> 0;\n }\n\n export function toChannels(value: number): [number, number, number, number] {\n return [(value >> 24) & 0xFF, (value >> 16) & 0xFF, (value >> 8) & 0xFF, value & 0xFF];\n }\n\n export function toColor(r: number, g: number, b: number): IColor {\n return {\n css: channels.toCss(r, g, b),\n rgba: channels.toRgba(r, g, b)\n };\n }\n}\n\nexport function toPaddedHex(c: number): string {\n const s = c.toString(16);\n return s.length < 2 ? '0' + s : s;\n}\n\n/**\n * Gets the contrast ratio between two relative luminance values.\n * @param l1 The first relative luminance.\n * @param l2 The first relative luminance.\n * @see https://www.w3.org/TR/WCAG20/#contrast-ratiodef\n */\nexport function contrastRatio(l1: number, l2: number): number {\n if (l1 < l2) {\n return (l2 + 0.05) / (l1 + 0.05);\n }\n return (l1 + 0.05) / (l2 + 0.05);\n}\n","/**\n * Copyright (c) 2016 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\ninterface INavigator {\n userAgent: string;\n language: string;\n platform: string;\n}\n\n// We're declaring a navigator global here as we expect it in all runtimes (node and browser), but\n// we want this module to live in common.\ndeclare const navigator: INavigator;\n\nconst isNode = (typeof navigator === 'undefined') ? true : false;\nconst userAgent = (isNode) ? 'node' : navigator.userAgent;\nconst platform = (isNode) ? 'node' : navigator.platform;\n\nexport const isFirefox = !!~userAgent.indexOf('Firefox');\nexport const isSafari = /^((?!chrome|android).)*safari/i.test(userAgent);\n\n// Find the users platform. We use this to interpret the meta key\n// and ISO third level shifts.\n// http://stackoverflow.com/q/19877924/577598\nexport const isMac = contains(['Macintosh', 'MacIntel', 'MacPPC', 'Mac68K'], platform);\nexport const isIpad = platform === 'iPad';\nexport const isIphone = platform === 'iPhone';\nexport const isWindows = contains(['Windows', 'Win16', 'Win32', 'WinCE'], platform);\nexport const isLinux = platform.indexOf('Linux') >= 0;\n\n/**\n * Return if the given array contains the given element\n * @param arr The array to search for the given element.\n * @param el The element to look for into the array\n */\nfunction contains(arr: any[], el: any): boolean {\n return arr.indexOf(el) >= 0;\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\n/**\n * C0 control codes\n * See = https://en.wikipedia.org/wiki/C0_and_C1_control_codes\n */\nexport namespace C0 {\n /** Null (Caret = ^@, C = \\0) */\n export const NUL = '\\x00';\n /** Start of Heading (Caret = ^A) */\n export const SOH = '\\x01';\n /** Start of Text (Caret = ^B) */\n export const STX = '\\x02';\n /** End of Text (Caret = ^C) */\n export const ETX = '\\x03';\n /** End of Transmission (Caret = ^D) */\n export const EOT = '\\x04';\n /** Enquiry (Caret = ^E) */\n export const ENQ = '\\x05';\n /** Acknowledge (Caret = ^F) */\n export const ACK = '\\x06';\n /** Bell (Caret = ^G, C = \\a) */\n export const BEL = '\\x07';\n /** Backspace (Caret = ^H, C = \\b) */\n export const BS = '\\x08';\n /** Character Tabulation, Horizontal Tabulation (Caret = ^I, C = \\t) */\n export const HT = '\\x09';\n /** Line Feed (Caret = ^J, C = \\n) */\n export const LF = '\\x0a';\n /** Line Tabulation, Vertical Tabulation (Caret = ^K, C = \\v) */\n export const VT = '\\x0b';\n /** Form Feed (Caret = ^L, C = \\f) */\n export const FF = '\\x0c';\n /** Carriage Return (Caret = ^M, C = \\r) */\n export const CR = '\\x0d';\n /** Shift Out (Caret = ^N) */\n export const SO = '\\x0e';\n /** Shift In (Caret = ^O) */\n export const SI = '\\x0f';\n /** Data Link Escape (Caret = ^P) */\n export const DLE = '\\x10';\n /** Device Control One (XON) (Caret = ^Q) */\n export const DC1 = '\\x11';\n /** Device Control Two (Caret = ^R) */\n export const DC2 = '\\x12';\n /** Device Control Three (XOFF) (Caret = ^S) */\n export const DC3 = '\\x13';\n /** Device Control Four (Caret = ^T) */\n export const DC4 = '\\x14';\n /** Negative Acknowledge (Caret = ^U) */\n export const NAK = '\\x15';\n /** Synchronous Idle (Caret = ^V) */\n export const SYN = '\\x16';\n /** End of Transmission Block (Caret = ^W) */\n export const ETB = '\\x17';\n /** Cancel (Caret = ^X) */\n export const CAN = '\\x18';\n /** End of Medium (Caret = ^Y) */\n export const EM = '\\x19';\n /** Substitute (Caret = ^Z) */\n export const SUB = '\\x1a';\n /** Escape (Caret = ^[, C = \\e) */\n export const ESC = '\\x1b';\n /** File Separator (Caret = ^\\) */\n export const FS = '\\x1c';\n /** Group Separator (Caret = ^]) */\n export const GS = '\\x1d';\n /** Record Separator (Caret = ^^) */\n export const RS = '\\x1e';\n /** Unit Separator (Caret = ^_) */\n export const US = '\\x1f';\n /** Space */\n export const SP = '\\x20';\n /** Delete (Caret = ^?) */\n export const DEL = '\\x7f';\n}\n\n/**\n * C1 control codes\n * See = https://en.wikipedia.org/wiki/C0_and_C1_control_codes\n */\nexport namespace C1 {\n /** padding character */\n export const PAD = '\\x80';\n /** High Octet Preset */\n export const HOP = '\\x81';\n /** Break Permitted Here */\n export const BPH = '\\x82';\n /** No Break Here */\n export const NBH = '\\x83';\n /** Index */\n export const IND = '\\x84';\n /** Next Line */\n export const NEL = '\\x85';\n /** Start of Selected Area */\n export const SSA = '\\x86';\n /** End of Selected Area */\n export const ESA = '\\x87';\n /** Horizontal Tabulation Set */\n export const HTS = '\\x88';\n /** Horizontal Tabulation With Justification */\n export const HTJ = '\\x89';\n /** Vertical Tabulation Set */\n export const VTS = '\\x8a';\n /** Partial Line Down */\n export const PLD = '\\x8b';\n /** Partial Line Up */\n export const PLU = '\\x8c';\n /** Reverse Index */\n export const RI = '\\x8d';\n /** Single-Shift 2 */\n export const SS2 = '\\x8e';\n /** Single-Shift 3 */\n export const SS3 = '\\x8f';\n /** Device Control String */\n export const DCS = '\\x90';\n /** Private Use 1 */\n export const PU1 = '\\x91';\n /** Private Use 2 */\n export const PU2 = '\\x92';\n /** Set Transmit State */\n export const STS = '\\x93';\n /** Destructive backspace, intended to eliminate ambiguity about meaning of BS. */\n export const CCH = '\\x94';\n /** Message Waiting */\n export const MW = '\\x95';\n /** Start of Protected Area */\n export const SPA = '\\x96';\n /** End of Protected Area */\n export const EPA = '\\x97';\n /** Start of String */\n export const SOS = '\\x98';\n /** Single Graphic Character Introducer */\n export const SGCI = '\\x99';\n /** Single Character Introducer */\n export const SCI = '\\x9a';\n /** Control Sequence Introducer */\n export const CSI = '\\x9b';\n /** String Terminator */\n export const ST = '\\x9c';\n /** Operating System Command */\n export const OSC = '\\x9d';\n /** Privacy Message */\n export const PM = '\\x9e';\n /** Application Program Command */\n export const APC = '\\x9f';\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { IRenderDimensions, IRenderLayer } from 'browser/renderer/Types';\nimport { ICellData } from 'common/Types';\nimport { DEFAULT_COLOR, WHITESPACE_CELL_CHAR, WHITESPACE_CELL_CODE, Attributes } from 'common/buffer/Constants';\nimport { IGlyphIdentifier } from 'browser/renderer/atlas/Types';\nimport { DIM_OPACITY, INVERTED_DEFAULT_COLOR } from 'browser/renderer/atlas/Constants';\nimport { BaseCharAtlas } from 'browser/renderer/atlas/BaseCharAtlas';\nimport { acquireCharAtlas } from 'browser/renderer/atlas/CharAtlasCache';\nimport { AttributeData } from 'common/buffer/AttributeData';\nimport { IColorSet, IColor } from 'browser/Types';\nimport { CellData } from 'common/buffer/CellData';\nimport { IBufferService, IOptionsService } from 'common/services/Services';\nimport { throwIfFalsy } from 'browser/renderer/RendererUtils';\nimport { channels, color, rgba } from 'browser/Color';\n\nexport abstract class BaseRenderLayer implements IRenderLayer {\n private _canvas: HTMLCanvasElement;\n protected _ctx!: CanvasRenderingContext2D;\n private _scaledCharWidth: number = 0;\n private _scaledCharHeight: number = 0;\n private _scaledCellWidth: number = 0;\n private _scaledCellHeight: number = 0;\n private _scaledCharLeft: number = 0;\n private _scaledCharTop: number = 0;\n\n protected _charAtlas: BaseCharAtlas | undefined;\n\n /**\n * An object that's reused when drawing glyphs in order to reduce GC.\n */\n private _currentGlyphIdentifier: IGlyphIdentifier = {\n chars: '',\n code: 0,\n bg: 0,\n fg: 0,\n bold: false,\n dim: false,\n italic: false\n };\n\n constructor(\n private _container: HTMLElement,\n id: string,\n zIndex: number,\n private _alpha: boolean,\n protected _colors: IColorSet,\n private _rendererId: number,\n protected readonly _bufferService: IBufferService,\n protected readonly _optionsService: IOptionsService\n ) {\n this._canvas = document.createElement('canvas');\n this._canvas.classList.add(`xterm-${id}-layer`);\n this._canvas.style.zIndex = zIndex.toString();\n this._initCanvas();\n this._container.appendChild(this._canvas);\n }\n\n public dispose(): void {\n this._container.removeChild(this._canvas);\n this._charAtlas?.dispose();\n }\n\n private _initCanvas(): void {\n this._ctx = throwIfFalsy(this._canvas.getContext('2d', {alpha: this._alpha}));\n // Draw the background if this is an opaque layer\n if (!this._alpha) {\n this._clearAll();\n }\n }\n\n public onOptionsChanged(): void {}\n public onBlur(): void {}\n public onFocus(): void {}\n public onCursorMove(): void {}\n public onGridChanged(startRow: number, endRow: number): void {}\n public onSelectionChanged(start: [number, number], end: [number, number], columnSelectMode: boolean = false): void {}\n\n public setColors(colorSet: IColorSet): void {\n this._refreshCharAtlas(colorSet);\n }\n\n protected _setTransparency(alpha: boolean): void {\n // Do nothing when alpha doesn't change\n if (alpha === this._alpha) {\n return;\n }\n\n // Create new canvas and replace old one\n const oldCanvas = this._canvas;\n this._alpha = alpha;\n // Cloning preserves properties\n this._canvas = this._canvas.cloneNode();\n this._initCanvas();\n this._container.replaceChild(this._canvas, oldCanvas);\n\n // Regenerate char atlas and force a full redraw\n this._refreshCharAtlas(this._colors);\n this.onGridChanged(0, this._bufferService.rows - 1);\n }\n\n /**\n * Refreshes the char atlas, aquiring a new one if necessary.\n * @param colorSet The color set to use for the char atlas.\n */\n private _refreshCharAtlas(colorSet: IColorSet): void {\n if (this._scaledCharWidth <= 0 && this._scaledCharHeight <= 0) {\n return;\n }\n this._charAtlas = acquireCharAtlas(this._optionsService.options, this._rendererId, colorSet, this._scaledCharWidth, this._scaledCharHeight);\n this._charAtlas.warmUp();\n }\n\n public resize(dim: IRenderDimensions): void {\n this._scaledCellWidth = dim.scaledCellWidth;\n this._scaledCellHeight = dim.scaledCellHeight;\n this._scaledCharWidth = dim.scaledCharWidth;\n this._scaledCharHeight = dim.scaledCharHeight;\n this._scaledCharLeft = dim.scaledCharLeft;\n this._scaledCharTop = dim.scaledCharTop;\n this._canvas.width = dim.scaledCanvasWidth;\n this._canvas.height = dim.scaledCanvasHeight;\n this._canvas.style.width = `${dim.canvasWidth}px`;\n this._canvas.style.height = `${dim.canvasHeight}px`;\n\n // Draw the background if this is an opaque layer\n if (!this._alpha) {\n this._clearAll();\n }\n\n this._refreshCharAtlas(this._colors);\n }\n\n public abstract reset(): void;\n\n /**\n * Fills 1+ cells completely. This uses the existing fillStyle on the context.\n * @param x The column to start at.\n * @param y The row to start at\n * @param width The number of columns to fill.\n * @param height The number of rows to fill.\n */\n protected _fillCells(x: number, y: number, width: number, height: number): void {\n this._ctx.fillRect(\n x * this._scaledCellWidth,\n y * this._scaledCellHeight,\n width * this._scaledCellWidth,\n height * this._scaledCellHeight);\n }\n\n /**\n * Fills a 1px line (2px on HDPI) at the bottom of the cell. This uses the\n * existing fillStyle on the context.\n * @param x The column to fill.\n * @param y The row to fill.\n */\n protected _fillBottomLineAtCells(x: number, y: number, width: number = 1): void {\n this._ctx.fillRect(\n x * this._scaledCellWidth,\n (y + 1) * this._scaledCellHeight - window.devicePixelRatio - 1 /* Ensure it's drawn within the cell */,\n width * this._scaledCellWidth,\n window.devicePixelRatio);\n }\n\n /**\n * Fills a 1px line (2px on HDPI) at the left of the cell. This uses the\n * existing fillStyle on the context.\n * @param x The column to fill.\n * @param y The row to fill.\n */\n protected _fillLeftLineAtCell(x: number, y: number, width: number): void {\n this._ctx.fillRect(\n x * this._scaledCellWidth,\n y * this._scaledCellHeight,\n window.devicePixelRatio * width,\n this._scaledCellHeight);\n }\n\n /**\n * Strokes a 1px rectangle (2px on HDPI) around a cell. This uses the existing\n * strokeStyle on the context.\n * @param x The column to fill.\n * @param y The row to fill.\n */\n protected _strokeRectAtCell(x: number, y: number, width: number, height: number): void {\n this._ctx.lineWidth = window.devicePixelRatio;\n this._ctx.strokeRect(\n x * this._scaledCellWidth + window.devicePixelRatio / 2,\n y * this._scaledCellHeight + (window.devicePixelRatio / 2),\n width * this._scaledCellWidth - window.devicePixelRatio,\n (height * this._scaledCellHeight) - window.devicePixelRatio);\n }\n\n /**\n * Clears the entire canvas.\n */\n protected _clearAll(): void {\n if (this._alpha) {\n this._ctx.clearRect(0, 0, this._canvas.width, this._canvas.height);\n } else {\n this._ctx.fillStyle = this._colors.background.css;\n this._ctx.fillRect(0, 0, this._canvas.width, this._canvas.height);\n }\n }\n\n /**\n * Clears 1+ cells completely.\n * @param x The column to start at.\n * @param y The row to start at.\n * @param width The number of columns to clear.\n * @param height The number of rows to clear.\n */\n protected _clearCells(x: number, y: number, width: number, height: number): void {\n if (this._alpha) {\n this._ctx.clearRect(\n x * this._scaledCellWidth,\n y * this._scaledCellHeight,\n width * this._scaledCellWidth,\n height * this._scaledCellHeight);\n } else {\n this._ctx.fillStyle = this._colors.background.css;\n this._ctx.fillRect(\n x * this._scaledCellWidth,\n y * this._scaledCellHeight,\n width * this._scaledCellWidth,\n height * this._scaledCellHeight);\n }\n }\n\n /**\n * Draws a truecolor character at the cell. The character will be clipped to\n * ensure that it fits with the cell, including the cell to the right if it's\n * a wide character. This uses the existing fillStyle on the context.\n * @param cell The cell data for the character to draw.\n * @param x The column to draw at.\n * @param y The row to draw at.\n * @param color The color of the character.\n */\n protected _fillCharTrueColor(cell: CellData, x: number, y: number): void {\n this._ctx.font = this._getFont(false, false);\n this._ctx.textBaseline = 'middle';\n this._clipRow(y);\n this._ctx.fillText(\n cell.getChars(),\n x * this._scaledCellWidth + this._scaledCharLeft,\n y * this._scaledCellHeight + this._scaledCharTop + this._scaledCharHeight / 2);\n }\n\n /**\n * Draws one or more characters at a cell. If possible this will draw using\n * the character atlas to reduce draw time.\n * @param chars The character or characters.\n * @param code The character code.\n * @param width The width of the characters.\n * @param x The column to draw at.\n * @param y The row to draw at.\n * @param fg The foreground color, in the format stored within the attributes.\n * @param bg The background color, in the format stored within the attributes.\n * This is used to validate whether a cached image can be used.\n * @param bold Whether the text is bold.\n */\n protected _drawChars(cell: ICellData, x: number, y: number): void {\n const contrastColor = this._getContrastColor(cell);\n\n // skip cache right away if we draw in RGB\n // Note: to avoid bad runtime JoinedCellData will be skipped\n // in the cache handler itself (atlasDidDraw == false) and\n // fall through to uncached later down below\n if (contrastColor || cell.isFgRGB() || cell.isBgRGB()) {\n this._drawUncachedChars(cell, x, y, contrastColor);\n return;\n }\n\n let fg;\n let bg;\n if (cell.isInverse()) {\n fg = (cell.isBgDefault()) ? INVERTED_DEFAULT_COLOR : cell.getBgColor();\n bg = (cell.isFgDefault()) ? INVERTED_DEFAULT_COLOR : cell.getFgColor();\n } else {\n bg = (cell.isBgDefault()) ? DEFAULT_COLOR : cell.getBgColor();\n fg = (cell.isFgDefault()) ? DEFAULT_COLOR : cell.getFgColor();\n }\n\n const drawInBrightColor = this._optionsService.options.drawBoldTextInBrightColors && cell.isBold() && fg < 8;\n\n fg += drawInBrightColor ? 8 : 0;\n this._currentGlyphIdentifier.chars = cell.getChars() || WHITESPACE_CELL_CHAR;\n this._currentGlyphIdentifier.code = cell.getCode() || WHITESPACE_CELL_CODE;\n this._currentGlyphIdentifier.bg = bg;\n this._currentGlyphIdentifier.fg = fg;\n this._currentGlyphIdentifier.bold = !!cell.isBold();\n this._currentGlyphIdentifier.dim = !!cell.isDim();\n this._currentGlyphIdentifier.italic = !!cell.isItalic();\n const atlasDidDraw = this._charAtlas && this._charAtlas.draw(\n this._ctx,\n this._currentGlyphIdentifier,\n x * this._scaledCellWidth + this._scaledCharLeft,\n y * this._scaledCellHeight + this._scaledCharTop\n );\n\n if (!atlasDidDraw) {\n this._drawUncachedChars(cell, x, y);\n }\n }\n\n /**\n * Draws one or more characters at one or more cells. The character(s) will be\n * clipped to ensure that they fit with the cell(s), including the cell to the\n * right if the last character is a wide character.\n * @param chars The character.\n * @param width The width of the character.\n * @param fg The foreground color, in the format stored within the attributes.\n * @param x The column to draw at.\n * @param y The row to draw at.\n */\n private _drawUncachedChars(cell: ICellData, x: number, y: number, fgOverride?: IColor): void {\n this._ctx.save();\n this._ctx.font = this._getFont(!!cell.isBold(), !!cell.isItalic());\n this._ctx.textBaseline = 'middle';\n\n if (cell.isInverse()) {\n if (fgOverride) {\n this._ctx.fillStyle = fgOverride.css;\n } else if (cell.isBgDefault()) {\n this._ctx.fillStyle = color.opaque(this._colors.background).css;\n } else if (cell.isBgRGB()) {\n this._ctx.fillStyle = `rgb(${AttributeData.toColorRGB(cell.getBgColor()).join(',')})`;\n } else {\n let bg = cell.getBgColor();\n if (this._optionsService.options.drawBoldTextInBrightColors && cell.isBold() && bg < 8) {\n bg += 8;\n }\n this._ctx.fillStyle = this._colors.ansi[bg].css;\n }\n } else {\n if (fgOverride) {\n this._ctx.fillStyle = fgOverride.css;\n } else if (cell.isFgDefault()) {\n this._ctx.fillStyle = this._colors.foreground.css;\n } else if (cell.isFgRGB()) {\n this._ctx.fillStyle = `rgb(${AttributeData.toColorRGB(cell.getFgColor()).join(',')})`;\n } else {\n let fg = cell.getFgColor();\n if (this._optionsService.options.drawBoldTextInBrightColors && cell.isBold() && fg < 8) {\n fg += 8;\n }\n this._ctx.fillStyle = this._colors.ansi[fg].css;\n }\n }\n\n this._clipRow(y);\n\n // Apply alpha to dim the character\n if (cell.isDim()) {\n this._ctx.globalAlpha = DIM_OPACITY;\n }\n // Draw the character\n this._ctx.fillText(\n cell.getChars(),\n x * this._scaledCellWidth + this._scaledCharLeft,\n y * this._scaledCellHeight + this._scaledCharTop + this._scaledCharHeight / 2);\n this._ctx.restore();\n }\n\n /**\n * Clips a row to ensure no pixels will be drawn outside the cells in the row.\n * @param y The row to clip.\n */\n private _clipRow(y: number): void {\n this._ctx.beginPath();\n this._ctx.rect(\n 0,\n y * this._scaledCellHeight,\n this._bufferService.cols * this._scaledCellWidth,\n this._scaledCellHeight);\n this._ctx.clip();\n }\n\n /**\n * Gets the current font.\n * @param isBold If we should use the bold fontWeight.\n */\n protected _getFont(isBold: boolean, isItalic: boolean): string {\n const fontWeight = isBold ? this._optionsService.options.fontWeightBold : this._optionsService.options.fontWeight;\n const fontStyle = isItalic ? 'italic' : '';\n\n return `${fontStyle} ${fontWeight} ${this._optionsService.options.fontSize * window.devicePixelRatio}px ${this._optionsService.options.fontFamily}`;\n }\n\n private _getContrastColor(cell: CellData): IColor | undefined {\n if (this._optionsService.options.minimumContrastRatio === 1) {\n return undefined;\n }\n\n // Try get from cache first\n const adjustedColor = this._colors.contrastCache.getColor(cell.bg, cell.fg);\n if (adjustedColor !== undefined) {\n return adjustedColor || undefined;\n }\n\n let fgColor = cell.getFgColor();\n let fgColorMode = cell.getFgColorMode();\n let bgColor = cell.getBgColor();\n let bgColorMode = cell.getBgColorMode();\n const isInverse = !!cell.isInverse();\n const isBold = !!cell.isInverse();\n if (isInverse) {\n const temp = fgColor;\n fgColor = bgColor;\n bgColor = temp;\n const temp2 = fgColorMode;\n fgColorMode = bgColorMode;\n bgColorMode = temp2;\n }\n\n const bgRgba = this._resolveBackgroundRgba(bgColorMode, bgColor, isInverse);\n const fgRgba = this._resolveForegroundRgba(fgColorMode, fgColor, isInverse, isBold);\n const result = rgba.ensureContrastRatio(bgRgba, fgRgba, this._optionsService.options.minimumContrastRatio);\n\n if (!result) {\n this._colors.contrastCache.setColor(cell.bg, cell.fg, null);\n return undefined;\n }\n\n const color: IColor = {\n css: channels.toCss(\n (result >> 24) & 0xFF,\n (result >> 16) & 0xFF,\n (result >> 8) & 0xFF\n ),\n rgba: result\n };\n this._colors.contrastCache.setColor(cell.bg, cell.fg, color);\n\n return color;\n }\n\n private _resolveBackgroundRgba(bgColorMode: number, bgColor: number, inverse: boolean): number {\n switch (bgColorMode) {\n case Attributes.CM_P16:\n case Attributes.CM_P256:\n return this._colors.ansi[bgColor].rgba;\n case Attributes.CM_RGB:\n return bgColor << 8;\n case Attributes.CM_DEFAULT:\n default:\n if (inverse) {\n return this._colors.foreground.rgba;\n }\n return this._colors.background.rgba;\n }\n }\n\n private _resolveForegroundRgba(fgColorMode: number, fgColor: number, inverse: boolean, bold: boolean): number {\n switch (fgColorMode) {\n case Attributes.CM_P16:\n case Attributes.CM_P256:\n if (this._optionsService.options.drawBoldTextInBrightColors && bold && fgColor < 8) {\n fgColor += 8;\n }\n return this._colors.ansi[fgColor].rgba;\n case Attributes.CM_RGB:\n return fgColor << 8;\n case Attributes.CM_DEFAULT:\n default:\n if (inverse) {\n return this._colors.background.rgba;\n }\n return this._colors.foreground.rgba;\n }\n }\n}\n\n","/**\n * Copyright (c) 2019 The xterm.js authors. All rights reserved.\n * @license MIT\n *\n * This was heavily inspired from microsoft/vscode's dependency injection system (MIT).\n */\n/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IServiceIdentifier } from 'common/services/Services';\n\nconst DI_TARGET = 'di$target';\nconst DI_DEPENDENCIES = 'di$dependencies';\n\nexport const serviceRegistry: Map> = new Map();\n\nexport function getServiceDependencies(ctor: any): { id: IServiceIdentifier, index: number, optional: boolean }[] {\n return ctor[DI_DEPENDENCIES] || [];\n}\n\nexport function createDecorator(id: string): IServiceIdentifier {\n if (serviceRegistry.has(id)) {\n return serviceRegistry.get(id)!;\n }\n\n const decorator = function (target: Function, key: string, index: number): any {\n if (arguments.length !== 3) {\n throw new Error('@IServiceName-decorator can only be used to decorate a parameter');\n }\n\n storeServiceDependency(decorator, target, index);\n };\n\n decorator.toString = () => id;\n\n serviceRegistry.set(id, decorator);\n return decorator;\n}\n\nfunction storeServiceDependency(id: Function, target: Function, index: number): void {\n if ((target as any)[DI_TARGET] === target) {\n (target as any)[DI_DEPENDENCIES].push({ id, index });\n } else {\n (target as any)[DI_DEPENDENCIES] = [{ id, index }];\n (target as any)[DI_TARGET] = target;\n }\n}\n","/**\n * Copyright (c) 2018 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nexport type TypedArray = Uint8Array | Uint16Array | Uint32Array | Uint8ClampedArray\n | Int8Array | Int16Array | Int32Array\n | Float32Array | Float64Array;\n\n\n/**\n * polyfill for TypedArray.fill\n * This is needed to support .fill in all safari versions and IE 11.\n */\nexport function fill(array: T, value: number, start?: number, end?: number): T {\n // all modern engines that support .fill\n if (array.fill) {\n return array.fill(value, start, end) as T;\n }\n return fillFallback(array, value, start, end);\n}\n\nexport function fillFallback(array: T, value: number, start: number = 0, end: number = array.length): T {\n // safari and IE 11\n // since IE 11 does not support Array.prototype.fill either\n // we cannot use the suggested polyfill from MDN\n // instead we simply fall back to looping\n if (start >= array.length) {\n return array;\n }\n start = (array.length + start) % array.length;\n if (end >= array.length) {\n end = array.length;\n } else {\n end = (array.length + end) % array.length;\n }\n for (let i = start; i < end; ++i) {\n array[i] = value;\n }\n return array;\n}\n\n/**\n * Concat two typed arrays `a` and `b`.\n * Returns a new typed array.\n */\nexport function concat(a: T, b: T): T {\n const result = new (a.constructor as any)(a.length + b.length);\n result.set(a);\n result.set(b, a.length);\n return result;\n}\n","/**\n * Copyright (c) 2018 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { CharData, IBufferLine, ICellData, IAttributeData } from 'common/Types';\nimport { stringFromCodePoint } from 'common/input/TextDecoder';\nimport { CHAR_DATA_CHAR_INDEX, CHAR_DATA_WIDTH_INDEX, CHAR_DATA_ATTR_INDEX, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE, WHITESPACE_CELL_CHAR, Content } from 'common/buffer/Constants';\nimport { CellData } from 'common/buffer/CellData';\nimport { AttributeData } from 'common/buffer/AttributeData';\n\n/**\n * buffer memory layout:\n *\n * | uint32_t | uint32_t | uint32_t |\n * | `content` | `FG` | `BG` |\n * | wcwidth(2) comb(1) codepoint(21) | flags(8) R(8) G(8) B(8) | flags(8) R(8) G(8) B(8) |\n */\n\n\n/** typed array slots taken by one cell */\nconst CELL_SIZE = 3;\n\n/**\n * Cell member indices.\n *\n * Direct access:\n * `content = data[column * CELL_SIZE + Cell.CONTENT];`\n * `fg = data[column * CELL_SIZE + Cell.FG];`\n * `bg = data[column * CELL_SIZE + Cell.BG];`\n */\nconst enum Cell {\n CONTENT = 0,\n FG = 1, // currently simply holds all known attrs\n BG = 2 // currently unused\n}\n\nexport const DEFAULT_ATTR_DATA = Object.freeze(new AttributeData());\n\n/**\n * Typed array based bufferline implementation.\n *\n * There are 2 ways to insert data into the cell buffer:\n * - `setCellFromCodepoint` + `addCodepointToCell`\n * Use these for data that is already UTF32.\n * Used during normal input in `InputHandler` for faster buffer access.\n * - `setCell`\n * This method takes a CellData object and stores the data in the buffer.\n * Use `CellData.fromCharData` to create the CellData object (e.g. from JS string).\n *\n * To retrieve data from the buffer use either one of the primitive methods\n * (if only one particular value is needed) or `loadCell`. For `loadCell` in a loop\n * memory allocs / GC pressure can be greatly reduced by reusing the CellData object.\n */\nexport class BufferLine implements IBufferLine {\n protected _data: Uint32Array;\n protected _combined: {[index: number]: string} = {};\n public length: number;\n\n constructor(cols: number, fillCellData?: ICellData, public isWrapped: boolean = false) {\n this._data = new Uint32Array(cols * CELL_SIZE);\n const cell = fillCellData || CellData.fromCharData([0, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]);\n for (let i = 0; i < cols; ++i) {\n this.setCell(i, cell);\n }\n this.length = cols;\n }\n\n /**\n * Get cell data CharData.\n * @deprecated\n */\n public get(index: number): CharData {\n const content = this._data[index * CELL_SIZE + Cell.CONTENT];\n const cp = content & Content.CODEPOINT_MASK;\n return [\n this._data[index * CELL_SIZE + Cell.FG],\n (content & Content.IS_COMBINED_MASK)\n ? this._combined[index]\n : (cp) ? stringFromCodePoint(cp) : '',\n content >> Content.WIDTH_SHIFT,\n (content & Content.IS_COMBINED_MASK)\n ? this._combined[index].charCodeAt(this._combined[index].length - 1)\n : cp\n ];\n }\n\n /**\n * Set cell data from CharData.\n * @deprecated\n */\n public set(index: number, value: CharData): void {\n this._data[index * CELL_SIZE + Cell.FG] = value[CHAR_DATA_ATTR_INDEX];\n if (value[CHAR_DATA_CHAR_INDEX].length > 1) {\n this._combined[index] = value[1];\n this._data[index * CELL_SIZE + Cell.CONTENT] = index | Content.IS_COMBINED_MASK | (value[CHAR_DATA_WIDTH_INDEX] << Content.WIDTH_SHIFT);\n } else {\n this._data[index * CELL_SIZE + Cell.CONTENT] = value[CHAR_DATA_CHAR_INDEX].charCodeAt(0) | (value[CHAR_DATA_WIDTH_INDEX] << Content.WIDTH_SHIFT);\n }\n }\n\n /**\n * primitive getters\n * use these when only one value is needed, otherwise use `loadCell`\n */\n public getWidth(index: number): number {\n return this._data[index * CELL_SIZE + Cell.CONTENT] >> Content.WIDTH_SHIFT;\n }\n\n /** Test whether content has width. */\n public hasWidth(index: number): number {\n return this._data[index * CELL_SIZE + Cell.CONTENT] & Content.WIDTH_MASK;\n }\n\n /** Get FG cell component. */\n public getFg(index: number): number {\n return this._data[index * CELL_SIZE + Cell.FG];\n }\n\n /** Get BG cell component. */\n public getBg(index: number): number {\n return this._data[index * CELL_SIZE + Cell.BG];\n }\n\n /**\n * Test whether contains any chars.\n * Basically an empty has no content, but other cells might differ in FG/BG\n * from real empty cells.\n * */\n public hasContent(index: number): number {\n return this._data[index * CELL_SIZE + Cell.CONTENT] & Content.HAS_CONTENT_MASK;\n }\n\n /**\n * Get codepoint of the cell.\n * To be in line with `code` in CharData this either returns\n * a single UTF32 codepoint or the last codepoint of a combined string.\n */\n public getCodePoint(index: number): number {\n const content = this._data[index * CELL_SIZE + Cell.CONTENT];\n if (content & Content.IS_COMBINED_MASK) {\n return this._combined[index].charCodeAt(this._combined[index].length - 1);\n }\n return content & Content.CODEPOINT_MASK;\n }\n\n /** Test whether the cell contains a combined string. */\n public isCombined(index: number): number {\n return this._data[index * CELL_SIZE + Cell.CONTENT] & Content.IS_COMBINED_MASK;\n }\n\n /** Returns the string content of the cell. */\n public getString(index: number): string {\n const content = this._data[index * CELL_SIZE + Cell.CONTENT];\n if (content & Content.IS_COMBINED_MASK) {\n return this._combined[index];\n }\n if (content & Content.CODEPOINT_MASK) {\n return stringFromCodePoint(content & Content.CODEPOINT_MASK);\n }\n // return empty string for empty cells\n return '';\n }\n\n /**\n * Load data at `index` into `cell`. This is used to access cells in a way that's more friendly\n * to GC as it significantly reduced the amount of new objects/references needed.\n */\n public loadCell(index: number, cell: ICellData): ICellData {\n const startIndex = index * CELL_SIZE;\n cell.content = this._data[startIndex + Cell.CONTENT];\n cell.fg = this._data[startIndex + Cell.FG];\n cell.bg = this._data[startIndex + Cell.BG];\n if (cell.content & Content.IS_COMBINED_MASK) {\n cell.combinedData = this._combined[index];\n }\n return cell;\n }\n\n /**\n * Set data at `index` to `cell`.\n */\n public setCell(index: number, cell: ICellData): void {\n if (cell.content & Content.IS_COMBINED_MASK) {\n this._combined[index] = cell.combinedData;\n }\n this._data[index * CELL_SIZE + Cell.CONTENT] = cell.content;\n this._data[index * CELL_SIZE + Cell.FG] = cell.fg;\n this._data[index * CELL_SIZE + Cell.BG] = cell.bg;\n }\n\n /**\n * Set cell data from input handler.\n * Since the input handler see the incoming chars as UTF32 codepoints,\n * it gets an optimized access method.\n */\n public setCellFromCodePoint(index: number, codePoint: number, width: number, fg: number, bg: number): void {\n this._data[index * CELL_SIZE + Cell.CONTENT] = codePoint | (width << Content.WIDTH_SHIFT);\n this._data[index * CELL_SIZE + Cell.FG] = fg;\n this._data[index * CELL_SIZE + Cell.BG] = bg;\n }\n\n /**\n * Add a codepoint to a cell from input handler.\n * During input stage combining chars with a width of 0 follow and stack\n * onto a leading char. Since we already set the attrs\n * by the previous `setDataFromCodePoint` call, we can omit it here.\n */\n public addCodepointToCell(index: number, codePoint: number): void {\n let content = this._data[index * CELL_SIZE + Cell.CONTENT];\n if (content & Content.IS_COMBINED_MASK) {\n // we already have a combined string, simply add\n this._combined[index] += stringFromCodePoint(codePoint);\n } else {\n if (content & Content.CODEPOINT_MASK) {\n // normal case for combining chars:\n // - move current leading char + new one into combined string\n // - set combined flag\n this._combined[index] = stringFromCodePoint(content & Content.CODEPOINT_MASK) + stringFromCodePoint(codePoint);\n content &= ~Content.CODEPOINT_MASK; // set codepoint in buffer to 0\n content |= Content.IS_COMBINED_MASK;\n } else {\n // should not happen - we actually have no data in the cell yet\n // simply set the data in the cell buffer with a width of 1\n content = codePoint | (1 << Content.WIDTH_SHIFT);\n }\n this._data[index * CELL_SIZE + Cell.CONTENT] = content;\n }\n }\n\n public insertCells(pos: number, n: number, fillCellData: ICellData, eraseAttr?: IAttributeData): void {\n pos %= this.length;\n\n // handle fullwidth at pos: reset cell one to the left if pos is second cell of a wide char\n if (pos && this.getWidth(pos - 1) === 2) {\n this.setCellFromCodePoint(pos - 1, 0, 1, eraseAttr?.fg || 0, eraseAttr?.bg || 0);\n }\n\n if (n < this.length - pos) {\n const cell = new CellData();\n for (let i = this.length - pos - n - 1; i >= 0; --i) {\n this.setCell(pos + n + i, this.loadCell(pos + i, cell));\n }\n for (let i = 0; i < n; ++i) {\n this.setCell(pos + i, fillCellData);\n }\n } else {\n for (let i = pos; i < this.length; ++i) {\n this.setCell(i, fillCellData);\n }\n }\n\n // handle fullwidth at line end: reset last cell if it is first cell of a wide char\n if (this.getWidth(this.length - 1) === 2) {\n this.setCellFromCodePoint(this.length - 1, 0, 1, eraseAttr?.fg || 0, eraseAttr?.bg || 0);\n }\n }\n\n public deleteCells(pos: number, n: number, fillCellData: ICellData, eraseAttr?: IAttributeData): void {\n pos %= this.length;\n if (n < this.length - pos) {\n const cell = new CellData();\n for (let i = 0; i < this.length - pos - n; ++i) {\n this.setCell(pos + i, this.loadCell(pos + n + i, cell));\n }\n for (let i = this.length - n; i < this.length; ++i) {\n this.setCell(i, fillCellData);\n }\n } else {\n for (let i = pos; i < this.length; ++i) {\n this.setCell(i, fillCellData);\n }\n }\n\n // handle fullwidth at pos:\n // - reset pos-1 if wide char\n // - reset pos if width==0 (previous second cell of a wide char)\n if (pos && this.getWidth(pos - 1) === 2) {\n this.setCellFromCodePoint(pos - 1, 0, 1, eraseAttr?.fg || 0, eraseAttr?.bg || 0);\n }\n if (this.getWidth(pos) === 0 && !this.hasContent(pos)) {\n this.setCellFromCodePoint(pos, 0, 1, eraseAttr?.fg || 0, eraseAttr?.bg || 0);\n }\n }\n\n public replaceCells(start: number, end: number, fillCellData: ICellData, eraseAttr?: IAttributeData): void {\n // handle fullwidth at start: reset cell one to the left if start is second cell of a wide char\n if (start && this.getWidth(start - 1) === 2) {\n this.setCellFromCodePoint(start - 1, 0, 1, eraseAttr?.fg || 0, eraseAttr?.bg || 0);\n }\n // handle fullwidth at last cell + 1: reset to empty cell if it is second part of a wide char\n if (end < this.length && this.getWidth(end - 1) === 2) {\n this.setCellFromCodePoint(end, 0, 1, eraseAttr?.fg || 0, eraseAttr?.bg || 0);\n }\n\n while (start < end && start < this.length) {\n this.setCell(start++, fillCellData);\n }\n }\n\n public resize(cols: number, fillCellData: ICellData): void {\n if (cols === this.length) {\n return;\n }\n if (cols > this.length) {\n const data = new Uint32Array(cols * CELL_SIZE);\n if (this.length) {\n if (cols * CELL_SIZE < this._data.length) {\n data.set(this._data.subarray(0, cols * CELL_SIZE));\n } else {\n data.set(this._data);\n }\n }\n this._data = data;\n for (let i = this.length; i < cols; ++i) {\n this.setCell(i, fillCellData);\n }\n } else {\n if (cols) {\n const data = new Uint32Array(cols * CELL_SIZE);\n data.set(this._data.subarray(0, cols * CELL_SIZE));\n this._data = data;\n // Remove any cut off combined data\n const keys = Object.keys(this._combined);\n for (let i = 0; i < keys.length; i++) {\n const key = parseInt(keys[i], 10);\n if (key >= cols) {\n delete this._combined[key];\n }\n }\n } else {\n this._data = new Uint32Array(0);\n this._combined = {};\n }\n }\n this.length = cols;\n }\n\n /** fill a line with fillCharData */\n public fill(fillCellData: ICellData): void {\n this._combined = {};\n for (let i = 0; i < this.length; ++i) {\n this.setCell(i, fillCellData);\n }\n }\n\n /** alter to a full copy of line */\n public copyFrom(line: BufferLine): void {\n if (this.length !== line.length) {\n this._data = new Uint32Array(line._data);\n } else {\n // use high speed copy if lengths are equal\n this._data.set(line._data);\n }\n this.length = line.length;\n this._combined = {};\n for (const el in line._combined) {\n this._combined[el] = line._combined[el];\n }\n this.isWrapped = line.isWrapped;\n }\n\n /** create a new clone */\n public clone(): IBufferLine {\n const newLine = new BufferLine(0);\n newLine._data = new Uint32Array(this._data);\n newLine.length = this.length;\n for (const el in this._combined) {\n newLine._combined[el] = this._combined[el];\n }\n newLine.isWrapped = this.isWrapped;\n return newLine;\n }\n\n public getTrimmedLength(): number {\n for (let i = this.length - 1; i >= 0; --i) {\n if ((this._data[i * CELL_SIZE + Cell.CONTENT] & Content.HAS_CONTENT_MASK)) {\n return i + (this._data[i * CELL_SIZE + Cell.CONTENT] >> Content.WIDTH_SHIFT);\n }\n }\n return 0;\n }\n\n public copyCellsFrom(src: BufferLine, srcCol: number, destCol: number, length: number, applyInReverse: boolean): void {\n const srcData = src._data;\n if (applyInReverse) {\n for (let cell = length - 1; cell >= 0; cell--) {\n for (let i = 0; i < CELL_SIZE; i++) {\n this._data[(destCol + cell) * CELL_SIZE + i] = srcData[(srcCol + cell) * CELL_SIZE + i];\n }\n }\n } else {\n for (let cell = 0; cell < length; cell++) {\n for (let i = 0; i < CELL_SIZE; i++) {\n this._data[(destCol + cell) * CELL_SIZE + i] = srcData[(srcCol + cell) * CELL_SIZE + i];\n }\n }\n }\n\n // Move any combined data over as needed\n const srcCombinedKeys = Object.keys(src._combined);\n for (let i = 0; i < srcCombinedKeys.length; i++) {\n const key = parseInt(srcCombinedKeys[i], 10);\n if (key >= srcCol) {\n this._combined[key - srcCol + destCol] = src._combined[key];\n }\n }\n }\n\n public translateToString(trimRight: boolean = false, startCol: number = 0, endCol: number = this.length): string {\n if (trimRight) {\n endCol = Math.min(endCol, this.getTrimmedLength());\n }\n let result = '';\n while (startCol < endCol) {\n const content = this._data[startCol * CELL_SIZE + Cell.CONTENT];\n const cp = content & Content.CODEPOINT_MASK;\n result += (content & Content.IS_COMBINED_MASK) ? this._combined[startCol] : (cp) ? stringFromCodePoint(cp) : WHITESPACE_CELL_CHAR;\n startCol += (content >> Content.WIDTH_SHIFT) || 1; // always advance by 1\n }\n return result;\n }\n}\n","/**\n * Copyright (c) 2018 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nexport let promptLabel = 'Terminal input';\nexport let tooMuchOutput = 'Too much output to announce, navigate to rows manually to read';\n","/**\n * Copyright (c) 2016 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { ICharset } from 'common/Types';\n\n/**\n * The character sets supported by the terminal. These enable several languages\n * to be represented within the terminal with only 8-bit encoding. See ISO 2022\n * for a discussion on character sets. Only VT100 character sets are supported.\n */\nexport const CHARSETS: { [key: string]: ICharset | null } = {};\n\n/**\n * The default character set, US.\n */\nexport const DEFAULT_CHARSET: ICharset | null = CHARSETS['B'];\n\n/**\n * DEC Special Character and Line Drawing Set.\n * Reference: http://vt100.net/docs/vt102-ug/table5-13.html\n * A lot of curses apps use this if they see TERM=xterm.\n * testing: echo -e '\\e(0a\\e(B'\n * The xterm output sometimes seems to conflict with the\n * reference above. xterm seems in line with the reference\n * when running vttest however.\n * The table below now uses xterm's output from vttest.\n */\nCHARSETS['0'] = {\n '`': '\\u25c6', // '◆'\n 'a': '\\u2592', // '▒'\n 'b': '\\u2409', // '␉' (HT)\n 'c': '\\u240c', // '␌' (FF)\n 'd': '\\u240d', // '␍' (CR)\n 'e': '\\u240a', // '␊' (LF)\n 'f': '\\u00b0', // '°'\n 'g': '\\u00b1', // '±'\n 'h': '\\u2424', // '␤' (NL)\n 'i': '\\u240b', // '␋' (VT)\n 'j': '\\u2518', // '┘'\n 'k': '\\u2510', // '┐'\n 'l': '\\u250c', // '┌'\n 'm': '\\u2514', // '└'\n 'n': '\\u253c', // '┼'\n 'o': '\\u23ba', // '⎺'\n 'p': '\\u23bb', // '⎻'\n 'q': '\\u2500', // '─'\n 'r': '\\u23bc', // '⎼'\n 's': '\\u23bd', // '⎽'\n 't': '\\u251c', // '├'\n 'u': '\\u2524', // '┤'\n 'v': '\\u2534', // '┴'\n 'w': '\\u252c', // '┬'\n 'x': '\\u2502', // '│'\n 'y': '\\u2264', // '≤'\n 'z': '\\u2265', // '≥'\n '{': '\\u03c0', // 'π'\n '|': '\\u2260', // '≠'\n '}': '\\u00a3', // '£'\n '~': '\\u00b7' // '·'\n};\n\n/**\n * British character set\n * ESC (A\n * Reference: http://vt100.net/docs/vt220-rm/table2-5.html\n */\nCHARSETS['A'] = {\n '#': '£'\n};\n\n/**\n * United States character set\n * ESC (B\n */\nCHARSETS['B'] = null;\n\n/**\n * Dutch character set\n * ESC (4\n * Reference: http://vt100.net/docs/vt220-rm/table2-6.html\n */\nCHARSETS['4'] = {\n '#': '£',\n '@': '¾',\n '[': 'ij',\n '\\\\': '½',\n ']': '|',\n '{': '¨',\n '|': 'f',\n '}': '¼',\n '~': '´'\n};\n\n/**\n * Finnish character set\n * ESC (C or ESC (5\n * Reference: http://vt100.net/docs/vt220-rm/table2-7.html\n */\nCHARSETS['C'] =\nCHARSETS['5'] = {\n '[': 'Ä',\n '\\\\': 'Ö',\n ']': 'Å',\n '^': 'Ü',\n '`': 'é',\n '{': 'ä',\n '|': 'ö',\n '}': 'å',\n '~': 'ü'\n};\n\n/**\n * French character set\n * ESC (R\n * Reference: http://vt100.net/docs/vt220-rm/table2-8.html\n */\nCHARSETS['R'] = {\n '#': '£',\n '@': 'à',\n '[': '°',\n '\\\\': 'ç',\n ']': '§',\n '{': 'é',\n '|': 'ù',\n '}': 'è',\n '~': '¨'\n};\n\n/**\n * French Canadian character set\n * ESC (Q\n * Reference: http://vt100.net/docs/vt220-rm/table2-9.html\n */\nCHARSETS['Q'] = {\n '@': 'à',\n '[': 'â',\n '\\\\': 'ç',\n ']': 'ê',\n '^': 'î',\n '`': 'ô',\n '{': 'é',\n '|': 'ù',\n '}': 'è',\n '~': 'û'\n};\n\n/**\n * German character set\n * ESC (K\n * Reference: http://vt100.net/docs/vt220-rm/table2-10.html\n */\nCHARSETS['K'] = {\n '@': '§',\n '[': 'Ä',\n '\\\\': 'Ö',\n ']': 'Ü',\n '{': 'ä',\n '|': 'ö',\n '}': 'ü',\n '~': 'ß'\n};\n\n/**\n * Italian character set\n * ESC (Y\n * Reference: http://vt100.net/docs/vt220-rm/table2-11.html\n */\nCHARSETS['Y'] = {\n '#': '£',\n '@': '§',\n '[': '°',\n '\\\\': 'ç',\n ']': 'é',\n '`': 'ù',\n '{': 'à',\n '|': 'ò',\n '}': 'è',\n '~': 'ì'\n};\n\n/**\n * Norwegian/Danish character set\n * ESC (E or ESC (6\n * Reference: http://vt100.net/docs/vt220-rm/table2-12.html\n */\nCHARSETS['E'] =\nCHARSETS['6'] = {\n '@': 'Ä',\n '[': 'Æ',\n '\\\\': 'Ø',\n ']': 'Å',\n '^': 'Ü',\n '`': 'ä',\n '{': 'æ',\n '|': 'ø',\n '}': 'å',\n '~': 'ü'\n};\n\n/**\n * Spanish character set\n * ESC (Z\n * Reference: http://vt100.net/docs/vt220-rm/table2-13.html\n */\nCHARSETS['Z'] = {\n '#': '£',\n '@': '§',\n '[': '¡',\n '\\\\': 'Ñ',\n ']': '¿',\n '{': '°',\n '|': 'ñ',\n '}': 'ç'\n};\n\n/**\n * Swedish character set\n * ESC (H or ESC (7\n * Reference: http://vt100.net/docs/vt220-rm/table2-14.html\n */\nCHARSETS['H'] =\nCHARSETS['7'] = {\n '@': 'É',\n '[': 'Ä',\n '\\\\': 'Ö',\n ']': 'Å',\n '^': 'Ü',\n '`': 'é',\n '{': 'ä',\n '|': 'ö',\n '}': 'å',\n '~': 'ü'\n};\n\n/**\n * Swiss character set\n * ESC (=\n * Reference: http://vt100.net/docs/vt220-rm/table2-15.html\n */\nCHARSETS['='] = {\n '#': 'ù',\n '@': 'à',\n '[': 'é',\n '\\\\': 'ç',\n ']': 'ê',\n '^': 'î',\n '_': 'è',\n '`': 'ô',\n '{': 'ä',\n '|': 'ö',\n '}': 'ü',\n '~': 'û'\n};\n","/**\n * Copyright (c) 2019 The xterm.js authors. All rights reserved.\n * @license MIT\n */\nimport { IParams, ParamsArray } from 'common/parser/Types';\n\n// max value supported for a single param/subparam (clamped to positive int32 range)\nconst MAX_VALUE = 0x7FFFFFFF;\n// max allowed subparams for a single sequence (hardcoded limitation)\nconst MAX_SUBPARAMS = 256;\n\n/**\n * Params storage class.\n * This type is used by the parser to accumulate sequence parameters and sub parameters\n * and transmit them to the input handler actions.\n *\n * NOTES:\n * - params object for action handlers is borrowed, use `.toArray` or `.clone` to get a copy\n * - never read beyond `params.length - 1` (likely to contain arbitrary data)\n * - `.getSubParams` returns a borrowed typed array, use `.getSubParamsAll` for cloned sub params\n * - hardcoded limitations:\n * - max. value for a single (sub) param is 2^31 - 1 (greater values are clamped to that)\n * - max. 256 sub params possible\n * - negative values are not allowed beside -1 (placeholder for default value)\n *\n * About ZDM (Zero Default Mode):\n * ZDM is not orchestrated by this class. If the parser is in ZDM,\n * it should add 0 for empty params, otherwise -1. This does not apply\n * to subparams, empty subparams should always be added with -1.\n */\nexport class Params implements IParams {\n // params store and length\n public params: Int32Array;\n public length: number;\n\n // sub params store and length\n protected _subParams: Int32Array;\n protected _subParamsLength: number;\n\n // sub params offsets from param: param idx --> [start, end] offset\n private _subParamsIdx: Uint16Array;\n private _rejectDigits: boolean;\n private _rejectSubDigits: boolean;\n private _digitIsSub: boolean;\n\n /**\n * Create a `Params` type from JS array representation.\n */\n public static fromArray(values: ParamsArray): Params {\n const params = new Params();\n if (!values.length) {\n return params;\n }\n // skip leading sub params\n for (let i = (values[0] instanceof Array) ? 1 : 0; i < values.length; ++i) {\n const value = values[i];\n if (value instanceof Array) {\n for (let k = 0; k < value.length; ++k) {\n params.addSubParam(value[k]);\n }\n } else {\n params.addParam(value);\n }\n }\n return params;\n }\n\n /**\n * @param maxLength max length of storable parameters\n * @param maxSubParamsLength max length of storable sub parameters\n */\n constructor(public maxLength: number = 32, public maxSubParamsLength: number = 32) {\n if (maxSubParamsLength > MAX_SUBPARAMS) {\n throw new Error('maxSubParamsLength must not be greater than 256');\n }\n this.params = new Int32Array(maxLength);\n this.length = 0;\n this._subParams = new Int32Array(maxSubParamsLength);\n this._subParamsLength = 0;\n this._subParamsIdx = new Uint16Array(maxLength);\n this._rejectDigits = false;\n this._rejectSubDigits = false;\n this._digitIsSub = false;\n }\n\n /**\n * Clone object.\n */\n public clone(): Params {\n const newParams = new Params(this.maxLength, this.maxSubParamsLength);\n newParams.params.set(this.params);\n newParams.length = this.length;\n newParams._subParams.set(this._subParams);\n newParams._subParamsLength = this._subParamsLength;\n newParams._subParamsIdx.set(this._subParamsIdx);\n newParams._rejectDigits = this._rejectDigits;\n newParams._rejectSubDigits = this._rejectSubDigits;\n newParams._digitIsSub = this._digitIsSub;\n return newParams;\n }\n\n /**\n * Get a JS array representation of the current parameters and sub parameters.\n * The array is structured as follows:\n * sequence: \"1;2:3:4;5::6\"\n * array : [1, 2, [3, 4], 5, [-1, 6]]\n */\n public toArray(): ParamsArray {\n const res: ParamsArray = [];\n for (let i = 0; i < this.length; ++i) {\n res.push(this.params[i]);\n const start = this._subParamsIdx[i] >> 8;\n const end = this._subParamsIdx[i] & 0xFF;\n if (end - start > 0) {\n res.push(Array.prototype.slice.call(this._subParams, start, end));\n }\n }\n return res;\n }\n\n /**\n * Reset to initial empty state.\n */\n public reset(): void {\n this.length = 0;\n this._subParamsLength = 0;\n this._rejectDigits = false;\n this._rejectSubDigits = false;\n this._digitIsSub = false;\n }\n\n /**\n * Add a parameter value.\n * `Params` only stores up to `maxLength` parameters, any later\n * parameter will be ignored.\n * Note: VT devices only stored up to 16 values, xterm seems to\n * store up to 30.\n */\n public addParam(value: number): void {\n this._digitIsSub = false;\n if (this.length >= this.maxLength) {\n this._rejectDigits = true;\n return;\n }\n if (value < -1) {\n throw new Error('values lesser than -1 are not allowed');\n }\n this._subParamsIdx[this.length] = this._subParamsLength << 8 | this._subParamsLength;\n this.params[this.length++] = value > MAX_VALUE ? MAX_VALUE : value;\n }\n\n /**\n * Add a sub parameter value.\n * The sub parameter is automatically associated with the last parameter value.\n * Thus it is not possible to add a subparameter without any parameter added yet.\n * `Params` only stores up to `subParamsLength` sub parameters, any later\n * sub parameter will be ignored.\n */\n public addSubParam(value: number): void {\n this._digitIsSub = true;\n if (!this.length) {\n return;\n }\n if (this._rejectDigits || this._subParamsLength >= this.maxSubParamsLength) {\n this._rejectSubDigits = true;\n return;\n }\n if (value < -1) {\n throw new Error('values lesser than -1 are not allowed');\n }\n this._subParams[this._subParamsLength++] = value > MAX_VALUE ? MAX_VALUE : value;\n this._subParamsIdx[this.length - 1]++;\n }\n\n /**\n * Whether parameter at index `idx` has sub parameters.\n */\n public hasSubParams(idx: number): boolean {\n return ((this._subParamsIdx[idx] & 0xFF) - (this._subParamsIdx[idx] >> 8) > 0);\n }\n\n /**\n * Return sub parameters for parameter at index `idx`.\n * Note: The values are borrowed, thus you need to copy\n * the values if you need to hold them in nonlocal scope.\n */\n public getSubParams(idx: number): Int32Array | null {\n const start = this._subParamsIdx[idx] >> 8;\n const end = this._subParamsIdx[idx] & 0xFF;\n if (end - start > 0) {\n return this._subParams.subarray(start, end);\n }\n return null;\n }\n\n /**\n * Return all sub parameters as {idx: subparams} mapping.\n * Note: The values are not borrowed.\n */\n public getSubParamsAll(): {[idx: number]: Int32Array} {\n const result: {[idx: number]: Int32Array} = {};\n for (let i = 0; i < this.length; ++i) {\n const start = this._subParamsIdx[i] >> 8;\n const end = this._subParamsIdx[i] & 0xFF;\n if (end - start > 0) {\n result[i] = this._subParams.slice(start, end);\n }\n }\n return result;\n }\n\n /**\n * Add a single digit value to current parameter.\n * This is used by the parser to account digits on a char by char basis.\n */\n public addDigit(value: number): void {\n let length;\n if (this._rejectDigits\n || !(length = this._digitIsSub ? this._subParamsLength : this.length)\n || (this._digitIsSub && this._rejectSubDigits)\n ) {\n return;\n }\n\n const store = this._digitIsSub ? this._subParams : this.params;\n const cur = store[length - 1];\n store[length - 1] = ~cur ? Math.min(cur * 10 + value, MAX_VALUE) : value;\n }\n}\n","/**\n * Copyright (c) 2019 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { IOscHandler, IHandlerCollection, OscFallbackHandlerType, IOscParser } from 'common/parser/Types';\nimport { OscState, PAYLOAD_LIMIT } from 'common/parser/Constants';\nimport { utf32ToString } from 'common/input/TextDecoder';\nimport { IDisposable } from 'common/Types';\n\n\nexport class OscParser implements IOscParser {\n private _state = OscState.START;\n private _id = -1;\n private _handlers: IHandlerCollection = Object.create(null);\n private _handlerFb: OscFallbackHandlerType = () => { };\n\n public addHandler(ident: number, handler: IOscHandler): IDisposable {\n if (this._handlers[ident] === undefined) {\n this._handlers[ident] = [];\n }\n const handlerList = this._handlers[ident];\n handlerList.push(handler);\n return {\n dispose: () => {\n const handlerIndex = handlerList.indexOf(handler);\n if (handlerIndex !== -1) {\n handlerList.splice(handlerIndex, 1);\n }\n }\n };\n }\n public setHandler(ident: number, handler: IOscHandler): void {\n this._handlers[ident] = [handler];\n }\n public clearHandler(ident: number): void {\n if (this._handlers[ident]) delete this._handlers[ident];\n }\n public setHandlerFallback(handler: OscFallbackHandlerType): void {\n this._handlerFb = handler;\n }\n\n public dispose(): void {\n this._handlers = Object.create(null);\n this._handlerFb = () => {};\n }\n\n public reset(): void {\n // cleanup handlers if payload was already sent\n if (this._state === OscState.PAYLOAD) {\n this.end(false);\n }\n this._id = -1;\n this._state = OscState.START;\n }\n\n private _start(): void {\n const handlers = this._handlers[this._id];\n if (!handlers) {\n this._handlerFb(this._id, 'START');\n } else {\n for (let j = handlers.length - 1; j >= 0; j--) {\n handlers[j].start();\n }\n }\n }\n\n private _put(data: Uint32Array, start: number, end: number): void {\n const handlers = this._handlers[this._id];\n if (!handlers) {\n this._handlerFb(this._id, 'PUT', utf32ToString(data, start, end));\n } else {\n for (let j = handlers.length - 1; j >= 0; j--) {\n handlers[j].put(data, start, end);\n }\n }\n }\n\n private _end(success: boolean): void {\n // other than the old code we always have to call .end\n // to keep the bubbling we use `success` to indicate\n // whether a handler should execute\n const handlers = this._handlers[this._id];\n if (!handlers) {\n this._handlerFb(this._id, 'END', success);\n } else {\n let j = handlers.length - 1;\n for (; j >= 0; j--) {\n if (handlers[j].end(success) !== false) {\n break;\n }\n }\n j--;\n // cleanup left over handlers\n for (; j >= 0; j--) {\n handlers[j].end(false);\n }\n }\n }\n\n public start(): void {\n // always reset leftover handlers\n this.reset();\n this._id = -1;\n this._state = OscState.ID;\n }\n\n /**\n * Put data to current OSC command.\n * Expects the identifier of the OSC command in the form\n * OSC id ; payload ST/BEL\n * Payload chunks are not further processed and get\n * directly passed to the handlers.\n */\n public put(data: Uint32Array, start: number, end: number): void {\n if (this._state === OscState.ABORT) {\n return;\n }\n if (this._state === OscState.ID) {\n while (start < end) {\n const code = data[start++];\n if (code === 0x3b) {\n this._state = OscState.PAYLOAD;\n this._start();\n break;\n }\n if (code < 0x30 || 0x39 < code) {\n this._state = OscState.ABORT;\n return;\n }\n if (this._id === -1) {\n this._id = 0;\n }\n this._id = this._id * 10 + code - 48;\n }\n }\n if (this._state === OscState.PAYLOAD && end - start > 0) {\n this._put(data, start, end);\n }\n }\n\n /**\n * Indicates end of an OSC command.\n * Whether the OSC got aborted or finished normally\n * is indicated by `success`.\n */\n public end(success: boolean): void {\n if (this._state === OscState.START) {\n return;\n }\n // do nothing if command was faulty\n if (this._state !== OscState.ABORT) {\n // if we are still in ID state and get an early end\n // means that the command has no payload thus we still have\n // to announce START and send END right after\n if (this._state === OscState.ID) {\n this._start();\n }\n this._end(success);\n }\n this._id = -1;\n this._state = OscState.START;\n }\n}\n\n/**\n * Convenient class to allow attaching string based handler functions\n * as OSC handlers.\n */\nexport class OscHandler implements IOscHandler {\n private _data = '';\n private _hitLimit: boolean = false;\n\n constructor(private _handler: (data: string) => any) {}\n\n public start(): void {\n this._data = '';\n this._hitLimit = false;\n }\n\n public put(data: Uint32Array, start: number, end: number): void {\n if (this._hitLimit) {\n return;\n }\n this._data += utf32ToString(data, start, end);\n if (this._data.length > PAYLOAD_LIMIT) {\n this._data = '';\n this._hitLimit = true;\n }\n }\n\n public end(success: boolean): any {\n let ret;\n if (this._hitLimit) {\n ret = false;\n } else if (success) {\n ret = this._handler(this._data);\n }\n this._data = '';\n this._hitLimit = false;\n return ret;\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\n/**\n * Internal states of EscapeSequenceParser.\n */\nexport const enum ParserState {\n GROUND = 0,\n ESCAPE = 1,\n ESCAPE_INTERMEDIATE = 2,\n CSI_ENTRY = 3,\n CSI_PARAM = 4,\n CSI_INTERMEDIATE = 5,\n CSI_IGNORE = 6,\n SOS_PM_APC_STRING = 7,\n OSC_STRING = 8,\n DCS_ENTRY = 9,\n DCS_PARAM = 10,\n DCS_IGNORE = 11,\n DCS_INTERMEDIATE = 12,\n DCS_PASSTHROUGH = 13\n}\n\n/**\n* Internal actions of EscapeSequenceParser.\n*/\nexport const enum ParserAction {\n IGNORE = 0,\n ERROR = 1,\n PRINT = 2,\n EXECUTE = 3,\n OSC_START = 4,\n OSC_PUT = 5,\n OSC_END = 6,\n CSI_DISPATCH = 7,\n PARAM = 8,\n COLLECT = 9,\n ESC_DISPATCH = 10,\n CLEAR = 11,\n DCS_HOOK = 12,\n DCS_PUT = 13,\n DCS_UNHOOK = 14\n}\n\n/**\n * Internal states of OscParser.\n */\nexport const enum OscState {\n START = 0,\n ID = 1,\n PAYLOAD = 2,\n ABORT = 3\n}\n\n// payload limit for OSC and DCS\nexport const PAYLOAD_LIMIT = 10000000;\n","/**\n * Copyright (c) 2019 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { IDisposable } from 'common/Types';\nimport { IDcsHandler, IParams, IHandlerCollection, IDcsParser, DcsFallbackHandlerType } from 'common/parser/Types';\nimport { utf32ToString } from 'common/input/TextDecoder';\nimport { Params } from 'common/parser/Params';\nimport { PAYLOAD_LIMIT } from 'common/parser/Constants';\n\nconst EMPTY_HANDLERS: IDcsHandler[] = [];\n\nexport class DcsParser implements IDcsParser {\n private _handlers: IHandlerCollection = Object.create(null);\n private _active: IDcsHandler[] = EMPTY_HANDLERS;\n private _ident: number = 0;\n private _handlerFb: DcsFallbackHandlerType = () => {};\n\n public dispose(): void {\n this._handlers = Object.create(null);\n this._handlerFb = () => {};\n }\n\n public addHandler(ident: number, handler: IDcsHandler): IDisposable {\n if (this._handlers[ident] === undefined) {\n this._handlers[ident] = [];\n }\n const handlerList = this._handlers[ident];\n handlerList.push(handler);\n return {\n dispose: () => {\n const handlerIndex = handlerList.indexOf(handler);\n if (handlerIndex !== -1) {\n handlerList.splice(handlerIndex, 1);\n }\n }\n };\n }\n\n public setHandler(ident: number, handler: IDcsHandler): void {\n this._handlers[ident] = [handler];\n }\n\n public clearHandler(ident: number): void {\n if (this._handlers[ident]) delete this._handlers[ident];\n }\n\n public setHandlerFallback(handler: DcsFallbackHandlerType): void {\n this._handlerFb = handler;\n }\n\n public reset(): void {\n if (this._active.length) {\n this.unhook(false);\n }\n this._active = EMPTY_HANDLERS;\n this._ident = 0;\n }\n\n public hook(ident: number, params: IParams): void {\n // always reset leftover handlers\n this.reset();\n this._ident = ident;\n this._active = this._handlers[ident] || EMPTY_HANDLERS;\n if (!this._active.length) {\n this._handlerFb(this._ident, 'HOOK', params);\n } else {\n for (let j = this._active.length - 1; j >= 0; j--) {\n this._active[j].hook(params);\n }\n }\n }\n\n public put(data: Uint32Array, start: number, end: number): void {\n if (!this._active.length) {\n this._handlerFb(this._ident, 'PUT', utf32ToString(data, start, end));\n } else {\n for (let j = this._active.length - 1; j >= 0; j--) {\n this._active[j].put(data, start, end);\n }\n }\n }\n\n public unhook(success: boolean): void {\n if (!this._active.length) {\n this._handlerFb(this._ident, 'UNHOOK', success);\n } else {\n let j = this._active.length - 1;\n for (; j >= 0; j--) {\n if (this._active[j].unhook(success) !== false) {\n break;\n }\n }\n j--;\n // cleanup left over handlers\n for (; j >= 0; j--) {\n this._active[j].unhook(false);\n }\n }\n this._active = EMPTY_HANDLERS;\n this._ident = 0;\n }\n}\n\n/**\n * Convenient class to create a DCS handler from a single callback function.\n * Note: The payload is currently limited to 50 MB (hardcoded).\n */\nexport class DcsHandler implements IDcsHandler {\n private _data = '';\n private _params: IParams | undefined;\n private _hitLimit: boolean = false;\n\n constructor(private _handler: (data: string, params: IParams) => any) {}\n\n public hook(params: IParams): void {\n this._params = params.clone();\n this._data = '';\n this._hitLimit = false;\n }\n\n public put(data: Uint32Array, start: number, end: number): void {\n if (this._hitLimit) {\n return;\n }\n this._data += utf32ToString(data, start, end);\n if (this._data.length > PAYLOAD_LIMIT) {\n this._data = '';\n this._hitLimit = true;\n }\n }\n\n public unhook(success: boolean): any {\n let ret;\n if (this._hitLimit) {\n ret = false;\n } else if (success) {\n ret = this._handler(this._data, this._params ? this._params : new Params());\n }\n this._params = undefined;\n this._data = '';\n this._hitLimit = false;\n return ret;\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { generateConfig, configEquals } from 'browser/renderer/atlas/CharAtlasUtils';\nimport { BaseCharAtlas } from 'browser/renderer/atlas/BaseCharAtlas';\nimport { DynamicCharAtlas } from 'browser/renderer/atlas/DynamicCharAtlas';\nimport { ICharAtlasConfig } from 'browser/renderer/atlas/Types';\nimport { IColorSet } from 'browser/Types';\nimport { ITerminalOptions } from 'common/services/Services';\n\ninterface ICharAtlasCacheEntry {\n atlas: BaseCharAtlas;\n config: ICharAtlasConfig;\n // N.B. This implementation potentially holds onto copies of the terminal forever, so\n // this may cause memory leaks.\n ownedBy: number[];\n}\n\nconst charAtlasCache: ICharAtlasCacheEntry[] = [];\n\n/**\n * Acquires a char atlas, either generating a new one or returning an existing\n * one that is in use by another terminal.\n */\nexport function acquireCharAtlas(\n options: ITerminalOptions,\n rendererId: number,\n colors: IColorSet,\n scaledCharWidth: number,\n scaledCharHeight: number\n): BaseCharAtlas {\n const newConfig = generateConfig(scaledCharWidth, scaledCharHeight, options, colors);\n\n // Check to see if the renderer already owns this config\n for (let i = 0; i < charAtlasCache.length; i++) {\n const entry = charAtlasCache[i];\n const ownedByIndex = entry.ownedBy.indexOf(rendererId);\n if (ownedByIndex >= 0) {\n if (configEquals(entry.config, newConfig)) {\n return entry.atlas;\n }\n // The configs differ, release the renderer from the entry\n if (entry.ownedBy.length === 1) {\n entry.atlas.dispose();\n charAtlasCache.splice(i, 1);\n } else {\n entry.ownedBy.splice(ownedByIndex, 1);\n }\n break;\n }\n }\n\n // Try match a char atlas from the cache\n for (let i = 0; i < charAtlasCache.length; i++) {\n const entry = charAtlasCache[i];\n if (configEquals(entry.config, newConfig)) {\n // Add the renderer to the cache entry and return\n entry.ownedBy.push(rendererId);\n return entry.atlas;\n }\n }\n\n const newEntry: ICharAtlasCacheEntry = {\n atlas: new DynamicCharAtlas(\n document,\n newConfig\n ),\n config: newConfig,\n ownedBy: [rendererId]\n };\n charAtlasCache.push(newEntry);\n return newEntry.atlas;\n}\n\n/**\n * Removes a terminal reference from the cache, allowing its memory to be freed.\n */\nexport function removeTerminalFromCache(rendererId: number): void {\n for (let i = 0; i < charAtlasCache.length; i++) {\n const index = charAtlasCache[i].ownedBy.indexOf(rendererId);\n if (index !== -1) {\n if (charAtlasCache[i].ownedBy.length === 1) {\n // Remove the cache entry if it's the only renderer\n charAtlasCache[i].atlas.dispose();\n charAtlasCache.splice(i, 1);\n } else {\n // Remove the reference from the cache entry\n charAtlasCache[i].ownedBy.splice(index, 1);\n }\n break;\n }\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { ICharAtlasConfig } from 'browser/renderer/atlas/Types';\nimport { DEFAULT_COLOR } from 'common/buffer/Constants';\nimport { IColorSet, IPartialColorSet } from 'browser/Types';\nimport { ITerminalOptions } from 'common/services/Services';\n\nexport function generateConfig(scaledCharWidth: number, scaledCharHeight: number, options: ITerminalOptions, colors: IColorSet): ICharAtlasConfig {\n // null out some fields that don't matter\n const clonedColors = {\n foreground: colors.foreground,\n background: colors.background,\n cursor: undefined,\n cursorAccent: undefined,\n selection: undefined,\n // For the static char atlas, we only use the first 16 colors, but we need all 256 for the\n // dynamic character atlas.\n ansi: colors.ansi.slice(0, 16)\n };\n return {\n devicePixelRatio: window.devicePixelRatio,\n scaledCharWidth,\n scaledCharHeight,\n fontFamily: options.fontFamily,\n fontSize: options.fontSize,\n fontWeight: options.fontWeight,\n fontWeightBold: options.fontWeightBold,\n allowTransparency: options.allowTransparency,\n colors: clonedColors\n };\n}\n\nexport function configEquals(a: ICharAtlasConfig, b: ICharAtlasConfig): boolean {\n for (let i = 0; i < a.colors.ansi.length; i++) {\n if (a.colors.ansi[i].rgba !== b.colors.ansi[i].rgba) {\n return false;\n }\n }\n return a.devicePixelRatio === b.devicePixelRatio &&\n a.fontFamily === b.fontFamily &&\n a.fontSize === b.fontSize &&\n a.fontWeight === b.fontWeight &&\n a.fontWeightBold === b.fontWeightBold &&\n a.allowTransparency === b.allowTransparency &&\n a.scaledCharWidth === b.scaledCharWidth &&\n a.scaledCharHeight === b.scaledCharHeight &&\n a.colors.foreground === b.colors.foreground &&\n a.colors.background === b.colors.background;\n}\n\nexport function is256Color(colorCode: number): boolean {\n return colorCode < DEFAULT_COLOR;\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { IColorManager, IColor, IColorSet, IColorContrastCache } from 'browser/Types';\nimport { ITheme } from 'common/services/Services';\nimport { channels, color, css } from 'browser/Color';\nimport { ColorContrastCache } from 'browser/ColorContrastCache';\n\nconst DEFAULT_FOREGROUND = css.toColor('#ffffff');\nconst DEFAULT_BACKGROUND = css.toColor('#000000');\nconst DEFAULT_CURSOR = css.toColor('#ffffff');\nconst DEFAULT_CURSOR_ACCENT = css.toColor('#000000');\nconst DEFAULT_SELECTION = {\n css: 'rgba(255, 255, 255, 0.3)',\n rgba: 0xFFFFFF4D\n};\n\n// An IIFE to generate DEFAULT_ANSI_COLORS. Do not mutate DEFAULT_ANSI_COLORS, instead make a copy\n// and mutate that.\nexport const DEFAULT_ANSI_COLORS = (() => {\n const colors = [\n // dark:\n css.toColor('#2e3436'),\n css.toColor('#cc0000'),\n css.toColor('#4e9a06'),\n css.toColor('#c4a000'),\n css.toColor('#3465a4'),\n css.toColor('#75507b'),\n css.toColor('#06989a'),\n css.toColor('#d3d7cf'),\n // bright:\n css.toColor('#555753'),\n css.toColor('#ef2929'),\n css.toColor('#8ae234'),\n css.toColor('#fce94f'),\n css.toColor('#729fcf'),\n css.toColor('#ad7fa8'),\n css.toColor('#34e2e2'),\n css.toColor('#eeeeec')\n ];\n\n // Fill in the remaining 240 ANSI colors.\n // Generate colors (16-231)\n const v = [0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff];\n for (let i = 0; i < 216; i++) {\n const r = v[(i / 36) % 6 | 0];\n const g = v[(i / 6) % 6 | 0];\n const b = v[i % 6];\n colors.push({\n css: channels.toCss(r, g, b),\n rgba: channels.toRgba(r, g, b)\n });\n }\n\n // Generate greys (232-255)\n for (let i = 0; i < 24; i++) {\n const c = 8 + i * 10;\n colors.push({\n css: channels.toCss(c, c, c),\n rgba: channels.toRgba(c, c, c)\n });\n }\n\n return colors;\n})();\n\n/**\n * Manages the source of truth for a terminal's colors.\n */\nexport class ColorManager implements IColorManager {\n public colors: IColorSet;\n private _ctx: CanvasRenderingContext2D;\n private _litmusColor: CanvasGradient;\n private _contrastCache: IColorContrastCache;\n\n constructor(document: Document, public allowTransparency: boolean) {\n const canvas = document.createElement('canvas');\n canvas.width = 1;\n canvas.height = 1;\n const ctx = canvas.getContext('2d');\n if (!ctx) {\n throw new Error('Could not get rendering context');\n }\n this._ctx = ctx;\n this._ctx.globalCompositeOperation = 'copy';\n this._litmusColor = this._ctx.createLinearGradient(0, 0, 1, 1);\n this._contrastCache = new ColorContrastCache();\n this.colors = {\n foreground: DEFAULT_FOREGROUND,\n background: DEFAULT_BACKGROUND,\n cursor: DEFAULT_CURSOR,\n cursorAccent: DEFAULT_CURSOR_ACCENT,\n selection: DEFAULT_SELECTION,\n selectionOpaque: color.blend(DEFAULT_BACKGROUND, DEFAULT_SELECTION),\n ansi: DEFAULT_ANSI_COLORS.slice(),\n contrastCache: this._contrastCache\n };\n }\n\n public onOptionsChange(key: string): void {\n if (key === 'minimumContrastRatio') {\n this._contrastCache.clear();\n }\n }\n\n /**\n * Sets the terminal's theme.\n * @param theme The theme to use. If a partial theme is provided then default\n * colors will be used where colors are not defined.\n */\n public setTheme(theme: ITheme = {}): void {\n this.colors.foreground = this._parseColor(theme.foreground, DEFAULT_FOREGROUND);\n this.colors.background = this._parseColor(theme.background, DEFAULT_BACKGROUND);\n this.colors.cursor = this._parseColor(theme.cursor, DEFAULT_CURSOR, true);\n this.colors.cursorAccent = this._parseColor(theme.cursorAccent, DEFAULT_CURSOR_ACCENT, true);\n this.colors.selection = this._parseColor(theme.selection, DEFAULT_SELECTION, true);\n this.colors.selectionOpaque = color.blend(this.colors.background, this.colors.selection);\n this.colors.ansi[0] = this._parseColor(theme.black, DEFAULT_ANSI_COLORS[0]);\n this.colors.ansi[1] = this._parseColor(theme.red, DEFAULT_ANSI_COLORS[1]);\n this.colors.ansi[2] = this._parseColor(theme.green, DEFAULT_ANSI_COLORS[2]);\n this.colors.ansi[3] = this._parseColor(theme.yellow, DEFAULT_ANSI_COLORS[3]);\n this.colors.ansi[4] = this._parseColor(theme.blue, DEFAULT_ANSI_COLORS[4]);\n this.colors.ansi[5] = this._parseColor(theme.magenta, DEFAULT_ANSI_COLORS[5]);\n this.colors.ansi[6] = this._parseColor(theme.cyan, DEFAULT_ANSI_COLORS[6]);\n this.colors.ansi[7] = this._parseColor(theme.white, DEFAULT_ANSI_COLORS[7]);\n this.colors.ansi[8] = this._parseColor(theme.brightBlack, DEFAULT_ANSI_COLORS[8]);\n this.colors.ansi[9] = this._parseColor(theme.brightRed, DEFAULT_ANSI_COLORS[9]);\n this.colors.ansi[10] = this._parseColor(theme.brightGreen, DEFAULT_ANSI_COLORS[10]);\n this.colors.ansi[11] = this._parseColor(theme.brightYellow, DEFAULT_ANSI_COLORS[11]);\n this.colors.ansi[12] = this._parseColor(theme.brightBlue, DEFAULT_ANSI_COLORS[12]);\n this.colors.ansi[13] = this._parseColor(theme.brightMagenta, DEFAULT_ANSI_COLORS[13]);\n this.colors.ansi[14] = this._parseColor(theme.brightCyan, DEFAULT_ANSI_COLORS[14]);\n this.colors.ansi[15] = this._parseColor(theme.brightWhite, DEFAULT_ANSI_COLORS[15]);\n // Clear our the cache\n this._contrastCache.clear();\n }\n\n private _parseColor(\n css: string | undefined,\n fallback: IColor,\n allowTransparency: boolean = this.allowTransparency\n ): IColor {\n if (css === undefined) {\n return fallback;\n }\n\n // If parsing the value results in failure, then it must be ignored, and the attribute must\n // retain its previous value.\n // -- https://html.spec.whatwg.org/multipage/canvas.html#fill-and-stroke-styles\n this._ctx.fillStyle = this._litmusColor;\n this._ctx.fillStyle = css;\n if (typeof this._ctx.fillStyle !== 'string') {\n console.warn(`Color: ${css} is invalid using fallback ${fallback.css}`);\n return fallback;\n }\n\n this._ctx.fillRect(0, 0, 1, 1);\n const data = this._ctx.getImageData(0, 0, 1, 1).data;\n\n // Check if the printed color was transparent\n if (data[3] !== 0xFF) {\n if (!allowTransparency) {\n // Ideally we'd just ignore the alpha channel, but...\n //\n // Browsers may not give back exactly the same RGB values we put in, because most/all\n // convert the color to a pre-multiplied representation. getImageData converts that back to\n // a un-premultipled representation, but the precision loss may make the RGB channels unuable\n // on their own.\n //\n // E.g. In Chrome #12345610 turns into #10305010, and in the extreme case, 0xFFFFFF00 turns\n // into 0x00000000.\n //\n // \"Note: Due to the lossy nature of converting to and from premultiplied alpha color values,\n // pixels that have just been set using putImageData() might be returned to an equivalent\n // getImageData() as different values.\"\n // -- https://html.spec.whatwg.org/multipage/canvas.html#pixel-manipulation\n //\n // So let's just use the fallback color in this case instead.\n console.warn(\n `Color: ${css} is using transparency, but allowTransparency is false. ` +\n `Using fallback ${fallback.css}.`\n );\n return fallback;\n }\n\n // https://html.spec.whatwg.org/multipage/canvas.html#serialisation-of-a-color\n // the color value has alpha less than 1.0, and the string is the color value in the CSS rgba()\n const [r, g, b, a] = this._ctx.fillStyle.substring(5, this._ctx.fillStyle.length - 1).split(',').map(component => Number(component));\n const alpha = Math.round(a * 255);\n const rgba: number = channels.toRgba(r, g, b, alpha);\n return {\n rgba,\n css: channels.toCss(r, g, b, alpha)\n };\n }\n\n return {\n // https://html.spec.whatwg.org/multipage/canvas.html#serialisation-of-a-color\n // if it has alpha equal to 1.0, then the string is a lowercase six-digit hex value, prefixed with a \"#\" character\n css: this._ctx.fillStyle,\n rgba: channels.toRgba(data[0], data[1], data[2], data[3])\n };\n }\n}\n","/**\n * Copyright (c) 2019 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nexport function throwIfFalsy(value: T | undefined | null): T {\n if (!value) {\n throw new Error('value must not be falsy');\n }\n return value;\n}\n","/**\n * Copyright (c) 2018 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { IBufferLine, ICellData, CharData } from 'common/Types';\nimport { ICharacterJoinerRegistry, ICharacterJoiner } from 'browser/renderer/Types';\nimport { AttributeData } from 'common/buffer/AttributeData';\nimport { WHITESPACE_CELL_CHAR, Content } from 'common/buffer/Constants';\nimport { CellData } from 'common/buffer/CellData';\nimport { IBufferService } from 'common/services/Services';\n\nexport class JoinedCellData extends AttributeData implements ICellData {\n private _width: number;\n // .content carries no meaning for joined CellData, simply nullify it\n // thus we have to overload all other .content accessors\n public content: number = 0;\n public fg: number;\n public bg: number;\n public combinedData: string = '';\n\n constructor(firstCell: ICellData, chars: string, width: number) {\n super();\n this.fg = firstCell.fg;\n this.bg = firstCell.bg;\n this.combinedData = chars;\n this._width = width;\n }\n\n public isCombined(): number {\n // always mark joined cell data as combined\n return Content.IS_COMBINED_MASK;\n }\n\n public getWidth(): number {\n return this._width;\n }\n\n public getChars(): string {\n return this.combinedData;\n }\n\n public getCode(): number {\n // code always gets the highest possible fake codepoint (read as -1)\n // this is needed as code is used by caches as identifier\n return 0x1FFFFF;\n }\n\n public setFromCharData(value: CharData): void {\n throw new Error('not implemented');\n }\n\n public getAsCharData(): CharData {\n return [this.fg, this.getChars(), this.getWidth(), this.getCode()];\n }\n}\n\nexport class CharacterJoinerRegistry implements ICharacterJoinerRegistry {\n\n private _characterJoiners: ICharacterJoiner[] = [];\n private _nextCharacterJoinerId: number = 0;\n private _workCell: CellData = new CellData();\n\n constructor(private _bufferService: IBufferService) { }\n\n public registerCharacterJoiner(handler: (text: string) => [number, number][]): number {\n const joiner: ICharacterJoiner = {\n id: this._nextCharacterJoinerId++,\n handler\n };\n\n this._characterJoiners.push(joiner);\n return joiner.id;\n }\n\n public deregisterCharacterJoiner(joinerId: number): boolean {\n for (let i = 0; i < this._characterJoiners.length; i++) {\n if (this._characterJoiners[i].id === joinerId) {\n this._characterJoiners.splice(i, 1);\n return true;\n }\n }\n\n return false;\n }\n\n public getJoinedCharacters(row: number): [number, number][] {\n if (this._characterJoiners.length === 0) {\n return [];\n }\n\n const line = this._bufferService.buffer.lines.get(row);\n if (!line || line.length === 0) {\n return [];\n }\n\n const ranges: [number, number][] = [];\n const lineStr = line.translateToString(true);\n\n // Because some cells can be represented by multiple javascript characters,\n // we track the cell and the string indexes separately. This allows us to\n // translate the string ranges we get from the joiners back into cell ranges\n // for use when rendering\n let rangeStartColumn = 0;\n let currentStringIndex = 0;\n let rangeStartStringIndex = 0;\n let rangeAttrFG = line.getFg(0);\n let rangeAttrBG = line.getBg(0);\n\n for (let x = 0; x < line.getTrimmedLength(); x++) {\n line.loadCell(x, this._workCell);\n\n if (this._workCell.getWidth() === 0) {\n // If this character is of width 0, skip it.\n continue;\n }\n\n // End of range\n if (this._workCell.fg !== rangeAttrFG || this._workCell.bg !== rangeAttrBG) {\n // If we ended up with a sequence of more than one character,\n // look for ranges to join.\n if (x - rangeStartColumn > 1) {\n const joinedRanges = this._getJoinedRanges(\n lineStr,\n rangeStartStringIndex,\n currentStringIndex,\n line,\n rangeStartColumn\n );\n for (let i = 0; i < joinedRanges.length; i++) {\n ranges.push(joinedRanges[i]);\n }\n }\n\n // Reset our markers for a new range.\n rangeStartColumn = x;\n rangeStartStringIndex = currentStringIndex;\n rangeAttrFG = this._workCell.fg;\n rangeAttrBG = this._workCell.bg;\n }\n\n currentStringIndex += this._workCell.getChars().length || WHITESPACE_CELL_CHAR.length;\n }\n\n // Process any trailing ranges.\n if (this._bufferService.cols - rangeStartColumn > 1) {\n const joinedRanges = this._getJoinedRanges(\n lineStr,\n rangeStartStringIndex,\n currentStringIndex,\n line,\n rangeStartColumn\n );\n for (let i = 0; i < joinedRanges.length; i++) {\n ranges.push(joinedRanges[i]);\n }\n }\n\n return ranges;\n }\n\n /**\n * Given a segment of a line of text, find all ranges of text that should be\n * joined in a single rendering unit. Ranges are internally converted to\n * column ranges, rather than string ranges.\n * @param line String representation of the full line of text\n * @param startIndex Start position of the range to search in the string (inclusive)\n * @param endIndex End position of the range to search in the string (exclusive)\n */\n private _getJoinedRanges(line: string, startIndex: number, endIndex: number, lineData: IBufferLine, startCol: number): [number, number][] {\n const text = line.substring(startIndex, endIndex);\n // At this point we already know that there is at least one joiner so\n // we can just pull its value and assign it directly rather than\n // merging it into an empty array, which incurs unnecessary writes.\n const joinedRanges: [number, number][] = this._characterJoiners[0].handler(text);\n for (let i = 1; i < this._characterJoiners.length; i++) {\n // We merge any overlapping ranges across the different joiners\n const joinerRanges = this._characterJoiners[i].handler(text);\n for (let j = 0; j < joinerRanges.length; j++) {\n CharacterJoinerRegistry._mergeRanges(joinedRanges, joinerRanges[j]);\n }\n }\n this._stringRangesToCellRanges(joinedRanges, lineData, startCol);\n return joinedRanges;\n }\n\n /**\n * Modifies the provided ranges in-place to adjust for variations between\n * string length and cell width so that the range represents a cell range,\n * rather than the string range the joiner provides.\n * @param ranges String ranges containing start (inclusive) and end (exclusive) index\n * @param line Cell data for the relevant line in the terminal\n * @param startCol Offset within the line to start from\n */\n private _stringRangesToCellRanges(ranges: [number, number][], line: IBufferLine, startCol: number): void {\n let currentRangeIndex = 0;\n let currentRangeStarted = false;\n let currentStringIndex = 0;\n let currentRange = ranges[currentRangeIndex];\n\n // If we got through all of the ranges, stop searching\n if (!currentRange) {\n return;\n }\n\n for (let x = startCol; x < this._bufferService.cols; x++) {\n const width = line.getWidth(x);\n const length = line.getString(x).length || WHITESPACE_CELL_CHAR.length;\n\n // We skip zero-width characters when creating the string to join the text\n // so we do the same here\n if (width === 0) {\n continue;\n }\n\n // Adjust the start of the range\n if (!currentRangeStarted && currentRange[0] <= currentStringIndex) {\n currentRange[0] = x;\n currentRangeStarted = true;\n }\n\n // Adjust the end of the range\n if (currentRange[1] <= currentStringIndex) {\n currentRange[1] = x;\n\n // We're finished with this range, so we move to the next one\n currentRange = ranges[++currentRangeIndex];\n\n // If there are no more ranges left, stop searching\n if (!currentRange) {\n break;\n }\n\n // Ranges can be on adjacent characters. Because the end index of the\n // ranges are exclusive, this means that the index for the start of a\n // range can be the same as the end index of the previous range. To\n // account for the start of the next range, we check here just in case.\n if (currentRange[0] <= currentStringIndex) {\n currentRange[0] = x;\n currentRangeStarted = true;\n } else {\n currentRangeStarted = false;\n }\n }\n\n // Adjust the string index based on the character length to line up with\n // the column adjustment\n currentStringIndex += length;\n }\n\n // If there is still a range left at the end, it must extend all the way to\n // the end of the line.\n if (currentRange) {\n currentRange[1] = this._bufferService.cols;\n }\n }\n\n /**\n * Merges the range defined by the provided start and end into the list of\n * existing ranges. The merge is done in place on the existing range for\n * performance and is also returned.\n * @param ranges Existing range list\n * @param newRange Tuple of two numbers representing the new range to merge in.\n * @returns The ranges input with the new range merged in place\n */\n private static _mergeRanges(ranges: [number, number][], newRange: [number, number]): [number, number][] {\n let inRange = false;\n for (let i = 0; i < ranges.length; i++) {\n const range = ranges[i];\n if (!inRange) {\n if (newRange[1] <= range[0]) {\n // Case 1: New range is before the search range\n ranges.splice(i, 0, newRange);\n return ranges;\n }\n\n if (newRange[1] <= range[1]) {\n // Case 2: New range is either wholly contained within the\n // search range or overlaps with the front of it\n range[0] = Math.min(newRange[0], range[0]);\n return ranges;\n }\n\n if (newRange[0] < range[1]) {\n // Case 3: New range either wholly contains the search range\n // or overlaps with the end of it\n range[0] = Math.min(newRange[0], range[0]);\n inRange = true;\n }\n\n // Case 4: New range starts after the search range\n continue;\n } else {\n if (newRange[1] <= range[0]) {\n // Case 5: New range extends from previous range but doesn't\n // reach the current one\n ranges[i - 1][1] = newRange[1];\n return ranges;\n }\n\n if (newRange[1] <= range[1]) {\n // Case 6: New range extends from prvious range into the\n // current range\n ranges[i - 1][1] = Math.max(newRange[1], range[1]);\n ranges.splice(i, 1);\n return ranges;\n }\n\n // Case 7: New range extends from previous range past the\n // end of the current range\n ranges.splice(i, 1);\n i--;\n }\n }\n\n if (inRange) {\n // Case 8: New range extends past the last existing range\n ranges[ranges.length - 1][1] = newRange[1];\n } else {\n // Case 9: New range starts after the last existing range\n ranges.push(newRange);\n }\n\n return ranges;\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nexport function getCoordsRelativeToElement(event: {clientX: number, clientY: number}, element: HTMLElement): [number, number] {\n const rect = element.getBoundingClientRect();\n return [event.clientX - rect.left, event.clientY - rect.top];\n}\n\n/**\n * Gets coordinates within the terminal for a particular mouse event. The result\n * is returned as an array in the form [x, y] instead of an object as it's a\n * little faster and this function is used in some low level code.\n * @param event The mouse event.\n * @param element The terminal's container element.\n * @param colCount The number of columns in the terminal.\n * @param rowCount The number of rows n the terminal.\n * @param isSelection Whether the request is for the selection or not. This will\n * apply an offset to the x value such that the left half of the cell will\n * select that cell and the right half will select the next cell.\n */\nexport function getCoords(event: {clientX: number, clientY: number}, element: HTMLElement, colCount: number, rowCount: number, hasValidCharSize: boolean, actualCellWidth: number, actualCellHeight: number, isSelection?: boolean): [number, number] | undefined {\n // Coordinates cannot be measured if there are no valid\n if (!hasValidCharSize) {\n return undefined;\n }\n\n const coords = getCoordsRelativeToElement(event, element);\n if (!coords) {\n return undefined;\n }\n\n coords[0] = Math.ceil((coords[0] + (isSelection ? actualCellWidth / 2 : 0)) / actualCellWidth);\n coords[1] = Math.ceil(coords[1] / actualCellHeight);\n\n // Ensure coordinates are within the terminal viewport. Note that selections\n // need an addition point of precision to cover the end point (as characters\n // cover half of one char and half of the next).\n coords[0] = Math.min(Math.max(coords[0], 1), colCount + (isSelection ? 1 : 0));\n coords[1] = Math.min(Math.max(coords[1], 1), rowCount);\n\n return coords;\n}\n\n/**\n * Gets coordinates within the terminal for a particular mouse event, wrapping\n * them to the bounds of the terminal and adding 32 to both the x and y values\n * as expected by xterm.\n */\nexport function getRawByteCoords(coords: [number, number] | undefined): { x: number, y: number } | undefined {\n if (!coords) {\n return undefined;\n }\n\n // xterm sends raw bytes and starts at 32 (SP) for each.\n return { x: coords[0] + 32, y: coords[1] + 32 };\n}\n","/**\n * Copyright (c) 2018 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { IDisposable } from 'common/Types';\n\n/**\n * Debounces calls to render terminal rows using animation frames.\n */\nexport class RenderDebouncer implements IDisposable {\n private _rowStart: number | undefined;\n private _rowEnd: number | undefined;\n private _rowCount: number | undefined;\n private _animationFrame: number | undefined;\n\n constructor(\n private _renderCallback: (start: number, end: number) => void\n ) {\n }\n\n public dispose(): void {\n if (this._animationFrame) {\n window.cancelAnimationFrame(this._animationFrame);\n this._animationFrame = undefined;\n }\n }\n\n public refresh(rowStart: number, rowEnd: number, rowCount: number): void {\n this._rowCount = rowCount;\n // Get the min/max row start/end for the arg values\n rowStart = rowStart !== undefined ? rowStart : 0;\n rowEnd = rowEnd !== undefined ? rowEnd : this._rowCount - 1;\n // Set the properties to the updated values\n this._rowStart = this._rowStart !== undefined ? Math.min(this._rowStart, rowStart) : rowStart;\n this._rowEnd = this._rowEnd !== undefined ? Math.max(this._rowEnd, rowEnd) : rowEnd;\n\n if (this._animationFrame) {\n return;\n }\n\n this._animationFrame = window.requestAnimationFrame(() => this._innerRefresh());\n }\n\n private _innerRefresh(): void {\n // Make sure values are set\n if (this._rowStart === undefined || this._rowEnd === undefined || this._rowCount === undefined) {\n return;\n }\n\n // Clamp values\n this._rowStart = Math.max(this._rowStart, 0);\n this._rowEnd = Math.min(this._rowEnd, this._rowCount - 1);\n\n // Run render callback\n this._renderCallback(this._rowStart, this._rowEnd);\n\n // Reset debouncer\n this._rowStart = undefined;\n this._rowEnd = undefined;\n this._animationFrame = undefined;\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { Disposable } from 'common/Lifecycle';\n\nexport type ScreenDprListener = (newDevicePixelRatio?: number, oldDevicePixelRatio?: number) => void;\n\n/**\n * The screen device pixel ratio monitor allows listening for when the\n * window.devicePixelRatio value changes. This is done not with polling but with\n * the use of window.matchMedia to watch media queries. When the event fires,\n * the listener will be reattached using a different media query to ensure that\n * any further changes will register.\n *\n * The listener should fire on both window zoom changes and switching to a\n * monitor with a different DPI.\n */\nexport class ScreenDprMonitor extends Disposable {\n private _currentDevicePixelRatio: number = window.devicePixelRatio;\n private _outerListener: ((this: MediaQueryList, ev: MediaQueryListEvent) => any) | undefined;\n private _listener: ScreenDprListener | undefined;\n private _resolutionMediaMatchList: MediaQueryList | undefined;\n\n public setListener(listener: ScreenDprListener): void {\n if (this._listener) {\n this.clearListener();\n }\n this._listener = listener;\n this._outerListener = () => {\n if (!this._listener) {\n return;\n }\n this._listener(window.devicePixelRatio, this._currentDevicePixelRatio);\n this._updateDpr();\n };\n this._updateDpr();\n }\n\n public dispose(): void {\n super.dispose();\n this.clearListener();\n }\n\n private _updateDpr(): void {\n if (!this._resolutionMediaMatchList || !this._outerListener) {\n return;\n }\n\n // Clear listeners for old DPR\n this._resolutionMediaMatchList.removeListener(this._outerListener);\n\n // Add listeners for new DPR\n this._currentDevicePixelRatio = window.devicePixelRatio;\n this._resolutionMediaMatchList = window.matchMedia(`screen and (resolution: ${window.devicePixelRatio}dppx)`);\n this._resolutionMediaMatchList.addListener(this._outerListener);\n }\n\n public clearListener(): void {\n if (!this._resolutionMediaMatchList || !this._listener || !this._outerListener) {\n return;\n }\n this._resolutionMediaMatchList.removeListener(this._outerListener);\n this._resolutionMediaMatchList = undefined;\n this._listener = undefined;\n this._outerListener = undefined;\n }\n}\n","/**\n * Copyright (c) 2016 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\n/*\n * A simple utility for cloning values\n */\nexport function clone(val: T, depth: number = 5): T {\n if (typeof val !== 'object') {\n return val;\n }\n\n // If we're cloning an array, use an array as the base, otherwise use an object\n const clonedObject: any = Array.isArray(val) ? [] : {};\n\n for (const key in val) {\n // Recursively clone eack item unless we're at the maximum depth\n clonedObject[key] = depth <= 1 ? val[key] : (val[key] ? clone(val[key], depth - 1) : val[key]);\n }\n\n return clonedObject as T;\n}\n","/**\n * Copyright (c) 2018 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { Terminal as ITerminalApi, ITerminalOptions, IMarker, IDisposable, ILinkMatcherOptions, ITheme, ILocalizableStrings, ITerminalAddon, ISelectionPosition, IBuffer as IBufferApi, IBufferLine as IBufferLineApi, IBufferCell as IBufferCellApi, IParser, IFunctionIdentifier, IUnicodeHandling, IUnicodeVersionProvider } from 'xterm';\nimport { ITerminal } from '../Types';\nimport { IBufferLine, ICellData } from 'common/Types';\nimport { IBuffer } from 'common/buffer/Types';\nimport { CellData } from 'common/buffer/CellData';\nimport { Terminal as TerminalCore } from '../Terminal';\nimport * as Strings from '../browser/LocalizableStrings';\nimport { IEvent } from 'common/EventEmitter';\nimport { AddonManager } from './AddonManager';\nimport { IParams } from 'common/parser/Types';\n\nexport class Terminal implements ITerminalApi {\n private _core: ITerminal;\n private _addonManager: AddonManager;\n private _parser: IParser;\n\n constructor(options?: ITerminalOptions) {\n this._core = new TerminalCore(options);\n this._addonManager = new AddonManager();\n }\n\n public get onCursorMove(): IEvent { return this._core.onCursorMove; }\n public get onLineFeed(): IEvent { return this._core.onLineFeed; }\n public get onSelectionChange(): IEvent { return this._core.onSelectionChange; }\n public get onData(): IEvent { return this._core.onData; }\n public get onBinary(): IEvent { return this._core.onBinary; }\n public get onTitleChange(): IEvent { return this._core.onTitleChange; }\n public get onScroll(): IEvent { return this._core.onScroll; }\n public get onKey(): IEvent<{ key: string, domEvent: KeyboardEvent }> { return this._core.onKey; }\n public get onRender(): IEvent<{ start: number, end: number }> { return this._core.onRender; }\n public get onResize(): IEvent<{ cols: number, rows: number }> { return this._core.onResize; }\n\n public get element(): HTMLElement | undefined { return this._core.element; }\n public get parser(): IParser {\n if (!this._parser) {\n this._parser = new ParserApi(this._core);\n }\n return this._parser;\n }\n public get unicode(): IUnicodeHandling {\n return new UnicodeApi(this._core);\n }\n public get textarea(): HTMLTextAreaElement | undefined { return this._core.textarea; }\n public get rows(): number { return this._core.rows; }\n public get cols(): number { return this._core.cols; }\n public get buffer(): IBufferApi { return new BufferApiView(this._core.buffer); }\n public get markers(): ReadonlyArray { return this._core.markers; }\n public blur(): void {\n this._core.blur();\n }\n public focus(): void {\n this._core.focus();\n }\n public resize(columns: number, rows: number): void {\n this._verifyIntegers(columns, rows);\n this._core.resize(columns, rows);\n }\n public open(parent: HTMLElement): void {\n this._core.open(parent);\n }\n public attachCustomKeyEventHandler(customKeyEventHandler: (event: KeyboardEvent) => boolean): void {\n this._core.attachCustomKeyEventHandler(customKeyEventHandler);\n }\n public registerLinkMatcher(regex: RegExp, handler: (event: MouseEvent, uri: string) => void, options?: ILinkMatcherOptions): number {\n return this._core.registerLinkMatcher(regex, handler, options);\n }\n public deregisterLinkMatcher(matcherId: number): void {\n this._core.deregisterLinkMatcher(matcherId);\n }\n public registerCharacterJoiner(handler: (text: string) => [number, number][]): number {\n return this._core.registerCharacterJoiner(handler);\n }\n public deregisterCharacterJoiner(joinerId: number): void {\n this._core.deregisterCharacterJoiner(joinerId);\n }\n public registerMarker(cursorYOffset: number): IMarker {\n this._verifyIntegers(cursorYOffset);\n return this._core.addMarker(cursorYOffset);\n }\n public addMarker(cursorYOffset: number): IMarker {\n return this.registerMarker(cursorYOffset);\n }\n public hasSelection(): boolean {\n return this._core.hasSelection();\n }\n public select(column: number, row: number, length: number): void {\n this._verifyIntegers(column, row, length);\n this._core.select(column, row, length);\n }\n public getSelection(): string {\n return this._core.getSelection();\n }\n public getSelectionPosition(): ISelectionPosition | undefined {\n return this._core.getSelectionPosition();\n }\n public clearSelection(): void {\n this._core.clearSelection();\n }\n public selectAll(): void {\n this._core.selectAll();\n }\n public selectLines(start: number, end: number): void {\n this._verifyIntegers(start, end);\n this._core.selectLines(start, end);\n }\n public dispose(): void {\n this._addonManager.dispose();\n this._core.dispose();\n }\n public scrollLines(amount: number): void {\n this._verifyIntegers(amount);\n this._core.scrollLines(amount);\n }\n public scrollPages(pageCount: number): void {\n this._verifyIntegers(pageCount);\n this._core.scrollPages(pageCount);\n }\n public scrollToTop(): void {\n this._core.scrollToTop();\n }\n public scrollToBottom(): void {\n this._core.scrollToBottom();\n }\n public scrollToLine(line: number): void {\n this._verifyIntegers(line);\n this._core.scrollToLine(line);\n }\n public clear(): void {\n this._core.clear();\n }\n public write(data: string | Uint8Array, callback?: () => void): void {\n this._core.write(data, callback);\n }\n public writeUtf8(data: Uint8Array, callback?: () => void): void {\n this._core.write(data, callback);\n }\n public writeln(data: string | Uint8Array, callback?: () => void): void {\n this._core.write(data);\n this._core.write('\\r\\n', callback);\n }\n public paste(data: string): void {\n this._core.paste(data);\n }\n public getOption(key: 'bellSound' | 'bellStyle' | 'cursorStyle' | 'fontFamily' | 'fontWeight' | 'fontWeightBold' | 'logLevel' | 'rendererType' | 'termName' | 'wordSeparator'): string;\n public getOption(key: 'allowTransparency' | 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'disableStdin' | 'macOptionIsMeta' | 'rightClickSelectsWord' | 'popOnBell' | 'visualBell'): boolean;\n public getOption(key: 'cols' | 'fontSize' | 'letterSpacing' | 'lineHeight' | 'rows' | 'tabStopWidth' | 'scrollback'): number;\n public getOption(key: string): any;\n public getOption(key: any): any {\n return this._core.optionsService.getOption(key);\n }\n public setOption(key: 'bellSound' | 'fontFamily' | 'termName' | 'wordSeparator', value: string): void;\n public setOption(key: 'fontWeight' | 'fontWeightBold', value: 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900'): void;\n public setOption(key: 'logLevel', value: 'debug' | 'info' | 'warn' | 'error' | 'off'): void;\n public setOption(key: 'bellStyle', value: 'none' | 'visual' | 'sound' | 'both'): void;\n public setOption(key: 'cursorStyle', value: 'block' | 'underline' | 'bar'): void;\n public setOption(key: 'allowTransparency' | 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'disableStdin' | 'macOptionIsMeta' | 'rightClickSelectsWord' | 'popOnBell' | 'visualBell', value: boolean): void;\n public setOption(key: 'fontSize' | 'letterSpacing' | 'lineHeight' | 'tabStopWidth' | 'scrollback', value: number): void;\n public setOption(key: 'theme', value: ITheme): void;\n public setOption(key: 'cols' | 'rows', value: number): void;\n public setOption(key: string, value: any): void;\n public setOption(key: any, value: any): void {\n this._core.optionsService.setOption(key, value);\n }\n public refresh(start: number, end: number): void {\n this._verifyIntegers(start, end);\n this._core.refresh(start, end);\n }\n public reset(): void {\n this._core.reset();\n }\n public loadAddon(addon: ITerminalAddon): void {\n return this._addonManager.loadAddon(this, addon);\n }\n public static get strings(): ILocalizableStrings {\n return Strings;\n }\n\n private _verifyIntegers(...values: number[]): void {\n values.forEach(value => {\n if (value === Infinity || isNaN(value) || value % 1 !== 0) {\n throw new Error('This API only accepts integers');\n }\n });\n }\n}\n\nclass BufferApiView implements IBufferApi {\n constructor(private _buffer: IBuffer) { }\n\n public get cursorY(): number { return this._buffer.y; }\n public get cursorX(): number { return this._buffer.x; }\n public get viewportY(): number { return this._buffer.ydisp; }\n public get baseY(): number { return this._buffer.ybase; }\n public get length(): number { return this._buffer.lines.length; }\n public getLine(y: number): IBufferLineApi | undefined {\n const line = this._buffer.lines.get(y);\n if (!line) {\n return undefined;\n }\n return new BufferLineApiView(line);\n }\n public getNullCell(): IBufferCellApi { return new CellData(); }\n}\n\nclass BufferLineApiView implements IBufferLineApi {\n constructor(private _line: IBufferLine) { }\n\n public get isWrapped(): boolean { return this._line.isWrapped; }\n public get length(): number { return this._line.length; }\n public getCell(x: number, cell?: IBufferCellApi): IBufferCellApi | undefined {\n if (x < 0 || x >= this._line.length) {\n return undefined;\n }\n\n if (cell) {\n this._line.loadCell(x, cell);\n return cell;\n }\n return this._line.loadCell(x, new CellData());\n }\n public translateToString(trimRight?: boolean, startColumn?: number, endColumn?: number): string {\n return this._line.translateToString(trimRight, startColumn, endColumn);\n }\n}\n\nclass ParserApi implements IParser {\n constructor(private _core: ITerminal) {}\n\n public registerCsiHandler(id: IFunctionIdentifier, callback: (params: (number | number[])[]) => boolean): IDisposable {\n return this._core.addCsiHandler(id, (params: IParams) => callback(params.toArray()));\n }\n public addCsiHandler(id: IFunctionIdentifier, callback: (params: (number | number[])[]) => boolean): IDisposable {\n return this.registerCsiHandler(id, callback);\n }\n public registerDcsHandler(id: IFunctionIdentifier, callback: (data: string, param: (number | number[])[]) => boolean): IDisposable {\n return this._core.addDcsHandler(id, (data: string, params: IParams) => callback(data, params.toArray()));\n }\n public addDcsHandler(id: IFunctionIdentifier, callback: (data: string, param: (number | number[])[]) => boolean): IDisposable {\n return this.registerDcsHandler(id, callback);\n }\n public registerEscHandler(id: IFunctionIdentifier, handler: () => boolean): IDisposable {\n return this._core.addEscHandler(id, handler);\n }\n public addEscHandler(id: IFunctionIdentifier, handler: () => boolean): IDisposable {\n return this.registerEscHandler(id, handler);\n }\n public registerOscHandler(ident: number, callback: (data: string) => boolean): IDisposable {\n return this._core.addOscHandler(ident, callback);\n }\n public addOscHandler(ident: number, callback: (data: string) => boolean): IDisposable {\n return this.registerOscHandler(ident, callback);\n }\n}\n\nclass UnicodeApi implements IUnicodeHandling {\n constructor(private _core: ITerminal) {}\n\n public register(provider: IUnicodeVersionProvider): void {\n this._core.unicodeService.register(provider);\n }\n\n public get versions(): string[] {\n return this._core.unicodeService.versions;\n }\n\n public get activeVersion(): string {\n return this._core.unicodeService.activeVersion;\n }\n\n public set activeVersion(version: string) {\n this._core.unicodeService.activeVersion = version;\n }\n}\n","/**\n * Copyright (c) 2014 The xterm.js authors. All rights reserved.\n * Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)\n * @license MIT\n *\n * Originally forked from (with the author's permission):\n * Fabrice Bellard's javascript vt100 for jslinux:\n * http://bellard.org/jslinux/\n * Copyright (c) 2011 Fabrice Bellard\n * The original design remains. The terminal itself\n * has been extended to include xterm CSI codes, among\n * other features.\n *\n * Terminal Emulation References:\n * http://vt100.net/\n * http://invisible-island.net/xterm/ctlseqs/ctlseqs.txt\n * http://invisible-island.net/xterm/ctlseqs/ctlseqs.html\n * http://invisible-island.net/vttest/\n * http://www.inwap.com/pdp10/ansicode.txt\n * http://linux.die.net/man/4/console_codes\n * http://linux.die.net/man/7/urxvt\n */\n\nimport { IInputHandlingTerminal, ICompositionHelper, ITerminalOptions, ITerminal, IBrowser, CustomKeyEventHandler } from './Types';\nimport { IRenderer, CharacterJoinerHandler } from 'browser/renderer/Types';\nimport { CompositionHelper } from 'browser/input/CompositionHelper';\nimport { Viewport } from 'browser/Viewport';\nimport { rightClickHandler, moveTextAreaUnderMouseCursor, handlePasteEvent, copyHandler, paste } from 'browser/Clipboard';\nimport { C0 } from 'common/data/EscapeSequences';\nimport { InputHandler } from './InputHandler';\nimport { Renderer } from 'browser/renderer/Renderer';\nimport { Linkifier } from 'browser/Linkifier';\nimport { SelectionService } from 'browser/services/SelectionService';\nimport * as Browser from 'common/Platform';\nimport { addDisposableDomListener } from 'browser/Lifecycle';\nimport * as Strings from 'browser/LocalizableStrings';\nimport { SoundService } from 'browser/services/SoundService';\nimport { MouseZoneManager } from 'browser/MouseZoneManager';\nimport { AccessibilityManager } from './AccessibilityManager';\nimport { ITheme, IMarker, IDisposable, ISelectionPosition } from 'xterm';\nimport { DomRenderer } from 'browser/renderer/dom/DomRenderer';\nimport { IKeyboardEvent, KeyboardResultType, IBufferLine, IAttributeData, CoreMouseEventType, CoreMouseButton, CoreMouseAction } from 'common/Types';\nimport { evaluateKeyboardEvent } from 'common/input/Keyboard';\nimport { EventEmitter, IEvent } from 'common/EventEmitter';\nimport { DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine';\nimport { updateWindowsModeWrappedState } from 'common/WindowsMode';\nimport { ColorManager } from 'browser/ColorManager';\nimport { RenderService } from 'browser/services/RenderService';\nimport { IOptionsService, IBufferService, ICoreMouseService, ICoreService, ILogService, IDirtyRowService, IInstantiationService, ICharsetService, IUnicodeService } from 'common/services/Services';\nimport { OptionsService } from 'common/services/OptionsService';\nimport { ICharSizeService, IRenderService, IMouseService, ISelectionService, ISoundService, ICoreBrowserService } from 'browser/services/Services';\nimport { CharSizeService } from 'browser/services/CharSizeService';\nimport { BufferService, MINIMUM_COLS, MINIMUM_ROWS } from 'common/services/BufferService';\nimport { Disposable } from 'common/Lifecycle';\nimport { IBufferSet, IBuffer } from 'common/buffer/Types';\nimport { MouseService } from 'browser/services/MouseService';\nimport { IParams, IFunctionIdentifier } from 'common/parser/Types';\nimport { CoreService } from 'common/services/CoreService';\nimport { LogService } from 'common/services/LogService';\nimport { ILinkifier, IMouseZoneManager, LinkMatcherHandler, ILinkMatcherOptions, IViewport } from 'browser/Types';\nimport { DirtyRowService } from 'common/services/DirtyRowService';\nimport { InstantiationService } from 'common/services/InstantiationService';\nimport { CoreMouseService } from 'common/services/CoreMouseService';\nimport { WriteBuffer } from 'common/input/WriteBuffer';\nimport { CoreBrowserService } from 'browser/services/CoreBrowserService';\nimport { UnicodeService } from 'common/services/UnicodeService';\nimport { CharsetService } from 'common/services/CharsetService';\n\n// Let it work inside Node.js for automated testing purposes.\nconst document = (typeof window !== 'undefined') ? window.document : null;\n\n\nexport class Terminal extends Disposable implements ITerminal, IDisposable, IInputHandlingTerminal {\n public textarea: HTMLTextAreaElement;\n public element: HTMLElement;\n public screenElement: HTMLElement;\n\n private _document: Document;\n private _viewportScrollArea: HTMLElement;\n private _viewportElement: HTMLElement;\n private _helperContainer: HTMLElement;\n private _compositionView: HTMLElement;\n\n private _visualBellTimer: number;\n\n public browser: IBrowser = Browser;\n\n // TODO: We should remove options once components adopt optionsService\n public get options(): ITerminalOptions { return this.optionsService.options; }\n\n private _customKeyEventHandler: CustomKeyEventHandler;\n\n // common services\n private _bufferService: IBufferService;\n private _coreService: ICoreService;\n private _charsetService: ICharsetService;\n private _coreMouseService: ICoreMouseService;\n private _dirtyRowService: IDirtyRowService;\n private _instantiationService: IInstantiationService;\n private _logService: ILogService;\n public optionsService: IOptionsService;\n public unicodeService: IUnicodeService;\n\n // browser services\n private _charSizeService: ICharSizeService;\n private _mouseService: IMouseService;\n private _renderService: IRenderService;\n private _selectionService: ISelectionService;\n private _soundService: ISoundService;\n\n // modes\n public insertMode: boolean;\n public bracketedPasteMode: boolean;\n\n // mouse properties\n public mouseEvents: CoreMouseEventType = CoreMouseEventType.NONE;\n public sendFocus: boolean;\n\n // write buffer\n private _writeBuffer: WriteBuffer;\n\n // Store if user went browsing history in scrollback\n private _userScrolling: boolean;\n\n /**\n * Records whether the keydown event has already been handled and triggered a data event, if so\n * the keypress event should not trigger a data event but should still print to the textarea so\n * screen readers will announce it.\n */\n private _keyDownHandled: boolean = false;\n\n private _inputHandler: InputHandler;\n public linkifier: ILinkifier;\n public viewport: IViewport;\n private _compositionHelper: ICompositionHelper;\n private _mouseZoneManager: IMouseZoneManager;\n private _accessibilityManager: AccessibilityManager;\n private _colorManager: ColorManager;\n private _theme: ITheme;\n private _windowsMode: IDisposable | undefined;\n\n // bufferline to clone/copy from for new blank lines\n private _blankLine: IBufferLine = null;\n\n public get cols(): number { return this._bufferService.cols; }\n public get rows(): number { return this._bufferService.rows; }\n\n private _onCursorMove = new EventEmitter();\n public get onCursorMove(): IEvent { return this._onCursorMove.event; }\n private _onData = new EventEmitter();\n public get onData(): IEvent { return this._onData.event; }\n private _onBinary = new EventEmitter();\n public get onBinary(): IEvent { return this._onBinary.event; }\n private _onKey = new EventEmitter<{ key: string, domEvent: KeyboardEvent }>();\n public get onKey(): IEvent<{ key: string, domEvent: KeyboardEvent }> { return this._onKey.event; }\n private _onLineFeed = new EventEmitter();\n public get onLineFeed(): IEvent { return this._onLineFeed.event; }\n private _onRender = new EventEmitter<{ start: number, end: number }>();\n public get onRender(): IEvent<{ start: number, end: number }> { return this._onRender.event; }\n private _onResize = new EventEmitter<{ cols: number, rows: number }>();\n public get onResize(): IEvent<{ cols: number, rows: number }> { return this._onResize.event; }\n private _onScroll = new EventEmitter();\n public get onScroll(): IEvent { return this._onScroll.event; }\n private _onSelectionChange = new EventEmitter();\n public get onSelectionChange(): IEvent { return this._onSelectionChange.event; }\n private _onTitleChange = new EventEmitter();\n public get onTitleChange(): IEvent { return this._onTitleChange.event; }\n\n private _onFocus = new EventEmitter();\n public get onFocus(): IEvent { return this._onFocus.event; }\n private _onBlur = new EventEmitter();\n public get onBlur(): IEvent { return this._onBlur.event; }\n public onA11yCharEmitter = new EventEmitter();\n public get onA11yChar(): IEvent { return this.onA11yCharEmitter.event; }\n public onA11yTabEmitter = new EventEmitter();\n public get onA11yTab(): IEvent { return this.onA11yTabEmitter.event; }\n\n /**\n * Creates a new `Terminal` object.\n *\n * @param options An object containing a set of options, the available options are:\n * - `cursorBlink` (boolean): Whether the terminal cursor blinks\n * - `cols` (number): The number of columns of the terminal (horizontal size)\n * - `rows` (number): The number of rows of the terminal (vertical size)\n *\n * @public\n * @class Xterm Xterm\n * @alias module:xterm/src/xterm\n */\n constructor(\n options: ITerminalOptions = {}\n ) {\n super();\n\n // Setup and initialize common services\n this._instantiationService = new InstantiationService();\n this.optionsService = new OptionsService(options);\n this._instantiationService.setService(IOptionsService, this.optionsService);\n this._bufferService = this._instantiationService.createInstance(BufferService);\n this._instantiationService.setService(IBufferService, this._bufferService);\n this._logService = this._instantiationService.createInstance(LogService);\n this._instantiationService.setService(ILogService, this._logService);\n this._coreService = this._instantiationService.createInstance(CoreService, () => this.scrollToBottom());\n this._instantiationService.setService(ICoreService, this._coreService);\n this._coreService.onData(e => this._onData.fire(e));\n this._coreService.onBinary(e => this._onBinary.fire(e));\n this._coreMouseService = this._instantiationService.createInstance(CoreMouseService);\n this._instantiationService.setService(ICoreMouseService, this._coreMouseService);\n this._dirtyRowService = this._instantiationService.createInstance(DirtyRowService);\n this._instantiationService.setService(IDirtyRowService, this._dirtyRowService);\n this.unicodeService = this._instantiationService.createInstance(UnicodeService);\n this._instantiationService.setService(IUnicodeService, this.unicodeService);\n this._charsetService = this._instantiationService.createInstance(CharsetService);\n this._instantiationService.setService(ICharsetService, this._charsetService);\n\n this._setupOptionsListeners();\n this._setup();\n\n this._writeBuffer = new WriteBuffer(data => this._inputHandler.parse(data));\n }\n\n public dispose(): void {\n if (this._isDisposed) {\n return;\n }\n super.dispose();\n this._windowsMode?.dispose();\n this._windowsMode = undefined;\n this._renderService?.dispose();\n this._customKeyEventHandler = null;\n this.write = () => {};\n this.element?.parentNode?.removeChild(this.element);\n }\n\n private _setup(): void {\n this._customKeyEventHandler = null;\n\n // modes\n this.insertMode = false;\n this.bracketedPasteMode = false;\n\n this._userScrolling = false;\n\n if (this._inputHandler) {\n this._inputHandler.reset();\n } else {\n // Register input handler and refire/handle events\n this._inputHandler = new InputHandler(this, this._bufferService, this._charsetService, this._coreService, this._dirtyRowService, this._logService, this.optionsService, this._coreMouseService, this.unicodeService, this._instantiationService);\n this._inputHandler.onRequestBell(() => this.bell());\n this._inputHandler.onRequestRefreshRows((start, end) => this.refresh(start, end));\n this._inputHandler.onRequestReset(() => this.reset());\n this._inputHandler.onCursorMove(() => this._onCursorMove.fire());\n this._inputHandler.onLineFeed(() => this._onLineFeed.fire());\n this.register(this._inputHandler);\n }\n\n if (!this.linkifier) {\n this.linkifier = new Linkifier(this._bufferService, this._logService, this.optionsService, this.unicodeService);\n }\n\n if (this.options.windowsMode) {\n this._enableWindowsMode();\n }\n }\n\n private _enableWindowsMode(): void {\n if (!this._windowsMode) {\n const disposables: IDisposable[] = [];\n disposables.push(this.onLineFeed(updateWindowsModeWrappedState.bind(null, this._bufferService)));\n disposables.push(this.addCsiHandler({ final: 'H' }, () => {\n updateWindowsModeWrappedState(this._bufferService);\n return false;\n }));\n this._windowsMode = {\n dispose: () => {\n disposables.forEach(d => d.dispose());\n }\n };\n }\n }\n\n /**\n * Convenience property to active buffer.\n */\n public get buffer(): IBuffer {\n return this.buffers.active;\n }\n\n public get buffers(): IBufferSet {\n return this._bufferService.buffers;\n }\n\n /**\n * Focus the terminal. Delegates focus handling to the terminal's DOM element.\n */\n public focus(): void {\n if (this.textarea) {\n this.textarea.focus({ preventScroll: true });\n }\n }\n\n private _setupOptionsListeners(): void {\n // TODO: These listeners should be owned by individual components\n this.optionsService.onOptionChange(key => {\n switch (key) {\n case 'fontFamily':\n case 'fontSize':\n // When the font changes the size of the cells may change which requires a renderer clear\n this._renderService?.clear();\n this._charSizeService?.measure();\n break;\n case 'cursorBlink':\n case 'cursorStyle':\n // The DOM renderer needs a row refresh to update the cursor styles\n this.refresh(this.buffer.y, this.buffer.y);\n break;\n case 'drawBoldTextInBrightColors':\n case 'letterSpacing':\n case 'lineHeight':\n case 'fontWeight':\n case 'fontWeightBold':\n case 'minimumContrastRatio':\n // When the font changes the size of the cells may change which requires a renderer clear\n if (this._renderService) {\n this._renderService.clear();\n this._renderService.onResize(this.cols, this.rows);\n this.refresh(0, this.rows - 1);\n }\n break;\n case 'rendererType':\n if (this._renderService) {\n this._renderService.setRenderer(this._createRenderer());\n this._renderService.onResize(this.cols, this.rows);\n }\n break;\n case 'scrollback':\n this.buffers.resize(this.cols, this.rows);\n this.viewport?.syncScrollArea();\n break;\n case 'screenReaderMode':\n if (this.optionsService.options.screenReaderMode) {\n if (!this._accessibilityManager && this._renderService) {\n this._accessibilityManager = new AccessibilityManager(this, this._renderService);\n }\n } else {\n this._accessibilityManager?.dispose();\n this._accessibilityManager = null;\n }\n break;\n case 'tabStopWidth': this.buffers.setupTabStops(); break;\n case 'theme':\n this._setTheme(this.optionsService.options.theme);\n break;\n case 'windowsMode':\n if (this.optionsService.options.windowsMode) {\n this._enableWindowsMode();\n } else {\n this._windowsMode?.dispose();\n this._windowsMode = undefined;\n }\n break;\n }\n });\n }\n\n /**\n * Binds the desired focus behavior on a given terminal object.\n */\n private _onTextAreaFocus(ev: KeyboardEvent): void {\n if (this.sendFocus) {\n this._coreService.triggerDataEvent(C0.ESC + '[I');\n }\n this.updateCursorStyle(ev);\n this.element.classList.add('focus');\n this.showCursor();\n this._onFocus.fire();\n }\n\n /**\n * Blur the terminal, calling the blur function on the terminal's underlying\n * textarea.\n */\n public blur(): void {\n return this.textarea.blur();\n }\n\n /**\n * Binds the desired blur behavior on a given terminal object.\n */\n private _onTextAreaBlur(): void {\n // Text can safely be removed on blur. Doing it earlier could interfere with\n // screen readers reading it out.\n this.textarea.value = '';\n this.refresh(this.buffer.y, this.buffer.y);\n if (this.sendFocus) {\n this._coreService.triggerDataEvent(C0.ESC + '[O');\n }\n this.element.classList.remove('focus');\n this._onBlur.fire();\n }\n\n /**\n * Initialize default behavior\n */\n private _initGlobal(): void {\n this._bindKeys();\n\n // Bind clipboard functionality\n this.register(addDisposableDomListener(this.element, 'copy', (event: ClipboardEvent) => {\n // If mouse events are active it means the selection manager is disabled and\n // copy should be handled by the host program.\n if (!this.hasSelection()) {\n return;\n }\n copyHandler(event, this._selectionService);\n }));\n const pasteHandlerWrapper = (event: ClipboardEvent) => handlePasteEvent(event, this.textarea, this.bracketedPasteMode, this._coreService);\n this.register(addDisposableDomListener(this.textarea, 'paste', pasteHandlerWrapper));\n this.register(addDisposableDomListener(this.element, 'paste', pasteHandlerWrapper));\n\n // Handle right click context menus\n if (Browser.isFirefox) {\n // Firefox doesn't appear to fire the contextmenu event on right click\n this.register(addDisposableDomListener(this.element, 'mousedown', (event: MouseEvent) => {\n if (event.button === 2) {\n rightClickHandler(event, this.textarea, this.screenElement, this._selectionService, this.options.rightClickSelectsWord);\n }\n }));\n } else {\n this.register(addDisposableDomListener(this.element, 'contextmenu', (event: MouseEvent) => {\n rightClickHandler(event, this.textarea, this.screenElement, this._selectionService, this.options.rightClickSelectsWord);\n }));\n }\n\n // Move the textarea under the cursor when middle clicking on Linux to ensure\n // middle click to paste selection works. This only appears to work in Chrome\n // at the time is writing.\n if (Browser.isLinux) {\n // Use auxclick event over mousedown the latter doesn't seem to work. Note\n // that the regular click event doesn't fire for the middle mouse button.\n this.register(addDisposableDomListener(this.element, 'auxclick', (event: MouseEvent) => {\n if (event.button === 1) {\n moveTextAreaUnderMouseCursor(event, this.textarea, this.screenElement);\n }\n }));\n }\n }\n\n /**\n * Apply key handling to the terminal\n */\n private _bindKeys(): void {\n this.register(addDisposableDomListener(this.textarea, 'keyup', (ev: KeyboardEvent) => this._keyUp(ev), true));\n this.register(addDisposableDomListener(this.textarea, 'keydown', (ev: KeyboardEvent) => this._keyDown(ev), true));\n this.register(addDisposableDomListener(this.textarea, 'keypress', (ev: KeyboardEvent) => this._keyPress(ev), true));\n this.register(addDisposableDomListener(this.textarea, 'compositionstart', () => this._compositionHelper.compositionstart()));\n this.register(addDisposableDomListener(this.textarea, 'compositionupdate', (e: CompositionEvent) => this._compositionHelper.compositionupdate(e)));\n this.register(addDisposableDomListener(this.textarea, 'compositionend', () => this._compositionHelper.compositionend()));\n this.register(this.onRender(() => this._compositionHelper.updateCompositionElements()));\n this.register(this.onRender(e => this._queueLinkification(e.start, e.end)));\n }\n\n /**\n * Opens the terminal within an element.\n *\n * @param parent The element to create the terminal within.\n */\n public open(parent: HTMLElement): void {\n if (!parent) {\n throw new Error('Terminal requires a parent element.');\n }\n\n if (!document.body.contains(parent)) {\n this._logService.warn('Terminal.open was called on an element that was not attached to the DOM');\n }\n\n this._document = parent.ownerDocument;\n\n // Create main element container\n this.element = this._document.createElement('div');\n this.element.dir = 'ltr'; // xterm.css assumes LTR\n this.element.classList.add('terminal');\n this.element.classList.add('xterm');\n this.element.setAttribute('tabindex', '0');\n parent.appendChild(this.element);\n\n // Performance: Use a document fragment to build the terminal\n // viewport and helper elements detached from the DOM\n const fragment = document.createDocumentFragment();\n this._viewportElement = document.createElement('div');\n this._viewportElement.classList.add('xterm-viewport');\n fragment.appendChild(this._viewportElement);\n this._viewportScrollArea = document.createElement('div');\n this._viewportScrollArea.classList.add('xterm-scroll-area');\n this._viewportElement.appendChild(this._viewportScrollArea);\n\n this.screenElement = document.createElement('div');\n this.screenElement.classList.add('xterm-screen');\n // Create the container that will hold helpers like the textarea for\n // capturing DOM Events. Then produce the helpers.\n this._helperContainer = document.createElement('div');\n this._helperContainer.classList.add('xterm-helpers');\n this.screenElement.appendChild(this._helperContainer);\n fragment.appendChild(this.screenElement);\n\n this.textarea = document.createElement('textarea');\n this.textarea.classList.add('xterm-helper-textarea');\n this.textarea.setAttribute('aria-label', Strings.promptLabel);\n this.textarea.setAttribute('aria-multiline', 'false');\n this.textarea.setAttribute('autocorrect', 'off');\n this.textarea.setAttribute('autocapitalize', 'off');\n this.textarea.setAttribute('spellcheck', 'false');\n this.textarea.tabIndex = 0;\n this.register(addDisposableDomListener(this.textarea, 'focus', (ev: KeyboardEvent) => this._onTextAreaFocus(ev)));\n this.register(addDisposableDomListener(this.textarea, 'blur', () => this._onTextAreaBlur()));\n this._helperContainer.appendChild(this.textarea);\n\n const coreBrowserService = this._instantiationService.createInstance(CoreBrowserService, this.textarea);\n this._instantiationService.setService(ICoreBrowserService, coreBrowserService);\n\n this._charSizeService = this._instantiationService.createInstance(CharSizeService, this._document, this._helperContainer);\n this._instantiationService.setService(ICharSizeService, this._charSizeService);\n\n this._compositionView = document.createElement('div');\n this._compositionView.classList.add('composition-view');\n this._compositionHelper = this._instantiationService.createInstance(CompositionHelper, this.textarea, this._compositionView);\n this._helperContainer.appendChild(this._compositionView);\n\n // Performance: Add viewport and helper elements from the fragment\n this.element.appendChild(fragment);\n\n this._theme = this.options.theme || this._theme;\n this.options.theme = undefined;\n this._colorManager = new ColorManager(document, this.options.allowTransparency);\n this.optionsService.onOptionChange(e => this._colorManager.onOptionsChange(e));\n this._colorManager.setTheme(this._theme);\n\n const renderer = this._createRenderer();\n this._renderService = this._instantiationService.createInstance(RenderService, renderer, this.rows, this.screenElement);\n this._instantiationService.setService(IRenderService, this._renderService);\n this._renderService.onRender(e => this._onRender.fire(e));\n this.onResize(e => this._renderService.resize(e.cols, e.rows));\n\n this._soundService = this._instantiationService.createInstance(SoundService);\n this._instantiationService.setService(ISoundService, this._soundService);\n this._mouseService = this._instantiationService.createInstance(MouseService);\n this._instantiationService.setService(IMouseService, this._mouseService);\n\n this.viewport = this._instantiationService.createInstance(Viewport,\n (amount: number, suppressEvent: boolean) => this.scrollLines(amount, suppressEvent),\n this._viewportElement,\n this._viewportScrollArea\n );\n this.viewport.onThemeChange(this._colorManager.colors);\n this.register(this.viewport);\n\n this.register(this.onCursorMove(() => this._renderService.onCursorMove()));\n this.register(this.onResize(() => this._renderService.onResize(this.cols, this.rows)));\n this.register(this.onBlur(() => this._renderService.onBlur()));\n this.register(this.onFocus(() => this._renderService.onFocus()));\n this.register(this._renderService.onDimensionsChange(() => this.viewport.syncScrollArea()));\n\n this._selectionService = this._instantiationService.createInstance(SelectionService,\n (amount: number, suppressEvent: boolean) => this.scrollLines(amount, suppressEvent),\n this.element,\n this.screenElement);\n this._instantiationService.setService(ISelectionService, this._selectionService);\n this.register(this._selectionService.onSelectionChange(() => this._onSelectionChange.fire()));\n this.register(this._selectionService.onRedrawRequest(e => this._renderService.onSelectionChanged(e.start, e.end, e.columnSelectMode)));\n this.register(this._selectionService.onLinuxMouseSelection(text => {\n // If there's a new selection, put it into the textarea, focus and select it\n // in order to register it as a selection on the OS. This event is fired\n // only on Linux to enable middle click to paste selection.\n this.textarea.value = text;\n this.textarea.focus();\n this.textarea.select();\n }));\n this.register(this.onScroll(() => {\n this.viewport.syncScrollArea();\n this._selectionService.refresh();\n }));\n this.register(addDisposableDomListener(this._viewportElement, 'scroll', () => this._selectionService.refresh()));\n\n this._mouseZoneManager = this._instantiationService.createInstance(MouseZoneManager, this.element, this.screenElement);\n this.register(this._mouseZoneManager);\n this.register(this.onScroll(() => this._mouseZoneManager.clearAll()));\n this.linkifier.attachToDom(this.element, this._mouseZoneManager);\n\n // This event listener must be registered aftre MouseZoneManager is created\n this.register(addDisposableDomListener(this.element, 'mousedown', (e: MouseEvent) => this._selectionService.onMouseDown(e)));\n\n // apply mouse event classes set by escape codes before terminal was attached\n if (this.mouseEvents) {\n this._selectionService.disable();\n this.element.classList.add('enable-mouse-events');\n } else {\n this._selectionService.enable();\n }\n\n if (this.options.screenReaderMode) {\n // Note that this must be done *after* the renderer is created in order to\n // ensure the correct order of the dprchange event\n this._accessibilityManager = new AccessibilityManager(this, this._renderService);\n }\n\n // Measure the character size\n this._charSizeService.measure();\n\n // Setup loop that draws to screen\n this.refresh(0, this.rows - 1);\n\n // Initialize global actions that need to be taken on the document.\n this._initGlobal();\n\n // Listen for mouse events and translate\n // them into terminal mouse protocols.\n this.bindMouse();\n }\n\n private _createRenderer(): IRenderer {\n switch (this.options.rendererType) {\n case 'canvas': return this._instantiationService.createInstance(Renderer, this._colorManager.colors, this.screenElement, this.linkifier);\n case 'dom': return this._instantiationService.createInstance(DomRenderer, this._colorManager.colors, this.element, this.screenElement, this._viewportElement, this.linkifier);\n default: throw new Error(`Unrecognized rendererType \"${this.options.rendererType}\"`);\n }\n }\n\n /**\n * Sets the theme on the renderer. The renderer must have been initialized.\n * @param theme The theme to set.\n */\n private _setTheme(theme: ITheme): void {\n this._theme = theme;\n this._colorManager?.setTheme(theme);\n this._renderService?.setColors(this._colorManager.colors);\n this.viewport?.onThemeChange(this._colorManager.colors);\n }\n\n /**\n * Bind certain mouse events to the terminal.\n * By default only 3 button + wheel up/down is ativated. For higher buttons\n * no mouse report will be created. Typically the standard actions will be active.\n *\n * There are several reasons not to enable support for higher buttons/wheel:\n * - Button 4 and 5 are typically used for history back and forward navigation,\n * there is no straight forward way to supress/intercept those standard actions.\n * - Support for higher buttons does not work in some platform/browser combinations.\n * - Left/right wheel was not tested.\n * - Emulators vary in mouse button support, typically only 3 buttons and\n * wheel up/down work reliable.\n *\n * TODO: Move mouse event code into its own file.\n */\n public bindMouse(): void {\n const self = this;\n const el = this.element;\n\n // send event to CoreMouseService\n function sendEvent(ev: MouseEvent | WheelEvent): boolean {\n let pos;\n\n // get mouse coordinates\n pos = self._mouseService.getRawByteCoords(ev, self.screenElement, self.cols, self.rows);\n if (!pos) {\n return false;\n }\n\n let but: CoreMouseButton;\n let action: CoreMouseAction;\n switch ((ev).overrideType || ev.type) {\n case 'mousemove':\n action = CoreMouseAction.MOVE;\n if (ev.buttons === undefined) {\n // buttons is not supported on macOS, try to get a value from button instead\n but = CoreMouseButton.NONE;\n if (ev.button !== undefined) {\n but = ev.button < 3 ? ev.button : CoreMouseButton.NONE;\n }\n } else {\n // according to MDN buttons only reports up to button 5 (AUX2)\n but = ev.buttons & 1 ? CoreMouseButton.LEFT :\n ev.buttons & 4 ? CoreMouseButton.MIDDLE :\n ev.buttons & 2 ? CoreMouseButton.RIGHT :\n CoreMouseButton.NONE; // fallback to NONE\n }\n break;\n case 'mouseup':\n action = CoreMouseAction.UP;\n but = ev.button < 3 ? ev.button : CoreMouseButton.NONE;\n break;\n case 'mousedown':\n action = CoreMouseAction.DOWN;\n but = ev.button < 3 ? ev.button : CoreMouseButton.NONE;\n break;\n case 'wheel':\n // only UP/DOWN wheel events are respected\n if ((ev as WheelEvent).deltaY !== 0) {\n action = (ev as WheelEvent).deltaY < 0 ? CoreMouseAction.UP : CoreMouseAction.DOWN;\n }\n but = CoreMouseButton.WHEEL;\n break;\n default:\n // dont handle other event types by accident\n return false;\n }\n\n // exit if we cannot determine valid button/action values\n // do nothing for higher buttons than wheel\n if (action === undefined || but === undefined || but > CoreMouseButton.WHEEL) {\n return false;\n }\n\n return self._coreMouseService.triggerMouseEvent({\n col: pos.x - 33, // FIXME: why -33 here?\n row: pos.y - 33,\n button: but,\n action,\n ctrl: ev.ctrlKey,\n alt: ev.altKey,\n shift: ev.shiftKey\n });\n }\n\n /**\n * Event listener state handling.\n * We listen to the onProtocolChange event of CoreMouseService and put\n * requested listeners in `requestedEvents`. With this the listeners\n * have all bits to do the event listener juggling.\n * Note: 'mousedown' currently is \"always on\" and not managed\n * by onProtocolChange.\n */\n const requestedEvents: {[key: string]: ((ev: Event) => void) | null} = {\n mouseup: null,\n wheel: null,\n mousedrag: null,\n mousemove: null\n };\n const eventListeners: {[key: string]: (ev: Event) => void} = {\n mouseup: (ev: MouseEvent) => {\n sendEvent(ev);\n if (!ev.buttons) {\n // if no other button is held remove global handlers\n this._document.removeEventListener('mouseup', requestedEvents.mouseup);\n if (requestedEvents.mousedrag) {\n this._document.removeEventListener('mousemove', requestedEvents.mousedrag);\n }\n }\n return this.cancel(ev);\n },\n wheel: (ev: WheelEvent) => {\n sendEvent(ev);\n ev.preventDefault();\n return this.cancel(ev);\n },\n mousedrag: (ev: MouseEvent) => {\n // deal only with move while a button is held\n if (ev.buttons) {\n sendEvent(ev);\n }\n },\n mousemove: (ev: MouseEvent) => {\n // deal only with move without any button\n if (!ev.buttons) {\n sendEvent(ev);\n }\n }\n };\n this._coreMouseService.onProtocolChange(events => {\n // apply global changes on events\n this.mouseEvents = events;\n if (events) {\n if (this.optionsService.options.logLevel === 'debug') {\n this._logService.debug('Binding to mouse events:', this._coreMouseService.explainEvents(events));\n }\n this.element.classList.add('enable-mouse-events');\n this._selectionService.disable();\n } else {\n this._logService.debug('Unbinding from mouse events.');\n this.element.classList.remove('enable-mouse-events');\n this._selectionService.enable();\n }\n\n // add/remove handlers from requestedEvents\n\n if (!(events & CoreMouseEventType.MOVE)) {\n el.removeEventListener('mousemove', requestedEvents.mousemove);\n requestedEvents.mousemove = null;\n } else if (!requestedEvents.mousemove) {\n el.addEventListener('mousemove', eventListeners.mousemove);\n requestedEvents.mousemove = eventListeners.mousemove;\n }\n\n if (!(events & CoreMouseEventType.WHEEL)) {\n el.removeEventListener('wheel', requestedEvents.wheel);\n requestedEvents.wheel = null;\n } else if (!requestedEvents.wheel) {\n el.addEventListener('wheel', eventListeners.wheel);\n requestedEvents.wheel = eventListeners.wheel;\n }\n\n if (!(events & CoreMouseEventType.UP)) {\n this._document.removeEventListener('mouseup', requestedEvents.mouseup);\n requestedEvents.mouseup = null;\n } else if (!requestedEvents.mouseup) {\n requestedEvents.mouseup = eventListeners.mouseup;\n }\n\n if (!(events & CoreMouseEventType.DRAG)) {\n this._document.removeEventListener('mousemove', requestedEvents.mousedrag);\n requestedEvents.mousedrag = null;\n } else if (!requestedEvents.mousedrag) {\n requestedEvents.mousedrag = eventListeners.mousedrag;\n }\n });\n // force initial onProtocolChange so we dont miss early mouse requests\n this._coreMouseService.activeProtocol = this._coreMouseService.activeProtocol;\n\n /**\n * \"Always on\" event listeners.\n */\n this.register(addDisposableDomListener(el, 'mousedown', (ev: MouseEvent) => {\n ev.preventDefault();\n this.focus();\n\n // Don't send the mouse button to the pty if mouse events are disabled or\n // if the selection manager is having selection forced (ie. a modifier is\n // held).\n if (!this.mouseEvents || this._selectionService.shouldForceSelection(ev)) {\n return;\n }\n\n sendEvent(ev);\n\n // Register additional global handlers which should keep reporting outside\n // of the terminal element.\n // Note: Other emulators also do this for 'mousedown' while a button\n // is held, we currently limit 'mousedown' to the terminal only.\n if (requestedEvents.mouseup) {\n this._document.addEventListener('mouseup', requestedEvents.mouseup);\n }\n if (requestedEvents.mousedrag) {\n this._document.addEventListener('mousemove', requestedEvents.mousedrag);\n }\n\n return this.cancel(ev);\n }));\n\n this.register(addDisposableDomListener(el, 'wheel', (ev: WheelEvent) => {\n if (!requestedEvents.wheel) {\n // Convert wheel events into up/down events when the buffer does not have scrollback, this\n // enables scrolling in apps hosted in the alt buffer such as vim or tmux.\n if (!this.buffer.hasScrollback) {\n const amount = this.viewport.getLinesScrolled(ev);\n\n // Do nothing if there's no vertical scroll\n if (amount === 0) {\n return;\n }\n\n // Construct and send sequences\n const sequence = C0.ESC + (this._coreService.decPrivateModes.applicationCursorKeys ? 'O' : '[') + ( ev.deltaY < 0 ? 'A' : 'B');\n let data = '';\n for (let i = 0; i < Math.abs(amount); i++) {\n data += sequence;\n }\n this._coreService.triggerDataEvent(data, true);\n }\n return;\n }\n }));\n\n // allow wheel scrolling in\n // the shell for example\n this.register(addDisposableDomListener(el, 'wheel', (ev: WheelEvent) => {\n if (requestedEvents.wheel) return;\n if (!this.viewport.onWheel(ev)) {\n return this.cancel(ev);\n }\n }));\n\n this.register(addDisposableDomListener(el, 'touchstart', (ev: TouchEvent) => {\n if (this.mouseEvents) return;\n this.viewport.onTouchStart(ev);\n return this.cancel(ev);\n }));\n\n this.register(addDisposableDomListener(el, 'touchmove', (ev: TouchEvent) => {\n if (this.mouseEvents) return;\n if (!this.viewport.onTouchMove(ev)) {\n return this.cancel(ev);\n }\n }));\n }\n\n\n /**\n * Tells the renderer to refresh terminal content between two rows (inclusive) at the next\n * opportunity.\n * @param start The row to start from (between 0 and this.rows - 1).\n * @param end The row to end at (between start and this.rows - 1).\n */\n public refresh(start: number, end: number): void {\n this._renderService?.refreshRows(start, end);\n }\n\n /**\n * Queues linkification for the specified rows.\n * @param start The row to start from (between 0 and this.rows - 1).\n * @param end The row to end at (between start and this.rows - 1).\n */\n private _queueLinkification(start: number, end: number): void {\n this.linkifier?.linkifyRows(start, end);\n }\n\n /**\n * Change the cursor style for different selection modes\n */\n public updateCursorStyle(ev: KeyboardEvent): void {\n if (this._selectionService && this._selectionService.shouldColumnSelect(ev)) {\n this.element.classList.add('column-select');\n } else {\n this.element.classList.remove('column-select');\n }\n }\n\n /**\n * Display the cursor element\n */\n public showCursor(): void {\n if (!this._coreService.isCursorInitialized) {\n this._coreService.isCursorInitialized = true;\n this.refresh(this.buffer.y, this.buffer.y);\n }\n }\n\n /**\n * Scroll the terminal down 1 row, creating a blank line.\n * @param isWrapped Whether the new line is wrapped from the previous line.\n */\n public scroll(eraseAttr: IAttributeData, isWrapped: boolean = false): void {\n let newLine: IBufferLine;\n newLine = this._blankLine;\n if (!newLine || newLine.length !== this.cols || newLine.getFg(0) !== eraseAttr.fg || newLine.getBg(0) !== eraseAttr.bg) {\n newLine = this.buffer.getBlankLine(eraseAttr, isWrapped);\n this._blankLine = newLine;\n }\n newLine.isWrapped = isWrapped;\n\n const topRow = this.buffer.ybase + this.buffer.scrollTop;\n const bottomRow = this.buffer.ybase + this.buffer.scrollBottom;\n\n if (this.buffer.scrollTop === 0) {\n // Determine whether the buffer is going to be trimmed after insertion.\n const willBufferBeTrimmed = this.buffer.lines.isFull;\n\n // Insert the line using the fastest method\n if (bottomRow === this.buffer.lines.length - 1) {\n if (willBufferBeTrimmed) {\n this.buffer.lines.recycle().copyFrom(newLine);\n } else {\n this.buffer.lines.push(newLine.clone());\n }\n } else {\n this.buffer.lines.splice(bottomRow + 1, 0, newLine.clone());\n }\n\n // Only adjust ybase and ydisp when the buffer is not trimmed\n if (!willBufferBeTrimmed) {\n this.buffer.ybase++;\n // Only scroll the ydisp with ybase if the user has not scrolled up\n if (!this._userScrolling) {\n this.buffer.ydisp++;\n }\n } else {\n // When the buffer is full and the user has scrolled up, keep the text\n // stable unless ydisp is right at the top\n if (this._userScrolling) {\n this.buffer.ydisp = Math.max(this.buffer.ydisp - 1, 0);\n }\n }\n } else {\n // scrollTop is non-zero which means no line will be going to the\n // scrollback, instead we can just shift them in-place.\n const scrollRegionHeight = bottomRow - topRow + 1/*as it's zero-based*/;\n this.buffer.lines.shiftElements(topRow + 1, scrollRegionHeight - 1, -1);\n this.buffer.lines.set(bottomRow, newLine.clone());\n }\n\n // Move the viewport to the bottom of the buffer unless the user is\n // scrolling.\n if (!this._userScrolling) {\n this.buffer.ydisp = this.buffer.ybase;\n }\n\n // Flag rows that need updating\n this._dirtyRowService.markRangeDirty(this.buffer.scrollTop, this.buffer.scrollBottom);\n\n this._onScroll.fire(this.buffer.ydisp);\n }\n\n /**\n * Scroll the display of the terminal\n * @param disp The number of lines to scroll down (negative scroll up).\n * @param suppressScrollEvent Don't emit the scroll event as scrollLines. This is used\n * to avoid unwanted events being handled by the viewport when the event was triggered from the\n * viewport originally.\n */\n public scrollLines(disp: number, suppressScrollEvent?: boolean): void {\n if (disp < 0) {\n if (this.buffer.ydisp === 0) {\n return;\n }\n this._userScrolling = true;\n } else if (disp + this.buffer.ydisp >= this.buffer.ybase) {\n this._userScrolling = false;\n }\n\n const oldYdisp = this.buffer.ydisp;\n this.buffer.ydisp = Math.max(Math.min(this.buffer.ydisp + disp, this.buffer.ybase), 0);\n\n // No change occurred, don't trigger scroll/refresh\n if (oldYdisp === this.buffer.ydisp) {\n return;\n }\n\n if (!suppressScrollEvent) {\n this._onScroll.fire(this.buffer.ydisp);\n }\n\n this.refresh(0, this.rows - 1);\n }\n\n /**\n * Scroll the display of the terminal by a number of pages.\n * @param pageCount The number of pages to scroll (negative scrolls up).\n */\n public scrollPages(pageCount: number): void {\n this.scrollLines(pageCount * (this.rows - 1));\n }\n\n /**\n * Scrolls the display of the terminal to the top.\n */\n public scrollToTop(): void {\n this.scrollLines(-this.buffer.ydisp);\n }\n\n /**\n * Scrolls the display of the terminal to the bottom.\n */\n public scrollToBottom(): void {\n this.scrollLines(this.buffer.ybase - this.buffer.ydisp);\n }\n\n public scrollToLine(line: number): void {\n const scrollAmount = line - this.buffer.ydisp;\n if (scrollAmount !== 0) {\n this.scrollLines(scrollAmount);\n }\n }\n\n public paste(data: string): void {\n paste(data, this.textarea, this.bracketedPasteMode, this._coreService);\n }\n\n /**\n * Attaches a custom key event handler which is run before keys are processed,\n * giving consumers of xterm.js ultimate control as to what keys should be\n * processed by the terminal and what keys should not.\n * @param customKeyEventHandler The custom KeyboardEvent handler to attach.\n * This is a function that takes a KeyboardEvent, allowing consumers to stop\n * propagation and/or prevent the default action. The function returns whether\n * the event should be processed by xterm.js.\n */\n public attachCustomKeyEventHandler(customKeyEventHandler: CustomKeyEventHandler): void {\n this._customKeyEventHandler = customKeyEventHandler;\n }\n\n /** Add handler for ESC escape sequence. See xterm.d.ts for details. */\n public addEscHandler(id: IFunctionIdentifier, callback: () => boolean): IDisposable {\n return this._inputHandler.addEscHandler(id, callback);\n }\n\n /** Add handler for DCS escape sequence. See xterm.d.ts for details. */\n public addDcsHandler(id: IFunctionIdentifier, callback: (data: string, param: IParams) => boolean): IDisposable {\n return this._inputHandler.addDcsHandler(id, callback);\n }\n\n /** Add handler for CSI escape sequence. See xterm.d.ts for details. */\n public addCsiHandler(id: IFunctionIdentifier, callback: (params: IParams) => boolean): IDisposable {\n return this._inputHandler.addCsiHandler(id, callback);\n }\n /** Add handler for OSC escape sequence. See xterm.d.ts for details. */\n public addOscHandler(ident: number, callback: (data: string) => boolean): IDisposable {\n return this._inputHandler.addOscHandler(ident, callback);\n }\n\n /**\n * Registers a link matcher, allowing custom link patterns to be matched and\n * handled.\n * @param regex The regular expression to search for, specifically\n * this searches the textContent of the rows. You will want to use \\s to match\n * a space ' ' character for example.\n * @param handler The callback when the link is called.\n * @param options Options for the link matcher.\n * @return The ID of the new matcher, this can be used to deregister.\n */\n public registerLinkMatcher(regex: RegExp, handler: LinkMatcherHandler, options?: ILinkMatcherOptions): number {\n const matcherId = this.linkifier.registerLinkMatcher(regex, handler, options);\n this.refresh(0, this.rows - 1);\n return matcherId;\n }\n\n /**\n * Deregisters a link matcher if it has been registered.\n * @param matcherId The link matcher's ID (returned after register)\n */\n public deregisterLinkMatcher(matcherId: number): void {\n if (this.linkifier.deregisterLinkMatcher(matcherId)) {\n this.refresh(0, this.rows - 1);\n }\n }\n\n public registerCharacterJoiner(handler: CharacterJoinerHandler): number {\n const joinerId = this._renderService.registerCharacterJoiner(handler);\n this.refresh(0, this.rows - 1);\n return joinerId;\n }\n\n public deregisterCharacterJoiner(joinerId: number): void {\n if (this._renderService.deregisterCharacterJoiner(joinerId)) {\n this.refresh(0, this.rows - 1);\n }\n }\n\n public get markers(): IMarker[] {\n return this.buffer.markers;\n }\n\n public addMarker(cursorYOffset: number): IMarker {\n // Disallow markers on the alt buffer\n if (this.buffer !== this.buffers.normal) {\n return;\n }\n\n return this.buffer.addMarker(this.buffer.ybase + this.buffer.y + cursorYOffset);\n }\n\n /**\n * Gets whether the terminal has an active selection.\n */\n public hasSelection(): boolean {\n return this._selectionService ? this._selectionService.hasSelection : false;\n }\n\n /**\n * Selects text within the terminal.\n * @param column The column the selection starts at..\n * @param row The row the selection starts at.\n * @param length The length of the selection.\n */\n public select(column: number, row: number, length: number): void {\n this._selectionService.setSelection(column, row, length);\n }\n\n /**\n * Gets the terminal's current selection, this is useful for implementing copy\n * behavior outside of xterm.js.\n */\n public getSelection(): string {\n return this._selectionService ? this._selectionService.selectionText : '';\n }\n\n public getSelectionPosition(): ISelectionPosition | undefined {\n if (!this._selectionService.hasSelection) {\n return undefined;\n }\n\n return {\n startColumn: this._selectionService.selectionStart[0],\n startRow: this._selectionService.selectionStart[1],\n endColumn: this._selectionService.selectionEnd[0],\n endRow: this._selectionService.selectionEnd[1]\n };\n }\n\n /**\n * Clears the current terminal selection.\n */\n public clearSelection(): void {\n this._selectionService?.clearSelection();\n }\n\n /**\n * Selects all text within the terminal.\n */\n public selectAll(): void {\n this._selectionService?.selectAll();\n }\n\n public selectLines(start: number, end: number): void {\n this._selectionService?.selectLines(start, end);\n }\n\n /**\n * Handle a keydown event\n * Key Resources:\n * - https://developer.mozilla.org/en-US/docs/DOM/KeyboardEvent\n * @param ev The keydown event to be handled.\n */\n protected _keyDown(event: KeyboardEvent): boolean {\n this._keyDownHandled = false;\n\n if (this._customKeyEventHandler && this._customKeyEventHandler(event) === false) {\n return false;\n }\n\n if (!this._compositionHelper.keydown(event)) {\n if (this.buffer.ybase !== this.buffer.ydisp) {\n this.scrollToBottom();\n }\n return false;\n }\n\n const result = evaluateKeyboardEvent(event, this._coreService.decPrivateModes.applicationCursorKeys, this.browser.isMac, this.options.macOptionIsMeta);\n\n this.updateCursorStyle(event);\n\n if (result.type === KeyboardResultType.PAGE_DOWN || result.type === KeyboardResultType.PAGE_UP) {\n const scrollCount = this.rows - 1;\n this.scrollLines(result.type === KeyboardResultType.PAGE_UP ? -scrollCount : scrollCount);\n return this.cancel(event, true);\n }\n\n if (result.type === KeyboardResultType.SELECT_ALL) {\n this.selectAll();\n }\n\n if (this._isThirdLevelShift(this.browser, event)) {\n return true;\n }\n\n if (result.cancel) {\n // The event is canceled at the end already, is this necessary?\n this.cancel(event, true);\n }\n\n if (!result.key) {\n return true;\n }\n\n // If ctrl+c or enter is being sent, clear out the textarea. This is done so that screen readers\n // will announce deleted characters. This will not work 100% of the time but it should cover\n // most scenarios.\n if (result.key === C0.ETX || result.key === C0.CR) {\n this.textarea.value = '';\n }\n\n this._onKey.fire({ key: result.key, domEvent: event });\n this.showCursor();\n this._coreService.triggerDataEvent(result.key, true);\n\n // Cancel events when not in screen reader mode so events don't get bubbled up and handled by\n // other listeners. When screen reader mode is enabled, this could cause issues if the event\n // is handled at a higher level, this is a compromise in order to echo keys to the screen\n // reader.\n if (!this.optionsService.options.screenReaderMode) {\n return this.cancel(event, true);\n }\n\n this._keyDownHandled = true;\n }\n\n private _isThirdLevelShift(browser: IBrowser, ev: IKeyboardEvent): boolean {\n const thirdLevelKey =\n (browser.isMac && !this.options.macOptionIsMeta && ev.altKey && !ev.ctrlKey && !ev.metaKey) ||\n (browser.isWindows && ev.altKey && ev.ctrlKey && !ev.metaKey);\n\n if (ev.type === 'keypress') {\n return thirdLevelKey;\n }\n\n // Don't invoke for arrows, pageDown, home, backspace, etc. (on non-keypress events)\n return thirdLevelKey && (!ev.keyCode || ev.keyCode > 47);\n }\n\n protected _keyUp(ev: KeyboardEvent): void {\n if (this._customKeyEventHandler && this._customKeyEventHandler(ev) === false) {\n return;\n }\n\n if (!wasModifierKeyOnlyEvent(ev)) {\n this.focus();\n }\n\n this.updateCursorStyle(ev);\n }\n\n /**\n * Handle a keypress event.\n * Key Resources:\n * - https://developer.mozilla.org/en-US/docs/DOM/KeyboardEvent\n * @param ev The keypress event to be handled.\n */\n protected _keyPress(ev: KeyboardEvent): boolean {\n let key;\n\n if (this._keyDownHandled) {\n return false;\n }\n\n if (this._customKeyEventHandler && this._customKeyEventHandler(ev) === false) {\n return false;\n }\n\n this.cancel(ev);\n\n if (ev.charCode) {\n key = ev.charCode;\n } else if (ev.which === null || ev.which === undefined) {\n key = ev.keyCode;\n } else if (ev.which !== 0 && ev.charCode !== 0) {\n key = ev.which;\n } else {\n return false;\n }\n\n if (!key || (\n (ev.altKey || ev.ctrlKey || ev.metaKey) && !this._isThirdLevelShift(this.browser, ev)\n )) {\n return false;\n }\n\n key = String.fromCharCode(key);\n\n this._onKey.fire({ key, domEvent: ev });\n this.showCursor();\n this._coreService.triggerDataEvent(key, true);\n\n return true;\n }\n\n /**\n * Ring the bell.\n * Note: We could do sweet things with webaudio here\n */\n public bell(): void {\n if (this._soundBell()) {\n this._soundService.playBellSound();\n }\n\n if (this._visualBell()) {\n this.element.classList.add('visual-bell-active');\n clearTimeout(this._visualBellTimer);\n this._visualBellTimer = window.setTimeout(() => {\n this.element.classList.remove('visual-bell-active');\n }, 200);\n }\n }\n\n /**\n * Resizes the terminal.\n *\n * @param x The number of columns to resize to.\n * @param y The number of rows to resize to.\n */\n public resize(x: number, y: number): void {\n if (isNaN(x) || isNaN(y)) {\n return;\n }\n\n if (x === this.cols && y === this.rows) {\n // Check if we still need to measure the char size (fixes #785).\n if (this._charSizeService && !this._charSizeService.hasValidSize) {\n this._charSizeService.measure();\n }\n return;\n }\n\n if (x < MINIMUM_COLS) x = MINIMUM_COLS;\n if (y < MINIMUM_ROWS) y = MINIMUM_ROWS;\n\n this.buffers.resize(x, y);\n\n this._bufferService.resize(x, y);\n this.buffers.setupTabStops(this.cols);\n\n this._charSizeService?.measure();\n\n // Sync the scroll area to make sure scroll events don't fire and scroll the viewport to an\n // invalid location\n this.viewport?.syncScrollArea(true);\n\n this.refresh(0, this.rows - 1);\n this._onResize.fire({ cols: x, rows: y });\n }\n\n /**\n * Clear the entire buffer, making the prompt line the new first line.\n */\n public clear(): void {\n if (this.buffer.ybase === 0 && this.buffer.y === 0) {\n // Don't clear if it's already clear\n return;\n }\n this.buffer.lines.set(0, this.buffer.lines.get(this.buffer.ybase + this.buffer.y));\n this.buffer.lines.length = 1;\n this.buffer.ydisp = 0;\n this.buffer.ybase = 0;\n this.buffer.y = 0;\n for (let i = 1; i < this.rows; i++) {\n this.buffer.lines.push(this.buffer.getBlankLine(DEFAULT_ATTR_DATA));\n }\n this.refresh(0, this.rows - 1);\n this._onScroll.fire(this.buffer.ydisp);\n }\n\n /**\n * Evaluate if the current terminal is the given argument.\n * @param term The terminal name to evaluate\n */\n public is(term: string): boolean {\n return (this.options.termName + '').indexOf(term) === 0;\n }\n\n /**\n * Emit the data event and populate the given data.\n * @param data The data to populate in the event.\n */\n // public handler(data: string): void {\n // // Prevents all events to pty process if stdin is disabled\n // if (this.options.disableStdin) {\n // return;\n // }\n\n // // Clear the selection if the selection manager is available and has an active selection\n // if (this.selectionService && this.selectionService.hasSelection) {\n // this.selectionService.clearSelection();\n // }\n\n // // Input is being sent to the terminal, the terminal should focus the prompt.\n // if (this.buffer.ybase !== this.buffer.ydisp) {\n // this.scrollToBottom();\n // }\n // this._onData.fire(data);\n // }\n\n /**\n * Emit the 'title' event and populate the given title.\n * @param title The title to populate in the event.\n */\n public handleTitle(title: string): void {\n this._onTitleChange.fire(title);\n }\n\n /**\n * Reset terminal.\n * Note: Calling this directly from JS is synchronous but does not clear\n * input buffers and does not reset the parser, thus the terminal will\n * continue to apply pending input data.\n * If you need in band reset (synchronous with input data) consider\n * using DECSTR (soft reset, CSI ! p) or RIS instead (hard reset, ESC c).\n */\n public reset(): void {\n /**\n * Since _setup handles a full terminal creation, we have to carry forward\n * a few things that should not reset.\n */\n this.options.rows = this.rows;\n this.options.cols = this.cols;\n const customKeyEventHandler = this._customKeyEventHandler;\n const userScrolling = this._userScrolling;\n\n this._setup();\n this._bufferService.reset();\n this._charsetService.reset();\n this._coreService.reset();\n this._coreMouseService.reset();\n this._selectionService?.reset();\n\n // reattach\n this._customKeyEventHandler = customKeyEventHandler;\n this._userScrolling = userScrolling;\n\n // do a full screen refresh\n this.refresh(0, this.rows - 1);\n this.viewport?.syncScrollArea();\n }\n\n // TODO: Remove cancel function and cancelEvents option\n public cancel(ev: Event, force?: boolean): boolean {\n if (!this.options.cancelEvents && !force) {\n return;\n }\n ev.preventDefault();\n ev.stopPropagation();\n return false;\n }\n\n private _visualBell(): boolean {\n return false;\n // return this.options.bellStyle === 'visual' ||\n // this.options.bellStyle === 'both';\n }\n\n private _soundBell(): boolean {\n return this.options.bellStyle === 'sound';\n // return this.options.bellStyle === 'sound' ||\n // this.options.bellStyle === 'both';\n }\n\n public write(data: string | Uint8Array, callback?: () => void): void {\n this._writeBuffer.write(data, callback);\n }\n\n public writeSync(data: string | Uint8Array): void {\n this._writeBuffer.writeSync(data);\n }\n}\n\n/**\n * Helpers\n */\n\nfunction wasModifierKeyOnlyEvent(ev: KeyboardEvent): boolean {\n return ev.keyCode === 16 || // Shift\n ev.keyCode === 17 || // Ctrl\n ev.keyCode === 18; // Alt\n}\n","/**\n * Copyright (c) 2016 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { ICharSizeService } from 'browser/services/Services';\nimport { IBufferService, ICoreService, IOptionsService } from 'common/services/Services';\n\ninterface IPosition {\n start: number;\n end: number;\n}\n\n/**\n * Encapsulates the logic for handling compositionstart, compositionupdate and compositionend\n * events, displaying the in-progress composition to the UI and forwarding the final composition\n * to the handler.\n */\nexport class CompositionHelper {\n /**\n * Whether input composition is currently happening, eg. via a mobile keyboard, speech input or\n * IME. This variable determines whether the compositionText should be displayed on the UI.\n */\n private _isComposing: boolean;\n\n /**\n * The position within the input textarea's value of the current composition.\n */\n private _compositionPosition: IPosition;\n\n /**\n * Whether a composition is in the process of being sent, setting this to false will cancel any\n * in-progress composition.\n */\n private _isSendingComposition: boolean;\n\n constructor(\n private readonly _textarea: HTMLTextAreaElement,\n private readonly _compositionView: HTMLElement,\n @IBufferService private readonly _bufferService: IBufferService,\n @IOptionsService private readonly _optionsService: IOptionsService,\n @ICharSizeService private readonly _charSizeService: ICharSizeService,\n @ICoreService private readonly _coreService: ICoreService\n ) {\n this._isComposing = false;\n this._isSendingComposition = false;\n this._compositionPosition = { start: 0, end: 0 };\n }\n\n /**\n * Handles the compositionstart event, activating the composition view.\n */\n public compositionstart(): void {\n this._isComposing = true;\n this._compositionPosition.start = this._textarea.value.length;\n this._compositionView.textContent = '';\n this._compositionView.classList.add('active');\n }\n\n /**\n * Handles the compositionupdate event, updating the composition view.\n * @param ev The event.\n */\n public compositionupdate(ev: CompositionEvent): void {\n this._compositionView.textContent = ev.data;\n this.updateCompositionElements();\n setTimeout(() => {\n this._compositionPosition.end = this._textarea.value.length;\n }, 0);\n }\n\n /**\n * Handles the compositionend event, hiding the composition view and sending the composition to\n * the handler.\n */\n public compositionend(): void {\n this._finalizeComposition(true);\n }\n\n /**\n * Handles the keydown event, routing any necessary events to the CompositionHelper functions.\n * @param ev The keydown event.\n * @return Whether the Terminal should continue processing the keydown event.\n */\n public keydown(ev: KeyboardEvent): boolean {\n if (this._isComposing || this._isSendingComposition) {\n if (ev.keyCode === 229) {\n // Continue composing if the keyCode is the \"composition character\"\n return false;\n } else if (ev.keyCode === 16 || ev.keyCode === 17 || ev.keyCode === 18) {\n // Continue composing if the keyCode is a modifier key\n return false;\n }\n // Finish composition immediately. This is mainly here for the case where enter is\n // pressed and the handler needs to be triggered before the command is executed.\n this._finalizeComposition(false);\n }\n\n if (ev.keyCode === 229) {\n // If the \"composition character\" is used but gets to this point it means a non-composition\n // character (eg. numbers and punctuation) was pressed when the IME was active.\n this._handleAnyTextareaChanges();\n return false;\n }\n\n return true;\n }\n\n /**\n * Finalizes the composition, resuming regular input actions. This is called when a composition\n * is ending.\n * @param waitForPropagation Whether to wait for events to propagate before sending\n * the input. This should be false if a non-composition keystroke is entered before the\n * compositionend event is triggered, such as enter, so that the composition is sent before\n * the command is executed.\n */\n private _finalizeComposition(waitForPropagation: boolean): void {\n this._compositionView.classList.remove('active');\n this._isComposing = false;\n this._clearTextareaPosition();\n\n if (!waitForPropagation) {\n // Cancel any delayed composition send requests and send the input immediately.\n this._isSendingComposition = false;\n const input = this._textarea.value.substring(this._compositionPosition.start, this._compositionPosition.end);\n this._coreService.triggerDataEvent(input, true);\n } else {\n // Make a deep copy of the composition position here as a new compositionstart event may\n // fire before the setTimeout executes.\n const currentCompositionPosition = {\n start: this._compositionPosition.start,\n end: this._compositionPosition.end\n };\n\n // Since composition* events happen before the changes take place in the textarea on most\n // browsers, use a setTimeout with 0ms time to allow the native compositionend event to\n // complete. This ensures the correct character is retrieved.\n // This solution was used because:\n // - The compositionend event's data property is unreliable, at least on Chromium\n // - The last compositionupdate event's data property does not always accurately describe\n // the character, a counter example being Korean where an ending consonsant can move to\n // the following character if the following input is a vowel.\n this._isSendingComposition = true;\n setTimeout(() => {\n // Ensure that the input has not already been sent\n if (this._isSendingComposition) {\n this._isSendingComposition = false;\n let input;\n if (this._isComposing) {\n // Use the end position to get the string if a new composition has started.\n input = this._textarea.value.substring(currentCompositionPosition.start, currentCompositionPosition.end);\n } else {\n // Don't use the end position here in order to pick up any characters after the\n // composition has finished, for example when typing a non-composition character\n // (eg. 2) after a composition character.\n input = this._textarea.value.substring(currentCompositionPosition.start);\n }\n this._coreService.triggerDataEvent(input, true);\n }\n }, 0);\n }\n }\n\n /**\n * Apply any changes made to the textarea after the current event chain is allowed to complete.\n * This should be called when not currently composing but a keydown event with the \"composition\n * character\" (229) is triggered, in order to allow non-composition text to be entered when an\n * IME is active.\n */\n private _handleAnyTextareaChanges(): void {\n const oldValue = this._textarea.value;\n setTimeout(() => {\n // Ignore if a composition has started since the timeout\n if (!this._isComposing) {\n const newValue = this._textarea.value;\n const diff = newValue.replace(oldValue, '');\n if (diff.length > 0) {\n this._coreService.triggerDataEvent(diff, true);\n }\n }\n }, 0);\n }\n\n /**\n * Positions the composition view on top of the cursor and the textarea just below it (so the\n * IME helper dialog is positioned correctly).\n * @param dontRecurse Whether to use setTimeout to recursively trigger another update, this is\n * necessary as the IME events across browsers are not consistently triggered.\n */\n public updateCompositionElements(dontRecurse?: boolean): void {\n if (!this._isComposing) {\n return;\n }\n\n if (this._bufferService.buffer.isCursorInViewport) {\n const cellHeight = Math.ceil(this._charSizeService.height * this._optionsService.options.lineHeight);\n const cursorTop = this._bufferService.buffer.y * cellHeight;\n const cursorLeft = this._bufferService.buffer.x * this._charSizeService.width;\n\n this._compositionView.style.left = cursorLeft + 'px';\n this._compositionView.style.top = cursorTop + 'px';\n this._compositionView.style.height = cellHeight + 'px';\n this._compositionView.style.lineHeight = cellHeight + 'px';\n this._compositionView.style.fontFamily = this._optionsService.options.fontFamily;\n this._compositionView.style.fontSize = this._optionsService.options.fontSize + 'px';\n // Sync the textarea to the exact position of the composition view so the IME knows where the\n // text is.\n const compositionViewBounds = this._compositionView.getBoundingClientRect();\n this._textarea.style.left = cursorLeft + 'px';\n this._textarea.style.top = cursorTop + 'px';\n this._textarea.style.width = compositionViewBounds.width + 'px';\n this._textarea.style.height = compositionViewBounds.height + 'px';\n this._textarea.style.lineHeight = compositionViewBounds.height + 'px';\n }\n\n if (!dontRecurse) {\n setTimeout(() => this.updateCompositionElements(true), 0);\n }\n }\n\n /**\n * Clears the textarea's position so that the cursor does not blink on IE.\n * @private\n */\n private _clearTextareaPosition(): void {\n this._textarea.style.left = '';\n this._textarea.style.top = '';\n }\n}\n","/**\n * Copyright (c) 2016 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { Disposable } from 'common/Lifecycle';\nimport { addDisposableDomListener } from 'browser/Lifecycle';\nimport { IColorSet, IViewport } from 'browser/Types';\nimport { ICharSizeService, IRenderService } from 'browser/services/Services';\nimport { IBufferService, IOptionsService } from 'common/services/Services';\n\nconst FALLBACK_SCROLL_BAR_WIDTH = 15;\n\n/**\n * Represents the viewport of a terminal, the visible area within the larger buffer of output.\n * Logic for the virtual scroll bar is included in this object.\n */\nexport class Viewport extends Disposable implements IViewport {\n public scrollBarWidth: number = 0;\n private _currentRowHeight: number = 0;\n private _lastRecordedBufferLength: number = 0;\n private _lastRecordedViewportHeight: number = 0;\n private _lastRecordedBufferHeight: number = 0;\n private _lastTouchY: number = 0;\n private _lastScrollTop: number = 0;\n\n // Stores a partial line amount when scrolling, this is used to keep track of how much of a line\n // is scrolled so we can \"scroll\" over partial lines and feel natural on touchpads. This is a\n // quick fix and could have a more robust solution in place that reset the value when needed.\n private _wheelPartialScroll: number = 0;\n\n private _refreshAnimationFrame: number | null = null;\n private _ignoreNextScrollEvent: boolean = false;\n\n constructor(\n private readonly _scrollLines: (amount: number, suppressEvent: boolean) => void,\n private readonly _viewportElement: HTMLElement,\n private readonly _scrollArea: HTMLElement,\n @IBufferService private readonly _bufferService: IBufferService,\n @IOptionsService private readonly _optionsService: IOptionsService,\n @ICharSizeService private readonly _charSizeService: ICharSizeService,\n @IRenderService private readonly _renderService: IRenderService\n ) {\n super();\n\n // Measure the width of the scrollbar. If it is 0 we can assume it's an OSX overlay scrollbar.\n // Unfortunately the overlay scrollbar would be hidden underneath the screen element in that case,\n // therefore we account for a standard amount to make it visible\n this.scrollBarWidth = (this._viewportElement.offsetWidth - this._scrollArea.offsetWidth) || FALLBACK_SCROLL_BAR_WIDTH;\n this.register(addDisposableDomListener(this._viewportElement, 'scroll', this._onScroll.bind(this)));\n\n // Perform this async to ensure the ICharSizeService is ready.\n setTimeout(() => this.syncScrollArea(), 0);\n }\n\n public onThemeChange(colors: IColorSet): void {\n this._viewportElement.style.backgroundColor = colors.background.css;\n }\n\n /**\n * Refreshes row height, setting line-height, viewport height and scroll area height if\n * necessary.\n */\n private _refresh(immediate: boolean): void {\n if (immediate) {\n this._innerRefresh();\n if (this._refreshAnimationFrame !== null) {\n cancelAnimationFrame(this._refreshAnimationFrame);\n }\n return;\n }\n if (this._refreshAnimationFrame === null) {\n this._refreshAnimationFrame = requestAnimationFrame(() => this._innerRefresh());\n }\n }\n\n private _innerRefresh(): void {\n if (this._charSizeService.height > 0) {\n this._currentRowHeight = this._renderService.dimensions.scaledCellHeight / window.devicePixelRatio;\n this._lastRecordedViewportHeight = this._viewportElement.offsetHeight;\n const newBufferHeight = Math.round(this._currentRowHeight * this._lastRecordedBufferLength) + (this._lastRecordedViewportHeight - this._renderService.dimensions.canvasHeight);\n if (this._lastRecordedBufferHeight !== newBufferHeight) {\n this._lastRecordedBufferHeight = newBufferHeight;\n this._scrollArea.style.height = this._lastRecordedBufferHeight + 'px';\n }\n }\n\n // Sync scrollTop\n const scrollTop = this._bufferService.buffer.ydisp * this._currentRowHeight;\n if (this._viewportElement.scrollTop !== scrollTop) {\n // Ignore the next scroll event which will be triggered by setting the scrollTop as we do not\n // want this event to scroll the terminal\n this._ignoreNextScrollEvent = true;\n this._viewportElement.scrollTop = scrollTop;\n }\n\n this._refreshAnimationFrame = null;\n }\n /**\n * Updates dimensions and synchronizes the scroll area if necessary.\n */\n public syncScrollArea(immediate: boolean = false): void {\n // If buffer height changed\n if (this._lastRecordedBufferLength !== this._bufferService.buffer.lines.length) {\n this._lastRecordedBufferLength = this._bufferService.buffer.lines.length;\n this._refresh(immediate);\n return;\n }\n\n // If viewport height changed\n if (this._lastRecordedViewportHeight !== this._renderService.dimensions.canvasHeight) {\n this._refresh(immediate);\n return;\n }\n\n // If the buffer position doesn't match last scroll top\n const newScrollTop = this._bufferService.buffer.ydisp * this._currentRowHeight;\n if (this._lastScrollTop !== newScrollTop) {\n this._refresh(immediate);\n return;\n }\n\n // If element's scroll top changed, this can happen when hiding the element\n if (this._lastScrollTop !== this._viewportElement.scrollTop) {\n this._refresh(immediate);\n return;\n }\n\n // If row height changed\n if (this._renderService.dimensions.scaledCellHeight / window.devicePixelRatio !== this._currentRowHeight) {\n this._refresh(immediate);\n return;\n }\n }\n\n /**\n * Handles scroll events on the viewport, calculating the new viewport and requesting the\n * terminal to scroll to it.\n * @param ev The scroll event.\n */\n private _onScroll(ev: Event): void {\n // Record current scroll top position\n this._lastScrollTop = this._viewportElement.scrollTop;\n\n // Don't attempt to scroll if the element is not visible, otherwise scrollTop will be corrupt\n // which causes the terminal to scroll the buffer to the top\n if (!this._viewportElement.offsetParent) {\n return;\n }\n\n // Ignore the event if it was flagged to ignore (when the source of the event is from Viewport)\n if (this._ignoreNextScrollEvent) {\n this._ignoreNextScrollEvent = false;\n return;\n }\n\n const newRow = Math.round(this._lastScrollTop / this._currentRowHeight);\n const diff = newRow - this._bufferService.buffer.ydisp;\n this._scrollLines(diff, true);\n }\n\n /**\n * Handles bubbling of scroll event in case the viewport has reached top or bottom\n * @param ev The scroll event.\n * @param amount The amount scrolled\n */\n private _bubbleScroll(ev: Event, amount: number): boolean {\n const scrollPosFromTop = this._viewportElement.scrollTop + this._lastRecordedViewportHeight;\n if ((amount < 0 && this._viewportElement.scrollTop !== 0) ||\n (amount > 0 && scrollPosFromTop < this._lastRecordedBufferHeight)) {\n if (ev.cancelable) {\n ev.preventDefault();\n }\n return false;\n }\n return true;\n }\n\n /**\n * Handles mouse wheel events by adjusting the viewport's scrollTop and delegating the actual\n * scrolling to `onScroll`, this event needs to be attached manually by the consumer of\n * `Viewport`.\n * @param ev The mouse wheel event.\n */\n public onWheel(ev: WheelEvent): boolean {\n const amount = this._getPixelsScrolled(ev);\n if (amount === 0) {\n return false;\n }\n this._viewportElement.scrollTop += amount;\n return this._bubbleScroll(ev, amount);\n }\n\n private _getPixelsScrolled(ev: WheelEvent): number {\n // Do nothing if it's not a vertical scroll event\n if (ev.deltaY === 0) {\n return 0;\n }\n\n // Fallback to WheelEvent.DOM_DELTA_PIXEL\n let amount = this._applyScrollModifier(ev.deltaY, ev);\n if (ev.deltaMode === WheelEvent.DOM_DELTA_LINE) {\n amount *= this._currentRowHeight;\n } else if (ev.deltaMode === WheelEvent.DOM_DELTA_PAGE) {\n amount *= this._currentRowHeight * this._bufferService.rows;\n }\n return amount;\n }\n\n /**\n * Gets the number of pixels scrolled by the mouse event taking into account what type of delta\n * is being used.\n * @param ev The mouse wheel event.\n */\n public getLinesScrolled(ev: WheelEvent): number {\n // Do nothing if it's not a vertical scroll event\n if (ev.deltaY === 0) {\n return 0;\n }\n\n // Fallback to WheelEvent.DOM_DELTA_LINE\n let amount = this._applyScrollModifier(ev.deltaY, ev);\n if (ev.deltaMode === WheelEvent.DOM_DELTA_PIXEL) {\n amount /= this._currentRowHeight + 0.0; // Prevent integer division\n this._wheelPartialScroll += amount;\n amount = Math.floor(Math.abs(this._wheelPartialScroll)) * (this._wheelPartialScroll > 0 ? 1 : -1);\n this._wheelPartialScroll %= 1;\n } else if (ev.deltaMode === WheelEvent.DOM_DELTA_PAGE) {\n amount *= this._bufferService.rows;\n }\n return amount;\n }\n\n private _applyScrollModifier(amount: number, ev: WheelEvent): number {\n const modifier = this._optionsService.options.fastScrollModifier;\n // Multiply the scroll speed when the modifier is down\n if ((modifier === 'alt' && ev.altKey) ||\n (modifier === 'ctrl' && ev.ctrlKey) ||\n (modifier === 'shift' && ev.shiftKey)) {\n return amount * this._optionsService.options.fastScrollSensitivity * this._optionsService.options.scrollSensitivity;\n }\n\n return amount * this._optionsService.options.scrollSensitivity;\n }\n\n /**\n * Handles the touchstart event, recording the touch occurred.\n * @param ev The touch event.\n */\n public onTouchStart(ev: TouchEvent): void {\n this._lastTouchY = ev.touches[0].pageY;\n }\n\n /**\n * Handles the touchmove event, scrolling the viewport if the position shifted.\n * @param ev The touch event.\n */\n public onTouchMove(ev: TouchEvent): boolean {\n const deltaY = this._lastTouchY - ev.touches[0].pageY;\n this._lastTouchY = ev.touches[0].pageY;\n if (deltaY === 0) {\n return false;\n }\n this._viewportElement.scrollTop += deltaY;\n return this._bubbleScroll(ev, deltaY);\n }\n}\n","/**\n * Copyright (c) 2016 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { ISelectionService } from 'browser/services/Services';\nimport { ICoreService } from 'common/services/Services';\n\n/**\n * Prepares text to be pasted into the terminal by normalizing the line endings\n * @param text The pasted text that needs processing before inserting into the terminal\n */\nexport function prepareTextForTerminal(text: string): string {\n return text.replace(/\\r?\\n/g, '\\r');\n}\n\n/**\n * Bracket text for paste, if necessary, as per https://cirw.in/blog/bracketed-paste\n * @param text The pasted text to bracket\n */\nexport function bracketTextForPaste(text: string, bracketedPasteMode: boolean): string {\n if (bracketedPasteMode) {\n return '\\x1b[200~' + text + '\\x1b[201~';\n }\n return text;\n}\n\n/**\n * Binds copy functionality to the given terminal.\n * @param ev The original copy event to be handled\n */\nexport function copyHandler(ev: ClipboardEvent, selectionService: ISelectionService): void {\n if (ev.clipboardData) {\n ev.clipboardData.setData('text/plain', selectionService.selectionText);\n }\n // Prevent or the original text will be copied.\n ev.preventDefault();\n}\n\n/**\n * Redirect the clipboard's data to the terminal's input handler.\n * @param ev The original paste event to be handled\n * @param term The terminal on which to apply the handled paste event\n */\nexport function handlePasteEvent(ev: ClipboardEvent, textarea: HTMLTextAreaElement, bracketedPasteMode: boolean, coreService: ICoreService): void {\n ev.stopPropagation();\n if (ev.clipboardData) {\n const text = ev.clipboardData.getData('text/plain');\n paste(text, textarea, bracketedPasteMode, coreService);\n }\n}\n\nexport function paste(text: string, textarea: HTMLTextAreaElement, bracketedPasteMode: boolean, coreService: ICoreService): void {\n text = prepareTextForTerminal(text);\n text = bracketTextForPaste(text, bracketedPasteMode);\n coreService.triggerDataEvent(text, true);\n textarea.value = '';\n}\n\n/**\n * Moves the textarea under the mouse cursor and focuses it.\n * @param ev The original right click event to be handled.\n * @param textarea The terminal's textarea.\n */\nexport function moveTextAreaUnderMouseCursor(ev: MouseEvent, textarea: HTMLTextAreaElement, screenElement: HTMLElement): void {\n\n // Calculate textarea position relative to the screen element\n const pos = screenElement.getBoundingClientRect();\n const left = ev.clientX - pos.left - 10;\n const top = ev.clientY - pos.top - 10;\n\n // Bring textarea at the cursor position\n textarea.style.position = 'absolute';\n textarea.style.width = '20px';\n textarea.style.height = '20px';\n textarea.style.left = `${left}px`;\n textarea.style.top = `${top}px`;\n textarea.style.zIndex = '1000';\n\n textarea.focus();\n\n // Reset the terminal textarea's styling\n // Timeout needs to be long enough for click event to be handled.\n setTimeout(() => {\n textarea.style.position = '';\n textarea.style.width = '';\n textarea.style.height = '';\n textarea.style.left = '';\n textarea.style.top = '';\n textarea.style.zIndex = '';\n }, 200);\n}\n\n/**\n * Bind to right-click event and allow right-click copy and paste.\n * @param ev The original right click event to be handled.\n * @param textarea The terminal's textarea.\n * @param selectionService The terminal's selection manager.\n * @param shouldSelectWord If true and there is no selection the current word will be selected\n */\nexport function rightClickHandler(ev: MouseEvent, textarea: HTMLTextAreaElement, screenElement: HTMLElement, selectionService: ISelectionService, shouldSelectWord: boolean): void {\n moveTextAreaUnderMouseCursor(ev, textarea, screenElement);\n\n if (shouldSelectWord && !selectionService.isClickInSelection(ev)) {\n selectionService.selectWordAtCursor(ev);\n }\n\n // Get textarea ready to copy from the context menu\n textarea.value = selectionService.selectionText;\n textarea.select();\n}\n","/**\n * Copyright (c) 2014 The xterm.js authors. All rights reserved.\n * Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)\n * @license MIT\n */\n\nimport { IInputHandler, IInputHandlingTerminal } from './Types';\nimport { C0, C1 } from 'common/data/EscapeSequences';\nimport { CHARSETS, DEFAULT_CHARSET } from 'common/data/Charsets';\nimport { EscapeSequenceParser } from 'common/parser/EscapeSequenceParser';\nimport { Disposable } from 'common/Lifecycle';\nimport { concat } from 'common/TypedArrayUtils';\nimport { StringToUtf32, stringFromCodePoint, utf32ToString, Utf8ToUtf32 } from 'common/input/TextDecoder';\nimport { DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine';\nimport { EventEmitter, IEvent } from 'common/EventEmitter';\nimport { IParsingState, IDcsHandler, IEscapeSequenceParser, IParams, IFunctionIdentifier } from 'common/parser/Types';\nimport { NULL_CELL_CODE, NULL_CELL_WIDTH, Attributes, FgFlags, BgFlags, Content } from 'common/buffer/Constants';\nimport { CellData } from 'common/buffer/CellData';\nimport { AttributeData } from 'common/buffer/AttributeData';\nimport { IAttributeData, IDisposable, IWindowOptions } from 'common/Types';\nimport { ICoreService, IBufferService, IOptionsService, ILogService, IDirtyRowService, ICoreMouseService, ICharsetService, IUnicodeService, IInstantiationService } from 'common/services/Services';\nimport { OscHandler } from 'common/parser/OscParser';\nimport { DcsHandler } from 'common/parser/DcsParser';\nimport { IRenderService } from 'browser/services/Services';\n\n/**\n * Map collect to glevel. Used in `selectCharset`.\n */\nconst GLEVEL: {[key: string]: number} = {'(': 0, ')': 1, '*': 2, '+': 3, '-': 1, '.': 2};\n\n/**\n * VT commands done by the parser - FIXME: move this to the parser?\n */\n// @vt: #Y ESC CSI \"Control Sequence Introducer\" \"ESC [\" \"Start of a CSI sequence.\"\n// @vt: #Y ESC OSC \"Operating System Command\" \"ESC ]\" \"Start of an OSC sequence.\"\n// @vt: #Y ESC DCS \"Device Control String\" \"ESC P\" \"Start of a DCS sequence.\"\n// @vt: #Y ESC ST \"String Terminator\" \"ESC \\\" \"Terminator used for string type sequences.\"\n// @vt: #Y ESC PM \"Privacy Message\" \"ESC ^\" \"Start of a privacy message.\"\n// @vt: #Y ESC APC \"Application Program Command\" \"ESC _\" \"Start of an APC sequence.\"\n// @vt: #Y C1 CSI \"Control Sequence Introducer\" \"\\x9B\" \"Start of a CSI sequence.\"\n// @vt: #Y C1 OSC \"Operating System Command\" \"\\x9D\" \"Start of an OSC sequence.\"\n// @vt: #Y C1 DCS \"Device Control String\" \"\\x90\" \"Start of a DCS sequence.\"\n// @vt: #Y C1 ST \"String Terminator\" \"\\x9C\" \"Terminator used for string type sequences.\"\n// @vt: #Y C1 PM \"Privacy Message\" \"\\x9E\" \"Start of a privacy message.\"\n// @vt: #Y C1 APC \"Application Program Command\" \"\\x9F\" \"Start of an APC sequence.\"\n// @vt: #Y C0 NUL \"Null\" \"\\0, \\x00\" \"NUL is ignored.\"\n// @vt: #Y C0 ESC \"Escape\" \"\\e, \\x1B\" \"Start of a sequence. Cancels any other sequence.\"\n\n/**\n * Document common VT features here that are currently unsupported\n */\n// @vt: #N DCS SIXEL \"SIXEL Graphics\" \"DCS Ps ; Ps ; Ps ; q \tPt ST\" \"Draw SIXEL image starting at cursor position.\"\n// @vt: #N OSC 1 \"Set Icon Name\" \"OSC 1 ; Pt BEL\" \"Set icon name.\"\n\n/**\n * Max length of the UTF32 input buffer. Real memory consumption is 4 times higher.\n */\nconst MAX_PARSEBUFFER_LENGTH = 131072;\n\n/**\n * Limit length of title and icon name stacks.\n */\nconst STACK_LIMIT = 10;\n\n// map params to window option\nfunction paramToWindowOption(n: number, opts: IWindowOptions): boolean {\n if (n > 24) {\n return opts.setWinLines || false;\n }\n switch (n) {\n case 1: return !!opts.restoreWin;\n case 2: return !!opts.minimizeWin;\n case 3: return !!opts.setWinPosition;\n case 4: return !!opts.setWinSizePixels;\n case 5: return !!opts.raiseWin;\n case 6: return !!opts.lowerWin;\n case 7: return !!opts.refreshWin;\n case 8: return !!opts.setWinSizeChars;\n case 9: return !!opts.maximizeWin;\n case 10: return !!opts.fullscreenWin;\n case 11: return !!opts.getWinState;\n case 13: return !!opts.getWinPosition;\n case 14: return !!opts.getWinSizePixels;\n case 15: return !!opts.getScreenSizePixels;\n case 16: return !!opts.getCellSizePixels;\n case 18: return !!opts.getWinSizeChars;\n case 19: return !!opts.getScreenSizeChars;\n case 20: return !!opts.getIconTitle;\n case 21: return !!opts.getWinTitle;\n case 22: return !!opts.pushTitle;\n case 23: return !!opts.popTitle;\n case 24: return !!opts.setWinLines;\n }\n return false;\n}\n\n\n\n/**\n * DCS subparser implementations\n */\n\n/**\n * DCS $ q Pt ST\n * DECRQSS (https://vt100.net/docs/vt510-rm/DECRQSS.html)\n * Request Status String (DECRQSS), VT420 and up.\n * Response: DECRPSS (https://vt100.net/docs/vt510-rm/DECRPSS.html)\n *\n * @vt: #P[See limited support below.] DCS DECRQSS \"Request Selection or Setting\" \"DCS $ q Pt ST\" \"Request several terminal settings.\"\n * Response is in the form `ESC P 1 $ r Pt ST` for valid requests, where `Pt` contains the corresponding CSI string,\n * `ESC P 0 ST` for invalid requests.\n *\n * Supported requests and responses:\n *\n * | Type | Request | Response (`Pt`) |\n * | -------------------------------- | ----------------- | ----------------------------------------------------- |\n * | Graphic Rendition (SGR) | `DCS $ q m ST` | always reporting `0m` (currently broken) |\n * | Top and Bottom Margins (DECSTBM) | `DCS $ q r ST` | `Ps ; Ps r` |\n * | Cursor Style (DECSCUSR) | `DCS $ q SP q ST` | `Ps SP q` |\n * | Protection Attribute (DECSCA) | `DCS $ q \" q ST` | always reporting `0 \" q` (DECSCA is unsupported) |\n * | Conformance Level (DECSCL) | `DCS $ q \" p ST` | always reporting `61 ; 1 \" p` (DECSCL is unsupported) |\n *\n *\n * TODO:\n * - fix SGR report\n * - either implement DECSCA or remove the report\n * - either check which conformance is better suited or remove the report completely\n * --> we are currently a mixture of all up to VT400 but dont follow anyone strictly\n */\nclass DECRQSS implements IDcsHandler {\n private _data: Uint32Array = new Uint32Array(0);\n\n constructor(\n private _bufferService: IBufferService,\n private _coreService: ICoreService,\n private _logService: ILogService,\n private _optionsService: IOptionsService\n ) { }\n\n hook(params: IParams): void {\n this._data = new Uint32Array(0);\n }\n\n put(data: Uint32Array, start: number, end: number): void {\n this._data = concat(this._data, data.subarray(start, end));\n }\n\n unhook(success: boolean): void {\n if (!success) {\n this._data = new Uint32Array(0);\n return;\n }\n const data = utf32ToString(this._data);\n this._data = new Uint32Array(0);\n switch (data) {\n // valid: DCS 1 $ r Pt ST (xterm)\n case '\"q': // DECSCA\n return this._coreService.triggerDataEvent(`${C0.ESC}P1$r0\"q${C0.ESC}\\\\`);\n case '\"p': // DECSCL\n return this._coreService.triggerDataEvent(`${C0.ESC}P1$r61;1\"p${C0.ESC}\\\\`);\n case 'r': // DECSTBM\n const pt = '' + (this._bufferService.buffer.scrollTop + 1) +\n ';' + (this._bufferService.buffer.scrollBottom + 1) + 'r';\n return this._coreService.triggerDataEvent(`${C0.ESC}P1$r${pt}${C0.ESC}\\\\`);\n case 'm': // SGR\n // TODO: report real settings instead of 0m\n return this._coreService.triggerDataEvent(`${C0.ESC}P1$r0m${C0.ESC}\\\\`);\n case ' q': // DECSCUSR\n const STYLES: {[key: string]: number} = {'block': 2, 'underline': 4, 'bar': 6};\n let style = STYLES[this._optionsService.options.cursorStyle];\n style -= this._optionsService.options.cursorBlink ? 1 : 0;\n return this._coreService.triggerDataEvent(`${C0.ESC}P1$r${style} q${C0.ESC}\\\\`);\n default:\n // invalid: DCS 0 $ r Pt ST (xterm)\n this._logService.debug('Unknown DCS $q %s', data);\n this._coreService.triggerDataEvent(`${C0.ESC}P0$r${C0.ESC}\\\\`);\n }\n }\n}\n\n/**\n * DCS Ps; Ps| Pt ST\n * DECUDK (https://vt100.net/docs/vt510-rm/DECUDK.html)\n * not supported\n *\n * @vt: #N DCS DECUDK \"User Defined Keys\" \"DCS Ps ; Ps | Pt ST\" \"Definitions for user-defined keys.\"\n */\n\n/**\n * DCS + q Pt ST (xterm)\n * Request Terminfo String\n * not implemented\n *\n * @vt: #N DCS XTGETTCAP \"Request Terminfo String\" \"DCS + q Pt ST\" \"Request Terminfo String.\"\n */\n\n/**\n * DCS + p Pt ST (xterm)\n * Set Terminfo Data\n * not supported\n *\n * @vt: #N DCS XTSETTCAP \"Set Terminfo Data\" \"DCS + p Pt ST\" \"Set Terminfo Data.\"\n */\n\n\n\n/**\n * The terminal's standard implementation of IInputHandler, this handles all\n * input from the Parser.\n *\n * Refer to http://invisible-island.net/xterm/ctlseqs/ctlseqs.html to understand\n * each function's header comment.\n */\nexport class InputHandler extends Disposable implements IInputHandler {\n private _parseBuffer: Uint32Array = new Uint32Array(4096);\n private _stringDecoder: StringToUtf32 = new StringToUtf32();\n private _utf8Decoder: Utf8ToUtf32 = new Utf8ToUtf32();\n private _workCell: CellData = new CellData();\n private _windowTitle = '';\n private _iconName = '';\n private _windowTitleStack: string[] = [];\n private _iconNameStack: string[] = [];\n\n private _curAttrData: IAttributeData = DEFAULT_ATTR_DATA.clone();\n private _eraseAttrDataInternal: IAttributeData = DEFAULT_ATTR_DATA.clone();\n\n private _onRequestRefreshRows = new EventEmitter();\n public get onRequestRefreshRows(): IEvent { return this._onRequestRefreshRows.event; }\n private _onRequestReset = new EventEmitter();\n public get onRequestReset(): IEvent { return this._onRequestReset.event; }\n private _onRequestBell = new EventEmitter();\n public get onRequestBell(): IEvent { return this._onRequestBell.event; }\n private _onCursorMove = new EventEmitter();\n public get onCursorMove(): IEvent { return this._onCursorMove.event; }\n private _onLineFeed = new EventEmitter();\n public get onLineFeed(): IEvent { return this._onLineFeed.event; }\n private _onScroll = new EventEmitter();\n public get onScroll(): IEvent { return this._onScroll.event; }\n\n constructor(\n private _terminal: IInputHandlingTerminal,\n private readonly _bufferService: IBufferService,\n private readonly _charsetService: ICharsetService,\n private readonly _coreService: ICoreService,\n private readonly _dirtyRowService: IDirtyRowService,\n private readonly _logService: ILogService,\n private readonly _optionsService: IOptionsService,\n private readonly _coreMouseService: ICoreMouseService,\n private readonly _unicodeService: IUnicodeService,\n private readonly _instantiationService: IInstantiationService,\n private readonly _parser: IEscapeSequenceParser = new EscapeSequenceParser())\n {\n super();\n this.register(this._parser);\n\n /**\n * custom fallback handlers\n */\n this._parser.setCsiHandlerFallback((ident, params) => {\n this._logService.debug('Unknown CSI code: ', { identifier: this._parser.identToString(ident), params: params.toArray() });\n });\n this._parser.setEscHandlerFallback(ident => {\n this._logService.debug('Unknown ESC code: ', { identifier: this._parser.identToString(ident) });\n });\n this._parser.setExecuteHandlerFallback(code => {\n this._logService.debug('Unknown EXECUTE code: ', { code });\n });\n this._parser.setOscHandlerFallback((identifier, action, data) => {\n this._logService.debug('Unknown OSC code: ', { identifier, action, data });\n });\n this._parser.setDcsHandlerFallback((ident, action, payload) => {\n if (action === 'HOOK') {\n payload = payload.toArray();\n }\n this._logService.debug('Unknown DCS code: ', { identifier: this._parser.identToString(ident), action, payload });\n });\n\n /**\n * print handler\n */\n this._parser.setPrintHandler((data, start, end) => this.print(data, start, end));\n\n /**\n * CSI handler\n */\n this._parser.setCsiHandler({final: '@'}, params => this.insertChars(params));\n this._parser.setCsiHandler({intermediates: ' ', final: '@'}, params => this.scrollLeft(params));\n this._parser.setCsiHandler({final: 'A'}, params => this.cursorUp(params));\n this._parser.setCsiHandler({intermediates: ' ', final: 'A'}, params => this.scrollRight(params));\n this._parser.setCsiHandler({final: 'B'}, params => this.cursorDown(params));\n this._parser.setCsiHandler({final: 'C'}, params => this.cursorForward(params));\n this._parser.setCsiHandler({final: 'D'}, params => this.cursorBackward(params));\n this._parser.setCsiHandler({final: 'E'}, params => this.cursorNextLine(params));\n this._parser.setCsiHandler({final: 'F'}, params => this.cursorPrecedingLine(params));\n this._parser.setCsiHandler({final: 'G'}, params => this.cursorCharAbsolute(params));\n this._parser.setCsiHandler({final: 'H'}, params => this.cursorPosition(params));\n this._parser.setCsiHandler({final: 'I'}, params => this.cursorForwardTab(params));\n this._parser.setCsiHandler({final: 'J'}, params => this.eraseInDisplay(params));\n this._parser.setCsiHandler({prefix: '?', final: 'J'}, params => this.eraseInDisplay(params));\n this._parser.setCsiHandler({final: 'K'}, params => this.eraseInLine(params));\n this._parser.setCsiHandler({prefix: '?', final: 'K'}, params => this.eraseInLine(params));\n this._parser.setCsiHandler({final: 'L'}, params => this.insertLines(params));\n this._parser.setCsiHandler({final: 'M'}, params => this.deleteLines(params));\n this._parser.setCsiHandler({final: 'P'}, params => this.deleteChars(params));\n this._parser.setCsiHandler({final: 'S'}, params => this.scrollUp(params));\n this._parser.setCsiHandler({final: 'T'}, params => this.scrollDown(params));\n this._parser.setCsiHandler({final: 'X'}, params => this.eraseChars(params));\n this._parser.setCsiHandler({final: 'Z'}, params => this.cursorBackwardTab(params));\n this._parser.setCsiHandler({final: '`'}, params => this.charPosAbsolute(params));\n this._parser.setCsiHandler({final: 'a'}, params => this.hPositionRelative(params));\n this._parser.setCsiHandler({final: 'b'}, params => this.repeatPrecedingCharacter(params));\n this._parser.setCsiHandler({final: 'c'}, params => this.sendDeviceAttributesPrimary(params));\n this._parser.setCsiHandler({prefix: '>', final: 'c'}, params => this.sendDeviceAttributesSecondary(params));\n this._parser.setCsiHandler({final: 'd'}, params => this.linePosAbsolute(params));\n this._parser.setCsiHandler({final: 'e'}, params => this.vPositionRelative(params));\n this._parser.setCsiHandler({final: 'f'}, params => this.hVPosition(params));\n this._parser.setCsiHandler({final: 'g'}, params => this.tabClear(params));\n this._parser.setCsiHandler({final: 'h'}, params => this.setMode(params));\n this._parser.setCsiHandler({prefix: '?', final: 'h'}, params => this.setModePrivate(params));\n this._parser.setCsiHandler({final: 'l'}, params => this.resetMode(params));\n this._parser.setCsiHandler({prefix: '?', final: 'l'}, params => this.resetModePrivate(params));\n this._parser.setCsiHandler({final: 'm'}, params => this.charAttributes(params));\n this._parser.setCsiHandler({final: 'n'}, params => this.deviceStatus(params));\n this._parser.setCsiHandler({prefix: '?', final: 'n'}, params => this.deviceStatusPrivate(params));\n this._parser.setCsiHandler({intermediates: '!', final: 'p'}, params => this.softReset(params));\n this._parser.setCsiHandler({intermediates: ' ', final: 'q'}, params => this.setCursorStyle(params));\n this._parser.setCsiHandler({final: 'r'}, params => this.setScrollRegion(params));\n this._parser.setCsiHandler({final: 's'}, params => this.saveCursor(params));\n this._parser.setCsiHandler({final: 't'}, params => this.windowOptions(params));\n this._parser.setCsiHandler({final: 'u'}, params => this.restoreCursor(params));\n this._parser.setCsiHandler({intermediates: '\\'', final: '}'}, params => this.insertColumns(params));\n this._parser.setCsiHandler({intermediates: '\\'', final: '~'}, params => this.deleteColumns(params));\n\n /**\n * execute handler\n */\n this._parser.setExecuteHandler(C0.BEL, () => this.bell());\n this._parser.setExecuteHandler(C0.LF, () => this.lineFeed());\n this._parser.setExecuteHandler(C0.VT, () => this.lineFeed());\n this._parser.setExecuteHandler(C0.FF, () => this.lineFeed());\n this._parser.setExecuteHandler(C0.CR, () => this.carriageReturn());\n this._parser.setExecuteHandler(C0.BS, () => this.backspace());\n this._parser.setExecuteHandler(C0.HT, () => this.tab());\n this._parser.setExecuteHandler(C0.SO, () => this.shiftOut());\n this._parser.setExecuteHandler(C0.SI, () => this.shiftIn());\n // FIXME: What do to with missing? Old code just added those to print.\n\n this._parser.setExecuteHandler(C1.IND, () => this.index());\n this._parser.setExecuteHandler(C1.NEL, () => this.nextLine());\n this._parser.setExecuteHandler(C1.HTS, () => this.tabSet());\n\n /**\n * OSC handler\n */\n // 0 - icon name + title\n this._parser.setOscHandler(0, new OscHandler((data: string) => { this.setTitle(data); this.setIconName(data); }));\n // 1 - icon name\n this._parser.setOscHandler(1, new OscHandler((data: string) => this.setIconName(data)));\n // 2 - title\n this._parser.setOscHandler(2, new OscHandler((data: string) => this.setTitle(data)));\n // 3 - set property X in the form \"prop=value\"\n // 4 - Change Color Number\n // 5 - Change Special Color Number\n // 6 - Enable/disable Special Color Number c\n // 7 - current directory? (not in xterm spec, see https://gitlab.com/gnachman/iterm2/issues/3939)\n // 10 - Change VT100 text foreground color to Pt.\n // 11 - Change VT100 text background color to Pt.\n // 12 - Change text cursor color to Pt.\n // 13 - Change mouse foreground color to Pt.\n // 14 - Change mouse background color to Pt.\n // 15 - Change Tektronix foreground color to Pt.\n // 16 - Change Tektronix background color to Pt.\n // 17 - Change highlight background color to Pt.\n // 18 - Change Tektronix cursor color to Pt.\n // 19 - Change highlight foreground color to Pt.\n // 46 - Change Log File to Pt.\n // 50 - Set Font to Pt.\n // 51 - reserved for Emacs shell.\n // 52 - Manipulate Selection Data.\n // 104 ; c - Reset Color Number c.\n // 105 ; c - Reset Special Color Number c.\n // 106 ; c; f - Enable/disable Special Color Number c.\n // 110 - Reset VT100 text foreground color.\n // 111 - Reset VT100 text background color.\n // 112 - Reset text cursor color.\n // 113 - Reset mouse foreground color.\n // 114 - Reset mouse background color.\n // 115 - Reset Tektronix foreground color.\n // 116 - Reset Tektronix background color.\n // 117 - Reset highlight color.\n // 118 - Reset Tektronix cursor color.\n // 119 - Reset highlight foreground color.\n\n /**\n * ESC handlers\n */\n this._parser.setEscHandler({final: '7'}, () => this.saveCursor());\n this._parser.setEscHandler({final: '8'}, () => this.restoreCursor());\n this._parser.setEscHandler({final: 'D'}, () => this.index());\n this._parser.setEscHandler({final: 'E'}, () => this.nextLine());\n this._parser.setEscHandler({final: 'H'}, () => this.tabSet());\n this._parser.setEscHandler({final: 'M'}, () => this.reverseIndex());\n this._parser.setEscHandler({final: '='}, () => this.keypadApplicationMode());\n this._parser.setEscHandler({final: '>'}, () => this.keypadNumericMode());\n this._parser.setEscHandler({final: 'c'}, () => this.fullReset());\n this._parser.setEscHandler({final: 'n'}, () => this.setgLevel(2));\n this._parser.setEscHandler({final: 'o'}, () => this.setgLevel(3));\n this._parser.setEscHandler({final: '|'}, () => this.setgLevel(3));\n this._parser.setEscHandler({final: '}'}, () => this.setgLevel(2));\n this._parser.setEscHandler({final: '~'}, () => this.setgLevel(1));\n this._parser.setEscHandler({intermediates: '%', final: '@'}, () => this.selectDefaultCharset());\n this._parser.setEscHandler({intermediates: '%', final: 'G'}, () => this.selectDefaultCharset());\n for (const flag in CHARSETS) {\n this._parser.setEscHandler({intermediates: '(', final: flag}, () => this.selectCharset('(' + flag));\n this._parser.setEscHandler({intermediates: ')', final: flag}, () => this.selectCharset(')' + flag));\n this._parser.setEscHandler({intermediates: '*', final: flag}, () => this.selectCharset('*' + flag));\n this._parser.setEscHandler({intermediates: '+', final: flag}, () => this.selectCharset('+' + flag));\n this._parser.setEscHandler({intermediates: '-', final: flag}, () => this.selectCharset('-' + flag));\n this._parser.setEscHandler({intermediates: '.', final: flag}, () => this.selectCharset('.' + flag));\n this._parser.setEscHandler({intermediates: '/', final: flag}, () => this.selectCharset('/' + flag)); // TODO: supported?\n }\n this._parser.setEscHandler({intermediates: '#', final: '8'}, () => this.screenAlignmentPattern());\n\n /**\n * error handler\n */\n this._parser.setErrorHandler((state: IParsingState) => {\n this._logService.error('Parsing error: ', state);\n return state;\n });\n\n /**\n * DCS handler\n */\n this._parser.setDcsHandler({intermediates: '$', final: 'q'}, new DECRQSS(this._bufferService, this._coreService, this._logService, this._optionsService));\n }\n\n public dispose(): void {\n super.dispose();\n }\n\n public parse(data: string | Uint8Array): void {\n let buffer = this._bufferService.buffer;\n const cursorStartX = buffer.x;\n const cursorStartY = buffer.y;\n\n this._logService.debug('parsing data', data);\n\n // resize input buffer if needed\n if (this._parseBuffer.length < data.length) {\n if (this._parseBuffer.length < MAX_PARSEBUFFER_LENGTH) {\n this._parseBuffer = new Uint32Array(Math.min(data.length, MAX_PARSEBUFFER_LENGTH));\n }\n }\n\n // Clear the dirty row service so we know which lines changed as a result of parsing\n this._dirtyRowService.clearRange();\n\n // process big data in smaller chunks\n if (data.length > MAX_PARSEBUFFER_LENGTH) {\n for (let i = 0; i < data.length; i += MAX_PARSEBUFFER_LENGTH) {\n const end = i + MAX_PARSEBUFFER_LENGTH < data.length ? i + MAX_PARSEBUFFER_LENGTH : data.length;\n const len = (typeof data === 'string')\n ? this._stringDecoder.decode(data.substring(i, end), this._parseBuffer)\n : this._utf8Decoder.decode(data.subarray(i, end), this._parseBuffer);\n this._parser.parse(this._parseBuffer, len);\n }\n } else {\n const len = (typeof data === 'string')\n ? this._stringDecoder.decode(data, this._parseBuffer)\n : this._utf8Decoder.decode(data, this._parseBuffer);\n this._parser.parse(this._parseBuffer, len);\n }\n\n buffer = this._bufferService.buffer;\n if (buffer.x !== cursorStartX || buffer.y !== cursorStartY) {\n this._onCursorMove.fire();\n }\n\n // Refresh any dirty rows accumulated as part of parsing\n this._onRequestRefreshRows.fire(this._dirtyRowService.start, this._dirtyRowService.end);\n }\n\n public print(data: Uint32Array, start: number, end: number): void {\n let code: number;\n let chWidth: number;\n const buffer = this._bufferService.buffer;\n const charset = this._charsetService.charset;\n const screenReaderMode = this._optionsService.options.screenReaderMode;\n const cols = this._bufferService.cols;\n const wraparoundMode = this._coreService.decPrivateModes.wraparound;\n const insertMode = this._terminal.insertMode;\n const curAttr = this._curAttrData;\n let bufferRow = buffer.lines.get(buffer.y + buffer.ybase);\n\n this._dirtyRowService.markDirty(buffer.y);\n\n // handle wide chars: reset start_cell-1 if we would overwrite the second cell of a wide char\n if (buffer.x && end - start > 0 && bufferRow.getWidth(buffer.x - 1) === 2) {\n bufferRow.setCellFromCodePoint(buffer.x - 1, 0, 1, curAttr.fg, curAttr.bg);\n }\n\n for (let pos = start; pos < end; ++pos) {\n code = data[pos];\n\n // calculate print space\n // expensive call, therefore we save width in line buffer\n chWidth = this._unicodeService.wcwidth(code);\n\n // get charset replacement character\n // charset is only defined for ASCII, therefore we only\n // search for an replacement char if code < 127\n if (code < 127 && charset) {\n const ch = charset[String.fromCharCode(code)];\n if (ch) {\n code = ch.charCodeAt(0);\n }\n }\n\n if (screenReaderMode) {\n this._terminal.onA11yCharEmitter.fire(stringFromCodePoint(code));\n }\n\n // insert combining char at last cursor position\n // buffer.x should never be 0 for a combining char\n // since they always follow a cell consuming char\n // therefore we can test for buffer.x to avoid overflow left\n if (!chWidth && buffer.x) {\n if (!bufferRow.getWidth(buffer.x - 1)) {\n // found empty cell after fullwidth, need to go 2 cells back\n // it is save to step 2 cells back here\n // since an empty cell is only set by fullwidth chars\n bufferRow.addCodepointToCell(buffer.x - 2, code);\n } else {\n bufferRow.addCodepointToCell(buffer.x - 1, code);\n }\n continue;\n }\n\n // goto next line if ch would overflow\n // NOTE: To avoid costly width checks here,\n // the terminal does not allow a cols < 2.\n if (buffer.x + chWidth - 1 >= cols) {\n // autowrap - DECAWM\n // automatically wraps to the beginning of the next line\n if (wraparoundMode) {\n buffer.x = 0;\n buffer.y++;\n if (buffer.y === buffer.scrollBottom + 1) {\n buffer.y--;\n this._terminal.scroll(this._eraseAttrData(), true);\n } else {\n if (buffer.y >= this._bufferService.rows) {\n buffer.y = this._bufferService.rows - 1;\n }\n // The line already exists (eg. the initial viewport), mark it as a\n // wrapped line\n buffer.lines.get(buffer.y).isWrapped = true;\n }\n // row changed, get it again\n bufferRow = buffer.lines.get(buffer.y + buffer.ybase);\n } else {\n buffer.x = cols - 1;\n if (chWidth === 2) {\n // FIXME: check for xterm behavior\n // What to do here? We got a wide char that does not fit into last cell\n continue;\n }\n }\n }\n\n // insert mode: move characters to right\n if (insertMode) {\n // right shift cells according to the width\n bufferRow.insertCells(buffer.x, chWidth, buffer.getNullCell(curAttr), curAttr);\n // test last cell - since the last cell has only room for\n // a halfwidth char any fullwidth shifted there is lost\n // and will be set to empty cell\n if (bufferRow.getWidth(cols - 1) === 2) {\n bufferRow.setCellFromCodePoint(cols - 1, NULL_CELL_CODE, NULL_CELL_WIDTH, curAttr.fg, curAttr.bg);\n }\n }\n\n // write current char to buffer and advance cursor\n bufferRow.setCellFromCodePoint(buffer.x++, code, chWidth, curAttr.fg, curAttr.bg);\n\n // fullwidth char - also set next cell to placeholder stub and advance cursor\n // for graphemes bigger than fullwidth we can simply loop to zero\n // we already made sure above, that buffer.x + chWidth will not overflow right\n if (chWidth > 0) {\n while (--chWidth) {\n // other than a regular empty cell a cell following a wide char has no width\n bufferRow.setCellFromCodePoint(buffer.x++, 0, 0, curAttr.fg, curAttr.bg);\n }\n }\n }\n // store last char in Parser.precedingCodepoint for REP to work correctly\n // This needs to check whether:\n // - fullwidth + surrogates: reset\n // - combining: only base char gets carried on (bug in xterm?)\n if (end - start > 0) {\n bufferRow.loadCell(buffer.x - 1, this._workCell);\n if (this._workCell.getWidth() === 2 || this._workCell.getCode() > 0xFFFF) {\n this._parser.precedingCodepoint = 0;\n } else if (this._workCell.isCombined()) {\n this._parser.precedingCodepoint = this._workCell.getChars().charCodeAt(0);\n } else {\n this._parser.precedingCodepoint = this._workCell.content;\n }\n }\n\n // handle wide chars: reset cell to the right if it is second cell of a wide char\n if (buffer.x < cols && end - start > 0 && bufferRow.getWidth(buffer.x) === 0 && !bufferRow.hasContent(buffer.x)) {\n bufferRow.setCellFromCodePoint(buffer.x, 0, 1, curAttr.fg, curAttr.bg);\n }\n\n this._dirtyRowService.markDirty(buffer.y);\n }\n\n /**\n * Forward addCsiHandler from parser.\n */\n public addCsiHandler(id: IFunctionIdentifier, callback: (params: IParams) => boolean): IDisposable {\n if (id.final === 't' && !id.prefix && !id.intermediates) {\n // security: always check whether window option is allowed\n return this._parser.addCsiHandler(id, params => {\n if (!paramToWindowOption(params.params[0], this._optionsService.options.windowOptions)) {\n return true;\n }\n return callback(params);\n });\n }\n return this._parser.addCsiHandler(id, callback);\n }\n\n /**\n * Forward addDcsHandler from parser.\n */\n public addDcsHandler(id: IFunctionIdentifier, callback: (data: string, param: IParams) => boolean): IDisposable {\n return this._parser.addDcsHandler(id, new DcsHandler(callback));\n }\n\n /**\n * Forward addEscHandler from parser.\n */\n public addEscHandler(id: IFunctionIdentifier, callback: () => boolean): IDisposable {\n return this._parser.addEscHandler(id, callback);\n }\n\n /**\n * Forward addOscHandler from parser.\n */\n public addOscHandler(ident: number, callback: (data: string) => boolean): IDisposable {\n return this._parser.addOscHandler(ident, new OscHandler(callback));\n }\n\n /**\n * BEL\n * Bell (Ctrl-G).\n *\n * @vt: #Y C0 BEL \"Bell\" \"\\a, \\x07\" \"Ring the bell.\"\n * The behavior of the bell is further customizable with `ITerminalOptions.bellStyle`\n * and `ITerminalOptions.bellSound`.\n */\n public bell(): void {\n this._onRequestBell.fire();\n }\n\n /**\n * LF\n * Line Feed or New Line (NL). (LF is Ctrl-J).\n *\n * @vt: #Y C0 LF \"Line Feed\" \"\\n, \\x0A\" \"Move the cursor one row down, scrolling if needed.\"\n * Scrolling is restricted to scroll margins and will only happen on the bottom line.\n *\n * @vt: #Y C0 VT \"Vertical Tabulation\" \"\\v, \\x0B\" \"Treated as LF.\"\n * @vt: #Y C0 FF \"Form Feed\" \"\\f, \\x0C\" \"Treated as LF.\"\n */\n public lineFeed(): void {\n // make buffer local for faster access\n const buffer = this._bufferService.buffer;\n\n this._dirtyRowService.markDirty(buffer.y);\n if (this._optionsService.options.convertEol) {\n buffer.x = 0;\n }\n buffer.y++;\n if (buffer.y === buffer.scrollBottom + 1) {\n buffer.y--;\n this._terminal.scroll(this._eraseAttrData());\n } else if (buffer.y >= this._bufferService.rows) {\n buffer.y = this._bufferService.rows - 1;\n }\n // If the end of the line is hit, prevent this action from wrapping around to the next line.\n if (buffer.x >= this._bufferService.cols) {\n buffer.x--;\n }\n this._dirtyRowService.markDirty(buffer.y);\n\n this._onLineFeed.fire();\n }\n\n /**\n * CR\n * Carriage Return (Ctrl-M).\n *\n * @vt: #Y C0 CR \"Carriage Return\" \"\\r, \\x0D\" \"Move the cursor to the beginning of the row.\"\n */\n public carriageReturn(): void {\n this._bufferService.buffer.x = 0;\n }\n\n /**\n * BS\n * Backspace (Ctrl-H).\n *\n * @vt: #Y C0 BS \"Backspace\" \"\\b, \\x08\" \"Move the cursor one position to the left.\"\n */\n public backspace(): void {\n this._restrictCursor();\n if (this._bufferService.buffer.x > 0) {\n this._bufferService.buffer.x--;\n }\n }\n\n /**\n * TAB\n * Horizontal Tab (HT) (Ctrl-I).\n *\n * @vt: #Y C0 HT \"Horizontal Tabulation\" \"\\t, \\x09\" \"Move the cursor to the next character tab stop.\"\n */\n public tab(): void {\n if (this._bufferService.buffer.x >= this._bufferService.cols) {\n return;\n }\n const originalX = this._bufferService.buffer.x;\n this._bufferService.buffer.x = this._bufferService.buffer.nextStop();\n if (this._optionsService.options.screenReaderMode) {\n this._terminal.onA11yTabEmitter.fire(this._bufferService.buffer.x - originalX);\n }\n }\n\n /**\n * SO\n * Shift Out (Ctrl-N) -> Switch to Alternate Character Set. This invokes the\n * G1 character set.\n *\n * @vt: #P[Only limited ISO-2022 charset support.] C0 SO \"Shift Out\" \"\\x0E\" \"Switch to an alternative character set.\"\n */\n public shiftOut(): void {\n this._charsetService.setgLevel(1);\n }\n\n /**\n * SI\n * Shift In (Ctrl-O) -> Switch to Standard Character Set. This invokes the G0\n * character set (the default).\n *\n * @vt: #Y C0 SI \"Shift In\" \"\\x0F\" \"Return to regular character set after Shift Out.\"\n */\n public shiftIn(): void {\n this._charsetService.setgLevel(0);\n }\n\n /**\n * Restrict cursor to viewport size / scroll margin (origin mode).\n */\n private _restrictCursor(): void {\n this._bufferService.buffer.x = Math.min(this._bufferService.cols - 1, Math.max(0, this._bufferService.buffer.x));\n this._bufferService.buffer.y = this._coreService.decPrivateModes.origin\n ? Math.min(this._bufferService.buffer.scrollBottom, Math.max(this._bufferService.buffer.scrollTop, this._bufferService.buffer.y))\n : Math.min(this._bufferService.rows - 1, Math.max(0, this._bufferService.buffer.y));\n this._dirtyRowService.markDirty(this._bufferService.buffer.y);\n }\n\n /**\n * Set absolute cursor position.\n */\n private _setCursor(x: number, y: number): void {\n this._dirtyRowService.markDirty(this._bufferService.buffer.y);\n if (this._coreService.decPrivateModes.origin) {\n this._bufferService.buffer.x = x;\n this._bufferService.buffer.y = this._bufferService.buffer.scrollTop + y;\n } else {\n this._bufferService.buffer.x = x;\n this._bufferService.buffer.y = y;\n }\n this._restrictCursor();\n this._dirtyRowService.markDirty(this._bufferService.buffer.y);\n }\n\n /**\n * Set relative cursor position.\n */\n private _moveCursor(x: number, y: number): void {\n // for relative changes we have to make sure we are within 0 .. cols/rows - 1\n // before calculating the new position\n this._restrictCursor();\n this._setCursor(this._bufferService.buffer.x + x, this._bufferService.buffer.y + y);\n }\n\n /**\n * CSI Ps A\n * Cursor Up Ps Times (default = 1) (CUU).\n *\n * @vt: #Y CSI CUU \"Cursor Up\" \"CSI Ps A\" \"Move cursor `Ps` times up (default=1).\"\n * If the cursor would pass the top scroll margin, it will stop there.\n */\n public cursorUp(params: IParams): void {\n // stop at scrollTop\n const diffToTop = this._bufferService.buffer.y - this._bufferService.buffer.scrollTop;\n if (diffToTop >= 0) {\n this._moveCursor(0, -Math.min(diffToTop, params.params[0] || 1));\n } else {\n this._moveCursor(0, -(params.params[0] || 1));\n }\n }\n\n /**\n * CSI Ps B\n * Cursor Down Ps Times (default = 1) (CUD).\n *\n * @vt: #Y CSI CUD \"Cursor Down\" \"CSI Ps B\" \"Move cursor `Ps` times down (default=1).\"\n * If the cursor would pass the bottom scroll margin, it will stop there.\n */\n public cursorDown(params: IParams): void {\n // stop at scrollBottom\n const diffToBottom = this._bufferService.buffer.scrollBottom - this._bufferService.buffer.y;\n if (diffToBottom >= 0) {\n this._moveCursor(0, Math.min(diffToBottom, params.params[0] || 1));\n } else {\n this._moveCursor(0, params.params[0] || 1);\n }\n }\n\n /**\n * CSI Ps C\n * Cursor Forward Ps Times (default = 1) (CUF).\n *\n * @vt: #Y CSI CUF \"Cursor Forward\" \"CSI Ps C\" \"Move cursor `Ps` times forward (default=1).\"\n */\n public cursorForward(params: IParams): void {\n this._moveCursor(params.params[0] || 1, 0);\n }\n\n /**\n * CSI Ps D\n * Cursor Backward Ps Times (default = 1) (CUB).\n *\n * @vt: #Y CSI CUB \"Cursor Backward\" \"CSI Ps D\" \"Move cursor `Ps` times backward (default=1).\"\n */\n public cursorBackward(params: IParams): void {\n this._moveCursor(-(params.params[0] || 1), 0);\n }\n\n /**\n * CSI Ps E\n * Cursor Next Line Ps Times (default = 1) (CNL).\n * Other than cursorDown (CUD) also set the cursor to first column.\n *\n * @vt: #Y CSI CNL \"Cursor Next Line\" \"CSI Ps E\" \"Move cursor `Ps` times down (default=1) and to the first column.\"\n * Same as CUD, additionally places the cursor at the first column.\n */\n public cursorNextLine(params: IParams): void {\n this.cursorDown(params);\n this._bufferService.buffer.x = 0;\n }\n\n /**\n * CSI Ps F\n * Cursor Previous Line Ps Times (default = 1) (CPL).\n * Other than cursorUp (CUU) also set the cursor to first column.\n *\n * @vt: #Y CSI CPL \"Cursor Backward\" \"CSI Ps F\" \"Move cursor `Ps` times up (default=1) and to the first column.\"\n * Same as CUU, additionally places the cursor at the first column.\n */\n public cursorPrecedingLine(params: IParams): void {\n this.cursorUp(params);\n this._bufferService.buffer.x = 0;\n }\n\n /**\n * CSI Ps G\n * Cursor Character Absolute [column] (default = [row,1]) (CHA).\n *\n * @vt: #Y CSI CHA \"Cursor Horizontal Absolute\" \"CSI Ps G\" \"Move cursor to `Ps`-th column of the active row (default=1).\"\n */\n public cursorCharAbsolute(params: IParams): void {\n this._setCursor((params.params[0] || 1) - 1, this._bufferService.buffer.y);\n }\n\n /**\n * CSI Ps ; Ps H\n * Cursor Position [row;column] (default = [1,1]) (CUP).\n *\n * @vt: #Y CSI CUP \"Cursor Position\" \"CSI Ps ; Ps H\" \"Set cursor to position [`Ps`, `Ps`] (default = [1, 1]).\"\n * If ORIGIN mode is set, places the cursor to the absolute position within the scroll margins.\n * If ORIGIN mode is not set, places the cursor to the absolute position within the viewport.\n * Note that the coordinates are 1-based, thus the top left position starts at `1 ; 1`.\n */\n public cursorPosition(params: IParams): void {\n this._setCursor(\n // col\n (params.length >= 2) ? (params.params[1] || 1) - 1 : 0,\n // row\n (params.params[0] || 1) - 1);\n }\n\n /**\n * CSI Pm ` Character Position Absolute\n * [column] (default = [row,1]) (HPA).\n * Currently same functionality as CHA.\n *\n * @vt: #Y CSI HPA \"Horizontal Position Absolute\" \"CSI Ps ` \" \"Same as CHA.\"\n */\n public charPosAbsolute(params: IParams): void {\n this._setCursor((params.params[0] || 1) - 1, this._bufferService.buffer.y);\n }\n\n /**\n * CSI Pm a Character Position Relative\n * [columns] (default = [row,col+1]) (HPR)\n *\n * @vt: #Y CSI HPR \"Horizontal Position Relative\" \"CSI Ps a\" \"Same as CUF.\"\n */\n public hPositionRelative(params: IParams): void {\n this._moveCursor(params.params[0] || 1, 0);\n }\n\n /**\n * CSI Pm d Vertical Position Absolute (VPA)\n * [row] (default = [1,column])\n *\n * @vt: #Y CSI VPA \"Vertical Position Absolute\" \"CSI Ps d\" \"Move cursor to `Ps`-th row (default=1).\"\n */\n public linePosAbsolute(params: IParams): void {\n this._setCursor(this._bufferService.buffer.x, (params.params[0] || 1) - 1);\n }\n\n /**\n * CSI Pm e Vertical Position Relative (VPR)\n * [rows] (default = [row+1,column])\n * reuse CSI Ps B ?\n *\n * @vt: #Y CSI VPR \"Vertical Position Relative\" \"CSI Ps e\" \"Move cursor `Ps` times down (default=1).\"\n */\n public vPositionRelative(params: IParams): void {\n this._moveCursor(0, params.params[0] || 1);\n }\n\n /**\n * CSI Ps ; Ps f\n * Horizontal and Vertical Position [row;column] (default =\n * [1,1]) (HVP).\n * Same as CUP.\n *\n * @vt: #Y CSI HVP \"Horizontal and Vertical Position\" \"CSI Ps ; Ps f\" \"Same as CUP.\"\n */\n public hVPosition(params: IParams): void {\n this.cursorPosition(params);\n }\n\n /**\n * CSI Ps g Tab Clear (TBC).\n * Ps = 0 -> Clear Current Column (default).\n * Ps = 3 -> Clear All.\n * Potentially:\n * Ps = 2 -> Clear Stops on Line.\n * http://vt100.net/annarbor/aaa-ug/section6.html\n *\n * @vt: #Y CSI TBC \"Tab Clear\" \"CSI Ps g\" \"Clear tab stops at current position (0) or all (3) (default=0).\"\n * Clearing tabstops off the active row (Ps = 2, VT100) is currently not supported.\n */\n public tabClear(params: IParams): void {\n const param = params.params[0];\n if (param === 0) {\n delete this._bufferService.buffer.tabs[this._bufferService.buffer.x];\n } else if (param === 3) {\n this._bufferService.buffer.tabs = {};\n }\n }\n\n /**\n * CSI Ps I\n * Cursor Forward Tabulation Ps tab stops (default = 1) (CHT).\n *\n * @vt: #Y CSI CHT \"Cursor Horizontal Tabulation\" \"CSI Ps I\" \"Move cursor `Ps` times tabs forward (default=1).\"\n */\n public cursorForwardTab(params: IParams): void {\n if (this._bufferService.buffer.x >= this._bufferService.cols) {\n return;\n }\n let param = params.params[0] || 1;\n while (param--) {\n this._bufferService.buffer.x = this._bufferService.buffer.nextStop();\n }\n }\n\n /**\n * CSI Ps Z Cursor Backward Tabulation Ps tab stops (default = 1) (CBT).\n *\n * @vt: #Y CSI CBT \"Cursor Backward Tabulation\" \"CSI Ps Z\" \"Move cursor `Ps` tabs backward (default=1).\"\n */\n public cursorBackwardTab(params: IParams): void {\n if (this._bufferService.buffer.x >= this._bufferService.cols) {\n return;\n }\n let param = params.params[0] || 1;\n\n // make buffer local for faster access\n const buffer = this._bufferService.buffer;\n\n while (param--) {\n buffer.x = buffer.prevStop();\n }\n }\n\n\n /**\n * Helper method to erase cells in a terminal row.\n * The cell gets replaced with the eraseChar of the terminal.\n * @param y row index\n * @param start first cell index to be erased\n * @param end end - 1 is last erased cell\n */\n private _eraseInBufferLine(y: number, start: number, end: number, clearWrap: boolean = false): void {\n const line = this._bufferService.buffer.lines.get(this._bufferService.buffer.ybase + y);\n line.replaceCells(\n start,\n end,\n this._bufferService.buffer.getNullCell(this._eraseAttrData()),\n this._eraseAttrData()\n );\n if (clearWrap) {\n line.isWrapped = false;\n }\n }\n\n /**\n * Helper method to reset cells in a terminal row.\n * The cell gets replaced with the eraseChar of the terminal and the isWrapped property is set to false.\n * @param y row index\n */\n private _resetBufferLine(y: number): void {\n const line = this._bufferService.buffer.lines.get(this._bufferService.buffer.ybase + y);\n line.fill(this._bufferService.buffer.getNullCell(this._eraseAttrData()));\n line.isWrapped = false;\n }\n\n /**\n * CSI Ps J Erase in Display (ED).\n * Ps = 0 -> Erase Below (default).\n * Ps = 1 -> Erase Above.\n * Ps = 2 -> Erase All.\n * Ps = 3 -> Erase Saved Lines (xterm).\n * CSI ? Ps J\n * Erase in Display (DECSED).\n * Ps = 0 -> Selective Erase Below (default).\n * Ps = 1 -> Selective Erase Above.\n * Ps = 2 -> Selective Erase All.\n *\n * @vt: #Y CSI ED \"Erase In Display\" \"CSI Ps J\" \"Erase various parts of the viewport.\"\n * Supported param values:\n *\n * | Ps | Effect |\n * | -- | ------------------------------------------------------------ |\n * | 0 | Erase from the cursor through the end of the viewport. |\n * | 1 | Erase from the beginning of the viewport through the cursor. |\n * | 2 | Erase complete viewport. |\n * | 3 | Erase scrollback. |\n *\n * @vt: #P[Protection attributes are not supported.] CSI DECSED \"Selective Erase In Display\" \"CSI ? Ps J\" \"Currently the same as ED.\"\n */\n public eraseInDisplay(params: IParams): void {\n this._restrictCursor();\n let j;\n switch (params.params[0]) {\n case 0:\n j = this._bufferService.buffer.y;\n this._dirtyRowService.markDirty(j);\n this._eraseInBufferLine(j++, this._bufferService.buffer.x, this._bufferService.cols, this._bufferService.buffer.x === 0);\n for (; j < this._bufferService.rows; j++) {\n this._resetBufferLine(j);\n }\n this._dirtyRowService.markDirty(j);\n break;\n case 1:\n j = this._bufferService.buffer.y;\n this._dirtyRowService.markDirty(j);\n // Deleted front part of line and everything before. This line will no longer be wrapped.\n this._eraseInBufferLine(j, 0, this._bufferService.buffer.x + 1, true);\n if (this._bufferService.buffer.x + 1 >= this._bufferService.cols) {\n // Deleted entire previous line. This next line can no longer be wrapped.\n this._bufferService.buffer.lines.get(j + 1).isWrapped = false;\n }\n while (j--) {\n this._resetBufferLine(j);\n }\n this._dirtyRowService.markDirty(0);\n break;\n case 2:\n j = this._bufferService.rows;\n this._dirtyRowService.markDirty(j - 1);\n while (j--) {\n this._resetBufferLine(j);\n }\n this._dirtyRowService.markDirty(0);\n break;\n case 3:\n // Clear scrollback (everything not in viewport)\n const scrollBackSize = this._bufferService.buffer.lines.length - this._bufferService.rows;\n if (scrollBackSize > 0) {\n this._bufferService.buffer.lines.trimStart(scrollBackSize);\n this._bufferService.buffer.ybase = Math.max(this._bufferService.buffer.ybase - scrollBackSize, 0);\n this._bufferService.buffer.ydisp = Math.max(this._bufferService.buffer.ydisp - scrollBackSize, 0);\n // Force a scroll event to refresh viewport\n this._onScroll.fire(0);\n }\n break;\n }\n }\n\n /**\n * CSI Ps K Erase in Line (EL).\n * Ps = 0 -> Erase to Right (default).\n * Ps = 1 -> Erase to Left.\n * Ps = 2 -> Erase All.\n * CSI ? Ps K\n * Erase in Line (DECSEL).\n * Ps = 0 -> Selective Erase to Right (default).\n * Ps = 1 -> Selective Erase to Left.\n * Ps = 2 -> Selective Erase All.\n *\n * @vt: #Y CSI EL \"Erase In Line\" \"CSI Ps K\" \"Erase various parts of the active row.\"\n * Supported param values:\n *\n * | Ps | Effect |\n * | -- | -------------------------------------------------------- |\n * | 0 | Erase from the cursor through the end of the row. |\n * | 1 | Erase from the beginning of the line through the cursor. |\n * | 2 | Erase complete line. |\n *\n * @vt: #P[Protection attributes are not supported.] CSI DECSEL \"Selective Erase In Line\" \"CSI ? Ps K\" \"Currently the same as EL.\"\n */\n public eraseInLine(params: IParams): void {\n this._restrictCursor();\n switch (params.params[0]) {\n case 0:\n this._eraseInBufferLine(this._bufferService.buffer.y, this._bufferService.buffer.x, this._bufferService.cols);\n break;\n case 1:\n this._eraseInBufferLine(this._bufferService.buffer.y, 0, this._bufferService.buffer.x + 1);\n break;\n case 2:\n this._eraseInBufferLine(this._bufferService.buffer.y, 0, this._bufferService.cols);\n break;\n }\n this._dirtyRowService.markDirty(this._bufferService.buffer.y);\n }\n\n /**\n * CSI Ps L\n * Insert Ps Line(s) (default = 1) (IL).\n *\n * @vt: #Y CSI IL \"Insert Line\" \"CSI Ps L\" \"Insert `Ps` blank lines at active row (default=1).\"\n * For every inserted line at the scroll top one line at the scroll bottom gets removed.\n * The cursor is set to the first column.\n * IL has no effect if the cursor is outside the scroll margins.\n */\n public insertLines(params: IParams): void {\n this._restrictCursor();\n let param = params.params[0] || 1;\n\n // make buffer local for faster access\n const buffer = this._bufferService.buffer;\n\n if (buffer.y > buffer.scrollBottom || buffer.y < buffer.scrollTop) {\n return;\n }\n\n const row: number = buffer.y + buffer.ybase;\n\n const scrollBottomRowsOffset = this._bufferService.rows - 1 - buffer.scrollBottom;\n const scrollBottomAbsolute = this._bufferService.rows - 1 + buffer.ybase - scrollBottomRowsOffset + 1;\n while (param--) {\n // test: echo -e '\\e[44m\\e[1L\\e[0m'\n // blankLine(true) - xterm/linux behavior\n buffer.lines.splice(scrollBottomAbsolute - 1, 1);\n buffer.lines.splice(row, 0, buffer.getBlankLine(this._eraseAttrData()));\n }\n\n this._dirtyRowService.markRangeDirty(buffer.y, buffer.scrollBottom);\n buffer.x = 0; // see https://vt100.net/docs/vt220-rm/chapter4.html - vt220 only?\n }\n\n /**\n * CSI Ps M\n * Delete Ps Line(s) (default = 1) (DL).\n *\n * @vt: #Y CSI DL \"Delete Line\" \"CSI Ps M\" \"Delete `Ps` lines at active row (default=1).\"\n * For every deleted line at the scroll top one blank line at the scroll bottom gets appended.\n * The cursor is set to the first column.\n * DL has no effect if the cursor is outside the scroll margins.\n */\n public deleteLines(params: IParams): void {\n this._restrictCursor();\n let param = params.params[0] || 1;\n\n // make buffer local for faster access\n const buffer = this._bufferService.buffer;\n\n if (buffer.y > buffer.scrollBottom || buffer.y < buffer.scrollTop) {\n return;\n }\n\n const row: number = buffer.y + buffer.ybase;\n\n let j: number;\n j = this._bufferService.rows - 1 - buffer.scrollBottom;\n j = this._bufferService.rows - 1 + buffer.ybase - j;\n while (param--) {\n // test: echo -e '\\e[44m\\e[1M\\e[0m'\n // blankLine(true) - xterm/linux behavior\n buffer.lines.splice(row, 1);\n buffer.lines.splice(j, 0, buffer.getBlankLine(this._eraseAttrData()));\n }\n\n this._dirtyRowService.markRangeDirty(buffer.y, buffer.scrollBottom);\n buffer.x = 0; // see https://vt100.net/docs/vt220-rm/chapter4.html - vt220 only?\n }\n\n /**\n * CSI Ps @\n * Insert Ps (Blank) Character(s) (default = 1) (ICH).\n *\n * @vt: #Y CSI ICH \"Insert Characters\" \"CSI Ps @\" \"Insert `Ps` (blank) characters (default = 1).\"\n * The ICH sequence inserts `Ps` blank characters. The cursor remains at the beginning of the blank characters.\n * Text between the cursor and right margin moves to the right. Characters moved past the right margin are lost.\n *\n *\n * FIXME: check against xterm - should not work outside of scroll margins (see VT520 manual)\n */\n public insertChars(params: IParams): void {\n this._restrictCursor();\n const line = this._bufferService.buffer.lines.get(this._bufferService.buffer.y + this._bufferService.buffer.ybase);\n if (line) {\n line.insertCells(\n this._bufferService.buffer.x,\n params.params[0] || 1,\n this._bufferService.buffer.getNullCell(this._eraseAttrData()),\n this._eraseAttrData()\n );\n this._dirtyRowService.markDirty(this._bufferService.buffer.y);\n }\n }\n\n /**\n * CSI Ps P\n * Delete Ps Character(s) (default = 1) (DCH).\n *\n * @vt: #Y CSI DCH \"Delete Character\" \"CSI Ps P\" \"Delete `Ps` characters (default=1).\"\n * As characters are deleted, the remaining characters between the cursor and right margin move to the left.\n * Character attributes move with the characters. The terminal adds blank characters at the right margin.\n *\n *\n * FIXME: check against xterm - should not work outside of scroll margins (see VT520 manual)\n */\n public deleteChars(params: IParams): void {\n this._restrictCursor();\n const line = this._bufferService.buffer.lines.get(this._bufferService.buffer.y + this._bufferService.buffer.ybase);\n if (line) {\n line.deleteCells(\n this._bufferService.buffer.x,\n params.params[0] || 1,\n this._bufferService.buffer.getNullCell(this._eraseAttrData()),\n this._eraseAttrData()\n );\n this._dirtyRowService.markDirty(this._bufferService.buffer.y);\n }\n }\n\n /**\n * CSI Ps S Scroll up Ps lines (default = 1) (SU).\n *\n * @vt: #Y CSI SU \"Scroll Up\" \"CSI Ps S\" \"Scroll `Ps` lines up (default=1).\"\n *\n *\n * FIXME: scrolled out lines at top = 1 should add to scrollback (xterm)\n */\n public scrollUp(params: IParams): void {\n let param = params.params[0] || 1;\n\n // make buffer local for faster access\n const buffer = this._bufferService.buffer;\n\n while (param--) {\n buffer.lines.splice(buffer.ybase + buffer.scrollTop, 1);\n buffer.lines.splice(buffer.ybase + buffer.scrollBottom, 0, buffer.getBlankLine(this._eraseAttrData()));\n }\n this._dirtyRowService.markRangeDirty(buffer.scrollTop, buffer.scrollBottom);\n }\n\n /**\n * CSI Ps T Scroll down Ps lines (default = 1) (SD).\n *\n * @vt: #Y CSI SD \"Scroll Down\" \"CSI Ps T\" \"Scroll `Ps` lines down (default=1).\"\n */\n public scrollDown(params: IParams): void {\n let param = params.params[0] || 1;\n\n // make buffer local for faster access\n const buffer = this._bufferService.buffer;\n\n while (param--) {\n buffer.lines.splice(buffer.ybase + buffer.scrollBottom, 1);\n buffer.lines.splice(buffer.ybase + buffer.scrollTop, 0, buffer.getBlankLine(DEFAULT_ATTR_DATA));\n }\n this._dirtyRowService.markRangeDirty(buffer.scrollTop, buffer.scrollBottom);\n }\n\n /**\n * CSI Ps SP @ Scroll left Ps columns (default = 1) (SL) ECMA-48\n *\n * Notation: (Pn)\n * Representation: CSI Pn 02/00 04/00\n * Parameter default value: Pn = 1\n * SL causes the data in the presentation component to be moved by n character positions\n * if the line orientation is horizontal, or by n line positions if the line orientation\n * is vertical, such that the data appear to move to the left; where n equals the value of Pn.\n * The active presentation position is not affected by this control function.\n *\n * Supported:\n * - always left shift (no line orientation setting respected)\n *\n * @vt: #Y CSI SL \"Scroll Left\" \"CSI Ps SP @\" \"Scroll viewport `Ps` times to the left.\"\n * SL moves the content of all lines within the scroll margins `Ps` times to the left.\n * SL has no effect outside of the scroll margins.\n */\n public scrollLeft(params: IParams): void {\n const buffer = this._bufferService.buffer;\n if (buffer.y > buffer.scrollBottom || buffer.y < buffer.scrollTop) {\n return;\n }\n const param = params.params[0] || 1;\n for (let y = buffer.scrollTop; y <= buffer.scrollBottom; ++y) {\n const line = buffer.lines.get(buffer.ybase + y);\n line.deleteCells(0, param, buffer.getNullCell(this._eraseAttrData()), this._eraseAttrData());\n line.isWrapped = false;\n }\n this._dirtyRowService.markRangeDirty(buffer.scrollTop, buffer.scrollBottom);\n }\n\n /**\n * CSI Ps SP A Scroll right Ps columns (default = 1) (SR) ECMA-48\n *\n * Notation: (Pn)\n * Representation: CSI Pn 02/00 04/01\n * Parameter default value: Pn = 1\n * SR causes the data in the presentation component to be moved by n character positions\n * if the line orientation is horizontal, or by n line positions if the line orientation\n * is vertical, such that the data appear to move to the right; where n equals the value of Pn.\n * The active presentation position is not affected by this control function.\n *\n * Supported:\n * - always right shift (no line orientation setting respected)\n *\n * @vt: #Y CSI SR \"Scroll Right\" \"CSI Ps SP A\" \"Scroll viewport `Ps` times to the right.\"\n * SL moves the content of all lines within the scroll margins `Ps` times to the right.\n * Content at the right margin is lost.\n * SL has no effect outside of the scroll margins.\n */\n public scrollRight(params: IParams): void {\n const buffer = this._bufferService.buffer;\n if (buffer.y > buffer.scrollBottom || buffer.y < buffer.scrollTop) {\n return;\n }\n const param = params.params[0] || 1;\n for (let y = buffer.scrollTop; y <= buffer.scrollBottom; ++y) {\n const line = buffer.lines.get(buffer.ybase + y);\n line.insertCells(0, param, buffer.getNullCell(this._eraseAttrData()), this._eraseAttrData());\n line.isWrapped = false;\n }\n this._dirtyRowService.markRangeDirty(buffer.scrollTop, buffer.scrollBottom);\n }\n\n /**\n * CSI Pm ' }\n * Insert Ps Column(s) (default = 1) (DECIC), VT420 and up.\n *\n * @vt: #Y CSI DECIC \"Insert Columns\" \"CSI Ps ' }\" \"Insert `Ps` columns at cursor position.\"\n * DECIC inserts `Ps` times blank columns at the cursor position for all lines with the scroll margins,\n * moving content to the right. Content at the right margin is lost.\n * DECIC has no effect outside the scrolling margins.\n */\n public insertColumns(params: IParams): void {\n const buffer = this._bufferService.buffer;\n if (buffer.y > buffer.scrollBottom || buffer.y < buffer.scrollTop) {\n return;\n }\n const param = params.params[0] || 1;\n for (let y = buffer.scrollTop; y <= buffer.scrollBottom; ++y) {\n const line = this._bufferService.buffer.lines.get(buffer.ybase + y);\n line.insertCells(buffer.x, param, buffer.getNullCell(this._eraseAttrData()), this._eraseAttrData());\n line.isWrapped = false;\n }\n this._dirtyRowService.markRangeDirty(buffer.scrollTop, buffer.scrollBottom);\n }\n\n /**\n * CSI Pm ' ~\n * Delete Ps Column(s) (default = 1) (DECDC), VT420 and up.\n *\n * @vt: #Y CSI DECDC \"Delete Columns\" \"CSI Ps ' ~\" \"Delete `Ps` columns at cursor position.\"\n * DECDC deletes `Ps` times columns at the cursor position for all lines with the scroll margins,\n * moving content to the left. Blank columns are added at the right margin.\n * DECDC has no effect outside the scrolling margins.\n */\n public deleteColumns(params: IParams): void {\n const buffer = this._bufferService.buffer;\n if (buffer.y > buffer.scrollBottom || buffer.y < buffer.scrollTop) {\n return;\n }\n const param = params.params[0] || 1;\n for (let y = buffer.scrollTop; y <= buffer.scrollBottom; ++y) {\n const line = buffer.lines.get(buffer.ybase + y);\n line.deleteCells(buffer.x, param, buffer.getNullCell(this._eraseAttrData()), this._eraseAttrData());\n line.isWrapped = false;\n }\n this._dirtyRowService.markRangeDirty(buffer.scrollTop, buffer.scrollBottom);\n }\n\n /**\n * CSI Ps X\n * Erase Ps Character(s) (default = 1) (ECH).\n *\n * @vt: #Y CSI ECH \"Erase Character\" \"CSI Ps X\" \"Erase `Ps` characters from current cursor position to the right (default=1).\"\n * ED erases `Ps` characters from current cursor position to the right.\n * ED works inside or outside the scrolling margins.\n */\n public eraseChars(params: IParams): void {\n this._restrictCursor();\n const line = this._bufferService.buffer.lines.get(this._bufferService.buffer.y + this._bufferService.buffer.ybase);\n if (line) {\n line.replaceCells(\n this._bufferService.buffer.x,\n this._bufferService.buffer.x + (params.params[0] || 1),\n this._bufferService.buffer.getNullCell(this._eraseAttrData()),\n this._eraseAttrData()\n );\n this._dirtyRowService.markDirty(this._bufferService.buffer.y);\n }\n }\n\n /**\n * CSI Ps b Repeat the preceding graphic character Ps times (REP).\n * From ECMA 48 (@see http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-048.pdf)\n * Notation: (Pn)\n * Representation: CSI Pn 06/02\n * Parameter default value: Pn = 1\n * REP is used to indicate that the preceding character in the data stream,\n * if it is a graphic character (represented by one or more bit combinations) including SPACE,\n * is to be repeated n times, where n equals the value of Pn.\n * If the character preceding REP is a control function or part of a control function,\n * the effect of REP is not defined by this Standard.\n *\n * Since we propagate the terminal as xterm-256color we have to follow xterm's behavior:\n * - fullwidth + surrogate chars are ignored\n * - for combining chars only the base char gets repeated\n * - text attrs are applied normally\n * - wrap around is respected\n * - any valid sequence resets the carried forward char\n *\n * Note: To get reset on a valid sequence working correctly without much runtime penalty,\n * the preceding codepoint is stored on the parser in `this.print` and reset during `parser.parse`.\n *\n * @vt: #Y CSI REP \"Repeat Preceding Character\" \"CSI Ps b\" \"Repeat preceding character `Ps` times (default=1).\"\n * REP repeats the previous character `Ps` times advancing the cursor, also wrapping if DECAWM is set.\n * REP has no effect if the sequence does not follow a printable ASCII character\n * (NOOP for any other sequence in between or NON ASCII characters).\n */\n public repeatPrecedingCharacter(params: IParams): void {\n if (!this._parser.precedingCodepoint) {\n return;\n }\n // call print to insert the chars and handle correct wrapping\n const length = params.params[0] || 1;\n const data = new Uint32Array(length);\n for (let i = 0; i < length; ++i) {\n data[i] = this._parser.precedingCodepoint;\n }\n this.print(data, 0, data.length);\n }\n\n /**\n * CSI Ps c Send Device Attributes (Primary DA).\n * Ps = 0 or omitted -> request attributes from terminal. The\n * response depends on the decTerminalID resource setting.\n * -> CSI ? 1 ; 2 c (``VT100 with Advanced Video Option'')\n * -> CSI ? 1 ; 0 c (``VT101 with No Options'')\n * -> CSI ? 6 c (``VT102'')\n * -> CSI ? 6 0 ; 1 ; 2 ; 6 ; 8 ; 9 ; 1 5 ; c (``VT220'')\n * The VT100-style response parameters do not mean anything by\n * themselves. VT220 parameters do, telling the host what fea-\n * tures the terminal supports:\n * Ps = 1 -> 132-columns.\n * Ps = 2 -> Printer.\n * Ps = 6 -> Selective erase.\n * Ps = 8 -> User-defined keys.\n * Ps = 9 -> National replacement character sets.\n * Ps = 1 5 -> Technical characters.\n * Ps = 2 2 -> ANSI color, e.g., VT525.\n * Ps = 2 9 -> ANSI text locator (i.e., DEC Locator mode).\n *\n * @vt: #Y CSI DA1 \"Primary Device Attributes\" \"CSI c\" \"Send primary device attributes.\"\n *\n *\n * TODO: fix and cleanup response\n */\n public sendDeviceAttributesPrimary(params: IParams): void {\n if (params.params[0] > 0) {\n return;\n }\n if (this._terminal.is('xterm') || this._terminal.is('rxvt-unicode') || this._terminal.is('screen')) {\n this._coreService.triggerDataEvent(C0.ESC + '[?1;2c');\n } else if (this._terminal.is('linux')) {\n this._coreService.triggerDataEvent(C0.ESC + '[?6c');\n }\n }\n\n /**\n * CSI > Ps c\n * Send Device Attributes (Secondary DA).\n * Ps = 0 or omitted -> request the terminal's identification\n * code. The response depends on the decTerminalID resource set-\n * ting. It should apply only to VT220 and up, but xterm extends\n * this to VT100.\n * -> CSI > Pp ; Pv ; Pc c\n * where Pp denotes the terminal type\n * Pp = 0 -> ``VT100''.\n * Pp = 1 -> ``VT220''.\n * and Pv is the firmware version (for xterm, this was originally\n * the XFree86 patch number, starting with 95). In a DEC termi-\n * nal, Pc indicates the ROM cartridge registration number and is\n * always zero.\n * More information:\n * xterm/charproc.c - line 2012, for more information.\n * vim responds with ^[[?0c or ^[[?1c after the terminal's response (?)\n *\n * @vt: #Y CSI DA2 \"Secondary Device Attributes\" \"CSI > c\" \"Send primary device attributes.\"\n *\n *\n * TODO: fix and cleanup response\n */\n public sendDeviceAttributesSecondary(params: IParams): void {\n if (params.params[0] > 0) {\n return;\n }\n // xterm and urxvt\n // seem to spit this\n // out around ~370 times (?).\n if (this._terminal.is('xterm')) {\n this._coreService.triggerDataEvent(C0.ESC + '[>0;276;0c');\n } else if (this._terminal.is('rxvt-unicode')) {\n this._coreService.triggerDataEvent(C0.ESC + '[>85;95;0c');\n } else if (this._terminal.is('linux')) {\n // not supported by linux console.\n // linux console echoes parameters.\n this._coreService.triggerDataEvent(params.params[0] + 'c');\n } else if (this._terminal.is('screen')) {\n this._coreService.triggerDataEvent(C0.ESC + '[>83;40003;0c');\n }\n }\n\n /**\n * CSI Pm h Set Mode (SM).\n * Ps = 2 -> Keyboard Action Mode (AM).\n * Ps = 4 -> Insert Mode (IRM).\n * Ps = 1 2 -> Send/receive (SRM).\n * Ps = 2 0 -> Automatic Newline (LNM).\n *\n * @vt: #P[Only IRM is supported.] CSI SM \"Set Mode\" \"CSI Pm h\" \"Set various terminal modes.\"\n * Supported param values by SM:\n *\n * | Param | Action | Support |\n * | ----- | -------------------------------------- | ------- |\n * | 2 | Keyboard Action Mode (KAM). Always on. | #N |\n * | 4 | Insert Mode (IRM). | #Y |\n * | 12 | Send/receive (SRM). Always off. | #N |\n * | 20 | Automatic Newline (LNM). Always off. | #N |\n *\n *\n * FIXME: why is LNM commented out?\n */\n public setMode(params: IParams): void {\n for (let i = 0; i < params.length; i++) {\n switch (params.params[i]) {\n case 4:\n this._terminal.insertMode = true;\n break;\n case 20:\n // this._t.convertEol = true;\n break;\n }\n }\n }\n\n /**\n * CSI ? Pm h\n * DEC Private Mode Set (DECSET).\n * Ps = 1 -> Application Cursor Keys (DECCKM).\n * Ps = 2 -> Designate USASCII for character sets G0-G3\n * (DECANM), and set VT100 mode.\n * Ps = 3 -> 132 Column Mode (DECCOLM).\n * Ps = 4 -> Smooth (Slow) Scroll (DECSCLM).\n * Ps = 5 -> Reverse Video (DECSCNM).\n * Ps = 6 -> Origin Mode (DECOM).\n * Ps = 7 -> Wraparound Mode (DECAWM).\n * Ps = 8 -> Auto-repeat Keys (DECARM).\n * Ps = 9 -> Send Mouse X & Y on button press. See the sec-\n * tion Mouse Tracking.\n * Ps = 1 0 -> Show toolbar (rxvt).\n * Ps = 1 2 -> Start Blinking Cursor (att610).\n * Ps = 1 8 -> Print form feed (DECPFF).\n * Ps = 1 9 -> Set print extent to full screen (DECPEX).\n * Ps = 2 5 -> Show Cursor (DECTCEM).\n * Ps = 3 0 -> Show scrollbar (rxvt).\n * Ps = 3 5 -> Enable font-shifting functions (rxvt).\n * Ps = 3 8 -> Enter Tektronix Mode (DECTEK).\n * Ps = 4 0 -> Allow 80 -> 132 Mode.\n * Ps = 4 1 -> more(1) fix (see curses resource).\n * Ps = 4 2 -> Enable Nation Replacement Character sets (DECN-\n * RCM).\n * Ps = 4 4 -> Turn On Margin Bell.\n * Ps = 4 5 -> Reverse-wraparound Mode.\n * Ps = 4 6 -> Start Logging. This is normally disabled by a\n * compile-time option.\n * Ps = 4 7 -> Use Alternate Screen Buffer. (This may be dis-\n * abled by the titeInhibit resource).\n * Ps = 6 6 -> Application keypad (DECNKM).\n * Ps = 6 7 -> Backarrow key sends backspace (DECBKM).\n * Ps = 1 0 0 0 -> Send Mouse X & Y on button press and\n * release. See the section Mouse Tracking.\n * Ps = 1 0 0 1 -> Use Hilite Mouse Tracking.\n * Ps = 1 0 0 2 -> Use Cell Motion Mouse Tracking.\n * Ps = 1 0 0 3 -> Use All Motion Mouse Tracking.\n * Ps = 1 0 0 4 -> Send FocusIn/FocusOut events.\n * Ps = 1 0 0 5 -> Enable Extended Mouse Mode.\n * Ps = 1 0 1 0 -> Scroll to bottom on tty output (rxvt).\n * Ps = 1 0 1 1 -> Scroll to bottom on key press (rxvt).\n * Ps = 1 0 3 4 -> Interpret \"meta\" key, sets eighth bit.\n * (enables the eightBitInput resource).\n * Ps = 1 0 3 5 -> Enable special modifiers for Alt and Num-\n * Lock keys. (This enables the numLock resource).\n * Ps = 1 0 3 6 -> Send ESC when Meta modifies a key. (This\n * enables the metaSendsEscape resource).\n * Ps = 1 0 3 7 -> Send DEL from the editing-keypad Delete\n * key.\n * Ps = 1 0 3 9 -> Send ESC when Alt modifies a key. (This\n * enables the altSendsEscape resource).\n * Ps = 1 0 4 0 -> Keep selection even if not highlighted.\n * (This enables the keepSelection resource).\n * Ps = 1 0 4 1 -> Use the CLIPBOARD selection. (This enables\n * the selectToClipboard resource).\n * Ps = 1 0 4 2 -> Enable Urgency window manager hint when\n * Control-G is received. (This enables the bellIsUrgent\n * resource).\n * Ps = 1 0 4 3 -> Enable raising of the window when Control-G\n * is received. (enables the popOnBell resource).\n * Ps = 1 0 4 7 -> Use Alternate Screen Buffer. (This may be\n * disabled by the titeInhibit resource).\n * Ps = 1 0 4 8 -> Save cursor as in DECSC. (This may be dis-\n * abled by the titeInhibit resource).\n * Ps = 1 0 4 9 -> Save cursor as in DECSC and use Alternate\n * Screen Buffer, clearing it first. (This may be disabled by\n * the titeInhibit resource). This combines the effects of the 1\n * 0 4 7 and 1 0 4 8 modes. Use this with terminfo-based\n * applications rather than the 4 7 mode.\n * Ps = 1 0 5 0 -> Set terminfo/termcap function-key mode.\n * Ps = 1 0 5 1 -> Set Sun function-key mode.\n * Ps = 1 0 5 2 -> Set HP function-key mode.\n * Ps = 1 0 5 3 -> Set SCO function-key mode.\n * Ps = 1 0 6 0 -> Set legacy keyboard emulation (X11R6).\n * Ps = 1 0 6 1 -> Set VT220 keyboard emulation.\n * Ps = 2 0 0 4 -> Set bracketed paste mode.\n * Modes:\n * http: *vt100.net/docs/vt220-rm/chapter4.html\n *\n * @vt: #P[See below for supported modes.] CSI DECSET \"DEC Private Set Mode\" \"CSI ? Pm h\" \"Set various terminal attributes.\"\n * Supported param values by DECSET:\n *\n * | param | Action | Support |\n * | ----- | ------------------------------------------------------- | --------|\n * | 1 | Application Cursor Keys (DECCKM). | #Y |\n * | 2 | Designate US-ASCII for character sets G0-G3 (DECANM). | #Y |\n * | 3 | 132 Column Mode (DECCOLM). | #Y |\n * | 6 | Origin Mode (DECOM). | #Y |\n * | 7 | Auto-wrap Mode (DECAWM). | #Y |\n * | 8 | Auto-repeat Keys (DECARM). Always on. | #N |\n * | 9 | X10 xterm mouse protocol. | #Y |\n * | 12 | Start Blinking Cursor. | #Y |\n * | 25 | Show Cursor (DECTCEM). | #Y |\n * | 47 | Use Alternate Screen Buffer. | #Y |\n * | 66 | Application keypad (DECNKM). | #Y |\n * | 1000 | X11 xterm mouse protocol. | #Y |\n * | 1002 | Use Cell Motion Mouse Tracking. | #Y |\n * | 1003 | Use All Motion Mouse Tracking. | #Y |\n * | 1004 | Send FocusIn/FocusOut events | #Y |\n * | 1005 | Enable UTF-8 Mouse Mode. | #N |\n * | 1006 | Enable SGR Mouse Mode. | #Y |\n * | 1015 | Enable urxvt Mouse Mode. | #N |\n * | 1047 | Use Alternate Screen Buffer. | #Y |\n * | 1048 | Save cursor as in DECSC. | #Y |\n * | 1049 | Save cursor and switch to alternate buffer clearing it. | #P[Does not clear the alternate buffer.] |\n * | 2004 | Set bracketed paste mode. | #Y |\n *\n *\n * FIXME: implement DECSCNM, 1049 should clear altbuffer\n */\n public setModePrivate(params: IParams): void {\n for (let i = 0; i < params.length; i++) {\n switch (params.params[i]) {\n case 1:\n this._coreService.decPrivateModes.applicationCursorKeys = true;\n break;\n case 2:\n this._charsetService.setgCharset(0, DEFAULT_CHARSET);\n this._charsetService.setgCharset(1, DEFAULT_CHARSET);\n this._charsetService.setgCharset(2, DEFAULT_CHARSET);\n this._charsetService.setgCharset(3, DEFAULT_CHARSET);\n // set VT100 mode here\n break;\n case 3:\n /**\n * DECCOLM - 132 column mode.\n * This is only active if 'SetWinLines' (24) is enabled\n * through `options.windowsOptions`.\n */\n if (this._optionsService.options.windowOptions.setWinLines) {\n this._terminal.resize(132, this._bufferService.rows);\n this._onRequestReset.fire();\n }\n break;\n case 6:\n this._coreService.decPrivateModes.origin = true;\n this._setCursor(0, 0);\n break;\n case 7:\n this._coreService.decPrivateModes.wraparound = true;\n break;\n case 12:\n // this.cursorBlink = true;\n break;\n case 66:\n this._logService.debug('Serial port requested application keypad.');\n this._coreService.decPrivateModes.applicationKeypad = true;\n this._terminal.viewport?.syncScrollArea();\n break;\n case 9: // X10 Mouse\n // no release, no motion, no wheel, no modifiers.\n this._coreMouseService.activeProtocol = 'X10';\n break;\n case 1000: // vt200 mouse\n // no motion.\n this._coreMouseService.activeProtocol = 'VT200';\n break;\n case 1002: // button event mouse\n this._coreMouseService.activeProtocol = 'DRAG';\n break;\n case 1003: // any event mouse\n // any event - sends motion events,\n // even if there is no button held down.\n this._coreMouseService.activeProtocol = 'ANY';\n break;\n case 1004: // send focusin/focusout events\n // focusin: ^[[I\n // focusout: ^[[O\n this._terminal.sendFocus = true;\n break;\n case 1005: // utf8 ext mode mouse - removed in #2507\n this._logService.debug('DECSET 1005 not supported (see #2507)');\n break;\n case 1006: // sgr ext mode mouse\n this._coreMouseService.activeEncoding = 'SGR';\n break;\n case 1015: // urxvt ext mode mouse - removed in #2507\n this._logService.debug('DECSET 1015 not supported (see #2507)');\n break;\n case 25: // show cursor\n this._coreService.isCursorHidden = false;\n break;\n case 1048: // alt screen cursor\n this.saveCursor();\n break;\n case 1049: // alt screen buffer cursor\n this.saveCursor();\n // FALL-THROUGH\n case 47: // alt screen buffer\n case 1047: // alt screen buffer\n this._bufferService.buffers.activateAltBuffer(this._eraseAttrData());\n this._onRequestRefreshRows.fire(0, this._bufferService.rows - 1);\n this._terminal.viewport?.syncScrollArea();\n this._terminal.showCursor();\n break;\n case 2004: // bracketed paste mode (https://cirw.in/blog/bracketed-paste)\n this._terminal.bracketedPasteMode = true;\n break;\n }\n }\n }\n\n\n /**\n * CSI Pm l Reset Mode (RM).\n * Ps = 2 -> Keyboard Action Mode (AM).\n * Ps = 4 -> Replace Mode (IRM).\n * Ps = 1 2 -> Send/receive (SRM).\n * Ps = 2 0 -> Normal Linefeed (LNM).\n *\n * @vt: #P[Only IRM is supported.] CSI RM \"Reset Mode\" \"CSI Pm l\" \"Set various terminal attributes.\"\n * Supported param values by RM:\n *\n * | Param | Action | Support |\n * | ----- | -------------------------------------- | ------- |\n * | 2 | Keyboard Action Mode (KAM). Always on. | #N |\n * | 4 | Replace Mode (IRM). (default) | #Y |\n * | 12 | Send/receive (SRM). Always off. | #N |\n * | 20 | Normal Linefeed (LNM). Always off. | #N |\n *\n *\n * FIXME: why is LNM commented out?\n */\n public resetMode(params: IParams): void {\n for (let i = 0; i < params.length; i++) {\n switch (params.params[i]) {\n case 4:\n this._terminal.insertMode = false;\n break;\n case 20:\n // this._t.convertEol = false;\n break;\n }\n }\n }\n\n /**\n * CSI ? Pm l\n * DEC Private Mode Reset (DECRST).\n * Ps = 1 -> Normal Cursor Keys (DECCKM).\n * Ps = 2 -> Designate VT52 mode (DECANM).\n * Ps = 3 -> 80 Column Mode (DECCOLM).\n * Ps = 4 -> Jump (Fast) Scroll (DECSCLM).\n * Ps = 5 -> Normal Video (DECSCNM).\n * Ps = 6 -> Normal Cursor Mode (DECOM).\n * Ps = 7 -> No Wraparound Mode (DECAWM).\n * Ps = 8 -> No Auto-repeat Keys (DECARM).\n * Ps = 9 -> Don't send Mouse X & Y on button press.\n * Ps = 1 0 -> Hide toolbar (rxvt).\n * Ps = 1 2 -> Stop Blinking Cursor (att610).\n * Ps = 1 8 -> Don't print form feed (DECPFF).\n * Ps = 1 9 -> Limit print to scrolling region (DECPEX).\n * Ps = 2 5 -> Hide Cursor (DECTCEM).\n * Ps = 3 0 -> Don't show scrollbar (rxvt).\n * Ps = 3 5 -> Disable font-shifting functions (rxvt).\n * Ps = 4 0 -> Disallow 80 -> 132 Mode.\n * Ps = 4 1 -> No more(1) fix (see curses resource).\n * Ps = 4 2 -> Disable Nation Replacement Character sets (DEC-\n * NRCM).\n * Ps = 4 4 -> Turn Off Margin Bell.\n * Ps = 4 5 -> No Reverse-wraparound Mode.\n * Ps = 4 6 -> Stop Logging. (This is normally disabled by a\n * compile-time option).\n * Ps = 4 7 -> Use Normal Screen Buffer.\n * Ps = 6 6 -> Numeric keypad (DECNKM).\n * Ps = 6 7 -> Backarrow key sends delete (DECBKM).\n * Ps = 1 0 0 0 -> Don't send Mouse X & Y on button press and\n * release. See the section Mouse Tracking.\n * Ps = 1 0 0 1 -> Don't use Hilite Mouse Tracking.\n * Ps = 1 0 0 2 -> Don't use Cell Motion Mouse Tracking.\n * Ps = 1 0 0 3 -> Don't use All Motion Mouse Tracking.\n * Ps = 1 0 0 4 -> Don't send FocusIn/FocusOut events.\n * Ps = 1 0 0 5 -> Disable Extended Mouse Mode.\n * Ps = 1 0 1 0 -> Don't scroll to bottom on tty output\n * (rxvt).\n * Ps = 1 0 1 1 -> Don't scroll to bottom on key press (rxvt).\n * Ps = 1 0 3 4 -> Don't interpret \"meta\" key. (This disables\n * the eightBitInput resource).\n * Ps = 1 0 3 5 -> Disable special modifiers for Alt and Num-\n * Lock keys. (This disables the numLock resource).\n * Ps = 1 0 3 6 -> Don't send ESC when Meta modifies a key.\n * (This disables the metaSendsEscape resource).\n * Ps = 1 0 3 7 -> Send VT220 Remove from the editing-keypad\n * Delete key.\n * Ps = 1 0 3 9 -> Don't send ESC when Alt modifies a key.\n * (This disables the altSendsEscape resource).\n * Ps = 1 0 4 0 -> Do not keep selection when not highlighted.\n * (This disables the keepSelection resource).\n * Ps = 1 0 4 1 -> Use the PRIMARY selection. (This disables\n * the selectToClipboard resource).\n * Ps = 1 0 4 2 -> Disable Urgency window manager hint when\n * Control-G is received. (This disables the bellIsUrgent\n * resource).\n * Ps = 1 0 4 3 -> Disable raising of the window when Control-\n * G is received. (This disables the popOnBell resource).\n * Ps = 1 0 4 7 -> Use Normal Screen Buffer, clearing screen\n * first if in the Alternate Screen. (This may be disabled by\n * the titeInhibit resource).\n * Ps = 1 0 4 8 -> Restore cursor as in DECRC. (This may be\n * disabled by the titeInhibit resource).\n * Ps = 1 0 4 9 -> Use Normal Screen Buffer and restore cursor\n * as in DECRC. (This may be disabled by the titeInhibit\n * resource). This combines the effects of the 1 0 4 7 and 1 0\n * 4 8 modes. Use this with terminfo-based applications rather\n * than the 4 7 mode.\n * Ps = 1 0 5 0 -> Reset terminfo/termcap function-key mode.\n * Ps = 1 0 5 1 -> Reset Sun function-key mode.\n * Ps = 1 0 5 2 -> Reset HP function-key mode.\n * Ps = 1 0 5 3 -> Reset SCO function-key mode.\n * Ps = 1 0 6 0 -> Reset legacy keyboard emulation (X11R6).\n * Ps = 1 0 6 1 -> Reset keyboard emulation to Sun/PC style.\n * Ps = 2 0 0 4 -> Reset bracketed paste mode.\n *\n * @vt: #P[See below for supported modes.] CSI DECRST \"DEC Private Reset Mode\" \"CSI ? Pm l\" \"Reset various terminal attributes.\"\n * Supported param values by DECRST:\n *\n * | param | Action | Support |\n * | ----- | ------------------------------------------------------- | ------- |\n * | 1 | Normal Cursor Keys (DECCKM). | #Y |\n * | 2 | Designate VT52 mode (DECANM). | #N |\n * | 3 | 80 Column Mode (DECCOLM). | #B[Switches to old column width instead of 80.] |\n * | 6 | Normal Cursor Mode (DECOM). | #Y |\n * | 7 | No Wraparound Mode (DECAWM). | #Y |\n * | 8 | No Auto-repeat Keys (DECARM). | #N |\n * | 9 | Don't send Mouse X & Y on button press. | #Y |\n * | 12 | Stop Blinking Cursor. | #Y |\n * | 25 | Hide Cursor (DECTCEM). | #Y |\n * | 47 | Use Normal Screen Buffer. | #Y |\n * | 66 | Numeric keypad (DECNKM). | #Y |\n * | 1000 | Don't send Mouse reports. | #Y |\n * | 1002 | Don't use Cell Motion Mouse Tracking. | #Y |\n * | 1003 | Don't use All Motion Mouse Tracking. | #Y |\n * | 1004 | Don't send FocusIn/FocusOut events. | #Y |\n * | 1005 | Disable UTF-8 Mouse Mode. | #N |\n * | 1006 | Disable SGR Mouse Mode. | #Y |\n * | 1015 | Disable urxvt Mouse Mode. | #N |\n * | 1047 | Use Normal Screen Buffer (clearing screen if in alt). | #Y |\n * | 1048 | Restore cursor as in DECRC. | #Y |\n * | 1049 | Use Normal Screen Buffer and restore cursor. | #Y |\n * | 2004 | Reset bracketed paste mode. | #Y |\n *\n *\n * FIXME: DECCOLM is currently broken (already fixed in window options PR)\n */\n public resetModePrivate(params: IParams): void {\n for (let i = 0; i < params.length; i++) {\n switch (params.params[i]) {\n case 1:\n this._coreService.decPrivateModes.applicationCursorKeys = false;\n break;\n case 3:\n /**\n * DECCOLM - 80 column mode.\n * This is only active if 'SetWinLines' (24) is enabled\n * through `options.windowsOptions`.\n */\n if (this._optionsService.options.windowOptions.setWinLines) {\n this._terminal.resize(80, this._bufferService.rows);\n this._onRequestReset.fire();\n }\n break;\n case 6:\n this._coreService.decPrivateModes.origin = false;\n this._setCursor(0, 0);\n break;\n case 7:\n this._coreService.decPrivateModes.wraparound = false;\n break;\n case 12:\n // this.cursorBlink = false;\n break;\n case 66:\n this._logService.debug('Switching back to normal keypad.');\n this._coreService.decPrivateModes.applicationKeypad = false;\n this._terminal.viewport?.syncScrollArea();\n break;\n case 9: // X10 Mouse\n case 1000: // vt200 mouse\n case 1002: // button event mouse\n case 1003: // any event mouse\n this._coreMouseService.activeProtocol = 'NONE';\n break;\n case 1004: // send focusin/focusout events\n this._terminal.sendFocus = false;\n break;\n case 1005: // utf8 ext mode mouse - removed in #2507\n this._logService.debug('DECRST 1005 not supported (see #2507)');\n break;\n case 1006: // sgr ext mode mouse\n this._coreMouseService.activeEncoding = 'DEFAULT';\n break;\n case 1015: // urxvt ext mode mouse - removed in #2507\n this._logService.debug('DECRST 1015 not supported (see #2507)');\n break;\n case 25: // hide cursor\n this._coreService.isCursorHidden = true;\n break;\n case 1048: // alt screen cursor\n this.restoreCursor();\n break;\n case 1049: // alt screen buffer cursor\n // FALL-THROUGH\n case 47: // normal screen buffer\n case 1047: // normal screen buffer - clearing it first\n // Ensure the selection manager has the correct buffer\n this._bufferService.buffers.activateNormalBuffer();\n if (params.params[i] === 1049) {\n this.restoreCursor();\n }\n this._onRequestRefreshRows.fire(0, this._bufferService.rows - 1);\n this._terminal.viewport?.syncScrollArea();\n this._terminal.showCursor();\n break;\n case 2004: // bracketed paste mode (https://cirw.in/blog/bracketed-paste)\n this._terminal.bracketedPasteMode = false;\n break;\n }\n }\n }\n\n /**\n * Helper to extract and apply color params/subparams.\n * Returns advance for params index.\n */\n private _extractColor(params: IParams, pos: number, attr: IAttributeData): number {\n // normalize params\n // meaning: [target, CM, ign, val, val, val]\n // RGB : [ 38/48, 2, ign, r, g, b]\n // P256 : [ 38/48, 5, ign, v, ign, ign]\n const accu = [0, 0, -1, 0, 0, 0];\n\n // alignment placeholder for non color space sequences\n let cSpace = 0;\n\n // return advance we took in params\n let advance = 0;\n\n do {\n accu[advance + cSpace] = params.params[pos + advance];\n if (params.hasSubParams(pos + advance)) {\n const subparams = params.getSubParams(pos + advance);\n let i = 0;\n do {\n if (accu[1] === 5) {\n cSpace = 1;\n }\n accu[advance + i + 1 + cSpace] = subparams[i];\n } while (++i < subparams.length && i + advance + 1 + cSpace < accu.length);\n break;\n }\n // exit early if can decide color mode with semicolons\n if ((accu[1] === 5 && advance + cSpace >= 2)\n || (accu[1] === 2 && advance + cSpace >= 5)) {\n break;\n }\n // offset colorSpace slot for semicolon mode\n if (accu[1]) {\n cSpace = 1;\n }\n } while (++advance + pos < params.length && advance + cSpace < accu.length);\n\n // set default values to 0\n for (let i = 2; i < accu.length; ++i) {\n if (accu[i] === -1) {\n accu[i] = 0;\n }\n }\n\n // apply colors\n if (accu[0] === 38) {\n if (accu[1] === 2) {\n attr.fg |= Attributes.CM_RGB;\n attr.fg &= ~Attributes.RGB_MASK;\n attr.fg |= AttributeData.fromColorRGB([accu[3], accu[4], accu[5]]);\n } else if (accu[1] === 5) {\n attr.fg &= ~(Attributes.CM_MASK | Attributes.PCOLOR_MASK);\n attr.fg |= Attributes.CM_P256 | (accu[3] & 0xff);\n }\n } else if (accu[0] === 48) {\n if (accu[1] === 2) {\n attr.bg |= Attributes.CM_RGB;\n attr.bg &= ~Attributes.RGB_MASK;\n attr.bg |= AttributeData.fromColorRGB([accu[3], accu[4], accu[5]]);\n } else if (accu[1] === 5) {\n attr.bg &= ~(Attributes.CM_MASK | Attributes.PCOLOR_MASK);\n attr.bg |= Attributes.CM_P256 | (accu[3] & 0xff);\n }\n }\n\n return advance;\n }\n\n /**\n * CSI Pm m Character Attributes (SGR).\n *\n * @vt: #P[See below for supported attributes.] CSI SGR \"Select Graphic Rendition\" \"CSI Pm m\" \"Set/Reset various text attributes.\"\n * SGR selects one or more character attributes at the same time. Multiple params (up to 32)\n * are applied from in order from left to right. The changed attributes are applied to all new\n * characters received. If you move characters in the viewport by scrolling or any other means,\n * then the attributes move with the characters.\n *\n * Supported param values by SGR:\n *\n * | Param | Meaning | Support |\n * | --------- | -------------------------------------------------------- | ------- |\n * | 0 | Normal (default). Resets any other preceding SGR. | #Y |\n * | 1 | Bold. (also see `options.drawBoldTextInBrightColors`) | #Y |\n * | 2 | Faint, decreased intensity. | #Y |\n * | 3 | Italic. | #Y |\n * | 4 | Underlined. (no support for newer underline styles) | #Y |\n * | 5 | Slowly blinking. | #N |\n * | 6 | Rapidly blinking. | #N |\n * | 7 | Inverse. Flips foreground and background color. | #Y |\n * | 8 | Invisible (hidden). | #Y |\n * | 9 | Crossed-out characters. | #N |\n * | 21 | Doubly underlined. | #N |\n * | 22 | Normal (neither bold nor faint). | #Y |\n * | 23 | No italic. | #Y |\n * | 24 | Not underlined. | #Y |\n * | 25 | Steady (not blinking). | #Y |\n * | 27 | Positive (not inverse). | #Y |\n * | 28 | Visible (not hidden). | #Y |\n * | 29 | Not Crossed-out. | #N |\n * | 30 | Foreground color: Black. | #Y |\n * | 31 | Foreground color: Red. | #Y |\n * | 32 | Foreground color: Green. | #Y |\n * | 33 | Foreground color: Yellow. | #Y |\n * | 34 | Foreground color: Blue. | #Y |\n * | 35 | Foreground color: Magenta. | #Y |\n * | 36 | Foreground color: Cyan. | #Y |\n * | 37 | Foreground color: White. | #Y |\n * | 38 | Foreground color: Extended color. | #P[Support for RGB and indexed colors, see below.] |\n * | 39 | Foreground color: Default (original). | #Y |\n * | 40 | Background color: Black. | #Y |\n * | 41 | Background color: Red. | #Y |\n * | 42 | Background color: Green. | #Y |\n * | 43 | Background color: Yellow. | #Y |\n * | 44 | Background color: Blue. | #Y |\n * | 45 | Background color: Magenta. | #Y |\n * | 46 | Background color: Cyan. | #Y |\n * | 47 | Background color: White. | #Y |\n * | 48 | Background color: Extended color. | #P[Support for RGB and indexed colors, see below.] |\n * | 49 | Background color: Default (original). | #Y |\n * | 90 - 97 | Bright foreground color (analogous to 30 - 37). | #Y |\n * | 100 - 107 | Bright background color (analogous to 40 - 47). | #Y |\n *\n * Extended colors are supported for foreground (Ps=38) and background (Ps=48) as follows:\n *\n * | Ps + 1 | Meaning | Support |\n * | ------ | ------------------------------------------------------------- | ------- |\n * | 0 | Implementation defined. | #N |\n * | 1 | Transparent. | #N |\n * | 2 | RGB color as `Ps ; 2 ; R ; G ; B` or `Ps : 2 : : R : G : B`. | #Y |\n * | 3 | CMY color. | #N |\n * | 4 | CMYK color. | #N |\n * | 5 | Indexed (256 colors) as `Ps ; 5 ; INDEX` or `Ps : 5 : INDEX`. | #Y |\n *\n *\n * FIXME: blinking is implemented in attrs, but not working in renderers?\n * FIXME: remove dead branch for p=100\n */\n public charAttributes(params: IParams): void {\n // Optimize a single SGR0.\n if (params.length === 1 && params.params[0] === 0) {\n this._curAttrData.fg = DEFAULT_ATTR_DATA.fg;\n this._curAttrData.bg = DEFAULT_ATTR_DATA.bg;\n return;\n }\n\n const l = params.length;\n let p;\n const attr = this._curAttrData;\n\n for (let i = 0; i < l; i++) {\n p = params.params[i];\n if (p >= 30 && p <= 37) {\n // fg color 8\n attr.fg &= ~(Attributes.CM_MASK | Attributes.PCOLOR_MASK);\n attr.fg |= Attributes.CM_P16 | (p - 30);\n } else if (p >= 40 && p <= 47) {\n // bg color 8\n attr.bg &= ~(Attributes.CM_MASK | Attributes.PCOLOR_MASK);\n attr.bg |= Attributes.CM_P16 | (p - 40);\n } else if (p >= 90 && p <= 97) {\n // fg color 16\n attr.fg &= ~(Attributes.CM_MASK | Attributes.PCOLOR_MASK);\n attr.fg |= Attributes.CM_P16 | (p - 90) | 8;\n } else if (p >= 100 && p <= 107) {\n // bg color 16\n attr.bg &= ~(Attributes.CM_MASK | Attributes.PCOLOR_MASK);\n attr.bg |= Attributes.CM_P16 | (p - 100) | 8;\n } else if (p === 0) {\n // default\n attr.fg = DEFAULT_ATTR_DATA.fg;\n attr.bg = DEFAULT_ATTR_DATA.bg;\n } else if (p === 1) {\n // bold text\n attr.fg |= FgFlags.BOLD;\n } else if (p === 3) {\n // italic text\n attr.bg |= BgFlags.ITALIC;\n } else if (p === 4) {\n // underlined text\n attr.fg |= FgFlags.UNDERLINE;\n } else if (p === 5) {\n // blink\n attr.fg |= FgFlags.BLINK;\n } else if (p === 7) {\n // inverse and positive\n // test with: echo -e '\\e[31m\\e[42mhello\\e[7mworld\\e[27mhi\\e[m'\n attr.fg |= FgFlags.INVERSE;\n } else if (p === 8) {\n // invisible\n attr.fg |= FgFlags.INVISIBLE;\n } else if (p === 2) {\n // dimmed text\n attr.bg |= BgFlags.DIM;\n } else if (p === 22) {\n // not bold nor faint\n attr.fg &= ~FgFlags.BOLD;\n attr.bg &= ~BgFlags.DIM;\n } else if (p === 23) {\n // not italic\n attr.bg &= ~BgFlags.ITALIC;\n } else if (p === 24) {\n // not underlined\n attr.fg &= ~FgFlags.UNDERLINE;\n } else if (p === 25) {\n // not blink\n attr.fg &= ~FgFlags.BLINK;\n } else if (p === 27) {\n // not inverse\n attr.fg &= ~FgFlags.INVERSE;\n } else if (p === 28) {\n // not invisible\n attr.fg &= ~FgFlags.INVISIBLE;\n } else if (p === 39) {\n // reset fg\n attr.fg &= ~(Attributes.CM_MASK | Attributes.RGB_MASK);\n attr.fg |= DEFAULT_ATTR_DATA.fg & (Attributes.PCOLOR_MASK | Attributes.RGB_MASK);\n } else if (p === 49) {\n // reset bg\n attr.bg &= ~(Attributes.CM_MASK | Attributes.RGB_MASK);\n attr.bg |= DEFAULT_ATTR_DATA.bg & (Attributes.PCOLOR_MASK | Attributes.RGB_MASK);\n } else if (p === 38 || p === 48) {\n // fg color 256 and RGB\n i += this._extractColor(params, i, attr);\n } else if (p === 100) { // FIXME: dead branch, p=100 already handled above!\n // reset fg/bg\n attr.fg &= ~(Attributes.CM_MASK | Attributes.RGB_MASK);\n attr.fg |= DEFAULT_ATTR_DATA.fg & (Attributes.PCOLOR_MASK | Attributes.RGB_MASK);\n attr.bg &= ~(Attributes.CM_MASK | Attributes.RGB_MASK);\n attr.bg |= DEFAULT_ATTR_DATA.bg & (Attributes.PCOLOR_MASK | Attributes.RGB_MASK);\n } else {\n this._logService.debug('Unknown SGR attribute: %d.', p);\n }\n }\n }\n\n /**\n * CSI Ps n Device Status Report (DSR).\n * Ps = 5 -> Status Report. Result (``OK'') is\n * CSI 0 n\n * Ps = 6 -> Report Cursor Position (CPR) [row;column].\n * Result is\n * CSI r ; c R\n * CSI ? Ps n\n * Device Status Report (DSR, DEC-specific).\n * Ps = 6 -> Report Cursor Position (CPR) [row;column] as CSI\n * ? r ; c R (assumes page is zero).\n * Ps = 1 5 -> Report Printer status as CSI ? 1 0 n (ready).\n * or CSI ? 1 1 n (not ready).\n * Ps = 2 5 -> Report UDK status as CSI ? 2 0 n (unlocked)\n * or CSI ? 2 1 n (locked).\n * Ps = 2 6 -> Report Keyboard status as\n * CSI ? 2 7 ; 1 ; 0 ; 0 n (North American).\n * The last two parameters apply to VT400 & up, and denote key-\n * board ready and LK01 respectively.\n * Ps = 5 3 -> Report Locator status as\n * CSI ? 5 3 n Locator available, if compiled-in, or\n * CSI ? 5 0 n No Locator, if not.\n *\n * @vt: #Y CSI DSR \"Device Status Report\" \"CSI Ps n\" \"Request cursor position (CPR) with `Ps` = 6.\"\n */\n public deviceStatus(params: IParams): void {\n switch (params.params[0]) {\n case 5:\n // status report\n this._coreService.triggerDataEvent(`${C0.ESC}[0n`);\n break;\n case 6:\n // cursor position\n const y = this._bufferService.buffer.y + 1;\n const x = this._bufferService.buffer.x + 1;\n this._coreService.triggerDataEvent(`${C0.ESC}[${y};${x}R`);\n break;\n }\n }\n\n // @vt: #P[Only CPR is supported.] CSI DECDSR \"DEC Device Status Report\" \"CSI ? Ps n\" \"Only CPR is supported (same as DSR).\"\n public deviceStatusPrivate(params: IParams): void {\n // modern xterm doesnt seem to\n // respond to any of these except ?6, 6, and 5\n switch (params.params[0]) {\n case 6:\n // cursor position\n const y = this._bufferService.buffer.y + 1;\n const x = this._bufferService.buffer.x + 1;\n this._coreService.triggerDataEvent(`${C0.ESC}[?${y};${x}R`);\n break;\n case 15:\n // no printer\n // this.handler(C0.ESC + '[?11n');\n break;\n case 25:\n // dont support user defined keys\n // this.handler(C0.ESC + '[?21n');\n break;\n case 26:\n // north american keyboard\n // this.handler(C0.ESC + '[?27;1;0;0n');\n break;\n case 53:\n // no dec locator/mouse\n // this.handler(C0.ESC + '[?50n');\n break;\n }\n }\n\n /**\n * CSI ! p Soft terminal reset (DECSTR).\n * http://vt100.net/docs/vt220-rm/table4-10.html\n *\n * @vt: #Y CSI DECSTR \"Soft Terminal Reset\" \"CSI ! p\" \"Reset several terminal attributes to initial state.\"\n * There are two terminal reset sequences - RIS and DECSTR. While RIS performs almost a full terminal bootstrap,\n * DECSTR only resets certain attributes. For most needs DECSTR should be sufficient.\n *\n * The following terminal attributes are reset to default values:\n * - cursor is reset (default = visible, home position)\n * - IRM is reset (dafault = false)\n * - scroll margins are reset (default = viewport size)\n * - erase attributes are reset to default\n * - charsets are reset\n *\n *\n * FIXME: there are several more attributes missing (see VT520 manual)\n */\n public softReset(params: IParams): void {\n this._coreService.isCursorHidden = false;\n this._terminal.insertMode = false;\n this._terminal.viewport?.syncScrollArea();\n this._bufferService.buffer.scrollTop = 0;\n this._bufferService.buffer.scrollBottom = this._bufferService.rows - 1;\n this._curAttrData = DEFAULT_ATTR_DATA.clone();\n this._bufferService.buffer.x = this._bufferService.buffer.y = 0; // ?\n this._coreService.reset();\n this._charsetService.reset();\n }\n\n /**\n * CSI Ps SP q Set cursor style (DECSCUSR, VT520).\n * Ps = 0 -> blinking block.\n * Ps = 1 -> blinking block (default).\n * Ps = 2 -> steady block.\n * Ps = 3 -> blinking underline.\n * Ps = 4 -> steady underline.\n * Ps = 5 -> blinking bar (xterm).\n * Ps = 6 -> steady bar (xterm).\n *\n * @vt: #Y CSI DECSCUSR \"Set Cursor Style\" \"CSI Ps SP q\" \"Set cursor style.\"\n * Supported cursor styles:\n * - empty, 0 or 1: steady block\n * - 2: blink block\n * - 3: steady underline\n * - 4: blink underline\n * - 5: steady bar\n * - 6: blink bar\n */\n public setCursorStyle(params: IParams): void {\n const param = params.params[0] || 1;\n switch (param) {\n case 1:\n case 2:\n this._optionsService.options.cursorStyle = 'block';\n break;\n case 3:\n case 4:\n this._optionsService.options.cursorStyle = 'underline';\n break;\n case 5:\n case 6:\n this._optionsService.options.cursorStyle = 'bar';\n break;\n }\n const isBlinking = param % 2 === 1;\n this._optionsService.options.cursorBlink = isBlinking;\n }\n\n /**\n * CSI Ps ; Ps r\n * Set Scrolling Region [top;bottom] (default = full size of win-\n * dow) (DECSTBM).\n *\n * @vt: #Y CSI DECSTBM \"Set Top and Bottom Margin\" \"CSI Ps ; Ps r\" \"Set top and bottom margins of the viewport [top;bottom] (default = viewport size).\"\n */\n public setScrollRegion(params: IParams): void {\n const top = params.params[0] || 1;\n let bottom: number;\n\n if (params.length < 2 || (bottom = params.params[1]) > this._bufferService.rows || bottom === 0) {\n bottom = this._bufferService.rows;\n }\n\n if (bottom > top) {\n this._bufferService.buffer.scrollTop = top - 1;\n this._bufferService.buffer.scrollBottom = bottom - 1;\n this._setCursor(0, 0);\n }\n }\n\n /**\n * CSI Ps ; Ps ; Ps t - Various window manipulations and reports (xterm)\n *\n * Note: Only those listed below are supported. All others are left to integrators and\n * need special treatment based on the embedding environment.\n *\n * Ps = 1 4 supported\n * Report xterm text area size in pixels.\n * Result is CSI 4 ; height ; width t\n * Ps = 14 ; 2 not implemented\n * Ps = 16 supported\n * Report xterm character cell size in pixels.\n * Result is CSI 6 ; height ; width t\n * Ps = 18 supported\n * Report the size of the text area in characters.\n * Result is CSI 8 ; height ; width t\n * Ps = 20 supported\n * Report xterm window's icon label.\n * Result is OSC L label ST\n * Ps = 21 supported\n * Report xterm window's title.\n * Result is OSC l label ST\n * Ps = 22 ; 0 -> Save xterm icon and window title on stack. supported\n * Ps = 22 ; 1 -> Save xterm icon title on stack. supported\n * Ps = 22 ; 2 -> Save xterm window title on stack. supported\n * Ps = 23 ; 0 -> Restore xterm icon and window title from stack. supported\n * Ps = 23 ; 1 -> Restore xterm icon title from stack. supported\n * Ps = 23 ; 2 -> Restore xterm window title from stack. supported\n * Ps >= 24 not implemented\n */\n public windowOptions(params: IParams): void {\n if (!paramToWindowOption(params.params[0], this._optionsService.options.windowOptions)) {\n return;\n }\n const second = (params.length > 1) ? params.params[1] : 0;\n const rs = this._instantiationService.getService(IRenderService);\n switch (params.params[0]) {\n case 14: // GetWinSizePixels, returns CSI 4 ; height ; width t\n if (rs && second !== 2) {\n console.log(rs.dimensions);\n const w = rs.dimensions.scaledCanvasWidth.toFixed(0);\n const h = rs.dimensions.scaledCanvasHeight.toFixed(0);\n this._coreService.triggerDataEvent(`${C0.ESC}[4;${h};${w}t`);\n }\n break;\n case 16: // GetCellSizePixels, returns CSI 6 ; height ; width t\n if (rs) {\n const w = rs.dimensions.scaledCellWidth.toFixed(0);\n const h = rs.dimensions.scaledCellHeight.toFixed(0);\n this._coreService.triggerDataEvent(`${C0.ESC}[6;${h};${w}t`);\n }\n break;\n case 18: // GetWinSizeChars, returns CSI 8 ; height ; width t\n if (this._bufferService) {\n this._coreService.triggerDataEvent(`${C0.ESC}[8;${this._bufferService.rows};${this._bufferService.cols}t`);\n }\n break;\n case 22: // PushTitle\n if (second === 0 || second === 2) {\n this._windowTitleStack.push(this._windowTitle);\n if (this._windowTitleStack.length > STACK_LIMIT) {\n this._windowTitleStack.shift();\n }\n }\n if (second === 0 || second === 1) {\n this._iconNameStack.push(this._iconName);\n if (this._iconNameStack.length > STACK_LIMIT) {\n this._iconNameStack.shift();\n }\n }\n break;\n case 23: // PopTitle\n if (second === 0 || second === 2) {\n if (this._windowTitleStack.length) {\n this.setTitle(this._windowTitleStack.pop());\n }\n }\n if (second === 0 || second === 1) {\n if (this._iconNameStack.length) {\n this.setIconName(this._iconNameStack.pop());\n }\n }\n break;\n }\n }\n\n\n /**\n * CSI s\n * ESC 7\n * Save cursor (ANSI.SYS).\n *\n * @vt: #P[TODO...] CSI SCOSC \"Save Cursor\" \"CSI s\" \"Save cursor position, charmap and text attributes.\"\n * @vt: #Y ESC SC \"Save Cursor\" \"ESC 7\" \"Save cursor position, charmap and text attributes.\"\n */\n public saveCursor(params?: IParams): void {\n this._bufferService.buffer.savedX = this._bufferService.buffer.x;\n this._bufferService.buffer.savedY = this._bufferService.buffer.ybase + this._bufferService.buffer.y;\n this._bufferService.buffer.savedCurAttrData.fg = this._curAttrData.fg;\n this._bufferService.buffer.savedCurAttrData.bg = this._curAttrData.bg;\n this._bufferService.buffer.savedCharset = this._charsetService.charset;\n }\n\n\n /**\n * CSI u\n * ESC 8\n * Restore cursor (ANSI.SYS).\n *\n * @vt: #P[TODO...] CSI SCORC \"Restore Cursor\" \"CSI u\" \"Restore cursor position, charmap and text attributes.\"\n * @vt: #Y ESC RC \"Restore Cursor\" \"ESC 8\" \"Restore cursor position, charmap and text attributes.\"\n */\n public restoreCursor(params?: IParams): void {\n this._bufferService.buffer.x = this._bufferService.buffer.savedX || 0;\n this._bufferService.buffer.y = Math.max(this._bufferService.buffer.savedY - this._bufferService.buffer.ybase, 0);\n this._curAttrData.fg = this._bufferService.buffer.savedCurAttrData.fg;\n this._curAttrData.bg = this._bufferService.buffer.savedCurAttrData.bg;\n this._charsetService.charset = (this as any)._savedCharset;\n if (this._bufferService.buffer.savedCharset) {\n this._charsetService.charset = this._bufferService.buffer.savedCharset;\n }\n this._restrictCursor();\n }\n\n\n /**\n * OSC 2; ST (set window title)\n * Proxy to set window title.\n *\n * @vt: #P[Icon name is not exposed.] OSC 0 \"Set Windows Title and Icon Name\" \"OSC 0 ; Pt BEL\" \"Set window title and icon name.\"\n * Icon name is not supported. For Window Title see below.\n *\n * @vt: #Y OSC 2 \"Set Windows Title\" \"OSC 2 ; Pt BEL\" \"Set window title.\"\n * xterm.js does not manipulate the title directly, instead exposes changes via the event `Terminal.onTitleChange`.\n */\n public setTitle(data: string): void {\n this._windowTitle = data;\n this._terminal.handleTitle(data);\n }\n\n /**\n * OSC 1; ST\n * Note: Icon name is not exposed.\n */\n public setIconName(data: string): void {\n this._iconName = data;\n }\n\n /**\n * ESC E\n * C1.NEL\n * DEC mnemonic: NEL (https://vt100.net/docs/vt510-rm/NEL)\n * Moves cursor to first position on next line.\n *\n * @vt: #Y C1 NEL \"Next Line\" \"\\x85\" \"Move the cursor to the beginning of the next row.\"\n * @vt: #Y ESC NEL \"Next Line\" \"ESC E\" \"Move the cursor to the beginning of the next row.\"\n */\n public nextLine(): void {\n this._bufferService.buffer.x = 0;\n this.index();\n }\n\n /**\n * ESC =\n * DEC mnemonic: DECKPAM (https://vt100.net/docs/vt510-rm/DECKPAM.html)\n * Enables the numeric keypad to send application sequences to the host.\n */\n public keypadApplicationMode(): void {\n this._logService.debug('Serial port requested application keypad.');\n this._coreService.decPrivateModes.applicationKeypad = true;\n this._terminal.viewport?.syncScrollArea();\n }\n\n /**\n * ESC >\n * DEC mnemonic: DECKPNM (https://vt100.net/docs/vt510-rm/DECKPNM.html)\n * Enables the keypad to send numeric characters to the host.\n */\n public keypadNumericMode(): void {\n this._logService.debug('Switching back to normal keypad.');\n this._coreService.decPrivateModes.applicationKeypad = false;\n this._terminal.viewport?.syncScrollArea();\n }\n\n /**\n * ESC % @\n * ESC % G\n * Select default character set. UTF-8 is not supported (string are unicode anyways)\n * therefore ESC % G does the same.\n */\n public selectDefaultCharset(): void {\n this._charsetService.setgLevel(0);\n this._charsetService.setgCharset(0, DEFAULT_CHARSET); // US (default)\n }\n\n /**\n * ESC ( C\n * Designate G0 Character Set, VT100, ISO 2022.\n * ESC ) C\n * Designate G1 Character Set (ISO 2022, VT100).\n * ESC * C\n * Designate G2 Character Set (ISO 2022, VT220).\n * ESC + C\n * Designate G3 Character Set (ISO 2022, VT220).\n * ESC - C\n * Designate G1 Character Set (VT300).\n * ESC . C\n * Designate G2 Character Set (VT300).\n * ESC / C\n * Designate G3 Character Set (VT300). C = A -> ISO Latin-1 Supplemental. - Supported?\n */\n public selectCharset(collectAndFlag: string): void {\n if (collectAndFlag.length !== 2) {\n this.selectDefaultCharset();\n return;\n }\n if (collectAndFlag[0] === '/') {\n return; // TODO: Is this supported?\n }\n this._charsetService.setgCharset(GLEVEL[collectAndFlag[0]], CHARSETS[collectAndFlag[1]] || DEFAULT_CHARSET);\n return;\n }\n\n /**\n * ESC D\n * C1.IND\n * DEC mnemonic: IND (https://vt100.net/docs/vt510-rm/IND.html)\n * Moves the cursor down one line in the same column.\n *\n * @vt: #Y C1 IND \"Index\" \"\\x84\" \"Move the cursor one line down scrolling if needed.\"\n * @vt: #Y ESC IND \"Index\" \"ESC D\" \"Move the cursor one line down scrolling if needed.\"\n */\n public index(): void {\n this._restrictCursor();\n const buffer = this._bufferService.buffer;\n this._bufferService.buffer.y++;\n if (buffer.y === buffer.scrollBottom + 1) {\n buffer.y--;\n this._terminal.scroll(this._eraseAttrData());\n } else if (buffer.y >= this._bufferService.rows) {\n buffer.y = this._bufferService.rows - 1;\n }\n this._restrictCursor();\n }\n\n /**\n * ESC H\n * C1.HTS\n * DEC mnemonic: HTS (https://vt100.net/docs/vt510-rm/HTS.html)\n * Sets a horizontal tab stop at the column position indicated by\n * the value of the active column when the terminal receives an HTS.\n *\n * @vt: #Y C1 HTS \"Horizontal Tabulation Set\" \"\\x88\" \"Places a tab stop at the current cursor position.\"\n * @vt: #Y ESC HTS \"Horizontal Tabulation Set\" \"ESC H\" \"Places a tab stop at the current cursor position.\"\n */\n public tabSet(): void {\n this._bufferService.buffer.tabs[this._bufferService.buffer.x] = true;\n }\n\n /**\n * ESC M\n * C1.RI\n * DEC mnemonic: HTS\n * Moves the cursor up one line in the same column. If the cursor is at the top margin,\n * the page scrolls down.\n *\n * @vt: #Y ESC IR \"Reverse Index\" \"ESC M\" \"Move the cursor one line up scrolling if needed.\"\n */\n public reverseIndex(): void {\n this._restrictCursor();\n const buffer = this._bufferService.buffer;\n if (buffer.y === buffer.scrollTop) {\n // possibly move the code below to term.reverseScroll();\n // test: echo -ne '\\e[1;1H\\e[44m\\eM\\e[0m'\n // blankLine(true) is xterm/linux behavior\n const scrollRegionHeight = buffer.scrollBottom - buffer.scrollTop;\n buffer.lines.shiftElements(buffer.y + buffer.ybase, scrollRegionHeight, 1);\n buffer.lines.set(buffer.y + buffer.ybase, buffer.getBlankLine(this._eraseAttrData()));\n this._dirtyRowService.markRangeDirty(buffer.scrollTop, buffer.scrollBottom);\n } else {\n buffer.y--;\n this._restrictCursor(); // quickfix to not run out of bounds\n }\n }\n\n /**\n * ESC c\n * DEC mnemonic: RIS (https://vt100.net/docs/vt510-rm/RIS.html)\n * Reset to initial state.\n */\n public fullReset(): void {\n this._parser.reset();\n this._onRequestReset.fire();\n }\n\n public reset(): void {\n this._curAttrData = DEFAULT_ATTR_DATA.clone();\n this._eraseAttrDataInternal = DEFAULT_ATTR_DATA.clone();\n }\n\n /**\n * back_color_erase feature for xterm.\n */\n private _eraseAttrData(): IAttributeData {\n this._eraseAttrDataInternal.bg &= ~(Attributes.CM_MASK | 0xFFFFFF);\n this._eraseAttrDataInternal.bg |= this._curAttrData.bg & ~0xFC000000;\n return this._eraseAttrDataInternal;\n }\n\n /**\n * ESC n\n * ESC o\n * ESC |\n * ESC }\n * ESC ~\n * DEC mnemonic: LS (https://vt100.net/docs/vt510-rm/LS.html)\n * When you use a locking shift, the character set remains in GL or GR until\n * you use another locking shift. (partly supported)\n */\n public setgLevel(level: number): void {\n this._charsetService.setgLevel(level);\n }\n\n /**\n * ESC # 8\n * DEC mnemonic: DECALN (https://vt100.net/docs/vt510-rm/DECALN.html)\n * This control function fills the complete screen area with\n * a test pattern (E) used for adjusting screen alignment.\n *\n * @vt: #Y ESC DECALN \"Screen Alignment Pattern\" \"ESC # 8\" \"Fill viewport with a test pattern (E).\"\n */\n public screenAlignmentPattern(): void {\n // prepare cell data\n const cell = new CellData();\n cell.content = 1 << Content.WIDTH_SHIFT | 'E'.charCodeAt(0);\n cell.fg = this._curAttrData.fg;\n cell.bg = this._curAttrData.bg;\n\n const buffer = this._bufferService.buffer;\n\n this._setCursor(0, 0);\n for (let yOffset = 0; yOffset < this._bufferService.rows; ++yOffset) {\n const row = buffer.y + buffer.ybase + yOffset;\n buffer.lines.get(row).fill(cell);\n buffer.lines.get(row).isWrapped = false;\n }\n this._dirtyRowService.markAllDirty();\n this._setCursor(0, 0);\n }\n}\n","/**\n * Copyright (c) 2018 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { IParsingState, IDcsHandler, IEscapeSequenceParser, IParams, IOscHandler, IHandlerCollection, CsiHandlerType, OscFallbackHandlerType, IOscParser, EscHandlerType, IDcsParser, DcsFallbackHandlerType, IFunctionIdentifier, ExecuteFallbackHandlerType, CsiFallbackHandlerType, EscFallbackHandlerType, PrintHandlerType, PrintFallbackHandlerType, ExecuteHandlerType } from 'common/parser/Types';\nimport { ParserState, ParserAction } from 'common/parser/Constants';\nimport { Disposable } from 'common/Lifecycle';\nimport { IDisposable } from 'common/Types';\nimport { fill } from 'common/TypedArrayUtils';\nimport { Params } from 'common/parser/Params';\nimport { OscParser } from 'common/parser/OscParser';\nimport { DcsParser } from 'common/parser/DcsParser';\n\n/**\n * Table values are generated like this:\n * index: currentState << TableValue.INDEX_STATE_SHIFT | charCode\n * value: action << TableValue.TRANSITION_ACTION_SHIFT | nextState\n */\nconst enum TableAccess {\n TRANSITION_ACTION_SHIFT = 4,\n TRANSITION_STATE_MASK = 15,\n INDEX_STATE_SHIFT = 8\n}\n\n/**\n * Transition table for EscapeSequenceParser.\n */\nexport class TransitionTable {\n public table: Uint8Array;\n\n constructor(length: number) {\n this.table = new Uint8Array(length);\n }\n\n /**\n * Set default transition.\n * @param action default action\n * @param next default next state\n */\n public setDefault(action: ParserAction, next: ParserState): void {\n fill(this.table, action << TableAccess.TRANSITION_ACTION_SHIFT | next);\n }\n\n /**\n * Add a transition to the transition table.\n * @param code input character code\n * @param state current parser state\n * @param action parser action to be done\n * @param next next parser state\n */\n public add(code: number, state: ParserState, action: ParserAction, next: ParserState): void {\n this.table[state << TableAccess.INDEX_STATE_SHIFT | code] = action << TableAccess.TRANSITION_ACTION_SHIFT | next;\n }\n\n /**\n * Add transitions for multiple input character codes.\n * @param codes input character code array\n * @param state current parser state\n * @param action parser action to be done\n * @param next next parser state\n */\n public addMany(codes: number[], state: ParserState, action: ParserAction, next: ParserState): void {\n for (let i = 0; i < codes.length; i++) {\n this.table[state << TableAccess.INDEX_STATE_SHIFT | codes[i]] = action << TableAccess.TRANSITION_ACTION_SHIFT | next;\n }\n }\n}\n\n\n// Pseudo-character placeholder for printable non-ascii characters (unicode).\nconst NON_ASCII_PRINTABLE = 0xA0;\n\n\n/**\n * VT500 compatible transition table.\n * Taken from https://vt100.net/emu/dec_ansi_parser.\n */\nexport const VT500_TRANSITION_TABLE = (function (): TransitionTable {\n const table: TransitionTable = new TransitionTable(4095);\n\n // range macro for byte\n const BYTE_VALUES = 256;\n const blueprint = Array.apply(null, Array(BYTE_VALUES)).map((unused: any, i: number) => i);\n const r = (start: number, end: number) => blueprint.slice(start, end);\n\n // Default definitions.\n const PRINTABLES = r(0x20, 0x7f); // 0x20 (SP) included, 0x7F (DEL) excluded\n const EXECUTABLES = r(0x00, 0x18);\n EXECUTABLES.push(0x19);\n EXECUTABLES.push.apply(EXECUTABLES, r(0x1c, 0x20));\n\n const states: number[] = r(ParserState.GROUND, ParserState.DCS_PASSTHROUGH + 1);\n let state: any;\n\n // set default transition\n table.setDefault(ParserAction.ERROR, ParserState.GROUND);\n // printables\n table.addMany(PRINTABLES, ParserState.GROUND, ParserAction.PRINT, ParserState.GROUND);\n // global anywhere rules\n for (state in states) {\n table.addMany([0x18, 0x1a, 0x99, 0x9a], state, ParserAction.EXECUTE, ParserState.GROUND);\n table.addMany(r(0x80, 0x90), state, ParserAction.EXECUTE, ParserState.GROUND);\n table.addMany(r(0x90, 0x98), state, ParserAction.EXECUTE, ParserState.GROUND);\n table.add(0x9c, state, ParserAction.IGNORE, ParserState.GROUND); // ST as terminator\n table.add(0x1b, state, ParserAction.CLEAR, ParserState.ESCAPE); // ESC\n table.add(0x9d, state, ParserAction.OSC_START, ParserState.OSC_STRING); // OSC\n table.addMany([0x98, 0x9e, 0x9f], state, ParserAction.IGNORE, ParserState.SOS_PM_APC_STRING);\n table.add(0x9b, state, ParserAction.CLEAR, ParserState.CSI_ENTRY); // CSI\n table.add(0x90, state, ParserAction.CLEAR, ParserState.DCS_ENTRY); // DCS\n }\n // rules for executables and 7f\n table.addMany(EXECUTABLES, ParserState.GROUND, ParserAction.EXECUTE, ParserState.GROUND);\n table.addMany(EXECUTABLES, ParserState.ESCAPE, ParserAction.EXECUTE, ParserState.ESCAPE);\n table.add(0x7f, ParserState.ESCAPE, ParserAction.IGNORE, ParserState.ESCAPE);\n table.addMany(EXECUTABLES, ParserState.OSC_STRING, ParserAction.IGNORE, ParserState.OSC_STRING);\n table.addMany(EXECUTABLES, ParserState.CSI_ENTRY, ParserAction.EXECUTE, ParserState.CSI_ENTRY);\n table.add(0x7f, ParserState.CSI_ENTRY, ParserAction.IGNORE, ParserState.CSI_ENTRY);\n table.addMany(EXECUTABLES, ParserState.CSI_PARAM, ParserAction.EXECUTE, ParserState.CSI_PARAM);\n table.add(0x7f, ParserState.CSI_PARAM, ParserAction.IGNORE, ParserState.CSI_PARAM);\n table.addMany(EXECUTABLES, ParserState.CSI_IGNORE, ParserAction.EXECUTE, ParserState.CSI_IGNORE);\n table.addMany(EXECUTABLES, ParserState.CSI_INTERMEDIATE, ParserAction.EXECUTE, ParserState.CSI_INTERMEDIATE);\n table.add(0x7f, ParserState.CSI_INTERMEDIATE, ParserAction.IGNORE, ParserState.CSI_INTERMEDIATE);\n table.addMany(EXECUTABLES, ParserState.ESCAPE_INTERMEDIATE, ParserAction.EXECUTE, ParserState.ESCAPE_INTERMEDIATE);\n table.add(0x7f, ParserState.ESCAPE_INTERMEDIATE, ParserAction.IGNORE, ParserState.ESCAPE_INTERMEDIATE);\n // osc\n table.add(0x5d, ParserState.ESCAPE, ParserAction.OSC_START, ParserState.OSC_STRING);\n table.addMany(PRINTABLES, ParserState.OSC_STRING, ParserAction.OSC_PUT, ParserState.OSC_STRING);\n table.add(0x7f, ParserState.OSC_STRING, ParserAction.OSC_PUT, ParserState.OSC_STRING);\n table.addMany([0x9c, 0x1b, 0x18, 0x1a, 0x07], ParserState.OSC_STRING, ParserAction.OSC_END, ParserState.GROUND);\n table.addMany(r(0x1c, 0x20), ParserState.OSC_STRING, ParserAction.IGNORE, ParserState.OSC_STRING);\n // sos/pm/apc does nothing\n table.addMany([0x58, 0x5e, 0x5f], ParserState.ESCAPE, ParserAction.IGNORE, ParserState.SOS_PM_APC_STRING);\n table.addMany(PRINTABLES, ParserState.SOS_PM_APC_STRING, ParserAction.IGNORE, ParserState.SOS_PM_APC_STRING);\n table.addMany(EXECUTABLES, ParserState.SOS_PM_APC_STRING, ParserAction.IGNORE, ParserState.SOS_PM_APC_STRING);\n table.add(0x9c, ParserState.SOS_PM_APC_STRING, ParserAction.IGNORE, ParserState.GROUND);\n table.add(0x7f, ParserState.SOS_PM_APC_STRING, ParserAction.IGNORE, ParserState.SOS_PM_APC_STRING);\n // csi entries\n table.add(0x5b, ParserState.ESCAPE, ParserAction.CLEAR, ParserState.CSI_ENTRY);\n table.addMany(r(0x40, 0x7f), ParserState.CSI_ENTRY, ParserAction.CSI_DISPATCH, ParserState.GROUND);\n table.addMany(r(0x30, 0x3c), ParserState.CSI_ENTRY, ParserAction.PARAM, ParserState.CSI_PARAM);\n table.addMany([0x3c, 0x3d, 0x3e, 0x3f], ParserState.CSI_ENTRY, ParserAction.COLLECT, ParserState.CSI_PARAM);\n table.addMany(r(0x30, 0x3c), ParserState.CSI_PARAM, ParserAction.PARAM, ParserState.CSI_PARAM);\n table.addMany(r(0x40, 0x7f), ParserState.CSI_PARAM, ParserAction.CSI_DISPATCH, ParserState.GROUND);\n table.addMany([0x3c, 0x3d, 0x3e, 0x3f], ParserState.CSI_PARAM, ParserAction.IGNORE, ParserState.CSI_IGNORE);\n table.addMany(r(0x20, 0x40), ParserState.CSI_IGNORE, ParserAction.IGNORE, ParserState.CSI_IGNORE);\n table.add(0x7f, ParserState.CSI_IGNORE, ParserAction.IGNORE, ParserState.CSI_IGNORE);\n table.addMany(r(0x40, 0x7f), ParserState.CSI_IGNORE, ParserAction.IGNORE, ParserState.GROUND);\n table.addMany(r(0x20, 0x30), ParserState.CSI_ENTRY, ParserAction.COLLECT, ParserState.CSI_INTERMEDIATE);\n table.addMany(r(0x20, 0x30), ParserState.CSI_INTERMEDIATE, ParserAction.COLLECT, ParserState.CSI_INTERMEDIATE);\n table.addMany(r(0x30, 0x40), ParserState.CSI_INTERMEDIATE, ParserAction.IGNORE, ParserState.CSI_IGNORE);\n table.addMany(r(0x40, 0x7f), ParserState.CSI_INTERMEDIATE, ParserAction.CSI_DISPATCH, ParserState.GROUND);\n table.addMany(r(0x20, 0x30), ParserState.CSI_PARAM, ParserAction.COLLECT, ParserState.CSI_INTERMEDIATE);\n // esc_intermediate\n table.addMany(r(0x20, 0x30), ParserState.ESCAPE, ParserAction.COLLECT, ParserState.ESCAPE_INTERMEDIATE);\n table.addMany(r(0x20, 0x30), ParserState.ESCAPE_INTERMEDIATE, ParserAction.COLLECT, ParserState.ESCAPE_INTERMEDIATE);\n table.addMany(r(0x30, 0x7f), ParserState.ESCAPE_INTERMEDIATE, ParserAction.ESC_DISPATCH, ParserState.GROUND);\n table.addMany(r(0x30, 0x50), ParserState.ESCAPE, ParserAction.ESC_DISPATCH, ParserState.GROUND);\n table.addMany(r(0x51, 0x58), ParserState.ESCAPE, ParserAction.ESC_DISPATCH, ParserState.GROUND);\n table.addMany([0x59, 0x5a, 0x5c], ParserState.ESCAPE, ParserAction.ESC_DISPATCH, ParserState.GROUND);\n table.addMany(r(0x60, 0x7f), ParserState.ESCAPE, ParserAction.ESC_DISPATCH, ParserState.GROUND);\n // dcs entry\n table.add(0x50, ParserState.ESCAPE, ParserAction.CLEAR, ParserState.DCS_ENTRY);\n table.addMany(EXECUTABLES, ParserState.DCS_ENTRY, ParserAction.IGNORE, ParserState.DCS_ENTRY);\n table.add(0x7f, ParserState.DCS_ENTRY, ParserAction.IGNORE, ParserState.DCS_ENTRY);\n table.addMany(r(0x1c, 0x20), ParserState.DCS_ENTRY, ParserAction.IGNORE, ParserState.DCS_ENTRY);\n table.addMany(r(0x20, 0x30), ParserState.DCS_ENTRY, ParserAction.COLLECT, ParserState.DCS_INTERMEDIATE);\n table.addMany(r(0x30, 0x3c), ParserState.DCS_ENTRY, ParserAction.PARAM, ParserState.DCS_PARAM);\n table.addMany([0x3c, 0x3d, 0x3e, 0x3f], ParserState.DCS_ENTRY, ParserAction.COLLECT, ParserState.DCS_PARAM);\n table.addMany(EXECUTABLES, ParserState.DCS_IGNORE, ParserAction.IGNORE, ParserState.DCS_IGNORE);\n table.addMany(r(0x20, 0x80), ParserState.DCS_IGNORE, ParserAction.IGNORE, ParserState.DCS_IGNORE);\n table.addMany(r(0x1c, 0x20), ParserState.DCS_IGNORE, ParserAction.IGNORE, ParserState.DCS_IGNORE);\n table.addMany(EXECUTABLES, ParserState.DCS_PARAM, ParserAction.IGNORE, ParserState.DCS_PARAM);\n table.add(0x7f, ParserState.DCS_PARAM, ParserAction.IGNORE, ParserState.DCS_PARAM);\n table.addMany(r(0x1c, 0x20), ParserState.DCS_PARAM, ParserAction.IGNORE, ParserState.DCS_PARAM);\n table.addMany(r(0x30, 0x3c), ParserState.DCS_PARAM, ParserAction.PARAM, ParserState.DCS_PARAM);\n table.addMany([0x3c, 0x3d, 0x3e, 0x3f], ParserState.DCS_PARAM, ParserAction.IGNORE, ParserState.DCS_IGNORE);\n table.addMany(r(0x20, 0x30), ParserState.DCS_PARAM, ParserAction.COLLECT, ParserState.DCS_INTERMEDIATE);\n table.addMany(EXECUTABLES, ParserState.DCS_INTERMEDIATE, ParserAction.IGNORE, ParserState.DCS_INTERMEDIATE);\n table.add(0x7f, ParserState.DCS_INTERMEDIATE, ParserAction.IGNORE, ParserState.DCS_INTERMEDIATE);\n table.addMany(r(0x1c, 0x20), ParserState.DCS_INTERMEDIATE, ParserAction.IGNORE, ParserState.DCS_INTERMEDIATE);\n table.addMany(r(0x20, 0x30), ParserState.DCS_INTERMEDIATE, ParserAction.COLLECT, ParserState.DCS_INTERMEDIATE);\n table.addMany(r(0x30, 0x40), ParserState.DCS_INTERMEDIATE, ParserAction.IGNORE, ParserState.DCS_IGNORE);\n table.addMany(r(0x40, 0x7f), ParserState.DCS_INTERMEDIATE, ParserAction.DCS_HOOK, ParserState.DCS_PASSTHROUGH);\n table.addMany(r(0x40, 0x7f), ParserState.DCS_PARAM, ParserAction.DCS_HOOK, ParserState.DCS_PASSTHROUGH);\n table.addMany(r(0x40, 0x7f), ParserState.DCS_ENTRY, ParserAction.DCS_HOOK, ParserState.DCS_PASSTHROUGH);\n table.addMany(EXECUTABLES, ParserState.DCS_PASSTHROUGH, ParserAction.DCS_PUT, ParserState.DCS_PASSTHROUGH);\n table.addMany(PRINTABLES, ParserState.DCS_PASSTHROUGH, ParserAction.DCS_PUT, ParserState.DCS_PASSTHROUGH);\n table.add(0x7f, ParserState.DCS_PASSTHROUGH, ParserAction.IGNORE, ParserState.DCS_PASSTHROUGH);\n table.addMany([0x1b, 0x9c, 0x18, 0x1a], ParserState.DCS_PASSTHROUGH, ParserAction.DCS_UNHOOK, ParserState.GROUND);\n // special handling of unicode chars\n table.add(NON_ASCII_PRINTABLE, ParserState.GROUND, ParserAction.PRINT, ParserState.GROUND);\n table.add(NON_ASCII_PRINTABLE, ParserState.OSC_STRING, ParserAction.OSC_PUT, ParserState.OSC_STRING);\n table.add(NON_ASCII_PRINTABLE, ParserState.CSI_IGNORE, ParserAction.IGNORE, ParserState.CSI_IGNORE);\n table.add(NON_ASCII_PRINTABLE, ParserState.DCS_IGNORE, ParserAction.IGNORE, ParserState.DCS_IGNORE);\n table.add(NON_ASCII_PRINTABLE, ParserState.DCS_PASSTHROUGH, ParserAction.DCS_PUT, ParserState.DCS_PASSTHROUGH);\n return table;\n})();\n\n\n/**\n * EscapeSequenceParser.\n * This class implements the ANSI/DEC compatible parser described by\n * Paul Williams (https://vt100.net/emu/dec_ansi_parser).\n *\n * To implement custom ANSI compliant escape sequences it is not needed to\n * alter this parser, instead consider registering a custom handler.\n * For non ANSI compliant sequences change the transition table with\n * the optional `transitions` constructor argument and\n * reimplement the `parse` method.\n *\n * This parser is currently hardcoded to operate in ZDM (Zero Default Mode)\n * as suggested by the original parser, thus empty parameters are set to 0.\n * This this is not in line with the latest ECMA-48 specification\n * (ZDM was part of the early specs and got completely removed later on).\n *\n * Other than the original parser from vt100.net this parser supports\n * sub parameters in digital parameters separated by colons. Empty sub parameters\n * are set to -1 (no ZDM for sub parameters).\n *\n * About prefix and intermediate bytes:\n * This parser follows the assumptions of the vt100.net parser with these restrictions:\n * - only one prefix byte is allowed as first parameter byte, byte range 0x3c .. 0x3f\n * - max. two intermediates are respected, byte range 0x20 .. 0x2f\n * Note that this is not in line with ECMA-48 which does not limit either of those.\n * Furthermore ECMA-48 allows the prefix byte range at any param byte position. Currently\n * there are no known sequences that follow the broader definition of the specification.\n *\n * TODO: implement error recovery hook via error handler return values\n */\nexport class EscapeSequenceParser extends Disposable implements IEscapeSequenceParser {\n public initialState: number;\n public currentState: number;\n public precedingCodepoint: number;\n\n // buffers over several parse calls\n protected _params: Params;\n protected _collect: number;\n\n // handler lookup containers\n protected _printHandler: PrintHandlerType;\n protected _executeHandlers: {[flag: number]: ExecuteHandlerType};\n protected _csiHandlers: IHandlerCollection;\n protected _escHandlers: IHandlerCollection;\n protected _oscParser: IOscParser;\n protected _dcsParser: IDcsParser;\n protected _errorHandler: (state: IParsingState) => IParsingState;\n\n // fallback handlers\n protected _printHandlerFb: PrintFallbackHandlerType;\n protected _executeHandlerFb: ExecuteFallbackHandlerType;\n protected _csiHandlerFb: CsiFallbackHandlerType;\n protected _escHandlerFb: EscFallbackHandlerType;\n protected _errorHandlerFb: (state: IParsingState) => IParsingState;\n\n constructor(readonly TRANSITIONS: TransitionTable = VT500_TRANSITION_TABLE) {\n super();\n\n this.initialState = ParserState.GROUND;\n this.currentState = this.initialState;\n this._params = new Params(); // defaults to 32 storable params/subparams\n this._params.addParam(0); // ZDM\n this._collect = 0;\n this.precedingCodepoint = 0;\n\n // set default fallback handlers and handler lookup containers\n this._printHandlerFb = (data, start, end): void => { };\n this._executeHandlerFb = (code: number): void => { };\n this._csiHandlerFb = (ident: number, params: IParams): void => { };\n this._escHandlerFb = (ident: number): void => { };\n this._errorHandlerFb = (state: IParsingState): IParsingState => state;\n this._printHandler = this._printHandlerFb;\n this._executeHandlers = Object.create(null);\n this._csiHandlers = Object.create(null);\n this._escHandlers = Object.create(null);\n this._oscParser = new OscParser();\n this._dcsParser = new DcsParser();\n this._errorHandler = this._errorHandlerFb;\n\n // swallow 7bit ST (ESC+\\)\n this.setEscHandler({final: '\\\\'}, () => {});\n }\n\n protected _identifier(id: IFunctionIdentifier, finalRange: number[] = [0x40, 0x7e]): number {\n let res = 0;\n if (id.prefix) {\n if (id.prefix.length > 1) {\n throw new Error('only one byte as prefix supported');\n }\n res = id.prefix.charCodeAt(0);\n if (res && 0x3c > res || res > 0x3f) {\n throw new Error('prefix must be in range 0x3c .. 0x3f');\n }\n }\n if (id.intermediates) {\n if (id.intermediates.length > 2) {\n throw new Error('only two bytes as intermediates are supported');\n }\n for (let i = 0; i < id.intermediates.length; ++i) {\n const intermediate = id.intermediates.charCodeAt(i);\n if (0x20 > intermediate || intermediate > 0x2f) {\n throw new Error('intermediate must be in range 0x20 .. 0x2f');\n }\n res <<= 8;\n res |= intermediate;\n }\n }\n if (id.final.length !== 1) {\n throw new Error('final must be a single byte');\n }\n const finalCode = id.final.charCodeAt(0);\n if (finalRange[0] > finalCode || finalCode > finalRange[1]) {\n throw new Error(`final must be in range ${finalRange[0]} .. ${finalRange[1]}`);\n }\n res <<= 8;\n res |= finalCode;\n\n return res;\n }\n\n public identToString(ident: number): string {\n const res: string[] = [];\n while (ident) {\n res.push(String.fromCharCode(ident & 0xFF));\n ident >>= 8;\n }\n return res.reverse().join('');\n }\n\n public dispose(): void {\n this._csiHandlers = Object.create(null);\n this._executeHandlers = Object.create(null);\n this._escHandlers = Object.create(null);\n this._oscParser.dispose();\n this._dcsParser.dispose();\n }\n\n public setPrintHandler(handler: PrintHandlerType): void {\n this._printHandler = handler;\n }\n public clearPrintHandler(): void {\n this._printHandler = this._printHandlerFb;\n }\n\n public addEscHandler(id: IFunctionIdentifier, handler: EscHandlerType): IDisposable {\n const ident = this._identifier(id, [0x30, 0x7e]);\n if (this._escHandlers[ident] === undefined) {\n this._escHandlers[ident] = [];\n }\n const handlerList = this._escHandlers[ident];\n handlerList.push(handler);\n return {\n dispose: () => {\n const handlerIndex = handlerList.indexOf(handler);\n if (handlerIndex !== -1) {\n handlerList.splice(handlerIndex, 1);\n }\n }\n };\n }\n public setEscHandler(id: IFunctionIdentifier, handler: EscHandlerType): void {\n this._escHandlers[this._identifier(id, [0x30, 0x7e])] = [handler];\n }\n public clearEscHandler(id: IFunctionIdentifier): void {\n if (this._escHandlers[this._identifier(id, [0x30, 0x7e])]) delete this._escHandlers[this._identifier(id, [0x30, 0x7e])];\n }\n public setEscHandlerFallback(handler: EscFallbackHandlerType): void {\n this._escHandlerFb = handler;\n }\n\n public setExecuteHandler(flag: string, handler: ExecuteHandlerType): void {\n this._executeHandlers[flag.charCodeAt(0)] = handler;\n }\n public clearExecuteHandler(flag: string): void {\n if (this._executeHandlers[flag.charCodeAt(0)]) delete this._executeHandlers[flag.charCodeAt(0)];\n }\n public setExecuteHandlerFallback(handler: ExecuteFallbackHandlerType): void {\n this._executeHandlerFb = handler;\n }\n\n public addCsiHandler(id: IFunctionIdentifier, handler: CsiHandlerType): IDisposable {\n const ident = this._identifier(id);\n if (this._csiHandlers[ident] === undefined) {\n this._csiHandlers[ident] = [];\n }\n const handlerList = this._csiHandlers[ident];\n handlerList.push(handler);\n return {\n dispose: () => {\n const handlerIndex = handlerList.indexOf(handler);\n if (handlerIndex !== -1) {\n handlerList.splice(handlerIndex, 1);\n }\n }\n };\n }\n public setCsiHandler(id: IFunctionIdentifier, handler: CsiHandlerType): void {\n this._csiHandlers[this._identifier(id)] = [handler];\n }\n public clearCsiHandler(id: IFunctionIdentifier): void {\n if (this._csiHandlers[this._identifier(id)]) delete this._csiHandlers[this._identifier(id)];\n }\n public setCsiHandlerFallback(callback: (ident: number, params: IParams) => void): void {\n this._csiHandlerFb = callback;\n }\n\n public addDcsHandler(id: IFunctionIdentifier, handler: IDcsHandler): IDisposable {\n return this._dcsParser.addHandler(this._identifier(id), handler);\n }\n public setDcsHandler(id: IFunctionIdentifier, handler: IDcsHandler): void {\n this._dcsParser.setHandler(this._identifier(id), handler);\n }\n public clearDcsHandler(id: IFunctionIdentifier): void {\n this._dcsParser.clearHandler(this._identifier(id));\n }\n public setDcsHandlerFallback(handler: DcsFallbackHandlerType): void {\n this._dcsParser.setHandlerFallback(handler);\n }\n\n public addOscHandler(ident: number, handler: IOscHandler): IDisposable {\n return this._oscParser.addHandler(ident, handler);\n }\n public setOscHandler(ident: number, handler: IOscHandler): void {\n this._oscParser.setHandler(ident, handler);\n }\n public clearOscHandler(ident: number): void {\n this._oscParser.clearHandler(ident);\n }\n public setOscHandlerFallback(handler: OscFallbackHandlerType): void {\n this._oscParser.setHandlerFallback(handler);\n }\n\n public setErrorHandler(callback: (state: IParsingState) => IParsingState): void {\n this._errorHandler = callback;\n }\n public clearErrorHandler(): void {\n this._errorHandler = this._errorHandlerFb;\n }\n\n public reset(): void {\n this.currentState = this.initialState;\n this._oscParser.reset();\n this._dcsParser.reset();\n this._params.reset();\n this._params.addParam(0); // ZDM\n this._collect = 0;\n this.precedingCodepoint = 0;\n }\n\n\n\n /**\n * Parse UTF32 codepoints in `data` up to `length`.\n *\n * Note: For several actions with high data load the parsing is optimized\n * by using local read ahead loops with hardcoded conditions to\n * avoid costly table lookups. Make sure that any change of table values\n * will be reflected in the loop conditions as well and vice versa.\n * Affected states/actions:\n * - GROUND:PRINT\n * - CSI_PARAM:PARAM\n * - DCS_PARAM:PARAM\n * - OSC_STRING:OSC_PUT\n * - DCS_PASSTHROUGH:DCS_PUT\n */\n public parse(data: Uint32Array, length: number): void {\n let code = 0;\n let transition = 0;\n let currentState = this.currentState;\n const osc = this._oscParser;\n const dcs = this._dcsParser;\n let collect = this._collect;\n const params = this._params;\n const table: Uint8Array = this.TRANSITIONS.table;\n\n // process input string\n for (let i = 0; i < length; ++i) {\n code = data[i];\n\n // normal transition & action lookup\n transition = table[currentState << TableAccess.INDEX_STATE_SHIFT | (code < 0xa0 ? code : NON_ASCII_PRINTABLE)];\n switch (transition >> TableAccess.TRANSITION_ACTION_SHIFT) {\n case ParserAction.PRINT:\n // read ahead with loop unrolling\n // Note: 0x20 (SP) is included, 0x7F (DEL) is excluded\n for (let j = i + 1; ; ++j) {\n if (j >= length || (code = data[j]) < 0x20 || (code > 0x7e && code < NON_ASCII_PRINTABLE)) {\n this._printHandler(data, i, j);\n i = j - 1;\n break;\n }\n if (++j >= length || (code = data[j]) < 0x20 || (code > 0x7e && code < NON_ASCII_PRINTABLE)) {\n this._printHandler(data, i, j);\n i = j - 1;\n break;\n }\n if (++j >= length || (code = data[j]) < 0x20 || (code > 0x7e && code < NON_ASCII_PRINTABLE)) {\n this._printHandler(data, i, j);\n i = j - 1;\n break;\n }\n if (++j >= length || (code = data[j]) < 0x20 || (code > 0x7e && code < NON_ASCII_PRINTABLE)) {\n this._printHandler(data, i, j);\n i = j - 1;\n break;\n }\n }\n break;\n case ParserAction.EXECUTE:\n if (this._executeHandlers[code]) this._executeHandlers[code]();\n else this._executeHandlerFb(code);\n this.precedingCodepoint = 0;\n break;\n case ParserAction.IGNORE:\n break;\n case ParserAction.ERROR:\n const inject: IParsingState = this._errorHandler(\n {\n position: i,\n code,\n currentState,\n collect,\n params,\n abort: false\n });\n if (inject.abort) return;\n // inject values: currently not implemented\n break;\n case ParserAction.CSI_DISPATCH:\n // Trigger CSI Handler\n const handlers = this._csiHandlers[collect << 8 | code];\n let j = handlers ? handlers.length - 1 : -1;\n for (; j >= 0; j--) {\n // undefined or true means success and to stop bubbling\n if (handlers[j](params) !== false) {\n break;\n }\n }\n if (j < 0) {\n this._csiHandlerFb(collect << 8 | code, params);\n }\n this.precedingCodepoint = 0;\n break;\n case ParserAction.PARAM:\n // inner loop: digits (0x30 - 0x39) and ; (0x3b) and : (0x3a)\n do {\n switch (code) {\n case 0x3b:\n params.addParam(0); // ZDM\n break;\n case 0x3a:\n params.addSubParam(-1);\n break;\n default: // 0x30 - 0x39\n params.addDigit(code - 48);\n }\n } while (++i < length && (code = data[i]) > 0x2f && code < 0x3c);\n i--;\n break;\n case ParserAction.COLLECT:\n collect <<= 8;\n collect |= code;\n break;\n case ParserAction.ESC_DISPATCH:\n const handlersEsc = this._escHandlers[collect << 8 | code];\n let jj = handlersEsc ? handlersEsc.length - 1 : -1;\n for (; jj >= 0; jj--) {\n // undefined or true means success and to stop bubbling\n if (handlersEsc[jj]() !== false) {\n break;\n }\n }\n if (jj < 0) {\n this._escHandlerFb(collect << 8 | code);\n }\n this.precedingCodepoint = 0;\n break;\n case ParserAction.CLEAR:\n params.reset();\n params.addParam(0); // ZDM\n collect = 0;\n break;\n case ParserAction.DCS_HOOK:\n dcs.hook(collect << 8 | code, params);\n break;\n case ParserAction.DCS_PUT:\n // inner loop - exit DCS_PUT: 0x18, 0x1a, 0x1b, 0x7f, 0x80 - 0x9f\n // unhook triggered by: 0x1b, 0x9c (success) and 0x18, 0x1a (abort)\n for (let j = i + 1; ; ++j) {\n if (j >= length || (code = data[j]) === 0x18 || code === 0x1a || code === 0x1b || (code > 0x7f && code < NON_ASCII_PRINTABLE)) {\n dcs.put(data, i, j);\n i = j - 1;\n break;\n }\n }\n break;\n case ParserAction.DCS_UNHOOK:\n dcs.unhook(code !== 0x18 && code !== 0x1a);\n if (code === 0x1b) transition |= ParserState.ESCAPE;\n params.reset();\n params.addParam(0); // ZDM\n collect = 0;\n this.precedingCodepoint = 0;\n break;\n case ParserAction.OSC_START:\n osc.start();\n break;\n case ParserAction.OSC_PUT:\n // inner loop: 0x20 (SP) included, 0x7F (DEL) included\n for (let j = i + 1; ; j++) {\n if (j >= length || (code = data[j]) < 0x20 || (code > 0x7f && code <= 0x9f)) {\n osc.put(data, i, j);\n i = j - 1;\n break;\n }\n }\n break;\n case ParserAction.OSC_END:\n osc.end(code !== 0x18 && code !== 0x1a);\n if (code === 0x1b) transition |= ParserState.ESCAPE;\n params.reset();\n params.addParam(0); // ZDM\n collect = 0;\n this.precedingCodepoint = 0;\n break;\n }\n currentState = transition & TableAccess.TRANSITION_STATE_MASK;\n }\n\n // save collected intermediates\n this._collect = collect;\n\n // save state\n this.currentState = currentState;\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { TextRenderLayer } from 'browser/renderer/TextRenderLayer';\nimport { SelectionRenderLayer } from 'browser/renderer/SelectionRenderLayer';\nimport { CursorRenderLayer } from 'browser/renderer/CursorRenderLayer';\nimport { IRenderLayer, IRenderer, IRenderDimensions, CharacterJoinerHandler, ICharacterJoinerRegistry, IRequestRefreshRowsEvent } from 'browser/renderer/Types';\nimport { LinkRenderLayer } from 'browser/renderer/LinkRenderLayer';\nimport { CharacterJoinerRegistry } from 'browser/renderer/CharacterJoinerRegistry';\nimport { Disposable } from 'common/Lifecycle';\nimport { IColorSet, ILinkifier } from 'browser/Types';\nimport { ICharSizeService, ICoreBrowserService } from 'browser/services/Services';\nimport { IBufferService, IOptionsService, ICoreService } from 'common/services/Services';\nimport { removeTerminalFromCache } from 'browser/renderer/atlas/CharAtlasCache';\nimport { EventEmitter, IEvent } from 'common/EventEmitter';\n\nlet nextRendererId = 1;\n\nexport class Renderer extends Disposable implements IRenderer {\n private _id = nextRendererId++;\n\n private _renderLayers: IRenderLayer[];\n private _devicePixelRatio: number;\n private _characterJoinerRegistry: ICharacterJoinerRegistry;\n\n public dimensions: IRenderDimensions;\n\n private _onRequestRefreshRows = new EventEmitter();\n public get onRequestRefreshRows(): IEvent { return this._onRequestRefreshRows.event; }\n\n constructor(\n private _colors: IColorSet,\n private readonly _screenElement: HTMLElement,\n private readonly _linkifier: ILinkifier,\n @IBufferService private readonly _bufferService: IBufferService,\n @ICharSizeService private readonly _charSizeService: ICharSizeService,\n @IOptionsService private readonly _optionsService: IOptionsService,\n @ICoreService readonly coreService: ICoreService,\n @ICoreBrowserService readonly coreBrowserService: ICoreBrowserService\n ) {\n super();\n const allowTransparency = this._optionsService.options.allowTransparency;\n this._characterJoinerRegistry = new CharacterJoinerRegistry(this._bufferService);\n\n this._renderLayers = [\n new TextRenderLayer(this._screenElement, 0, this._colors, this._characterJoinerRegistry, allowTransparency, this._id, this._bufferService, _optionsService),\n new SelectionRenderLayer(this._screenElement, 1, this._colors, this._id, this._bufferService, _optionsService),\n new LinkRenderLayer(this._screenElement, 2, this._colors, this._id, this._linkifier, this._bufferService, _optionsService),\n new CursorRenderLayer(this._screenElement, 3, this._colors, this._id, this._onRequestRefreshRows, this._bufferService, _optionsService, coreService, coreBrowserService)\n ];\n this.dimensions = {\n scaledCharWidth: 0,\n scaledCharHeight: 0,\n scaledCellWidth: 0,\n scaledCellHeight: 0,\n scaledCharLeft: 0,\n scaledCharTop: 0,\n scaledCanvasWidth: 0,\n scaledCanvasHeight: 0,\n canvasWidth: 0,\n canvasHeight: 0,\n actualCellWidth: 0,\n actualCellHeight: 0\n };\n this._devicePixelRatio = window.devicePixelRatio;\n this._updateDimensions();\n this.onOptionsChanged();\n }\n\n public dispose(): void {\n super.dispose();\n this._renderLayers.forEach(l => l.dispose());\n removeTerminalFromCache(this._id);\n }\n\n public onDevicePixelRatioChange(): void {\n // If the device pixel ratio changed, the char atlas needs to be regenerated\n // and the terminal needs to refreshed\n if (this._devicePixelRatio !== window.devicePixelRatio) {\n this._devicePixelRatio = window.devicePixelRatio;\n this.onResize(this._bufferService.cols, this._bufferService.rows);\n }\n }\n\n public setColors(colors: IColorSet): void {\n this._colors = colors;\n\n // Clear layers and force a full render\n this._renderLayers.forEach(l => {\n l.setColors(this._colors);\n l.reset();\n });\n }\n\n public onResize(cols: number, rows: number): void {\n // Update character and canvas dimensions\n this._updateDimensions();\n\n // Resize all render layers\n this._renderLayers.forEach(l => l.resize(this.dimensions));\n\n // Resize the screen\n this._screenElement.style.width = `${this.dimensions.canvasWidth}px`;\n this._screenElement.style.height = `${this.dimensions.canvasHeight}px`;\n }\n\n public onCharSizeChanged(): void {\n this.onResize(this._bufferService.cols, this._bufferService.rows);\n }\n\n public onBlur(): void {\n this._runOperation(l => l.onBlur());\n }\n\n public onFocus(): void {\n this._runOperation(l => l.onFocus());\n }\n\n public onSelectionChanged(start: [number, number], end: [number, number], columnSelectMode: boolean = false): void {\n this._runOperation(l => l.onSelectionChanged(start, end, columnSelectMode));\n }\n\n public onCursorMove(): void {\n this._runOperation(l => l.onCursorMove());\n }\n\n public onOptionsChanged(): void {\n this._runOperation(l => l.onOptionsChanged());\n }\n\n public clear(): void {\n this._runOperation(l => l.reset());\n }\n\n private _runOperation(operation: (layer: IRenderLayer) => void): void {\n this._renderLayers.forEach(l => operation(l));\n }\n\n /**\n * Performs the refresh loop callback, calling refresh only if a refresh is\n * necessary before queueing up the next one.\n */\n public renderRows(start: number, end: number): void {\n this._renderLayers.forEach(l => l.onGridChanged(start, end));\n }\n\n /**\n * Recalculates the character and canvas dimensions.\n */\n private _updateDimensions(): void {\n if (!this._charSizeService.hasValidSize) {\n return;\n }\n\n // Calculate the scaled character width. Width is floored as it must be\n // drawn to an integer grid in order for the CharAtlas \"stamps\" to not be\n // blurry. When text is drawn to the grid not using the CharAtlas, it is\n // clipped to ensure there is no overlap with the next cell.\n this.dimensions.scaledCharWidth = Math.floor(this._charSizeService.width * window.devicePixelRatio);\n\n // Calculate the scaled character height. Height is ceiled in case\n // devicePixelRatio is a floating point number in order to ensure there is\n // enough space to draw the character to the cell.\n this.dimensions.scaledCharHeight = Math.ceil(this._charSizeService.height * window.devicePixelRatio);\n\n // Calculate the scaled cell height, if lineHeight is not 1 then the value\n // will be floored because since lineHeight can never be lower then 1, there\n // is a guarentee that the scaled line height will always be larger than\n // scaled char height.\n this.dimensions.scaledCellHeight = Math.floor(this.dimensions.scaledCharHeight * this._optionsService.options.lineHeight);\n\n // Calculate the y coordinate within a cell that text should draw from in\n // order to draw in the center of a cell.\n this.dimensions.scaledCharTop = this._optionsService.options.lineHeight === 1 ? 0 : Math.round((this.dimensions.scaledCellHeight - this.dimensions.scaledCharHeight) / 2);\n\n // Calculate the scaled cell width, taking the letterSpacing into account.\n this.dimensions.scaledCellWidth = this.dimensions.scaledCharWidth + Math.round(this._optionsService.options.letterSpacing);\n\n // Calculate the x coordinate with a cell that text should draw from in\n // order to draw in the center of a cell.\n this.dimensions.scaledCharLeft = Math.floor(this._optionsService.options.letterSpacing / 2);\n\n // Recalculate the canvas dimensions; scaled* define the actual number of\n // pixel in the canvas\n this.dimensions.scaledCanvasHeight = this._bufferService.rows * this.dimensions.scaledCellHeight;\n this.dimensions.scaledCanvasWidth = this._bufferService.cols * this.dimensions.scaledCellWidth;\n\n // The the size of the canvas on the page. It's very important that this\n // rounds to nearest integer and not ceils as browsers often set\n // window.devicePixelRatio as something like 1.100000023841858, when it's\n // actually 1.1. Ceiling causes blurriness as the backing canvas image is 1\n // pixel too large for the canvas element size.\n this.dimensions.canvasHeight = Math.round(this.dimensions.scaledCanvasHeight / window.devicePixelRatio);\n this.dimensions.canvasWidth = Math.round(this.dimensions.scaledCanvasWidth / window.devicePixelRatio);\n\n // Get the _actual_ dimensions of an individual cell. This needs to be\n // derived from the canvasWidth/Height calculated above which takes into\n // account window.devicePixelRatio. ICharSizeService.width/height by itself\n // is insufficient when the page is not at 100% zoom level as it's measured\n // in CSS pixels, but the actual char size on the canvas can differ.\n this.dimensions.actualCellHeight = this.dimensions.canvasHeight / this._bufferService.rows;\n this.dimensions.actualCellWidth = this.dimensions.canvasWidth / this._bufferService.cols;\n }\n\n public registerCharacterJoiner(handler: CharacterJoinerHandler): number {\n return this._characterJoinerRegistry.registerCharacterJoiner(handler);\n }\n\n public deregisterCharacterJoiner(joinerId: number): boolean {\n return this._characterJoinerRegistry.deregisterCharacterJoiner(joinerId);\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { ICharacterJoinerRegistry, IRenderDimensions } from 'browser/renderer/Types';\nimport { CharData, ICellData } from 'common/Types';\nimport { GridCache } from 'browser/renderer/GridCache';\nimport { BaseRenderLayer } from 'browser/renderer/BaseRenderLayer';\nimport { AttributeData } from 'common/buffer/AttributeData';\nimport { NULL_CELL_CODE, Content } from 'common/buffer/Constants';\nimport { JoinedCellData } from 'browser/renderer/CharacterJoinerRegistry';\nimport { IColorSet } from 'browser/Types';\nimport { CellData } from 'common/buffer/CellData';\nimport { IOptionsService, IBufferService } from 'common/services/Services';\n\n/**\n * This CharData looks like a null character, which will forc a clear and render\n * when the character changes (a regular space ' ' character may not as it's\n * drawn state is a cleared cell).\n */\n// const OVERLAP_OWNED_CHAR_DATA: CharData = [null, '', 0, -1];\n\nexport class TextRenderLayer extends BaseRenderLayer {\n private _state: GridCache;\n private _characterWidth: number = 0;\n private _characterFont: string = '';\n private _characterOverlapCache: { [key: string]: boolean } = {};\n private _characterJoinerRegistry: ICharacterJoinerRegistry;\n private _workCell = new CellData();\n\n constructor(\n container: HTMLElement,\n zIndex: number,\n colors: IColorSet,\n characterJoinerRegistry: ICharacterJoinerRegistry,\n alpha: boolean,\n rendererId: number,\n readonly bufferService: IBufferService,\n readonly optionsService: IOptionsService\n ) {\n super(container, 'text', zIndex, alpha, colors, rendererId, bufferService, optionsService);\n this._state = new GridCache();\n this._characterJoinerRegistry = characterJoinerRegistry;\n }\n\n public resize(dim: IRenderDimensions): void {\n super.resize(dim);\n\n // Clear the character width cache if the font or width has changed\n const terminalFont = this._getFont(false, false);\n if (this._characterWidth !== dim.scaledCharWidth || this._characterFont !== terminalFont) {\n this._characterWidth = dim.scaledCharWidth;\n this._characterFont = terminalFont;\n this._characterOverlapCache = {};\n }\n // Resizing the canvas discards the contents of the canvas so clear state\n this._state.clear();\n this._state.resize(this._bufferService.cols, this._bufferService.rows);\n }\n\n public reset(): void {\n this._state.clear();\n this._clearAll();\n }\n\n private _forEachCell(\n firstRow: number,\n lastRow: number,\n joinerRegistry: ICharacterJoinerRegistry | null,\n callback: (\n cell: ICellData,\n x: number,\n y: number\n ) => void\n ): void {\n for (let y = firstRow; y <= lastRow; y++) {\n const row = y + this._bufferService.buffer.ydisp;\n const line = this._bufferService.buffer.lines.get(row);\n const joinedRanges = joinerRegistry ? joinerRegistry.getJoinedCharacters(row) : [];\n for (let x = 0; x < this._bufferService.cols; x++) {\n line!.loadCell(x, this._workCell);\n let cell = this._workCell;\n\n // If true, indicates that the current character(s) to draw were joined.\n let isJoined = false;\n let lastCharX = x;\n\n // The character to the left is a wide character, drawing is owned by\n // the char at x-1\n if (cell.getWidth() === 0) {\n continue;\n }\n\n // Process any joined character ranges as needed. Because of how the\n // ranges are produced, we know that they are valid for the characters\n // and attributes of our input.\n if (joinedRanges.length > 0 && x === joinedRanges[0][0]) {\n isJoined = true;\n const range = joinedRanges.shift()!;\n\n // We already know the exact start and end column of the joined range,\n // so we get the string and width representing it directly\n\n cell = new JoinedCellData(\n this._workCell,\n line!.translateToString(true, range[0], range[1]),\n range[1] - range[0]\n );\n\n // Skip over the cells occupied by this range in the loop\n lastCharX = range[1] - 1;\n }\n\n // If the character is an overlapping char and the character to the\n // right is a space, take ownership of the cell to the right. We skip\n // this check for joined characters because their rendering likely won't\n // yield the same result as rendering the last character individually.\n if (!isJoined && this._isOverlapping(cell)) {\n // If the character is overlapping, we want to force a re-render on every\n // frame. This is specifically to work around the case where two\n // overlaping chars `a` and `b` are adjacent, the cursor is moved to b and a\n // space is added. Without this, the first half of `b` would never\n // get removed, and `a` would not re-render because it thinks it's\n // already in the correct state.\n // this._state.cache[x][y] = OVERLAP_OWNED_CHAR_DATA;\n if (lastCharX < line!.length - 1 && line!.getCodePoint(lastCharX + 1) === NULL_CELL_CODE) {\n // patch width to 2\n cell.content &= ~Content.WIDTH_MASK;\n cell.content |= 2 << Content.WIDTH_SHIFT;\n // this._clearChar(x + 1, y);\n // The overlapping char's char data will force a clear and render when the\n // overlapping char is no longer to the left of the character and also when\n // the space changes to another character.\n // this._state.cache[x + 1][y] = OVERLAP_OWNED_CHAR_DATA;\n }\n }\n\n callback(\n cell,\n x,\n y\n );\n\n x = lastCharX;\n }\n }\n }\n\n /**\n * Draws the background for a specified range of columns. Tries to batch adjacent cells of the\n * same color together to reduce draw calls.\n */\n private _drawBackground(firstRow: number, lastRow: number): void {\n const ctx = this._ctx;\n const cols = this._bufferService.cols;\n let startX: number = 0;\n let startY: number = 0;\n let prevFillStyle: string | null = null;\n\n ctx.save();\n\n this._forEachCell(firstRow, lastRow, null, (cell, x, y) => {\n // libvte and xterm both draw the background (but not foreground) of invisible characters,\n // so we should too.\n let nextFillStyle = null; // null represents default background color\n\n if (cell.isInverse()) {\n if (cell.isFgDefault()) {\n nextFillStyle = this._colors.foreground.css;\n } else if (cell.isFgRGB()) {\n nextFillStyle = `rgb(${AttributeData.toColorRGB(cell.getFgColor()).join(',')})`;\n } else {\n nextFillStyle = this._colors.ansi[cell.getFgColor()].css;\n }\n } else if (cell.isBgRGB()) {\n nextFillStyle = `rgb(${AttributeData.toColorRGB(cell.getBgColor()).join(',')})`;\n } else if (cell.isBgPalette()) {\n nextFillStyle = this._colors.ansi[cell.getBgColor()].css;\n }\n\n if (prevFillStyle === null) {\n // This is either the first iteration, or the default background was set. Either way, we\n // don't need to draw anything.\n startX = x;\n startY = y;\n }\n\n if (y !== startY) {\n // our row changed, draw the previous row\n ctx.fillStyle = prevFillStyle ? prevFillStyle : '';\n this._fillCells(startX, startY, cols - startX, 1);\n startX = x;\n startY = y;\n } else if (prevFillStyle !== nextFillStyle) {\n // our color changed, draw the previous characters in this row\n ctx.fillStyle = prevFillStyle ? prevFillStyle : '';\n this._fillCells(startX, startY, x - startX, 1);\n startX = x;\n startY = y;\n }\n\n prevFillStyle = nextFillStyle;\n });\n\n // flush the last color we encountered\n if (prevFillStyle !== null) {\n ctx.fillStyle = prevFillStyle;\n this._fillCells(startX, startY, cols - startX, 1);\n }\n\n ctx.restore();\n }\n\n private _drawForeground(firstRow: number, lastRow: number): void {\n this._forEachCell(firstRow, lastRow, this._characterJoinerRegistry, (cell, x, y) => {\n if (cell.isInvisible()) {\n return;\n }\n this._drawChars(cell, x, y);\n if (cell.isUnderline()) {\n this._ctx.save();\n\n if (cell.isInverse()) {\n if (cell.isBgDefault()) {\n this._ctx.fillStyle = this._colors.background.css;\n } else if (cell.isBgRGB()) {\n this._ctx.fillStyle = `rgb(${AttributeData.toColorRGB(cell.getBgColor()).join(',')})`;\n } else {\n let bg = cell.getBgColor();\n if (this._optionsService.options.drawBoldTextInBrightColors && cell.isBold() && bg < 8) {\n bg += 8;\n }\n this._ctx.fillStyle = this._colors.ansi[bg].css;\n }\n } else {\n if (cell.isFgDefault()) {\n this._ctx.fillStyle = this._colors.foreground.css;\n } else if (cell.isFgRGB()) {\n this._ctx.fillStyle = `rgb(${AttributeData.toColorRGB(cell.getFgColor()).join(',')})`;\n } else {\n let fg = cell.getFgColor();\n if (this._optionsService.options.drawBoldTextInBrightColors && cell.isBold() && fg < 8) {\n fg += 8;\n }\n this._ctx.fillStyle = this._colors.ansi[fg].css;\n }\n }\n\n this._fillBottomLineAtCells(x, y, cell.getWidth());\n this._ctx.restore();\n }\n });\n }\n\n public onGridChanged(firstRow: number, lastRow: number): void {\n // Resize has not been called yet\n if (this._state.cache.length === 0) {\n return;\n }\n\n if (this._charAtlas) {\n this._charAtlas.beginFrame();\n }\n\n this._clearCells(0, firstRow, this._bufferService.cols, lastRow - firstRow + 1);\n this._drawBackground(firstRow, lastRow);\n this._drawForeground(firstRow, lastRow);\n }\n\n public onOptionsChanged(): void {\n this._setTransparency(this._optionsService.options.allowTransparency);\n }\n\n /**\n * Whether a character is overlapping to the next cell.\n */\n private _isOverlapping(cell: ICellData): boolean {\n // Only single cell characters can be overlapping, rendering issues can\n // occur without this check\n if (cell.getWidth() !== 1) {\n return false;\n }\n\n // We assume that any ascii character will not overlap\n if (cell.getCode() < 256) {\n return false;\n }\n\n const chars = cell.getChars();\n\n // Deliver from cache if available\n if (this._characterOverlapCache.hasOwnProperty(chars)) {\n return this._characterOverlapCache[chars];\n }\n\n // Setup the font\n this._ctx.save();\n this._ctx.font = this._characterFont;\n\n // Measure the width of the character, but Math.floor it\n // because that is what the renderer does when it calculates\n // the character dimensions we are comparing against\n const overlaps = Math.floor(this._ctx.measureText(chars).width) > this._characterWidth;\n\n // Restore the original context\n this._ctx.restore();\n\n // Cache and return\n this._characterOverlapCache[chars] = overlaps;\n return overlaps;\n }\n\n /**\n * Clear the charcater at the cell specified.\n * @param x The column of the char.\n * @param y The row of the char.\n */\n // private _clearChar(x: number, y: number): void {\n // let colsToClear = 1;\n // // Clear the adjacent character if it was wide\n // const state = this._state.cache[x][y];\n // if (state && state[CHAR_DATA_WIDTH_INDEX] === 2) {\n // colsToClear = 2;\n // }\n // this.clearCells(x, y, colsToClear, 1);\n // }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nexport class GridCache {\n public cache: (T | undefined)[][];\n\n public constructor() {\n this.cache = [];\n }\n\n public resize(width: number, height: number): void {\n for (let x = 0; x < width; x++) {\n if (this.cache.length <= x) {\n this.cache.push([]);\n }\n for (let y = this.cache[x].length; y < height; y++) {\n this.cache[x].push(undefined);\n }\n this.cache[x].length = height;\n }\n this.cache.length = width;\n }\n\n public clear(): void {\n for (let x = 0; x < this.cache.length; x++) {\n for (let y = 0; y < this.cache[x].length; y++) {\n this.cache[x][y] = undefined;\n }\n }\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { DIM_OPACITY, INVERTED_DEFAULT_COLOR } from 'browser/renderer/atlas/Constants';\nimport { IGlyphIdentifier, ICharAtlasConfig } from 'browser/renderer/atlas/Types';\nimport { BaseCharAtlas } from 'browser/renderer/atlas/BaseCharAtlas';\nimport { DEFAULT_ANSI_COLORS } from 'browser/ColorManager';\nimport { LRUMap } from 'browser/renderer/atlas/LRUMap';\nimport { isFirefox, isSafari } from 'common/Platform';\nimport { IColor } from 'browser/Types';\nimport { throwIfFalsy } from 'browser/renderer/RendererUtils';\nimport { color } from 'browser/Color';\n\n// In practice we're probably never going to exhaust a texture this large. For debugging purposes,\n// however, it can be useful to set this to a really tiny value, to verify that LRU eviction works.\nconst TEXTURE_WIDTH = 1024;\nconst TEXTURE_HEIGHT = 1024;\n\nconst TRANSPARENT_COLOR = {\n css: 'rgba(0, 0, 0, 0)',\n rgba: 0\n};\n\n// Drawing to the cache is expensive: If we have to draw more than this number of glyphs to the\n// cache in a single frame, give up on trying to cache anything else, and try to finish the current\n// frame ASAP.\n//\n// This helps to limit the amount of damage a program can do when it would otherwise thrash the\n// cache.\nconst FRAME_CACHE_DRAW_LIMIT = 100;\n\n/**\n * The number of milliseconds to wait before generating the ImageBitmap, this is to debounce/batch\n * the operation as window.createImageBitmap is asynchronous.\n */\nconst GLYPH_BITMAP_COMMIT_DELAY = 100;\n\ninterface IGlyphCacheValue {\n index: number;\n isEmpty: boolean;\n inBitmap: boolean;\n}\n\nexport function getGlyphCacheKey(glyph: IGlyphIdentifier): number {\n // Note that this only returns a valid key when code < 256\n // Layout:\n // 0b00000000000000000000000000000001: italic (1)\n // 0b00000000000000000000000000000010: dim (1)\n // 0b00000000000000000000000000000100: bold (1)\n // 0b00000000000000000000111111111000: fg (9)\n // 0b00000000000111111111000000000000: bg (9)\n // 0b00011111111000000000000000000000: code (8)\n // 0b11100000000000000000000000000000: unused (3)\n return glyph.code << 21 | glyph.bg << 12 | glyph.fg << 3 | (glyph.bold ? 0 : 4) + (glyph.dim ? 0 : 2) + (glyph.italic ? 0 : 1);\n}\n\nexport class DynamicCharAtlas extends BaseCharAtlas {\n // An ordered map that we're using to keep track of where each glyph is in the atlas texture.\n // It's ordered so that we can determine when to remove the old entries.\n private _cacheMap: LRUMap;\n\n // The texture that the atlas is drawn to\n private _cacheCanvas: HTMLCanvasElement;\n private _cacheCtx: CanvasRenderingContext2D;\n\n // A temporary context that glyphs are drawn to before being transfered to the atlas.\n private _tmpCtx: CanvasRenderingContext2D;\n\n // The number of characters stored in the atlas by width/height\n private _width: number;\n private _height: number;\n\n private _drawToCacheCount: number = 0;\n\n // An array of glyph keys that are waiting on the bitmap to be generated.\n private _glyphsWaitingOnBitmap: IGlyphCacheValue[] = [];\n\n // The timeout that is used to batch bitmap generation so it's not requested for every new glyph.\n private _bitmapCommitTimeout: number | null = null;\n\n // The bitmap to draw from, this is much faster on other browsers than others.\n private _bitmap: ImageBitmap | null = null;\n\n constructor(document: Document, private _config: ICharAtlasConfig) {\n super();\n this._cacheCanvas = document.createElement('canvas');\n this._cacheCanvas.width = TEXTURE_WIDTH;\n this._cacheCanvas.height = TEXTURE_HEIGHT;\n // The canvas needs alpha because we use clearColor to convert the background color to alpha.\n // It might also contain some characters with transparent backgrounds if allowTransparency is\n // set.\n this._cacheCtx = throwIfFalsy(this._cacheCanvas.getContext('2d', {alpha: true}));\n\n const tmpCanvas = document.createElement('canvas');\n tmpCanvas.width = this._config.scaledCharWidth;\n tmpCanvas.height = this._config.scaledCharHeight;\n this._tmpCtx = throwIfFalsy(tmpCanvas.getContext('2d', {alpha: this._config.allowTransparency}));\n\n this._width = Math.floor(TEXTURE_WIDTH / this._config.scaledCharWidth);\n this._height = Math.floor(TEXTURE_HEIGHT / this._config.scaledCharHeight);\n const capacity = this._width * this._height;\n this._cacheMap = new LRUMap(capacity);\n this._cacheMap.prealloc(capacity);\n\n // This is useful for debugging\n // document.body.appendChild(this._cacheCanvas);\n }\n\n public dispose(): void {\n if (this._bitmapCommitTimeout !== null) {\n window.clearTimeout(this._bitmapCommitTimeout);\n this._bitmapCommitTimeout = null;\n }\n }\n\n public beginFrame(): void {\n this._drawToCacheCount = 0;\n }\n\n public draw(\n ctx: CanvasRenderingContext2D,\n glyph: IGlyphIdentifier,\n x: number,\n y: number\n ): boolean {\n // Space is always an empty cell, special case this as it's so common\n if (glyph.code === 32) {\n return true;\n }\n\n // Exit early for uncachable glyphs\n if (!this._canCache(glyph)) {\n return false;\n }\n\n const glyphKey = getGlyphCacheKey(glyph);\n const cacheValue = this._cacheMap.get(glyphKey);\n if (cacheValue !== null && cacheValue !== undefined) {\n this._drawFromCache(ctx, cacheValue, x, y);\n return true;\n } else if (this._drawToCacheCount < FRAME_CACHE_DRAW_LIMIT) {\n let index;\n if (this._cacheMap.size < this._cacheMap.capacity) {\n index = this._cacheMap.size;\n } else {\n // we're out of space, so our call to set will delete this item\n index = this._cacheMap.peek()!.index;\n }\n const cacheValue = this._drawToCache(glyph, index);\n this._cacheMap.set(glyphKey, cacheValue);\n this._drawFromCache(ctx, cacheValue, x, y);\n return true;\n }\n return false;\n }\n\n private _canCache(glyph: IGlyphIdentifier): boolean {\n // Only cache ascii and extended characters for now, to be safe. In the future, we could do\n // something more complicated to determine the expected width of a character.\n //\n // If we switch the renderer over to webgl at some point, we may be able to use blending modes\n // to draw overlapping glyphs from the atlas:\n // https://github.com/servo/webrender/issues/464#issuecomment-255632875\n // https://webglfundamentals.org/webgl/lessons/webgl-text-texture.html\n return glyph.code < 256;\n }\n\n private _toCoordinateX(index: number): number {\n return (index % this._width) * this._config.scaledCharWidth;\n }\n\n private _toCoordinateY(index: number): number {\n return Math.floor(index / this._width) * this._config.scaledCharHeight;\n }\n\n private _drawFromCache(\n ctx: CanvasRenderingContext2D,\n cacheValue: IGlyphCacheValue,\n x: number,\n y: number\n ): void {\n // We don't actually need to do anything if this is whitespace.\n if (cacheValue.isEmpty) {\n return;\n }\n const cacheX = this._toCoordinateX(cacheValue.index);\n const cacheY = this._toCoordinateY(cacheValue.index);\n ctx.drawImage(\n cacheValue.inBitmap ? this._bitmap! : this._cacheCanvas,\n cacheX,\n cacheY,\n this._config.scaledCharWidth,\n this._config.scaledCharHeight,\n x,\n y,\n this._config.scaledCharWidth,\n this._config.scaledCharHeight\n );\n }\n\n private _getColorFromAnsiIndex(idx: number): IColor {\n if (idx < this._config.colors.ansi.length) {\n return this._config.colors.ansi[idx];\n }\n return DEFAULT_ANSI_COLORS[idx];\n }\n\n private _getBackgroundColor(glyph: IGlyphIdentifier): IColor {\n if (this._config.allowTransparency) {\n // The background color might have some transparency, so we need to render it as fully\n // transparent in the atlas. Otherwise we'd end up drawing the transparent background twice\n // around the anti-aliased edges of the glyph, and it would look too dark.\n return TRANSPARENT_COLOR;\n } else if (glyph.bg === INVERTED_DEFAULT_COLOR) {\n return this._config.colors.foreground;\n } else if (glyph.bg < 256) {\n return this._getColorFromAnsiIndex(glyph.bg);\n }\n return this._config.colors.background;\n }\n\n private _getForegroundColor(glyph: IGlyphIdentifier): IColor {\n if (glyph.fg === INVERTED_DEFAULT_COLOR) {\n return color.opaque(this._config.colors.background);\n } else if (glyph.fg < 256) {\n // 256 color support\n return this._getColorFromAnsiIndex(glyph.fg);\n }\n return this._config.colors.foreground;\n }\n\n // TODO: We do this (or something similar) in multiple places. We should split this off\n // into a shared function.\n private _drawToCache(glyph: IGlyphIdentifier, index: number): IGlyphCacheValue {\n this._drawToCacheCount++;\n\n this._tmpCtx.save();\n\n // draw the background\n const backgroundColor = this._getBackgroundColor(glyph);\n // Use a 'copy' composite operation to clear any existing glyph out of _tmpCtxWithAlpha, regardless of\n // transparency in backgroundColor\n this._tmpCtx.globalCompositeOperation = 'copy';\n this._tmpCtx.fillStyle = backgroundColor.css;\n this._tmpCtx.fillRect(0, 0, this._config.scaledCharWidth, this._config.scaledCharHeight);\n this._tmpCtx.globalCompositeOperation = 'source-over';\n\n // draw the foreground/glyph\n const fontWeight = glyph.bold ? this._config.fontWeightBold : this._config.fontWeight;\n const fontStyle = glyph.italic ? 'italic' : '';\n this._tmpCtx.font =\n `${fontStyle} ${fontWeight} ${this._config.fontSize * this._config.devicePixelRatio}px ${this._config.fontFamily}`;\n this._tmpCtx.textBaseline = 'middle';\n\n this._tmpCtx.fillStyle = this._getForegroundColor(glyph).css;\n\n // Apply alpha to dim the character\n if (glyph.dim) {\n this._tmpCtx.globalAlpha = DIM_OPACITY;\n }\n // Draw the character\n this._tmpCtx.fillText(glyph.chars, 0, this._config.scaledCharHeight / 2);\n this._tmpCtx.restore();\n\n // clear the background from the character to avoid issues with drawing over the previous\n // character if it extends past it's bounds\n const imageData = this._tmpCtx.getImageData(\n 0, 0, this._config.scaledCharWidth, this._config.scaledCharHeight\n );\n let isEmpty = false;\n if (!this._config.allowTransparency) {\n isEmpty = clearColor(imageData, backgroundColor);\n }\n\n // copy the data from imageData to _cacheCanvas\n const x = this._toCoordinateX(index);\n const y = this._toCoordinateY(index);\n // putImageData doesn't do any blending, so it will overwrite any existing cache entry for us\n this._cacheCtx.putImageData(imageData, x, y);\n\n // Add the glyph and queue it to the bitmap (if the browser supports it)\n const cacheValue = {\n index,\n isEmpty,\n inBitmap: false\n };\n this._addGlyphToBitmap(cacheValue);\n\n return cacheValue;\n }\n\n private _addGlyphToBitmap(cacheValue: IGlyphCacheValue): void {\n // Support is patchy for createImageBitmap at the moment, pass a canvas back\n // if support is lacking as drawImage works there too. Firefox is also\n // included here as ImageBitmap appears both buggy and has horrible\n // performance (tested on v55).\n if (!('createImageBitmap' in window) || isFirefox || isSafari) {\n return;\n }\n\n // Add the glyph to the queue\n this._glyphsWaitingOnBitmap.push(cacheValue);\n\n // Check if bitmap generation timeout already exists\n if (this._bitmapCommitTimeout !== null) {\n return;\n }\n\n this._bitmapCommitTimeout = window.setTimeout(() => this._generateBitmap(), GLYPH_BITMAP_COMMIT_DELAY);\n }\n\n private _generateBitmap(): void {\n const glyphsMovingToBitmap = this._glyphsWaitingOnBitmap;\n this._glyphsWaitingOnBitmap = [];\n window.createImageBitmap(this._cacheCanvas).then(bitmap => {\n // Set bitmap\n this._bitmap = bitmap;\n\n // Mark all new glyphs as in bitmap, excluding glyphs that came in after\n // the bitmap was requested\n for (let i = 0; i < glyphsMovingToBitmap.length; i++) {\n const value = glyphsMovingToBitmap[i];\n // It doesn't matter if the value was already evicted, it will be\n // released from memory after this block if so.\n value.inBitmap = true;\n }\n });\n this._bitmapCommitTimeout = null;\n }\n}\n\n// This is used for debugging the renderer, just swap out `new DynamicCharAtlas` with\n// `new NoneCharAtlas`.\nexport class NoneCharAtlas extends BaseCharAtlas {\n constructor(document: Document, config: ICharAtlasConfig) {\n super();\n }\n\n public draw(\n ctx: CanvasRenderingContext2D,\n glyph: IGlyphIdentifier,\n x: number,\n y: number\n ): boolean {\n return false;\n }\n}\n\n/**\n * Makes a partiicular rgb color in an ImageData completely transparent.\n * @returns True if the result is \"empty\", meaning all pixels are fully transparent.\n */\nfunction clearColor(imageData: ImageData, color: IColor): boolean {\n let isEmpty = true;\n const r = color.rgba >>> 24;\n const g = color.rgba >>> 16 & 0xFF;\n const b = color.rgba >>> 8 & 0xFF;\n for (let offset = 0; offset < imageData.data.length; offset += 4) {\n if (imageData.data[offset] === r &&\n imageData.data[offset + 1] === g &&\n imageData.data[offset + 2] === b) {\n imageData.data[offset + 3] = 0;\n } else {\n isEmpty = false;\n }\n }\n return isEmpty;\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { IGlyphIdentifier } from 'browser/renderer/atlas/Types';\nimport { IDisposable } from 'common/Types';\n\nexport abstract class BaseCharAtlas implements IDisposable {\n private _didWarmUp: boolean = false;\n\n public dispose(): void { }\n\n /**\n * Perform any work needed to warm the cache before it can be used. May be called multiple times.\n * Implement _doWarmUp instead if you only want to get called once.\n */\n public warmUp(): void {\n if (!this._didWarmUp) {\n this._doWarmUp();\n this._didWarmUp = true;\n }\n }\n\n /**\n * Perform any work needed to warm the cache before it can be used. Used by the default\n * implementation of warmUp(), and will only be called once.\n */\n protected _doWarmUp(): void { }\n\n /**\n * Called when we start drawing a new frame.\n *\n * TODO: We rely on this getting called by TextRenderLayer. This should really be called by\n * Renderer instead, but we need to make Renderer the source-of-truth for the char atlas, instead\n * of BaseRenderLayer.\n */\n public beginFrame(): void { }\n\n /**\n * May be called before warmUp finishes, however it is okay for the implementation to\n * do nothing and return false in that case.\n *\n * @param ctx Where to draw the character onto.\n * @param glyph Information about what to draw\n * @param x The position on the context to start drawing at\n * @param y The position on the context to start drawing at\n * @returns The success state. True if we drew the character.\n */\n public abstract draw(\n ctx: CanvasRenderingContext2D,\n glyph: IGlyphIdentifier,\n x: number,\n y: number\n ): boolean;\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { IColor, IColorContrastCache } from 'browser/Types';\n\nexport class ColorContrastCache implements IColorContrastCache {\n private _color: { [bg: number]: { [fg: number]: IColor | null | undefined } | undefined } = {};\n private _rgba: { [bg: number]: { [fg: number]: string | null | undefined } | undefined } = {};\n\n public clear(): void {\n this._color = {};\n this._rgba = {};\n }\n\n public setCss(bg: number, fg: number, value: string | null): void {\n if (!this._rgba[bg]) {\n this._rgba[bg] = {};\n }\n this._rgba[bg]![fg] = value;\n }\n\n public getCss(bg: number, fg: number): string | null | undefined {\n return this._rgba[bg] ? this._rgba[bg]![fg] : undefined;\n }\n\n public setColor(bg: number, fg: number, value: IColor | null): void {\n if (!this._color[bg]) {\n this._color[bg] = {};\n }\n this._color[bg]![fg] = value;\n }\n\n public getColor(bg: number, fg: number): IColor | null | undefined {\n return this._color[bg] ? this._color[bg]![fg] : undefined;\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\ninterface ILinkedListNode {\n prev: ILinkedListNode | null;\n next: ILinkedListNode | null;\n key: number | null;\n value: T | null;\n}\n\nexport class LRUMap {\n private _map: { [key: number]: ILinkedListNode } = {};\n private _head: ILinkedListNode | null = null;\n private _tail: ILinkedListNode | null = null;\n private _nodePool: ILinkedListNode[] = [];\n public size: number = 0;\n\n constructor(public capacity: number) { }\n\n private _unlinkNode(node: ILinkedListNode): void {\n const prev = node.prev;\n const next = node.next;\n if (node === this._head) {\n this._head = next;\n }\n if (node === this._tail) {\n this._tail = prev;\n }\n if (prev !== null) {\n prev.next = next;\n }\n if (next !== null) {\n next.prev = prev;\n }\n }\n\n private _appendNode(node: ILinkedListNode): void {\n const tail = this._tail;\n if (tail !== null) {\n tail.next = node;\n }\n node.prev = tail;\n node.next = null;\n this._tail = node;\n if (this._head === null) {\n this._head = node;\n }\n }\n\n /**\n * Preallocate a bunch of linked-list nodes. Allocating these nodes ahead of time means that\n * they're more likely to live next to each other in memory, which seems to improve performance.\n *\n * Each empty object only consumes about 60 bytes of memory, so this is pretty cheap, even for\n * large maps.\n */\n public prealloc(count: number): void {\n const nodePool = this._nodePool;\n for (let i = 0; i < count; i++) {\n nodePool.push({\n prev: null,\n next: null,\n key: null,\n value: null\n });\n }\n }\n\n public get(key: number): T | null {\n // This is unsafe: We're assuming our keyspace doesn't overlap with Object.prototype. However,\n // it's faster than calling hasOwnProperty, and in our case, it would never overlap.\n const node = this._map[key];\n if (node !== undefined) {\n this._unlinkNode(node);\n this._appendNode(node);\n return node.value;\n }\n return null;\n }\n\n /**\n * Gets a value from a key without marking it as the most recently used item.\n */\n public peekValue(key: number): T | null {\n const node = this._map[key];\n if (node !== undefined) {\n return node.value;\n }\n return null;\n }\n\n public peek(): T | null {\n const head = this._head;\n return head === null ? null : head.value;\n }\n\n public set(key: number, value: T): void {\n // This is unsafe: See note above.\n let node = this._map[key];\n if (node !== undefined) {\n // already exists, we just need to mutate it and move it to the end of the list\n node = this._map[key];\n this._unlinkNode(node);\n node.value = value;\n } else if (this.size >= this.capacity) {\n // we're out of space: recycle the head node, move it to the tail\n node = this._head!;\n this._unlinkNode(node);\n delete this._map[node.key!];\n node.key = key;\n node.value = value;\n this._map[key] = node;\n } else {\n // make a new element\n const nodePool = this._nodePool;\n if (nodePool.length > 0) {\n // use a preallocated node if we can\n node = nodePool.pop()!;\n node.key = key;\n node.value = value;\n } else {\n node = {\n prev: null,\n next: null,\n key,\n value\n };\n }\n this._map[key] = node;\n this.size++;\n }\n this._appendNode(node);\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { IRenderDimensions } from 'browser/renderer/Types';\nimport { BaseRenderLayer } from 'browser/renderer/BaseRenderLayer';\nimport { IColorSet } from 'browser/Types';\nimport { IBufferService, IOptionsService } from 'common/services/Services';\n\ninterface ISelectionState {\n start?: [number, number];\n end?: [number, number];\n columnSelectMode?: boolean;\n ydisp?: number;\n}\n\nexport class SelectionRenderLayer extends BaseRenderLayer {\n private _state!: ISelectionState;\n\n constructor(\n container: HTMLElement,\n zIndex: number,\n colors: IColorSet,\n rendererId: number,\n readonly bufferService: IBufferService,\n readonly optionsService: IOptionsService\n ) {\n super(container, 'selection', zIndex, true, colors, rendererId, bufferService, optionsService);\n this._clearState();\n }\n\n private _clearState(): void {\n this._state = {\n start: undefined,\n end: undefined,\n columnSelectMode: undefined,\n ydisp: undefined\n };\n }\n\n public resize(dim: IRenderDimensions): void {\n super.resize(dim);\n // Resizing the canvas discards the contents of the canvas so clear state\n this._clearState();\n }\n\n public reset(): void {\n if (this._state.start && this._state.end) {\n this._clearState();\n this._clearAll();\n }\n }\n\n public onSelectionChanged(start: [number, number], end: [number, number], columnSelectMode: boolean): void {\n // Selection has not changed\n if (!this._didStateChange(start, end, columnSelectMode, this._bufferService.buffer.ydisp)) {\n return;\n }\n\n // Remove all selections\n this._clearAll();\n\n // Selection does not exist\n if (!start || !end) {\n this._clearState();\n return;\n }\n\n // Translate from buffer position to viewport position\n const viewportStartRow = start[1] - this._bufferService.buffer.ydisp;\n const viewportEndRow = end[1] - this._bufferService.buffer.ydisp;\n const viewportCappedStartRow = Math.max(viewportStartRow, 0);\n const viewportCappedEndRow = Math.min(viewportEndRow, this._bufferService.rows - 1);\n\n // No need to draw the selection\n if (viewportCappedStartRow >= this._bufferService.rows || viewportCappedEndRow < 0) {\n return;\n }\n\n this._ctx.fillStyle = this._colors.selection.css;\n\n if (columnSelectMode) {\n const startCol = start[0];\n const width = end[0] - startCol;\n const height = viewportCappedEndRow - viewportCappedStartRow + 1;\n this._fillCells(startCol, viewportCappedStartRow, width, height);\n } else {\n // Draw first row\n const startCol = viewportStartRow === viewportCappedStartRow ? start[0] : 0;\n const startRowEndCol = viewportCappedStartRow === viewportCappedEndRow ? end[0] : this._bufferService.cols;\n this._fillCells(startCol, viewportCappedStartRow, startRowEndCol - startCol, 1);\n\n // Draw middle rows\n const middleRowsCount = Math.max(viewportCappedEndRow - viewportCappedStartRow - 1, 0);\n this._fillCells(0, viewportCappedStartRow + 1, this._bufferService.cols, middleRowsCount);\n\n // Draw final row\n if (viewportCappedStartRow !== viewportCappedEndRow) {\n // Only draw viewportEndRow if it's not the same as viewportStartRow\n const endCol = viewportEndRow === viewportCappedEndRow ? end[0] : this._bufferService.cols;\n this._fillCells(0, viewportCappedEndRow, endCol, 1);\n }\n }\n\n // Save state for next render\n this._state.start = [start[0], start[1]];\n this._state.end = [end[0], end[1]];\n this._state.columnSelectMode = columnSelectMode;\n this._state.ydisp = this._bufferService.buffer.ydisp;\n }\n\n private _didStateChange(start: [number, number], end: [number, number], columnSelectMode: boolean, ydisp: number): boolean {\n return !this._areCoordinatesEqual(start, this._state.start) ||\n !this._areCoordinatesEqual(end, this._state.end) ||\n columnSelectMode !== this._state.columnSelectMode ||\n ydisp !== this._state.ydisp;\n }\n\n private _areCoordinatesEqual(coord1: [number, number] | undefined, coord2: [number, number] | undefined): boolean {\n if (!coord1 || !coord2) {\n return false;\n }\n\n return coord1[0] === coord2[0] && coord1[1] === coord2[1];\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { IRenderDimensions, IRequestRefreshRowsEvent } from 'browser/renderer/Types';\nimport { BaseRenderLayer } from 'browser/renderer/BaseRenderLayer';\nimport { ICellData } from 'common/Types';\nimport { CellData } from 'common/buffer/CellData';\nimport { IColorSet } from 'browser/Types';\nimport { IBufferService, IOptionsService, ICoreService } from 'common/services/Services';\nimport { IEventEmitter } from 'common/EventEmitter';\nimport { ICoreBrowserService } from 'browser/services/Services';\n\ninterface ICursorState {\n x: number;\n y: number;\n isFocused: boolean;\n style: string;\n width: number;\n}\n\n/**\n * The time between cursor blinks.\n */\nconst BLINK_INTERVAL = 600;\n\nexport class CursorRenderLayer extends BaseRenderLayer {\n private _state: ICursorState;\n private _cursorRenderers: {[key: string]: (x: number, y: number, cell: ICellData) => void};\n private _cursorBlinkStateManager: CursorBlinkStateManager | undefined;\n private _cell: ICellData = new CellData();\n\n constructor(\n container: HTMLElement,\n zIndex: number,\n colors: IColorSet,\n rendererId: number,\n private _onRequestRefreshRowsEvent: IEventEmitter,\n readonly bufferService: IBufferService,\n readonly optionsService: IOptionsService,\n private readonly _coreService: ICoreService,\n private readonly _coreBrowserService: ICoreBrowserService\n ) {\n super(container, 'cursor', zIndex, true, colors, rendererId, bufferService, optionsService);\n this._state = {\n x: 0,\n y: 0,\n isFocused: false,\n style: '',\n width: 0\n };\n this._cursorRenderers = {\n 'bar': this._renderBarCursor.bind(this),\n 'block': this._renderBlockCursor.bind(this),\n 'underline': this._renderUnderlineCursor.bind(this)\n };\n // TODO: Consider initial options? Maybe onOptionsChanged should be called at the end of open?\n }\n\n public resize(dim: IRenderDimensions): void {\n super.resize(dim);\n // Resizing the canvas discards the contents of the canvas so clear state\n this._state = {\n x: 0,\n y: 0,\n isFocused: false,\n style: '',\n width: 0\n };\n }\n\n public reset(): void {\n this._clearCursor();\n if (this._cursorBlinkStateManager) {\n this._cursorBlinkStateManager.dispose();\n this._cursorBlinkStateManager = undefined;\n this.onOptionsChanged();\n }\n }\n\n public onBlur(): void {\n if (this._cursorBlinkStateManager) {\n this._cursorBlinkStateManager.pause();\n }\n this._onRequestRefreshRowsEvent.fire({ start: this._bufferService.buffer.y, end: this._bufferService.buffer.y });\n }\n\n public onFocus(): void {\n if (this._cursorBlinkStateManager) {\n this._cursorBlinkStateManager.resume();\n } else {\n this._onRequestRefreshRowsEvent.fire({ start: this._bufferService.buffer.y, end: this._bufferService.buffer.y });\n }\n }\n\n public onOptionsChanged(): void {\n if (this._optionsService.options.cursorBlink) {\n if (!this._cursorBlinkStateManager) {\n this._cursorBlinkStateManager = new CursorBlinkStateManager(this._coreBrowserService.isFocused, () => {\n this._render(true);\n });\n }\n } else {\n this._cursorBlinkStateManager?.dispose();\n this._cursorBlinkStateManager = undefined;\n }\n // Request a refresh from the terminal as management of rendering is being\n // moved back to the terminal\n this._onRequestRefreshRowsEvent.fire({ start: this._bufferService.buffer.y, end: this._bufferService.buffer.y });\n }\n\n public onCursorMove(): void {\n if (this._cursorBlinkStateManager) {\n this._cursorBlinkStateManager.restartBlinkAnimation();\n }\n }\n\n public onGridChanged(startRow: number, endRow: number): void {\n if (!this._cursorBlinkStateManager || this._cursorBlinkStateManager.isPaused) {\n this._render(false);\n } else {\n this._cursorBlinkStateManager.restartBlinkAnimation();\n }\n }\n\n private _render(triggeredByAnimationFrame: boolean): void {\n // Don't draw the cursor if it's hidden\n if (!this._coreService.isCursorInitialized || this._coreService.isCursorHidden) {\n this._clearCursor();\n return;\n }\n\n const cursorY = this._bufferService.buffer.ybase + this._bufferService.buffer.y;\n const viewportRelativeCursorY = cursorY - this._bufferService.buffer.ydisp;\n\n // Don't draw the cursor if it's off-screen\n if (viewportRelativeCursorY < 0 || viewportRelativeCursorY >= this._bufferService.rows) {\n this._clearCursor();\n return;\n }\n\n this._bufferService.buffer.lines.get(cursorY)!.loadCell(this._bufferService.buffer.x, this._cell);\n if (this._cell.content === undefined) {\n return;\n }\n\n if (!this._coreBrowserService.isFocused) {\n this._clearCursor();\n this._ctx.save();\n this._ctx.fillStyle = this._colors.cursor.css;\n const cursorStyle = this._optionsService.options.cursorStyle;\n if (cursorStyle && cursorStyle !== 'block') {\n this._cursorRenderers[cursorStyle](this._bufferService.buffer.x, viewportRelativeCursorY, this._cell);\n } else {\n this._renderBlurCursor(this._bufferService.buffer.x, viewportRelativeCursorY, this._cell);\n }\n this._ctx.restore();\n this._state.x = this._bufferService.buffer.x;\n this._state.y = viewportRelativeCursorY;\n this._state.isFocused = false;\n this._state.style = cursorStyle;\n this._state.width = this._cell.getWidth();\n return;\n }\n\n // Don't draw the cursor if it's blinking\n if (this._cursorBlinkStateManager && !this._cursorBlinkStateManager.isCursorVisible) {\n this._clearCursor();\n return;\n }\n\n if (this._state) {\n // The cursor is already in the correct spot, don't redraw\n if (this._state.x === this._bufferService.buffer.x &&\n this._state.y === viewportRelativeCursorY &&\n this._state.isFocused === this._coreBrowserService.isFocused &&\n this._state.style === this._optionsService.options.cursorStyle &&\n this._state.width === this._cell.getWidth()) {\n return;\n }\n this._clearCursor();\n }\n\n this._ctx.save();\n this._cursorRenderers[this._optionsService.options.cursorStyle || 'block'](this._bufferService.buffer.x, viewportRelativeCursorY, this._cell);\n this._ctx.restore();\n\n this._state.x = this._bufferService.buffer.x;\n this._state.y = viewportRelativeCursorY;\n this._state.isFocused = false;\n this._state.style = this._optionsService.options.cursorStyle;\n this._state.width = this._cell.getWidth();\n }\n\n private _clearCursor(): void {\n if (this._state) {\n this._clearCells(this._state.x, this._state.y, this._state.width, 1);\n this._state = {\n x: 0,\n y: 0,\n isFocused: false,\n style: '',\n width: 0\n };\n }\n }\n\n private _renderBarCursor(x: number, y: number, cell: ICellData): void {\n this._ctx.save();\n this._ctx.fillStyle = this._colors.cursor.css;\n this._fillLeftLineAtCell(x, y, this._optionsService.options.cursorWidth);\n this._ctx.restore();\n }\n\n private _renderBlockCursor(x: number, y: number, cell: ICellData): void {\n this._ctx.save();\n this._ctx.fillStyle = this._colors.cursor.css;\n this._fillCells(x, y, cell.getWidth(), 1);\n this._ctx.fillStyle = this._colors.cursorAccent.css;\n this._fillCharTrueColor(cell, x, y);\n this._ctx.restore();\n }\n\n private _renderUnderlineCursor(x: number, y: number, cell: ICellData): void {\n this._ctx.save();\n this._ctx.fillStyle = this._colors.cursor.css;\n this._fillBottomLineAtCells(x, y);\n this._ctx.restore();\n }\n\n private _renderBlurCursor(x: number, y: number, cell: ICellData): void {\n this._ctx.save();\n this._ctx.strokeStyle = this._colors.cursor.css;\n this._strokeRectAtCell(x, y, cell.getWidth(), 1);\n this._ctx.restore();\n }\n}\n\nclass CursorBlinkStateManager {\n public isCursorVisible: boolean;\n\n private _animationFrame: number | undefined;\n private _blinkStartTimeout: number | undefined;\n private _blinkInterval: number | undefined;\n\n /**\n * The time at which the animation frame was restarted, this is used on the\n * next render to restart the timers so they don't need to restart the timers\n * multiple times over a short period.\n */\n private _animationTimeRestarted: number | undefined;\n\n constructor(\n isFocused: boolean,\n private _renderCallback: () => void\n ) {\n this.isCursorVisible = true;\n if (isFocused) {\n this._restartInterval();\n }\n }\n\n public get isPaused(): boolean { return !(this._blinkStartTimeout || this._blinkInterval); }\n\n public dispose(): void {\n if (this._blinkInterval) {\n window.clearInterval(this._blinkInterval);\n this._blinkInterval = undefined;\n }\n if (this._blinkStartTimeout) {\n window.clearTimeout(this._blinkStartTimeout);\n this._blinkStartTimeout = undefined;\n }\n if (this._animationFrame) {\n window.cancelAnimationFrame(this._animationFrame);\n this._animationFrame = undefined;\n }\n }\n\n public restartBlinkAnimation(): void {\n if (this.isPaused) {\n return;\n }\n // Save a timestamp so that the restart can be done on the next interval\n this._animationTimeRestarted = Date.now();\n // Force a cursor render to ensure it's visible and in the correct position\n this.isCursorVisible = true;\n if (!this._animationFrame) {\n this._animationFrame = window.requestAnimationFrame(() => {\n this._renderCallback();\n this._animationFrame = undefined;\n });\n }\n }\n\n private _restartInterval(timeToStart: number = BLINK_INTERVAL): void {\n // Clear any existing interval\n if (this._blinkInterval) {\n window.clearInterval(this._blinkInterval);\n }\n\n // Setup the initial timeout which will hide the cursor, this is done before\n // the regular interval is setup in order to support restarting the blink\n // animation in a lightweight way (without thrashing clearInterval and\n // setInterval).\n this._blinkStartTimeout = setTimeout(() => {\n // Check if another animation restart was requested while this was being\n // started\n if (this._animationTimeRestarted) {\n const time = BLINK_INTERVAL - (Date.now() - this._animationTimeRestarted);\n this._animationTimeRestarted = undefined;\n if (time > 0) {\n this._restartInterval(time);\n return;\n }\n }\n\n // Hide the cursor\n this.isCursorVisible = false;\n this._animationFrame = window.requestAnimationFrame(() => {\n this._renderCallback();\n this._animationFrame = undefined;\n });\n\n // Setup the blink interval\n this._blinkInterval = setInterval(() => {\n // Adjust the animation time if it was restarted\n if (this._animationTimeRestarted) {\n // calc time diff\n // Make restart interval do a setTimeout initially?\n const time = BLINK_INTERVAL - (Date.now() - this._animationTimeRestarted);\n this._animationTimeRestarted = undefined;\n this._restartInterval(time);\n return;\n }\n\n // Invert visibility and render\n this.isCursorVisible = !this.isCursorVisible;\n this._animationFrame = window.requestAnimationFrame(() => {\n this._renderCallback();\n this._animationFrame = undefined;\n });\n }, BLINK_INTERVAL);\n }, timeToStart);\n }\n\n public pause(): void {\n this.isCursorVisible = true;\n if (this._blinkInterval) {\n window.clearInterval(this._blinkInterval);\n this._blinkInterval = undefined;\n }\n if (this._blinkStartTimeout) {\n window.clearTimeout(this._blinkStartTimeout);\n this._blinkStartTimeout = undefined;\n }\n if (this._animationFrame) {\n window.cancelAnimationFrame(this._animationFrame);\n this._animationFrame = undefined;\n }\n }\n\n public resume(): void {\n this._animationTimeRestarted = undefined;\n this._restartInterval();\n this.restartBlinkAnimation();\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { IRenderDimensions } from 'browser/renderer/Types';\nimport { BaseRenderLayer } from './BaseRenderLayer';\nimport { INVERTED_DEFAULT_COLOR } from 'browser/renderer/atlas/Constants';\nimport { is256Color } from 'browser/renderer/atlas/CharAtlasUtils';\nimport { IColorSet, ILinkifierEvent, ILinkifier } from 'browser/Types';\nimport { IBufferService, IOptionsService } from 'common/services/Services';\n\nexport class LinkRenderLayer extends BaseRenderLayer {\n private _state: ILinkifierEvent | undefined;\n\n constructor(\n container: HTMLElement,\n zIndex: number,\n colors: IColorSet,\n rendererId: number,\n linkifier: ILinkifier,\n readonly bufferService: IBufferService,\n readonly optionsService: IOptionsService\n ) {\n super(container, 'link', zIndex, true, colors, rendererId, bufferService, optionsService);\n linkifier.onLinkHover(e => this._onLinkHover(e));\n linkifier.onLinkLeave(e => this._onLinkLeave(e));\n }\n\n public resize(dim: IRenderDimensions): void {\n super.resize(dim);\n // Resizing the canvas discards the contents of the canvas so clear state\n this._state = undefined;\n }\n\n public reset(): void {\n this._clearCurrentLink();\n }\n\n private _clearCurrentLink(): void {\n if (this._state) {\n this._clearCells(this._state.x1, this._state.y1, this._state.cols - this._state.x1, 1);\n const middleRowCount = this._state.y2 - this._state.y1 - 1;\n if (middleRowCount > 0) {\n this._clearCells(0, this._state.y1 + 1, this._state.cols, middleRowCount);\n }\n this._clearCells(0, this._state.y2, this._state.x2, 1);\n this._state = undefined;\n }\n }\n\n private _onLinkHover(e: ILinkifierEvent): void {\n if (e.fg === INVERTED_DEFAULT_COLOR) {\n this._ctx.fillStyle = this._colors.background.css;\n } else if (e.fg && is256Color(e.fg)) {\n // 256 color support\n this._ctx.fillStyle = this._colors.ansi[e.fg].css;\n } else {\n this._ctx.fillStyle = this._colors.foreground.css;\n }\n\n if (e.y1 === e.y2) {\n // Single line link\n this._fillBottomLineAtCells(e.x1, e.y1, e.x2 - e.x1);\n } else {\n // Multi-line link\n this._fillBottomLineAtCells(e.x1, e.y1, e.cols - e.x1);\n for (let y = e.y1 + 1; y < e.y2; y++) {\n this._fillBottomLineAtCells(0, y, e.cols);\n }\n this._fillBottomLineAtCells(0, e.y2, e.x2);\n }\n this._state = e;\n }\n\n private _onLinkLeave(e: ILinkifierEvent): void {\n this._clearCurrentLink();\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { ILinkifierEvent, ILinkMatcher, LinkMatcherHandler, ILinkMatcherOptions, ILinkifier, IMouseZoneManager, IMouseZone, IRegisteredLinkMatcher } from 'browser/Types';\nimport { IBufferStringIteratorResult } from 'common/buffer/Types';\nimport { EventEmitter, IEvent } from 'common/EventEmitter';\nimport { ILogService, IBufferService, IOptionsService, IUnicodeService } from 'common/services/Services';\n\n/**\n * Limit of the unwrapping line expansion (overscan) at the top and bottom\n * of the actual viewport in ASCII characters.\n * A limit of 2000 should match most sane urls.\n */\nconst OVERSCAN_CHAR_LIMIT = 2000;\n\n/**\n * The Linkifier applies links to rows shortly after they have been refreshed.\n */\nexport class Linkifier implements ILinkifier {\n /**\n * The time to wait after a row is changed before it is linkified. This prevents\n * the costly operation of searching every row multiple times, potentially a\n * huge amount of times.\n */\n protected static _timeBeforeLatency = 200;\n\n protected _linkMatchers: IRegisteredLinkMatcher[] = [];\n\n private _mouseZoneManager: IMouseZoneManager | undefined;\n private _element: HTMLElement | undefined;\n\n private _rowsTimeoutId: number | undefined;\n private _nextLinkMatcherId = 0;\n private _rowsToLinkify: { start: number | undefined, end: number | undefined };\n\n private _onLinkHover = new EventEmitter();\n public get onLinkHover(): IEvent { return this._onLinkHover.event; }\n private _onLinkLeave = new EventEmitter();\n public get onLinkLeave(): IEvent { return this._onLinkLeave.event; }\n private _onLinkTooltip = new EventEmitter();\n public get onLinkTooltip(): IEvent { return this._onLinkTooltip.event; }\n\n constructor(\n protected readonly _bufferService: IBufferService,\n private readonly _logService: ILogService,\n private readonly _optionsService: IOptionsService,\n private readonly _unicodeService: IUnicodeService\n ) {\n this._rowsToLinkify = {\n start: undefined,\n end: undefined\n };\n }\n\n /**\n * Attaches the linkifier to the DOM, enabling linkification.\n * @param mouseZoneManager The mouse zone manager to register link zones with.\n */\n public attachToDom(element: HTMLElement, mouseZoneManager: IMouseZoneManager): void {\n this._element = element;\n this._mouseZoneManager = mouseZoneManager;\n }\n\n /**\n * Queue linkification on a set of rows.\n * @param start The row to linkify from (inclusive).\n * @param end The row to linkify to (inclusive).\n */\n public linkifyRows(start: number, end: number): void {\n // Don't attempt linkify if not yet attached to DOM\n if (!this._mouseZoneManager) {\n return;\n }\n\n // Increase range to linkify\n if (this._rowsToLinkify.start === undefined || this._rowsToLinkify.end === undefined) {\n this._rowsToLinkify.start = start;\n this._rowsToLinkify.end = end;\n } else {\n this._rowsToLinkify.start = Math.min(this._rowsToLinkify.start, start);\n this._rowsToLinkify.end = Math.max(this._rowsToLinkify.end, end);\n }\n\n // Clear out any existing links on this row range\n this._mouseZoneManager.clearAll(start, end);\n\n // Restart timer\n if (this._rowsTimeoutId) {\n clearTimeout(this._rowsTimeoutId);\n }\n this._rowsTimeoutId = setTimeout(() => this._linkifyRows(), Linkifier._timeBeforeLatency);\n }\n\n /**\n * Linkifies the rows requested.\n */\n private _linkifyRows(): void {\n this._rowsTimeoutId = undefined;\n const buffer = this._bufferService.buffer;\n\n if (this._rowsToLinkify.start === undefined || this._rowsToLinkify.end === undefined) {\n this._logService.debug('_rowToLinkify was unset before _linkifyRows was called');\n return;\n }\n\n // Ensure the start row exists\n const absoluteRowIndexStart = buffer.ydisp + this._rowsToLinkify.start;\n if (absoluteRowIndexStart >= buffer.lines.length) {\n return;\n }\n\n // Invalidate bad end row values (if a resize happened)\n const absoluteRowIndexEnd = buffer.ydisp + Math.min(this._rowsToLinkify.end, this._bufferService.rows) + 1;\n\n // Iterate over the range of unwrapped content strings within start..end\n // (excluding).\n // _doLinkifyRow gets full unwrapped lines with the start row as buffer offset\n // for every matcher.\n // The unwrapping is needed to also match content that got wrapped across\n // several buffer lines. To avoid a worst case scenario where the whole buffer\n // contains just a single unwrapped string we limit this line expansion beyond\n // the viewport to +OVERSCAN_CHAR_LIMIT chars (overscan) at top and bottom.\n // This comes with the tradeoff that matches longer than OVERSCAN_CHAR_LIMIT\n // chars will not match anymore at the viewport borders.\n const overscanLineLimit = Math.ceil(OVERSCAN_CHAR_LIMIT / this._bufferService.cols);\n const iterator = this._bufferService.buffer.iterator(\n false, absoluteRowIndexStart, absoluteRowIndexEnd, overscanLineLimit, overscanLineLimit);\n while (iterator.hasNext()) {\n const lineData: IBufferStringIteratorResult = iterator.next();\n for (let i = 0; i < this._linkMatchers.length; i++) {\n this._doLinkifyRow(lineData.range.first, lineData.content, this._linkMatchers[i]);\n }\n }\n\n this._rowsToLinkify.start = undefined;\n this._rowsToLinkify.end = undefined;\n }\n\n /**\n * Registers a link matcher, allowing custom link patterns to be matched and\n * handled.\n * @param regex The regular expression to search for. Specifically, this\n * searches the textContent of the rows. You will want to use \\s to match a\n * space ' ' character for example.\n * @param handler The callback when the link is called.\n * @param options Options for the link matcher.\n * @return The ID of the new matcher, this can be used to deregister.\n */\n public registerLinkMatcher(regex: RegExp, handler: LinkMatcherHandler, options: ILinkMatcherOptions = {}): number {\n if (!handler) {\n throw new Error('handler must be defined');\n }\n const matcher: IRegisteredLinkMatcher = {\n id: this._nextLinkMatcherId++,\n regex,\n handler,\n matchIndex: options.matchIndex,\n validationCallback: options.validationCallback,\n hoverTooltipCallback: options.tooltipCallback,\n hoverLeaveCallback: options.leaveCallback,\n willLinkActivate: options.willLinkActivate,\n priority: options.priority || 0\n };\n this._addLinkMatcherToList(matcher);\n return matcher.id;\n }\n\n /**\n * Inserts a link matcher to the list in the correct position based on the\n * priority of each link matcher. New link matchers of equal priority are\n * considered after older link matchers.\n * @param matcher The link matcher to be added.\n */\n private _addLinkMatcherToList(matcher: IRegisteredLinkMatcher): void {\n if (this._linkMatchers.length === 0) {\n this._linkMatchers.push(matcher);\n return;\n }\n\n for (let i = this._linkMatchers.length - 1; i >= 0; i--) {\n if (matcher.priority <= this._linkMatchers[i].priority) {\n this._linkMatchers.splice(i + 1, 0, matcher);\n return;\n }\n }\n\n this._linkMatchers.splice(0, 0, matcher);\n }\n\n /**\n * Deregisters a link matcher if it has been registered.\n * @param matcherId The link matcher's ID (returned after register)\n * @return Whether a link matcher was found and deregistered.\n */\n public deregisterLinkMatcher(matcherId: number): boolean {\n for (let i = 0; i < this._linkMatchers.length; i++) {\n if (this._linkMatchers[i].id === matcherId) {\n this._linkMatchers.splice(i, 1);\n return true;\n }\n }\n return false;\n }\n\n /**\n * Linkifies a row given a specific handler.\n * @param rowIndex The row index to linkify (absolute index).\n * @param text string content of the unwrapped row.\n * @param matcher The link matcher for this line.\n */\n private _doLinkifyRow(rowIndex: number, text: string, matcher: ILinkMatcher): void {\n // clone regex to do a global search on text\n const rex = new RegExp(matcher.regex.source, (matcher.regex.flags || '') + 'g');\n let match;\n let stringIndex = -1;\n while ((match = rex.exec(text)) !== null) {\n const uri = match[typeof matcher.matchIndex !== 'number' ? 0 : matcher.matchIndex];\n if (!uri) {\n // something matched but does not comply with the given matchIndex\n // since this is most likely a bug the regex itself we simply do nothing here\n this._logService.debug('match found without corresponding matchIndex', match, matcher);\n break;\n }\n\n // Get index, match.index is for the outer match which includes negated chars\n // therefore we cannot use match.index directly, instead we search the position\n // of the match group in text again\n // also correct regex and string search offsets for the next loop run\n stringIndex = text.indexOf(uri, stringIndex + 1);\n rex.lastIndex = stringIndex + uri.length;\n if (stringIndex < 0) {\n // invalid stringIndex (should not have happened)\n break;\n }\n\n // get the buffer index as [absolute row, col] for the match\n const bufferIndex = this._bufferService.buffer.stringIndexToBufferIndex(rowIndex, stringIndex);\n if (bufferIndex[0] < 0) {\n // invalid bufferIndex (should not have happened)\n break;\n }\n\n const line = this._bufferService.buffer.lines.get(bufferIndex[0]);\n if (!line) {\n break;\n }\n\n const attr = line.getFg(bufferIndex[1]);\n const fg = attr ? (attr >> 9) & 0x1ff : undefined;\n\n if (matcher.validationCallback) {\n matcher.validationCallback(uri, isValid => {\n // Discard link if the line has already changed\n if (this._rowsTimeoutId) {\n return;\n }\n if (isValid) {\n this._addLink(bufferIndex[1], bufferIndex[0] - this._bufferService.buffer.ydisp, uri, matcher, fg);\n }\n });\n } else {\n this._addLink(bufferIndex[1], bufferIndex[0] - this._bufferService.buffer.ydisp, uri, matcher, fg);\n }\n }\n }\n\n /**\n * Registers a link to the mouse zone manager.\n * @param x The column the link starts.\n * @param y The row the link is on.\n * @param uri The URI of the link.\n * @param matcher The link matcher for the link.\n * @param fg The link color for hover event.\n */\n private _addLink(x: number, y: number, uri: string, matcher: ILinkMatcher, fg: number | undefined): void {\n if (!this._mouseZoneManager || !this._element) {\n return;\n }\n // FIXME: get cell length from buffer to avoid mismatch after Unicode version change\n const width = this._unicodeService.getStringCellWidth(uri);\n const x1 = x % this._bufferService.cols;\n const y1 = y + Math.floor(x / this._bufferService.cols);\n let x2 = (x1 + width) % this._bufferService.cols;\n let y2 = y1 + Math.floor((x1 + width) / this._bufferService.cols);\n if (x2 === 0) {\n x2 = this._bufferService.cols;\n y2--;\n }\n\n this._mouseZoneManager.add(new MouseZone(\n x1 + 1,\n y1 + 1,\n x2 + 1,\n y2 + 1,\n e => {\n if (matcher.handler) {\n return matcher.handler(e, uri);\n }\n const newWindow = window.open();\n if (newWindow) {\n newWindow.opener = null;\n newWindow.location.href = uri;\n } else {\n console.warn('Opening link blocked as opener could not be cleared');\n }\n },\n () => {\n this._onLinkHover.fire(this._createLinkHoverEvent(x1, y1, x2, y2, fg));\n this._element!.classList.add('xterm-cursor-pointer');\n },\n e => {\n this._onLinkTooltip.fire(this._createLinkHoverEvent(x1, y1, x2, y2, fg));\n if (matcher.hoverTooltipCallback) {\n // Note that IViewportRange use 1-based coordinates to align with escape sequences such\n // as CUP which use 1,1 as the default for row/col\n matcher.hoverTooltipCallback(e, uri, { start: { x: x1, y: y1 }, end: { x: x2, y: y2 } });\n }\n },\n () => {\n this._onLinkLeave.fire(this._createLinkHoverEvent(x1, y1, x2, y2, fg));\n this._element!.classList.remove('xterm-cursor-pointer');\n if (matcher.hoverLeaveCallback) {\n matcher.hoverLeaveCallback();\n }\n },\n e => {\n if (matcher.willLinkActivate) {\n return matcher.willLinkActivate(e, uri);\n }\n return true;\n }\n ));\n }\n\n private _createLinkHoverEvent(x1: number, y1: number, x2: number, y2: number, fg: number | undefined): ILinkifierEvent {\n return { x1, y1, x2, y2, cols: this._bufferService.cols, fg };\n }\n}\n\nexport class MouseZone implements IMouseZone {\n constructor(\n public x1: number,\n public y1: number,\n public x2: number,\n public y2: number,\n public clickCallback: (e: MouseEvent) => any,\n public hoverCallback: (e: MouseEvent) => any,\n public tooltipCallback: (e: MouseEvent) => any,\n public leaveCallback: () => void,\n public willLinkActivate: (e: MouseEvent) => boolean\n ) {\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { ISelectionRedrawRequestEvent } from 'browser/selection/Types';\nimport { IBuffer } from 'common/buffer/Types';\nimport { IBufferLine, IDisposable } from 'common/Types';\nimport * as Browser from 'common/Platform';\nimport { SelectionModel } from 'browser/selection/SelectionModel';\nimport { CellData } from 'common/buffer/CellData';\nimport { EventEmitter, IEvent } from 'common/EventEmitter';\nimport { ICharSizeService, IMouseService, ISelectionService } from 'browser/services/Services';\nimport { IBufferService, IOptionsService, ICoreService } from 'common/services/Services';\nimport { getCoordsRelativeToElement } from 'browser/input/Mouse';\nimport { moveToCellSequence } from 'browser/input/MoveToCell';\n\n/**\n * The number of pixels the mouse needs to be above or below the viewport in\n * order to scroll at the maximum speed.\n */\nconst DRAG_SCROLL_MAX_THRESHOLD = 50;\n\n/**\n * The maximum scrolling speed\n */\nconst DRAG_SCROLL_MAX_SPEED = 15;\n\n/**\n * The number of milliseconds between drag scroll updates.\n */\nconst DRAG_SCROLL_INTERVAL = 50;\n\n/**\n * The maximum amount of time that can have elapsed for an alt click to move the\n * cursor.\n */\nconst ALT_CLICK_MOVE_CURSOR_TIME = 500;\n\nconst NON_BREAKING_SPACE_CHAR = String.fromCharCode(160);\nconst ALL_NON_BREAKING_SPACE_REGEX = new RegExp(NON_BREAKING_SPACE_CHAR, 'g');\n\n/**\n * Represents a position of a word on a line.\n */\ninterface IWordPosition {\n start: number;\n length: number;\n}\n\n/**\n * A selection mode, this drives how the selection behaves on mouse move.\n */\nexport const enum SelectionMode {\n NORMAL,\n WORD,\n LINE,\n COLUMN\n}\n\n/**\n * A class that manages the selection of the terminal. With help from\n * SelectionModel, SelectionService handles with all logic associated with\n * dealing with the selection, including handling mouse interaction, wide\n * characters and fetching the actual text within the selection. Rendering is\n * not handled by the SelectionService but the onRedrawRequest event is fired\n * when the selection is ready to be redrawn (on an animation frame).\n */\nexport class SelectionService implements ISelectionService {\n serviceBrand: any;\n\n protected _model: SelectionModel;\n\n /**\n * The amount to scroll every drag scroll update (depends on how far the mouse\n * drag is above or below the terminal).\n */\n private _dragScrollAmount: number = 0;\n\n /**\n * The current selection mode.\n */\n protected _activeSelectionMode: SelectionMode;\n\n /**\n * A setInterval timer that is active while the mouse is down whose callback\n * scrolls the viewport when necessary.\n */\n private _dragScrollIntervalTimer: number | undefined;\n\n /**\n * The animation frame ID used for refreshing the selection.\n */\n private _refreshAnimationFrame: number | undefined;\n\n /**\n * Whether selection is enabled.\n */\n private _enabled = true;\n\n private _mouseMoveListener: EventListener;\n private _mouseUpListener: EventListener;\n private _trimListener: IDisposable;\n private _workCell: CellData = new CellData();\n\n private _mouseDownTimeStamp: number = 0;\n\n private _onLinuxMouseSelection = new EventEmitter();\n public get onLinuxMouseSelection(): IEvent { return this._onLinuxMouseSelection.event; }\n private _onRedrawRequest = new EventEmitter();\n public get onRedrawRequest(): IEvent { return this._onRedrawRequest.event; }\n private _onSelectionChange = new EventEmitter();\n public get onSelectionChange(): IEvent { return this._onSelectionChange.event; }\n\n constructor(\n private readonly _scrollLines: (amount: number, suppressEvent: boolean) => void,\n private readonly _element: HTMLElement,\n private readonly _screenElement: HTMLElement,\n @ICharSizeService private readonly _charSizeService: ICharSizeService,\n @IBufferService private readonly _bufferService: IBufferService,\n @ICoreService private readonly _coreService: ICoreService,\n @IMouseService private readonly _mouseService: IMouseService,\n @IOptionsService private readonly _optionsService: IOptionsService\n ) {\n // Init listeners\n this._mouseMoveListener = event => this._onMouseMove(event);\n this._mouseUpListener = event => this._onMouseUp(event);\n this._coreService.onUserInput(() => {\n if (this.hasSelection) {\n this.clearSelection();\n }\n });\n this._trimListener = this._bufferService.buffer.lines.onTrim(amount => this._onTrim(amount));\n this._bufferService.buffers.onBufferActivate(e => this._onBufferActivate(e));\n\n this.enable();\n\n this._model = new SelectionModel(this._bufferService);\n this._activeSelectionMode = SelectionMode.NORMAL;\n }\n\n public dispose(): void {\n this._removeMouseDownListeners();\n }\n\n public reset(): void {\n this.clearSelection();\n }\n\n /**\n * Disables the selection manager. This is useful for when terminal mouse\n * are enabled.\n */\n public disable(): void {\n this.clearSelection();\n this._enabled = false;\n }\n\n /**\n * Enable the selection manager.\n */\n public enable(): void {\n this._enabled = true;\n }\n\n public get selectionStart(): [number, number] | undefined { return this._model.finalSelectionStart; }\n public get selectionEnd(): [number, number] | undefined { return this._model.finalSelectionEnd; }\n\n /**\n * Gets whether there is an active text selection.\n */\n public get hasSelection(): boolean {\n const start = this._model.finalSelectionStart;\n const end = this._model.finalSelectionEnd;\n if (!start || !end) {\n return false;\n }\n return start[0] !== end[0] || start[1] !== end[1];\n }\n\n /**\n * Gets the text currently selected.\n */\n public get selectionText(): string {\n const start = this._model.finalSelectionStart;\n const end = this._model.finalSelectionEnd;\n if (!start || !end) {\n return '';\n }\n\n const buffer = this._bufferService.buffer;\n const result: string[] = [];\n\n if (this._activeSelectionMode === SelectionMode.COLUMN) {\n // Ignore zero width selections\n if (start[0] === end[0]) {\n return '';\n }\n\n for (let i = start[1]; i <= end[1]; i++) {\n const lineText = buffer.translateBufferLineToString(i, true, start[0], end[0]);\n result.push(lineText);\n }\n } else {\n // Get first row\n const startRowEndCol = start[1] === end[1] ? end[0] : undefined;\n result.push(buffer.translateBufferLineToString(start[1], true, start[0], startRowEndCol));\n\n // Get middle rows\n for (let i = start[1] + 1; i <= end[1] - 1; i++) {\n const bufferLine = buffer.lines.get(i);\n const lineText = buffer.translateBufferLineToString(i, true);\n if (bufferLine && bufferLine.isWrapped) {\n result[result.length - 1] += lineText;\n } else {\n result.push(lineText);\n }\n }\n\n // Get final row\n if (start[1] !== end[1]) {\n const bufferLine = buffer.lines.get(end[1]);\n const lineText = buffer.translateBufferLineToString(end[1], true, 0, end[0]);\n if (bufferLine && bufferLine!.isWrapped) {\n result[result.length - 1] += lineText;\n } else {\n result.push(lineText);\n }\n }\n }\n\n // Format string by replacing non-breaking space chars with regular spaces\n // and joining the array into a multi-line string.\n const formattedResult = result.map(line => {\n return line.replace(ALL_NON_BREAKING_SPACE_REGEX, ' ');\n }).join(Browser.isWindows ? '\\r\\n' : '\\n');\n\n return formattedResult;\n }\n\n /**\n * Clears the current terminal selection.\n */\n public clearSelection(): void {\n this._model.clearSelection();\n this._removeMouseDownListeners();\n this.refresh();\n this._onSelectionChange.fire();\n }\n\n /**\n * Queues a refresh, redrawing the selection on the next opportunity.\n * @param isLinuxMouseSelection Whether the selection should be registered as a new\n * selection on Linux.\n */\n public refresh(isLinuxMouseSelection?: boolean): void {\n // Queue the refresh for the renderer\n if (!this._refreshAnimationFrame) {\n this._refreshAnimationFrame = window.requestAnimationFrame(() => this._refresh());\n }\n\n // If the platform is Linux and the refresh call comes from a mouse event,\n // we need to update the selection for middle click to paste selection.\n if (Browser.isLinux && isLinuxMouseSelection) {\n const selectionText = this.selectionText;\n if (selectionText.length) {\n this._onLinuxMouseSelection.fire(this.selectionText);\n }\n }\n }\n\n /**\n * Fires the refresh event, causing consumers to pick it up and redraw the\n * selection state.\n */\n private _refresh(): void {\n this._refreshAnimationFrame = undefined;\n this._onRedrawRequest.fire({\n start: this._model.finalSelectionStart,\n end: this._model.finalSelectionEnd,\n columnSelectMode: this._activeSelectionMode === SelectionMode.COLUMN\n });\n }\n\n /**\n * Checks if the current click was inside the current selection\n * @param event The mouse event\n */\n public isClickInSelection(event: MouseEvent): boolean {\n const coords = this._getMouseBufferCoords(event);\n const start = this._model.finalSelectionStart;\n const end = this._model.finalSelectionEnd;\n\n if (!start || !end || !coords) {\n return false;\n }\n\n return this._areCoordsInSelection(coords, start, end);\n }\n\n protected _areCoordsInSelection(coords: [number, number], start: [number, number], end: [number, number]): boolean {\n return (coords[1] > start[1] && coords[1] < end[1]) ||\n (start[1] === end[1] && coords[1] === start[1] && coords[0] >= start[0] && coords[0] < end[0]) ||\n (start[1] < end[1] && coords[1] === end[1] && coords[0] < end[0]) ||\n (start[1] < end[1] && coords[1] === start[1] && coords[0] >= start[0]);\n }\n\n /**\n * Selects word at the current mouse event coordinates.\n * @param event The mouse event.\n */\n public selectWordAtCursor(event: MouseEvent): void {\n const coords = this._getMouseBufferCoords(event);\n if (coords) {\n this._selectWordAt(coords, false);\n this._model.selectionEnd = undefined;\n this.refresh(true);\n }\n }\n\n /**\n * Selects all text within the terminal.\n */\n public selectAll(): void {\n this._model.isSelectAllActive = true;\n this.refresh();\n this._onSelectionChange.fire();\n }\n\n public selectLines(start: number, end: number): void {\n this._model.clearSelection();\n start = Math.max(start, 0);\n end = Math.min(end, this._bufferService.buffer.lines.length - 1);\n this._model.selectionStart = [0, start];\n this._model.selectionEnd = [this._bufferService.cols, end];\n this.refresh();\n this._onSelectionChange.fire();\n }\n\n /**\n * Handle the buffer being trimmed, adjust the selection position.\n * @param amount The amount the buffer is being trimmed.\n */\n private _onTrim(amount: number): void {\n const needsRefresh = this._model.onTrim(amount);\n if (needsRefresh) {\n this.refresh();\n }\n }\n\n /**\n * Gets the 0-based [x, y] buffer coordinates of the current mouse event.\n * @param event The mouse event.\n */\n private _getMouseBufferCoords(event: MouseEvent): [number, number] | undefined {\n const coords = this._mouseService.getCoords(event, this._screenElement, this._bufferService.cols, this._bufferService.rows, true);\n if (!coords) {\n return undefined;\n }\n\n // Convert to 0-based\n coords[0]--;\n coords[1]--;\n\n // Convert viewport coords to buffer coords\n coords[1] += this._bufferService.buffer.ydisp;\n return coords;\n }\n\n /**\n * Gets the amount the viewport should be scrolled based on how far out of the\n * terminal the mouse is.\n * @param event The mouse event.\n */\n private _getMouseEventScrollAmount(event: MouseEvent): number {\n let offset = getCoordsRelativeToElement(event, this._screenElement)[1];\n const terminalHeight = this._bufferService.rows * Math.ceil(this._charSizeService.height * this._optionsService.options.lineHeight);\n if (offset >= 0 && offset <= terminalHeight) {\n return 0;\n }\n if (offset > terminalHeight) {\n offset -= terminalHeight;\n }\n\n offset = Math.min(Math.max(offset, -DRAG_SCROLL_MAX_THRESHOLD), DRAG_SCROLL_MAX_THRESHOLD);\n offset /= DRAG_SCROLL_MAX_THRESHOLD;\n return (offset / Math.abs(offset)) + Math.round(offset * (DRAG_SCROLL_MAX_SPEED - 1));\n }\n\n /**\n * Returns whether the selection manager should force selection, regardless of\n * whether the terminal is in mouse events mode.\n * @param event The mouse event.\n */\n public shouldForceSelection(event: MouseEvent): boolean {\n if (Browser.isMac) {\n return event.altKey && this._optionsService.options.macOptionClickForcesSelection;\n }\n\n return event.shiftKey;\n }\n\n /**\n * Handles te mousedown event, setting up for a new selection.\n * @param event The mousedown event.\n */\n public onMouseDown(event: MouseEvent): void {\n this._mouseDownTimeStamp = event.timeStamp;\n // If we have selection, we want the context menu on right click even if the\n // terminal is in mouse mode.\n if (event.button === 2 && this.hasSelection) {\n return;\n }\n\n // Only action the primary button\n if (event.button !== 0) {\n return;\n }\n\n // Allow selection when using a specific modifier key, even when disabled\n if (!this._enabled) {\n if (!this.shouldForceSelection(event)) {\n return;\n }\n\n // Don't send the mouse down event to the current process, we want to select\n event.stopPropagation();\n }\n\n // Tell the browser not to start a regular selection\n event.preventDefault();\n\n // Reset drag scroll state\n this._dragScrollAmount = 0;\n\n if (this._enabled && event.shiftKey) {\n this._onIncrementalClick(event);\n } else {\n if (event.detail === 1) {\n this._onSingleClick(event);\n } else if (event.detail === 2) {\n this._onDoubleClick(event);\n } else if (event.detail === 3) {\n this._onTripleClick(event);\n }\n }\n\n this._addMouseDownListeners();\n this.refresh(true);\n }\n\n /**\n * Adds listeners when mousedown is triggered.\n */\n private _addMouseDownListeners(): void {\n // Listen on the document so that dragging outside of viewport works\n if (this._screenElement.ownerDocument) {\n this._screenElement.ownerDocument.addEventListener('mousemove', this._mouseMoveListener);\n this._screenElement.ownerDocument.addEventListener('mouseup', this._mouseUpListener);\n }\n this._dragScrollIntervalTimer = window.setInterval(() => this._dragScroll(), DRAG_SCROLL_INTERVAL);\n }\n\n /**\n * Removes the listeners that are registered when mousedown is triggered.\n */\n private _removeMouseDownListeners(): void {\n if (this._screenElement.ownerDocument) {\n this._screenElement.ownerDocument.removeEventListener('mousemove', this._mouseMoveListener);\n this._screenElement.ownerDocument.removeEventListener('mouseup', this._mouseUpListener);\n }\n clearInterval(this._dragScrollIntervalTimer);\n this._dragScrollIntervalTimer = undefined;\n }\n\n /**\n * Performs an incremental click, setting the selection end position to the mouse\n * position.\n * @param event The mouse event.\n */\n private _onIncrementalClick(event: MouseEvent): void {\n if (this._model.selectionStart) {\n this._model.selectionEnd = this._getMouseBufferCoords(event);\n }\n }\n\n /**\n * Performs a single click, resetting relevant state and setting the selection\n * start position.\n * @param event The mouse event.\n */\n private _onSingleClick(event: MouseEvent): void {\n this._model.selectionStartLength = 0;\n this._model.isSelectAllActive = false;\n this._activeSelectionMode = this.shouldColumnSelect(event) ? SelectionMode.COLUMN : SelectionMode.NORMAL;\n\n // Initialize the new selection\n this._model.selectionStart = this._getMouseBufferCoords(event);\n if (!this._model.selectionStart) {\n return;\n }\n this._model.selectionEnd = undefined;\n\n // Ensure the line exists\n const line = this._bufferService.buffer.lines.get(this._model.selectionStart[1]);\n if (!line) {\n return;\n }\n\n // Return early if the click event is not in the buffer (eg. in scroll bar)\n if (line.length === this._model.selectionStart[0]) {\n return;\n }\n\n // If the mouse is over the second half of a wide character, adjust the\n // selection to cover the whole character\n if (line.hasWidth(this._model.selectionStart[0]) === 0) {\n this._model.selectionStart[0]++;\n }\n }\n\n /**\n * Performs a double click, selecting the current work.\n * @param event The mouse event.\n */\n private _onDoubleClick(event: MouseEvent): void {\n const coords = this._getMouseBufferCoords(event);\n if (coords) {\n this._activeSelectionMode = SelectionMode.WORD;\n this._selectWordAt(coords, true);\n }\n }\n\n /**\n * Performs a triple click, selecting the current line and activating line\n * select mode.\n * @param event The mouse event.\n */\n private _onTripleClick(event: MouseEvent): void {\n const coords = this._getMouseBufferCoords(event);\n if (coords) {\n this._activeSelectionMode = SelectionMode.LINE;\n this._selectLineAt(coords[1]);\n }\n }\n\n /**\n * Returns whether the selection manager should operate in column select mode\n * @param event the mouse or keyboard event\n */\n public shouldColumnSelect(event: KeyboardEvent | MouseEvent): boolean {\n return event.altKey && !(Browser.isMac && this._optionsService.options.macOptionClickForcesSelection);\n }\n\n /**\n * Handles the mousemove event when the mouse button is down, recording the\n * end of the selection and refreshing the selection.\n * @param event The mousemove event.\n */\n private _onMouseMove(event: MouseEvent): void {\n // If the mousemove listener is active it means that a selection is\n // currently being made, we should stop propagation to prevent mouse events\n // to be sent to the pty.\n event.stopImmediatePropagation();\n\n // Do nothing if there is no selection start, this can happen if the first\n // click in the terminal is an incremental click\n if (!this._model.selectionStart) {\n return;\n }\n\n // Record the previous position so we know whether to redraw the selection\n // at the end.\n const previousSelectionEnd = this._model.selectionEnd ? [this._model.selectionEnd[0], this._model.selectionEnd[1]] : null;\n\n // Set the initial selection end based on the mouse coordinates\n this._model.selectionEnd = this._getMouseBufferCoords(event);\n if (!this._model.selectionEnd) {\n this.refresh(true);\n return;\n }\n\n // Select the entire line if line select mode is active.\n if (this._activeSelectionMode === SelectionMode.LINE) {\n if (this._model.selectionEnd[1] < this._model.selectionStart[1]) {\n this._model.selectionEnd[0] = 0;\n } else {\n this._model.selectionEnd[0] = this._bufferService.cols;\n }\n } else if (this._activeSelectionMode === SelectionMode.WORD) {\n this._selectToWordAt(this._model.selectionEnd);\n }\n\n // Determine the amount of scrolling that will happen.\n this._dragScrollAmount = this._getMouseEventScrollAmount(event);\n\n // If the cursor was above or below the viewport, make sure it's at the\n // start or end of the viewport respectively. This should only happen when\n // NOT in column select mode.\n if (this._activeSelectionMode !== SelectionMode.COLUMN) {\n if (this._dragScrollAmount > 0) {\n this._model.selectionEnd[0] = this._bufferService.cols;\n } else if (this._dragScrollAmount < 0) {\n this._model.selectionEnd[0] = 0;\n }\n }\n\n // If the character is a wide character include the cell to the right in the\n // selection. Note that selections at the very end of the line will never\n // have a character.\n const buffer = this._bufferService.buffer;\n if (this._model.selectionEnd[1] < buffer.lines.length) {\n const line = buffer.lines.get(this._model.selectionEnd[1]);\n if (line && line.hasWidth(this._model.selectionEnd[0]) === 0) {\n this._model.selectionEnd[0]++;\n }\n }\n\n // Only draw here if the selection changes.\n if (!previousSelectionEnd ||\n previousSelectionEnd[0] !== this._model.selectionEnd[0] ||\n previousSelectionEnd[1] !== this._model.selectionEnd[1]) {\n this.refresh(true);\n }\n }\n\n /**\n * The callback that occurs every DRAG_SCROLL_INTERVAL ms that does the\n * scrolling of the viewport.\n */\n private _dragScroll(): void {\n if (!this._model.selectionEnd || !this._model.selectionStart) {\n return;\n }\n if (this._dragScrollAmount) {\n this._scrollLines(this._dragScrollAmount, false);\n // Re-evaluate selection\n // If the cursor was above or below the viewport, make sure it's at the\n // start or end of the viewport respectively. This should only happen when\n // NOT in column select mode.\n const buffer = this._bufferService.buffer;\n if (this._dragScrollAmount > 0) {\n if (this._activeSelectionMode !== SelectionMode.COLUMN) {\n this._model.selectionEnd[0] = this._bufferService.cols;\n }\n this._model.selectionEnd[1] = Math.min(buffer.ydisp + this._bufferService.rows, buffer.lines.length - 1);\n } else {\n if (this._activeSelectionMode !== SelectionMode.COLUMN) {\n this._model.selectionEnd[0] = 0;\n }\n this._model.selectionEnd[1] = buffer.ydisp;\n }\n this.refresh();\n }\n }\n\n /**\n * Handles the mouseup event, removing the mousedown listeners.\n * @param event The mouseup event.\n */\n private _onMouseUp(event: MouseEvent): void {\n const timeElapsed = event.timeStamp - this._mouseDownTimeStamp;\n\n this._removeMouseDownListeners();\n\n if (this.selectionText.length <= 1 && timeElapsed < ALT_CLICK_MOVE_CURSOR_TIME) {\n if (event.altKey && this._bufferService.buffer.ybase === this._bufferService.buffer.ydisp) {\n const coordinates = this._mouseService.getCoords(\n event,\n this._element,\n this._bufferService.cols,\n this._bufferService.rows,\n false\n );\n if (coordinates && coordinates[0] !== undefined && coordinates[1] !== undefined) {\n const sequence = moveToCellSequence(coordinates[0] - 1, coordinates[1] - 1, this._bufferService, this._coreService.decPrivateModes.applicationCursorKeys);\n this._coreService.triggerDataEvent(sequence, true);\n }\n }\n } else if (this.hasSelection) {\n this._onSelectionChange.fire();\n }\n }\n\n private _onBufferActivate(e: {activeBuffer: IBuffer, inactiveBuffer: IBuffer}): void {\n this.clearSelection();\n // Only adjust the selection on trim, shiftElements is rarely used (only in\n // reverseIndex) and delete in a splice is only ever used when the same\n // number of elements was just added. Given this is could actually be\n // beneficial to leave the selection as is for these cases.\n this._trimListener.dispose();\n this._trimListener = e.activeBuffer.lines.onTrim(amount => this._onTrim(amount));\n }\n\n /**\n * Converts a viewport column to the character index on the buffer line, the\n * latter takes into account wide characters.\n * @param coords The coordinates to find the 2 index for.\n */\n private _convertViewportColToCharacterIndex(bufferLine: IBufferLine, coords: [number, number]): number {\n let charIndex = coords[0];\n for (let i = 0; coords[0] >= i; i++) {\n const length = bufferLine.loadCell(i, this._workCell).getChars().length;\n if (this._workCell.getWidth() === 0) {\n // Wide characters aren't included in the line string so decrement the\n // index so the index is back on the wide character.\n charIndex--;\n } else if (length > 1 && coords[0] !== i) {\n // Emojis take up multiple characters, so adjust accordingly. For these\n // we don't want ot include the character at the column as we're\n // returning the start index in the string, not the end index.\n charIndex += length - 1;\n }\n }\n return charIndex;\n }\n\n public setSelection(col: number, row: number, length: number): void {\n this._model.clearSelection();\n this._removeMouseDownListeners();\n this._model.selectionStart = [col, row];\n this._model.selectionStartLength = length;\n this.refresh();\n }\n\n /**\n * Gets positional information for the word at the coordinated specified.\n * @param coords The coordinates to get the word at.\n */\n private _getWordAt(coords: [number, number], allowWhitespaceOnlySelection: boolean, followWrappedLinesAbove: boolean = true, followWrappedLinesBelow: boolean = true): IWordPosition | undefined {\n // Ensure coords are within viewport (eg. not within scroll bar)\n if (coords[0] >= this._bufferService.cols) {\n return undefined;\n }\n\n const buffer = this._bufferService.buffer;\n const bufferLine = buffer.lines.get(coords[1]);\n if (!bufferLine) {\n return undefined;\n }\n\n const line = buffer.translateBufferLineToString(coords[1], false);\n\n // Get actual index, taking into consideration wide characters\n let startIndex = this._convertViewportColToCharacterIndex(bufferLine, coords);\n let endIndex = startIndex;\n\n // Record offset to be used later\n const charOffset = coords[0] - startIndex;\n let leftWideCharCount = 0;\n let rightWideCharCount = 0;\n let leftLongCharOffset = 0;\n let rightLongCharOffset = 0;\n\n if (line.charAt(startIndex) === ' ') {\n // Expand until non-whitespace is hit\n while (startIndex > 0 && line.charAt(startIndex - 1) === ' ') {\n startIndex--;\n }\n while (endIndex < line.length && line.charAt(endIndex + 1) === ' ') {\n endIndex++;\n }\n } else {\n // Expand until whitespace is hit. This algorithm works by scanning left\n // and right from the starting position, keeping both the index format\n // (line) and the column format (bufferLine) in sync. When a wide\n // character is hit, it is recorded and the column index is adjusted.\n let startCol = coords[0];\n let endCol = coords[0];\n\n // Consider the initial position, skip it and increment the wide char\n // variable\n if (bufferLine.getWidth(startCol) === 0) {\n leftWideCharCount++;\n startCol--;\n }\n if (bufferLine.getWidth(endCol) === 2) {\n rightWideCharCount++;\n endCol++;\n }\n\n // Adjust the end index for characters whose length are > 1 (emojis)\n const length = bufferLine.getString(endCol).length;\n if (length > 1) {\n rightLongCharOffset += length - 1;\n endIndex += length - 1;\n }\n\n // Expand the string in both directions until a space is hit\n while (startCol > 0 && startIndex > 0 && !this._isCharWordSeparator(bufferLine.loadCell(startCol - 1, this._workCell))) {\n bufferLine.loadCell(startCol - 1, this._workCell);\n const length = this._workCell.getChars().length;\n if (this._workCell.getWidth() === 0) {\n // If the next character is a wide char, record it and skip the column\n leftWideCharCount++;\n startCol--;\n } else if (length > 1) {\n // If the next character's string is longer than 1 char (eg. emoji),\n // adjust the index\n leftLongCharOffset += length - 1;\n startIndex -= length - 1;\n }\n startIndex--;\n startCol--;\n }\n while (endCol < bufferLine.length && endIndex + 1 < line.length && !this._isCharWordSeparator(bufferLine.loadCell(endCol + 1, this._workCell))) {\n bufferLine.loadCell(endCol + 1, this._workCell);\n const length = this._workCell.getChars().length;\n if (this._workCell.getWidth() === 2) {\n // If the next character is a wide char, record it and skip the column\n rightWideCharCount++;\n endCol++;\n } else if (length > 1) {\n // If the next character's string is longer than 1 char (eg. emoji),\n // adjust the index\n rightLongCharOffset += length - 1;\n endIndex += length - 1;\n }\n endIndex++;\n endCol++;\n }\n }\n\n // Incremenet the end index so it is at the start of the next character\n endIndex++;\n\n // Calculate the start _column_, converting the the string indexes back to\n // column coordinates.\n let start =\n startIndex // The index of the selection's start char in the line string\n + charOffset // The difference between the initial char's column and index\n - leftWideCharCount // The number of wide chars left of the initial char\n + leftLongCharOffset; // The number of additional chars left of the initial char added by columns with strings longer than 1 (emojis)\n\n // Calculate the length in _columns_, converting the the string indexes back\n // to column coordinates.\n let length = Math.min(this._bufferService.cols, // Disallow lengths larger than the terminal cols\n endIndex // The index of the selection's end char in the line string\n - startIndex // The index of the selection's start char in the line string\n + leftWideCharCount // The number of wide chars left of the initial char\n + rightWideCharCount // The number of wide chars right of the initial char (inclusive)\n - leftLongCharOffset // The number of additional chars left of the initial char added by columns with strings longer than 1 (emojis)\n - rightLongCharOffset); // The number of additional chars right of the initial char (inclusive) added by columns with strings longer than 1 (emojis)\n\n if (!allowWhitespaceOnlySelection && line.slice(startIndex, endIndex).trim() === '') {\n return undefined;\n }\n\n // Recurse upwards if the line is wrapped and the word wraps to the above line\n if (followWrappedLinesAbove) {\n if (start === 0 && bufferLine.getCodePoint(0) !== 32 /*' '*/) {\n const previousBufferLine = buffer.lines.get(coords[1] - 1);\n if (previousBufferLine && bufferLine.isWrapped && previousBufferLine.getCodePoint(this._bufferService.cols - 1) !== 32 /*' '*/) {\n const previousLineWordPosition = this._getWordAt([this._bufferService.cols - 1, coords[1] - 1], false, true, false);\n if (previousLineWordPosition) {\n const offset = this._bufferService.cols - previousLineWordPosition.start;\n start -= offset;\n length += offset;\n }\n }\n }\n }\n\n // Recurse downwards if the line is wrapped and the word wraps to the next line\n if (followWrappedLinesBelow) {\n if (start + length === this._bufferService.cols && bufferLine.getCodePoint(this._bufferService.cols - 1) !== 32 /*' '*/) {\n const nextBufferLine = buffer.lines.get(coords[1] + 1);\n if (nextBufferLine && nextBufferLine.isWrapped && nextBufferLine.getCodePoint(0) !== 32 /*' '*/) {\n const nextLineWordPosition = this._getWordAt([0, coords[1] + 1], false, false, true);\n if (nextLineWordPosition) {\n length += nextLineWordPosition.length;\n }\n }\n }\n }\n\n return { start, length };\n }\n\n /**\n * Selects the word at the coordinates specified.\n * @param coords The coordinates to get the word at.\n * @param allowWhitespaceOnlySelection If whitespace should be selected\n */\n protected _selectWordAt(coords: [number, number], allowWhitespaceOnlySelection: boolean): void {\n const wordPosition = this._getWordAt(coords, allowWhitespaceOnlySelection);\n if (wordPosition) {\n // Adjust negative start value\n while (wordPosition.start < 0) {\n wordPosition.start += this._bufferService.cols;\n coords[1]--;\n }\n this._model.selectionStart = [wordPosition.start, coords[1]];\n this._model.selectionStartLength = wordPosition.length;\n }\n }\n\n /**\n * Sets the selection end to the word at the coordinated specified.\n * @param coords The coordinates to get the word at.\n */\n private _selectToWordAt(coords: [number, number]): void {\n const wordPosition = this._getWordAt(coords, true);\n if (wordPosition) {\n let endRow = coords[1];\n\n // Adjust negative start value\n while (wordPosition.start < 0) {\n wordPosition.start += this._bufferService.cols;\n endRow--;\n }\n\n // Adjust wrapped length value, this only needs to happen when values are reversed as in that\n // case we're interested in the start of the word, not the end\n if (!this._model.areSelectionValuesReversed()) {\n while (wordPosition.start + wordPosition.length > this._bufferService.cols) {\n wordPosition.length -= this._bufferService.cols;\n endRow++;\n }\n }\n\n this._model.selectionEnd = [this._model.areSelectionValuesReversed() ? wordPosition.start : wordPosition.start + wordPosition.length, endRow];\n }\n }\n\n /**\n * Gets whether the character is considered a word separator by the select\n * word logic.\n * @param char The character to check.\n */\n private _isCharWordSeparator(cell: CellData): boolean {\n // Zero width characters are never separators as they are always to the\n // right of wide characters\n if (cell.getWidth() === 0) {\n return false;\n }\n return this._optionsService.options.wordSeparator.indexOf(cell.getChars()) >= 0;\n }\n\n /**\n * Selects the line specified.\n * @param line The line index.\n */\n protected _selectLineAt(line: number): void {\n const wrappedRange = this._bufferService.buffer.getWrappedRangeForLine(line);\n this._model.selectionStart = [0, wrappedRange.first];\n this._model.selectionEnd = [this._bufferService.cols, wrappedRange.last];\n this._model.selectionStartLength = 0;\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { IBufferService } from 'common/services/Services';\n\n/**\n * Represents a selection within the buffer. This model only cares about column\n * and row coordinates, not wide characters.\n */\nexport class SelectionModel {\n /**\n * Whether select all is currently active.\n */\n public isSelectAllActive: boolean = false;\n\n /**\n * The minimal length of the selection from the start position. When double\n * clicking on a word, the word will be selected which makes the selection\n * start at the start of the word and makes this variable the length.\n */\n public selectionStartLength: number = 0;\n\n /**\n * The [x, y] position the selection starts at.\n */\n public selectionStart: [number, number] | undefined;\n\n /**\n * The [x, y] position the selection ends at.\n */\n public selectionEnd: [number, number] | undefined;\n\n constructor(\n private _bufferService: IBufferService\n ) {\n }\n\n /**\n * Clears the current selection.\n */\n public clearSelection(): void {\n this.selectionStart = undefined;\n this.selectionEnd = undefined;\n this.isSelectAllActive = false;\n this.selectionStartLength = 0;\n }\n\n /**\n * The final selection start, taking into consideration select all.\n */\n public get finalSelectionStart(): [number, number] | undefined {\n if (this.isSelectAllActive) {\n return [0, 0];\n }\n\n if (!this.selectionEnd || !this.selectionStart) {\n return this.selectionStart;\n }\n\n return this.areSelectionValuesReversed() ? this.selectionEnd : this.selectionStart;\n }\n\n /**\n * The final selection end, taking into consideration select all, double click\n * word selection and triple click line selection.\n */\n public get finalSelectionEnd(): [number, number] | undefined {\n if (this.isSelectAllActive) {\n return [this._bufferService.cols, this._bufferService.buffer.ybase + this._bufferService.rows - 1];\n }\n\n if (!this.selectionStart) {\n return undefined;\n }\n\n // Use the selection start + length if the end doesn't exist or they're reversed\n if (!this.selectionEnd || this.areSelectionValuesReversed()) {\n const startPlusLength = this.selectionStart[0] + this.selectionStartLength;\n if (startPlusLength > this._bufferService.cols) {\n return [startPlusLength % this._bufferService.cols, this.selectionStart[1] + Math.floor(startPlusLength / this._bufferService.cols)];\n }\n return [startPlusLength, this.selectionStart[1]];\n }\n\n // Ensure the the word/line is selected after a double/triple click\n if (this.selectionStartLength) {\n // Select the larger of the two when start and end are on the same line\n if (this.selectionEnd[1] === this.selectionStart[1]) {\n return [Math.max(this.selectionStart[0] + this.selectionStartLength, this.selectionEnd[0]), this.selectionEnd[1]];\n }\n }\n return this.selectionEnd;\n }\n\n /**\n * Returns whether the selection start and end are reversed.\n */\n public areSelectionValuesReversed(): boolean {\n const start = this.selectionStart;\n const end = this.selectionEnd;\n if (!start || !end) {\n return false;\n }\n return start[1] > end[1] || (start[1] === end[1] && start[0] > end[0]);\n }\n\n /**\n * Handle the buffer being trimmed, adjust the selection position.\n * @param amount The amount the buffer is being trimmed.\n * @return Whether a refresh is necessary.\n */\n public onTrim(amount: number): boolean {\n // Adjust the selection position based on the trimmed amount.\n if (this.selectionStart) {\n this.selectionStart[1] -= amount;\n }\n if (this.selectionEnd) {\n this.selectionEnd[1] -= amount;\n }\n\n // The selection has moved off the buffer, clear it.\n if (this.selectionEnd && this.selectionEnd[1] < 0) {\n this.clearSelection();\n return true;\n }\n\n // If the selection start is trimmed, ensure the start column is 0.\n if (this.selectionStart && this.selectionStart[1] < 0) {\n this.selectionStart[1] = 0;\n }\n return false;\n }\n}\n","/**\n * Copyright (c) 2018 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { C0 } from 'common/data/EscapeSequences';\nimport { IBufferService } from 'common/services/Services';\n\nconst enum Direction {\n UP = 'A',\n DOWN = 'B',\n RIGHT = 'C',\n LEFT = 'D'\n}\n\n/**\n * Concatenates all the arrow sequences together.\n * Resets the starting row to an unwrapped row, moves to the requested row,\n * then moves to requested col.\n */\nexport function moveToCellSequence(targetX: number, targetY: number, bufferService: IBufferService, applicationCursor: boolean): string {\n const startX = bufferService.buffer.x;\n const startY = bufferService.buffer.y;\n\n // The alt buffer should try to navigate between rows\n if (!bufferService.buffer.hasScrollback) {\n return resetStartingRow(startX, startY, targetX, targetY, bufferService, applicationCursor) +\n moveToRequestedRow(startY, targetY, bufferService, applicationCursor) +\n moveToRequestedCol(startX, startY, targetX, targetY, bufferService, applicationCursor);\n }\n\n // Only move horizontally for the normal buffer\n let direction;\n if (startY === targetY) {\n direction = startX > targetX ? Direction.LEFT : Direction.RIGHT;\n return repeat(Math.abs(startX - targetX), sequence(direction, applicationCursor));\n }\n direction = startY > targetY ? Direction.LEFT : Direction.RIGHT;\n const rowDifference = Math.abs(startY - targetY);\n const cellsToMove = colsFromRowEnd(startY > targetY ? targetX : startX, bufferService) +\n (rowDifference - 1) * bufferService.cols + 1 /*wrap around 1 row*/ +\n colsFromRowBeginning(startY > targetY ? startX : targetX, bufferService);\n return repeat(cellsToMove, sequence(direction, applicationCursor));\n}\n\n/**\n * Find the number of cols from a row beginning to a col.\n */\nfunction colsFromRowBeginning(currX: number, bufferService: IBufferService): number {\n return currX - 1;\n}\n\n/**\n * Find the number of cols from a col to row end.\n */\nfunction colsFromRowEnd(currX: number, bufferService: IBufferService): number {\n return bufferService.cols - currX;\n}\n\n/**\n * If the initial position of the cursor is on a row that is wrapped, move the\n * cursor up to the first row that is not wrapped to have accurate vertical\n * positioning.\n */\nfunction resetStartingRow(startX: number, startY: number, targetX: number, targetY: number, bufferService: IBufferService, applicationCursor: boolean): string {\n if (moveToRequestedRow(startY, targetY, bufferService, applicationCursor).length === 0) {\n return '';\n }\n return repeat(bufferLine(\n startX, startY, startX,\n startY - wrappedRowsForRow(bufferService, startY), false, bufferService\n ).length, sequence(Direction.LEFT, applicationCursor));\n}\n\n/**\n * Using the reset starting and ending row, move to the requested row,\n * ignoring wrapped rows\n */\nfunction moveToRequestedRow(startY: number, targetY: number, bufferService: IBufferService, applicationCursor: boolean): string {\n const startRow = startY - wrappedRowsForRow(bufferService, startY);\n const endRow = targetY - wrappedRowsForRow(bufferService, targetY);\n\n const rowsToMove = Math.abs(startRow - endRow) - wrappedRowsCount(startY, targetY, bufferService);\n\n return repeat(rowsToMove, sequence(verticalDirection(startY, targetY), applicationCursor));\n}\n\n/**\n * Move to the requested col on the ending row\n */\nfunction moveToRequestedCol(startX: number, startY: number, targetX: number, targetY: number, bufferService: IBufferService, applicationCursor: boolean): string {\n let startRow;\n if (moveToRequestedRow(startY, targetY, bufferService, applicationCursor).length > 0) {\n startRow = targetY - wrappedRowsForRow(bufferService, targetY);\n } else {\n startRow = startY;\n }\n\n const endRow = targetY;\n const direction = horizontalDirection(startX, startY, targetX, targetY, bufferService, applicationCursor);\n\n return repeat(bufferLine(\n startX, startRow, targetX, endRow,\n direction === Direction.RIGHT, bufferService\n ).length, sequence(direction, applicationCursor));\n}\n\nfunction moveHorizontallyOnly(startX: number, startY: number, targetX: number, targetY: number, bufferService: IBufferService, applicationCursor: boolean): string {\n const direction = horizontalDirection(startX, startY, targetX, targetY, bufferService, applicationCursor);\n return repeat(Math.abs(startX - targetX), sequence(direction, applicationCursor));\n}\n\n/**\n * Utility functions\n */\n\n/**\n * Calculates the number of wrapped rows between the unwrapped starting and\n * ending rows. These rows need to ignored since the cursor skips over them.\n */\nfunction wrappedRowsCount(startY: number, targetY: number, bufferService: IBufferService): number {\n let wrappedRows = 0;\n const startRow = startY - wrappedRowsForRow(bufferService, startY);\n const endRow = targetY - wrappedRowsForRow(bufferService, targetY);\n\n for (let i = 0; i < Math.abs(startRow - endRow); i++) {\n const direction = verticalDirection(startY, targetY) === Direction.UP ? -1 : 1;\n const line = bufferService.buffer.lines.get(startRow + (direction * i));\n if (line && line.isWrapped) {\n wrappedRows++;\n }\n }\n\n return wrappedRows;\n}\n\n/**\n * Calculates the number of wrapped rows that make up a given row.\n * @param currentRow The row to determine how many wrapped rows make it up\n */\nfunction wrappedRowsForRow(bufferService: IBufferService, currentRow: number): number {\n let rowCount = 0;\n let line = bufferService.buffer.lines.get(currentRow);\n let lineWraps = line && line.isWrapped;\n\n while (lineWraps && currentRow >= 0 && currentRow < bufferService.rows) {\n rowCount++;\n line = bufferService.buffer.lines.get(--currentRow);\n lineWraps = line && line.isWrapped;\n }\n\n return rowCount;\n}\n\n/**\n * Direction determiners\n */\n\n/**\n * Determines if the right or left arrow is needed\n */\nfunction horizontalDirection(startX: number, startY: number, targetX: number, targetY: number, bufferService: IBufferService, applicationCursor: boolean): Direction {\n let startRow;\n if (moveToRequestedRow(targetX, targetY, bufferService, applicationCursor).length > 0) {\n startRow = targetY - wrappedRowsForRow(bufferService, targetY);\n } else {\n startRow = startY;\n }\n\n if ((startX < targetX &&\n startRow <= targetY) || // down/right or same y/right\n (startX >= targetX &&\n startRow < targetY)) { // down/left or same y/left\n return Direction.RIGHT;\n }\n return Direction.LEFT;\n}\n\n/**\n * Determines if the up or down arrow is needed\n */\nfunction verticalDirection(startY: number, targetY: number): Direction {\n return startY > targetY ? Direction.UP : Direction.DOWN;\n}\n\n/**\n * Constructs the string of chars in the buffer from a starting row and col\n * to an ending row and col\n * @param startCol The starting column position\n * @param startRow The starting row position\n * @param endCol The ending column position\n * @param endRow The ending row position\n * @param forward Direction to move\n */\nfunction bufferLine(\n startCol: number,\n startRow: number,\n endCol: number,\n endRow: number,\n forward: boolean,\n bufferService: IBufferService\n): string {\n let currentCol = startCol;\n let currentRow = startRow;\n let bufferStr = '';\n\n while (currentCol !== endCol || currentRow !== endRow) {\n currentCol += forward ? 1 : -1;\n\n if (forward && currentCol > bufferService.cols - 1) {\n bufferStr += bufferService.buffer.translateBufferLineToString(\n currentRow, false, startCol, currentCol\n );\n currentCol = 0;\n startCol = 0;\n currentRow++;\n } else if (!forward && currentCol < 0) {\n bufferStr += bufferService.buffer.translateBufferLineToString(\n currentRow, false, 0, startCol + 1\n );\n currentCol = bufferService.cols - 1;\n startCol = currentCol;\n currentRow--;\n }\n }\n\n return bufferStr + bufferService.buffer.translateBufferLineToString(\n currentRow, false, startCol, currentCol\n );\n}\n\n/**\n * Constructs the escape sequence for clicking an arrow\n * @param direction The direction to move\n */\nfunction sequence(direction: Direction, applicationCursor: boolean): string {\n const mod = applicationCursor ? 'O' : '[';\n return C0.ESC + mod + direction;\n}\n\n/**\n * Returns a string repeated a given number of times\n * Polyfill from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat\n * @param count The number of times to repeat the string\n * @param string The string that is to be repeated\n */\nfunction repeat(count: number, str: string): string {\n count = Math.floor(count);\n let rpt = '';\n for (let i = 0; i < count; i++) {\n rpt += str;\n }\n return rpt;\n}\n","/**\n * Copyright (c) 2018 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { IOptionsService } from 'common/services/Services';\nimport { ISoundService } from 'browser/services/Services';\n\nexport class SoundService implements ISoundService {\n serviceBrand: any;\n\n private static _audioContext: AudioContext;\n\n static get audioContext(): AudioContext | null {\n if (!SoundService._audioContext) {\n const audioContextCtor: typeof AudioContext = (window).AudioContext || (window).webkitAudioContext;\n if (!audioContextCtor) {\n console.warn('Web Audio API is not supported by this browser. Consider upgrading to the latest version');\n return null;\n }\n SoundService._audioContext = new audioContextCtor();\n }\n return SoundService._audioContext;\n }\n\n constructor(\n @IOptionsService private _optionsService: IOptionsService\n ) {\n }\n\n public playBellSound(): void {\n const ctx = SoundService.audioContext;\n if (!ctx) {\n return;\n }\n const bellAudioSource = ctx.createBufferSource();\n ctx.decodeAudioData(this._base64ToArrayBuffer(this._removeMimeType(this._optionsService.options.bellSound)), (buffer) => {\n bellAudioSource.buffer = buffer;\n bellAudioSource.connect(ctx.destination);\n bellAudioSource.start(0);\n });\n }\n\n private _base64ToArrayBuffer(base64: string): ArrayBuffer {\n const binaryString = window.atob(base64);\n const len = binaryString.length;\n const bytes = new Uint8Array(len);\n\n for (let i = 0; i < len; i++) {\n bytes[i] = binaryString.charCodeAt(i);\n }\n\n return bytes.buffer;\n }\n\n private _removeMimeType(dataURI: string): string {\n // Split the input to get the mime-type and the data itself\n const splitUri = dataURI.split(',');\n\n // Return only the data\n return splitUri[1];\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { Disposable } from 'common/Lifecycle';\nimport { addDisposableDomListener } from 'browser/Lifecycle';\nimport { IMouseService, ISelectionService } from 'browser/services/Services';\nimport { IMouseZoneManager, IMouseZone } from 'browser/Types';\nimport { IBufferService } from 'common/services/Services';\n\nconst HOVER_DURATION = 500;\n\n/**\n * The MouseZoneManager allows components to register zones within the terminal\n * that trigger hover and click callbacks.\n *\n * This class was intentionally made not so robust initially as the only case it\n * needed to support was single-line links which never overlap. Improvements can\n * be made in the future.\n */\nexport class MouseZoneManager extends Disposable implements IMouseZoneManager {\n private _zones: IMouseZone[] = [];\n\n private _areZonesActive: boolean = false;\n private _mouseMoveListener: (e: MouseEvent) => any;\n private _mouseLeaveListener: (e: MouseEvent) => any;\n private _clickListener: (e: MouseEvent) => any;\n\n private _tooltipTimeout: number | undefined;\n private _currentZone: IMouseZone | undefined;\n private _lastHoverCoords: [number | undefined, number | undefined] = [undefined, undefined];\n private _initialSelectionLength: number = 0;\n\n constructor(\n private readonly _element: HTMLElement,\n private readonly _screenElement: HTMLElement,\n @IBufferService private readonly _bufferService: IBufferService,\n @IMouseService private readonly _mouseService: IMouseService,\n @ISelectionService private readonly _selectionService: ISelectionService\n ) {\n super();\n\n this.register(addDisposableDomListener(this._element, 'mousedown', e => this._onMouseDown(e)));\n\n // These events are expensive, only listen to it when mouse zones are active\n this._mouseMoveListener = e => this._onMouseMove(e);\n this._mouseLeaveListener = e => this._onMouseLeave(e);\n this._clickListener = e => this._onClick(e);\n }\n\n public dispose(): void {\n super.dispose();\n this._deactivate();\n }\n\n public add(zone: IMouseZone): void {\n this._zones.push(zone);\n if (this._zones.length === 1) {\n this._activate();\n }\n }\n\n public clearAll(start?: number, end?: number): void {\n // Exit if there's nothing to clear\n if (this._zones.length === 0) {\n return;\n }\n\n // Clear all if start/end weren't set\n if (!start || !end) {\n start = 0;\n end = this._bufferService.rows - 1;\n }\n\n // Iterate through zones and clear them out if they're within the range\n for (let i = 0; i < this._zones.length; i++) {\n const zone = this._zones[i];\n if ((zone.y1 > start && zone.y1 <= end + 1) ||\n (zone.y2 > start && zone.y2 <= end + 1) ||\n (zone.y1 < start && zone.y2 > end + 1)) {\n if (this._currentZone && this._currentZone === zone) {\n this._currentZone.leaveCallback();\n this._currentZone = undefined;\n }\n this._zones.splice(i--, 1);\n }\n }\n\n // Deactivate the mouse zone manager if all the zones have been removed\n if (this._zones.length === 0) {\n this._deactivate();\n }\n }\n\n private _activate(): void {\n if (!this._areZonesActive) {\n this._areZonesActive = true;\n this._element.addEventListener('mousemove', this._mouseMoveListener);\n this._element.addEventListener('mouseleave', this._mouseLeaveListener);\n this._element.addEventListener('click', this._clickListener);\n }\n }\n\n private _deactivate(): void {\n if (this._areZonesActive) {\n this._areZonesActive = false;\n this._element.removeEventListener('mousemove', this._mouseMoveListener);\n this._element.removeEventListener('mouseleave', this._mouseLeaveListener);\n this._element.removeEventListener('click', this._clickListener);\n }\n }\n\n private _onMouseMove(e: MouseEvent): void {\n // TODO: Ideally this would only clear the hover state when the mouse moves\n // outside of the mouse zone\n if (this._lastHoverCoords[0] !== e.pageX || this._lastHoverCoords[1] !== e.pageY) {\n this._onHover(e);\n // Record the current coordinates\n this._lastHoverCoords = [e.pageX, e.pageY];\n }\n }\n\n private _onHover(e: MouseEvent): void {\n const zone = this._findZoneEventAt(e);\n\n // Do nothing if the zone is the same\n if (zone === this._currentZone) {\n return;\n }\n\n // Fire the hover end callback and cancel any existing timer if a new zone\n // is being hovered\n if (this._currentZone) {\n this._currentZone.leaveCallback();\n this._currentZone = undefined;\n if (this._tooltipTimeout) {\n clearTimeout(this._tooltipTimeout);\n }\n }\n\n // Exit if there is not zone\n if (!zone) {\n return;\n }\n this._currentZone = zone;\n\n // Trigger the hover callback\n if (zone.hoverCallback) {\n zone.hoverCallback(e);\n }\n\n // Restart the tooltip timeout\n this._tooltipTimeout = setTimeout(() => this._onTooltip(e), HOVER_DURATION);\n }\n\n private _onTooltip(e: MouseEvent): void {\n this._tooltipTimeout = undefined;\n const zone = this._findZoneEventAt(e);\n if (zone && zone.tooltipCallback) {\n zone.tooltipCallback(e);\n }\n }\n\n private _onMouseDown(e: MouseEvent): void {\n // Store current terminal selection length, to check if we're performing\n // a selection operation\n this._initialSelectionLength = this._getSelectionLength();\n\n // Ignore the event if there are no zones active\n if (!this._areZonesActive) {\n return;\n }\n\n // Find the active zone, prevent event propagation if found to prevent other\n // components from handling the mouse event.\n const zone = this._findZoneEventAt(e);\n if (zone?.willLinkActivate(e)) {\n e.preventDefault();\n e.stopImmediatePropagation();\n }\n }\n\n private _onMouseLeave(e: MouseEvent): void {\n // Fire the hover end callback and cancel any existing timer if the mouse\n // leaves the terminal element\n if (this._currentZone) {\n this._currentZone.leaveCallback();\n this._currentZone = undefined;\n if (this._tooltipTimeout) {\n clearTimeout(this._tooltipTimeout);\n }\n }\n }\n\n private _onClick(e: MouseEvent): void {\n // Find the active zone and click it if found and no selection was\n // being performed\n const zone = this._findZoneEventAt(e);\n const currentSelectionLength = this._getSelectionLength();\n\n if (zone && currentSelectionLength === this._initialSelectionLength) {\n zone.clickCallback(e);\n e.preventDefault();\n e.stopImmediatePropagation();\n }\n }\n\n private _getSelectionLength(): number {\n const selectionText = this._selectionService.selectionText;\n return selectionText ? selectionText.length : 0;\n }\n\n private _findZoneEventAt(e: MouseEvent): IMouseZone | undefined {\n const coords = this._mouseService.getCoords(e, this._screenElement, this._bufferService.cols, this._bufferService.rows);\n if (!coords) {\n return undefined;\n }\n const x = coords[0];\n const y = coords[1];\n for (let i = 0; i < this._zones.length; i++) {\n const zone = this._zones[i];\n if (zone.y1 === zone.y2) {\n // Single line link\n if (y === zone.y1 && x >= zone.x1 && x < zone.x2) {\n return zone;\n }\n } else {\n // Multi-line link\n if ((y === zone.y1 && x >= zone.x1) ||\n (y === zone.y2 && x < zone.x2) ||\n (y > zone.y1 && y < zone.y2)) {\n return zone;\n }\n }\n }\n return undefined;\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport * as Strings from './browser/LocalizableStrings';\nimport { ITerminal } from './Types';\nimport { IBuffer } from 'common/buffer/Types';\nimport { isMac } from 'common/Platform';\nimport { RenderDebouncer } from 'browser/RenderDebouncer';\nimport { addDisposableDomListener } from 'browser/Lifecycle';\nimport { Disposable } from 'common/Lifecycle';\nimport { ScreenDprMonitor } from 'browser/ScreenDprMonitor';\nimport { IRenderService } from 'browser/services/Services';\n\nconst MAX_ROWS_TO_READ = 20;\n\nconst enum BoundaryPosition {\n TOP,\n BOTTOM\n}\n\nexport class AccessibilityManager extends Disposable {\n private _accessibilityTreeRoot: HTMLElement;\n private _rowContainer: HTMLElement;\n private _rowElements: HTMLElement[];\n private _liveRegion: HTMLElement;\n private _liveRegionLineCount: number = 0;\n\n private _renderRowsDebouncer: RenderDebouncer;\n private _screenDprMonitor: ScreenDprMonitor;\n\n private _topBoundaryFocusListener: (e: FocusEvent) => void;\n private _bottomBoundaryFocusListener: (e: FocusEvent) => void;\n\n /**\n * This queue has a character pushed to it for keys that are pressed, if the\n * next character added to the terminal is equal to the key char then it is\n * not announced (added to live region) because it has already been announced\n * by the textarea event (which cannot be canceled). There are some race\n * condition cases if there is typing while data is streaming, but this covers\n * the main case of typing into the prompt and inputting the answer to a\n * question (Y/N, etc.).\n */\n private _charsToConsume: string[] = [];\n\n private _charsToAnnounce: string = '';\n\n constructor(\n private readonly _terminal: ITerminal,\n private readonly _renderService: IRenderService\n ) {\n super();\n this._accessibilityTreeRoot = document.createElement('div');\n this._accessibilityTreeRoot.classList.add('xterm-accessibility');\n\n this._rowContainer = document.createElement('div');\n this._rowContainer.classList.add('xterm-accessibility-tree');\n this._rowElements = [];\n for (let i = 0; i < this._terminal.rows; i++) {\n this._rowElements[i] = this._createAccessibilityTreeNode();\n this._rowContainer.appendChild(this._rowElements[i]);\n }\n\n this._topBoundaryFocusListener = e => this._onBoundaryFocus(e, BoundaryPosition.TOP);\n this._bottomBoundaryFocusListener = e => this._onBoundaryFocus(e, BoundaryPosition.BOTTOM);\n this._rowElements[0].addEventListener('focus', this._topBoundaryFocusListener);\n this._rowElements[this._rowElements.length - 1].addEventListener('focus', this._bottomBoundaryFocusListener);\n\n this._refreshRowsDimensions();\n this._accessibilityTreeRoot.appendChild(this._rowContainer);\n\n this._renderRowsDebouncer = new RenderDebouncer(this._renderRows.bind(this));\n this._refreshRows();\n\n this._liveRegion = document.createElement('div');\n this._liveRegion.classList.add('live-region');\n this._liveRegion.setAttribute('aria-live', 'assertive');\n this._accessibilityTreeRoot.appendChild(this._liveRegion);\n\n this._terminal.element.insertAdjacentElement('afterbegin', this._accessibilityTreeRoot);\n\n this.register(this._renderRowsDebouncer);\n this.register(this._terminal.onResize(e => this._onResize(e.rows)));\n this.register(this._terminal.onRender(e => this._refreshRows(e.start, e.end)));\n this.register(this._terminal.onScroll(() => this._refreshRows()));\n // Line feed is an issue as the prompt won't be read out after a command is run\n this.register(this._terminal.onA11yChar(char => this._onChar(char)));\n this.register(this._terminal.onLineFeed(() => this._onChar('\\n')));\n this.register(this._terminal.onA11yTab(spaceCount => this._onTab(spaceCount)));\n this.register(this._terminal.onKey(e => this._onKey(e.key)));\n this.register(this._terminal.onBlur(() => this._clearLiveRegion()));\n this.register(this._renderService.onDimensionsChange(() => this._refreshRowsDimensions()));\n\n this._screenDprMonitor = new ScreenDprMonitor();\n this.register(this._screenDprMonitor);\n this._screenDprMonitor.setListener(() => this._refreshRowsDimensions());\n // This shouldn't be needed on modern browsers but is present in case the\n // media query that drives the ScreenDprMonitor isn't supported\n this.register(addDisposableDomListener(window, 'resize', () => this._refreshRowsDimensions()));\n }\n\n public dispose(): void {\n super.dispose();\n this._terminal.element.removeChild(this._accessibilityTreeRoot);\n this._rowElements.length = 0;\n }\n\n private _onBoundaryFocus(e: FocusEvent, position: BoundaryPosition): void {\n const boundaryElement = e.target;\n const beforeBoundaryElement = this._rowElements[position === BoundaryPosition.TOP ? 1 : this._rowElements.length - 2];\n\n // Don't scroll if the buffer top has reached the end in that direction\n const posInSet = boundaryElement.getAttribute('aria-posinset');\n const lastRowPos = position === BoundaryPosition.TOP ? '1' : `${this._terminal.buffer.lines.length}`;\n if (posInSet === lastRowPos) {\n return;\n }\n\n // Don't scroll when the last focused item was not the second row (focus is going the other\n // direction)\n if (e.relatedTarget !== beforeBoundaryElement) {\n return;\n }\n\n // Remove old boundary element from array\n let topBoundaryElement: HTMLElement;\n let bottomBoundaryElement: HTMLElement;\n if (position === BoundaryPosition.TOP) {\n topBoundaryElement = boundaryElement;\n bottomBoundaryElement = this._rowElements.pop()!;\n this._rowContainer.removeChild(bottomBoundaryElement);\n } else {\n topBoundaryElement = this._rowElements.shift()!;\n bottomBoundaryElement = boundaryElement;\n this._rowContainer.removeChild(topBoundaryElement);\n }\n\n // Remove listeners from old boundary elements\n topBoundaryElement.removeEventListener('focus', this._topBoundaryFocusListener);\n bottomBoundaryElement.removeEventListener('focus', this._bottomBoundaryFocusListener);\n\n // Add new element to array/DOM\n if (position === BoundaryPosition.TOP) {\n const newElement = this._createAccessibilityTreeNode();\n this._rowElements.unshift(newElement);\n this._rowContainer.insertAdjacentElement('afterbegin', newElement);\n } else {\n const newElement = this._createAccessibilityTreeNode();\n this._rowElements.push(newElement);\n this._rowContainer.appendChild(newElement);\n }\n\n // Add listeners to new boundary elements\n this._rowElements[0].addEventListener('focus', this._topBoundaryFocusListener);\n this._rowElements[this._rowElements.length - 1].addEventListener('focus', this._bottomBoundaryFocusListener);\n\n // Scroll up\n this._terminal.scrollLines(position === BoundaryPosition.TOP ? -1 : 1);\n\n // Focus new boundary before element\n this._rowElements[position === BoundaryPosition.TOP ? 1 : this._rowElements.length - 2].focus();\n\n // Prevent the standard behavior\n e.preventDefault();\n e.stopImmediatePropagation();\n }\n\n private _onResize(rows: number): void {\n // Remove bottom boundary listener\n this._rowElements[this._rowElements.length - 1].removeEventListener('focus', this._bottomBoundaryFocusListener);\n\n // Grow rows as required\n for (let i = this._rowContainer.children.length; i < this._terminal.rows; i++) {\n this._rowElements[i] = this._createAccessibilityTreeNode();\n this._rowContainer.appendChild(this._rowElements[i]);\n }\n // Shrink rows as required\n while (this._rowElements.length > rows) {\n this._rowContainer.removeChild(this._rowElements.pop()!);\n }\n\n // Add bottom boundary listener\n this._rowElements[this._rowElements.length - 1].addEventListener('focus', this._bottomBoundaryFocusListener);\n\n this._refreshRowsDimensions();\n }\n\n private _createAccessibilityTreeNode(): HTMLElement {\n const element = document.createElement('div');\n element.setAttribute('role', 'listitem');\n element.tabIndex = -1;\n this._refreshRowDimensions(element);\n return element;\n }\n\n private _onTab(spaceCount: number): void {\n for (let i = 0; i < spaceCount; i++) {\n this._onChar(' ');\n }\n }\n\n private _onChar(char: string): void {\n if (this._liveRegionLineCount < MAX_ROWS_TO_READ + 1) {\n if (this._charsToConsume.length > 0) {\n // Have the screen reader ignore the char if it was just input\n const shiftedChar = this._charsToConsume.shift();\n if (shiftedChar !== char) {\n this._charsToAnnounce += char;\n }\n } else {\n this._charsToAnnounce += char;\n }\n\n if (char === '\\n') {\n this._liveRegionLineCount++;\n if (this._liveRegionLineCount === MAX_ROWS_TO_READ + 1) {\n this._liveRegion.textContent += Strings.tooMuchOutput;\n }\n }\n\n // Only detach/attach on mac as otherwise messages can go unaccounced\n if (isMac) {\n if (this._liveRegion.textContent && this._liveRegion.textContent.length > 0 && !this._liveRegion.parentNode) {\n setTimeout(() => {\n this._accessibilityTreeRoot.appendChild(this._liveRegion);\n }, 0);\n }\n }\n }\n }\n\n private _clearLiveRegion(): void {\n this._liveRegion.textContent = '';\n this._liveRegionLineCount = 0;\n\n // Only detach/attach on mac as otherwise messages can go unaccounced\n if (isMac) {\n if (this._liveRegion.parentNode) {\n this._accessibilityTreeRoot.removeChild(this._liveRegion);\n }\n }\n }\n\n private _onKey(keyChar: string): void {\n this._clearLiveRegion();\n this._charsToConsume.push(keyChar);\n }\n\n private _refreshRows(start?: number, end?: number): void {\n this._renderRowsDebouncer.refresh(start, end, this._terminal.rows);\n }\n\n private _renderRows(start: number, end: number): void {\n const buffer: IBuffer = this._terminal.buffer;\n const setSize = buffer.lines.length.toString();\n for (let i = start; i <= end; i++) {\n const lineData = buffer.translateBufferLineToString(buffer.ydisp + i, true);\n const posInSet = (buffer.ydisp + i + 1).toString();\n const element = this._rowElements[i];\n if (element) {\n if (lineData.length === 0) {\n element.innerHTML = ' ';\n } else {\n element.textContent = lineData;\n }\n element.setAttribute('aria-posinset', posInSet);\n element.setAttribute('aria-setsize', setSize);\n }\n }\n this._announceCharacters();\n }\n\n private _refreshRowsDimensions(): void {\n if (!this._renderService.dimensions.actualCellHeight) {\n return;\n }\n if (this._rowElements.length !== this._terminal.rows) {\n this._onResize(this._terminal.rows);\n }\n for (let i = 0; i < this._terminal.rows; i++) {\n this._refreshRowDimensions(this._rowElements[i]);\n }\n }\n\n private _refreshRowDimensions(element: HTMLElement): void {\n element.style.height = `${this._renderService.dimensions.actualCellHeight}px`;\n }\n\n private _announceCharacters(): void {\n if (this._charsToAnnounce.length === 0) {\n return;\n }\n this._liveRegion.textContent += this._charsToAnnounce;\n this._charsToAnnounce = '';\n }\n}\n","/**\n * Copyright (c) 2018 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { IRenderer, IRenderDimensions, CharacterJoinerHandler, IRequestRefreshRowsEvent } from 'browser/renderer/Types';\nimport { BOLD_CLASS, ITALIC_CLASS, CURSOR_CLASS, CURSOR_STYLE_BLOCK_CLASS, CURSOR_BLINK_CLASS, CURSOR_STYLE_BAR_CLASS, CURSOR_STYLE_UNDERLINE_CLASS, DomRendererRowFactory } from 'browser/renderer/dom/DomRendererRowFactory';\nimport { INVERTED_DEFAULT_COLOR } from 'browser/renderer/atlas/Constants';\nimport { Disposable } from 'common/Lifecycle';\nimport { IColorSet, ILinkifierEvent, ILinkifier } from 'browser/Types';\nimport { ICharSizeService } from 'browser/services/Services';\nimport { IOptionsService, IBufferService } from 'common/services/Services';\nimport { EventEmitter, IEvent } from 'common/EventEmitter';\nimport { color } from 'browser/Color';\n\nconst TERMINAL_CLASS_PREFIX = 'xterm-dom-renderer-owner-';\nconst ROW_CONTAINER_CLASS = 'xterm-rows';\nconst FG_CLASS_PREFIX = 'xterm-fg-';\nconst BG_CLASS_PREFIX = 'xterm-bg-';\nconst FOCUS_CLASS = 'xterm-focus';\nconst SELECTION_CLASS = 'xterm-selection';\n\nlet nextTerminalId = 1;\n\n/**\n * A fallback renderer for when canvas is slow. This is not meant to be\n * particularly fast or feature complete, more just stable and usable for when\n * canvas is not an option.\n */\nexport class DomRenderer extends Disposable implements IRenderer {\n private _rowFactory: DomRendererRowFactory;\n private _terminalClass: number = nextTerminalId++;\n\n private _themeStyleElement!: HTMLStyleElement;\n private _dimensionsStyleElement!: HTMLStyleElement;\n private _rowContainer: HTMLElement;\n private _rowElements: HTMLElement[] = [];\n private _selectionContainer: HTMLElement;\n\n public dimensions: IRenderDimensions;\n\n private _onRequestRefreshRows = new EventEmitter();\n public get onRequestRefreshRows(): IEvent { return this._onRequestRefreshRows.event; }\n\n constructor(\n private _colors: IColorSet,\n private readonly _element: HTMLElement,\n private readonly _screenElement: HTMLElement,\n private readonly _viewportElement: HTMLElement,\n private readonly _linkifier: ILinkifier,\n @ICharSizeService private readonly _charSizeService: ICharSizeService,\n @IOptionsService private readonly _optionsService: IOptionsService,\n @IBufferService private readonly _bufferService: IBufferService\n ) {\n super();\n\n this._rowContainer = document.createElement('div');\n this._rowContainer.classList.add(ROW_CONTAINER_CLASS);\n this._rowContainer.style.lineHeight = 'normal';\n this._rowContainer.setAttribute('aria-hidden', 'true');\n this._refreshRowElements(this._bufferService.cols, this._bufferService.rows);\n this._selectionContainer = document.createElement('div');\n this._selectionContainer.classList.add(SELECTION_CLASS);\n this._selectionContainer.setAttribute('aria-hidden', 'true');\n\n this.dimensions = {\n scaledCharWidth: 0,\n scaledCharHeight: 0,\n scaledCellWidth: 0,\n scaledCellHeight: 0,\n scaledCharLeft: 0,\n scaledCharTop: 0,\n scaledCanvasWidth: 0,\n scaledCanvasHeight: 0,\n canvasWidth: 0,\n canvasHeight: 0,\n actualCellWidth: 0,\n actualCellHeight: 0\n };\n this._updateDimensions();\n this._injectCss();\n\n this._rowFactory = new DomRendererRowFactory(document, this._optionsService, this._colors);\n\n this._element.classList.add(TERMINAL_CLASS_PREFIX + this._terminalClass);\n this._screenElement.appendChild(this._rowContainer);\n this._screenElement.appendChild(this._selectionContainer);\n\n this._linkifier.onLinkHover(e => this._onLinkHover(e));\n this._linkifier.onLinkLeave(e => this._onLinkLeave(e));\n }\n\n public dispose(): void {\n this._element.classList.remove(TERMINAL_CLASS_PREFIX + this._terminalClass);\n this._screenElement.removeChild(this._rowContainer);\n this._screenElement.removeChild(this._selectionContainer);\n this._screenElement.removeChild(this._themeStyleElement);\n this._screenElement.removeChild(this._dimensionsStyleElement);\n super.dispose();\n }\n\n private _updateDimensions(): void {\n this.dimensions.scaledCharWidth = this._charSizeService.width * window.devicePixelRatio;\n this.dimensions.scaledCharHeight = Math.ceil(this._charSizeService.height * window.devicePixelRatio);\n this.dimensions.scaledCellWidth = this.dimensions.scaledCharWidth + Math.round(this._optionsService.options.letterSpacing);\n this.dimensions.scaledCellHeight = Math.floor(this.dimensions.scaledCharHeight * this._optionsService.options.lineHeight);\n this.dimensions.scaledCharLeft = 0;\n this.dimensions.scaledCharTop = 0;\n this.dimensions.scaledCanvasWidth = this.dimensions.scaledCellWidth * this._bufferService.cols;\n this.dimensions.scaledCanvasHeight = this.dimensions.scaledCellHeight * this._bufferService.rows;\n this.dimensions.canvasWidth = Math.round(this.dimensions.scaledCanvasWidth / window.devicePixelRatio);\n this.dimensions.canvasHeight = Math.round(this.dimensions.scaledCanvasHeight / window.devicePixelRatio);\n this.dimensions.actualCellWidth = this.dimensions.canvasWidth / this._bufferService.cols;\n this.dimensions.actualCellHeight = this.dimensions.canvasHeight / this._bufferService.rows;\n\n this._rowElements.forEach(element => {\n element.style.width = `${this.dimensions.canvasWidth}px`;\n element.style.height = `${this.dimensions.actualCellHeight}px`;\n element.style.lineHeight = `${this.dimensions.actualCellHeight}px`;\n // Make sure rows don't overflow onto following row\n element.style.overflow = 'hidden';\n });\n\n if (!this._dimensionsStyleElement) {\n this._dimensionsStyleElement = document.createElement('style');\n this._screenElement.appendChild(this._dimensionsStyleElement);\n }\n\n const styles =\n `${this._terminalSelector} .${ROW_CONTAINER_CLASS} span {` +\n ` display: inline-block;` +\n ` height: 100%;` +\n ` vertical-align: top;` +\n ` width: ${this.dimensions.actualCellWidth}px` +\n `}`;\n\n this._dimensionsStyleElement.innerHTML = styles;\n\n this._selectionContainer.style.height = this._viewportElement.style.height;\n this._screenElement.style.width = `${this.dimensions.canvasWidth}px`;\n this._screenElement.style.height = `${this.dimensions.canvasHeight}px`;\n }\n\n public setColors(colors: IColorSet): void {\n this._colors = colors;\n this._injectCss();\n }\n\n private _injectCss(): void {\n if (!this._themeStyleElement) {\n this._themeStyleElement = document.createElement('style');\n this._screenElement.appendChild(this._themeStyleElement);\n }\n\n // Base CSS\n let styles =\n `${this._terminalSelector} .${ROW_CONTAINER_CLASS} {` +\n ` color: ${this._colors.foreground.css};` +\n ` background-color: ${this._colors.background.css};` +\n ` font-family: ${this._optionsService.options.fontFamily};` +\n ` font-size: ${this._optionsService.options.fontSize}px;` +\n `}`;\n // Text styles\n styles +=\n `${this._terminalSelector} span:not(.${BOLD_CLASS}) {` +\n ` font-weight: ${this._optionsService.options.fontWeight};` +\n `}` +\n `${this._terminalSelector} span.${BOLD_CLASS} {` +\n ` font-weight: ${this._optionsService.options.fontWeightBold};` +\n `}` +\n `${this._terminalSelector} span.${ITALIC_CLASS} {` +\n ` font-style: italic;` +\n `}`;\n // Blink animation\n styles +=\n `@keyframes blink_box_shadow` + `_` + this._terminalClass + ` {` +\n ` 50% {` +\n ` box-shadow: none;` +\n ` }` +\n `}`;\n styles +=\n `@keyframes blink_block` + `_` + this._terminalClass + ` {` +\n ` 0% {` +\n ` background-color: ${this._colors.cursor.css};` +\n ` color: ${this._colors.cursorAccent.css};` +\n ` }` +\n ` 50% {` +\n ` background-color: ${this._colors.cursorAccent.css};` +\n ` color: ${this._colors.cursor.css};` +\n ` }` +\n `}`;\n // Cursor\n styles +=\n `${this._terminalSelector} .${ROW_CONTAINER_CLASS}:not(.${FOCUS_CLASS}) .${CURSOR_CLASS}.${CURSOR_STYLE_BLOCK_CLASS} {` +\n ` outline: 1px solid ${this._colors.cursor.css};` +\n ` outline-offset: -1px;` +\n `}` +\n `${this._terminalSelector} .${ROW_CONTAINER_CLASS}.${FOCUS_CLASS} .${CURSOR_CLASS}.${CURSOR_BLINK_CLASS}:not(.${CURSOR_STYLE_BLOCK_CLASS}) {` +\n ` animation: blink_box_shadow` + `_` + this._terminalClass + ` 1s step-end infinite;` +\n `}` +\n `${this._terminalSelector} .${ROW_CONTAINER_CLASS}.${FOCUS_CLASS} .${CURSOR_CLASS}.${CURSOR_BLINK_CLASS}.${CURSOR_STYLE_BLOCK_CLASS} {` +\n ` animation: blink_block` + `_` + this._terminalClass + ` 1s step-end infinite;` +\n `}` +\n `${this._terminalSelector} .${ROW_CONTAINER_CLASS}.${FOCUS_CLASS} .${CURSOR_CLASS}.${CURSOR_STYLE_BLOCK_CLASS} {` +\n ` background-color: ${this._colors.cursor.css};` +\n ` color: ${this._colors.cursorAccent.css};` +\n `}` +\n `${this._terminalSelector} .${ROW_CONTAINER_CLASS} .${CURSOR_CLASS}.${CURSOR_STYLE_BAR_CLASS} {` +\n ` box-shadow: ${this._optionsService.options.cursorWidth}px 0 0 ${this._colors.cursor.css} inset;` +\n `}` +\n `${this._terminalSelector} .${ROW_CONTAINER_CLASS} .${CURSOR_CLASS}.${CURSOR_STYLE_UNDERLINE_CLASS} {` +\n ` box-shadow: 0 -1px 0 ${this._colors.cursor.css} inset;` +\n `}`;\n // Selection\n styles +=\n `${this._terminalSelector} .${SELECTION_CLASS} {` +\n ` position: absolute;` +\n ` top: 0;` +\n ` left: 0;` +\n ` z-index: 1;` +\n ` pointer-events: none;` +\n `}` +\n `${this._terminalSelector} .${SELECTION_CLASS} div {` +\n ` position: absolute;` +\n ` background-color: ${this._colors.selection.css};` +\n `}`;\n // Colors\n this._colors.ansi.forEach((c, i) => {\n styles +=\n `${this._terminalSelector} .${FG_CLASS_PREFIX}${i} { color: ${c.css}; }` +\n `${this._terminalSelector} .${BG_CLASS_PREFIX}${i} { background-color: ${c.css}; }`;\n });\n styles +=\n `${this._terminalSelector} .${FG_CLASS_PREFIX}${INVERTED_DEFAULT_COLOR} { color: ${color.opaque(this._colors.background).css}; }` +\n `${this._terminalSelector} .${BG_CLASS_PREFIX}${INVERTED_DEFAULT_COLOR} { background-color: ${this._colors.foreground.css}; }`;\n\n this._themeStyleElement.innerHTML = styles;\n }\n\n public onDevicePixelRatioChange(): void {\n this._updateDimensions();\n }\n\n private _refreshRowElements(cols: number, rows: number): void {\n // Add missing elements\n for (let i = this._rowElements.length; i <= rows; i++) {\n const row = document.createElement('div');\n this._rowContainer.appendChild(row);\n this._rowElements.push(row);\n }\n // Remove excess elements\n while (this._rowElements.length > rows) {\n this._rowContainer.removeChild(this._rowElements.pop()!);\n }\n }\n\n public onResize(cols: number, rows: number): void {\n this._refreshRowElements(cols, rows);\n this._updateDimensions();\n }\n\n public onCharSizeChanged(): void {\n this._updateDimensions();\n }\n\n public onBlur(): void {\n this._rowContainer.classList.remove(FOCUS_CLASS);\n }\n\n public onFocus(): void {\n this._rowContainer.classList.add(FOCUS_CLASS);\n }\n\n public onSelectionChanged(start: [number, number], end: [number, number], columnSelectMode: boolean): void {\n // Remove all selections\n while (this._selectionContainer.children.length) {\n this._selectionContainer.removeChild(this._selectionContainer.children[0]);\n }\n\n // Selection does not exist\n if (!start || !end) {\n return;\n }\n\n // Translate from buffer position to viewport position\n const viewportStartRow = start[1] - this._bufferService.buffer.ydisp;\n const viewportEndRow = end[1] - this._bufferService.buffer.ydisp;\n const viewportCappedStartRow = Math.max(viewportStartRow, 0);\n const viewportCappedEndRow = Math.min(viewportEndRow, this._bufferService.rows - 1);\n\n // No need to draw the selection\n if (viewportCappedStartRow >= this._bufferService.rows || viewportCappedEndRow < 0) {\n return;\n }\n\n // Create the selections\n const documentFragment = document.createDocumentFragment();\n\n if (columnSelectMode) {\n documentFragment.appendChild(\n this._createSelectionElement(viewportCappedStartRow, start[0], end[0], viewportCappedEndRow - viewportCappedStartRow + 1)\n );\n } else {\n // Draw first row\n const startCol = viewportStartRow === viewportCappedStartRow ? start[0] : 0;\n const endCol = viewportCappedStartRow === viewportCappedEndRow ? end[0] : this._bufferService.cols;\n documentFragment.appendChild(this._createSelectionElement(viewportCappedStartRow, startCol, endCol));\n // Draw middle rows\n const middleRowsCount = viewportCappedEndRow - viewportCappedStartRow - 1;\n documentFragment.appendChild(this._createSelectionElement(viewportCappedStartRow + 1, 0, this._bufferService.cols, middleRowsCount));\n // Draw final row\n if (viewportCappedStartRow !== viewportCappedEndRow) {\n // Only draw viewportEndRow if it's not the same as viewporttartRow\n const endCol = viewportEndRow === viewportCappedEndRow ? end[0] : this._bufferService.cols;\n documentFragment.appendChild(this._createSelectionElement(viewportCappedEndRow, 0, endCol));\n }\n }\n this._selectionContainer.appendChild(documentFragment);\n }\n\n /**\n * Creates a selection element at the specified position.\n * @param row The row of the selection.\n * @param colStart The start column.\n * @param colEnd The end columns.\n */\n private _createSelectionElement(row: number, colStart: number, colEnd: number, rowCount: number = 1): HTMLElement {\n const element = document.createElement('div');\n element.style.height = `${rowCount * this.dimensions.actualCellHeight}px`;\n element.style.top = `${row * this.dimensions.actualCellHeight}px`;\n element.style.left = `${colStart * this.dimensions.actualCellWidth}px`;\n element.style.width = `${this.dimensions.actualCellWidth * (colEnd - colStart)}px`;\n return element;\n }\n\n public onCursorMove(): void {\n // No-op, the cursor is drawn when rows are drawn\n }\n\n public onOptionsChanged(): void {\n // Force a refresh\n this._updateDimensions();\n this._injectCss();\n }\n\n public clear(): void {\n this._rowElements.forEach(e => e.innerHTML = '');\n }\n\n public renderRows(start: number, end: number): void {\n const cursorAbsoluteY = this._bufferService.buffer.ybase + this._bufferService.buffer.y;\n const cursorX = this._bufferService.buffer.x;\n const cursorBlink = this._optionsService.options.cursorBlink;\n\n for (let y = start; y <= end; y++) {\n const rowElement = this._rowElements[y];\n rowElement.innerHTML = '';\n\n const row = y + this._bufferService.buffer.ydisp;\n const lineData = this._bufferService.buffer.lines.get(row);\n const cursorStyle = this._optionsService.options.cursorStyle;\n rowElement.appendChild(this._rowFactory.createRow(lineData!, row === cursorAbsoluteY, cursorStyle, cursorX, cursorBlink, this.dimensions.actualCellWidth, this._bufferService.cols));\n }\n }\n\n private get _terminalSelector(): string {\n return `.${TERMINAL_CLASS_PREFIX}${this._terminalClass}`;\n }\n\n public registerCharacterJoiner(handler: CharacterJoinerHandler): number { return -1; }\n public deregisterCharacterJoiner(joinerId: number): boolean { return false; }\n\n private _onLinkHover(e: ILinkifierEvent): void {\n this._setCellUnderline(e.x1, e.x2, e.y1, e.y2, e.cols, true);\n }\n\n private _onLinkLeave(e: ILinkifierEvent): void {\n this._setCellUnderline(e.x1, e.x2, e.y1, e.y2, e.cols, false);\n }\n\n private _setCellUnderline(x: number, x2: number, y: number, y2: number, cols: number, enabled: boolean): void {\n while (x !== x2 || y !== y2) {\n const row = this._rowElements[y];\n if (!row) {\n return;\n }\n const span = row.children[x];\n if (span) {\n span.style.textDecoration = enabled ? 'underline' : 'none';\n }\n if (++x >= cols) {\n x = 0;\n y++;\n }\n }\n }\n}\n","/**\n * Copyright (c) 2018 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { IBufferLine } from 'common/Types';\nimport { INVERTED_DEFAULT_COLOR } from 'browser/renderer/atlas/Constants';\nimport { NULL_CELL_CODE, WHITESPACE_CELL_CHAR, Attributes } from 'common/buffer/Constants';\nimport { CellData } from 'common/buffer/CellData';\nimport { IOptionsService } from 'common/services/Services';\nimport { color, rgba } from 'browser/Color';\nimport { IColorSet, IColor } from 'browser/Types';\n\nexport const BOLD_CLASS = 'xterm-bold';\nexport const DIM_CLASS = 'xterm-dim';\nexport const ITALIC_CLASS = 'xterm-italic';\nexport const UNDERLINE_CLASS = 'xterm-underline';\nexport const CURSOR_CLASS = 'xterm-cursor';\nexport const CURSOR_BLINK_CLASS = 'xterm-cursor-blink';\nexport const CURSOR_STYLE_BLOCK_CLASS = 'xterm-cursor-block';\nexport const CURSOR_STYLE_BAR_CLASS = 'xterm-cursor-bar';\nexport const CURSOR_STYLE_UNDERLINE_CLASS = 'xterm-cursor-underline';\n\nexport class DomRendererRowFactory {\n private _workCell: CellData = new CellData();\n\n constructor(\n private readonly _document: Document,\n private readonly _optionsService: IOptionsService,\n private _colors: IColorSet\n ) {\n }\n\n public setColors(colors: IColorSet): void {\n this._colors = colors;\n }\n\n public createRow(lineData: IBufferLine, isCursorRow: boolean, cursorStyle: string | undefined, cursorX: number, cursorBlink: boolean, cellWidth: number, cols: number): DocumentFragment {\n const fragment = this._document.createDocumentFragment();\n\n // Find the line length first, this prevents the need to output a bunch of\n // empty cells at the end. This cannot easily be integrated into the main\n // loop below because of the colCount feature (which can be removed after we\n // properly support reflow and disallow data to go beyond the right-side of\n // the viewport).\n let lineLength = 0;\n for (let x = Math.min(lineData.length, cols) - 1; x >= 0; x--) {\n if (lineData.loadCell(x, this._workCell).getCode() !== NULL_CELL_CODE || (isCursorRow && x === cursorX)) {\n lineLength = x + 1;\n break;\n }\n }\n\n for (let x = 0; x < lineLength; x++) {\n lineData.loadCell(x, this._workCell);\n const width = this._workCell.getWidth();\n\n // The character to the left is a wide character, drawing is owned by the char at x-1\n if (width === 0) {\n continue;\n }\n\n const charElement = this._document.createElement('span');\n if (width > 1) {\n charElement.style.width = `${cellWidth * width}px`;\n }\n\n if (isCursorRow && x === cursorX) {\n charElement.classList.add(CURSOR_CLASS);\n\n if (cursorBlink) {\n charElement.classList.add(CURSOR_BLINK_CLASS);\n }\n\n switch (cursorStyle) {\n case 'bar':\n charElement.classList.add(CURSOR_STYLE_BAR_CLASS);\n break;\n case 'underline':\n charElement.classList.add(CURSOR_STYLE_UNDERLINE_CLASS);\n break;\n default:\n charElement.classList.add(CURSOR_STYLE_BLOCK_CLASS);\n break;\n }\n }\n\n if (this._workCell.isBold()) {\n charElement.classList.add(BOLD_CLASS);\n }\n\n if (this._workCell.isItalic()) {\n charElement.classList.add(ITALIC_CLASS);\n }\n\n if (this._workCell.isDim()) {\n charElement.classList.add(DIM_CLASS);\n }\n\n if (this._workCell.isUnderline()) {\n charElement.classList.add(UNDERLINE_CLASS);\n }\n\n if (this._workCell.isInvisible()) {\n charElement.textContent = WHITESPACE_CELL_CHAR;\n } else {\n charElement.textContent = this._workCell.getChars() || WHITESPACE_CELL_CHAR;\n }\n\n let fg = this._workCell.getFgColor();\n let fgColorMode = this._workCell.getFgColorMode();\n let bg = this._workCell.getBgColor();\n let bgColorMode = this._workCell.getBgColorMode();\n const isInverse = !!this._workCell.isInverse();\n if (isInverse) {\n const temp = fg;\n fg = bg;\n bg = temp;\n const temp2 = fgColorMode;\n fgColorMode = bgColorMode;\n bgColorMode = temp2;\n }\n\n // Foreground\n switch (fgColorMode) {\n case Attributes.CM_P16:\n case Attributes.CM_P256:\n if (this._workCell.isBold() && fg < 8 && this._optionsService.options.drawBoldTextInBrightColors) {\n fg += 8;\n }\n if (!this._applyMinimumContrast(charElement, this._colors.background, this._colors.ansi[fg])) {\n charElement.classList.add(`xterm-fg-${fg}`);\n }\n break;\n case Attributes.CM_RGB:\n const color = rgba.toColor(\n (fg >> 16) & 0xFF,\n (fg >> 8) & 0xFF,\n (fg ) & 0xFF\n );\n if (!this._applyMinimumContrast(charElement, this._colors.background, color)) {\n this._addStyle(charElement, `color:#${padStart(fg.toString(16), '0', 6)}`);\n }\n break;\n case Attributes.CM_DEFAULT:\n default:\n if (!this._applyMinimumContrast(charElement, this._colors.background, this._colors.foreground)) {\n if (isInverse) {\n charElement.classList.add(`xterm-fg-${INVERTED_DEFAULT_COLOR}`);\n }\n }\n }\n\n // Background\n switch (bgColorMode) {\n case Attributes.CM_P16:\n case Attributes.CM_P256:\n charElement.classList.add(`xterm-bg-${bg}`);\n break;\n case Attributes.CM_RGB:\n this._addStyle(charElement, `background-color:#${padStart(bg.toString(16), '0', 6)}`);\n break;\n case Attributes.CM_DEFAULT:\n default:\n if (isInverse) {\n charElement.classList.add(`xterm-bg-${INVERTED_DEFAULT_COLOR}`);\n }\n }\n\n fragment.appendChild(charElement);\n }\n return fragment;\n }\n\n private _applyMinimumContrast(element: HTMLElement, bg: IColor, fg: IColor): boolean {\n if (this._optionsService.options.minimumContrastRatio === 1) {\n return false;\n }\n\n // Try get from cache first\n let adjustedColor = this._colors.contrastCache.getColor(this._workCell.bg, this._workCell.fg);\n\n // Calculate and store in cache\n if (adjustedColor === undefined) {\n adjustedColor = color.ensureContrastRatio(bg, fg, this._optionsService.options.minimumContrastRatio);\n this._colors.contrastCache.setColor(this._workCell.bg, this._workCell.fg, adjustedColor ?? null);\n }\n\n if (adjustedColor) {\n this._addStyle(element, `color:${adjustedColor.css}`);\n return true;\n }\n\n return false;\n }\n\n private _addStyle(element: HTMLElement, style: string): void {\n element.setAttribute('style', `${element.getAttribute('style') || ''}${style};`);\n }\n}\n\nfunction padStart(text: string, padChar: string, length: number): string {\n while (text.length < length) {\n text = padChar + text;\n }\n return text;\n}\n","/**\n * Copyright (c) 2014 The xterm.js authors. All rights reserved.\n * Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)\n * @license MIT\n */\n\nimport { IKeyboardEvent, IKeyboardResult, KeyboardResultType } from 'common/Types';\nimport { C0 } from 'common/data/EscapeSequences';\n\n// reg + shift key mappings for digits and special chars\nconst KEYCODE_KEY_MAPPINGS: { [key: number]: [string, string]} = {\n // digits 0-9\n 48: ['0', ')'],\n 49: ['1', '!'],\n 50: ['2', '@'],\n 51: ['3', '#'],\n 52: ['4', '$'],\n 53: ['5', '%'],\n 54: ['6', '^'],\n 55: ['7', '&'],\n 56: ['8', '*'],\n 57: ['9', '('],\n\n // special chars\n 186: [';', ':'],\n 187: ['=', '+'],\n 188: [',', '<'],\n 189: ['-', '_'],\n 190: ['.', '>'],\n 191: ['/', '?'],\n 192: ['`', '~'],\n 219: ['[', '{'],\n 220: ['\\\\', '|'],\n 221: [']', '}'],\n 222: ['\\'', '\"']\n};\n\nexport function evaluateKeyboardEvent(\n ev: IKeyboardEvent,\n applicationCursorMode: boolean,\n isMac: boolean,\n macOptionIsMeta: boolean\n): IKeyboardResult {\n const result: IKeyboardResult = {\n type: KeyboardResultType.SEND_KEY,\n // Whether to cancel event propagation (NOTE: this may not be needed since the event is\n // canceled at the end of keyDown\n cancel: false,\n // The new key even to emit\n key: undefined\n };\n const modifiers = (ev.shiftKey ? 1 : 0) | (ev.altKey ? 2 : 0) | (ev.ctrlKey ? 4 : 0) | (ev.metaKey ? 8 : 0);\n switch (ev.keyCode) {\n case 0:\n if (ev.key === 'UIKeyInputUpArrow') {\n if (applicationCursorMode) {\n result.key = C0.ESC + 'OA';\n } else {\n result.key = C0.ESC + '[A';\n }\n }\n else if (ev.key === 'UIKeyInputLeftArrow') {\n if (applicationCursorMode) {\n result.key = C0.ESC + 'OD';\n } else {\n result.key = C0.ESC + '[D';\n }\n }\n else if (ev.key === 'UIKeyInputRightArrow') {\n if (applicationCursorMode) {\n result.key = C0.ESC + 'OC';\n } else {\n result.key = C0.ESC + '[C';\n }\n }\n else if (ev.key === 'UIKeyInputDownArrow') {\n if (applicationCursorMode) {\n result.key = C0.ESC + 'OB';\n } else {\n result.key = C0.ESC + '[B';\n }\n }\n break;\n case 8:\n // backspace\n if (ev.shiftKey) {\n result.key = C0.BS; // ^H\n break;\n } else if (ev.altKey) {\n result.key = C0.ESC + C0.DEL; // \\e ^?\n break;\n }\n result.key = C0.DEL; // ^?\n break;\n case 9:\n // tab\n if (ev.shiftKey) {\n result.key = C0.ESC + '[Z';\n break;\n }\n result.key = C0.HT;\n result.cancel = true;\n break;\n case 13:\n // return/enter\n result.key = C0.CR;\n result.cancel = true;\n break;\n case 27:\n // escape\n result.key = C0.ESC;\n result.cancel = true;\n break;\n case 37:\n // left-arrow\n if (ev.metaKey) {\n break;\n }\n if (modifiers) {\n result.key = C0.ESC + '[1;' + (modifiers + 1) + 'D';\n // HACK: Make Alt + left-arrow behave like Ctrl + left-arrow: move one word backwards\n // http://unix.stackexchange.com/a/108106\n // macOS uses different escape sequences than linux\n if (result.key === C0.ESC + '[1;3D') {\n result.key = C0.ESC + (isMac ? 'b' : '[1;5D');\n }\n } else if (applicationCursorMode) {\n result.key = C0.ESC + 'OD';\n } else {\n result.key = C0.ESC + '[D';\n }\n break;\n case 39:\n // right-arrow\n if (ev.metaKey) {\n break;\n }\n if (modifiers) {\n result.key = C0.ESC + '[1;' + (modifiers + 1) + 'C';\n // HACK: Make Alt + right-arrow behave like Ctrl + right-arrow: move one word forward\n // http://unix.stackexchange.com/a/108106\n // macOS uses different escape sequences than linux\n if (result.key === C0.ESC + '[1;3C') {\n result.key = C0.ESC + (isMac ? 'f' : '[1;5C');\n }\n } else if (applicationCursorMode) {\n result.key = C0.ESC + 'OC';\n } else {\n result.key = C0.ESC + '[C';\n }\n break;\n case 38:\n // up-arrow\n if (ev.metaKey) {\n break;\n }\n if (modifiers) {\n result.key = C0.ESC + '[1;' + (modifiers + 1) + 'A';\n // HACK: Make Alt + up-arrow behave like Ctrl + up-arrow\n // http://unix.stackexchange.com/a/108106\n // macOS uses different escape sequences than linux\n if (!isMac && result.key === C0.ESC + '[1;3A') {\n result.key = C0.ESC + '[1;5A';\n }\n } else if (applicationCursorMode) {\n result.key = C0.ESC + 'OA';\n } else {\n result.key = C0.ESC + '[A';\n }\n break;\n case 40:\n // down-arrow\n if (ev.metaKey) {\n break;\n }\n if (modifiers) {\n result.key = C0.ESC + '[1;' + (modifiers + 1) + 'B';\n // HACK: Make Alt + down-arrow behave like Ctrl + down-arrow\n // http://unix.stackexchange.com/a/108106\n // macOS uses different escape sequences than linux\n if (!isMac && result.key === C0.ESC + '[1;3B') {\n result.key = C0.ESC + '[1;5B';\n }\n } else if (applicationCursorMode) {\n result.key = C0.ESC + 'OB';\n } else {\n result.key = C0.ESC + '[B';\n }\n break;\n case 45:\n // insert\n if (!ev.shiftKey && !ev.ctrlKey) {\n // or + are used to\n // copy-paste on some systems.\n result.key = C0.ESC + '[2~';\n }\n break;\n case 46:\n // delete\n if (modifiers) {\n result.key = C0.ESC + '[3;' + (modifiers + 1) + '~';\n } else {\n result.key = C0.ESC + '[3~';\n }\n break;\n case 36:\n // home\n if (modifiers) {\n result.key = C0.ESC + '[1;' + (modifiers + 1) + 'H';\n } else if (applicationCursorMode) {\n result.key = C0.ESC + 'OH';\n } else {\n result.key = C0.ESC + '[H';\n }\n break;\n case 35:\n // end\n if (modifiers) {\n result.key = C0.ESC + '[1;' + (modifiers + 1) + 'F';\n } else if (applicationCursorMode) {\n result.key = C0.ESC + 'OF';\n } else {\n result.key = C0.ESC + '[F';\n }\n break;\n case 33:\n // page up\n if (ev.shiftKey) {\n result.type = KeyboardResultType.PAGE_UP;\n } else {\n result.key = C0.ESC + '[5~';\n }\n break;\n case 34:\n // page down\n if (ev.shiftKey) {\n result.type = KeyboardResultType.PAGE_DOWN;\n } else {\n result.key = C0.ESC + '[6~';\n }\n break;\n case 112:\n // F1-F12\n if (modifiers) {\n result.key = C0.ESC + '[1;' + (modifiers + 1) + 'P';\n } else {\n result.key = C0.ESC + 'OP';\n }\n break;\n case 113:\n if (modifiers) {\n result.key = C0.ESC + '[1;' + (modifiers + 1) + 'Q';\n } else {\n result.key = C0.ESC + 'OQ';\n }\n break;\n case 114:\n if (modifiers) {\n result.key = C0.ESC + '[1;' + (modifiers + 1) + 'R';\n } else {\n result.key = C0.ESC + 'OR';\n }\n break;\n case 115:\n if (modifiers) {\n result.key = C0.ESC + '[1;' + (modifiers + 1) + 'S';\n } else {\n result.key = C0.ESC + 'OS';\n }\n break;\n case 116:\n if (modifiers) {\n result.key = C0.ESC + '[15;' + (modifiers + 1) + '~';\n } else {\n result.key = C0.ESC + '[15~';\n }\n break;\n case 117:\n if (modifiers) {\n result.key = C0.ESC + '[17;' + (modifiers + 1) + '~';\n } else {\n result.key = C0.ESC + '[17~';\n }\n break;\n case 118:\n if (modifiers) {\n result.key = C0.ESC + '[18;' + (modifiers + 1) + '~';\n } else {\n result.key = C0.ESC + '[18~';\n }\n break;\n case 119:\n if (modifiers) {\n result.key = C0.ESC + '[19;' + (modifiers + 1) + '~';\n } else {\n result.key = C0.ESC + '[19~';\n }\n break;\n case 120:\n if (modifiers) {\n result.key = C0.ESC + '[20;' + (modifiers + 1) + '~';\n } else {\n result.key = C0.ESC + '[20~';\n }\n break;\n case 121:\n if (modifiers) {\n result.key = C0.ESC + '[21;' + (modifiers + 1) + '~';\n } else {\n result.key = C0.ESC + '[21~';\n }\n break;\n case 122:\n if (modifiers) {\n result.key = C0.ESC + '[23;' + (modifiers + 1) + '~';\n } else {\n result.key = C0.ESC + '[23~';\n }\n break;\n case 123:\n if (modifiers) {\n result.key = C0.ESC + '[24;' + (modifiers + 1) + '~';\n } else {\n result.key = C0.ESC + '[24~';\n }\n break;\n default:\n // a-z and space\n if (ev.ctrlKey && !ev.shiftKey && !ev.altKey && !ev.metaKey) {\n if (ev.keyCode >= 65 && ev.keyCode <= 90) {\n result.key = String.fromCharCode(ev.keyCode - 64);\n } else if (ev.keyCode === 32) {\n result.key = C0.NUL;\n } else if (ev.keyCode >= 51 && ev.keyCode <= 55) {\n // escape, file sep, group sep, record sep, unit sep\n result.key = String.fromCharCode(ev.keyCode - 51 + 27);\n } else if (ev.keyCode === 56) {\n result.key = C0.DEL;\n } else if (ev.keyCode === 219) {\n result.key = C0.ESC;\n } else if (ev.keyCode === 220) {\n result.key = C0.FS;\n } else if (ev.keyCode === 221) {\n result.key = C0.GS;\n }\n } else if ((!isMac || macOptionIsMeta) && ev.altKey && !ev.metaKey) {\n // On macOS this is a third level shift when !macOptionIsMeta. Use instead.\n const keyMapping = KEYCODE_KEY_MAPPINGS[ev.keyCode];\n const key = keyMapping && keyMapping[!ev.shiftKey ? 0 : 1];\n if (key) {\n result.key = C0.ESC + key;\n } else if (ev.keyCode >= 65 && ev.keyCode <= 90) {\n const keyCode = ev.ctrlKey ? ev.keyCode - 64 : ev.keyCode + 32;\n result.key = C0.ESC + String.fromCharCode(keyCode);\n }\n } else if (isMac && !ev.altKey && !ev.ctrlKey && ev.metaKey) {\n if (ev.keyCode === 65) { // cmd + a\n result.type = KeyboardResultType.SELECT_ALL;\n }\n } else if (ev.key && !ev.ctrlKey && !ev.altKey && !ev.metaKey && ev.keyCode >= 48 && ev.key.length === 1) {\n // Include only keys that that result in a _single_ character; don't include num lock, volume up, etc.\n result.key = ev.key;\n } else if (ev.key && ev.ctrlKey) {\n if (ev.key === '_') { // ^_\n result.key = C0.US;\n }\n }\n break;\n }\n\n return result;\n}\n","/**\n * Copyright (c) 2019 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { CHAR_DATA_CODE_INDEX, NULL_CELL_CODE, WHITESPACE_CELL_CODE } from 'common/buffer/Constants';\nimport { IBufferService } from 'common/services/Services';\n\nexport function updateWindowsModeWrappedState(bufferService: IBufferService): void {\n // Winpty does not support wraparound mode which means that lines will never\n // be marked as wrapped. This causes issues for things like copying a line\n // retaining the wrapped new line characters or if consumers are listening\n // in on the data stream.\n //\n // The workaround for this is to listen to every incoming line feed and mark\n // the line as wrapped if the last character in the previous line is not a\n // space. This is certainly not without its problems, but generally on\n // Windows when text reaches the end of the terminal it's likely going to be\n // wrapped.\n const line = bufferService.buffer.lines.get(bufferService.buffer.ybase + bufferService.buffer.y - 1);\n const lastChar = line?.get(bufferService.cols - 1);\n\n const nextLine = bufferService.buffer.lines.get(bufferService.buffer.ybase + bufferService.buffer.y);\n if (nextLine && lastChar) {\n nextLine.isWrapped = (lastChar[CHAR_DATA_CODE_INDEX] !== NULL_CELL_CODE && lastChar[CHAR_DATA_CODE_INDEX] !== WHITESPACE_CELL_CODE);\n }\n}\n","/**\n * Copyright (c) 2019 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { IRenderer, IRenderDimensions, CharacterJoinerHandler } from 'browser/renderer/Types';\nimport { RenderDebouncer } from 'browser/RenderDebouncer';\nimport { EventEmitter, IEvent } from 'common/EventEmitter';\nimport { Disposable } from 'common/Lifecycle';\nimport { ScreenDprMonitor } from 'browser/ScreenDprMonitor';\nimport { addDisposableDomListener } from 'browser/Lifecycle';\nimport { IColorSet } from 'browser/Types';\nimport { IOptionsService } from 'common/services/Services';\nimport { ICharSizeService, IRenderService } from 'browser/services/Services';\n\nexport class RenderService extends Disposable implements IRenderService {\n serviceBrand: any;\n\n private _renderDebouncer: RenderDebouncer;\n private _screenDprMonitor: ScreenDprMonitor;\n\n private _isPaused: boolean = false;\n private _needsFullRefresh: boolean = false;\n private _canvasWidth: number = 0;\n private _canvasHeight: number = 0;\n\n private _onDimensionsChange = new EventEmitter();\n public get onDimensionsChange(): IEvent { return this._onDimensionsChange.event; }\n private _onRender = new EventEmitter<{ start: number, end: number }>();\n public get onRender(): IEvent<{ start: number, end: number }> { return this._onRender.event; }\n private _onRefreshRequest = new EventEmitter<{ start: number, end: number }>();\n public get onRefreshRequest(): IEvent<{ start: number, end: number }> { return this._onRefreshRequest.event; }\n\n public get dimensions(): IRenderDimensions { return this._renderer.dimensions; }\n\n constructor(\n private _renderer: IRenderer,\n private _rowCount: number,\n readonly screenElement: HTMLElement,\n @IOptionsService readonly optionsService: IOptionsService,\n @ICharSizeService readonly charSizeService: ICharSizeService\n ) {\n super();\n this._renderDebouncer = new RenderDebouncer((start, end) => this._renderRows(start, end));\n this.register(this._renderDebouncer);\n\n this._screenDprMonitor = new ScreenDprMonitor();\n this._screenDprMonitor.setListener(() => this.onDevicePixelRatioChange());\n this.register(this._screenDprMonitor);\n\n this.register(optionsService.onOptionChange(() => this._renderer.onOptionsChanged()));\n this.register(charSizeService.onCharSizeChange(() => this.onCharSizeChanged()));\n\n // No need to register this as renderer is explicitly disposed in RenderService.dispose\n this._renderer.onRequestRefreshRows(e => this.refreshRows(e.start, e.end));\n\n // dprchange should handle this case, we need this as well for browsers that don't support the\n // matchMedia query.\n this.register(addDisposableDomListener(window, 'resize', () => this.onDevicePixelRatioChange()));\n\n // Detect whether IntersectionObserver is detected and enable renderer pause\n // and resume based on terminal visibility if so\n if ('IntersectionObserver' in window) {\n const observer = new IntersectionObserver(e => this._onIntersectionChange(e[e.length - 1]), { threshold: 0 });\n observer.observe(screenElement);\n this.register({ dispose: () => observer.disconnect() });\n }\n }\n\n private _onIntersectionChange(entry: IntersectionObserverEntry): void {\n this._isPaused = entry.intersectionRatio === 0;\n if (!this._isPaused && this._needsFullRefresh) {\n this.refreshRows(0, this._rowCount - 1);\n this._needsFullRefresh = false;\n }\n }\n\n public refreshRows(start: number, end: number): void {\n if (this._isPaused) {\n this._needsFullRefresh = true;\n return;\n }\n this._renderDebouncer.refresh(start, end, this._rowCount);\n }\n\n private _renderRows(start: number, end: number): void {\n this._renderer.renderRows(start, end);\n this._onRender.fire({ start, end });\n }\n\n public resize(cols: number, rows: number): void {\n this._rowCount = rows;\n this._fireOnCanvasResize();\n }\n\n public changeOptions(): void {\n this._renderer.onOptionsChanged();\n this.refreshRows(0, this._rowCount - 1);\n this._fireOnCanvasResize();\n }\n\n private _fireOnCanvasResize(): void {\n // Don't fire the event if the dimensions haven't changed\n if (this._renderer.dimensions.canvasWidth === this._canvasWidth && this._renderer.dimensions.canvasHeight === this._canvasHeight) {\n return;\n }\n this._onDimensionsChange.fire(this._renderer.dimensions);\n }\n\n public dispose(): void {\n this._renderer.dispose();\n super.dispose();\n }\n\n public setRenderer(renderer: IRenderer): void {\n // TODO: RenderService should be the only one to dispose the renderer\n this._renderer.dispose();\n this._renderer = renderer;\n this._renderer.onRequestRefreshRows(e => this.refreshRows(e.start, e.end));\n this.refreshRows(0, this._rowCount - 1);\n }\n\n private _fullRefresh(): void {\n if (this._isPaused) {\n this._needsFullRefresh = true;\n } else {\n this.refreshRows(0, this._rowCount - 1);\n }\n }\n\n public setColors(colors: IColorSet): void {\n this._renderer.setColors(colors);\n this._fullRefresh();\n }\n\n public onDevicePixelRatioChange(): void {\n this._renderer.onDevicePixelRatioChange();\n this.refreshRows(0, this._rowCount - 1);\n }\n\n public onResize(cols: number, rows: number): void {\n this._renderer.onResize(cols, rows);\n this._fullRefresh();\n }\n\n // TODO: Is this useful when we have onResize?\n public onCharSizeChanged(): void {\n this._renderer.onCharSizeChanged();\n }\n\n public onBlur(): void {\n this._renderer.onBlur();\n }\n\n public onFocus(): void {\n this._renderer.onFocus();\n }\n\n public onSelectionChanged(start: [number, number], end: [number, number], columnSelectMode: boolean): void {\n this._renderer.onSelectionChanged(start, end, columnSelectMode);\n }\n\n public onCursorMove(): void {\n this._renderer.onCursorMove();\n }\n\n public clear(): void {\n this._renderer.clear();\n }\n\n public registerCharacterJoiner(handler: CharacterJoinerHandler): number {\n return this._renderer.registerCharacterJoiner(handler);\n }\n\n public deregisterCharacterJoiner(joinerId: number): boolean {\n return this._renderer.deregisterCharacterJoiner(joinerId);\n }\n}\n","/**\n * Copyright (c) 2019 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { IOptionsService, ITerminalOptions, IPartialTerminalOptions } from 'common/services/Services';\nimport { EventEmitter, IEvent } from 'common/EventEmitter';\nimport { isMac } from 'common/Platform';\nimport { clone } from 'common/Clone';\n\n// Source: https://freesound.org/people/altemark/sounds/45759/\n// This sound is released under the Creative Commons Attribution 3.0 Unported\n// (CC BY 3.0) license. It was created by 'altemark'. No modifications have been\n// made, apart from the conversion to base64.\nexport const DEFAULT_BELL_SOUND = 'data:audio/mp3;base64,SUQzBAAAAAAAI1RTU0UAAAAPAAADTGF2ZjU4LjMyLjEwNAAAAAAAAAAAAAAA//tQxAADB8AhSmxhIIEVCSiJrDCQBTcu3UrAIwUdkRgQbFAZC1CQEwTJ9mjRvBA4UOLD8nKVOWfh+UlK3z/177OXrfOdKl7pyn3Xf//WreyTRUoAWgBgkOAGbZHBgG1OF6zM82DWbZaUmMBptgQhGjsyYqc9ae9XFz280948NMBWInljyzsNRFLPWdnZGWrddDsjK1unuSrVN9jJsK8KuQtQCtMBjCEtImISdNKJOopIpBFpNSMbIHCSRpRR5iakjTiyzLhchUUBwCgyKiweBv/7UsQbg8isVNoMPMjAAAA0gAAABEVFGmgqK////9bP/6XCykxBTUUzLjEwMKqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq';\n\n// TODO: Freeze?\nexport const DEFAULT_OPTIONS: ITerminalOptions = Object.freeze({\n cols: 80,\n rows: 24,\n cursorBlink: false,\n cursorStyle: 'block',\n cursorWidth: 1,\n bellSound: DEFAULT_BELL_SOUND,\n bellStyle: 'none',\n drawBoldTextInBrightColors: true,\n fastScrollModifier: 'alt',\n fastScrollSensitivity: 5,\n fontFamily: 'courier-new, courier, monospace',\n fontSize: 15,\n fontWeight: 'normal',\n fontWeightBold: 'bold',\n lineHeight: 1.0,\n letterSpacing: 0,\n logLevel: 'info',\n scrollback: 1000,\n scrollSensitivity: 1,\n screenReaderMode: false,\n macOptionIsMeta: false,\n macOptionClickForcesSelection: false,\n minimumContrastRatio: 1,\n disableStdin: false,\n allowTransparency: false,\n tabStopWidth: 8,\n theme: {},\n rightClickSelectsWord: isMac,\n rendererType: 'canvas',\n windowOptions: {},\n windowsMode: false,\n wordSeparator: ' ()[]{}\\',\"`',\n\n convertEol: false,\n termName: 'xterm',\n cancelEvents: false\n});\n\n/**\n * The set of options that only have an effect when set in the Terminal constructor.\n */\nconst CONSTRUCTOR_ONLY_OPTIONS = ['cols', 'rows'];\n\nexport class OptionsService implements IOptionsService {\n serviceBrand: any;\n\n public options: ITerminalOptions;\n\n private _onOptionChange = new EventEmitter();\n public get onOptionChange(): IEvent { return this._onOptionChange.event; }\n\n constructor(options: IPartialTerminalOptions) {\n this.options = clone(DEFAULT_OPTIONS);\n Object.keys(options).forEach(k => {\n if (k in this.options) {\n const newValue = options[k as keyof IPartialTerminalOptions] as any;\n this.options[k] = newValue;\n }\n });\n }\n\n public setOption(key: string, value: any): void {\n if (!(key in DEFAULT_OPTIONS)) {\n throw new Error('No option with key \"' + key + '\"');\n }\n if (CONSTRUCTOR_ONLY_OPTIONS.indexOf(key) !== -1) {\n throw new Error(`Option \"${key}\" can only be set in the constructor`);\n }\n if (this.options[key] === value) {\n return;\n }\n\n value = this._sanitizeAndValidateOption(key, value);\n\n // Don't fire an option change event if they didn't change\n if (this.options[key] === value) {\n return;\n }\n\n this.options[key] = value;\n this._onOptionChange.fire(key);\n }\n\n private _sanitizeAndValidateOption(key: string, value: any): any {\n switch (key) {\n case 'bellStyle':\n case 'cursorStyle':\n case 'fontWeight':\n case 'fontWeightBold':\n case 'rendererType':\n case 'wordSeparator':\n if (!value) {\n value = DEFAULT_OPTIONS[key];\n }\n break;\n case 'cursorWidth':\n value = Math.floor(value);\n // Fall through for bounds check\n case 'lineHeight':\n case 'tabStopWidth':\n if (value < 1) {\n throw new Error(`${key} cannot be less than 1, value: ${value}`);\n }\n break;\n case 'minimumContrastRatio':\n value = Math.max(1, Math.min(21, Math.round(value * 10) / 10));\n break;\n case 'scrollback':\n value = Math.min(value, 4294967295);\n if (value < 0) {\n throw new Error(`${key} cannot be less than 0, value: ${value}`);\n }\n break;\n case 'fastScrollSensitivity':\n case 'scrollSensitivity':\n if (value <= 0) {\n throw new Error(`${key} cannot be less than or equal to 0, value: ${value}`);\n }\n break;\n }\n return value;\n }\n\n public getOption(key: string): any {\n if (!(key in DEFAULT_OPTIONS)) {\n throw new Error(`No option with key \"${key}\"`);\n }\n return this.options[key];\n }\n}\n","/**\n * Copyright (c) 2016 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { IOptionsService } from 'common/services/Services';\nimport { IEvent, EventEmitter } from 'common/EventEmitter';\nimport { ICharSizeService } from 'browser/services/Services';\n\nexport class CharSizeService implements ICharSizeService {\n serviceBrand: any;\n\n public width: number = 0;\n public height: number = 0;\n private _measureStrategy: IMeasureStrategy;\n\n public get hasValidSize(): boolean { return this.width > 0 && this.height > 0; }\n\n private _onCharSizeChange = new EventEmitter();\n public get onCharSizeChange(): IEvent { return this._onCharSizeChange.event; }\n\n constructor(\n readonly document: Document,\n readonly parentElement: HTMLElement,\n @IOptionsService private readonly _optionsService: IOptionsService\n ) {\n this._measureStrategy = new DomMeasureStrategy(document, parentElement, this._optionsService);\n }\n\n public measure(): void {\n const result = this._measureStrategy.measure();\n if (result.width !== this.width || result.height !== this.height) {\n this.width = result.width;\n this.height = result.height;\n this._onCharSizeChange.fire();\n }\n }\n}\n\ninterface IMeasureStrategy {\n measure(): IReadonlyMeasureResult;\n}\n\ninterface IReadonlyMeasureResult {\n readonly width: number;\n readonly height: number;\n}\n\ninterface IMeasureResult {\n width: number;\n height: number;\n}\n\n// TODO: For supporting browsers we should also provide a CanvasCharDimensionsProvider that uses ctx.measureText\nclass DomMeasureStrategy implements IMeasureStrategy {\n private _result: IMeasureResult = { width: 0, height: 0 };\n private _measureElement: HTMLElement;\n\n constructor(\n private _document: Document,\n private _parentElement: HTMLElement,\n private _optionsService: IOptionsService\n ) {\n this._measureElement = this._document.createElement('span');\n this._measureElement.classList.add('xterm-char-measure-element');\n this._measureElement.textContent = 'W';\n this._measureElement.setAttribute('aria-hidden', 'true');\n this._parentElement.appendChild(this._measureElement);\n }\n\n public measure(): IReadonlyMeasureResult {\n this._measureElement.style.fontFamily = this._optionsService.options.fontFamily;\n this._measureElement.style.fontSize = `${this._optionsService.options.fontSize}px`;\n\n // Note that this triggers a synchronous layout\n const geometry = this._measureElement.getBoundingClientRect();\n\n // If values are 0 then the element is likely currently display:none, in which case we should\n // retain the previous value.\n if (geometry.width !== 0 && geometry.height !== 0) {\n this._result.width = geometry.width;\n this._result.height = Math.ceil(geometry.height);\n }\n\n return this._result;\n }\n}\n","/**\n * Copyright (c) 2019 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { IBufferService, IOptionsService } from 'common/services/Services';\nimport { BufferSet } from 'common/buffer/BufferSet';\nimport { IBufferSet, IBuffer } from 'common/buffer/Types';\n\nexport const MINIMUM_COLS = 2; // Less than 2 can mess with wide chars\nexport const MINIMUM_ROWS = 1;\n\nexport class BufferService implements IBufferService {\n serviceBrand: any;\n\n public cols: number;\n public rows: number;\n public buffers: IBufferSet;\n\n public get buffer(): IBuffer { return this.buffers.active; }\n\n constructor(\n @IOptionsService private _optionsService: IOptionsService\n ) {\n this.cols = Math.max(_optionsService.options.cols, MINIMUM_COLS);\n this.rows = Math.max(_optionsService.options.rows, MINIMUM_ROWS);\n this.buffers = new BufferSet(_optionsService, this);\n }\n\n public resize(cols: number, rows: number): void {\n this.cols = cols;\n this.rows = rows;\n }\n\n public reset(): void {\n this.buffers = new BufferSet(this._optionsService, this);\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { IBuffer, IBufferSet } from 'common/buffer/Types';\nimport { IAttributeData } from 'common/Types';\nimport { Buffer } from 'common/buffer/Buffer';\nimport { EventEmitter, IEvent } from 'common/EventEmitter';\nimport { IOptionsService, IBufferService } from 'common/services/Services';\n\n/**\n * The BufferSet represents the set of two buffers used by xterm terminals (normal and alt) and\n * provides also utilities for working with them.\n */\nexport class BufferSet implements IBufferSet {\n private _normal: Buffer;\n private _alt: Buffer;\n private _activeBuffer: Buffer;\n\n\n private _onBufferActivate = new EventEmitter<{activeBuffer: IBuffer, inactiveBuffer: IBuffer}>();\n public get onBufferActivate(): IEvent<{activeBuffer: IBuffer, inactiveBuffer: IBuffer}> { return this._onBufferActivate.event; }\n\n /**\n * Create a new BufferSet for the given terminal.\n * @param _terminal - The terminal the BufferSet will belong to\n */\n constructor(\n readonly optionsService: IOptionsService,\n readonly bufferService: IBufferService\n ) {\n this._normal = new Buffer(true, optionsService, bufferService);\n this._normal.fillViewportRows();\n\n // The alt buffer should never have scrollback.\n // See http://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-The-Alternate-Screen-Buffer\n this._alt = new Buffer(false, optionsService, bufferService);\n this._activeBuffer = this._normal;\n\n this.setupTabStops();\n }\n\n /**\n * Returns the alt Buffer of the BufferSet\n */\n public get alt(): Buffer {\n return this._alt;\n }\n\n /**\n * Returns the normal Buffer of the BufferSet\n */\n public get active(): Buffer {\n return this._activeBuffer;\n }\n\n /**\n * Returns the currently active Buffer of the BufferSet\n */\n public get normal(): Buffer {\n return this._normal;\n }\n\n /**\n * Sets the normal Buffer of the BufferSet as its currently active Buffer\n */\n public activateNormalBuffer(): void {\n if (this._activeBuffer === this._normal) {\n return;\n }\n this._normal.x = this._alt.x;\n this._normal.y = this._alt.y;\n // The alt buffer should always be cleared when we switch to the normal\n // buffer. This frees up memory since the alt buffer should always be new\n // when activated.\n this._alt.clear();\n this._activeBuffer = this._normal;\n this._onBufferActivate.fire({\n activeBuffer: this._normal,\n inactiveBuffer: this._alt\n });\n }\n\n /**\n * Sets the alt Buffer of the BufferSet as its currently active Buffer\n */\n public activateAltBuffer(fillAttr?: IAttributeData): void {\n if (this._activeBuffer === this._alt) {\n return;\n }\n // Since the alt buffer is always cleared when the normal buffer is\n // activated, we want to fill it when switching to it.\n this._alt.fillViewportRows(fillAttr);\n this._alt.x = this._normal.x;\n this._alt.y = this._normal.y;\n this._activeBuffer = this._alt;\n this._onBufferActivate.fire({\n activeBuffer: this._alt,\n inactiveBuffer: this._normal\n });\n }\n\n /**\n * Resizes both normal and alt buffers, adjusting their data accordingly.\n * @param newCols The new number of columns.\n * @param newRows The new number of rows.\n */\n public resize(newCols: number, newRows: number): void {\n this._normal.resize(newCols, newRows);\n this._alt.resize(newCols, newRows);\n }\n\n /**\n * Setup the tab stops.\n * @param i The index to start setting up tab stops from.\n */\n public setupTabStops(i?: number): void {\n this._normal.setupTabStops(i);\n this._alt.setupTabStops(i);\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { CircularList, IInsertEvent } from 'common/CircularList';\nimport { IBuffer, BufferIndex, IBufferStringIterator, IBufferStringIteratorResult } from 'common/buffer/Types';\nimport { IBufferLine, ICellData, IAttributeData, ICharset } from 'common/Types';\nimport { BufferLine, DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine';\nimport { CellData } from 'common/buffer/CellData';\nimport { NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE, WHITESPACE_CELL_CHAR, WHITESPACE_CELL_WIDTH, WHITESPACE_CELL_CODE, CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CHAR_INDEX } from 'common/buffer/Constants';\nimport { reflowLargerApplyNewLayout, reflowLargerCreateNewLayout, reflowLargerGetLinesToRemove, reflowSmallerGetNewLineLengths, getWrappedLineTrimmedLength } from 'common/buffer/BufferReflow';\nimport { Marker } from 'common/buffer/Marker';\nimport { IOptionsService, IBufferService } from 'common/services/Services';\nimport { DEFAULT_CHARSET } from 'common/data/Charsets';\n\nexport const MAX_BUFFER_SIZE = 4294967295; // 2^32 - 1\n\n/**\n * This class represents a terminal buffer (an internal state of the terminal), where the\n * following information is stored (in high-level):\n * - text content of this particular buffer\n * - cursor position\n * - scroll position\n */\nexport class Buffer implements IBuffer {\n public lines: CircularList;\n public ydisp: number = 0;\n public ybase: number = 0;\n public y: number = 0;\n public x: number = 0;\n public scrollBottom: number;\n public scrollTop: number;\n // TODO: Type me\n public tabs: any;\n public savedY: number = 0;\n public savedX: number = 0;\n public savedCurAttrData = DEFAULT_ATTR_DATA.clone();\n public savedCharset: ICharset | null = DEFAULT_CHARSET;\n public markers: Marker[] = [];\n private _nullCell: ICellData = CellData.fromCharData([0, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]);\n private _whitespaceCell: ICellData = CellData.fromCharData([0, WHITESPACE_CELL_CHAR, WHITESPACE_CELL_WIDTH, WHITESPACE_CELL_CODE]);\n private _cols: number;\n private _rows: number;\n\n constructor(\n private _hasScrollback: boolean,\n private _optionsService: IOptionsService,\n private _bufferService: IBufferService\n ) {\n this._cols = this._bufferService.cols;\n this._rows = this._bufferService.rows;\n this.lines = new CircularList(this._getCorrectBufferLength(this._rows));\n this.scrollTop = 0;\n this.scrollBottom = this._rows - 1;\n this.setupTabStops();\n }\n\n public getNullCell(attr?: IAttributeData): ICellData {\n if (attr) {\n this._nullCell.fg = attr.fg;\n this._nullCell.bg = attr.bg;\n } else {\n this._nullCell.fg = 0;\n this._nullCell.bg = 0;\n }\n return this._nullCell;\n }\n\n public getWhitespaceCell(attr?: IAttributeData): ICellData {\n if (attr) {\n this._whitespaceCell.fg = attr.fg;\n this._whitespaceCell.bg = attr.bg;\n } else {\n this._whitespaceCell.fg = 0;\n this._whitespaceCell.bg = 0;\n }\n return this._whitespaceCell;\n }\n\n public getBlankLine(attr: IAttributeData, isWrapped?: boolean): IBufferLine {\n return new BufferLine(this._bufferService.cols, this.getNullCell(attr), isWrapped);\n }\n\n public get hasScrollback(): boolean {\n return this._hasScrollback && this.lines.maxLength > this._rows;\n }\n\n public get isCursorInViewport(): boolean {\n const absoluteY = this.ybase + this.y;\n const relativeY = absoluteY - this.ydisp;\n return (relativeY >= 0 && relativeY < this._rows);\n }\n\n /**\n * Gets the correct buffer length based on the rows provided, the terminal's\n * scrollback and whether this buffer is flagged to have scrollback or not.\n * @param rows The terminal rows to use in the calculation.\n */\n private _getCorrectBufferLength(rows: number): number {\n if (!this._hasScrollback) {\n return rows;\n }\n\n const correctBufferLength = rows + this._optionsService.options.scrollback;\n\n return correctBufferLength > MAX_BUFFER_SIZE ? MAX_BUFFER_SIZE : correctBufferLength;\n }\n\n /**\n * Fills the buffer's viewport with blank lines.\n */\n public fillViewportRows(fillAttr?: IAttributeData): void {\n if (this.lines.length === 0) {\n if (fillAttr === undefined) {\n fillAttr = DEFAULT_ATTR_DATA;\n }\n let i = this._rows;\n while (i--) {\n this.lines.push(this.getBlankLine(fillAttr));\n }\n }\n }\n\n /**\n * Clears the buffer to it's initial state, discarding all previous data.\n */\n public clear(): void {\n this.ydisp = 0;\n this.ybase = 0;\n this.y = 0;\n this.x = 0;\n this.lines = new CircularList(this._getCorrectBufferLength(this._rows));\n this.scrollTop = 0;\n this.scrollBottom = this._rows - 1;\n this.setupTabStops();\n }\n\n /**\n * Resizes the buffer, adjusting its data accordingly.\n * @param newCols The new number of columns.\n * @param newRows The new number of rows.\n */\n public resize(newCols: number, newRows: number): void {\n // store reference to null cell with default attrs\n const nullCell = this.getNullCell(DEFAULT_ATTR_DATA);\n\n // Increase max length if needed before adjustments to allow space to fill\n // as required.\n const newMaxLength = this._getCorrectBufferLength(newRows);\n if (newMaxLength > this.lines.maxLength) {\n this.lines.maxLength = newMaxLength;\n }\n\n // The following adjustments should only happen if the buffer has been\n // initialized/filled.\n if (this.lines.length > 0) {\n // Deal with columns increasing (reducing needs to happen after reflow)\n if (this._cols < newCols) {\n for (let i = 0; i < this.lines.length; i++) {\n this.lines.get(i)!.resize(newCols, nullCell);\n }\n }\n\n // Resize rows in both directions as needed\n let addToY = 0;\n if (this._rows < newRows) {\n for (let y = this._rows; y < newRows; y++) {\n if (this.lines.length < newRows + this.ybase) {\n if (this._optionsService.options.windowsMode) {\n // Just add the new missing rows on Windows as conpty reprints the screen with it's\n // view of the world. Once a line enters scrollback for conpty it remains there\n this.lines.push(new BufferLine(newCols, nullCell));\n } else {\n if (this.ybase > 0 && this.lines.length <= this.ybase + this.y + addToY + 1) {\n // There is room above the buffer and there are no empty elements below the line,\n // scroll up\n this.ybase--;\n addToY++;\n if (this.ydisp > 0) {\n // Viewport is at the top of the buffer, must increase downwards\n this.ydisp--;\n }\n } else {\n // Add a blank line if there is no buffer left at the top to scroll to, or if there\n // are blank lines after the cursor\n this.lines.push(new BufferLine(newCols, nullCell));\n }\n }\n }\n }\n } else { // (this._rows >= newRows)\n for (let y = this._rows; y > newRows; y--) {\n if (this.lines.length > newRows + this.ybase) {\n if (this.lines.length > this.ybase + this.y + 1) {\n // The line is a blank line below the cursor, remove it\n this.lines.pop();\n } else {\n // The line is the cursor, scroll down\n this.ybase++;\n this.ydisp++;\n }\n }\n }\n }\n\n // Reduce max length if needed after adjustments, this is done after as it\n // would otherwise cut data from the bottom of the buffer.\n if (newMaxLength < this.lines.maxLength) {\n // Trim from the top of the buffer and adjust ybase and ydisp.\n const amountToTrim = this.lines.length - newMaxLength;\n if (amountToTrim > 0) {\n this.lines.trimStart(amountToTrim);\n this.ybase = Math.max(this.ybase - amountToTrim, 0);\n this.ydisp = Math.max(this.ydisp - amountToTrim, 0);\n this.savedY = Math.max(this.savedY - amountToTrim, 0);\n }\n this.lines.maxLength = newMaxLength;\n }\n\n // Make sure that the cursor stays on screen\n this.x = Math.min(this.x, newCols - 1);\n this.y = Math.min(this.y, newRows - 1);\n if (addToY) {\n this.y += addToY;\n }\n this.savedX = Math.min(this.savedX, newCols - 1);\n\n this.scrollTop = 0;\n }\n\n this.scrollBottom = newRows - 1;\n\n if (this._isReflowEnabled) {\n this._reflow(newCols, newRows);\n\n // Trim the end of the line off if cols shrunk\n if (this._cols > newCols) {\n for (let i = 0; i < this.lines.length; i++) {\n this.lines.get(i)!.resize(newCols, nullCell);\n }\n }\n }\n\n this._cols = newCols;\n this._rows = newRows;\n }\n\n private get _isReflowEnabled(): boolean {\n return this._hasScrollback && !this._optionsService.options.windowsMode;\n }\n\n private _reflow(newCols: number, newRows: number): void {\n if (this._cols === newCols) {\n return;\n }\n\n // Iterate through rows, ignore the last one as it cannot be wrapped\n if (newCols > this._cols) {\n this._reflowLarger(newCols, newRows);\n } else {\n this._reflowSmaller(newCols, newRows);\n }\n }\n\n private _reflowLarger(newCols: number, newRows: number): void {\n const toRemove: number[] = reflowLargerGetLinesToRemove(this.lines, this._cols, newCols, this.ybase + this.y, this.getNullCell(DEFAULT_ATTR_DATA));\n if (toRemove.length > 0) {\n const newLayoutResult = reflowLargerCreateNewLayout(this.lines, toRemove);\n reflowLargerApplyNewLayout(this.lines, newLayoutResult.layout);\n this._reflowLargerAdjustViewport(newCols, newRows, newLayoutResult.countRemoved);\n }\n }\n\n private _reflowLargerAdjustViewport(newCols: number, newRows: number, countRemoved: number): void {\n const nullCell = this.getNullCell(DEFAULT_ATTR_DATA);\n // Adjust viewport based on number of items removed\n let viewportAdjustments = countRemoved;\n while (viewportAdjustments-- > 0) {\n if (this.ybase === 0) {\n if (this.y > 0) {\n this.y--;\n }\n if (this.lines.length < newRows) {\n // Add an extra row at the bottom of the viewport\n this.lines.push(new BufferLine(newCols, nullCell));\n }\n } else {\n if (this.ydisp === this.ybase) {\n this.ydisp--;\n }\n this.ybase--;\n }\n }\n this.savedY = Math.max(this.savedY - countRemoved, 0);\n }\n\n private _reflowSmaller(newCols: number, newRows: number): void {\n const nullCell = this.getNullCell(DEFAULT_ATTR_DATA);\n // Gather all BufferLines that need to be inserted into the Buffer here so that they can be\n // batched up and only committed once\n const toInsert = [];\n let countToInsert = 0;\n // Go backwards as many lines may be trimmed and this will avoid considering them\n for (let y = this.lines.length - 1; y >= 0; y--) {\n // Check whether this line is a problem\n let nextLine = this.lines.get(y) as BufferLine;\n if (!nextLine || !nextLine.isWrapped && nextLine.getTrimmedLength() <= newCols) {\n continue;\n }\n\n // Gather wrapped lines and adjust y to be the starting line\n const wrappedLines: BufferLine[] = [nextLine];\n while (nextLine.isWrapped && y > 0) {\n nextLine = this.lines.get(--y) as BufferLine;\n wrappedLines.unshift(nextLine);\n }\n\n // If these lines contain the cursor don't touch them, the program will handle fixing up\n // wrapped lines with the cursor\n const absoluteY = this.ybase + this.y;\n if (absoluteY >= y && absoluteY < y + wrappedLines.length) {\n continue;\n }\n\n const lastLineLength = wrappedLines[wrappedLines.length - 1].getTrimmedLength();\n const destLineLengths = reflowSmallerGetNewLineLengths(wrappedLines, this._cols, newCols);\n const linesToAdd = destLineLengths.length - wrappedLines.length;\n let trimmedLines: number;\n if (this.ybase === 0 && this.y !== this.lines.length - 1) {\n // If the top section of the buffer is not yet filled\n trimmedLines = Math.max(0, this.y - this.lines.maxLength + linesToAdd);\n } else {\n trimmedLines = Math.max(0, this.lines.length - this.lines.maxLength + linesToAdd);\n }\n\n // Add the new lines\n const newLines: BufferLine[] = [];\n for (let i = 0; i < linesToAdd; i++) {\n const newLine = this.getBlankLine(DEFAULT_ATTR_DATA, true) as BufferLine;\n newLines.push(newLine);\n }\n if (newLines.length > 0) {\n toInsert.push({\n // countToInsert here gets the actual index, taking into account other inserted items.\n // using this we can iterate through the list forwards\n start: y + wrappedLines.length + countToInsert,\n newLines\n });\n countToInsert += newLines.length;\n }\n wrappedLines.push(...newLines);\n\n // Copy buffer data to new locations, this needs to happen backwards to do in-place\n let destLineIndex = destLineLengths.length - 1; // Math.floor(cellsNeeded / newCols);\n let destCol = destLineLengths[destLineIndex]; // cellsNeeded % newCols;\n if (destCol === 0) {\n destLineIndex--;\n destCol = destLineLengths[destLineIndex];\n }\n let srcLineIndex = wrappedLines.length - linesToAdd - 1;\n let srcCol = lastLineLength;\n while (srcLineIndex >= 0) {\n const cellsToCopy = Math.min(srcCol, destCol);\n wrappedLines[destLineIndex].copyCellsFrom(wrappedLines[srcLineIndex], srcCol - cellsToCopy, destCol - cellsToCopy, cellsToCopy, true);\n destCol -= cellsToCopy;\n if (destCol === 0) {\n destLineIndex--;\n destCol = destLineLengths[destLineIndex];\n }\n srcCol -= cellsToCopy;\n if (srcCol === 0) {\n srcLineIndex--;\n const wrappedLinesIndex = Math.max(srcLineIndex, 0);\n srcCol = getWrappedLineTrimmedLength(wrappedLines, wrappedLinesIndex, this._cols);\n }\n }\n\n // Null out the end of the line ends if a wide character wrapped to the following line\n for (let i = 0; i < wrappedLines.length; i++) {\n if (destLineLengths[i] < newCols) {\n wrappedLines[i].setCell(destLineLengths[i], nullCell);\n }\n }\n\n // Adjust viewport as needed\n let viewportAdjustments = linesToAdd - trimmedLines;\n while (viewportAdjustments-- > 0) {\n if (this.ybase === 0) {\n if (this.y < newRows - 1) {\n this.y++;\n this.lines.pop();\n } else {\n this.ybase++;\n this.ydisp++;\n }\n } else {\n // Ensure ybase does not exceed its maximum value\n if (this.ybase < Math.min(this.lines.maxLength, this.lines.length + countToInsert) - newRows) {\n if (this.ybase === this.ydisp) {\n this.ydisp++;\n }\n this.ybase++;\n }\n }\n }\n this.savedY = Math.min(this.savedY + linesToAdd, this.ybase + newRows - 1);\n }\n\n // Rearrange lines in the buffer if there are any insertions, this is done at the end rather\n // than earlier so that it's a single O(n) pass through the buffer, instead of O(n^2) from many\n // costly calls to CircularList.splice.\n if (toInsert.length > 0) {\n // Record buffer insert events and then play them back backwards so that the indexes are\n // correct\n const insertEvents: IInsertEvent[] = [];\n\n // Record original lines so they don't get overridden when we rearrange the list\n const originalLines: BufferLine[] = [];\n for (let i = 0; i < this.lines.length; i++) {\n originalLines.push(this.lines.get(i) as BufferLine);\n }\n const originalLinesLength = this.lines.length;\n\n let originalLineIndex = originalLinesLength - 1;\n let nextToInsertIndex = 0;\n let nextToInsert = toInsert[nextToInsertIndex];\n this.lines.length = Math.min(this.lines.maxLength, this.lines.length + countToInsert);\n let countInsertedSoFar = 0;\n for (let i = Math.min(this.lines.maxLength - 1, originalLinesLength + countToInsert - 1); i >= 0; i--) {\n if (nextToInsert && nextToInsert.start > originalLineIndex + countInsertedSoFar) {\n // Insert extra lines here, adjusting i as needed\n for (let nextI = nextToInsert.newLines.length - 1; nextI >= 0; nextI--) {\n this.lines.set(i--, nextToInsert.newLines[nextI]);\n }\n i++;\n\n // Create insert events for later\n insertEvents.push({\n index: originalLineIndex + 1,\n amount: nextToInsert.newLines.length\n });\n\n countInsertedSoFar += nextToInsert.newLines.length;\n nextToInsert = toInsert[++nextToInsertIndex];\n } else {\n this.lines.set(i, originalLines[originalLineIndex--]);\n }\n }\n\n // Update markers\n let insertCountEmitted = 0;\n for (let i = insertEvents.length - 1; i >= 0; i--) {\n insertEvents[i].index += insertCountEmitted;\n this.lines.onInsertEmitter.fire(insertEvents[i]);\n insertCountEmitted += insertEvents[i].amount;\n }\n const amountToTrim = Math.max(0, originalLinesLength + countToInsert - this.lines.maxLength);\n if (amountToTrim > 0) {\n this.lines.onTrimEmitter.fire(amountToTrim);\n }\n }\n }\n\n // private _reflowSmallerGetLinesNeeded()\n\n /**\n * Translates a string index back to a BufferIndex.\n * To get the correct buffer position the string must start at `startCol` 0\n * (default in translateBufferLineToString).\n * The method also works on wrapped line strings given rows were not trimmed.\n * The method operates on the CharData string length, there are no\n * additional content or boundary checks. Therefore the string and the buffer\n * should not be altered in between.\n * TODO: respect trim flag after fixing #1685\n * @param lineIndex line index the string was retrieved from\n * @param stringIndex index within the string\n * @param startCol column offset the string was retrieved from\n */\n public stringIndexToBufferIndex(lineIndex: number, stringIndex: number, trimRight: boolean = false): BufferIndex {\n while (stringIndex) {\n const line = this.lines.get(lineIndex);\n if (!line) {\n return [-1, -1];\n }\n const length = (trimRight) ? line.getTrimmedLength() : line.length;\n for (let i = 0; i < length; ++i) {\n if (line.get(i)[CHAR_DATA_WIDTH_INDEX]) {\n // empty cells report a string length of 0, but get replaced\n // with a whitespace in translateToString, thus replace with 1\n stringIndex -= line.get(i)[CHAR_DATA_CHAR_INDEX].length || 1;\n }\n if (stringIndex < 0) {\n return [lineIndex, i];\n }\n }\n lineIndex++;\n }\n return [lineIndex, 0];\n }\n\n /**\n * Translates a buffer line to a string, with optional start and end columns.\n * Wide characters will count as two columns in the resulting string. This\n * function is useful for getting the actual text underneath the raw selection\n * position.\n * @param line The line being translated.\n * @param trimRight Whether to trim whitespace to the right.\n * @param startCol The column to start at.\n * @param endCol The column to end at.\n */\n public translateBufferLineToString(lineIndex: number, trimRight: boolean, startCol: number = 0, endCol?: number): string {\n const line = this.lines.get(lineIndex);\n if (!line) {\n return '';\n }\n return line.translateToString(trimRight, startCol, endCol);\n }\n\n public getWrappedRangeForLine(y: number): { first: number, last: number } {\n let first = y;\n let last = y;\n // Scan upwards for wrapped lines\n while (first > 0 && this.lines.get(first)!.isWrapped) {\n first--;\n }\n // Scan downwards for wrapped lines\n while (last + 1 < this.lines.length && this.lines.get(last + 1)!.isWrapped) {\n last++;\n }\n return { first, last };\n }\n\n /**\n * Setup the tab stops.\n * @param i The index to start setting up tab stops from.\n */\n public setupTabStops(i?: number): void {\n if (i !== null && i !== undefined) {\n if (!this.tabs[i]) {\n i = this.prevStop(i);\n }\n } else {\n this.tabs = {};\n i = 0;\n }\n\n for (; i < this._cols; i += this._optionsService.options.tabStopWidth) {\n this.tabs[i] = true;\n }\n }\n\n /**\n * Move the cursor to the previous tab stop from the given position (default is current).\n * @param x The position to move the cursor to the previous tab stop.\n */\n public prevStop(x?: number): number {\n if (x === null || x === undefined) {\n x = this.x;\n }\n while (!this.tabs[--x] && x > 0);\n return x >= this._cols ? this._cols - 1 : x < 0 ? 0 : x;\n }\n\n /**\n * Move the cursor one tab stop forward from the given position (default is current).\n * @param x The position to move the cursor one tab stop forward.\n */\n public nextStop(x?: number): number {\n if (x === null || x === undefined) {\n x = this.x;\n }\n while (!this.tabs[++x] && x < this._cols);\n return x >= this._cols ? this._cols - 1 : x < 0 ? 0 : x;\n }\n\n public addMarker(y: number): Marker {\n const marker = new Marker(y);\n this.markers.push(marker);\n marker.register(this.lines.onTrim(amount => {\n marker.line -= amount;\n // The marker should be disposed when the line is trimmed from the buffer\n if (marker.line < 0) {\n marker.dispose();\n }\n }));\n marker.register(this.lines.onInsert(event => {\n if (marker.line >= event.index) {\n marker.line += event.amount;\n }\n }));\n marker.register(this.lines.onDelete(event => {\n // Delete the marker if it's within the range\n if (marker.line >= event.index && marker.line < event.index + event.amount) {\n marker.dispose();\n }\n\n // Shift the marker if it's after the deleted range\n if (marker.line > event.index) {\n marker.line -= event.amount;\n }\n }));\n marker.register(marker.onDispose(() => this._removeMarker(marker)));\n return marker;\n }\n\n private _removeMarker(marker: Marker): void {\n this.markers.splice(this.markers.indexOf(marker), 1);\n }\n\n public iterator(trimRight: boolean, startIndex?: number, endIndex?: number, startOverscan?: number, endOverscan?: number): IBufferStringIterator {\n return new BufferStringIterator(this, trimRight, startIndex, endIndex, startOverscan, endOverscan);\n }\n}\n\n/**\n * Iterator to get unwrapped content strings from the buffer.\n * The iterator returns at least the string data between the borders\n * `startIndex` and `endIndex` (exclusive) and will expand the lines\n * by `startOverscan` to the top and by `endOverscan` to the bottom,\n * if no new line was found in between.\n * It will never read/return string data beyond `startIndex - startOverscan`\n * or `endIndex + endOverscan`. Therefore the first and last line might be truncated.\n * It is possible to always get the full string for the first and last line as well\n * by setting the overscan values to the actual buffer length. This not recommended\n * since it might return the whole buffer within a single string in a worst case scenario.\n */\nexport class BufferStringIterator implements IBufferStringIterator {\n private _current: number;\n\n constructor (\n private _buffer: IBuffer,\n private _trimRight: boolean,\n private _startIndex: number = 0,\n private _endIndex: number = _buffer.lines.length,\n private _startOverscan: number = 0,\n private _endOverscan: number = 0\n ) {\n if (this._startIndex < 0) {\n this._startIndex = 0;\n }\n if (this._endIndex > this._buffer.lines.length) {\n this._endIndex = this._buffer.lines.length;\n }\n this._current = this._startIndex;\n }\n\n public hasNext(): boolean {\n return this._current < this._endIndex;\n }\n\n public next(): IBufferStringIteratorResult {\n const range = this._buffer.getWrappedRangeForLine(this._current);\n // limit search window to overscan value at both borders\n if (range.first < this._startIndex - this._startOverscan) {\n range.first = this._startIndex - this._startOverscan;\n }\n if (range.last > this._endIndex + this._endOverscan) {\n range.last = this._endIndex + this._endOverscan;\n }\n // limit to current buffer length\n range.first = Math.max(range.first, 0);\n range.last = Math.min(range.last, this._buffer.lines.length);\n let result = '';\n for (let i = range.first; i <= range.last; ++i) {\n result += this._buffer.translateBufferLineToString(i, this._trimRight);\n }\n this._current = range.last + 1;\n return {range: range, content: result};\n }\n}\n","/**\n * Copyright (c) 2016 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { ICircularList } from 'common/Types';\nimport { EventEmitter, IEvent } from 'common/EventEmitter';\n\nexport interface IInsertEvent {\n index: number;\n amount: number;\n}\n\nexport interface IDeleteEvent {\n index: number;\n amount: number;\n}\n\n/**\n * Represents a circular list; a list with a maximum size that wraps around when push is called,\n * overriding values at the start of the list.\n */\nexport class CircularList implements ICircularList {\n protected _array: (T | undefined)[];\n private _startIndex: number;\n private _length: number;\n\n public onDeleteEmitter = new EventEmitter();\n public get onDelete(): IEvent { return this.onDeleteEmitter.event; }\n public onInsertEmitter = new EventEmitter();\n public get onInsert(): IEvent { return this.onInsertEmitter.event; }\n public onTrimEmitter = new EventEmitter();\n public get onTrim(): IEvent { return this.onTrimEmitter.event; }\n\n constructor(\n private _maxLength: number\n ) {\n this._array = new Array(this._maxLength);\n this._startIndex = 0;\n this._length = 0;\n }\n\n public get maxLength(): number {\n return this._maxLength;\n }\n\n public set maxLength(newMaxLength: number) {\n // There was no change in maxLength, return early.\n if (this._maxLength === newMaxLength) {\n return;\n }\n\n // Reconstruct array, starting at index 0. Only transfer values from the\n // indexes 0 to length.\n const newArray = new Array(newMaxLength);\n for (let i = 0; i < Math.min(newMaxLength, this.length); i++) {\n newArray[i] = this._array[this._getCyclicIndex(i)];\n }\n this._array = newArray;\n this._maxLength = newMaxLength;\n this._startIndex = 0;\n }\n\n public get length(): number {\n return this._length;\n }\n\n public set length(newLength: number) {\n if (newLength > this._length) {\n for (let i = this._length; i < newLength; i++) {\n this._array[i] = undefined;\n }\n }\n this._length = newLength;\n }\n\n /**\n * Gets the value at an index.\n *\n * Note that for performance reasons there is no bounds checking here, the index reference is\n * circular so this should always return a value and never throw.\n * @param index The index of the value to get.\n * @return The value corresponding to the index.\n */\n public get(index: number): T | undefined {\n return this._array[this._getCyclicIndex(index)];\n }\n\n /**\n * Sets the value at an index.\n *\n * Note that for performance reasons there is no bounds checking here, the index reference is\n * circular so this should always return a value and never throw.\n * @param index The index to set.\n * @param value The value to set.\n */\n public set(index: number, value: T | undefined): void {\n this._array[this._getCyclicIndex(index)] = value;\n }\n\n /**\n * Pushes a new value onto the list, wrapping around to the start of the array, overriding index 0\n * if the maximum length is reached.\n * @param value The value to push onto the list.\n */\n public push(value: T): void {\n this._array[this._getCyclicIndex(this._length)] = value;\n if (this._length === this._maxLength) {\n this._startIndex = ++this._startIndex % this._maxLength;\n this.onTrimEmitter.fire(1);\n } else {\n this._length++;\n }\n }\n\n /**\n * Advance ringbuffer index and return current element for recycling.\n * Note: The buffer must be full for this method to work.\n * @throws When the buffer is not full.\n */\n public recycle(): T {\n if (this._length !== this._maxLength) {\n throw new Error('Can only recycle when the buffer is full');\n }\n this._startIndex = ++this._startIndex % this._maxLength;\n this.onTrimEmitter.fire(1);\n return this._array[this._getCyclicIndex(this._length - 1)]!;\n }\n\n /**\n * Ringbuffer is at max length.\n */\n public get isFull(): boolean {\n return this._length === this._maxLength;\n }\n\n /**\n * Removes and returns the last value on the list.\n * @return The popped value.\n */\n public pop(): T | undefined {\n return this._array[this._getCyclicIndex(this._length-- - 1)];\n }\n\n /**\n * Deletes and/or inserts items at a particular index (in that order). Unlike\n * Array.prototype.splice, this operation does not return the deleted items as a new array in\n * order to save creating a new array. Note that this operation may shift all values in the list\n * in the worst case.\n * @param start The index to delete and/or insert.\n * @param deleteCount The number of elements to delete.\n * @param items The items to insert.\n */\n public splice(start: number, deleteCount: number, ...items: T[]): void {\n // Delete items\n if (deleteCount) {\n for (let i = start; i < this._length - deleteCount; i++) {\n this._array[this._getCyclicIndex(i)] = this._array[this._getCyclicIndex(i + deleteCount)];\n }\n this._length -= deleteCount;\n }\n\n // Add items\n for (let i = this._length - 1; i >= start; i--) {\n this._array[this._getCyclicIndex(i + items.length)] = this._array[this._getCyclicIndex(i)];\n }\n for (let i = 0; i < items.length; i++) {\n this._array[this._getCyclicIndex(start + i)] = items[i];\n }\n\n // Adjust length as needed\n if (this._length + items.length > this._maxLength) {\n const countToTrim = (this._length + items.length) - this._maxLength;\n this._startIndex += countToTrim;\n this._length = this._maxLength;\n this.onTrimEmitter.fire(countToTrim);\n } else {\n this._length += items.length;\n }\n }\n\n /**\n * Trims a number of items from the start of the list.\n * @param count The number of items to remove.\n */\n public trimStart(count: number): void {\n if (count > this._length) {\n count = this._length;\n }\n this._startIndex += count;\n this._length -= count;\n this.onTrimEmitter.fire(count);\n }\n\n public shiftElements(start: number, count: number, offset: number): void {\n if (count <= 0) {\n return;\n }\n if (start < 0 || start >= this._length) {\n throw new Error('start argument out of range');\n }\n if (start + offset < 0) {\n throw new Error('Cannot shift elements in list beyond index 0');\n }\n\n if (offset > 0) {\n for (let i = count - 1; i >= 0; i--) {\n this.set(start + i + offset, this.get(start + i));\n }\n const expandListBy = (start + count + offset) - this._length;\n if (expandListBy > 0) {\n this._length += expandListBy;\n while (this._length > this._maxLength) {\n this._length--;\n this._startIndex++;\n this.onTrimEmitter.fire(1);\n }\n }\n } else {\n for (let i = 0; i < count; i++) {\n this.set(start + i + offset, this.get(start + i));\n }\n }\n }\n\n /**\n * Gets the cyclic index for the specified regular index. The cyclic index can then be used on the\n * backing array to get the element associated with the regular index.\n * @param index The regular index.\n * @returns The cyclic index.\n */\n private _getCyclicIndex(index: number): number {\n return (this._startIndex + index) % this._maxLength;\n }\n}\n","/**\n * Copyright (c) 2019 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { BufferLine } from 'common/buffer/BufferLine';\nimport { CircularList } from 'common/CircularList';\nimport { IBufferLine, ICellData } from 'common/Types';\n\nexport interface INewLayoutResult {\n layout: number[];\n countRemoved: number;\n}\n\n/**\n * Evaluates and returns indexes to be removed after a reflow larger occurs. Lines will be removed\n * when a wrapped line unwraps.\n * @param lines The buffer lines.\n * @param newCols The columns after resize.\n */\nexport function reflowLargerGetLinesToRemove(lines: CircularList, oldCols: number, newCols: number, bufferAbsoluteY: number, nullCell: ICellData): number[] {\n // Gather all BufferLines that need to be removed from the Buffer here so that they can be\n // batched up and only committed once\n const toRemove: number[] = [];\n\n for (let y = 0; y < lines.length - 1; y++) {\n // Check if this row is wrapped\n let i = y;\n let nextLine = lines.get(++i) as BufferLine;\n if (!nextLine.isWrapped) {\n continue;\n }\n\n // Check how many lines it's wrapped for\n const wrappedLines: BufferLine[] = [lines.get(y) as BufferLine];\n while (i < lines.length && nextLine.isWrapped) {\n wrappedLines.push(nextLine);\n nextLine = lines.get(++i) as BufferLine;\n }\n\n // If these lines contain the cursor don't touch them, the program will handle fixing up wrapped\n // lines with the cursor\n if (bufferAbsoluteY >= y && bufferAbsoluteY < i) {\n y += wrappedLines.length - 1;\n continue;\n }\n\n // Copy buffer data to new locations\n let destLineIndex = 0;\n let destCol = getWrappedLineTrimmedLength(wrappedLines, destLineIndex, oldCols);\n let srcLineIndex = 1;\n let srcCol = 0;\n while (srcLineIndex < wrappedLines.length) {\n const srcTrimmedTineLength = getWrappedLineTrimmedLength(wrappedLines, srcLineIndex, oldCols);\n const srcRemainingCells = srcTrimmedTineLength - srcCol;\n const destRemainingCells = newCols - destCol;\n const cellsToCopy = Math.min(srcRemainingCells, destRemainingCells);\n\n wrappedLines[destLineIndex].copyCellsFrom(wrappedLines[srcLineIndex], srcCol, destCol, cellsToCopy, false);\n\n destCol += cellsToCopy;\n if (destCol === newCols) {\n destLineIndex++;\n destCol = 0;\n }\n srcCol += cellsToCopy;\n if (srcCol === srcTrimmedTineLength) {\n srcLineIndex++;\n srcCol = 0;\n }\n\n // Make sure the last cell isn't wide, if it is copy it to the current dest\n if (destCol === 0 && destLineIndex !== 0) {\n if (wrappedLines[destLineIndex - 1].getWidth(newCols - 1) === 2) {\n wrappedLines[destLineIndex].copyCellsFrom(wrappedLines[destLineIndex - 1], newCols - 1, destCol++, 1, false);\n // Null out the end of the last row\n wrappedLines[destLineIndex - 1].setCell(newCols - 1, nullCell);\n }\n }\n }\n\n // Clear out remaining cells or fragments could remain;\n wrappedLines[destLineIndex].replaceCells(destCol, newCols, nullCell);\n\n // Work backwards and remove any rows at the end that only contain null cells\n let countToRemove = 0;\n for (let i = wrappedLines.length - 1; i > 0; i--) {\n if (i > destLineIndex || wrappedLines[i].getTrimmedLength() === 0) {\n countToRemove++;\n } else {\n break;\n }\n }\n\n if (countToRemove > 0) {\n toRemove.push(y + wrappedLines.length - countToRemove); // index\n toRemove.push(countToRemove);\n }\n\n y += wrappedLines.length - 1;\n }\n return toRemove;\n}\n\n/**\n * Creates and return the new layout for lines given an array of indexes to be removed.\n * @param lines The buffer lines.\n * @param toRemove The indexes to remove.\n */\nexport function reflowLargerCreateNewLayout(lines: CircularList, toRemove: number[]): INewLayoutResult {\n const layout: number[] = [];\n // First iterate through the list and get the actual indexes to use for rows\n let nextToRemoveIndex = 0;\n let nextToRemoveStart = toRemove[nextToRemoveIndex];\n let countRemovedSoFar = 0;\n for (let i = 0; i < lines.length; i++) {\n if (nextToRemoveStart === i) {\n const countToRemove = toRemove[++nextToRemoveIndex];\n\n // Tell markers that there was a deletion\n lines.onDeleteEmitter.fire({\n index: i - countRemovedSoFar,\n amount: countToRemove\n });\n\n i += countToRemove - 1;\n countRemovedSoFar += countToRemove;\n nextToRemoveStart = toRemove[++nextToRemoveIndex];\n } else {\n layout.push(i);\n }\n }\n return {\n layout,\n countRemoved: countRemovedSoFar\n };\n}\n\n/**\n * Applies a new layout to the buffer. This essentially does the same as many splice calls but it's\n * done all at once in a single iteration through the list since splice is very expensive.\n * @param lines The buffer lines.\n * @param newLayout The new layout to apply.\n */\nexport function reflowLargerApplyNewLayout(lines: CircularList, newLayout: number[]): void {\n // Record original lines so they don't get overridden when we rearrange the list\n const newLayoutLines: BufferLine[] = [];\n for (let i = 0; i < newLayout.length; i++) {\n newLayoutLines.push(lines.get(newLayout[i]) as BufferLine);\n }\n\n // Rearrange the list\n for (let i = 0; i < newLayoutLines.length; i++) {\n lines.set(i, newLayoutLines[i]);\n }\n lines.length = newLayout.length;\n}\n\n/**\n * Gets the new line lengths for a given wrapped line. The purpose of this function it to pre-\n * compute the wrapping points since wide characters may need to be wrapped onto the following line.\n * This function will return an array of numbers of where each line wraps to, the resulting array\n * will only contain the values `newCols` (when the line does not end with a wide character) and\n * `newCols - 1` (when the line does end with a wide character), except for the last value which\n * will contain the remaining items to fill the line.\n *\n * Calling this with a `newCols` value of `1` will lock up.\n *\n * @param wrappedLines The wrapped lines to evaluate.\n * @param oldCols The columns before resize.\n * @param newCols The columns after resize.\n */\nexport function reflowSmallerGetNewLineLengths(wrappedLines: BufferLine[], oldCols: number, newCols: number): number[] {\n const newLineLengths: number[] = [];\n const cellsNeeded = wrappedLines.map((l, i) => getWrappedLineTrimmedLength(wrappedLines, i, oldCols)).reduce((p, c) => p + c);\n\n // Use srcCol and srcLine to find the new wrapping point, use that to get the cellsAvailable and\n // linesNeeded\n let srcCol = 0;\n let srcLine = 0;\n let cellsAvailable = 0;\n while (cellsAvailable < cellsNeeded) {\n if (cellsNeeded - cellsAvailable < newCols) {\n // Add the final line and exit the loop\n newLineLengths.push(cellsNeeded - cellsAvailable);\n break;\n }\n srcCol += newCols;\n const oldTrimmedLength = getWrappedLineTrimmedLength(wrappedLines, srcLine, oldCols);\n if (srcCol > oldTrimmedLength) {\n srcCol -= oldTrimmedLength;\n srcLine++;\n }\n const endsWithWide = wrappedLines[srcLine].getWidth(srcCol - 1) === 2;\n if (endsWithWide) {\n srcCol--;\n }\n const lineLength = endsWithWide ? newCols - 1 : newCols;\n newLineLengths.push(lineLength);\n cellsAvailable += lineLength;\n }\n\n return newLineLengths;\n}\n\nexport function getWrappedLineTrimmedLength(lines: BufferLine[], i: number, cols: number): number {\n // If this is the last row in the wrapped line, get the actual trimmed length\n if (i === lines.length - 1) {\n return lines[i].getTrimmedLength();\n }\n // Detect whether the following line starts with a wide character and the end of the current line\n // is null, if so then we can be pretty sure the null character should be excluded from the line\n // length]\n const endsInNull = !(lines[i].hasContent(cols - 1)) && lines[i].getWidth(cols - 1) === 1;\n const followingLineStartsWithWide = lines[i + 1].getWidth(0) === 2;\n if (endsInNull && followingLineStartsWithWide) {\n return cols - 1;\n }\n return cols;\n}\n","/**\n * Copyright (c) 2018 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { EventEmitter, IEvent } from 'common/EventEmitter';\nimport { Disposable } from 'common/Lifecycle';\nimport { IMarker } from 'common/Types';\n\nexport class Marker extends Disposable implements IMarker {\n private static _nextId = 1;\n\n private _id: number = Marker._nextId++;\n public isDisposed: boolean = false;\n\n public get id(): number { return this._id; }\n\n private _onDispose = new EventEmitter();\n public get onDispose(): IEvent { return this._onDispose.event; }\n\n constructor(\n public line: number\n ) {\n super();\n }\n\n public dispose(): void {\n if (this.isDisposed) {\n return;\n }\n this.isDisposed = true;\n this.line = -1;\n // Emit before super.dispose such that dispose listeners get a change to react\n this._onDispose.fire();\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { ICharSizeService, IRenderService, IMouseService } from './Services';\nimport { getCoords, getRawByteCoords } from 'browser/input/Mouse';\n\nexport class MouseService implements IMouseService {\n serviceBrand: any;\n\n constructor(\n @IRenderService private readonly _renderService: IRenderService,\n @ICharSizeService private readonly _charSizeService: ICharSizeService\n ) {\n }\n\n public getCoords(event: {clientX: number, clientY: number}, element: HTMLElement, colCount: number, rowCount: number, isSelection?: boolean): [number, number] | undefined {\n return getCoords(\n event,\n element,\n colCount,\n rowCount,\n this._charSizeService.hasValidSize,\n this._renderService.dimensions.actualCellWidth,\n this._renderService.dimensions.actualCellHeight,\n isSelection\n );\n }\n\n public getRawByteCoords(event: MouseEvent, element: HTMLElement, colCount: number, rowCount: number): { x: number, y: number } | undefined {\n const coords = this.getCoords(event, element, colCount, rowCount);\n return getRawByteCoords(coords);\n }\n}\n","/**\n * Copyright (c) 2019 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { ICoreService, ILogService, IOptionsService, IBufferService } from 'common/services/Services';\nimport { EventEmitter, IEvent } from 'common/EventEmitter';\nimport { IDecPrivateModes, ICharset } from 'common/Types';\nimport { clone } from 'common/Clone';\n\nconst DEFAULT_DEC_PRIVATE_MODES: IDecPrivateModes = Object.freeze({\n applicationCursorKeys: false,\n applicationKeypad: false,\n origin: false,\n wraparound: true // defaults: xterm - true, vt100 - false\n});\n\nexport class CoreService implements ICoreService {\n serviceBrand: any;\n\n public isCursorInitialized: boolean = false;\n public isCursorHidden: boolean = false;\n public decPrivateModes: IDecPrivateModes;\n\n private _onData = new EventEmitter();\n public get onData(): IEvent { return this._onData.event; }\n private _onUserInput = new EventEmitter();\n public get onUserInput(): IEvent { return this._onUserInput.event; }\n private _onBinary = new EventEmitter();\n public get onBinary(): IEvent { return this._onBinary.event; }\n\n constructor(\n // TODO: Move this into a service\n private readonly _scrollToBottom: () => void,\n @IBufferService private readonly _bufferService: IBufferService,\n @ILogService private readonly _logService: ILogService,\n @IOptionsService private readonly _optionsService: IOptionsService\n ) {\n this.decPrivateModes = clone(DEFAULT_DEC_PRIVATE_MODES);\n }\n\n public reset(): void {\n this.decPrivateModes = clone(DEFAULT_DEC_PRIVATE_MODES);\n }\n\n public triggerDataEvent(data: string, wasUserInput: boolean = false): void {\n // Prevents all events to pty process if stdin is disabled\n if (this._optionsService.options.disableStdin) {\n return;\n }\n\n // Input is being sent to the terminal, the terminal should focus the prompt.\n const buffer = this._bufferService.buffer;\n if (buffer.ybase !== buffer.ydisp) {\n this._scrollToBottom();\n }\n\n // Fire onUserInput so listeners can react as well (eg. clear selection)\n if (wasUserInput) {\n this._onUserInput.fire();\n }\n\n // Fire onData API\n this._logService.debug(`sending data \"${data}\"`, () => data.split('').map(e => e.charCodeAt(0)));\n this._onData.fire(data);\n }\n\n public triggerBinaryEvent(data: string): void {\n if (this._optionsService.options.disableStdin) {\n return;\n }\n this._logService.debug(`sending binary \"${data}\"`, () => data.split('').map(e => e.charCodeAt(0)));\n this._onBinary.fire(data);\n }\n}\n","/**\n * Copyright (c) 2019 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { ILogService, IOptionsService } from 'common/services/Services';\n\ntype LogType = (message?: any, ...optionalParams: any[]) => void;\n\ninterface IConsole {\n log: LogType;\n error: LogType;\n info: LogType;\n trace: LogType;\n warn: LogType;\n}\n\n// console is available on both node.js and browser contexts but the common\n// module doesn't depend on them so we need to explicitly declare it.\ndeclare const console: IConsole;\n\n\nexport enum LogLevel {\n DEBUG = 0,\n INFO = 1,\n WARN = 2,\n ERROR = 3,\n OFF = 4\n}\n\nconst optionsKeyToLogLevel: { [key: string]: LogLevel } = {\n debug: LogLevel.DEBUG,\n info: LogLevel.INFO,\n warn: LogLevel.WARN,\n error: LogLevel.ERROR,\n off: LogLevel.OFF\n};\n\nconst LOG_PREFIX = 'xterm.js: ';\n\nexport class LogService implements ILogService {\n serviceBrand: any;\n\n private _logLevel!: LogLevel;\n\n constructor(\n @IOptionsService private readonly _optionsService: IOptionsService\n ) {\n this._updateLogLevel();\n this._optionsService.onOptionChange(key => {\n if (key === 'logLevel') {\n this._updateLogLevel();\n }\n });\n }\n\n private _updateLogLevel(): void {\n this._logLevel = optionsKeyToLogLevel[this._optionsService.options.logLevel];\n }\n\n private _evalLazyOptionalParams(optionalParams: any[]): void {\n for (let i = 0; i < optionalParams.length; i++) {\n if (typeof optionalParams[i] === 'function') {\n optionalParams[i] = optionalParams[i]();\n }\n }\n }\n\n private _log(type: LogType, message: string, optionalParams: any[]): void {\n this._evalLazyOptionalParams(optionalParams);\n type.call(console, LOG_PREFIX + message, ...optionalParams);\n }\n\n debug(message: string, ...optionalParams: any[]): void {\n if (this._logLevel <= LogLevel.DEBUG) {\n this._log(console.log, message, optionalParams);\n }\n }\n\n info(message: string, ...optionalParams: any[]): void {\n if (this._logLevel <= LogLevel.INFO) {\n this._log(console.info, message, optionalParams);\n }\n }\n\n warn(message: string, ...optionalParams: any[]): void {\n if (this._logLevel <= LogLevel.WARN) {\n this._log(console.warn, message, optionalParams);\n }\n }\n\n error(message: string, ...optionalParams: any[]): void {\n if (this._logLevel <= LogLevel.ERROR) {\n this._log(console.error, message, optionalParams);\n }\n }\n}\n","/**\n * Copyright (c) 2019 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { IBufferService, IDirtyRowService } from 'common/services/Services';\n\nexport class DirtyRowService implements IDirtyRowService {\n serviceBrand: any;\n\n private _start!: number;\n private _end!: number;\n\n public get start(): number { return this._start; }\n public get end(): number { return this._end; }\n\n constructor(\n @IBufferService private readonly _bufferService: IBufferService\n ) {\n this.clearRange();\n }\n\n public clearRange(): void {\n this._start = this._bufferService.buffer.y;\n this._end = this._bufferService.buffer.y;\n }\n\n public markDirty(y: number): void {\n if (y < this._start) {\n this._start = y;\n } else if (y > this._end) {\n this._end = y;\n }\n }\n\n public markRangeDirty(y1: number, y2: number): void {\n if (y1 > y2) {\n const temp = y1;\n y1 = y2;\n y2 = temp;\n }\n if (y1 < this._start) {\n this._start = y1;\n }\n if (y2 > this._end) {\n this._end = y2;\n }\n }\n\n public markAllDirty(): void {\n this.markRangeDirty(0, this._bufferService.rows - 1);\n }\n}\n","/**\n * Copyright (c) 2019 The xterm.js authors. All rights reserved.\n * @license MIT\n *\n * This was heavily inspired from microsoft/vscode's dependency injection system (MIT).\n */\n/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\nimport { IInstantiationService, IServiceIdentifier } from 'common/services/Services';\nimport { getServiceDependencies } from 'common/services/ServiceRegistry';\n\nexport class ServiceCollection {\n\n private _entries = new Map, any>();\n\n constructor(...entries: [IServiceIdentifier, any][]) {\n for (const [id, service] of entries) {\n this.set(id, service);\n }\n }\n\n set(id: IServiceIdentifier, instance: T): T {\n const result = this._entries.get(id);\n this._entries.set(id, instance);\n return result;\n }\n\n forEach(callback: (id: IServiceIdentifier, instance: any) => any): void {\n this._entries.forEach((value, key) => callback(key, value));\n }\n\n has(id: IServiceIdentifier): boolean {\n return this._entries.has(id);\n }\n\n get(id: IServiceIdentifier): T | undefined {\n return this._entries.get(id);\n }\n}\n\nexport class InstantiationService implements IInstantiationService {\n private readonly _services: ServiceCollection = new ServiceCollection();\n\n constructor() {\n this._services.set(IInstantiationService, this);\n }\n\n public setService(id: IServiceIdentifier, instance: T): void {\n this._services.set(id, instance);\n }\n\n public getService(id: IServiceIdentifier): T | undefined {\n return this._services.get(id);\n }\n\n public createInstance(ctor: any, ...args: any[]): any {\n const serviceDependencies = getServiceDependencies(ctor).sort((a, b) => a.index - b.index);\n\n const serviceArgs: any[] = [];\n for (const dependency of serviceDependencies) {\n const service = this._services.get(dependency.id);\n if (!service) {\n throw new Error(`[createInstance] ${ctor.name} depends on UNKNOWN service ${dependency.id}.`);\n }\n serviceArgs.push(service);\n }\n\n const firstServiceArgPos = serviceDependencies.length > 0 ? serviceDependencies[0].index : args.length;\n\n // check for argument mismatches, adjust static args if needed\n if (args.length !== firstServiceArgPos) {\n throw new Error(`[createInstance] First service dependency of ${ctor.name} at position ${firstServiceArgPos + 1} conflicts with ${args.length} static arguments`);\n }\n\n // now create the instance\n return new ctor(...[...args, ...serviceArgs]);\n }\n}\n","/**\n * Copyright (c) 2019 The xterm.js authors. All rights reserved.\n * @license MIT\n */\nimport { IBufferService, ICoreService, ICoreMouseService } from 'common/services/Services';\nimport { EventEmitter, IEvent } from 'common/EventEmitter';\nimport { ICoreMouseProtocol, ICoreMouseEvent, CoreMouseEncoding, CoreMouseEventType, CoreMouseButton, CoreMouseAction } from 'common/Types';\n\n/**\n * Supported default protocols.\n */\nconst DEFAULT_PROTOCOLS: {[key: string]: ICoreMouseProtocol} = {\n /**\n * NONE\n * Events: none\n * Modifiers: none\n */\n NONE: {\n events: CoreMouseEventType.NONE,\n restrict: () => false\n },\n /**\n * X10\n * Events: mousedown\n * Modifiers: none\n */\n X10: {\n events: CoreMouseEventType.DOWN,\n restrict: (e: ICoreMouseEvent) => {\n // no wheel, no move, no up\n if (e.button === CoreMouseButton.WHEEL || e.action !== CoreMouseAction.DOWN) {\n return false;\n }\n // no modifiers\n e.ctrl = false;\n e.alt = false;\n e.shift = false;\n return true;\n }\n },\n /**\n * VT200\n * Events: mousedown / mouseup / wheel\n * Modifiers: all\n */\n VT200: {\n events: CoreMouseEventType.DOWN | CoreMouseEventType.UP | CoreMouseEventType.WHEEL,\n restrict: (e: ICoreMouseEvent) => {\n // no move\n if (e.action === CoreMouseAction.MOVE) {\n return false;\n }\n return true;\n }\n },\n /**\n * DRAG\n * Events: mousedown / mouseup / wheel / mousedrag\n * Modifiers: all\n */\n DRAG: {\n events: CoreMouseEventType.DOWN | CoreMouseEventType.UP | CoreMouseEventType.WHEEL | CoreMouseEventType.DRAG,\n restrict: (e: ICoreMouseEvent) => {\n // no move without button\n if (e.action === CoreMouseAction.MOVE && e.button === CoreMouseButton.NONE) {\n return false;\n }\n return true;\n }\n },\n /**\n * ANY\n * Events: all mouse related events\n * Modifiers: all\n */\n ANY: {\n events:\n CoreMouseEventType.DOWN | CoreMouseEventType.UP | CoreMouseEventType.WHEEL\n | CoreMouseEventType.DRAG | CoreMouseEventType.MOVE,\n restrict: (e: ICoreMouseEvent) => true\n }\n};\n\nconst enum Modifiers {\n SHIFT = 4,\n ALT = 8,\n CTRL = 16\n}\n\n// helper for default encoders to generate the event code.\nfunction eventCode(e: ICoreMouseEvent, isSGR: boolean): number {\n let code = (e.ctrl ? Modifiers.CTRL : 0) | (e.shift ? Modifiers.SHIFT : 0) | (e.alt ? Modifiers.ALT : 0);\n if (e.button === CoreMouseButton.WHEEL) {\n code |= 64;\n code |= e.action;\n } else {\n code |= e.button & 3;\n if (e.button & 4) {\n code |= 64;\n }\n if (e.button & 8) {\n code |= 128;\n }\n if (e.action === CoreMouseAction.MOVE) {\n code |= CoreMouseAction.MOVE;\n } else if (e.action === CoreMouseAction.UP && !isSGR) {\n // special case - only SGR can report button on release\n // all others have to go with NONE\n code |= CoreMouseButton.NONE;\n }\n }\n return code;\n}\n\nconst S = String.fromCharCode;\n\n/**\n * Supported default encodings.\n */\nconst DEFAULT_ENCODINGS: {[key: string]: CoreMouseEncoding} = {\n /**\n * DEFAULT - CSI M Pb Px Py\n * Single byte encoding for coords and event code.\n * Can encode values up to 223 (1-based).\n */\n DEFAULT: (e: ICoreMouseEvent) => {\n const params = [eventCode(e, false) + 32, e.col + 32, e.row + 32];\n // supress mouse report if we exceed addressible range\n // Note this is handled differently by emulators\n // - xterm: sends 0;0 coords instead\n // - vte, konsole: no report\n if (params[0] > 255 || params[1] > 255 || params[2] > 255) {\n return '';\n }\n return `\\x1b[M${S(params[0])}${S(params[1])}${S(params[2])}`;\n },\n /**\n * SGR - CSI < Pb ; Px ; Py M|m\n * No encoding limitation.\n * Can report button on release and works with a well formed sequence.\n */\n SGR: (e: ICoreMouseEvent) => {\n const final = (e.action === CoreMouseAction.UP && e.button !== CoreMouseButton.WHEEL) ? 'm' : 'M';\n return `\\x1b[<${eventCode(e, true)};${e.col};${e.row}${final}`;\n }\n};\n\n/**\n * CoreMouseService\n *\n * Provides mouse tracking reports with different protocols and encodings.\n * - protocols: NONE (default), X10, VT200, DRAG, ANY\n * - encodings: DEFAULT, SGR (UTF8, URXVT removed in #2507)\n *\n * Custom protocols/encodings can be added by `addProtocol` / `addEncoding`.\n * To activate a protocol/encoding, set `activeProtocol` / `activeEncoding`.\n * Switching a protocol will send a notification event `onProtocolChange`\n * with a list of needed events to track.\n *\n * The service handles the mouse tracking state and decides whether to send\n * a tracking report to the backend based on protocol and encoding limitations.\n * To send a mouse event call `triggerMouseEvent`.\n */\nexport class CoreMouseService implements ICoreMouseService {\n private _protocols: {[name: string]: ICoreMouseProtocol} = {};\n private _encodings: {[name: string]: CoreMouseEncoding} = {};\n private _activeProtocol: string = '';\n private _activeEncoding: string = '';\n private _onProtocolChange = new EventEmitter();\n private _lastEvent: ICoreMouseEvent | null = null;\n\n constructor(\n @IBufferService private readonly _bufferService: IBufferService,\n @ICoreService private readonly _coreService: ICoreService\n ) {\n // register default protocols and encodings\n Object.keys(DEFAULT_PROTOCOLS).forEach(name => this.addProtocol(name, DEFAULT_PROTOCOLS[name]));\n Object.keys(DEFAULT_ENCODINGS).forEach(name => this.addEncoding(name, DEFAULT_ENCODINGS[name]));\n // call reset to set defaults\n this.reset();\n }\n\n public addProtocol(name: string, protocol: ICoreMouseProtocol): void {\n this._protocols[name] = protocol;\n }\n\n public addEncoding(name: string, encoding: CoreMouseEncoding): void {\n this._encodings[name] = encoding;\n }\n\n public get activeProtocol(): string {\n return this._activeProtocol;\n }\n\n public set activeProtocol(name: string) {\n if (!this._protocols[name]) {\n throw new Error(`unknown protocol \"${name}\"`);\n }\n this._activeProtocol = name;\n this._onProtocolChange.fire(this._protocols[name].events);\n }\n\n public get activeEncoding(): string {\n return this._activeEncoding;\n }\n\n public set activeEncoding(name: string) {\n if (!this._encodings[name]) {\n throw new Error(`unknown encoding \"${name}\"`);\n }\n this._activeEncoding = name;\n }\n\n public reset(): void {\n this.activeProtocol = 'NONE';\n this.activeEncoding = 'DEFAULT';\n this._lastEvent = null;\n }\n\n /**\n * Event to announce changes in mouse tracking.\n */\n public get onProtocolChange(): IEvent {\n return this._onProtocolChange.event;\n }\n\n /**\n * Triggers a mouse event to be sent.\n *\n * Returns true if the event passed all protocol restrictions and a report\n * was sent, otherwise false. The return value may be used to decide whether\n * the default event action in the bowser component should be omitted.\n *\n * Note: The method will change values of the given event object\n * to fullfill protocol and encoding restrictions.\n */\n public triggerMouseEvent(e: ICoreMouseEvent): boolean {\n // range check for col/row\n if (e.col < 0 || e.col >= this._bufferService.cols\n || e.row < 0 || e.row >= this._bufferService.rows) {\n return false;\n }\n\n // filter nonsense combinations of button + action\n if (e.button === CoreMouseButton.WHEEL && e.action === CoreMouseAction.MOVE) {\n return false;\n }\n if (e.button === CoreMouseButton.NONE && e.action !== CoreMouseAction.MOVE) {\n return false;\n }\n if (e.button !== CoreMouseButton.WHEEL && (e.action === CoreMouseAction.LEFT || e.action === CoreMouseAction.RIGHT)) {\n return false;\n }\n\n // report 1-based coords\n e.col++;\n e.row++;\n\n // debounce move at grid level\n if (e.action === CoreMouseAction.MOVE && this._lastEvent && this._compareEvents(this._lastEvent, e)) {\n return false;\n }\n\n // apply protocol restrictions\n if (!this._protocols[this._activeProtocol].restrict(e)) {\n return false;\n }\n\n // encode report and send\n const report = this._encodings[this._activeEncoding](e);\n if (report) {\n // always send DEFAULT as binary data\n if (this._activeEncoding === 'DEFAULT') {\n this._coreService.triggerBinaryEvent(report);\n } else {\n this._coreService.triggerDataEvent(report, true);\n }\n }\n\n this._lastEvent = e;\n\n return true;\n }\n\n public explainEvents(events: CoreMouseEventType): {[event: string]: boolean} {\n return {\n DOWN: !!(events & CoreMouseEventType.DOWN),\n UP: !!(events & CoreMouseEventType.UP),\n DRAG: !!(events & CoreMouseEventType.DRAG),\n MOVE: !!(events & CoreMouseEventType.MOVE),\n WHEEL: !!(events & CoreMouseEventType.WHEEL)\n };\n }\n\n private _compareEvents(e1: ICoreMouseEvent, e2: ICoreMouseEvent): boolean {\n if (e1.col !== e2.col) return false;\n if (e1.row !== e2.row) return false;\n if (e1.button !== e2.button) return false;\n if (e1.action !== e2.action) return false;\n if (e1.ctrl !== e2.ctrl) return false;\n if (e1.alt !== e2.alt) return false;\n if (e1.shift !== e2.shift) return false;\n return true;\n }\n}\n","\n/**\n * Copyright (c) 2019 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\ndeclare const setTimeout: (handler: () => void, timeout?: number) => void;\n\n/**\n * Safety watermark to avoid memory exhaustion and browser engine crash on fast data input.\n * Enable flow control to avoid this limit and make sure that your backend correctly\n * propagates this to the underlying pty. (see docs for further instructions)\n * Since this limit is meant as a safety parachute to prevent browser crashs,\n * it is set to a very high number. Typically xterm.js gets unresponsive with\n * a 100 times lower number (>500 kB).\n */\nconst DISCARD_WATERMARK = 50000000; // ~50 MB\n\n/**\n * The max number of ms to spend on writes before allowing the renderer to\n * catch up with a 0ms setTimeout. A value of < 33 to keep us close to\n * 30fps, and a value of < 16 to try to run at 60fps. Of course, the real FPS\n * depends on the time it takes for the renderer to draw the frame.\n */\nconst WRITE_TIMEOUT_MS = 12;\n\n/**\n * Threshold of max held chunks in the write buffer, that were already processed.\n * This is a tradeoff between extensive write buffer shifts (bad runtime) and high\n * memory consumption by data thats not used anymore.\n */\nconst WRITE_BUFFER_LENGTH_THRESHOLD = 50;\n\nexport class WriteBuffer {\n private _writeBuffer: (string | Uint8Array)[] = [];\n private _callbacks: ((() => void) | undefined)[] = [];\n private _pendingData = 0;\n private _bufferOffset = 0;\n\n constructor(private _action: (data: string | Uint8Array) => void) { }\n\n public writeSync(data: string | Uint8Array): void {\n // force sync processing on pending data chunks to avoid in-band data scrambling\n // does the same as innerWrite but without event loop\n if (this._writeBuffer.length) {\n for (let i = this._bufferOffset; i < this._writeBuffer.length; ++i) {\n const data = this._writeBuffer[i];\n const cb = this._callbacks[i];\n this._action(data);\n if (cb) cb();\n }\n // reset all to avoid reprocessing of chunks with scheduled innerWrite call\n this._writeBuffer = [];\n this._callbacks = [];\n this._pendingData = 0;\n // stop scheduled innerWrite by offset > length condition\n this._bufferOffset = 0x7FFFFFFF;\n }\n // handle current data chunk\n this._action(data);\n }\n\n public write(data: string | Uint8Array, callback?: () => void): void {\n if (this._pendingData > DISCARD_WATERMARK) {\n throw new Error('write data discarded, use flow control to avoid losing data');\n }\n\n // schedule chunk processing for next event loop run\n if (!this._writeBuffer.length) {\n this._bufferOffset = 0;\n setTimeout(() => this._innerWrite());\n }\n\n this._pendingData += data.length;\n this._writeBuffer.push(data);\n this._callbacks.push(callback);\n }\n\n protected _innerWrite(): void {\n const startTime = Date.now();\n while (this._writeBuffer.length > this._bufferOffset) {\n const data = this._writeBuffer[this._bufferOffset];\n const cb = this._callbacks[this._bufferOffset];\n this._bufferOffset++;\n\n this._action(data);\n this._pendingData -= data.length;\n if (cb) cb();\n\n if (Date.now() - startTime >= WRITE_TIMEOUT_MS) {\n break;\n }\n }\n if (this._writeBuffer.length > this._bufferOffset) {\n // Allow renderer to catch up before processing the next batch\n // trim already processed chunks if we are above threshold\n if (this._bufferOffset > WRITE_BUFFER_LENGTH_THRESHOLD) {\n this._writeBuffer = this._writeBuffer.slice(this._bufferOffset);\n this._callbacks = this._callbacks.slice(this._bufferOffset);\n this._bufferOffset = 0;\n }\n setTimeout(() => this._innerWrite(), 0);\n } else {\n this._writeBuffer = [];\n this._callbacks = [];\n this._pendingData = 0;\n this._bufferOffset = 0;\n }\n }\n}\n","/**\n * Copyright (c) 2019 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { ICoreBrowserService } from './Services';\n\nexport class CoreBrowserService implements ICoreBrowserService {\n serviceBrand: any;\n\n constructor(\n private _textarea: HTMLTextAreaElement\n ) {\n }\n\n public get isFocused(): boolean {\n return document.activeElement === this._textarea && document.hasFocus();\n }\n}\n","/**\n * Copyright (c) 2019 The xterm.js authors. All rights reserved.\n * @license MIT\n */\nimport { IUnicodeService, IUnicodeVersionProvider } from 'common/services/Services';\nimport { EventEmitter, IEvent } from 'common/EventEmitter';\nimport { UnicodeV6 } from 'common/input/UnicodeV6';\n\n\nexport class UnicodeService implements IUnicodeService {\n private _providers: {[key: string]: IUnicodeVersionProvider} = Object.create(null);\n private _active: string = '';\n private _activeProvider: IUnicodeVersionProvider;\n private _onChange = new EventEmitter();\n public get onChange(): IEvent { return this._onChange.event; }\n\n constructor() {\n const defaultProvider = new UnicodeV6();\n this.register(defaultProvider);\n this._active = defaultProvider.version;\n this._activeProvider = defaultProvider;\n }\n\n public get versions(): string[] {\n return Object.keys(this._providers);\n }\n\n public get activeVersion(): string {\n return this._active;\n }\n\n public set activeVersion(version: string) {\n if (!this._providers[version]) {\n throw new Error(`unknown Unicode version \"${version}\"`);\n }\n this._active = version;\n this._activeProvider = this._providers[version];\n this._onChange.fire(version);\n }\n\n public register(provider: IUnicodeVersionProvider): void {\n this._providers[provider.version] = provider;\n }\n\n /**\n * Unicode version dependent interface.\n */\n public wcwidth(num: number): number {\n return this._activeProvider.wcwidth(num);\n }\n\n public getStringCellWidth(s: string): number {\n let result = 0;\n const length = s.length;\n for (let i = 0; i < length; ++i) {\n let code = s.charCodeAt(i);\n // surrogate pair first\n if (0xD800 <= code && code <= 0xDBFF) {\n if (++i >= length) {\n // this should not happen with strings retrieved from\n // Buffer.translateToString as it converts from UTF-32\n // and therefore always should contain the second part\n // for any other string we still have to handle it somehow:\n // simply treat the lonely surrogate first as a single char (UCS-2 behavior)\n return result + this.wcwidth(code);\n }\n const second = s.charCodeAt(i);\n // convert surrogate pair to high codepoint only for valid second part (UTF-16)\n // otherwise treat them independently (UCS-2 behavior)\n if (0xDC00 <= second && second <= 0xDFFF) {\n code = (code - 0xD800) * 0x400 + second - 0xDC00 + 0x10000;\n } else {\n result += this.wcwidth(second);\n }\n }\n result += this.wcwidth(code);\n }\n return result;\n }\n}\n","/**\n * Copyright (c) 2019 The xterm.js authors. All rights reserved.\n * @license MIT\n */\nimport { IUnicodeVersionProvider } from 'common/services/Services';\nimport { fill } from 'common/TypedArrayUtils';\n\ntype CharWidth = 0 | 1 | 2;\n\nconst BMP_COMBINING = [\n [0x0300, 0x036F], [0x0483, 0x0486], [0x0488, 0x0489],\n [0x0591, 0x05BD], [0x05BF, 0x05BF], [0x05C1, 0x05C2],\n [0x05C4, 0x05C5], [0x05C7, 0x05C7], [0x0600, 0x0603],\n [0x0610, 0x0615], [0x064B, 0x065E], [0x0670, 0x0670],\n [0x06D6, 0x06E4], [0x06E7, 0x06E8], [0x06EA, 0x06ED],\n [0x070F, 0x070F], [0x0711, 0x0711], [0x0730, 0x074A],\n [0x07A6, 0x07B0], [0x07EB, 0x07F3], [0x0901, 0x0902],\n [0x093C, 0x093C], [0x0941, 0x0948], [0x094D, 0x094D],\n [0x0951, 0x0954], [0x0962, 0x0963], [0x0981, 0x0981],\n [0x09BC, 0x09BC], [0x09C1, 0x09C4], [0x09CD, 0x09CD],\n [0x09E2, 0x09E3], [0x0A01, 0x0A02], [0x0A3C, 0x0A3C],\n [0x0A41, 0x0A42], [0x0A47, 0x0A48], [0x0A4B, 0x0A4D],\n [0x0A70, 0x0A71], [0x0A81, 0x0A82], [0x0ABC, 0x0ABC],\n [0x0AC1, 0x0AC5], [0x0AC7, 0x0AC8], [0x0ACD, 0x0ACD],\n [0x0AE2, 0x0AE3], [0x0B01, 0x0B01], [0x0B3C, 0x0B3C],\n [0x0B3F, 0x0B3F], [0x0B41, 0x0B43], [0x0B4D, 0x0B4D],\n [0x0B56, 0x0B56], [0x0B82, 0x0B82], [0x0BC0, 0x0BC0],\n [0x0BCD, 0x0BCD], [0x0C3E, 0x0C40], [0x0C46, 0x0C48],\n [0x0C4A, 0x0C4D], [0x0C55, 0x0C56], [0x0CBC, 0x0CBC],\n [0x0CBF, 0x0CBF], [0x0CC6, 0x0CC6], [0x0CCC, 0x0CCD],\n [0x0CE2, 0x0CE3], [0x0D41, 0x0D43], [0x0D4D, 0x0D4D],\n [0x0DCA, 0x0DCA], [0x0DD2, 0x0DD4], [0x0DD6, 0x0DD6],\n [0x0E31, 0x0E31], [0x0E34, 0x0E3A], [0x0E47, 0x0E4E],\n [0x0EB1, 0x0EB1], [0x0EB4, 0x0EB9], [0x0EBB, 0x0EBC],\n [0x0EC8, 0x0ECD], [0x0F18, 0x0F19], [0x0F35, 0x0F35],\n [0x0F37, 0x0F37], [0x0F39, 0x0F39], [0x0F71, 0x0F7E],\n [0x0F80, 0x0F84], [0x0F86, 0x0F87], [0x0F90, 0x0F97],\n [0x0F99, 0x0FBC], [0x0FC6, 0x0FC6], [0x102D, 0x1030],\n [0x1032, 0x1032], [0x1036, 0x1037], [0x1039, 0x1039],\n [0x1058, 0x1059], [0x1160, 0x11FF], [0x135F, 0x135F],\n [0x1712, 0x1714], [0x1732, 0x1734], [0x1752, 0x1753],\n [0x1772, 0x1773], [0x17B4, 0x17B5], [0x17B7, 0x17BD],\n [0x17C6, 0x17C6], [0x17C9, 0x17D3], [0x17DD, 0x17DD],\n [0x180B, 0x180D], [0x18A9, 0x18A9], [0x1920, 0x1922],\n [0x1927, 0x1928], [0x1932, 0x1932], [0x1939, 0x193B],\n [0x1A17, 0x1A18], [0x1B00, 0x1B03], [0x1B34, 0x1B34],\n [0x1B36, 0x1B3A], [0x1B3C, 0x1B3C], [0x1B42, 0x1B42],\n [0x1B6B, 0x1B73], [0x1DC0, 0x1DCA], [0x1DFE, 0x1DFF],\n [0x200B, 0x200F], [0x202A, 0x202E], [0x2060, 0x2063],\n [0x206A, 0x206F], [0x20D0, 0x20EF], [0x302A, 0x302F],\n [0x3099, 0x309A], [0xA806, 0xA806], [0xA80B, 0xA80B],\n [0xA825, 0xA826], [0xFB1E, 0xFB1E], [0xFE00, 0xFE0F],\n [0xFE20, 0xFE23], [0xFEFF, 0xFEFF], [0xFFF9, 0xFFFB]\n];\nconst HIGH_COMBINING = [\n [0x10A01, 0x10A03], [0x10A05, 0x10A06], [0x10A0C, 0x10A0F],\n [0x10A38, 0x10A3A], [0x10A3F, 0x10A3F], [0x1D167, 0x1D169],\n [0x1D173, 0x1D182], [0x1D185, 0x1D18B], [0x1D1AA, 0x1D1AD],\n [0x1D242, 0x1D244], [0xE0001, 0xE0001], [0xE0020, 0xE007F],\n [0xE0100, 0xE01EF]\n];\n\n// BMP lookup table, lazy initialized during first addon loading\nlet table: Uint8Array;\n\nfunction bisearch(ucs: number, data: number[][]): boolean {\n let min = 0;\n let max = data.length - 1;\n let mid;\n if (ucs < data[0][0] || ucs > data[max][1]) {\n return false;\n }\n while (max >= min) {\n mid = (min + max) >> 1;\n if (ucs > data[mid][1]) {\n min = mid + 1;\n } else if (ucs < data[mid][0]) {\n max = mid - 1;\n } else {\n return true;\n }\n }\n return false;\n}\n\nexport class UnicodeV6 implements IUnicodeVersionProvider {\n public readonly version = '6';\n\n constructor() {\n // init lookup table once\n if (!table) {\n table = new Uint8Array(65536);\n fill(table, 1);\n table[0] = 0;\n // control chars\n fill(table, 0, 1, 32);\n fill(table, 0, 0x7f, 0xa0);\n\n // apply wide char rules first\n // wide chars\n fill(table, 2, 0x1100, 0x1160);\n table[0x2329] = 2;\n table[0x232a] = 2;\n fill(table, 2, 0x2e80, 0xa4d0);\n table[0x303f] = 1; // wrongly in last line\n\n fill(table, 2, 0xac00, 0xd7a4);\n fill(table, 2, 0xf900, 0xfb00);\n fill(table, 2, 0xfe10, 0xfe1a);\n fill(table, 2, 0xfe30, 0xfe70);\n fill(table, 2, 0xff00, 0xff61);\n fill(table, 2, 0xffe0, 0xffe7);\n\n // apply combining last to ensure we overwrite\n // wrongly wide set chars:\n // the original algo evals combining first and falls\n // through to wide check so we simply do here the opposite\n // combining 0\n for (let r = 0; r < BMP_COMBINING.length; ++r) {\n fill(table, 0, BMP_COMBINING[r][0], BMP_COMBINING[r][1] + 1);\n }\n }\n }\n\n public wcwidth(num: number): CharWidth {\n if (num < 32) return 0;\n if (num < 127) return 1;\n if (num < 65536) return table[num] as CharWidth;\n if (bisearch(num, HIGH_COMBINING)) return 0;\n if ((num >= 0x20000 && num <= 0x2fffd) || (num >= 0x30000 && num <= 0x3fffd)) return 2;\n return 1;\n }\n}\n","/**\n * Copyright (c) 2019 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { ICharsetService } from 'common/services/Services';\nimport { ICharset } from 'common/Types';\n\nexport class CharsetService implements ICharsetService {\n serviceBrand: any;\n\n public charset: ICharset | undefined;\n public charsets: ICharset[] = [];\n public glevel: number = 0;\n\n public reset(): void {\n this.charset = undefined;\n this.charsets = [];\n this.glevel = 0;\n }\n\n public setgLevel(g: number): void {\n this.glevel = g;\n this.charset = this.charsets[g];\n }\n\n public setgCharset(g: number, charset: ICharset): void {\n this.charsets[g] = charset;\n if (this.glevel === g) {\n this.charset = charset;\n }\n }\n}\n","/**\n * Copyright (c) 2019 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport { ITerminalAddon, IDisposable, Terminal } from 'xterm';\n\nexport interface ILoadedAddon {\n instance: ITerminalAddon;\n dispose: () => void;\n isDisposed: boolean;\n}\n\nexport class AddonManager implements IDisposable {\n protected _addons: ILoadedAddon[] = [];\n\n constructor() {\n }\n\n public dispose(): void {\n for (let i = this._addons.length - 1; i >= 0; i--) {\n this._addons[i].instance.dispose();\n }\n }\n\n public loadAddon(terminal: Terminal, instance: ITerminalAddon): void {\n const loadedAddon: ILoadedAddon = {\n instance,\n dispose: instance.dispose,\n isDisposed: false\n };\n this._addons.push(loadedAddon);\n instance.dispose = () => this._wrappedAddonDispose(loadedAddon);\n instance.activate(terminal);\n }\n\n private _wrappedAddonDispose(loadedAddon: ILoadedAddon): void {\n if (loadedAddon.isDisposed) {\n // Do nothing if already disposed\n return;\n }\n let index = -1;\n for (let i = 0; i < this._addons.length; i++) {\n if (this._addons[i] === loadedAddon) {\n index = i;\n break;\n }\n }\n if (index === -1) {\n throw new Error('Could not dispose an addon that has not been loaded');\n }\n loadedAddon.isDisposed = true;\n loadedAddon.dispose.apply(loadedAddon.instance);\n this._addons.splice(index, 1);\n }\n}\n"],"sourceRoot":""} \ No newline at end of file diff --git a/public/translate.bat b/public/translate.bat index c0f31f12..8772850d 100644 --- a/public/translate.bat +++ b/public/translate.bat @@ -1,5 +1,6 @@ @ECHO OFF CD ..\translate -C:\Users\Default.DESKTOP-M9I88C9\AppData\Roaming\nvm\v12.13.0\node translate.js minifyall -C:\Users\Default.DESKTOP-M9I88C9\AppData\Roaming\nvm\v12.13.0\node translate.js translateall -C:\Users\Default.DESKTOP-M9I88C9\AppData\Roaming\nvm\v12.13.0\node translate.js extractall +%LOCALAPPDATA%\..\Roaming\nvm\v12.13.0\node translate.js minifyall +%LOCALAPPDATA%\..\Roaming\nvm\v12.13.0\node translate.js translateall +%LOCALAPPDATA%\..\Roaming\nvm\v12.13.0\node translate.js extractall +DEL ..\emails\translations\*-min_* \ No newline at end of file diff --git a/redirserver.js b/redirserver.js index a3a74071..50d560dd 100644 --- a/redirserver.js +++ b/redirserver.js @@ -75,7 +75,15 @@ module.exports.CreateRedirServer = function (parent, db, args, func) { parent.letsencrypt.challenge(req.url.slice(leChallengePrefix.length), getCleanHostname(req), function (response) { if (response == null) { res.sendStatus(404); } else { res.send(response); } }); } else { // Everything else - res.set({ 'strict-transport-security': "max-age=60000; includeSubDomains", "Referrer-Policy": "no-referrer", "x-frame-options": "SAMEORIGIN", "X-XSS-Protection": "1; mode=block", "X-Content-Type-Options": "nosniff", "Content-Security-Policy": "default-src http: ws: \"self\" \"unsafe-inline\"" }); + var selfurl = ((args.notls !== true) ? (' wss://' + req.headers.host) : (' ws://' + req.headers.host)); + res.set({ + 'strict-transport-security': 'max-age=60000; includeSubDomains', + 'Referrer-Policy': 'no-referrer', + 'x-frame-options': 'SAMEORIGIN', + 'X-XSS-Protection': '1; mode=block', + 'X-Content-Type-Options': 'nosniff', + 'Content-Security-Policy': "default-src 'none'; style-src 'self' 'unsafe-inline';" + }); return next(); } }); @@ -105,7 +113,8 @@ module.exports.CreateRedirServer = function (parent, db, args, func) { if (parent.config.domains[i].dns != null) { continue; } var url = parent.config.domains[i].url; obj.app.get(url, performRedirection); // Root redirection - obj.app.use(url + "clickonce", obj.express.static(obj.parent.path.join(__dirname, "public/clickonce"))); // Indicates the clickonce folder is public + obj.app.get(url + 'player.htm', performRedirection); // Player redirection + obj.app.use(url + 'clickonce', obj.express.static(obj.parent.path.join(__dirname, "public/clickonce"))); // Indicates the clickonce folder is public // Setup all of the redirections to HTTPS const redirections = ['terms', 'logout', 'MeshServerRootCert.cer', 'mescript.ashx', 'checkmail', 'agentinvite', 'messenger', 'meshosxagent', 'devicepowerevents.ashx', 'downloadfile.ashx', 'userfiles/*', 'webrelay.ashx', 'health.ashx', 'logo.png', 'welcome.jpg']; @@ -127,10 +136,11 @@ module.exports.CreateRedirServer = function (parent, db, args, func) { obj.tcpServer = obj.app.listen(port, function () { obj.port = port; console.log("MeshCentral HTTP redirection server running on port " + port + "."); - obj.parent.updateServerState("redirect-port", port); + obj.parent.authLog('http', 'Server listening on 0.0.0.0 port ' + port + '.'); + obj.parent.updateServerState('redirect-port', port); func(obj.port); - }).on("error", function (err) { - if ((err.code == "EACCES") && (port < 65535)) { StartRedirServer(port + 1); } else { console.log(err); func(obj.port); } + }).on('error', function (err) { + if ((err.code == 'EACCES') && (port < 65535)) { StartRedirServer(port + 1); } else { console.log(err); func(obj.port); } }); } diff --git a/sample-config.json b/sample-config.json index 06f05072..e58648d7 100644 --- a/sample-config.json +++ b/sample-config.json @@ -5,6 +5,7 @@ "_MongoDb": "mongodb://127.0.0.1:27017", "_MongoDbName": "meshcentral", "_MongoDbChangeStream": true, + "_MongoDumpPath": "C:\\Program Files\\MongoDB\\Server\\4.2\\bin\\mongodump.exe", "_WANonly": true, "_LANonly": true, "_Minify": 1, @@ -14,14 +15,19 @@ "_DbEncryptKey": "MyReallySecretPassword2", "_DbRecordsEncryptKey": "MyReallySecretPassword", "_DbRecordsDecryptKey": "MyReallySecretPassword", + "__DbExpire": "Amount of time to keep various events in the database, in seconds. Below are the default values.", "_DbExpire": { "events": 1728000, - "powerevents": 864000 + "powerevents": 864000, + "statsevents": 2592000 }, "_Port": 443, + "_AliasPort": 444, "_RedirPort": 80, + "_ExactPorts": true, "_AllowLoginToken": true, "_AllowFraming": true, + "_AgentInviteCodes": true, "_WebRTC": false, "_Nice404": false, "_ClickOnce": false, @@ -37,17 +43,21 @@ "_UserBlockedIP": "127.0.0.1,::1,192.168.0.100", "_AgentAllowedIP": "192.168.0.100/24", "_AgentBlockedIP": "127.0.0.1,::1", + "_AuthLog": "c:\\temp\\auth.log", "_LocalDiscovery": { "name": "Local server name", "info": "Information about this server" }, - "_TlsOffload": true, + "_TlsOffload": "127.0.0.1", + "_TrustedProxy": "127.0.0.1", "_MpsPort": 44330, "_MpsAliasPort": 4433, "_MpsAliasHost": "mps.mydomain.com", "_MpsTlsOffload": true, "_No2FactorAuth": true, "_Log": "main,web,webrequest,cert", + "_syslog": true, + "_syslogjson": true, "_WebRtConfig": { "iceServers": [ { "urls": "stun:stun.services.mozilla.com" }, @@ -65,7 +75,7 @@ }, "__MaxInvalidLogin": "Time in minutes, max amount of bad logins from a source IP in the time before logins are rejected.", "MaxInvalidLogin": { "time": 10, "count": 10, "coolofftime": 10 }, - "_Plugins": { + "Plugins": { "enabled": true } }, @@ -80,7 +90,10 @@ "_UserNameIsEmail": true, "_NewAccountEmailDomains": [ "sample.com" ], "_NewAccountsRights": [ "nonewgroups", "notools" ], - "Footer": "Twitter", + "_ManageAllDeviceGroups": [ "admin" ], + "_WelcomeText": "Sample Text on Login Page.", + "_WelcomePicture": "mainwelcome.jpg", + "_Footer": "Twitter", "_CertUrl": "https://192.168.2.106:443/", "_PasswordRequirements": { "min": 8, "max": 128, "upper": 1, "lower": 1, "numeric": 1, "nonalpha": 1, "reset": 90, "force2factor": true, "skip2factor": "127.0.0.1,192.168.2.0/24" }, "_AgentNoProxy": true, @@ -121,6 +134,7 @@ "_agentConfig": [ "webSocketMaskOverride=1" ], "_SessionRecording": { "_filepath": "C:\\temp", + "_index": true, "__protocols__": "Is an array: 1 = Terminal, 2 = Desktop, 5 = Files, 100 = Intel AMT WSMAN, 101 = Intel AMT Redirection", "protocols": [ 1, 2, 101 ] } diff --git a/translate/translate.bat b/translate/translate.bat new file mode 100644 index 00000000..9a98a8da --- /dev/null +++ b/translate/translate.bat @@ -0,0 +1,4 @@ +@ECHO OFF +%LOCALAPPDATA%\..\Roaming\nvm\v12.13.0\node translate.js minifyall +%LOCALAPPDATA%\..\Roaming\nvm\v12.13.0\node translate.js translateall +%LOCALAPPDATA%\..\Roaming\nvm\v12.13.0\node translate.js extractall \ No newline at end of file diff --git a/translate/translate.js b/translate/translate.js index e231a95b..3abc0811 100644 --- a/translate/translate.js +++ b/translate/translate.js @@ -18,6 +18,35 @@ var minify = null; var meshCentralSourceFiles = [ "../views/agentinvite.handlebars", + "../views/invite.handlebars", + "../views/default.handlebars", + "../views/default-mobile.handlebars", + "../views/download.handlebars", + "../views/error404.handlebars", + "../views/error404-mobile.handlebars", + "../views/login.handlebars", + "../views/login-mobile.handlebars", + "../views/terms.handlebars", + "../views/terms-mobile.handlebars", + "../views/xterm.handlebars", + "../views/message.handlebars", + "../views/messenger.handlebars", + "../views/player.handlebars", + "../emails/account-check.html", + "../emails/account-invite.html", + "../emails/account-login.html", + "../emails/account-reset.html", + "../emails/mesh-invite.html", + "../emails/account-check.txt", + "../emails/account-invite.txt", + "../emails/account-login.txt", + "../emails/account-reset.txt", + "../emails/mesh-invite.txt" +]; + +var minifyMeshCentralSourceFiles = [ + "../views/agentinvite.handlebars", + "../views/invite.handlebars", "../views/default.handlebars", "../views/default-mobile.handlebars", "../views/download.handlebars", @@ -247,8 +276,8 @@ function startEx(argv) { } if (command == 'minifyall') { - for (var i in meshCentralSourceFiles) { - var outname = meshCentralSourceFiles[i]; + for (var i in minifyMeshCentralSourceFiles) { + var outname = minifyMeshCentralSourceFiles[i]; var outnamemin = null; if (outname.endsWith('.handlebars')) { outnamemin = (outname.substring(0, outname.length - 11) + '-min.handlebars'); @@ -485,10 +514,12 @@ function translateEx(lang, langFileData, sources, createSubDir) { if ((entry['en'] != null) && (entry[lang] != null)) { translationTable[entry['en']] = entry[lang]; } } // Translate the files - for (var i = 0; i < sources.length; i++) { translateFromHtml(lang, sources[i], createSubDir); } + for (var i = 0; i < sources.length; i++) { + if (sources[i].endsWith('.html') || sources[i].endsWith('.htm') || sources[i].endsWith('.handlebars')) { translateFromHtml(lang, sources[i], createSubDir); } + else if (sources[i].endsWith('.txt')) { translateFromTxt(lang, sources[i], createSubDir); } + } } - function extract(langFile, sources) { sourceStrings = {}; if (fs.existsSync(langFile) == true) { @@ -500,7 +531,10 @@ function extract(langFile, sources) { delete sourceStrings[langFileData.strings[i]['en']].xloc; } } - for (var i = 0; i < sources.length; i++) { extractFromHtml(sources[i]); } + for (var i = 0; i < sources.length; i++) { + if (sources[i].endsWith('.html') || sources[i].endsWith('.htm') || sources[i].endsWith('.handlebars')) { extractFromHtml(sources[i]); } + else if (sources[i].endsWith('.txt')) { extractFromTxt(sources[i]); } + } var count = 0, output = []; for (var i in sourceStrings) { count++; @@ -514,22 +548,36 @@ function extract(langFile, sources) { return; } +function extractFromTxt(file) { + log("Processing TXT: " + path.basename(file)); + var lines = fs.readFileSync(file).toString().split('\r\n'); + var name = path.basename(file); + for (var i in lines) { + var line = lines[i]; + if ((line.length > 1) && (line[0] != '~')) { + if (sourceStrings[line] == null) { sourceStrings[line] = { en: line, xloc: [name] }; } else { if (sourceStrings[line].xloc == null) { sourceStrings[line].xloc = []; } sourceStrings[line].xloc.push(name); } + } + } +} + function extractFromHtml(file) { var data = fs.readFileSync(file); var { JSDOM } = jsdom; const dom = new JSDOM(data, { includeNodeLocations: true }); log("Processing HTML: " + path.basename(file)); - getStrings(path.basename(file), dom.window.document.querySelector('body')); + getStringsHtml(path.basename(file), dom.window.document.querySelector('body')); } -function getStrings(name, node) { +function getStringsHtml(name, node) { for (var i = 0; i < node.childNodes.length; i++) { var subnode = node.childNodes[i]; // Check if the "value" attribute exists and needs to be translated + var subnodeignore = false; if ((subnode.attributes != null) && (subnode.attributes.length > 0)) { - var subnodeignore = false, subnodevalue = null, subnodeplaceholder = null, subnodetitle = null; + var subnodevalue = null, subnodeplaceholder = null, subnodetitle = null; for (var j in subnode.attributes) { + if ((subnode.attributes[j].name == 'notrans') && (subnode.attributes[j].value == '1')) { subnodeignore = true; } if ((subnode.attributes[j].name == 'type') && (subnode.attributes[j].value == 'hidden')) { subnodeignore = true; } if (subnode.attributes[j].name == 'value') { subnodevalue = subnode.attributes[j].value; } if (subnode.attributes[j].name == 'placeholder') { subnodeplaceholder = subnode.attributes[j].value; } @@ -552,22 +600,24 @@ function getStrings(name, node) { } } - // Check the content of the element - var subname = subnode.id; - if (subname == null || subname == '') { subname = i; } - if (subnode.hasChildNodes()) { - getStrings(name + '->' + subname, subnode); - } else { - if (subnode.nodeValue == null) continue; - var nodeValue = subnode.nodeValue.trim().split('\\r').join('').split('\\n').join('').trim(); - if ((nodeValue.length > 0) && (subnode.nodeType == 3)) { - if ((node.tagName != 'SCRIPT') && (node.tagName != 'STYLE') && (nodeValue.length < 8000) && (nodeValue.startsWith('{{{') == false) && (nodeValue != ' ')) { - if (performCheck) { log(' "' + nodeValue + '"'); } - // Add a new string to the list - if (sourceStrings[nodeValue] == null) { sourceStrings[nodeValue] = { en: nodeValue, xloc: [name] }; } else { if (sourceStrings[nodeValue].xloc == null) { sourceStrings[nodeValue].xloc = []; } sourceStrings[nodeValue].xloc.push(name); } - } else if (node.tagName == 'SCRIPT') { - // Parse JavaScript - getStringFromJavaScript(name, subnode.nodeValue); + if (subnodeignore == false) { + // Check the content of the element + var subname = subnode.id; + if (subname == null || subname == '') { subname = i; } + if (subnode.hasChildNodes()) { + getStringsHtml(name + '->' + subname, subnode); + } else { + if (subnode.nodeValue == null) continue; + var nodeValue = subnode.nodeValue.trim().split('\\r').join('').split('\\n').join('').trim(); + if ((nodeValue.length > 0) && (subnode.nodeType == 3)) { + if ((node.tagName != 'SCRIPT') && (node.tagName != 'STYLE') && (nodeValue.length < 8000) && (nodeValue.startsWith('{{{') == false) && (nodeValue != ' ')) { + if (performCheck) { log(' "' + nodeValue + '"'); } + // Add a new string to the list + if (sourceStrings[nodeValue] == null) { sourceStrings[nodeValue] = { en: nodeValue, xloc: [name] }; } else { if (sourceStrings[nodeValue].xloc == null) { sourceStrings[nodeValue].xloc = []; } sourceStrings[nodeValue].xloc.push(name); } + } else if (node.tagName == 'SCRIPT') { + // Parse JavaScript + getStringFromJavaScript(name, subnode.nodeValue); + } } } } @@ -588,7 +638,27 @@ function getStringFromJavaScript(name, script) { } } +function translateFromTxt(lang, file, createSubDir) { + log("Translating TXT (" + lang + "): " + path.basename(file)); + var lines = fs.readFileSync(file).toString().split('\r\n'), outlines = []; + for (var i in lines) { + var line = lines[i]; + if ((line.length > 1) && (line[0] != '~')) { + if (translationTable[line] != null) { outlines.push(translationTable[line]); } else { outlines.push(line); } + } else { + outlines.push(line); + } + } + var outname = file, out = outlines.join('\r\n'); + if (createSubDir != null) { + var outfolder = path.join(path.dirname(file), createSubDir); + if (fs.existsSync(outfolder) == false) { fs.mkdirSync(outfolder); } + outname = path.join(path.dirname(file), createSubDir, path.basename(file)); + } + outname = (outname.substring(0, outname.length - 4) + '_' + lang + '.txt'); + fs.writeFileSync(outname, out, { flag: 'w+' }); +} @@ -663,9 +733,11 @@ function translateStrings(name, node) { var subnode = node.childNodes[i]; // Check if the "value" attribute exists and needs to be translated + var subnodeignore = false; if ((subnode.attributes != null) && (subnode.attributes.length > 0)) { - var subnodeignore = false, subnodevalue = null, subnodeindex = null, subnodeplaceholder = null, subnodeplaceholderindex = null, subnodetitle = null, subnodetitleindex = null; + var subnodevalue = null, subnodeindex = null, subnodeplaceholder = null, subnodeplaceholderindex = null, subnodetitle = null, subnodetitleindex = null; for (var j in subnode.attributes) { + if ((subnode.attributes[j].name == 'notrans') && (subnode.attributes[j].value == '1')) { subnodeignore = true; } if ((subnode.attributes[j].name == 'type') && (subnode.attributes[j].value == 'hidden')) { subnodeignore = true; } if (subnode.attributes[j].name == 'value') { subnodevalue = subnode.attributes[j].value; subnodeindex = j; } if (subnode.attributes[j].name == 'placeholder') { subnodeplaceholder = subnode.attributes[j].value; subnodeplaceholderindex = j; } @@ -688,27 +760,29 @@ function translateStrings(name, node) { } } - var subname = subnode.id; - if (subname == null || subname == '') { subname = i; } - if (subnode.hasChildNodes()) { - translateStrings(name + '->' + subname, subnode); - } else { - if (subnode.nodeValue == null) continue; - var nodeValue = subnode.nodeValue.trim().split('\\r').join('').split('\\n').join('').trim(); + if (subnodeignore == false) { + var subname = subnode.id; + if (subname == null || subname == '') { subname = i; } + if (subnode.hasChildNodes()) { + translateStrings(name + '->' + subname, subnode); + } else { + if (subnode.nodeValue == null) continue; + var nodeValue = subnode.nodeValue.trim().split('\\r').join('').split('\\n').join('').trim(); - // Look for the front trim - var frontTrim = '', backTrim = '';; - var x1 = subnode.nodeValue.indexOf(nodeValue); - if (x1 > 0) { frontTrim = subnode.nodeValue.substring(0, x1); } - if (x1 != -1) { backTrim = subnode.nodeValue.substring(x1 + nodeValue.length); } + // Look for the front trim + var frontTrim = '', backTrim = '';; + var x1 = subnode.nodeValue.indexOf(nodeValue); + if (x1 > 0) { frontTrim = subnode.nodeValue.substring(0, x1); } + if (x1 != -1) { backTrim = subnode.nodeValue.substring(x1 + nodeValue.length); } - if ((nodeValue.length > 0) && (subnode.nodeType == 3)) { - if ((node.tagName != 'SCRIPT') && (node.tagName != 'STYLE') && (nodeValue.length < 8000) && (nodeValue.startsWith('{{{') == false) && (nodeValue != ' ')) { - // Check if we have a translation for this string - if (translationTable[nodeValue]) { subnode.nodeValue = (frontTrim + translationTable[nodeValue] + backTrim); } - } else if (node.tagName == 'SCRIPT') { - // Translate JavaScript - subnode.nodeValue = translateStringsFromJavaScript(name, subnode.nodeValue); + if ((nodeValue.length > 0) && (subnode.nodeType == 3)) { + if ((node.tagName != 'SCRIPT') && (node.tagName != 'STYLE') && (nodeValue.length < 8000) && (nodeValue.startsWith('{{{') == false) && (nodeValue != ' ')) { + // Check if we have a translation for this string + if (translationTable[nodeValue]) { subnode.nodeValue = (frontTrim + translationTable[nodeValue] + backTrim); } + } else if (node.tagName == 'SCRIPT') { + // Translate JavaScript + subnode.nodeValue = translateStringsFromJavaScript(name, subnode.nodeValue); + } } } } @@ -787,7 +861,7 @@ function translationsToJson(t) { for (var i in arr) { var names = [], el = arr[i], el2 = {}; for (var j in el) { names.push(j); } - names.sort(); + names.sort(function (a, b) { if (a == b) { return 0; } if (a == 'xloc') { return 1; } if (b == 'xloc') { return -1; } return a - b }); for (var j in names) { el2[names[j]] = el[names[j]]; } if (el2.xloc != null) { el2.xloc.sort(); } arr2.push(el2); diff --git a/translate/translate.json b/translate/translate.json index 6e50033a..28be0179 100644 --- a/translate/translate.json +++ b/translate/translate.json @@ -6,13 +6,16 @@ "en": " + CIRA", "es": " + CIRA", "fr": " + CIRA", + "hi": " + CIRA", "ja": " + CIRA", + "ko": " + CIRA", "nl": " + CIRA", "pt": " + CIRA", "ru": " + CIRA", + "zh-chs": " + CIRA", "xloc": [ - "default.handlebars->25->1009", - "default.handlebars->25->1011" + "default.handlebars->27->1116", + "default.handlebars->27->1118" ] }, { @@ -20,11 +23,17 @@ "de": " - Zurücksetzen in 1 Tag.", "en": " - Reset in 1 day.", "es": " - Reiniciar en 1 dia.", + "fr": " - Réinitialisation dans un jour", + "hi": " - 1 दिन में रीसेट करें।", + "ja": " - 1日でリセットします。", + "ko": " - 1 일 후에 재설정합니다.", "nl": " - Herstart in {0} dag.", - "ru": "- Сброс через 1 день.", + "pt": " - Redefinir em 1 dia.", + "ru": " - Сброс через 1 день.", + "zh-chs": " - 1天后重設。", "xloc": [ "default-mobile.handlebars->9->15", - "default.handlebars->25->57" + "default.handlebars->27->57" ] }, { @@ -32,11 +41,17 @@ "de": " - Zurücksetzen in 1 Stunde.", "en": " - Reset in 1 hour.", "es": " - Reiniciar en 1 hora.", + "fr": " - Réinitialisation dans une heure", + "hi": " - 1 घंटे में रीसेट करें।", + "ja": " - 1時間でリセットします。", + "ko": " - 1 시간 후에 재설정합니다.", "nl": " - Herstart in 1 uur.", - "ru": "- Сброс через 1 час.", + "pt": " - Reinicie em 1 hora.", + "ru": " - Сброс через 1 час.", + "zh-chs": " - 1小時後重設。", "xloc": [ "default-mobile.handlebars->9->13", - "default.handlebars->25->55" + "default.handlebars->27->55" ] }, { @@ -44,11 +59,17 @@ "de": " - Zurücksetzen in 1 Minute.", "en": " - Reset in 1 minute.", "es": " - Reiniciar en 1 minuto.", + "fr": " - Réinitialisation dans une minute", + "hi": " - 1 मिनट में रीसेट करें।", + "ja": " - 1分でリセットします。", + "ko": " - 1 분 후에 재설정하십시오.", "nl": " - Herstart in {0} days.", - "ru": "- Сброс через 1 минуту.", + "pt": " - Reinicie em 1 minuto.", + "ru": " - Сброс через 1 минуту.", + "zh-chs": " - 1分鐘後重設。", "xloc": [ "default-mobile.handlebars->9->11", - "default.handlebars->25->53" + "default.handlebars->27->53" ] }, { @@ -56,11 +77,17 @@ "de": " - Zurücksetzen in {0} Tagen.", "en": " - Reset in {0} days.", "es": " - Reiniciar en {0} dias.", + "fr": " - Réinitialisation dans {0} jours.", + "hi": " - {0} दिनों में रीसेट करें।", + "ja": " - {0}日後にリセットします。", + "ko": " - {0} 일 후에 재설정하십시오.", "nl": " - Herstart in {0} dagen.", - "ru": "- Сброс через {0} дней.", + "pt": " - Redefina em {0} dias.", + "ru": " - Сброс через {0} дней.", + "zh-chs": " - 在{0}天內重置。", "xloc": [ "default-mobile.handlebars->9->16", - "default.handlebars->25->58" + "default.handlebars->27->58" ] }, { @@ -69,21 +96,30 @@ "en": " - Reset in {0} day{1}.", "es": " - Reiniciar en {0} dias{1}.", "fr": " - Réinitialiser dans le {0} jour {1}.", + "hi": " - {0} दिन {1} में रीसेट करें।", "ja": " - {0}日でリセット{1}。", + "ko": " - {0} 일 {1}에 재설정하십시오.", "nl": " - Reset in {0} dag(en){1}.", "pt": " - Redefinir em {0} dia {1}.", - "ru": " - Сброс через {0} дней." + "ru": " - Сброс через {0} дней.", + "zh-chs": " - 在{0}天{1}中重置。" }, { "cs": " - Resetovat za {0} hodin.", "de": " - Zurücksetzen in {0} Stunden.", "en": " - Reset in {0} hours.", "es": " - Reiniciar en {0} horas.", + "fr": " - Réinitialisation dans {0} heures.", + "hi": " - {0} घंटे में रीसेट करें।", + "ja": " - {0}時間後にリセットします。", + "ko": " - {0} 시간 후에 재설정하십시오.", "nl": " - Herstart in {0} uren.", - "ru": "- Сброс через {0} часов.", + "pt": " - Redefina em {0} horas.", + "ru": " - Сброс через {0} часов.", + "zh-chs": " - 在{0}小時內重置。", "xloc": [ "default-mobile.handlebars->9->14", - "default.handlebars->25->56" + "default.handlebars->27->56" ] }, { @@ -92,33 +128,45 @@ "en": " - Reset in {0} hour{1}.", "es": " - Reiniciar en {0} horas{1}.", "fr": " - Réinitialisation dans {0} heure {1}.", + "hi": " - {0} घंटे {1} में रीसेट करें।", "ja": " - {0}時間でリセット{1}。", + "ko": " - {0} 시간 {1}에 재설정하십시오.", "nl": " - Reset in {0} uur{1}.", "pt": " - Redefinir em {0} hora {1}.", - "ru": " - Сброс через {0} часов." + "ru": " - Сброс через {0} часов.", + "zh-chs": " - 在{0}小時{1}內重置。" }, { "cs": " - Resetovat za {0} minut.", "de": " - Zurücksetzen in {0} Minuten.", "en": " - Reset in {0} minutes.", "es": " - Reiniciar en {0} minutos.", + "fr": " - Réinitialisation dans {0} minutes.", + "hi": " - {0} मिनट में रीसेट करें।", + "ja": " - {0}分でリセットします。", + "ko": " - {0} 분 후에 재설정하십시오.", "nl": " - Herstart in {0} minuten.", - "ru": "- Сброс через {0} минут.", + "pt": " - Redefina em {0} minutos.", + "ru": " - Сброс через {0} минут.", + "zh-chs": " - 在{0}分鐘內重置。", "xloc": [ "default-mobile.handlebars->9->12", - "default.handlebars->25->54" + "default.handlebars->27->54" ] }, { "cs": " - Resetovat za {0} minut{1}.", "de": " - Zurücksetzen in {0} Minute{1}.", "en": " - Reset in {0} minute{1}.", - "es": "- Reiniciar en {0} minutos{1}.", + "es": " - Reiniciar en {0} minutos{1}.", "fr": " - Réinitialisation en {0} minute {1}.", + "hi": " - {0} मिनट {1} में रीसेट करें।", "ja": " - {0}分でリセット{1}。", + "ko": " - {0} 분 {1}에 재설정하십시오.", "nl": " - Reset in {0} minuten{1}.", "pt": " - Redefinir em {0} minuto {1}.", - "ru": " - Сброс через {0} минут." + "ru": " - Сброс через {0} минут.", + "zh-chs": " - 在{0}分鐘{1}內重置。" }, { "cs": " - Resetovat při příštím přihlášení.", @@ -126,15 +174,18 @@ "en": " - Reset on next login.", "es": " - Reiniciar en el proximo inicio de sesión.", "fr": " - Réinitialiser à la prochaine connexion.", + "hi": " - अगले लॉगिन पर रीसेट करें।", "ja": " - 次回ログイン時にリセット。", + "ko": " - 다음 로그인시 재설정하십시오.", "nl": " - Reset bij volgende inlog.", "pt": " - Redefinir no próximo login.", "ru": " - Сброс при следующем входе.", + "zh-chs": " -下次登錄時重置。", "xloc": [ "default-mobile.handlebars->9->10", "default-mobile.handlebars->9->9", - "default.handlebars->25->51", - "default.handlebars->25->52" + "default.handlebars->27->51", + "default.handlebars->27->52" ] }, { @@ -142,12 +193,16 @@ "de": " / ", "en": " / ", "es": " / ", + "fr": " / ", + "hi": " / ", "ja": " / ", + "ko": " / ", "nl": " / ", "pt": " / ", "ru": " / ", + "zh-chs": " / ", "xloc": [ - "default-mobile.handlebars->9->94" + "default-mobile.handlebars->9->98" ] }, { @@ -156,13 +211,13 @@ "en": " Add User", "es": " Agregar Usuario", "fr": " Ajouter un utilisateur", + "hi": " उपयोगकर्ता जोड़ें", "ja": " ユーザーを追加する", + "ko": " 사용자 추가", "nl": " Gebruiker toevoegen", "pt": " Adicionar usuário", "ru": " Добавить пользователя", - "xloc": [ - "default-mobile.handlebars->9->280" - ] + "zh-chs": " 添加用戶" }, { "cs": " Je možné zadat i nápovědu pro heslo, ale nedoporučuje se to.", @@ -170,12 +225,15 @@ "en": " Password hint can be used but is not recommanded.", "es": " Sugerencia de contraseña puede ser usada pero no se recomienda.", "fr": " Un indice de mot de passe peut être utilisé mais n'est pas recommandé.", + "hi": " पासवर्ड संकेत का उपयोग किया जा सकता है, लेकिन अनुशंसित नहीं है।", "ja": " パスワードヒントは使用できますが、推奨されません。", + "ko": " 비밀번호 힌트를 사용할 수 있지만 권장하지는 않습니다.", "nl": " Een wachtwoord hint kan gebruikt worden maar wordt afgeraden", "pt": " Dica de senha pode ser usada, mas não é recomendada.", - "ru": "Может быть использована подсказка пароля, но не рекоммендуется.", + "ru": " Может быть использована подсказка пароля, но не рекоммендуется.", + "zh-chs": " 可以使用密碼提示,但不建議使用。", "xloc": [ - "default.handlebars->25->941" + "default.handlebars->27->1046" ] }, { @@ -184,13 +242,16 @@ "en": " Users need to login to this server once before they can be added to a device group.", "es": " Los usuarios deben iniciar sesión en el server antes de que pueda agregar un dispositivo al grupo.", "fr": " Les utilisateurs doivent se connecter une fois sur ce serveur avant de pouvoir être ajoutés à un groupe de périphériques..", + "hi": " डिवाइस समूह में जोड़े जाने से पहले उपयोगकर्ताओं को एक बार इस सर्वर में प्रवेश करना होगा।", "ja": " ユーザーは、デバイスグループに追加する前にこのサーバーに1回ログインする必要があります。", + "ko": " 장치 그룹에 추가하려면이 서버에 한 번 로그인해야합니다.", "nl": " Gebruikers moeten inloggen bij de server voordat ze kunnen worden toegevoegd aan een apparaatgroep.", "pt": " Os usuários precisam fazer login neste servidor uma vez antes de poderem ser adicionados a um grupo de dispositivos.", "ru": " Для добавления в группу устройств, пользователь должен зайти на сервер хотя бы один раз.", + "zh-chs": " 用戶需要先登錄到該服務器一次,然後才能將其添加到設備組。", "xloc": [ - "default.handlebars->25->1084", - "default.handlebars->25->1314" + "default.handlebars->27->1189", + "default.handlebars->27->1447" ] }, { @@ -199,12 +260,15 @@ "en": " and authenticate to the server using this username and any password.", "es": " y autenticarse al server usando este usuario y cualquier contraseña.", "fr": " et vous authentifier sur le serveur en utilisant ce nom d'utilisateur et n'importe quel mot de passe.", + "hi": " और इस उपयोगकर्ता नाम और किसी भी पासवर्ड का उपयोग कर सर्वर को प्रमाणित करें।", "ja": " このユーザー名とパスワードを使用してサーバーに対して認証します。", + "ko": " 이 사용자 이름과 암호를 사용하여 서버를 인증하십시오.", "nl": " verifieer bij de server met deze gebruikersnaam en elk wachtwoord.", "pt": " e autenticar no servidor usando esse nome de usuário e qualquer senha.", "ru": " и задайте указанное ниже имя пользователя и любой пароль.", + "zh-chs": " 並使用該用戶名和任何密碼對服務器進行身份驗證。", "xloc": [ - "default.handlebars->25->267" + "default.handlebars->27->251" ] }, { @@ -213,12 +277,15 @@ "en": " and authenticate to the server using this username and password.", "es": " y autenticarse al server usando este usuario y contraseña.", "fr": " et authentifiez-vous sur le serveur en utilisant ce nom d'utilisateur et mot de passe.", + "hi": " और इस उपयोगकर्ता नाम और पासवर्ड का उपयोग कर सर्वर को प्रमाणित करें।", "ja": " このユーザー名とパスワードを使用してサーバーに対して認証します。", + "ko": " 이 사용자 이름과 비밀번호를 사용하여 서버를 인증하십시오.", "nl": " verifieer bij de server met deze gebruikersnaam en wachtwoord.", "pt": " e autenticar no servidor usando esse nome de usuário e senha.", "ru": " и задайте указанные ниже имя пользователя и пароль.", + "zh-chs": " 並使用該用戶名和密碼向服務器驗證身份。", "xloc": [ - "default.handlebars->25->266" + "default.handlebars->27->250" ] }, { @@ -227,12 +294,15 @@ "en": " node", "es": " nodo", "fr": " nœud", + "hi": " नोड", "ja": " ノード", + "ko": " 마디", "nl": " apparaat", "pt": " nó", "ru": " устройство", + "zh-chs": " 節點", "xloc": [ - "default-mobile.handlebars->9->127" + "default-mobile.handlebars->9->131" ] }, { @@ -241,12 +311,15 @@ "en": " nodes", "es": " nodos", "fr": " noeuds", + "hi": " नोड्स", "ja": " ノード", + "ko": " 노드", "nl": " apparaten", "pt": " nós", "ru": " устройства", + "zh-chs": " 節點", "xloc": [ - "default-mobile.handlebars->9->128" + "default-mobile.handlebars->9->132" ] }, { @@ -255,12 +328,15 @@ "en": " with TLS.", "es": " con TLS.", "fr": " avec TLS.", + "hi": " टीएलएस के साथ।", "ja": " TLSを使用。", + "ko": " TLS로.", "nl": " met TLS.", "pt": " com TLS.", "ru": " с TLS.", + "zh-chs": " TLS。", "xloc": [ - "default.handlebars->25->164" + "default.handlebars->27->147" ] }, { @@ -269,12 +345,15 @@ "en": " without TLS.", "es": " sin TLS.", "fr": " sans TLS.", + "hi": " टीएलएस के बिना।", "ja": " TLSなし。", + "ko": " TLS없이.", "nl": " zonder TLS.", "pt": " sem TLS.", "ru": " без TLS", + "zh-chs": " 沒有TLS。", "xloc": [ - "default.handlebars->25->165" + "default.handlebars->27->148" ] }, { @@ -282,6 +361,7 @@ "de": "(", "en": "(", "es": "(", + "fr": "(", "ja": "(", "nl": "(", "pt": "(", @@ -296,12 +376,16 @@ "de": "(optional)", "en": "(optional)", "es": "(opcional)", + "fr": "(optionnel)", + "hi": "(वैकल्पिक)", "ja": "(オプション)", + "ko": "(선택 과목)", "nl": "(optioneel)", "pt": "(opcional)", "ru": "(необязательно)", + "zh-chs": "(可選的)", "xloc": [ - "default.handlebars->25->303" + "default.handlebars->27->290" ] }, { @@ -309,6 +393,7 @@ "de": ")", "en": ")", "es": ")", + "fr": ")", "ja": ")", "nl": ")", "pt": ")", @@ -322,13 +407,17 @@ "cs": "* Pro BSD, nejprve spusťte „pkg install wget sudo bash“.", "de": "* Unter BSD, führe zunächst \\\"pkg install wget sudo bash\\\" aus.", "en": "* For BSD, run \\\"pkg install wget sudo bash\\\" first.", - "es": "* Para BSD, ejecute \\\"pkg install wget sudo bash\\\" ", + "es": "* Para BSD, ejecute \\\"pkg install wget sudo bash\\\".", + "fr": "* Pour BSD, exécuter d'abord la commande \\\"pkg install wget sudo bash\\\".", + "hi": "* बीएसडी के लिए, पहले \\\"pkg install wget sudo bash\\\" को रन करें।", "ja": "* BSDの場合、最初に\\\"pkg install wget sudo bash\\\"を実行します。", + "ko": "* BSD의 경우, 먼저 \\\"pkg install wget sudo bash \\\"를 실행하십시오.", "nl": "* Voor BSD, start eerst \\\"pkg install wget sudo bash\\\" .", "pt": "* Para o BSD, execute \\\"pkg install wget sudo bash\\\".", "ru": "* Для BSD сначала запустите \\\"pkg install wget sudo bash\\\".", + "zh-chs": "*對於BSD,首先運行 “pkg install wget sudo bash”。", "xloc": [ - "default.handlebars->25->334" + "default.handlebars->27->323" ] }, { @@ -336,12 +425,16 @@ "de": "* Frei lassen, um jedem Gerät ein zufälliges Passwort zuzuweisen.", "en": "* Leave blank to assign a random password to each device.", "es": "* Deje en blanco para asignar una contraseña random a cada dispositivo.", - "ja": "*空白のままにして、各デバイスにランダムなパスワードを割り当てます。", + "fr": "* Laisser vide pour créer un mot de passe aléatoire pour chaque appareil", + "hi": "* प्रत्येक डिवाइस के लिए एक यादृच्छिक पासवर्ड असाइन करने के लिए खाली छोड़ दें।", + "ja": "* 空白のままにして、各デバイスにランダムなパスワードを割り当てます。", + "ko": "* 각 장치에 임의의 암호를 할당하려면 비워 두십시오.", "nl": "* Laat leeg om een willekeurig wachtwoord toe te wijzen aan elk apparaat.", "pt": "* Deixe em branco para atribuir uma senha aleatória a cada dispositivo.", "ru": "* Оставьте пустым для установления случайного пароля каждому устройству.", + "zh-chs": "*保留空白以為每個設備分配一個隨機密碼。", "xloc": [ - "default.handlebars->25->1059" + "default.handlebars->27->1163" ] }, { @@ -349,6 +442,7 @@ "de": ",", "en": ",", "es": ",", + "fr": ",", "ja": "、", "nl": ",", "pt": ",", @@ -363,13 +457,17 @@ "de": ", ", "en": ", ", "es": ", ", + "fr": ", ", + "hi": ",", "ja": "、", + "ko": ",", "nl": ", ", "pt": ", ", "ru": ", ", + "zh-chs": ",", "xloc": [ - "default-mobile.handlebars->9->330", - "default.handlebars->25->1135" + "default-mobile.handlebars->9->334", + "default.handlebars->27->1248" ] }, { @@ -377,13 +475,17 @@ "de": ", nur Intel® AMT", "en": ", Intel® AMT only", "es": ", Intel® solo AMT.", + "fr": ", Intel® AMT uniquement", + "hi": ", Intel® AMT केवल", "ja": "、Intel® AMTのみ", + "ko": ", 인텔 ® AMT 만", "nl": ", Intel® AMT alleen", "pt": ", Intel® AMT only", "ru": ", только для Intel® AMT", + "zh-chs": ",僅限Intel®AMT", "xloc": [ - "default-mobile.handlebars->9->92", - "default.handlebars->25->180" + "default-mobile.handlebars->9->95", + "default.handlebars->27->163" ] }, { @@ -391,12 +493,16 @@ "de": ", MQTT ist verbunden", "en": ", MQTT is online", "es": ", MQQT esta en linea.", + "fr": ", MQTT est connecté", + "hi": ", MQTT ऑनलाइन है", "ja": "、MQTTはオンラインです", + "ko": ", MQTT가 온라인 상태입니다.", "nl": ", MQTT is online", "pt": ", O MQTT está online", "ru": ", MQTT онлайн", + "zh-chs": ",MQTT在線", "xloc": [ - "default.handlebars->25->694" + "default.handlebars->27->795" ] }, { @@ -404,12 +510,16 @@ "de": ", Soft-KVM", "en": ", Soft-KVM", "es": ", Soft-KVM", + "fr": ", Soft-KVM", + "hi": ", शीतल-केवीएम", "ja": "、Soft-KVM", + "ko": "소프트 -KVM", "nl": ", Soft-KVM", "pt": ", Soft-KVM", "ru": ", Soft-KVM", + "zh-chs": ",軟KVM", "xloc": [ - "default.handlebars->25->606" + "default.handlebars->27->654" ] }, { @@ -417,16 +527,20 @@ "de": ", WebRTC", "en": ", WebRTC", "es": ", WebRTC", + "fr": ", WebRTC", + "hi": ", WebRTC", "ja": "、WebRTC", + "ko": ", WebRTC", "nl": ", WebRTC", "pt": ", WebRTC", "ru": ", WebRTC", + "zh-chs": ",WebRTC", "xloc": [ - "default-mobile.handlebars->9->228", - "default-mobile.handlebars->9->238", - "default.handlebars->25->607", - "default.handlebars->25->637", - "default.handlebars->25->649", + "default-mobile.handlebars->9->232", + "default-mobile.handlebars->9->242", + "default.handlebars->27->655", + "default.handlebars->27->686", + "default.handlebars->27->698", "xterm.handlebars->9->6" ] }, @@ -435,10 +549,14 @@ "de": ", zum Einschalten hier klicken.", "en": ", click here to enable it.", "es": ", haga click aquí para habilitarlo.", + "fr": ", cliquez ici pour l'activer", + "hi": "इसे सक्षम करने के लिए यहां क्लिक करें।", "ja": "、ここをクリックして有効にします。", + "ko": "사용하려면 여기를 클릭하십시오.", "nl": ", klik hier om in te schakelen", "pt": ", clique aqui para habilitá-lo.", "ru": ", для включения нажмите сюда.", + "zh-chs": ",請點擊此處啟用它。", "xloc": [ "default.handlebars->container->column_l->p11->p11warning->3->p11warninga", "default.handlebars->container->column_l->p12->p12warning->3->p12warninga" @@ -449,10 +567,14 @@ "de": ", rechtsklicken oder \"Ctrl\" halten und Datei anklicken. Anschließend \"Öffnen\" wählen und den Anweisungen folgen.", "en": ", right click on it or press \"control\" and click on the file. Then select \"Open\" and follow the instructions.", "es": ", haga click derecho o presione \"Ctrl\" y de click en el archivo. Despues seleecione \"Abrir\" y siga las instrucciones.", + "fr": ", faites un clic droit dessus ou appuyez sur \"contrôle\" et cliquez sur le fichier. Sélectionnez ensuite \"Ouvrir\" et suivez les instructions.", + "hi": ", उस पर क्लिक करें या \"नियंत्रण\" दबाएं और फ़ाइल पर क्लिक करें। फिर \"ओपन\" चुनें और निर्देशों का पालन करें।", "ja": "、それを右クリックするか、「control」を押してファイルをクリックします。次に、「開く」を選択し、指示に従います。", + "ko": "을 마우스 오른쪽 버튼으로 클릭하거나 \"control\"을 누르고 파일을 클릭하십시오. 그런 다음 \"열기\"를 선택하고 지침을 따르십시오.", "nl": ", klik er met de rechtermuisknop op of druk op \"beheer\" en klik op het bestand. Daarna op \"open\" en volg de instructies.", "pt": ", clique com o botão direito do mouse ou pressione \"control\".Em seguida, selecione \"Open\".", "ru": ", нажмите правой кнопкой мыши на скачанном файле, выберите пункт \"Открыть\" и следуйте инструкциям программы.", + "zh-chs": ",右鍵單擊它或按“控制”,然後單擊文件。然後選擇“打開”並按照說明進行操作。", "xloc": [ "agentinvite.handlebars->container->column_l->5->macostab->3" ] @@ -462,26 +584,44 @@ "de": ", ausführen und \"Installieren\" oder \"Verbinden\" wählen.", "en": ", run it and press \"Install\" or \"Connect\".", "es": ", execute y presione \"Instalar\" o \"Conectar\".", + "fr": ", exécutez le puis cliquez sur \"Install\" or \"Connect.", + "hi": ", इसे चलाएं और \"इंस्टॉल करें\" या \"कनेक्ट\" दबाएं।", "ja": "、実行して「インストール」または「接続」を押します。", + "ko": "실행하고 \"설치\"또는 \"연결\"을 누르십시오.", "nl": ", open het en klik op \"installeren\" of \"verbinden\".", "pt": ", execute-o e pressione \"Install\" or \"Connect\".", "ru": ", запустите и нажмите \"Инсталлировать\" или \"Подключиться\".", + "zh-chs": ",運行它,然後按“安裝”或“連接”。", "xloc": [ "agentinvite.handlebars->container->column_l->5->wintab32->3", "agentinvite.handlebars->container->column_l->5->wintab64->3" ] }, + { + "cs": ", nyní k němu máte přístup:", + "de": "können Sie jetzt darauf zugreifen mit:", + "en": ", you can access it now with:", + "fr": ", vous pouvez y accéder maintenant avec:", + "nl": ", je hebt er nu toegang toe met:", + "ja": "、あなたは今それを使ってそれにアクセスできます:", + "ru": "Вы можете получить к нему доступ сейчас:", + "zh-chs": ",您现在可以通过以下方式访问它:", + "xloc": [ + "account-invite.html->2->3" + ] + }, { "cs": "–", "de": "-", "en": "-", "es": "-", + "fr": "-", "ja": "-", "nl": "-", "pt": "-", "ru": "-", "xloc": [ - "default-mobile.handlebars->9->231", + "default-mobile.handlebars->9->235", "xterm.handlebars->p11->deskarea0->deskarea1->3" ] }, @@ -490,6 +630,7 @@ "de": ".", "en": ".", "es": ".", + "fr": ".", "ja": "。", "nl": ".", "pt": ".", @@ -511,16 +652,20 @@ "de": "...", "en": "...", "es": "...", + "fr": "...", + "hi": "...", "ja": "...", + "ko": "...", "nl": "...", "pt": "...", "ru": "...", + "zh-chs": "...", "xloc": [ - "default-mobile.handlebars->9->243", - "default-mobile.handlebars->9->67", - "default.handlebars->25->1157", - "default.handlebars->25->1390", - "default.handlebars->25->651" + "default-mobile.handlebars->9->247", + "default-mobile.handlebars->9->70", + "default.handlebars->27->1285", + "default.handlebars->27->1536", + "default.handlebars->27->700" ] }, { @@ -528,12 +673,13 @@ "de": "0", "en": "0", "es": "0", + "fr": "0", "ja": "0", "nl": "0", "pt": "0", "ru": "0", "xloc": [ - "default-mobile.handlebars->9->232", + "default-mobile.handlebars->9->236", "default.handlebars->container->masthead->7->notificationCount" ] }, @@ -542,10 +688,14 @@ "de": "00:00:00", "en": "00:00:00", "es": "00:00:00", + "fr": "00:00:00", + "hi": "00:00:00", "ja": "00:00:00", + "ko": "00:00:00", "nl": "00:00:00", "pt": "00:00:00", "ru": "00:00:00", + "zh-chs": "00:00:00", "xloc": [ "player.handlebars->p11->deskarea0->deskarea4->1->timespan" ] @@ -556,12 +706,15 @@ "en": "1 active session", "es": "Una sesión activa", "fr": "1 session active", + "hi": "1 सक्रिय सत्र", "ja": "1つのアクティブなセッション", + "ko": "1 개의 활성 세션", "nl": "1 actieve sessie", "pt": "1 sessão ativa", "ru": "1 активная сессия", + "zh-chs": "1個活動會話", "xloc": [ - "default.handlebars->25->1354" + "default.handlebars->27->1490" ] }, { @@ -570,14 +723,17 @@ "en": "1 byte", "es": "Un byte", "fr": "1 octet", + "hi": "1 बाइट", "ja": "1バイト", + "ko": "1 바이트", "nl": "1 byte", "pt": "1 byte", "ru": "1 байт", + "zh-chs": "1個字節", "xloc": [ - "default-mobile.handlebars->9->334", - "default-mobile.handlebars->9->77", - "default.handlebars->25->1174" + "default-mobile.handlebars->9->338", + "default-mobile.handlebars->9->80", + "default.handlebars->27->1304" ] }, { @@ -586,14 +742,17 @@ "en": "1 day", "es": "Un dia", "fr": "1 jour", + "hi": "एक दिन", "ja": "1日", + "ko": "1 일", "nl": "1 dag", "pt": "1 dia", "ru": "1 день", + "zh-chs": "1天", "xloc": [ - "default.handlebars->25->170", - "default.handlebars->25->294", - "default.handlebars->25->308" + "default.handlebars->27->153", + "default.handlebars->27->281", + "default.handlebars->27->295" ] }, { @@ -602,12 +761,15 @@ "en": "1 group", "es": "Un grupo", "fr": "1 groupe", + "hi": "1 समूह", "ja": "1グループ", + "ko": "1 그룹", "nl": "1 groep", "pt": "1 grupo", "ru": "1 группа", + "zh-chs": "1組", "xloc": [ - "default.handlebars->25->1338" + "default.handlebars->27->1472" ] }, { @@ -616,14 +778,17 @@ "en": "1 hour", "es": "Una hora", "fr": "1 heure", + "hi": "1 घंटा", "ja": "1時間", + "ko": "1 시간", "nl": "1 uur", "pt": "1 hora", "ru": "1 час", + "zh-chs": "1小時", "xloc": [ - "default.handlebars->25->168", - "default.handlebars->25->292", - "default.handlebars->25->306" + "default.handlebars->27->151", + "default.handlebars->27->279", + "default.handlebars->27->293" ] }, { @@ -631,10 +796,16 @@ "de": "1 Minute bis zur Trennung", "en": "1 minute until disconnect", "es": "Un minuto hasta desconectar", + "fr": "Déconnexion dans 1 minute", + "hi": "डिस्कनेक्ट होने तक 1 मिनट", + "ja": "切断されるまで1分", + "ko": "분리 할 때까지 1 분", "nl": "1 minuut totdat de verbinding wordt verbroken", + "pt": "1 minuto até desconectar", "ru": "1 минута до разъединения", + "zh-chs": "1分鐘直到斷開連接", "xloc": [ - "default.handlebars->25->61" + "default.handlebars->27->61" ] }, { @@ -643,14 +814,17 @@ "en": "1 month", "es": "Un mes", "fr": "1 mois", + "hi": "1 महीना", "ja": "1ヶ月", + "ko": "1 개월", "nl": "1 maand", "pt": "1 mês", "ru": "1 месяц", + "zh-chs": "1個月", "xloc": [ - "default.handlebars->25->172", - "default.handlebars->25->296", - "default.handlebars->25->310" + "default.handlebars->27->155", + "default.handlebars->27->283", + "default.handlebars->27->297" ] }, { @@ -658,12 +832,16 @@ "de": "1 weiterer Benutzer nicht angezeigt, Suchfeld verwenden um weitere Benutzer zu suchen...", "en": "1 more user not shown, use search box to look for users...", "es": "No se muestra un usuario más, use el cuadro de búsqueda para buscar usuarios...", + "fr": "au moins 1 utilisateur non affiché, utilisez la recherche pour les trouver...", + "hi": "1 और उपयोगकर्ता नहीं दिखाया गया है, उपयोगकर्ताओं को देखने के लिए खोज बॉक्स का उपयोग करें ...", "ja": "さらに1人のユーザーが表示されていません。検索ボックスを使用してユーザーを検索してください...", + "ko": "1 명의 사용자가 더 이상 표시되지 않습니다. 검색 창을 사용하여 사용자를 찾으십시오.", "nl": "1 gebruiker niet getoond, gebruik de zoekfunctie om gebruikers te vinden...", "pt": "Mais 1 usuário não mostrado, use a caixa de pesquisa para procurar usuários...", "ru": "Еще 1 пользователь не показан, используйте поиск чтобы найти пользователей...", + "zh-chs": "未再顯示1個用戶,請使用搜索框查找用戶...", "xloc": [ - "default.handlebars->25->1209" + "default.handlebars->27->1339" ] }, { @@ -672,12 +850,15 @@ "en": "1 node", "es": "Un nodo", "fr": "1 appareil", + "hi": "1 नोड", "ja": "1ノード", + "ko": "1 노드", "nl": "1 knooppunt", "pt": "1 nó", "ru": "1 устройство", + "zh-chs": "1個節點", "xloc": [ - "default.handlebars->25->347" + "default.handlebars->27->337" ] }, { @@ -685,10 +866,16 @@ "de": "1 Sekunde bis zur Trennung", "en": "1 second until disconnect", "es": "Un segundo hasta desconectar", + "fr": "Déconnexion dans 1 seconde", + "hi": "डिस्कनेक्ट होने तक 1 सेकंड", + "ja": "切断するまで1秒", + "ko": "분리 할 때까지 1 초", "nl": "1 seconde totdat de verbinding wordt verbroken", + "pt": "1 segundo até desconectar", "ru": "1 секунда до разъединения", + "zh-chs": "1秒,直到斷開連接", "xloc": [ - "default.handlebars->25->59" + "default.handlebars->27->59" ] }, { @@ -697,12 +884,15 @@ "en": "1 session", "es": "Una sesión", "fr": "1 session", + "hi": "1 सत्र", "ja": "1セッション", + "ko": "1 회", "nl": "1 sessie", "pt": "1 sessão", "ru": "1 сессия", + "zh-chs": "1節", "xloc": [ - "default.handlebars->25->1213" + "default.handlebars->27->1343" ] }, { @@ -711,37 +901,50 @@ "en": "1 week", "es": "Una semana", "fr": "1 semaine", + "hi": "1 सप्ताह", "ja": "1週間", + "ko": "일주", "nl": "1 week", "pt": "1 semana", "ru": "1 неделя", + "zh-chs": "1週", "xloc": [ - "default.handlebars->25->171", - "default.handlebars->25->295", - "default.handlebars->25->309" + "default.handlebars->27->154", + "default.handlebars->27->282", + "default.handlebars->27->296" ] }, { - "cs": "1. AJAX Control Toolkit – Nová BSD licence", + "cs": "1.AJAX Control Toolkit – Nová BSD licence", + "de": "1.AJAX Control Toolkit - Neue BSD-Lizenz", "en": "1.AJAX Control Toolkit - New BSD License", "es": "1.AJAX Control Toolkit - New BSD License", + "fr": "1.AJAX Control Toolkit - Nouvelle licence BSD", + "hi": "1.जैक्स कंट्रोल टूलकिट - न्यू बीएसडी लाइसेंस", "ja": "1.AJAX Control Toolkit-新しいBSDライセンス", + "ko": "1.AJAX Control Toolkit-새로운 BSD 라이센스", "nl": "1.AJAX Control Toolkit - Nieuwe BSD Licentie", "pt": "1.AJAX Control Toolkit - Nova licença BSD", "ru": "1.AJAX Control Toolkit - Новая BSD Лицензия", + "zh-chs": "1.AJAX控制工具包-新的BSD許可證", "xloc": [ "terms-mobile.handlebars->container->page_content->column_l->9->1->0", "terms.handlebars->container->column_l->9->1->0" ] }, { - "cs": "1. Při šíření zdrojového kódu dál musí být zachováno výše uvedené upozornění o autorských právech, tento seznam podmínek a následující vyloučení odpovědnosti.", + "cs": "1.Při šíření zdrojového kódu dál musí být zachováno výše uvedené upozornění o autorských právech, tento seznam podmínek a následující vyloučení odpovědnosti.", + "de": "1. Bei der Weiterverteilung des Quellcodes müssen der oben genannte Copyright-Hinweis, diese Liste der Bedingungen und der folgende Haftungsausschluss erhalten bleiben.", "en": "1.Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.", - "es": "1. Las redistribuciones del código fuente deben conservar el aviso de copyright anterior, esta lista de condiciones y el siguiente descargo de responsabilidad.", + "es": "1.Las redistribuciones del código fuente deben conservar el aviso de copyright anterior, esta lista de condiciones y el siguiente descargo de responsabilidad.", + "fr": "1.La redistribution du code source doit contenir le copyright, la liste des conditions et le la décharge de responsabilité suivante.", + "hi": "स्रोत कोड के 1.Ristributions उपरोक्त कॉपीराइट नोटिस, शर्तों की सूची और निम्नलिखित अस्वीकरण को बनाए रखना चाहिए।", "ja": "1.ソースコードの再配布には、上記の著作権表示、この条件リスト、および以下の免責事項を保持する必要があります。", + "ko": "1.소스 코드의 재배포에는 위의 저작권 표시,이 조건 목록 및 다음 면책 사항이 유지되어야합니다.", "nl": "1.Herdistributies van broncode moeten de bovenstaande copyright kennisgeving en deze lijst met voorwaarden en de volgende disclaimer bevatten.", "pt": "1.As redistribuições do código-fonte devem manter o aviso de direitos autorais acima, esta lista de condições e o aviso de isenção de responsabilidade a seguir.", - "ru": "1. Распространение исходного кода должно включать указанное выше уведомление об авторских правах, этот список условий и следующий отказ от ответственности.", + "ru": "1.Распространение исходного кода должно включать указанное выше уведомление об авторских правах, этот список условий и следующий отказ от ответственности.", + "zh-chs": "1.重新分發源代碼必須保留以上版權聲明,此條件列表和以下免責聲明。", "xloc": [ "terms-mobile.handlebars->container->page_content->column_l->15->1", "terms-mobile.handlebars->container->page_content->column_l->31->1", @@ -755,10 +958,13 @@ "en": "1/2 Speed", "es": "1/2 Velocidad", "fr": "1/2 vitesse", + "hi": "1/2 गति", "ja": "1/2速度", + "ko": "1/2 속도", "nl": "1/2 snelheid", "pt": "1/2 velocidade", "ru": "1/2 Скорость", + "zh-chs": "1/2速度", "xloc": [ "player.handlebars->p11->deskarea0->deskarea4->3->PlaySpeed->3" ] @@ -769,10 +975,13 @@ "en": "1/4 Speed", "es": "1/4 Velocidad", "fr": "1/4 vitesse", + "hi": "1/4 गति", "ja": "1/4スピード", + "ko": "1/4 속도", "nl": "1/4 snelheid", "pt": "1/4 de velocidade", "ru": "1/4 Скорость", + "zh-chs": "1/4速度", "xloc": [ "player.handlebars->p11->deskarea0->deskarea4->3->PlaySpeed->1" ] @@ -782,10 +991,14 @@ "de": "100%", "en": "100%", "es": "100%", + "fr": "100%", + "hi": "100%", "ja": "100%", + "ko": "100%", "nl": "100%", "pt": "100%", "ru": "100%", + "zh-chs": "100%", "xloc": [ "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->5->d7bitmapscaling->1", "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->1" @@ -796,10 +1009,14 @@ "de": "100x30", "en": "100x30", "es": "100x30", + "fr": "100x30", + "hi": "100x30", "ja": "100x30", + "ko": "100x30", "nl": "100x30", "pt": "100x30", "ru": "100x30", + "zh-chs": "100x30", "xloc": [ "default.handlebars->container->column_l->p12->termTable->1->1->6->1->1->terminalSizeDropDown->termSizeList->1" ] @@ -810,10 +1027,13 @@ "en": "10x Speed", "es": "Velocidad 10x", "fr": "10x vitesse", + "hi": "10x स्पीड", "ja": "10倍速", + "ko": "10 배속", "nl": "10x Snelheid", "pt": "10x Velocidade", "ru": "10x Скорость", + "zh-chs": "10倍速度", "xloc": [ "player.handlebars->p11->deskarea0->deskarea4->3->PlaySpeed->11" ] @@ -823,10 +1043,14 @@ "de": "12.5%", "en": "12.5%", "es": "12.5%", + "fr": "12.5%", + "hi": "12.5%", "ja": "12.5%", + "ko": "12.5%", "nl": "12.5%", "pt": "12.5%", "ru": "12.5%", + "zh-chs": "12.5%", "xloc": [ "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->5->d7bitmapscaling->15", "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->15" @@ -837,12 +1061,16 @@ "de": "Aktivierung der Zweifaktor-Anmeldung fehlgeschlagen.", "en": "2-step login activation failed.", "es": "La activación de inicio de sesión en 2 pasos falló.", + "fr": "Echec de l'activitation de l'authentifcation à double facteur.", + "hi": "2-चरण लॉगिन सक्रियण विफल।", "ja": "2段階ログインのアクティベーションに失敗しました。", + "ko": "2 단계 로그인 활성화에 실패했습니다.", "nl": "Tweestapsverificatie is msilukt.", "pt": "Falha na ativação do login em duas etapas.", "ru": "Активация двухэтапного входа не удалась.", + "zh-chs": "兩步登錄激活失敗。", "xloc": [ - "default.handlebars->25->125" + "default.handlebars->27->108" ] }, { @@ -850,22 +1078,31 @@ "de": "Entfernung der Aktivierung der Zweifaktor-Anmeldung fehlgeschlagen.", "en": "2-step login activation removal failed.", "es": "La eliminación de activación de inicio de sesión en 2 pasos falló.", + "fr": "Echec de la suppression de l'authenfication à double facteur.", + "hi": "2-चरण लॉगिन सक्रियण निष्कासन विफल।", "ja": "2段階ログインアクティベーションの削除に失敗しました。", + "ko": "2 단계 로그인 활성화 제거에 실패했습니다.", "nl": "Tweestapsverificatie verwijdering is mislukt.", "pt": "A remoção da ativação do login em duas etapas falhou.", "ru": "Удаление активации двухэтапного входа не удалось.", + "zh-chs": "兩步登錄激活刪除失敗。", "xloc": [ - "default.handlebars->25->130" + "default.handlebars->27->113" ] }, { "cs": "2. OpenSSL – OpenSSL a SSLeay licence", + "de": "2.OpenSSL - OpenSSL- und SSLeay-Lizenz", "en": "2.OpenSSL – OpenSSL and SSLeay License", "es": "2.OpenSSL – Licencia OpenSSL and SSLeay", + "fr": "2.OpenSSL - Licence OpenSSL et SSLeay", + "hi": "2.OpenSSL - OpenSSL और SSLeay लाइसेंस", "ja": "2.OpenSSL – OpenSSLおよびSSLeayライセンス", + "ko": "2. OpenSSL – OpenSSL 및 SSLeay 라이센스", "nl": "2.OpenSSL – OpenSSL en SSLeay Licentie", "pt": "2.OpenSSL - Licença OpenSSL e SSLeay", "ru": "2.OpenSSL – OpenSSL и SSLeay Лицензия", + "zh-chs": "2.OpenSSL – OpenSSL和SSLeay許可證", "xloc": [ "terms-mobile.handlebars->container->page_content->column_l->23->1->0", "terms.handlebars->container->column_l->23->1->0" @@ -873,12 +1110,17 @@ }, { "cs": "2. Šíření dál ve zkompilované podobě musí reprodukovat výše uvedené oznámení o autorských právech, tento seznam podmínek a následující vyloučení odpovědnosti v dokumentaci a / nebo jiných materiálech dodávaných s distribucí.", + "de": "2. Weiterverteilungen in binärer Form müssen den obigen Copyright-Hinweis, diese Liste von Bedingungen und den folgenden Haftungsausschluss in der Dokumentation und / oder anderen Materialien, die mit der Verteilung bereitgestellt werden, wiedergeben.", "en": "2.Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.", "es": "2. Las redistribuciones en forma binaria deben reproducir el aviso de copyright anterior, esta lista de condiciones y el siguiente descargo de responsabilidad en la documentación y / u otros materiales proporcionados con la distribución.", + "fr": "2.Les redistributions sous forme binaire doivent reproduire l'avis de droit d'auteur ci-dessus, cette liste de conditions et la clause de non-responsabilité suivante dans la documentation et / ou les autres documents fournis avec la distribution.", + "hi": "2. द्विआधारी रूप में सहायताएं उपरोक्त कॉपीराइट नोटिस, शर्तों की इस सूची और वितरण के साथ प्रदान किए गए प्रलेखन और / या अन्य सामग्रियों में निम्नलिखित अस्वीकरण को पुन: प्रस्तुत करना चाहिए।", "ja": "2.バイナリ形式での再配布では、上記の著作権表示、この条件リスト、および以下の免責事項を、配布物とともに提供されるドキュメントおよび/またはその他の資料に複製する必要があります。", + "ko": "2. 이진 형태의 배포는 배포와 함께 제공된 설명서 및 / 또는 기타 자료에 위의 저작권 표시,이 조건 목록 및 다음 면책 사항을 재현해야합니다.", "nl": "2.Herdistributies in binaire vorm moeten de bovenstaande copyright kennisgeving, deze lijst met voorwaarden en de volgende disclaimer reproduceren in de documentatie en / of andere materialen die bij de distributie worden geleverd.", "pt": "2.As redistribuições em formato binário devem reproduzir o aviso de direitos autorais acima, esta lista de condições e o aviso de isenção de responsabilidade a seguir na documentação e / ou outros materiais fornecidos com a distribuição.", "ru": "2. Распространение в двоичной форме должно включать указанное выше уведомление об авторских правах, этот список условий и следующий отказ от ответственности в документации и/или других материалов дистрибутива.", + "zh-chs": "2.以二進制形式進行的再分發必須在分發隨附的文檔和/或其他材料中復制上述版權聲明,此條件列表以及以下免責聲明。", "xloc": [ "terms-mobile.handlebars->container->page_content->column_l->17->1", "terms-mobile.handlebars->container->page_content->column_l->33->1", @@ -891,10 +1133,14 @@ "de": "25%", "en": "25%", "es": "25%", + "fr": "25%", + "hi": "25%", "ja": "25%", + "ko": "25 %", "nl": "25%", "pt": "25%", "ru": "25%", + "zh-chs": "25%", "xloc": [ "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->5->d7bitmapscaling->13", "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->13" @@ -905,12 +1151,17 @@ "de": "Zweifaktorauthentifizierung eingeschaltet", "en": "2nd factor authentication enabled", "es": "Segundo factor de autenticación habilitado.", + "fr": "Authenfitication à double facteur activée", + "hi": "2 कारक प्रमाणीकरण सक्षम", "ja": "二要素認証が有効", + "ko": "2 단계 인증 사용", "nl": "Tweestapsverificatie ingeschakeld", "pt": "Autenticação de segundo fator ativada", "ru": "двухфакторная аутентификация включена", + "zh-chs": "啟用第二因素身份驗證", "xloc": [ - "default.handlebars->25->1347" + "default.handlebars->27->1356", + "default.handlebars->27->1481" ] }, { @@ -919,10 +1170,13 @@ "en": "2x Speed", "es": "Velocidad 2x", "fr": "2x vitesse", + "hi": "2x गति", "ja": "2倍速", + "ko": "2 배속", "nl": "2x Snelheid", "pt": "2x velocidade", "ru": "2x Скорость", + "zh-chs": "2倍速度", "xloc": [ "player.handlebars->p11->deskarea0->deskarea4->3->PlaySpeed->7" ] @@ -932,22 +1186,28 @@ "de": "3", "en": "3", "es": "3", + "fr": "3", "ja": "3", "nl": "3", "pt": "3", "ru": "3", "xloc": [ - "default-mobile.handlebars->9->269" + "default-mobile.handlebars->9->273" ] }, { "cs": "3. Všechny reklamní materiály zmiňující funkce nebo použití tohoto softwaru musí obsahovat následující oznámení: „Tento produkt zahrnuje software vyvinutý projektem OpenSSL pro použití v sadě OpenSSL Toolkit. (http://www.openssl.org/)“", + "de": "3. Alle Werbematerialien, in denen Funktionen oder die Verwendung dieser Software erwähnt werden, müssen die folgende Bestätigung aufweisen: \"Dieses Produkt enthält Software, die vom OpenSSL-Projekt zur Verwendung im OpenSSL Toolkit entwickelt wurde (http://www.openssl.org/).\"", "en": "3.All advertising materials mentioning features or use of this software must display the following acknowledgment: \"This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit. (http://www.openssl.org/)\"", "es": "3. Todos los materiales publicitarios que mencionen características o el uso de este software deben mostrar el siguiente reconocimiento: \"Este producto incluye software desarrollado por OpenSSL Project para su uso en OpenSSL Toolkit. (Http://www.openssl.org/)\"", + "fr": "3.Tous les supports publicitaires mentionnant des fonctionnalités ou l'utilisation de ce logiciel doivent afficher la mention suivante: \"Ce produit inclut un logiciel développé par le projet OpenSSL pour une utilisation dans l'OpenSSL Toolkit. (Http://www.openssl.org/)\"", + "hi": "3. इस सॉफ्टवेयर की विशेषताओं या उपयोग के बारे में सभी विज्ञापन सामग्री में निम्नलिखित स्वीकार्यता प्रदर्शित होनी चाहिए: \"इस उत्पाद में ओपनएसएसएल टूलकिट में उपयोग के लिए ओपनएसएसएल प्रोजेक्ट द्वारा विकसित सॉफ्टवेयर शामिल है। (http://www.openssl.org/)\"", "ja": "3.このソフトウェアの機能または使用について言及するすべての広告資料には、「この製品には、OpenSSL Toolkitで使用するためにOpenSSL Projectによって開発されたソフトウェアが含まれます。(http://www.openssl.org/)」", + "ko": "3.이 소프트웨어의 기능이나 사용을 언급하는 모든 광고 자료에는 다음 인정이 표시되어야합니다. \"이 제품에는 OpenSSL Toolkit에서 사용하기 위해 OpenSSL Project에서 개발 한 소프트웨어가 포함되어 있습니다. (http://www.openssl.org/)\"", "nl": "3.Alle advertentiematerialen die functies of gebruik van deze software maken, moeten de volgende tekst bevatten: \"Dit product bevat software die is ontwikkeld door het OpenSSL-project voor gebruik in de OpenSSL Toolkit. (Http://www.openssl.org/)\"", "pt": "3.Todos os materiais publicitários que mencionam os recursos ou o uso deste software devem exibir o seguinte reconhecimento: \"This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit. (http://www.openssl.org/)\"", "ru": "3.Все рекламные материалы, в которых упоминаются функции или использование этого программного обеспечения, должны отображать следующее подтверждение: \"Этот продукт включает программное обеспечение, разработанное OpenSSL Project для использования в OpenSSL Toolkit. (http://www.openssl.org/)\"", + "zh-chs": "3.所有提及該功能或使用該軟件的廣告材料都必須顯示以下確認:“此產品包括由OpenSSL Project開發並在OpenSSL Toolkit中使用的軟件。(http://www.openssl.org/)”", "xloc": [ "terms-mobile.handlebars->container->page_content->column_l->35->1", "terms.handlebars->container->column_l->35->1" @@ -955,12 +1215,17 @@ }, { "cs": "3. Název nadace CodePlex Foundation ani jména jejích přispěvatelů nesmí být bez předchozího písemného svolení použita k doporučování nebo propagaci produktů odvozených od tohoto softwaru.", + "de": "3. Weder der Name der CodePlex Foundation noch die Namen ihrer Mitwirkenden dürfen verwendet werden, um Produkte, die von dieser Software abgeleitet sind, ohne ausdrückliche vorherige schriftliche Genehmigung zu unterstützen oder zu bewerben.", "en": "3.Neither the name of CodePlex Foundation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.", "es": "3. Ni el nombre de la Fundación CodePlex ni los nombres de sus colaboradores pueden utilizarse para respaldar o promocionar productos derivados de este software sin un permiso previo por escrito específico.", + "fr": "3. Ni le nom de la Fondation CodePlex ni les noms de ses contributeurs ne peuvent être utilisés pour approuver ou promouvoir des produits dérivés de ce logiciel sans autorisation écrite préalable spécifique.", + "hi": "3. न तो कोडप्लेक्स फाउंडेशन का नाम और न ही इसके योगदानकर्ताओं के नाम का उपयोग विशिष्ट पूर्व लिखित अनुमति के बिना इस सॉफ्टवेयर से प्राप्त उत्पादों को समर्थन या बढ़ावा देने के लिए किया जा सकता है।", "ja": "3. CodePlex Foundationの名前もその貢献者の名前も、書面による事前の許可なしに、このソフトウェアから派生した製品を推奨または宣伝するために使用することはできません。", + "ko": "3. CodePlex Foundation의 이름이나 기여자의 이름을 사전 서면 허가없이이 소프트웨어에서 파생 된 제품을 보증하거나 홍보하는 데 사용할 수 없습니다.", "nl": "3.Noch de naam van CodePlex Foundation, noch de namen van haar bijdragers mogen worden gebruikt om producten die zijn afgeleid van deze software te ondersteunen of promoten zonder specifieke voorafgaande schriftelijke toestemming.", "pt": "3.Nem o nome da CodePlex Foundation nem os nomes de seus colaboradores podem ser usados \\u200b\\u200bpara endossar ou promover produtos derivados deste software sem permissão prévia por escrito específica.", "ru": "3. Ни имя CodePlex Foundation, ни имена его участников не могут использоваться для поддержки или продвижения продуктов, созданных на основе данного программного обеспечения, без специального предварительного письменного разрешения.", + "zh-chs": "3.未經事先特別書面許可,不得使用CodePlex Foundation的名稱或其貢獻者的名稱來認可或促銷從該軟件衍生的產品。", "xloc": [ "terms-mobile.handlebars->container->page_content->column_l->19->1", "terms.handlebars->container->column_l->19->1" @@ -968,12 +1233,17 @@ }, { "cs": "3. jQuery Foundation – MIT licence", + "de": "3.jQuery Foundation - MIT-Lizenz", "en": "3.jQuery Foundation - MIT License", "es": "3.jQuery Foundation - Licencia MIT", + "fr": "3.jQuery Foundation - Licence MIT", + "hi": "3.jQuery फाउंडेशन - एमआईटी लाइसेंस", "ja": "3. jQuery Foundation-MITライセンス", + "ko": "3.jQuery Foundation-MIT 라이센스", "nl": "3.jQuery Foundation - MIT Licentie", "pt": "3.jQuery Foundation - Licença MIT", "ru": "3.jQuery Foundation - MIT Лицензия", + "zh-chs": "3.jQuery Foundation-MIT許可證", "xloc": [ "terms-mobile.handlebars->container->page_content->column_l->45->1->0", "terms.handlebars->container->column_l->45->1->0" @@ -984,13 +1254,17 @@ "de": "32bit-Version des MeshAgents", "en": "32bit version of the MeshAgent", "es": "Version 32bits del MeshAgent", + "fr": "Version 32bits de MeshAgent", + "hi": "मेशएजेंट का 32 बिट संस्करण", "ja": "MeshAgentの32ビットバージョン", + "ko": "32 비트 버전의 MeshAgent", "nl": "32bit versie van de MeshAgent", "pt": "Versão de 32 bits do MeshAgent", "ru": "32-разрядная версия MeshAgent", + "zh-chs": "MeshAgent的32位版本", "xloc": [ - "default.handlebars->25->326", - "default.handlebars->25->340" + "default.handlebars->27->313", + "default.handlebars->27->330" ] }, { @@ -998,10 +1272,14 @@ "de": "37.5%", "en": "37.5%", "es": "37.5%", + "fr": "37.5%", + "hi": "37.5%", "ja": "37.5%", + "ko": "37.5 %", "nl": "37.5%", - "pt": "37..5%", + "pt": "37.5%", "ru": "37.5%", + "zh-chs": "37.5%", "xloc": [ "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->5->d7bitmapscaling->11", "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->11" @@ -1009,11 +1287,17 @@ }, { "cs": "4. Názvy „OpenSSL Toolkit“ a „OpenSSL Project“ nesmí být bez předchozího písemného souhlasu použity k doporučování nebo propagaci produktů odvozených z tohoto softwaru. Pro písemné povolení kontaktujte na openssl-core@openssl.org.", + "de": "4.Die Namen \"OpenSSL Toolkit\" und \"OpenSSL Project\" dürfen ohne vorherige schriftliche Genehmigung nicht verwendet werden, um von dieser Software abgeleitete Produkte zu unterstützen oder zu bewerben. Für eine schriftliche Genehmigung wenden Sie sich bitte an openssl-core@openssl.org.", "en": "4.The names \"OpenSSL Toolkit\" and \"OpenSSL Project\" must not be used to endorse or promote products derived from this software without prior written permission. For written permission, please contact openssl-core@openssl.org.", "es": "4. Los nombres \"OpenSSL Toolkit\" y \"OpenSSL Project\" no deben utilizarse para respaldar o promocionar productos derivados de este software sin un permiso previo por escrito. Para obtener un permiso por escrito, comuníquese con openssl-core@openssl.org.", + "fr": "4. Les noms «OpenSSL Toolkit» et «OpenSSL Project» ne doivent pas être utilisés pour approuver ou promouvoir des produits dérivés de ce logiciel sans autorisation écrite préalable. Pour une autorisation écrite, veuillez contacter openssl-core@openssl.org.", + "hi": "4. \"ओपनएसएसएल टूलकिट\" और \"ओपनएसएसएल प्रोजेक्ट\" नामों का उपयोग पूर्व लिखित अनुमति के बिना इस सॉफ्टवेयर से प्राप्त उत्पादों को समर्थन या बढ़ावा देने के लिए नहीं किया जाना चाहिए। लिखित अनुमति के लिए, कृपया खुलता है- whatsl-core@openssl.org।", "ja": "4.「OpenSSL Toolkit」および「OpenSSL Project」という名前は、事前の書面による許可なしに、このソフトウェアから派生した製品を推奨または宣伝するために使用しないでください。書面による許可については、openssl-core @ openssl.orgにお問い合わせください。", + "ko": "4. 사전 서면 허가없이 \"OpenSSL Toolkit\"및 \"OpenSSL Project\"라는 이름을 사용하여이 소프트웨어에서 파생 된 제품을 보증하거나 홍보해서는 안됩니다. 서면 허가를 받으려면 openssl-core@openssl.org에 문의하십시오.", "nl": "4.De namen \"OpenSSL Toolkit\" en \"OpenSSL Project\" mogen niet worden gebruikt om producten die zijn afgeleid van deze software te ondersteunen of promoten zonder voorafgaande schriftelijke toestemming. Neem voor schriftelijke toestemming contact op met openssl-core@openssl.org.", + "pt": "4.Os nomes \"OpenSSL Toolkit\" e \"OpenSSL Project\" não devem ser usados ​​para endossar ou promover produtos derivados deste software sem permissão prévia por escrito. Para permissão por escrito, entre em contato com openssl-core@openssl.org.", "ru": "4.Наименования «OpenSSL Toolkit» и «OpenSSL Project» не должны использоваться для поддержки или продвижения продуктов, созданных на основе данного программного обеспечения, без предварительного письменного разрешения. Для получения письменного разрешения, пожалуйста, свяжитесь с openssl-core@openssl.org.", + "zh-chs": "4.未經事先書面許可,不得使用名稱“ OpenSSL Toolkit”和“ OpenSSL Project”來認可或促銷從該軟件衍生的產品。要獲得書面許可,請聯繫openssl-core@openssl.org。", "xloc": [ "terms-mobile.handlebars->container->page_content->column_l->37->1", "terms.handlebars->container->column_l->37->1" @@ -1021,12 +1305,17 @@ }, { "cs": "4. jQuery uživatelské rozhraní – MIT Licence", + "de": "4.jQuery-Benutzeroberfläche - MIT-Lizenz", "en": "4.jQuery User Interface - MIT License", "es": "4.jQuery User Interface - Licencia MIT", + "fr": "4. Interface utilisateur jQuery - Licence MIT", + "hi": "4.jQuery उपयोगकर्ता इंटरफ़ेस - एमआईटी लाइसेंस", "ja": "4. jQueryユーザーインターフェイス-MITライセンス", + "ko": "4.jQuery 사용자 인터페이스-MIT 라이센스", "nl": "4.jQuery Gebruikers Interface - MIT Licentie", "pt": "4.Interface do Usuário jQuery - Licença MIT", "ru": "4.jQuery User Interface - MIT Лицензия", + "zh-chs": "4.jQuery用戶界面-MIT許可證", "xloc": [ "terms-mobile.handlebars->container->page_content->column_l->51->1->0", "terms.handlebars->container->column_l->51->1->0" @@ -1037,10 +1326,14 @@ "de": "404", "en": "404", "es": "404", + "fr": "404", + "hi": "404", "ja": "404", + "ko": "404", "nl": "404", "pt": "404", "ru": "404", + "zh-chs": "404", "xloc": [ "error404-mobile.handlebars->container->page_content->column_l->1->0", "error404.handlebars->container->column_l->1->0" @@ -1052,21 +1345,30 @@ "en": "4x Speed", "es": "Velocidad 4x", "fr": "4x vitesse", + "hi": "4x स्पीड", "ja": "4倍速", + "ko": "4 배속", "nl": "4x snelheid", "pt": "4x velocidade", "ru": "4x Скорость", + "zh-chs": "4倍速度", "xloc": [ "player.handlebars->p11->deskarea0->deskarea4->3->PlaySpeed->9" ] }, { "cs": "5. Produkty odvozené od tohoto softwaru nesmí být nazývány „OpenSSL“ ani se nesmí „OpenSSL“ objevit v jejich názvech bez předchozího písemného souhlasu projektu OpenSSL.", + "de": "5. Von dieser Software abgeleitete Produkte dürfen ohne vorherige schriftliche Genehmigung des OpenSSL-Projekts weder \"OpenSSL\" genannt noch \"OpenSSL\" in ihren Namen angezeigt werden.", "en": "5.Products derived from this software may not be called \"OpenSSL\" nor may \"OpenSSL\" appear in their names without prior written permission of the OpenSSL Project.", "es": "5. Los productos derivados de este software no pueden llamarse \"OpenSSL\" ni \"OpenSSL\" aparecer en sus nombres sin el permiso previo por escrito del Proyecto OpenSSL.", + "fr": "5.Les produits dérivés de ce logiciel ne peuvent pas être appelés \"OpenSSL\" ni \"OpenSSL\" apparaître dans leurs noms sans l'autorisation écrite préalable du projet OpenSSL.", + "hi": "5. इस सॉफ्टवेयर से प्राप्त उत्पादों को \"ओपनएसएसएल\" नहीं कहा जा सकता है और न ही ओपनएसएसएल परियोजना की पूर्व लिखित अनुमति के बिना उनके नाम में \"ओपनएसएसएल\" दिखाई दे सकता है।", "ja": "5.このソフトウェアから派生した製品は、OpenSSL Projectの事前の書面による許可なしに、「OpenSSL」と呼ばれたり、名前に「OpenSSL」が表示されたりすることはありません。", + "ko": "5. OpenSSL Project의 사전 서면 승인없이이 소프트웨어에서 파생 된 제품을 \"OpenSSL\"이라고하거나 이름에 \"OpenSSL\"을 표시 할 수 없습니다.", "nl": "5.Producten die zijn afgeleid van deze software mogen niet \"OpenSSL\" worden genoemd, noch mag \"OpenSSL\" in hun naam worden weergegeven zonder voorafgaande schriftelijke toestemming van het OpenSSL-project.", + "pt": "5.Os produtos derivados deste software não podem ser chamados de \"OpenSSL\" nem \"OpenSSL\" aparece em seus nomes sem a permissão prévia por escrito do OpenSSL Project.", "ru": "5. Продукты, полученные из этого программного обеспечения, не могут называться «OpenSSL», а также «OpenSSL» не может появляться в их названиях без предварительного письменного разрешения OpenSSL Project.", + "zh-chs": "5.未經OpenSSL Project事先書面許可,從該軟件派生的產品不得稱為“ OpenSSL”,也不得在其名稱中出現“ OpenSSL”。", "xloc": [ "terms-mobile.handlebars->container->page_content->column_l->39->1", "terms.handlebars->container->column_l->39->1" @@ -1074,12 +1376,17 @@ }, { "cs": "5. noVNC – Mozilla Public licence 2.0", + "de": "5.noVNC - Mozilla Public License 2.0", "en": "5.noVNC - Mozilla Public License 2.0", "es": "5.noVNC - Mozilla Public License 2.0", + "fr": "5.noVNC - Mozilla Public License 2.0", + "hi": "5.noVNC - मोज़िला पब्लिक लाइसेंस 2.0", "ja": "5. noVNC-Mozilla Public License 2.0", + "ko": "5. noVNC-Mozilla Public License 2.0", "nl": "5.noVNC - Mozilla Public Licentie 2.0", "pt": "5.noVNC - Licença Pública Mozilla 2.0 0", "ru": "5.noVNC - Mozilla Public License 2.0", + "zh-chs": "5.noVNC-Mozilla公共許可證2.0", "xloc": [ "terms-mobile.handlebars->container->page_content->column_l->59->1->0", "terms.handlebars->container->column_l->59->1->0" @@ -1090,10 +1397,14 @@ "de": "50%", "en": "50%", "es": "50%", + "fr": "50%", + "hi": "50%", "ja": "50%", + "ko": "50 %", "nl": "50%", "pt": "50%", "ru": "50%", + "zh-chs": "50%", "xloc": [ "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->5->d7bitmapscaling->9", "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->9" @@ -1101,12 +1412,17 @@ }, { "cs": "6. Rcarousel – MIT licence", + "de": "6. Karussell - MIT LIcense", "en": "6.Rcarousel - MIT LIcense", "es": "6.Rcarousel - Licencia MIT", - "ja": "6.Rcarousel-MITライセンス", + "fr": "6. Carrousel - Licence MIT", + "hi": "6.रॉसेल - MIT LIcense", + "ja": "6.Rcarousel - MITライセンス", + "ko": "6. 회전 목마-MIT 라이센스", "nl": "6.Rcarousel - MIT Licentie", "pt": "6.Rcarousel - License MIT", "ru": "6.Rcarousel - MIT Лицензия", + "zh-chs": "6,Rcarousel-麻省理工學院執照", "xloc": [ "terms-mobile.handlebars->container->page_content->column_l->65->1->0", "terms.handlebars->container->column_l->65->1->0" @@ -1114,12 +1430,17 @@ }, { "cs": "6. Šíření dál v jakékoli formě si musí zachovat následující prohlášení: „Tento produkt zahrnuje software vyvinutý v rámci projektu OpenSSL pro použití v sadě OpenSSL Toolkit (http://www.openssl.org/)“.", + "de": "6. Weiterverteilungen jeglicher Art müssen die folgende Bestätigung behalten: \"Dieses Produkt enthält Software, die vom OpenSSL-Projekt zur Verwendung im OpenSSL Toolkit (http://www.openssl.org/) entwickelt wurde.\"", "en": "6.Redistributions of any form whatsoever must retain the following acknowledgment: \"This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/)\".", "es": "6. Las redistribuciones de cualquier forma deben conservar el siguiente reconocimiento: \"Este producto incluye software desarrollado por OpenSSL Project para su uso en OpenSSL Toolkit (http://www.openssl.org/)\".", + "fr": "6.Les redistributions sous quelque forme que ce soit doivent conserver la mention suivante: \"Ce produit comprend un logiciel développé par le projet OpenSSL pour une utilisation dans la boîte à outils OpenSSL (http://www.openssl.org/)\".", + "hi": "किसी भी रूप के 6.Redistributions जो भी निम्नलिखित स्वीकार्यता को बनाए रखने चाहिए: \"इस उत्पाद में OpenSSL टूलकिट (http://www.openssl.org/) में उपयोग के लिए OpenSSL प्रोजेक्ट द्वारा विकसित सॉफ्टवेयर शामिल है\"।", "ja": "6.いかなる形式の再配布でも、「この製品には、OpenSSL Toolkit(http://www.openssl.org/)で使用するためにOpenSSL Projectによって開発されたソフトウェアが含まれます」という承認を保持する必要があります。", + "ko": "6. \"이 제품에는 OpenSSL 툴킷 (http://www.openssl.org/)에서 사용하기 위해 OpenSSL Project에서 개발 한 소프트웨어가 포함되어 있습니다.\"", "nl": "6.Herdistributies in welke vorm dan ook moet de volgende tekst behouden: \"Dit product bevat software die is ontwikkeld door het OpenSSL-project voor gebruik in de OpenSSL Toolkit (http://www.openssl.org/)\".", "pt": "6.As redistribuições de qualquer forma devem manter o seguinte reconhecimento: \"Este produto inclui software desenvolvido pelo OpenSSL Project para uso no OpenSSL Toolkit (http://www.openssl.org/)\".", "ru": "6.Распространение в любой форме должно включать следующее подтверждение: \"Этот продукт включает программное обеспечение, разработанное OpenSSL Project для использования в OpenSSL Toolkit (http://www.openssl.org/)\".", + "zh-chs": "6.任何形式的重新分發都必須保留以下聲明:“此產品包括由OpenSSL Project開發的,用於OpenSSL Toolkit(http://www.openssl.org/)的軟件”。", "xloc": [ "terms-mobile.handlebars->container->page_content->column_l->41->1", "terms.handlebars->container->column_l->41->1" @@ -1130,27 +1451,51 @@ "de": "62.5%", "en": "62.5%", "es": "62.5%", + "fr": "62.5%", + "hi": "62.5%", "ja": "62.5%", + "ko": "62.5 %", "nl": "62.5%", "pt": "62.5%", "ru": "62.5%", + "zh-chs": "62.5%", "xloc": [ "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->5->d7bitmapscaling->7", "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->7" ] }, + { + "cs": "64bitová verze agenta MacOS Mesh Agent", + "de": "64-Bit-Version von MacOS Mesh Agent", + "en": "64bit version of MacOS Mesh Agent", + "fr": "Version 64 bits de MacOS Mesh Agent", + "hi": "MacOS मेष एजेंट का 64 बिट संस्करण", + "ja": "MacOS Mesh Agentの64ビットバージョン", + "ko": "MacOS Mesh Agent 64 비트 버전", + "nl": "64bit versie van de MacOS Mesh Agent", + "pt": "Versão de 64 bits do MacOS Mesh Agent", + "ru": "64-битная версия MacOS Mesh Agent", + "zh-chs": "64位版本的MacOS Mesh Agent", + "xloc": [ + "default.handlebars->27->326" + ] + }, { "cs": "64bit verze MeshAgent", "de": "64bit-Version des MeshAgents", "en": "64bit version of the MeshAgent", "es": "Version 64bits del MeshAgent", + "fr": "Version 64bits de MeshAgent", + "hi": "मेशजेंट का 64 बिट संस्करण", "ja": "MeshAgentの64ビットバージョン", + "ko": "64 비트 버전의 MeshAgent", "nl": "64bit versie van de MeshAgent", "pt": "Versão de 64 bits do MeshAgent", "ru": "64-разрядная версия MeshAgent", + "zh-chs": "MeshAgent的64位版本", "xloc": [ - "default.handlebars->25->329", - "default.handlebars->25->343" + "default.handlebars->27->317", + "default.handlebars->27->333" ] }, { @@ -1158,30 +1503,45 @@ "de": "7-Tage-Anmelde-Status", "en": "7 Day Login State", "es": "Estado de inicio de sesión de 7 días", + "fr": "Statistiques de connexions sur 7 jours ", + "hi": "7 दिन लॉगिन राज्य", + "ja": "7日間のログイン状態", + "ko": "7 일 로그인 상태", "nl": "Inlogstatus afgelopen 7 dagen", - "ru": "7-дневная статистика входов" + "pt": "Estado de login de 7 dias", + "ru": "7-дневная статистика входов", + "zh-chs": "7天登錄狀態" }, { "cs": "Stav napájení za uplynulých 7 dnů", "de": "7-Tage-Energiezustand", "en": "7 Day Power State", "es": "Estado de energía de 7 días", + "fr": "Alimentation sur les 7 derniers jours", + "hi": "7 डे पावर स्टेट", "ja": "7日間の電源状態", + "ko": "7 일 전원 상태", "nl": "7 dagen stroom status", "pt": "Estado de energia de 7 dias", "ru": "7-дневная статистика работы", + "zh-chs": "7天電源狀態", "xloc": [ - "default.handlebars->25->546" + "default.handlebars->27->593" ] }, { "cs": "7. Webtoolkit Javascript Base 64 – Creative Commons Attribution 2.0 UK licence", + "de": "7.Webtoolkit Javascript Base 64 - Creative Commons Attribution 2.0 UK-Lizenz", "en": "7.Webtoolkit Javascript Base 64 – Creative Commons Attribution 2.0 UK License", "es": "7.Webtoolkit Javascript Base 64 - Creative Commons Attribution 2.0 UK Licencia", + "fr": "7.Webtoolkit Javascript Base 64 - Licence Creative Commons Attribution 2.0 UK", + "hi": "7.वेबटूलकिट जावास्क्रिप्ट बेस 64 - क्रिएटिव कॉमन्स एट्रिब्यूशन 2.0 यूके लाइसेंस", "ja": "7.Webtoolkit Javascript Base 64 – Creative Commons Attribution 2.0 UKライセンス", + "ko": "7. Webtoolkit Javascript Base 64 – Creative Commons Attribution 2.0 영국 라이센스", "nl": "7.Webtoolkit Javascript Base 64 – Creative Commons Attribution 2.0 UK Licentie", "pt": "7.Webtoolkit Javascript Base 64 - Licença Creative Commons Attribution 2.0 UK", "ru": "7.Webtoolkit Javascript Base 64 – Creative Commons Attribution 2.0 UK Лицензия", + "zh-chs": "7.Webtoolkit Javascript Base 64 –知識共享署名2.0英國許可證", "xloc": [ "terms-mobile.handlebars->container->page_content->column_l->73->1->0", "terms.handlebars->container->column_l->73->1->0" @@ -1192,10 +1552,14 @@ "de": "75%", "en": "75%", "es": "75%", + "fr": "75%", + "hi": "75%", "ja": "75%", + "ko": "75 %", "nl": "75%", "pt": "75%", "ru": "75%", + "zh-chs": "75%", "xloc": [ "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->5->d7bitmapscaling->5", "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->5" @@ -1207,13 +1571,16 @@ "en": "8 hours", "es": "8 horas", "fr": "8 heures", + "hi": "8 घंटे", "ja": "8時間", + "ko": "8 시간", "nl": "8 uur", "pt": "8 horas", "ru": "8 часов", + "zh-chs": "8小時", "xloc": [ - "default.handlebars->25->293", - "default.handlebars->25->307" + "default.handlebars->27->280", + "default.handlebars->27->294" ] }, { @@ -1221,10 +1588,14 @@ "de": "80x25", "en": "80x25", "es": "80x25", + "fr": "80x25", + "hi": "80x25", "ja": "80x25", + "ko": "80x25", "nl": "80x25", "pt": "80x25", "ru": "80x25", + "zh-chs": "80x25", "xloc": [ "default.handlebars->container->column_l->p12->termTable->1->1->6->1->1->terminalSizeDropDown->termSizeList->0" ] @@ -1234,10 +1605,14 @@ "de": "87.5%", "en": "87.5%", "es": "87.5%", + "fr": "87.5%", + "hi": "87.5%", "ja": "87.5%", + "ko": "87.5 %", "nl": "87.5%", "pt": "87.5%", "ru": "87.5%", + "zh-chs": "87.5%", "xloc": [ "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->5->d7bitmapscaling->3", "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->3" @@ -1248,6 +1623,7 @@ "de": ":", "en": ":", "es": ":", + "fr": ":", "ja": ":", "nl": ":", "pt": ":", @@ -1256,17 +1632,38 @@ "agentinvite.handlebars->3->4" ] }, + { + "cs": "<<", + "de": "<<", + "en": "<<", + "es": "<<", + "fr": "<<", + "hi": "<<", + "ja": "<<", + "ko": "<<", + "nl": "<<", + "pt": "<<", + "ru": "<<", + "zh-chs": "<<", + "xloc": [ + "player.handlebars->p11->deskarea0->deskarea4->3" + ] + }, { "cs": "Hardwarové klíče jsou použity jako druhý faktor ověřování.", "de": "Hardware-Schlüssel werden für Zweifaktor-Anmeldung verwendet.", "en": "Hardware keys are used as secondary login authentication.", "es": "Las claves de Hardware son usadas como segundo factor de autenticación.", + "fr": "Les clés physiques (Yubikeys) sont utilisées pour l'authentification à double facteur.", + "hi": " हार्डवेयर कुंजियाँ को द्वितीयक लॉगिन प्रमाणीकरण के रूप में उपयोग किया जाता है।", "ja": "ハードウェアキーは、セカンダリログイン認証として使用されます。", + "ko": " 하드웨어 키 는 보조 로그인 인증으로 사용됩니다.", "nl": "Hardware sleutels worden gebruikt als secundaire inlogverificatie.", "pt": "Chaves Hardware são usados como autenticação de login secundária.", "ru": "Аппаратные ключи используются в качестве дополнительной аутентификации.", + "zh-chs": "硬件密鑰用作輔助登錄身份驗證。", "xloc": [ - "default.handlebars->25->139" + "default.handlebars->27->122" ] }, { @@ -1274,10 +1671,14 @@ "de": "Aktivierung der Zweifaktor-Anmeldung entfernt. Sie können dieses Merkmal jederzeit reaktivieren.", "en": "2-step login activation removed. You can reactivate this feature at any time.", "es": "Activación de inicio de sesión de 2 pasos eliminada. Puede reactivar esta funcion en cualqueir momento.", - "ja": " 2段階のログインアクティベーションが削除されました。この機能はいつでも再アクティブ化できます。", + "fr": "Authentification à double facteur supprimée. Vous pouvez la réactiver à n'importe quel moment.", + "hi": "2-चरण लॉगिन सक्रियण हटा दिया गया । आप किसी भी समय इस सुविधा को पुनः सक्रिय कर सकते हैं।", + "ja": "2段階のログインアクティベーションが削除されました。この機能はいつでも再アクティブ化できます。", + "ko": "2 단계 로그인 활성화가 제거되었습니다 . 언제든지이 기능을 다시 활성화 할 수 있습니다.", "nl": "Tweestapsverificatie verwijderd. Je kan deze functie ten allen tijde weer inschakelen.", "pt": "Ativação de login em duas etapas removida. Você pode reativar esse recurso a qualquer momento.", "ru": "Активация двухэтапного входа удалена. Вы можете активировать обратно эту функцию в любое время.", + "zh-chs": "刪除了兩步登錄激活。您可以隨時重新激活此功能。", "xloc": [ "default-mobile.handlebars->9->22" ] @@ -1287,10 +1688,14 @@ "de": "Aktivierung der Zweifaktor-Anmeldung erfolgreich. Sie werden nun ein gültiges Token benötigen, um sich erneut einzuloggen.", "en": "2-step login activation successful. You will now need a valid token to login again.", "es": "Segundo-factor de autentcacion activado exitosamente. Ahora necesitará un token válido para iniciar sesión nuevamente.", - "ja": " 2段階ログインの有効化に成功。再度ログインするには、有効なトークンが必要になります。", + "fr": "Authentification à double facteur activée. Vous aurez besoin maintenant d'un jeton de connexion pour vous connecter. ", + "hi": "2-चरण लॉगिन सक्रियण सफल । अब आपको फिर से लॉगिन करने के लिए वैध टोकन की आवश्यकता होगी।", + "ja": "2段階ログインの有効化に成功。再度ログインするには、有効なトークンが必要になります。", + "ko": "2 단계 로그인 활성화 성공 . 이제 다시 로그인하려면 유효한 토큰이 필요합니다.", "nl": "Tweestapsverificatie successvol. U hebt nu een geldig token nodig om opnieuw in te loggen.", "pt": " ativação de login em duas etapas . Agora você precisará de um token válido para fazer login novamente.", "ru": "Активация двухэтапного входа успешна. Теперь вам понадобится действительный токен, чтобы снова войти в систему.", + "zh-chs": "兩步登錄激活成功。您現在需要一個有效的令牌才能再次登錄。", "xloc": [ "default-mobile.handlebars->9->19" ] @@ -1299,11 +1704,15 @@ "cs": "zapnutí 2-faktorového přihlášení se nezdařilo. Vymažte tajemství z aplikace a zkuste to znovu. Na zadání správného kódu máte jen pár minut.", "de": "Aktivierung der Zweifaktor-Anmeldung fehlgeschlagen. Entfernen Sie das Geheimnis aus der Applikation und versuchen Sie es erneut. Sie haben nur wenige Minuten Zeit, um einen gültigen Code einzugeben.", "en": "2-step login activation failed. Clear the secret from the application and try again. You only have a few minutes to enter the proper code.", - "es": " Error de activación de inicio de sesión usando el segundo factor de autenticación. Borre el código de la aplicación e intente nuevamente. Solo tiene unos minutos para ingresar el código adecuado.", - "ja": " 2段階ログインの有効化に失敗しました。アプリケーションから秘密をクリアして、再試行してください。適切なコードを入力するのに数分しかかかりません。", + "es": "Error de activación de inicio de sesión usando el segundo factor de autenticación. Borre el código de la aplicación e intente nuevamente. Solo tiene unos minutos para ingresar el código adecuado.", + "fr": "Echec de l'authentification à double facteur. Essayez à nouveau. Vous disposez de quelques minutes pour taper le bon code.", + "hi": "2-step लॉगिन सक्रियण विफल है। एप्लिकेशन से रहस्य साफ़ करें और पुनः प्रयास करें। आपके पास उचित कोड दर्ज करने के लिए केवल कुछ मिनट हैं।", + "ja": "2段階ログインの有効化に失敗しました。アプリケーションから秘密をクリアして、再試行してください。適切なコードを入力するのに数分しかかかりません。", + "ko": "2 단계 로그인 활성화 실패 . 응용 프로그램에서 비밀을 지우고 다시 시도하십시오. 올바른 코드를 입력하는 데 몇 분 밖에 걸리지 않습니다.", "nl": "Tweestapsverificatie mislukt. Wis het geheim van de applicatie en probeer het opnieuw. Je hebt maar een paar minuten om de juiste code in te voeren.", - "pt": " falha na ativação do login em duas etapas . Limpe o segredo do aplicativo e tente novamente. Você tem apenas alguns minutos para inserir o código correto.", + "pt": "falha na ativação do login em duas etapas . Limpe o segredo do aplicativo e tente novamente. Você tem apenas alguns minutos para inserir o código correto.", "ru": "Активация двухэтапного входа не удалась. Удалите ключ из приложения и попробуйте еще раз. У вас есть всего несколько минут, чтобы ввести правильный код.", + "zh-chs": "兩步登錄激活失敗。從應用程序中清除機密,然後重試。您只有幾分鐘的時間來輸入正確的代碼。", "xloc": [ "default-mobile.handlebars->9->20" ] @@ -1312,27 +1721,52 @@ "cs": "Odstranění 2-faktorového přihlašování se nezdařilo. Zkuste znovu.", "de": "Entfernen der Aktivierung der Zweifaktor-Anmeldung fehlgeschlagen. Versuchen Sie es erneut.", "en": "2-step login activation removal failed. Try again.", - "es": " Error al eliminar la activación del segundo factor de autenticación. Inténtalo de nuevo.", - "ja": " 2段階のログインアクティベーションの削除に失敗しました。再試行する。", + "es": "Error al eliminar la activación del segundo factor de autenticación. Inténtalo de nuevo.", + "fr": "Echec de la suppression de l'authentification à double facteur. Essayer à nouveau.", + "hi": "2-step लॉगिन सक्रियण निष्कासन विफल रहा। पुनः प्रयास करें।", + "ja": "2段階のログインアクティベーションの削除に失敗しました。再試行する。", + "ko": "2 단계 로그인 활성화 제거에 실패했습니다 . 다시 시도하십시오.", "nl": "Tweestapsverificatie verwijdering mislukt. Probeer het opnieuw.", - "pt": " falha na remoção da ativação do login em duas etapas . Tente novamente.", + "pt": "falha na remoção da ativação do login em duas etapas . Tente novamente.", "ru": "Удаление активации двухэтапного входа не удалось. Попытайтесь снова.", + "zh-chs": "兩步登錄激活刪除失敗。再試一次。", "xloc": [ "default-mobile.handlebars->9->23" ] }, + { + "cs": ">>", + "de": ">>", + "en": ">>", + "es": ">>", + "fr": ">>", + "hi": ">>", + "ja": ">>", + "ko": ">>", + "nl": ">>", + "pt": ">>", + "ru": ">>", + "zh-chs": ">>", + "xloc": [ + "player.handlebars->p11->deskarea0->deskarea4->3" + ] + }, { "cs": "ACM", "de": "ACM", "en": "ACM", "es": "ACM", + "fr": "ACM", + "hi": "ACM", "ja": "ACM", + "ko": "ACM", "nl": "ACM", "pt": "ACM", "ru": "ACM", + "zh-chs": "ACM", "xloc": [ - "default-mobile.handlebars->9->182", - "default.handlebars->25->462" + "default-mobile.handlebars->9->186", + "default.handlebars->27->469" ] }, { @@ -1340,13 +1774,17 @@ "de": "AMT", "en": "AMT", "es": "AMT", + "fr": "AMT", + "hi": "AMT", "ja": "AMT", + "ko": "AMT", "nl": "AMT", "pt": "AMT", "ru": "AMT", + "zh-chs": "AMT", "xloc": [ - "default.handlebars->25->188", - "default.handlebars->25->375" + "default.handlebars->27->172", + "default.handlebars->27->365" ] }, { @@ -1354,13 +1792,17 @@ "de": "ARM-Linaro", "en": "ARM-Linaro", "es": "ARM-Linaro", - "ja": "ARM-リナロ", + "fr": "ARM-Linaro", + "hi": "ARM-Linaro", + "ja": "ARM-Linaro", + "ko": "ARM-Linaro", "nl": "ARM-Linaro", "pt": "ARM-Linaro", "ru": "ARM-Linaro", + "zh-chs": "ARM-Linaro", "xloc": [ - "default-mobile.handlebars->9->167", - "default.handlebars->25->37" + "default-mobile.handlebars->9->171", + "default.handlebars->27->37" ] }, { @@ -1368,13 +1810,17 @@ "de": "ARMv6l / ARMv7l", "en": "ARMv6l / ARMv7l", "es": "ARMv6l / ARMv7l", + "fr": "ARMv6l / ARMv7l", + "hi": "ARMv6l / ARMv7l", "ja": "ARMv6l / ARMv7l", + "ko": "ARMv6l / ARMv7l", "nl": "ARMv6l / ARMv7l", "pt": "ARMv6l / ARMv7l", "ru": "ARMv6l / ARMv7l", + "zh-chs": "ARMv6l / ARMv7l", "xloc": [ - "default-mobile.handlebars->9->168", - "default.handlebars->25->38" + "default-mobile.handlebars->9->172", + "default.handlebars->27->38" ] }, { @@ -1382,13 +1828,17 @@ "de": "ARMv6l / ARMv7l / NoKVM", "en": "ARMv6l / ARMv7l / NoKVM", "es": "ARMv6l / ARMv7l / Sin KVM", + "fr": "ARMv6l / ARMv7l / NoKVM", + "hi": "ARMv6l / ARMv7l / NoKVM", "ja": "ARMv6l / ARMv7l / NoKVM", + "ko": "ARMv6l / ARMv7l / NoKVM", "nl": "ARMv6l / ARMv7l / NoKVM", "pt": "ARMv6l / ARMv7l / NoKVM", "ru": "ARMv6l / ARMv7l / NoKVM", + "zh-chs": "ARMv6l / ARMv7l / NoKVM", "xloc": [ - "default-mobile.handlebars->9->170", - "default.handlebars->25->40" + "default-mobile.handlebars->9->174", + "default.handlebars->27->40" ] }, { @@ -1396,13 +1846,17 @@ "de": "ARMv8 64bit", "en": "ARMv8 64bit", "es": "ARMv8 64bits", + "fr": "ARMv8 64bit", + "hi": "ARMv8 64 बिट", "ja": "ARMv8 64ビット", + "ko": "ARMv8 64 비트", "nl": "ARMv8 64bit", "pt": "ARMv8 64bit", "ru": "ARMv8 64bit", + "zh-chs": "ARMv8 64位", "xloc": [ - "default-mobile.handlebars->9->169", - "default.handlebars->25->39" + "default-mobile.handlebars->9->173", + "default.handlebars->27->39" ] }, { @@ -1411,12 +1865,15 @@ "en": "Access Denied", "es": "Acceso Negado", "fr": "Accès refusé", + "hi": "पहुंच अस्वीकृत", "ja": "アクセスが拒否されました", + "ko": "접근 불가", "nl": "Toegang geweigerd", "pt": "Acesso Negado", "ru": "Отказано в доступе", + "zh-chs": "拒絕訪問", "xloc": [ - "default.handlebars->25->695" + "default.handlebars->27->796" ] }, { @@ -1424,12 +1881,17 @@ "de": "Zugriff verweigert.", "en": "Access denied.", "es": "Acceso Negado", + "fr": "Accès refusé.", + "hi": "पहुंच अस्वीकृत।", "ja": "アクセスが拒否されました。", + "ko": "접근 불가.", "nl": "Toegang geweigerd.", + "pt": "Acesso negado.", "ru": "Отказано в доступе.", + "zh-chs": "拒絕訪問。", "xloc": [ - "login-mobile.handlebars->5->13", - "login.handlebars->5->13" + "login-mobile.handlebars->5->14", + "login.handlebars->5->14" ] }, { @@ -1437,12 +1899,16 @@ "de": "Zugriff auf Server-Dateien", "en": "Access to server files", "es": "Acceso a archivos del servidor", + "fr": "Accès au serveur de fichiers", + "hi": "सर्वर फ़ाइलों तक पहुँच", "ja": "サーバーファイルへのアクセス", + "ko": "서버 파일에 액세스", "nl": "Toegang tot de server bestanden", "pt": "Acesso aos arquivos do servidor", "ru": "Доступ к файлам сервера", + "zh-chs": "訪問服務器文件", "xloc": [ - "default.handlebars->25->1319" + "default.handlebars->27->1453" ] }, { @@ -1450,10 +1916,14 @@ "de": "Konto-Aktionen", "en": "Account Actions", "es": "Acciones de la cuenta", + "fr": "Gestion du compte", + "hi": "खाता क्रिया", "ja": "アカウントアクション", - "nl": "gebruikersacties", + "ko": "계정 작업", + "nl": "Gebruikersacties", "pt": "Ações da Conta", "ru": "Действия учетной записи", + "zh-chs": "帳戶動作", "xloc": [ "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3AccountActions->5->0" ] @@ -1463,10 +1933,14 @@ "de": "Konto-Erzeugung", "en": "Account Creation", "es": "Creación de Cuenta", + "fr": "Création de compte", + "hi": "खाता निर्माण", "ja": "アカウント作成", + "ko": "계정 생성", "nl": "Gebruikersaccount aanmaken", "pt": "Criação de conta", "ru": "Создание учетной записи", + "zh-chs": "賬戶創建", "xloc": [ "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->createpanel->1->1->5->1", "login.handlebars->container->column_l->centralTable->1->0->logincell->createpanel->1->5->1" @@ -1477,10 +1951,14 @@ "de": "Konto-Rücksetzung", "en": "Account Reset", "es": "Restablecimiento de cuenta", + "fr": "Réinitialisation du compte", + "hi": "खाता रीसेट करें", "ja": "アカウントのリセット", + "ko": "계정 재설정", "nl": "Gebruikersaccount resetten", "pt": "Redefinição de conta", "ru": "Сброс учетной записи", + "zh-chs": "賬戶重置", "xloc": [ "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->resetpanel->1->5->1", "login.handlebars->container->column_l->centralTable->1->0->logincell->resetpanel->1->5->1" @@ -1491,20 +1969,24 @@ "de": "Konto-Sicherheit", "en": "Account Security", "es": "Seguridad de la cuenta", + "fr": "Sécurité du compte", + "hi": "खाते की सुरक्षा", "ja": "アカウントのセキュリティ", + "ko": "계정 보안", "nl": "Gebruikersaccount beveiliging", "pt": "Segurança da Conta", "ru": "Безопасность учетной записи", + "zh-chs": "帳號安全", "xloc": [ - "default-mobile.handlebars->9->129", - "default-mobile.handlebars->9->131", - "default-mobile.handlebars->9->52", - "default-mobile.handlebars->9->54", + "default-mobile.handlebars->9->133", + "default-mobile.handlebars->9->135", + "default-mobile.handlebars->9->55", + "default-mobile.handlebars->9->57", "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3AccountActions->1->0", - "default.handlebars->25->435", - "default.handlebars->25->437", - "default.handlebars->25->950", - "default.handlebars->25->952" + "default.handlebars->27->1055", + "default.handlebars->27->1057", + "default.handlebars->27->439", + "default.handlebars->27->441" ] }, { @@ -1512,25 +1994,48 @@ "de": "Konto-Aktionen", "en": "Account actions", "es": "Acciones de la cuenta", + "fr": "Gestion du compte", + "hi": "खाता क्रिया", "ja": "アカウントアクション", - "nl": "gebruikersacties", + "ko": "계정 작업", + "nl": "Gebruikersacties", "pt": "Ações da conta", "ru": "Действия учетной записи", + "zh-chs": "帳戶動作", "xloc": [ "default.handlebars->container->column_l->p2->p2AccountActions->1->0" ] }, + { + "cs": "Účet je uzamčen", + "de": "Konto ist gesperrt", + "en": "Account is locked", + "fr": "Le compte est verrouillé", + "ja": "アカウントがロックされています", + "nl": "Account is uitgeschakeld", + "ru": "Аккаунт заблокирован", + "zh-chs": "帐户已被锁定", + "xloc": [ + "default.handlebars->27->1357", + "default.handlebars->27->1450" + ] + }, { "cs": "Dosažen nejvyšší možný počet účtů.", "de": "Konten-Obergrenze erreicht.", "en": "Account limit reached.", "es": "Límite de cuenta alcanzado.", + "fr": "Limite du compte atteinte.", + "hi": "खाता सीमा तक पहुंच गया।", "ja": "アカウントの上限に達しました。", + "ko": "계정 한도에 도달했습니다.", "nl": "Gebruikersaccount limiet bereikt.", + "pt": "Limite da conta atingido.", "ru": "Достигнуто ограничение учетных записей.", + "zh-chs": "達到帳戶限制。", "xloc": [ - "login-mobile.handlebars->5->3", - "login.handlebars->5->3" + "login-mobile.handlebars->5->4", + "login.handlebars->5->4" ] }, { @@ -1538,12 +2043,17 @@ "de": "Konto gesperrt.", "en": "Account locked.", "es": "Cuenta Bloqueada.", + "fr": "Compte bloqué", + "hi": "खाता बंद।", "ja": "アカウントがロックされました。", + "ko": "잠긴 계정.", "nl": "Gebruikersaccount vergrendeld", + "pt": "Conta bloqueada.", "ru": "Учетная запись заблокирована.", + "zh-chs": "帳戶被鎖定。", "xloc": [ - "login-mobile.handlebars->5->12", - "login.handlebars->5->12" + "login-mobile.handlebars->5->13", + "login.handlebars->5->13" ] }, { @@ -1551,12 +2061,17 @@ "de": "Konto nicht gefunden.", "en": "Account not found.", "es": "Cuenta no encontrada.", + "fr": "Compte introuvable", + "hi": "खता नहीं मिला।", "ja": "アカウントが見つかりませんでした。", + "ko": "계정을 찾지 못했습니다.", "nl": "Gebruikersaccount niet gevonden", + "pt": "Conta não encontrada.", "ru": "Учетная запись не найдена.", + "zh-chs": "找不到帳戶。", "xloc": [ - "login-mobile.handlebars->5->9", - "login.handlebars->5->9" + "login-mobile.handlebars->5->10", + "login.handlebars->5->10" ] }, { @@ -1564,10 +2079,14 @@ "de": "Konto-Sicherheit", "en": "Account security", "es": "Seguridad de la cuenta", + "fr": "Sécurité du compte", + "hi": "खाते की सुरक्षा", "ja": "アカウントのセキュリティ", + "ko": "계정 보안", "nl": "Gebruikersaccount beveiliging", "pt": "Segurança da conta", "ru": "Безопасность учетной записи", + "zh-chs": "帳號安全", "xloc": [ "default.handlebars->container->column_l->p2->p2AccountSecurity->1->0" ] @@ -1577,23 +2096,35 @@ "de": "Aktion", "en": "Action", "es": "Acción", + "fr": "action", + "hi": "कार्य", "ja": "アクション", + "ko": "동작", "nl": "Actie", "pt": "Ação", "ru": "Действиe", + "zh-chs": "行動", "xloc": [ - "default.handlebars->25->700", + "default.handlebars->27->801", "default.handlebars->container->column_l->p42->p42tbl->1->0->8" ] }, { + "cs": "Soubor akcí", + "de": "Aktionsdatei", "en": "Action File", "es": "Archivo de acción", + "fr": "Fichier d'actions", + "hi": "कार्रवाई फ़ाइल", + "ja": "アクションファイル", + "ko": "액션 파일", "nl": "Actie bestand", + "pt": "Arquivo de Ação", "ru": "Файл действий", + "zh-chs": "動作文件", "xloc": [ - "default.handlebars->25->586", - "default.handlebars->25->588" + "default.handlebars->27->634", + "default.handlebars->27->636" ] }, { @@ -1601,14 +2132,18 @@ "de": "Aktionen", "en": "Actions", "es": "Acciones", + "fr": "Actions", + "hi": "क्रिया", "ja": "行動", + "ko": "행위", "nl": "Acties", "pt": "Ações", "ru": "Действия", + "zh-chs": "動作", "xloc": [ "default-mobile.handlebars->container->page_content->column_l->p10->p10desktop->deskarea4->1->3", "default-mobile.handlebars->container->page_content->column_l->p10->p10files->p13toolbar->1->0->1->1", - "default.handlebars->25->494", + "default.handlebars->27->501", "default.handlebars->container->column_l->p11->deskarea0->deskarea1->1", "default.handlebars->container->column_l->p12->termTable->1->1->0->1->1", "default.handlebars->container->column_l->p13->p13toolbar->1->0->1->1" @@ -1620,10 +2155,13 @@ "en": "Activate camera & microphone", "es": "Activar cámara y micrófono", "fr": "Activer caméra et microphone", + "hi": "कैमरा और माइक्रोफोन सक्रिय करें", "ja": "カメラとマイクを有効にする", + "ko": "카메라 및 마이크 활성화", "nl": "Activeer camera & microfoon", "pt": "Ativar câmera e microfone", "ru": "Активирование камеры и микрофона", + "zh-chs": "激活相機和麥克風", "xloc": [ "messenger.handlebars->xtop->1" ] @@ -1634,10 +2172,13 @@ "en": "Activate microphone", "es": "Activar micrófono", "fr": "Activer le microphone", + "hi": "माइक्रोफ़ोन को सक्रिय करें", "ja": "マイクを有効にする", + "ko": "마이크 활성화", "nl": "Activeer microfoon", "pt": "Ativar microfone", "ru": "Активирование микрофона", + "zh-chs": "啟動麥克風", "xloc": [ "messenger.handlebars->xtop->1" ] @@ -1648,15 +2189,19 @@ "en": "Activated", "es": "Activado", "fr": "Activé", + "hi": "सक्रिय", "ja": "有効化", + "ko": "활성화", "nl": "Geactiveerd", "pt": "ativado", "ru": "Активировано", + "zh-chs": "活性", "xloc": [ - "default-mobile.handlebars->9->177", - "default-mobile.handlebars->9->179", - "default.handlebars->25->455", - "default.handlebars->25->457" + "default-mobile.handlebars->9->181", + "default-mobile.handlebars->9->183", + "default.handlebars->27->462", + "default.handlebars->27->464", + "default.handlebars->27->766" ] }, { @@ -1664,15 +2209,19 @@ "de": "Aktivierung", "en": "Activation", "es": "Activación", + "fr": "Activation", + "hi": "सक्रियण", "ja": "アクティベーション", + "ko": "활성화", "nl": "Activatie", "pt": "Ativação", "ru": "Активация", + "zh-chs": "激活", "xloc": [ - "default.handlebars->25->1022", - "default.handlebars->25->1024", - "default.handlebars->25->230", - "default.handlebars->25->232" + "default.handlebars->27->1129", + "default.handlebars->27->1131", + "default.handlebars->27->214", + "default.handlebars->27->216" ] }, { @@ -1680,12 +2229,16 @@ "de": "Aktive Benutzer{0}", "en": "Active User{0}", "es": "Usuario Activo {0}", + "fr": "Utilisateur(s) actif(s) {0}", + "hi": "सक्रिय उपयोगकर्ता {0}", "ja": "アクティブユーザー{0}", + "ko": "활성 사용자 {0}", "nl": "Actieve gebruikers{0}", "pt": "Usuário ativo {0}", "ru": "Активный пользователь", + "zh-chs": "活動用戶{0}", "xloc": [ - "default.handlebars->25->481" + "default.handlebars->27->488" ] }, { @@ -1694,12 +2247,15 @@ "en": "Add Agent", "es": "Agregar Agente", "fr": "Ajouter un agent", + "hi": "एजेंट जोड़ें", "ja": "エージェントを追加", + "ko": "에이전트 추가", "nl": "Toevoegen Agent", "pt": "Adicionar agente", "ru": "Добавить агент", + "zh-chs": "添加代理", "xloc": [ - "default.handlebars->25->234" + "default.handlebars->27->218" ] }, { @@ -1708,12 +2264,31 @@ "en": "Add CIRA", "es": "Agregar CIRA", "fr": "Ajouter CIRA", + "hi": "CIRA जोड़ें", "ja": "CIRAを追加", + "ko": "CIRA 추가", "nl": "Toevoegen CIRA", "pt": "Adicionar CIRA", "ru": "Добавить CIRA", + "zh-chs": "添加CIRA", "xloc": [ - "default.handlebars->25->224" + "default.handlebars->27->208" + ] + }, + { + "cs": "Přidat zařízení", + "de": "Gerät hinzufügen", + "en": "Add Device", + "fr": "Ajouter un appareil", + "hi": "डिवाइस जोडे", + "ja": "デバイスを追加", + "ko": "기기 추가", + "nl": "Apparaat toevoegen", + "pt": "Adicionar Dispositivo", + "ru": "Добавить устройство", + "zh-chs": "添加設備", + "xloc": [ + "default.handlebars->27->1506" ] }, { @@ -1722,12 +2297,15 @@ "en": "Add Device Event", "es": "Agregar evento del dispositivo", "fr": "Ajouter un événement", + "hi": "डिवाइस इवेंट जोड़ें", "ja": "デバイスイベントを追加", + "ko": "장치 이벤트 추가", "nl": "Apparaatgebeurtenis toevoegen", "pt": "Adicionar evento do dispositivo", "ru": "Добавить событие к устройству", + "zh-chs": "添加設備事件", "xloc": [ - "default.handlebars->25->529" + "default.handlebars->27->576" ] }, { @@ -1736,16 +2314,32 @@ "en": "Add Device Group", "es": "Agregar grupo de dispositivos", "fr": "Ajouter un groupe", + "hi": "डिवाइस समूह जोड़ें", "ja": "デバイスグループを追加", + "ko": "장치 그룹 추가", "nl": "Apparaatgroep toevoegen", "pt": "Adicionar grupo de dispositivos", "ru": "Добавить группу устройств", + "zh-chs": "添加設備組", "xloc": [ - "default.handlebars->25->1109", - "default.handlebars->25->1111", - "default.handlebars->25->1293", - "default.handlebars->25->1367", - "default.handlebars->25->205" + "default.handlebars->27->1217", + "default.handlebars->27->1219", + "default.handlebars->27->1429", + "default.handlebars->27->1512", + "default.handlebars->27->189" + ] + }, + { + "cs": "Přidat oprávnění zařízení", + "de": "Geräteberechtigungen hinzufügen", + "en": "Add Device Permissions", + "fr": "Ajouter des autorisations de périphérique", + "ja": "デバイス権限を追加", + "nl": "Apparaatrechten toevoegen", + "ru": "Добавить разрешения для устройства", + "zh-chs": "添加设备权限", + "xloc": [ + "default.handlebars->27->1220" ] }, { @@ -1753,12 +2347,16 @@ "de": "Intel®-AMT-CIRA-Gerät hinzufügen", "en": "Add Intel® AMT CIRA device", "es": "Agregar Dispositivo con Intel AMT CIRA", + "fr": "Ajouter un appareil Intel® AMT CIRA", + "hi": "Intel® AMT CIRA डिवाइस जोड़ें", "ja": "Intel®を追加AMT CIRAデバイス", + "ko": "인텔 ® AMT CIRA 장치 추가", "nl": "Toevoegen Intel® AMT CIRA apparaat", "pt": "Adicione Intelreg; AMT", "ru": "Добавить Intel® AMT CIRA устройство", + "zh-chs": "添加英特爾®AMT CIRA設備", "xloc": [ - "default.handlebars->25->279" + "default.handlebars->27->264" ] }, { @@ -1766,12 +2364,16 @@ "de": "Intel®-AMT-Gerät hinzufügen", "en": "Add Intel® AMT device", "es": "Agregar Dispositivo con Intel AMT", + "fr": "Ajouter un nouvel ordinateur Intel® AMT", + "hi": "Intel® AMT डिवाइस जोड़ें", "ja": "Intel®を追加AMTデバイス", - "nl": "Add Intel® AMT apparaat", + "ko": "인텔 ® AMT 장치 추가", + "nl": "Toevoegen Intel® AMT apparaat", "pt": "Adicione Intelreg; dispositivo AMT", "ru": "Добавить Intel® AMT устройство", + "zh-chs": "添加英特爾®AMT設備", "xloc": [ - "default.handlebars->25->247" + "default.handlebars->27->231" ] }, { @@ -1779,12 +2381,16 @@ "de": "Schlüssel hinzufügen", "en": "Add Key", "es": "Agregar Llave", + "fr": "Ajouter une clé", + "hi": "कुंजी जोड़ें", "ja": "キーを追加", + "ko": "키 추가", "nl": "Sleutel toevoegen", "pt": "Adicionar chave", "ru": "Добавить ключ", + "zh-chs": "新增金鑰", "xloc": [ - "default.handlebars->25->143" + "default.handlebars->27->126" ] }, { @@ -1792,12 +2398,16 @@ "de": "Lokales Gerät hinzufügen", "en": "Add Local", "es": "Agregar Local", + "fr": "Ajouter local", + "hi": "स्थानीय जोड़ें", "ja": "ローカルを追加", + "ko": "로컬 추가", "nl": "Lokaal toevoegen", "pt": "Adicionar local", "ru": "Добавить локально", + "zh-chs": "添加本地", "xloc": [ - "default.handlebars->25->226" + "default.handlebars->27->210" ] }, { @@ -1805,10 +2415,16 @@ "de": "Mitgliedschaft hinzufügen", "en": "Add Membership", "es": "Agregar Miembros", + "fr": "Ajouter un membre", + "hi": "सदस्यता जोड़ें", + "ja": "メンバーシップを追加", + "ko": "멤버십 추가", "nl": "Lidmaatschap toevoegen", + "pt": "Adicionar associação", "ru": "Добавить участие", + "zh-chs": "添加會員", "xloc": [ - "default.handlebars->25->1386" + "default.handlebars->27->1532" ] }, { @@ -1816,12 +2432,16 @@ "de": "Mesh Agent hinzufügen", "en": "Add Mesh Agent", "es": "Agregar Agente Mesh", + "fr": "Ajouter un agent", + "hi": "मेष एजेंट जोड़ें", "ja": "メッシュエージェントを追加", + "ko": "메시 에이전트 추가", "nl": "Toevoegen Mesh agent", "pt": "Adicionar agente de malha", "ru": "Добавить Mesh Agent", + "zh-chs": "添加網格代理", "xloc": [ - "default.handlebars->25->346" + "default.handlebars->27->336" ] }, { @@ -1830,17 +2450,51 @@ "en": "Add Security Key", "es": "Agregar Llave de Seguridad", "fr": "Ajouter une clé de sécurité", + "hi": "सुरक्षा कुंजी जोड़ें", "ja": "セキュリティキーを追加", + "ko": "보안 키 추가", "nl": "Beveiligingssleutel toevoegen", "pt": "Adicionar chave de segurança", "ru": "Добавить ключ безопасности", + "zh-chs": "添加安全密鑰", "xloc": [ - "default.handlebars->25->146", - "default.handlebars->25->148", - "default.handlebars->25->151", - "default.handlebars->25->152", - "default.handlebars->25->719", - "default.handlebars->25->720" + "default.handlebars->27->129", + "default.handlebars->27->131", + "default.handlebars->27->134", + "default.handlebars->27->135", + "default.handlebars->27->823", + "default.handlebars->27->824" + ] + }, + { + "cs": "Přidat uživatele", + "de": "Benutzer hinzufügen", + "en": "Add User", + "es": "Agregar Usuario", + "fr": "Ajouter un utilisateur", + "hi": "उपयोगकर्ता जोड़ें", + "ja": "ユーザーを追加する", + "ko": "사용자 추가", + "nl": "Gebruiker toevoegen", + "pt": "Adicionar usuário", + "ru": "Добавить пользователя", + "zh-chs": "添加用戶", + "xloc": [ + "default-mobile.handlebars->9->284", + "default.handlebars->27->536" + ] + }, + { + "cs": "Přidat oprávnění uživatelského zařízení", + "de": "Hinzufügen von Benutzergeräteberechtigungen", + "en": "Add User Device Permissions", + "fr": "Ajouter des autorisations de périphérique utilisateur", + "ja": "ユーザーデバイスの権限を追加する", + "nl": "Gebruikersmachtigingen voor apparaat toevoegen", + "ru": "Добавить разрешения для пользовательских устройств", + "zh-chs": "添加用户设备权限", + "xloc": [ + "default.handlebars->27->1223" ] }, { @@ -1848,12 +2502,18 @@ "de": "Benutzergruppe hinzufügen", "en": "Add User Group", "es": "Agregar Grupos de Usuarios", + "fr": "Ajouter un groupe utilisateurs", + "hi": "उपयोगकर्ता समूह जोड़ें", + "ja": "ユーザーグループを追加", + "ko": "사용자 그룹 추가", "nl": "Gebruikersgroep toevoegen", + "pt": "Adicionar grupo de usuários", "ru": "Добавить группу пользователей", + "zh-chs": "添加用戶組", "xloc": [ - "default.handlebars->25->1016", - "default.handlebars->25->1110", - "default.handlebars->25->1376" + "default.handlebars->27->1123", + "default.handlebars->27->1218", + "default.handlebars->27->1518" ] }, { @@ -1862,12 +2522,15 @@ "en": "Add User to Mesh", "es": "Agregar Usuario al Mesh", "fr": "Ajouter un utilisateur au groupe", + "hi": "उपयोगकर्ता को मेष में जोड़ें", "ja": "メッシュにユーザーを追加", + "ko": "메시에 사용자 추가", "nl": "Gebruiker toevoegen aan Mesh", "pt": "Adicionar usuário à malha", "ru": "Добавить пользователя в Mesh", + "zh-chs": "將用戶添加到網格", "xloc": [ - "default-mobile.handlebars->9->309" + "default-mobile.handlebars->9->313" ] }, { @@ -1876,13 +2539,16 @@ "en": "Add Users", "es": "Agregar Usuarios", "fr": "Ajouter des utilisateurs", + "hi": "उपयोगकर्ता जोड़ें", "ja": "ユーザーを追加", + "ko": "사용자 추가", "nl": "Gebruikers toevoegen", "pt": "Adicionar usuários", "ru": "Добавить пользователей", + "zh-chs": "添加用戶", "xloc": [ - "default.handlebars->25->1015", - "default.handlebars->25->1288" + "default.handlebars->27->1122", + "default.handlebars->27->1424" ] }, { @@ -1890,12 +2556,16 @@ "de": "Benutzer zu Gerätegruppe hinzufügen", "en": "Add Users to Device Group", "es": "Agregar Usuarios al Grupo de Dispositivos", + "fr": "Ajouter des utilisateurs au groupe d'appareils", + "hi": "डिवाइस समूह में उपयोगकर्ता जोड़ें", "ja": "ユーザーをデバイスグループに追加する", + "ko": "장치 그룹에 사용자 추가", "nl": "Gebruikers toevoegen aan apparaatgroep", "pt": "Adicionar usuários ao grupo de dispositivos", "ru": "Добавить пользователей в группу устройств", + "zh-chs": "將用戶添加到設備組", "xloc": [ - "default.handlebars->25->1108" + "default.handlebars->27->1216" ] }, { @@ -1903,10 +2573,16 @@ "de": "Benutzer zu Benutzergruppe hinzufügen", "en": "Add Users to User Group", "es": "Agregar Usuarios a un Grupo", + "fr": "Ajouter des utilisateurs au groupe", + "hi": "उपयोगकर्ता समूह में उपयोगकर्ता जोड़ें", + "ja": "ユーザーをユーザーグループに追加", + "ko": "사용자 그룹에 사용자 추가", "nl": "Voeg gebruikers toe aan de gebruikersgroep", + "pt": "Adicionar usuários ao grupo de usuários", "ru": "Добавить пользователей в группу", + "zh-chs": "將用戶添加到用戶組", "xloc": [ - "default.handlebars->25->1316" + "default.handlebars->27->1449" ] }, { @@ -1914,12 +2590,16 @@ "de": "YubiKey® OTP hinzufügen", "en": "Add YubiKey® OTP", "es": "Agregar YubiKey OTP", + "fr": "Ajouter une clé YubiKey® OTP", + "hi": "YubiKey® OTP जोड़ें", "ja": "YubiKey®を追加OTP", + "ko": "YubiKey® OTP 추가", "nl": "Voeg YubiKey® OTP toe", "pt": "Adicione YubiKeyreg; OTP", "ru": "Добавить YubiKey® OTP", + "zh-chs": "添加YubiKey®OTP", "xloc": [ - "default.handlebars->25->144" + "default.handlebars->27->127" ] }, { @@ -1927,12 +2607,16 @@ "de": "Füge einen neuen Intel®-AMT-Rechner durch Scannen des lokalen Netzwerks hinzu.", "en": "Add a new Intel® AMT computer by scanning the local network.", "es": "Agregue una nueva computadora Intel AMT escaneando la red Local.", + "fr": "Ajouter un nouvel ordinateur Intel® AMT en scannant le réseau local.", + "hi": "स्थानीय नेटवर्क को स्कैन करके एक नया Intel® AMT कंप्यूटर जोड़ें।", "ja": "新しいIntel®を追加しますローカルネットワークをスキャンしてAMTコンピューター。", + "ko": "로컬 네트워크를 스캔하여 새 인텔 ® AMT 컴퓨터를 추가하십시오.", "nl": "Voeg een nieuwe Intel® AMT computer toe door het lokale netwerk te scannen.", "pt": "Adicione um novo Intelreg; Computador AMT digitalizando a rede local.", "ru": "Добавить новый Intel® AMT компьютер сканированием локальной сети.", + "zh-chs": "通過掃描本地網絡添加新的英特爾®AMT計算機。", "xloc": [ - "default.handlebars->25->227" + "default.handlebars->27->211" ] }, { @@ -1940,13 +2624,17 @@ "de": "Füge einen neuen Intel®-AMT-Rechner hinzu, der sich im Internet befindet.", "en": "Add a new Intel® AMT computer that is located on the internet.", "es": "Agregue una nueva computadora Intel AMT localizada en el internet", + "fr": "Ajouter un nouvel ordinateur Intel® AMT connecté à internet.", + "hi": "एक नया Intel® AMT कंप्यूटर जोड़ें जो इंटरनेट पर स्थित है।", "ja": "新しいIntel®を追加しますインターネット上にあるAMTコンピューター。", + "ko": "인터넷에있는 새 인텔 ® AMT 컴퓨터를 추가하십시오.", "nl": "Voeg een nieuwe Intel® AMT computer toe welke zich op het internet bevind.", "pt": "Adicione um novo Intel® Computador AMT localizado na Internet.", "ru": "Добавить новый Intel® AMT компьютер, находящийся в интернете.", + "zh-chs": "添加位於互聯網上的新英特爾®AMT計算機。", "xloc": [ - "default.handlebars->25->1017", - "default.handlebars->25->223" + "default.handlebars->27->1124", + "default.handlebars->27->207" ] }, { @@ -1954,13 +2642,17 @@ "de": "Füge einen neuen Intel®-AMT-Rechner hinzu, der sich im lokalen Netzwerk befindet.", "en": "Add a new Intel® AMT computer that is located on the local network.", "es": "Agregue una nueva computadora Intel AMT localizada en la red Local.", + "fr": "Ajouter un nouvel ordinateur Intel® AMT du réseau local.", + "hi": "एक नया Intel® AMT कंप्यूटर जोड़ें जो स्थानीय नेटवर्क पर स्थित है।", "ja": "新しいIntel®を追加しますローカルネットワーク上にあるAMTコンピューター。", + "ko": "로컬 네트워크에있는 새 인텔 ® AMT 컴퓨터를 추가하십시오.", "nl": "Voeg een nieuwe Intel® AMT computer toe welke zich op het lokale netwerk bevind.", "pt": "Adicione um novo Intel® AMT computer that is located on the local network.", "ru": "Добавить новый Intel® AMT компьютер, находящийся в локальной сети.", + "zh-chs": "添加位於本地網絡上的新英特爾®AMT計算機。", "xloc": [ - "default.handlebars->25->1019", - "default.handlebars->25->225" + "default.handlebars->27->1126", + "default.handlebars->27->209" ] }, { @@ -1968,12 +2660,16 @@ "de": "Füge ein neues Intel®-AMT-Gerät zur Gerätegruppe \\\"{0}\\\" hinzu.", "en": "Add a new Intel® AMT device to device group \\\"{0}\\\".", "es": "Agregue un nuevo dispositivo AMT al grupo de dispositivos.", + "fr": "Ajouter un appareil Intel® AM au groupe d'appareils \\\"{0}\\\".", + "hi": "उपकरण समूह \\\"{0} \\\" में एक नया Intel® AMT उपकरण जोड़ें।", "ja": "新しいIntel®を追加しますAMTデバイスからデバイスグループ\\\"{0}\\\"へ。", + "ko": "장치 그룹 \\\"{0} \\\"에 새 Intel® AMT 장치를 추가하십시오.", "nl": "Voeg een nieuwe Intel® AMT computer toe aan een apparaatgroep \\\"{0}\\\".", "pt": "Adicione um novo Intel® Dispositivo AMT para grupo de dispositivos \\\"{0}\\\".", "ru": "Добавить новое Intel® AMT устройство к группе устройств \\\"{0}\\\".", + "zh-chs": "將新的英特爾®AMT設備添加到設備組“{0}”。", "xloc": [ - "default.handlebars->25->237" + "default.handlebars->27->221" ] }, { @@ -1981,13 +2677,17 @@ "de": "Füge einen neuen Rechner durch Installation des Mesh-Agenten zu diesem Mesh hinzu.", "en": "Add a new computer to this mesh by installing the mesh agent.", "es": "Agregue una nueva computadora al MESH instalando el agente.", + "fr": "Ajouter un nouvel ordinateur à ce groupe en installant l'agent", + "hi": "मेष एजेंट स्थापित करके इस मेष में एक नया कंप्यूटर जोड़ें।", "ja": "メッシュエージェントをインストールして、このメッシュに新しいコンピューターを追加します。", + "ko": "메시 에이전트를 설치하여이 메시에 새 컴퓨터를 추가하십시오.", "nl": "Voeg een nieuwe computer toe aan deze mesh door de mesh-agent te installeren.", "pt": "Adicione um novo computador a essa malha instalando o agente de malha.", "ru": "Добавить новый компьютер к этой сети установкой Mesh Agent.", + "zh-chs": "通過安裝網格代理將新計算機添加到該網格。", "xloc": [ - "default.handlebars->25->1025", - "default.handlebars->25->233" + "default.handlebars->27->1132", + "default.handlebars->27->217" ] }, { @@ -1995,12 +2695,16 @@ "de": "Adresse", "en": "Address", "es": "Dirección", + "fr": "Adresse", + "hi": "पता", "ja": "住所", + "ko": "주소", "nl": "Adres", "pt": "Endereço", "ru": "Адрес", + "zh-chs": "地址", "xloc": [ - "default.handlebars->25->201" + "default.handlebars->27->185" ] }, { @@ -2008,22 +2712,64 @@ "de": "Adressen", "en": "Addresses", "es": "Direcciónes", + "fr": "Adresses", + "hi": "पतों", "ja": "住所", + "ko": "구애", "nl": "Adressen", "pt": "Endereços", "ru": "Адреса", + "zh-chs": "地址", "xloc": [ "player.handlebars->3->7" ] }, + { + "cs": "Admin Control Mode (ACM)", + "de": "Admin Control Mode (ACM)", + "en": "Admin Control Mode (ACM)", + "es": "Admin Control Mode (ACM)", + "fr": "Admin Control Mode (ACM)", + "hi": "व्यवस्थापक नियंत्रण मोड (ACM)", + "ja": "管理制御モード(ACM)", + "ko": "관리 제어 모드 (ACM)", + "nl": "Admin Control Mode (ACM)", + "pt": "Admin Control Mode (ACM)", + "ru": "Режим управления администратора (ACM)", + "zh-chs": "管理員控制模式(ACM)", + "xloc": [ + "default.handlebars->27->768" + ] + }, + { + "cs": "Pověření správce", + "de": "Administrator-Anmeldeinformationen", + "en": "Admin Credentials", + "fr": "Informations d'identification d'administrateur", + "hi": "व्यवस्थापक क्रेडेंशियल", + "ja": "管理者の資格情報", + "ko": "관리자 자격 증명", + "nl": "Beheerdersreferenties", + "pt": "Credenciais de administrador", + "ru": "Учетные данные администратора", + "zh-chs": "管理員憑證", + "xloc": [ + "default.handlebars->27->774" + ] + }, { "cs": "PowerShell správce", "de": "Admin-PowerShell", "en": "Admin PowerShell", "es": "Administrar Powershell", + "fr": "Powershell administateur", + "hi": "व्यवस्थापक PowerShell", "ja": "管理者PowerShell", + "ko": "관리 PowerShell", "nl": "Beheerder PowerShell", + "pt": "Admin PowerShell", "ru": "Admin PowerShell", + "zh-chs": "管理員PowerShell", "xloc": [ "default.handlebars->termShellContextMenu->cxtermps", "xterm.handlebars->termShellContextMenu->cxtermps" @@ -2034,12 +2780,16 @@ "de": "Admin-Bereiche", "en": "Admin Realms", "es": "Admin Realms", + "fr": "Domaines d'administration", + "hi": "प्रशासन के दायरे", "ja": "管理レルム", + "ko": "관리자 영역", "nl": "Beheerdersgebied", "pt": "Admin Realms", "ru": "Области администратора", + "zh-chs": "管理領域", "xloc": [ - "default.handlebars->25->1342" + "default.handlebars->27->1476" ] }, { @@ -2047,9 +2797,14 @@ "de": "Admin-Shell", "en": "Admin Shell", "es": "Administrar Shell", + "fr": "Console administrateur", + "hi": "व्यवस्थापक शेल", "ja": "管理シェル", + "ko": "관리 셸", "nl": "Beheerder Shell", + "pt": "Shell de administração", "ru": "Admin Shell", + "zh-chs": "管理員外殼", "xloc": [ "default.handlebars->termShellContextMenu->cxtermnorm->0", "xterm.handlebars->termShellContextMenu->cxtermnorm->0" @@ -2060,12 +2815,16 @@ "de": "Administrative Bereiche", "en": "Administrative Realms", "es": "Administrative Realms", + "fr": "Domaines administratifs", + "hi": "प्रशासनिक क्षेत्र", "ja": "管理レルム", + "ko": "관리 영역", "nl": "Administratieve gebieden", "pt": "Domínios Administrativos", "ru": "Административные области", + "zh-chs": "行政領域", "xloc": [ - "default.handlebars->25->1258" + "default.handlebars->27->1393" ] }, { @@ -2073,12 +2832,16 @@ "de": "Administrator", "en": "Administrator", "es": "Administrator", + "fr": "Administrateur", + "hi": "प्रशासक", "ja": "管理者", + "ko": "관리자", "nl": "Beheerder", "pt": "Administrador", "ru": "Администратор", + "zh-chs": "管理員", "xloc": [ - "default.handlebars->25->1220" + "default.handlebars->27->1350" ] }, { @@ -2086,12 +2849,16 @@ "de": "Afrikaans", "en": "Afrikaans", "es": "Africanos", + "fr": "afrikaans", + "hi": "अफ्रीकी", "ja": "アフリカーンス語", + "ko": "아프리카 어", "nl": "Afrikaans", "pt": "afrikaans", "ru": "Африканский", + "zh-chs": "南非語", "xloc": [ - "default.handlebars->25->722" + "default.handlebars->27->826" ] }, { @@ -2100,18 +2867,21 @@ "en": "Agent", "es": "Agente", "fr": "Agent", + "hi": "एजेंट", "ja": "エージェント", + "ko": "에이전트", "nl": "Agent", "pt": "Agente", "ru": "Агент", + "zh-chs": "代理人", "xloc": [ - "default-mobile.handlebars->9->121", - "default-mobile.handlebars->9->174", - "default-mobile.handlebars->9->190", - "default.handlebars->25->1145", - "default.handlebars->25->1151", - "default.handlebars->25->184", - "default.handlebars->25->371", + "default-mobile.handlebars->9->125", + "default-mobile.handlebars->9->178", + "default-mobile.handlebars->9->194", + "default.handlebars->27->1273", + "default.handlebars->27->1279", + "default.handlebars->27->168", + "default.handlebars->27->361", "default.handlebars->container->column_l->p15->consoleTable->1->6->1->1->1->0->p15outputselecttd->p15outputselect->1" ] }, @@ -2120,11 +2890,17 @@ "de": "Agent + Intel AMT", "en": "Agent + Intel AMT", "es": "Agente + Intel AMT", + "fr": "Agent + Intel AMT", + "hi": "एजेंट + इंटेल एएमटी", + "ja": "エージェント+ Intel AMT", + "ko": "에이전트 + 인텔 AMT", "nl": "Agent + Intel AMT", + "pt": "Agente + Intel AMT", "ru": "Агент + Intel AMT", + "zh-chs": "代理+英特爾AMT", "xloc": [ - "default.handlebars->25->1147", - "default.handlebars->25->1153" + "default.handlebars->27->1275", + "default.handlebars->27->1281" ] }, { @@ -2132,10 +2908,14 @@ "de": "Agent-Aktion", "en": "Agent Action", "es": "Acción del agente", + "fr": "Action de l'agent", + "hi": "एजेंट कार्रवाई", "ja": "エージェントアクション", + "ko": "에이전트 작업", "nl": "Agent actie", "pt": "Ação do agente", "ru": "Управление агентом", + "zh-chs": "代理人行動", "xloc": [ "default.handlebars->container->column_l->p15->consoleTable->1->0->1->1" ] @@ -2145,13 +2925,17 @@ "de": "Agent-Konsole", "en": "Agent Console", "es": "Consola de Agente", + "fr": "Console d'agent", + "hi": "एजेंट कंसोल", "ja": "エージェントコンソール", + "ko": "에이전트 콘솔", "nl": "Agent console", "pt": "Console do agente", "ru": "Консоль агента", + "zh-chs": "代理控制台", "xloc": [ - "default-mobile.handlebars->9->315", - "default.handlebars->25->1119" + "default-mobile.handlebars->9->319", + "default.handlebars->27->1231" ] }, { @@ -2159,15 +2943,30 @@ "de": "Agent-Fehlerzähler", "en": "Agent Error Counters", "es": "Contador de errores del Agente", + "fr": "Compteurs d'erreurs d'agent", + "hi": "एजेंट त्रुटि काउंटर", + "ja": "エージェントエラーカウンター", + "ko": "에이전트 오류 카운터", "nl": "Agent fout tellers", + "pt": "Contadores de erros do agente", "ru": "Счетчик ошибок агента", + "zh-chs": "座席錯誤計數器", "xloc": [ - "default.handlebars->25->1398" + "default.handlebars->27->1545" ] }, { + "cs": "Instalace agenta", + "de": "Agenteninstallation", "en": "Agent Installation", + "fr": "Installation de l'agent", + "hi": "एजेंट स्थापना", + "ja": "エージェントのインストール", + "ko": "에이전트 설치", + "nl": "Agent Installatie", + "pt": "Instalação do agente", "ru": "Установка агента", + "zh-chs": "代理安裝", "xloc": [ "agentinvite.handlebars->3->3" ] @@ -2177,12 +2976,16 @@ "de": "Agent-Weiterleitung", "en": "Agent Relay", "es": "Agente Relay", + "fr": "Relais d'agent", + "hi": "एजेंट रिले", "ja": "エージェントリレー", + "ko": "에이전트 릴레이", "nl": "Agent Relay", "pt": "Retransmissão do agente", "ru": "Ретранслятор агента", + "zh-chs": "代理中繼", "xloc": [ - "default-mobile.handlebars->9->193" + "default-mobile.handlebars->9->197" ] }, { @@ -2190,10 +2993,14 @@ "de": "Entfernter Desktop via Agent", "en": "Agent Remote Desktop", "es": "Escritorio Remoto del Agente", + "fr": "Bureau distant - Configuration de l'agent", + "hi": "एजेंट दूरस्थ डेस्कटॉप", "ja": "エージェントリモートデスクトップ", + "ko": "에이전트 원격 데스크톱", "nl": "Agent Extern bureaublad", "pt": "Área de trabalho remota do agente", "ru": "Агент удаленного рабочего стола", + "zh-chs": "代理遠程桌面", "xloc": [ "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->1", "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->1" @@ -2204,10 +3011,16 @@ "de": "Agent-Sitzungen", "en": "Agent Sessions", "es": "Sesiones del Agente", + "fr": "Nombre d'agents connectés", + "hi": "एजेंट सत्र", + "ja": "エージェントセッション", + "ko": "에이전트 세션", "nl": "Agent Sessies", + "pt": "Sessões do agente", "ru": "Сессии агентов", + "zh-chs": "座席會議", "xloc": [ - "default.handlebars->25->1414" + "default.handlebars->27->1561" ] }, { @@ -2215,13 +3028,17 @@ "de": "Agent-Markierung", "en": "Agent Tag", "es": "Etiqueta del Agente", + "fr": "Tag d'agent", + "hi": "एजेंट टैग", "ja": "エージェントタグ", + "ko": "에이전트 태그", "nl": "Agent Tag", "pt": "Etiqueta do agente", "ru": "Тег агента", + "zh-chs": "代理商標籤", "xloc": [ - "default-mobile.handlebars->9->189", - "default.handlebars->25->474" + "default-mobile.handlebars->9->193", + "default.handlebars->27->481" ] }, { @@ -2229,10 +3046,16 @@ "de": "Agent-Typen", "en": "Agent Types", "es": "Tipos de Agente", + "fr": "Types d'agents", + "hi": "एजेंट प्रकार", + "ja": "エージェントの種類", + "ko": "에이전트 유형", "nl": "Agent Type", + "pt": "Tipos de agentes", "ru": "Типы агента", + "zh-chs": "代理類型", "xloc": [ - "default.handlebars->25->1149", + "default.handlebars->27->1277", "default.handlebars->container->column_l->p21->3->1->meshOsChartDiv->1" ] }, @@ -2241,14 +3064,18 @@ "de": "Agent verbunden", "en": "Agent connected", "es": "Agente Conectado", + "fr": "Agent connecté", + "hi": "एजेंट जुड़ा हुआ है", "ja": "接続されたエージェント", + "ko": "에이전트 연결", "nl": "Agent verbonden", "pt": "Agente conectado", "ru": "Агент подключен", + "zh-chs": "代理已連接", "xloc": [ - "default.handlebars->25->154", - "default.handlebars->25->520", - "default.handlebars->25->521" + "default.handlebars->27->137", + "default.handlebars->27->527", + "default.handlebars->27->528" ] }, { @@ -2256,12 +3083,16 @@ "de": "Agent getrennt", "en": "Agent disconnected", "es": "Agente Desconectado", + "fr": "Agent déconnecté", + "hi": "एजेंट ने काट दिया", "ja": "エージェントが切断されました", + "ko": "에이전트 연결이 끊어졌습니다", "nl": "Agent niet verbonden", "pt": "Agente desconectado", "ru": "Агент отключился", + "zh-chs": "代理已斷開連接", "xloc": [ - "default.handlebars->25->158" + "default.handlebars->27->141" ] }, { @@ -2269,12 +3100,16 @@ "de": "Agent ist offline", "en": "Agent is offline", "es": "Agente desconectado", + "fr": "Agent déconnecté", + "hi": "एजेंट ऑफ़लाइन है", "ja": "エージェントはオフラインです", + "ko": "에이전트가 오프라인입니다", "nl": "Agent is offline", "pt": "O agente está offline", "ru": "Агент оффлайн", + "zh-chs": "代理離線", "xloc": [ - "default.handlebars->25->693" + "default.handlebars->27->794" ] }, { @@ -2282,12 +3117,16 @@ "de": "Agent ist online", "en": "Agent is online", "es": "Agente Conectado", + "fr": "Agent connecté", + "hi": "एजेंट ऑनलाइन है", "ja": "エージェントはオンラインです", + "ko": "에이전트가 온라인입니다", "nl": "Agent is online", "pt": "Agente está online", "ru": "Агент онлайн", + "zh-chs": "代理在線", "xloc": [ - "default.handlebars->25->692" + "default.handlebars->27->793" ] }, { @@ -2295,12 +3134,16 @@ "de": "Agenten", "en": "Agents", "es": "Agentes", + "fr": "Agents", + "hi": "एजेंटों", "ja": "エージェント", + "ko": "자치령 대표", "nl": "Agents", "pt": "Agentes", "ru": "Агенты", + "zh-chs": "代理商", "xloc": [ - "default.handlebars->25->1427" + "default.handlebars->27->1574" ] }, { @@ -2308,12 +3151,16 @@ "de": "Albanian", "en": "Albanian", "es": "Albanesa", + "fr": "albanais", + "hi": "अल्बानियन", "ja": "アルバニア語", + "ko": "알바니아", "nl": "Albanees", "pt": "albanês", "ru": "Албанский", + "zh-chs": "阿爾巴尼亞語", "xloc": [ - "default.handlebars->25->723" + "default.handlebars->27->827" ] }, { @@ -2322,14 +3169,17 @@ "en": "All", "es": "Todos", "fr": "Tout", + "hi": "सब", "ja": "すべて", - "nl": "alles", + "ko": "모두", + "nl": "Alles", "pt": "Todos", "ru": "Все", + "zh-chs": "所有", "xloc": [ - "default-mobile.handlebars->9->244", - "default-mobile.handlebars->9->246", - "default-mobile.handlebars->9->76" + "default-mobile.handlebars->9->248", + "default-mobile.handlebars->9->250", + "default-mobile.handlebars->9->79" ] }, { @@ -2337,12 +3187,16 @@ "de": "Alle Bildschirme", "en": "All Displays", "es": "Todos los Displays", + "fr": "Tous affichages", + "hi": "सभी प्रदर्शित करता है", "ja": "すべてのディスプレイ", - "nl": "alle schermen", + "ko": "모든 디스플레이", + "nl": "Alle schermen", "pt": "Todas as telas", "ru": "Все экраны", + "zh-chs": "所有顯示", "xloc": [ - "default-mobile.handlebars->9->233" + "default-mobile.handlebars->9->237" ] }, { @@ -2350,14 +3204,18 @@ "de": "Alles fokussieren", "en": "All Focus", "es": "All Focus", + "fr": "Tout se concentrer", + "hi": "ऑल फोकस", "ja": "オールフォーカス", + "ko": "모든 초점", "nl": "All Focus", "pt": "All Focus", "ru": "Фокусирование всех", + "zh-chs": "全部聚焦", "xloc": [ - "default.handlebars->25->608", - "default.handlebars->25->610", - "default.handlebars->25->611" + "default.handlebars->27->656", + "default.handlebars->27->658", + "default.handlebars->27->659" ] }, { @@ -2366,13 +3224,29 @@ "en": "Allow users to manage this device group and devices in this group.", "es": "Permitir a los Usuarios Administrar este grupo de dispositivos y Dispositivos en este grupo.", "fr": "Autoriser les utilisateurs à gérer ce groupe et les périphériques de ce groupe.", + "hi": "उपयोगकर्ताओं को इस समूह में इस उपकरण समूह और उपकरणों को प्रबंधित करने की अनुमति दें।", "ja": "ユーザーがこのデバイスグループとこのグループ内のデバイスを管理できるようにします。", + "ko": "사용자가이 장치 그룹과이 그룹의 장치를 관리 할 수 ​​있도록합니다.", "nl": "Gebruikers toestaan deze apparaatgroep en apparaten in deze groep te beheren.", "pt": "Permitir que os usuários gerenciem esse grupo de dispositivos e dispositivos neste grupo.", "ru": "Разрешить пользователям управлять этой группой и устройствами этой группы.", + "zh-chs": "允許用戶管理此設備組和該組中的設備。", "xloc": [ - "default.handlebars->25->1083", - "default.handlebars->25->1313" + "default.handlebars->27->1187", + "default.handlebars->27->1446" + ] + }, + { + "cs": "Povolit uživatelům spravovat toto zařízení.", + "de": "Ermöglichen Sie Benutzern die Verwaltung dieses Geräts.", + "en": "Allow users to manage this device.", + "fr": "Autorisez les utilisateurs à gérer cet appareil.", + "ja": "ユーザーにこのデバイスの管理を許可します。", + "nl": "Sta gebruikers toe om dit apparaat te beheren.", + "ru": "Разрешить пользователям управлять этим устройством.", + "zh-chs": "允许用户管理此设备。", + "xloc": [ + "default.handlebars->27->1188" ] }, { @@ -2380,10 +3254,14 @@ "de": "Alt+F4", "en": "Alt-F4", "es": "Alt+F4", + "fr": "Alt-F4", + "hi": "Alt-F4", "ja": "Alt-F4", + "ko": "Alt-F4", "nl": "Alt-F4", "pt": "Alt-F4", "ru": "Alt-F4", + "zh-chs": "Alt-F4", "xloc": [ "default-mobile.handlebars->dialog->3->dialog3->deskkeys->19", "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->deskkeys->17" @@ -2394,10 +3272,14 @@ "de": "Alt+Tab", "en": "Alt-Tab", "es": "Alt+Tab", + "fr": "Alt-Tab", + "hi": "Alt-टैब", "ja": "Alt-Tab", + "ko": "Alt-Tab", "nl": "Alt-Tab", "pt": "Alt-Tab", "ru": "Alt-Tab", + "zh-chs": "Alt-Tab", "xloc": [ "default-mobile.handlebars->dialog->3->dialog3->deskkeys->23", "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->deskkeys->21" @@ -2408,18 +3290,30 @@ "de": "Alternativ (F10 = ESC+0)", "en": "Alternate (F10 = ESC+0)", "es": "Alternativo (F10 = ESC + 0)", + "fr": "Alternative (F10 = ESC+0)", + "hi": "वैकल्पिक (F10 = ESC + 0)", "ja": "代替(F10 = ESC + 0)", + "ko": "대체 (F10 = ESC + 0)", "nl": "Alternatief (F10 = ESC + 0)", "pt": "Alternativo (F10 = ESC + 0)", "ru": "Поменять (F10 = ESC+0)", + "zh-chs": "備用(F10 = ESC + 0)", "xloc": [ - "default.handlebars->25->642" + "default.handlebars->27->691" ] }, { + "cs": "Alternativní port", + "de": "Alternativer Port", "en": "Alternate Port", + "fr": "Port alternatif", + "hi": "वैकल्पिक पोर्ट", + "ja": "代替ポート", + "ko": "대체 포트", "nl": "Alternatieve poort", + "pt": "Porta alternativa", "ru": "Поменять порт", + "zh-chs": "備用端口", "xloc": [ "default.handlebars->altPortContextMenu->cxaltport->0" ] @@ -2430,12 +3324,15 @@ "en": "Always Notify", "es": "Notificar Siempre", "fr": "Toujours aviser", + "hi": "हमेशा सुचित करें", "ja": "常に通知する", + "ko": "항상 알림", "nl": "Altijd informeren", "pt": "Notificar sempre", "ru": "Всегда уведомлять", + "zh-chs": "始終通知", "xloc": [ - "default.handlebars->25->998" + "default.handlebars->27->1103" ] }, { @@ -2443,26 +3340,64 @@ "de": "Immer nachfragen", "en": "Always Prompt", "es": "Simepre Preguntar", + "fr": "Toujours demander", + "hi": "हमेशा शीघ्र", "ja": "常にプロンプ​​ト", + "ko": "항상 프롬프트", "nl": "Altijd prompt", "pt": "Sempre alerta", "ru": "Всегда запрашивать", + "zh-chs": "總是提示", "xloc": [ - "default.handlebars->25->999" + "default.handlebars->27->1104" ] }, + { + "cs": "Účet byl pro vás vytvořen na serveru", + "de": "Auf dem Server wurde ein Konto für Sie erstellt", + "en": "An account was created for you on server", + "fr": "Un compte a été créé pour vous sur le serveur", + "nl": "Er is een account voor je aangemaakt op de server", + "ja": "サーバー上にアカウントが作成されました", + "ru": "Учетная запись была создана для вас на сервере", + "zh-chs": "在服务器上为您创建了一个帐户", + "xloc": [ + "account-invite.html->2->3" + ] + }, + { + "en": "An account was created for you on server [[[SERVERNAME]]] ([[[SERVERURL]]]/), you can access it now with username \"[[[ACCOUNTNAME]]]\" and password \"[[[PASSWORD]]]\".", + "nl": "Er is een account jouw aangemaakt op de server [[[SERVERNAME]]] ([[[SERVERURL]]]/), Je kan inloggen met de gebruikersnaam \"[[[ACCOUNTNAME]]]\" en wachtwoord \"[[[PASSWORD]]]\".", + "xloc": [ + "account-invite.txt" + ] + }, + { + "cs": "Účet byl pro vás vytvořen na serveru [[[SERVERNAME]]] ([[[SERVERURL]]]/), nyní k němu máte přístup pomocí uživatelského jména \\\"[[[ACCOUNTNAME]]]\\\" a hesla \\\"[[[PASSWORD]]]\\\".", + "de": "Auf dem Server [[[SERVERNAME]]] ([[[SERVERURL]]]/) wurde ein Konto für Sie erstellt. Sie können jetzt mit dem Benutzernamen \\\"[[[ACCOUNTNAME]]]\\\" und dem Passwort \\\"[[[PASSWORD]]]\\\".", + "en": "An account was created for you on server [[[SERVERNAME]]] ([[[SERVERURL]]]/), you can access it now with username \\\"[[[ACCOUNTNAME]]]\\\" en wachtwoord \\\"[[[PASSWORD]]]\\\".", + "nl": "Er is een account jouw aangemaakt op de server [[[SERVERNAME]]] ([[[SERVERURL]]]/), Je kan inloggen met de gebruikersnaam \\\"[[[ACCOUNTNAME]]]\\\" and password \\\"[[[PASSWORD]]]\\\".", + "fr": "Un compte a été créé pour vous sur le serveur [[[SERVERNAME]]] ([[[SERVERURL]]]/), vous pouvez y accéder maintenant avec le nom d'utilisateur \\\"[[[ACCOUNTNAME]]]\\\" et le mot de passe \\\"[[[PASSWORD]]]\\\".", + "ja": "サーバー[[[SERVERNAME]]]([[[SERVERURL]]]/)にアカウントが作成されました。ユーザー名 \\\"[[[ACCOUNTNAME]]]\\\" とパスワード \\\"[[[PASSWORD]]]\\\"。", + "ru": "Для вас была создана учетная запись на сервере [[[SERVERNAME]]] ([[[SERVERURL]]]/), теперь вы можете получить к ней доступ с помощью имени пользователя \\\"[[[ACCOUNTNAME]]]\\\" и пароля \\\"[[[PASSWORD]]]\\\".", + "zh-chs": "已在服务器[[[SERVERNAME]]]([[[SERVERURL]]]/ 上为您创建了一个帐户,您现在可以使用用户名\\“ [[[ACCOUNTNAME]]] 和密码 \\\"[[[PASSWORD]]]\\\"。" + }, { "cs": "Android APK", "de": "Android-APK", "en": "Android APK", "es": "Android APK", + "fr": "Android APK", + "hi": "Android APK", "ja": "Android APK", + "ko": "안드로이드 APK", "nl": "Android APK", "pt": "Android APK", "ru": "Android APK", + "zh-chs": "Android APK", "xloc": [ - "default-mobile.handlebars->9->157", - "default.handlebars->25->27" + "default-mobile.handlebars->9->161", + "default.handlebars->27->27" ] }, { @@ -2470,13 +3405,17 @@ "de": "Android ARM", "en": "Android ARM", "es": "Android ARM", + "fr": "Android ARM", + "hi": "Android ARM", "ja": "Android ARM", + "ko": "안드로이드 팔", "nl": "Android ARM", "pt": "Android ARM", "ru": "Android ARM", + "zh-chs": "Android ARM", "xloc": [ - "default-mobile.handlebars->9->152", - "default.handlebars->25->22" + "default-mobile.handlebars->9->156", + "default.handlebars->27->22" ] }, { @@ -2484,13 +3423,17 @@ "de": "Android x86", "en": "Android x86", "es": "Android x86", + "fr": "Android x86", + "hi": "Android x86", "ja": "Android x86", + "ko": "안드로이드 x86", "nl": "Android x86", "pt": "Android x86", "ru": "Android x86", + "zh-chs": "安卓x86", "xloc": [ - "default-mobile.handlebars->9->155", - "default.handlebars->25->25" + "default-mobile.handlebars->9->159", + "default.handlebars->27->25" ] }, { @@ -2499,12 +3442,15 @@ "en": "Antivirus", "es": "Antivirus", "fr": "Antivirus", + "hi": "एंटीवायरस", "ja": "アンチウイルス", + "ko": "안티 바이러스", "nl": "Anti-virus", "pt": "Antivírus", "ru": "Антивирус", + "zh-chs": "防毒軟件", "xloc": [ - "default.handlebars->25->480" + "default.handlebars->27->487" ] }, { @@ -2512,12 +3458,16 @@ "de": "Alle unterstützten", "en": "Any supported", "es": "Cualquier Soporte.", + "fr": "Tout pris en charge", + "hi": "कोई समर्थित", "ja": "サポートされているもの", + "ko": "모든 지원", "nl": "Alle ondersteunde", "pt": "Qualquer suportado", "ru": "Любые поддерживаемые", + "zh-chs": "任何支持", "xloc": [ - "default.handlebars->25->287" + "default.handlebars->27->274" ] }, { @@ -2525,12 +3475,16 @@ "de": "Apple MacOS", "en": "Apple MacOS", "es": "Apple MacOS", + "fr": "Apple MacOS", + "hi": "Apple MacOS", "ja": "Apple MacOS", + "ko": "애플 맥 OS", "nl": "Apple MacOS", "pt": "Apple MacOS", "ru": "Apple MacOS", + "zh-chs": "蘋果MacOS", "xloc": [ - "default.handlebars->25->317" + "default.handlebars->27->304" ] }, { @@ -2538,12 +3492,16 @@ "de": "Nur Apple MacOS", "en": "Apple MacOS only", "es": "Solo Apple MacOS", + "fr": "Apple MacOS seulement", + "hi": "केवल Apple MacOS", "ja": "Apple MacOSのみ", + "ko": "Apple MacOS 만", "nl": "Alleen Apple MacOS", "pt": "Apenas Apple MacOS ", "ru": "Только Apple MacOS", + "zh-chs": "僅限Apple MacOS", "xloc": [ - "default.handlebars->25->289" + "default.handlebars->27->276" ] }, { @@ -2551,10 +3509,14 @@ "de": "Apple™ MacOS", "en": "Apple™ MacOS", "es": "Apple™ MacOS", + "fr": "Apple™ MacOS", + "hi": "Apple ™ MacOS", "ja": "Apple™MacOS", + "ko": "애플 맥 OS", "nl": "Apple™ MacOS", "pt": "Apple™ MacOS", "ru": "Apple™ MacOS", + "zh-chs": "蘋果™MacOS", "xloc": [ "agentinvite.handlebars->container->column_l->5->macostab->1" ] @@ -2563,216 +3525,288 @@ "cs": "arabština (Alžír)", "de": "Arabisch (Algerien)", "en": "Arabic (Algeria)", + "fr": "Arabe (Algérie)", + "hi": "अरबी (अल्जीरिया)", "ja": "アラビア語(アルジェリア)", + "ko": "아랍어 (알제리)", "nl": "Arabisch (Algerije)", "pt": "Árabe (Argélia)", "ru": "Арабский (Алжир)", + "zh-chs": "阿拉伯文(阿爾及利亞)", "xloc": [ - "default.handlebars->25->725" + "default.handlebars->27->829" ] }, { "cs": "arabština (Bahrajn)", "de": "Arabisch (Bahrain)", "en": "Arabic (Bahrain)", + "fr": "Arabe (Bahreïn)", + "hi": "अरबी (बहरीन)", "ja": "アラビア語(バーレーン)", + "ko": "아랍어 (바레인)", "nl": "Arabisch (Bahrein)", "pt": "Árabe (Bahrain)", "ru": "Арабский (Бахрейн)", + "zh-chs": "阿拉伯文(巴林)", "xloc": [ - "default.handlebars->25->726" + "default.handlebars->27->830" ] }, { "cs": "arabština (Egypt)", "de": "Arabisch (Ägypten)", "en": "Arabic (Egypt)", + "fr": "Arabe (Egypte)", + "hi": "अरबी (मिस्र)", "ja": "アラビア語(エジプト)", + "ko": "아랍어 (이집트)", "nl": "Arabisch (Egypte)", "pt": "Árabe (Egito)", "ru": "Арабский (Египет)", + "zh-chs": "阿拉伯文(埃及)", "xloc": [ - "default.handlebars->25->727" + "default.handlebars->27->831" ] }, { "cs": "arabština (Irák)", "de": "Arabisch (Irak)", "en": "Arabic (Iraq)", + "fr": "Arabe (Iraq)", + "hi": "अरबी (इराक)", "ja": "アラビア語(イラク)", + "ko": "아랍어 (이라크)", "nl": "Arabisch (Irak)", "pt": "Árabe (Iraque)", "ru": "Арабский (Ирак)", + "zh-chs": "阿拉伯文(伊拉克)", "xloc": [ - "default.handlebars->25->728" + "default.handlebars->27->832" ] }, { "cs": "arabština (Jordánsko)", "de": "Arabisch (Jordanien)", "en": "Arabic (Jordan)", + "fr": "Arabe (Jordanie)", + "hi": "अरबी (जॉर्डन)", "ja": "アラビア語(ヨルダン)", + "ko": "아랍어 (요르단)", "nl": "Arabisch (Jordanië)", "pt": "Árabe (Jordânia)", "ru": "Арабский (Иордания)", + "zh-chs": "阿拉伯語(約旦)", "xloc": [ - "default.handlebars->25->729" + "default.handlebars->27->833" ] }, { "cs": "arabština (Kuvajt)", "de": "Arabisch (Kuwait)", "en": "Arabic (Kuwait)", + "fr": "Arabe (Koweït)", + "hi": "अरबी (कुवैत)", "ja": "アラビア語(クウェート)", + "ko": "아랍어 (쿠웨이트)", "nl": "Arabisch (Koeweit)", "pt": "Árabe (Kuwait)", "ru": "Арабский (Кувейт)", + "zh-chs": "阿拉伯文(科威特)", "xloc": [ - "default.handlebars->25->730" + "default.handlebars->27->834" ] }, { "cs": "arabština (Libanon)", "de": "Arabisch (Libanon)", "en": "Arabic (Lebanon)", + "fr": "Arabe (Liban)", + "hi": "अरबी (लेबनान)", "ja": "アラビア語(レバノン)", + "ko": "아랍어 (레바논)", "nl": "Arabisch (Libanon)", "pt": "Árabe (Líbano)", "ru": "Арабский (Ливан)", + "zh-chs": "阿拉伯語(黎巴嫩)", "xloc": [ - "default.handlebars->25->731" + "default.handlebars->27->835" ] }, { "cs": "arabština (Libye)", "de": "Arabisch (Libyen)", "en": "Arabic (Libya)", + "fr": "Arabe (Lybie)", + "hi": "अरबी (लीबिया)", "ja": "アラビア語(リビア)", + "ko": "아랍어 (리비아)", "nl": "Arabisch (Libië)", "pt": "Árabe (Líbia)", "ru": "Арабский (Ливия)", + "zh-chs": "阿拉伯文(利比亞)", "xloc": [ - "default.handlebars->25->732" + "default.handlebars->27->836" ] }, { "cs": "arabština (Maroko)", "de": "Arabisch (Marokko)", "en": "Arabic (Morocco)", + "fr": "Arabe (Maroc)", + "hi": "अरबी (मोरक्को)", "ja": "アラビア語(モロッコ)", + "ko": "아랍어 (모로코)", "nl": "Arabisch (Marokko)", "pt": "Árabe (Marrocos)", "ru": "Арабский (Марокко)", + "zh-chs": "阿拉伯文(摩洛哥)", "xloc": [ - "default.handlebars->25->733" + "default.handlebars->27->837" ] }, { "cs": "arabština (Omán)", "de": "Arabisch (Oman)", "en": "Arabic (Oman)", + "fr": "Arabe (Oman)", + "hi": "अरबी (ओमान)", "ja": "アラビア語(オマーン)", + "ko": "아랍어 (오만)", "nl": "Arabisch (Oman)", "pt": "Árabe (Omã)", "ru": "Арабский (Оман)", + "zh-chs": "阿拉伯文(阿曼)", "xloc": [ - "default.handlebars->25->734" + "default.handlebars->27->838" ] }, { "cs": "arabština (Katar)", "de": "Arabisch (Katar)", "en": "Arabic (Qatar)", + "fr": "Arabe (Qatar)", + "hi": "अरबी (कतर)", "ja": "アラビア語(カタール)", + "ko": "아랍어 (카타르)", "nl": "Arabisch (Qatar)", "pt": "Árabe (Catar)", "ru": "Арабский (Катар)", + "zh-chs": "阿拉伯語(卡塔爾)", "xloc": [ - "default.handlebars->25->735" + "default.handlebars->27->839" ] }, { "cs": "arabština (Saudská Arábie)", "de": "Arabisch (Saudi-Arabien)", "en": "Arabic (Saudi Arabia)", + "fr": "Arabe (Arabie Saoudite)", + "hi": "अरबी (सऊदी अरब)", "ja": "アラビア語(サウジアラビア)", + "ko": "아랍어 (사우디 아라비아)", "nl": "Arabisch (Saoedi-Arabië)", "pt": "Árabe (Arábia Saudita)", "ru": "Арабский (Саудовская Аравия)", + "zh-chs": "阿拉伯語(沙特阿拉伯)", "xloc": [ - "default.handlebars->25->736" + "default.handlebars->27->840" ] }, { "cs": "arabština (standardní)", "de": "Arabisch (Standard)", "en": "Arabic (Standard)", + "fr": "Arabe (Standard)", + "hi": "अरबी (मानक)", "ja": "アラビア語(標準)", + "ko": "아랍어 (표준)", "nl": "Arabisch (Standaard)", "pt": "Árabe (padrão)", "ru": "Арабский (стандартный)", + "zh-chs": "阿拉伯語(標準)", "xloc": [ - "default.handlebars->25->724" + "default.handlebars->27->828" ] }, { "cs": "arabština (Sýrie)", "de": "Arabisch (Syrien)", "en": "Arabic (Syria)", + "fr": "Arabe (Syrie)", + "hi": "अरबी (सीरिया)", "ja": "アラビア語(シリア)", + "ko": "아랍어 (시리아)", "nl": "Arabisch (Syrië)", "pt": "Árabe (Síria)", "ru": "Арабский (Сирия)", + "zh-chs": "阿拉伯語(敘利亞)", "xloc": [ - "default.handlebars->25->737" + "default.handlebars->27->841" ] }, { "cs": "arabština (Tunisko)", "de": "Arabisch (Tunesien)", "en": "Arabic (Tunisia)", + "fr": "Arabe (Tunisie)", + "hi": "अरबी (ट्यूनीशिया)", "ja": "アラビア語(チュニジア)", + "ko": "아랍어 (튀니지)", "nl": "Arabisch (Tunesië)", "pt": "Árabe (Tunísia)", "ru": "Арабский (Тунис)", + "zh-chs": "阿拉伯文(突尼斯)", "xloc": [ - "default.handlebars->25->738" + "default.handlebars->27->842" ] }, { "cs": "arabština (Spojené Emiráty)", "de": "Arabisch (V.A.E.)", "en": "Arabic (U.A.E.)", + "fr": "Arabe (U.A.E.)", + "hi": "अरबी (U.A.E.)", "ja": "アラビア語(U.A.E.)", + "ko": "아랍어 (미국)", "nl": "Arabisch (Verenigde Arabische Emiraten.)", "pt": "Árabe (U.A.E)", "ru": "Арабский (О.А.Э.)", + "zh-chs": "阿拉伯文(阿聯酋)", "xloc": [ - "default.handlebars->25->739" + "default.handlebars->27->843" ] }, { "cs": "arabština (Jemen)", "de": "Arabisch (Jemen)", "en": "Arabic (Yemen)", + "fr": "Arabe (Yemen)", + "hi": "अरबी (यमन)", "ja": "アラビア語(イエメン)", + "ko": "아랍어 (예멘)", "nl": "Arabisch (Jemen)", "pt": "Árabe (Iêmen)", "ru": "Арабский (Йемен)", + "zh-chs": "阿拉伯文(也門)", "xloc": [ - "default.handlebars->25->740" + "default.handlebars->27->844" ] }, { "cs": "aragonština", "de": "Aragonesisch", "en": "Aragonese", + "fr": "Aragonais", + "hi": "Aragonese", "ja": "アラゴン語", + "ko": "아라곤 어", "nl": "Aragonese", "pt": "Aragonês", "ru": "Арагонский", + "zh-chs": "阿拉貢人", "xloc": [ - "default.handlebars->25->741" + "default.handlebars->27->845" ] }, { @@ -2781,12 +3815,15 @@ "en": "Architecture", "es": "Architectura", "fr": "Architecture", + "hi": "आर्किटेक्चर", "ja": "建築", - "nl": "architectuur", + "ko": "건축물", + "nl": "Architectuur", "pt": "Arquitetura", "ru": "Архитектура", + "zh-chs": "建築", "xloc": [ - "default.handlebars->25->82" + "default.handlebars->27->742" ] }, { @@ -2794,11 +3831,16 @@ "de": "Möchten Sie wirklich eine Verbindung zu {0} Geräten herstellen?", "en": "Are you sure you want to connect to {0} devices?", "es": "¿Está seguro de que desea conectarse a {0} dispositivos?", + "fr": "Êtes vous sur de vouloir vous connecter à ces {0} appareils ?", + "hi": "क्या आप वाकई {0} उपकरणों से कनेक्ट करना चाहते हैं?", "ja": "{0}台のデバイスに接続してもよろしいですか?", + "ko": "{0} 기기에 연결 하시겠습니까?", "nl": "Weet u zeker dat u verbinding wilt maken met {0} apparaten?", + "pt": "Tem certeza de que deseja se conectar a {0} dispositivos?", "ru": "Вы действительно хотите подключиться к {0} устройствам?", + "zh-chs": "您確定要連接到{0}設備嗎?", "xloc": [ - "default.handlebars->25->218" + "default.handlebars->27->202" ] }, { @@ -2807,13 +3849,16 @@ "en": "Are you sure you want to delete group {0}? Deleting the device group will also delete all information about devices within this group.", "es": "¿Está seguro de que desea eliminar el grupo {0}? Al eliminar el grupo de dispositivos también se eliminará toda la información sobre los dispositivos dentro de este grupo.", "fr": "Êtes-vous sûr de vouloir supprimer le groupe {0}? La suppression du groupe de périphériques supprimera également toutes les informations relatives aux périphériques de ce groupe.", + "hi": "क्या आप वाकई {0} समूह को हटाना चाहते हैं? डिवाइस समूह को हटाने से इस समूह के भीतर डिवाइस के बारे में सभी जानकारी भी हट जाएगी।", "ja": "グループ{0}を削除してもよろしいですか?デバイスグループを削除すると、このグループ内のデバイスに関するすべての情報も削除されます。", + "ko": "그룹 {0}을 (를) 삭제 하시겠습니까? 장치 그룹을 삭제하면이 그룹 내의 장치에 대한 모든 정보도 삭제됩니다.", "nl": "Weet je zeker dat je groep {0} wilt verwijderen? Als u de apparaatgroep verwijdert, wordt ook alle informatie over apparaten binnen deze groep verwijderd.", "pt": "Tem certeza de que deseja excluir o grupo {0}? A exclusão do grupo de dispositivos também excluirá todas as informações sobre os dispositivos desse grupo.", "ru": "Вы действительно хотите удалить группу \\\"{0}\\\"? Удаление группы приведет к удалению всей информации связанной с устройствами в этой группе.", + "zh-chs": "您確定要刪除組{0}嗎?刪除設備組還將刪除該組中有關設備的所有信息。", "xloc": [ - "default-mobile.handlebars->9->286", - "default.handlebars->25->1063" + "default-mobile.handlebars->9->290", + "default.handlebars->27->1167" ] }, { @@ -2822,12 +3867,15 @@ "en": "Are you sure you want to delete node {0}?", "es": "¿Está seguro de que desea eliminar el nodo {0}?", "fr": "Êtes-vous sûr de vouloir supprimer le noeud {0}?", + "hi": "क्या आप वाकई {0} नोड को हटाना चाहते हैं?", "ja": "ノード{0}を削除してもよろしいですか?", + "ko": "{0} 노드를 삭제 하시겠습니까?", "nl": "Weet u zeker dat u apparaat {0} wilt verwijderen?", "pt": "Tem certeza de que deseja excluir o nó {0}?", "ru": "Вы действительно хотите удалить устройство \\\"{0}\\\"?", + "zh-chs": "您確定要刪除節點{0}嗎?", "xloc": [ - "default.handlebars->25->568" + "default.handlebars->27->615" ] }, { @@ -2835,11 +3883,16 @@ "de": "Möchten Sie den ausgewählten Agenten wirklich deinstallieren?", "en": "Are you sure you want to uninstall selected agent?", "es": "¿Está seguro de que desea desinstalar el agente seleccionado?", + "fr": "Êtes vous sur de vouloir désinstaller l'agent sélectionné ?", + "hi": "क्या आप वाकई चयनित एजेंट को अनइंस्टॉल करना चाहते हैं?", "ja": "選択したエージェントをアンインストールしてもよろしいですか?", + "ko": "선택한 에이전트를 제거 하시겠습니까?", "nl": "Weet u zeker dat u de geselecteerde agent wilt verwijderen?", + "pt": "Tem certeza de que deseja desinstalar o agente selecionado?", "ru": "Вы действительно хотите деинсталировать выбранного агента?", + "zh-chs": "您確定要卸載所選代理嗎?", "xloc": [ - "default.handlebars->25->557" + "default.handlebars->27->604" ] }, { @@ -2847,11 +3900,16 @@ "de": "Möchten Sie die ausgewählten {0} Agenten wirklich deinstallieren?", "en": "Are you sure you want to uninstall the selected {0} agents?", "es": "¿Está seguro de que desea desinstalar los {0} agentes seleccionados?", + "fr": "Êtes vous sur de vouloir désinstaller ces {0} agents ?", + "hi": "क्या आप वाकई चयनित {0} एजेंटों की स्थापना रद्द करना चाहते हैं?", "ja": "選択した{0}エージェントをアンインストールしてもよろしいですか?", + "ko": "선택한 {0} 에이전트를 설치 제거 하시겠습니까?", "nl": "Weet u zeker dat u de geselecteerde {0} agenten wilt verwijderen?", + "pt": "Tem certeza de que deseja desinstalar os {0} agentes selecionados?", "ru": "Вы действительно хотите деинсталлировать выбранных {0} агентов?", + "zh-chs": "您確定要卸載所選的{0}代理嗎?", "xloc": [ - "default.handlebars->25->556" + "default.handlebars->27->603" ] }, { @@ -2859,47 +3917,64 @@ "de": "Möchten Sie wirklich das Plugin {0}: {1}", "en": "Are you sure you want to {0} the plugin: {1}", "es": "Está seguro de que desea {0} el plugin: {1}?", + "fr": "Êtes vous sur de vouloir {0} le module: {1}", + "hi": "क्या आप वाकई {0} प्लगइन चाहते हैं: {1}", "ja": "プラグインを{0}してもよろしいですか:{1}", + "ko": "플러그인 {0}을 (를) {0} 하시겠습니까?", "nl": "Weet u zeker dat u de plug-in {0} wilt gebruiken: {1}", + "pt": "Tem certeza de que deseja {0} o plug-in: {1}", "ru": "Вы уверенны, что {0} плагин: {1}", + "zh-chs": "您確定要{0}插件嗎:{1}", "xloc": [ - "default.handlebars->25->1462" + "default.handlebars->27->1614" ] }, { "cs": "arménština", "de": "Armenisch", "en": "Armenian", + "fr": "Arménien", + "hi": "अर्मेनियाई", "ja": "アルメニア人", + "ko": "아르메니아 사람", "nl": "Armeens", "pt": "Armênio", "ru": "Армянский", + "zh-chs": "亞美尼亞人", "xloc": [ - "default.handlebars->25->742" + "default.handlebars->27->846" ] }, { "cs": "asámština", "de": "Assamesisch", "en": "Assamese", + "fr": "Assamais", + "hi": "असमिया", "ja": "アッサム語", + "ko": "아쌈", "nl": "Assamees", "pt": "Assamese", "ru": "Ассамский", + "zh-chs": "阿薩姆語", "xloc": [ - "default.handlebars->25->743" + "default.handlebars->27->847" ] }, { "cs": "asturština", "de": "Asturisch", "en": "Asturian", + "fr": "Asturien", + "hi": "अस्तुरियन", "ja": "アストゥリアス", + "ko": "아 스투 리아 사람", "nl": "Asturische", "pt": "Asturiano", "ru": "Астурии", + "zh-chs": "阿斯圖里亞斯人", "xloc": [ - "default.handlebars->25->744" + "default.handlebars->27->848" ] }, { @@ -2907,12 +3982,16 @@ "de": "Authentifizierungsanwendung", "en": "Authentication App", "es": "Aplicación de autenticación", + "fr": "Application d'authentification", + "hi": "प्रमाणीकरण ऐप", "ja": "認証アプリ", + "ko": "인증 앱", "nl": "Verificatie-app", "pt": "Aplicativo de autenticação", "ru": "Приложение аутентификации", + "zh-chs": "身份驗證應用", "xloc": [ - "default.handlebars->25->1343" + "default.handlebars->27->1477" ] }, { @@ -2920,19 +3999,23 @@ "de": "Authentifikator-Anwendung", "en": "Authenticator App", "es": "Aplicación de autenticación", + "fr": "Application d'authentification", + "hi": "प्रमाणक ऐप", "ja": "認証アプリ", + "ko": "인증 자 앱", "nl": "Verificatie-app", "pt": "Autenticador de aplicativo", "ru": "Приложение-аутентификатор", + "zh-chs": "身份驗證器應用", "xloc": [ "default-mobile.handlebars->9->18", "default-mobile.handlebars->9->21", - "default-mobile.handlebars->9->30", - "default-mobile.handlebars->9->32", - "default.handlebars->25->122", - "default.handlebars->25->127", - "default.handlebars->25->708", - "default.handlebars->25->710" + "default-mobile.handlebars->9->33", + "default-mobile.handlebars->9->35", + "default.handlebars->27->105", + "default.handlebars->27->110", + "default.handlebars->27->812", + "default.handlebars->27->814" ] }, { @@ -2940,12 +4023,16 @@ "de": "Aktivierung der Authentifikator-Anwendung erfolgreich.", "en": "Authenticator app activation successful.", "es": "Autenticación de la aplicación de autenticación exitosa.", + "fr": "Authentification à double facteur activée avec succès.", + "hi": "प्रमाणक अनुप्रयोग सक्रियण सफल।", "ja": "認証アプリのアクティベーションが成功しました。", + "ko": "인증 자 앱 활성화에 성공했습니다.", "nl": "Verificatie-app activatie geslaagd", "pt": "Ativação do aplicativo autenticador bem-sucedida.", "ru": "Приложение для аутентификации активированно успешно.", + "zh-chs": "身份驗證器應用程序激活成功。", "xloc": [ - "default.handlebars->25->123" + "default.handlebars->27->106" ] }, { @@ -2953,12 +4040,16 @@ "de": "Authentifikator-Anwendung entfernt.", "en": "Authenticator application removed.", "es": "Aplicación de autenticación eliminada.", + "fr": "Authentification à double facteur supprimée.", + "hi": "प्रमाणीकरणकर्ता का आवेदन हटा दिया गया।", "ja": "認証アプリケーションが削除されました。", + "ko": "인증 기 응용 프로그램이 제거되었습니다.", "nl": "Verificatie-applicatie verwijderd.", "pt": "Aplicativo autenticador removido.", "ru": "Приложение для аутентификации удалено.", + "zh-chs": "身份驗證器應用程序已刪除。", "xloc": [ - "default.handlebars->25->128" + "default.handlebars->27->111" ] }, { @@ -2967,13 +4058,15 @@ "en": "Auto", "es": "Automatico", "fr": "Automatique", + "hi": "ऑटो", "ja": "オート", + "ko": "자동", "nl": "Automatisch", "pt": "Auto", "ru": "Автоматически", + "zh-chs": "汽車", "xloc": [ - "default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->kvmListToolbar->5", - "default.handlebars->container->column_l->p12->termTable->1->1->6->1->1->terminalSizeDropDown->termSizeList->2" + "default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->kvmListToolbar->5" ] }, { @@ -2981,12 +4074,16 @@ "de": "Auto-Entfernen", "en": "Auto-Remove", "es": "Eliminar automáticamente", + "fr": "Suppression automatique", + "hi": "ऑटो निकालें", "ja": "自動削除", + "ko": "자동 제거", "nl": "Geautomatiseerde verwijdering", "pt": "Remover automaticamente", "ru": "Автоудаление", + "zh-chs": "自動刪除", "xloc": [ - "default.handlebars->25->986" + "default.handlebars->27->1091" ] }, { @@ -2994,10 +4091,14 @@ "de": "Auto-Verbindung", "en": "AutoConnect", "es": "Auto Conectarse", + "fr": "Connection automatique", + "hi": "स्वतः जुड़ना", "ja": "自動接続", + "ko": "자동 연결", "nl": "Automatisch verbinden", "pt": "Conexão automática", "ru": "Автоподключение", + "zh-chs": "自動連接", "xloc": [ "default-mobile.handlebars->container->page_content->column_l->p10->p10files->p13toolbar->1->0->1->3", "default.handlebars->container->column_l->p11->deskarea0->deskarea1->3", @@ -3011,10 +4112,13 @@ "en": "Automatic connect", "es": "Conexion Automatica", "fr": "Connexion automatique", + "hi": "स्वचालित कनेक्ट", "ja": "自動接続", + "ko": "자동 연결", "nl": "Automatisch verbinden", "pt": "Conexão automática", "ru": "Автоматическое подключение", + "zh-chs": "自動連接", "xloc": [ "default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->kvmListToolbar->5" ] @@ -3023,12 +4127,16 @@ "cs": "azerbájdžánština", "de": "Aserbaidschanisch", "en": "Azerbaijani", + "fr": "Azerbaïdjanais", + "hi": "आज़रबाइजानी", "ja": "アゼルバイジャン語", + "ko": "아제르바이잔", "nl": "Azerbeidzjaanse", "pt": "Azerbaijão", "ru": "Азербайджанский", + "zh-chs": "阿塞拜疆", "xloc": [ - "default.handlebars->25->745" + "default.handlebars->27->849" ] }, { @@ -3036,12 +4144,16 @@ "de": "BIOS", "en": "BIOS", "es": "BIOS", + "fr": "BIOS", + "hi": "BIOS", "ja": "BIOS", + "ko": "BIOS", "nl": "BIOS", "pt": "BIOS", "ru": "BIOS", + "zh-chs": "的BIOS", "xloc": [ - "default.handlebars->25->66" + "default.handlebars->27->780" ] }, { @@ -3050,10 +4162,13 @@ "en": "Back", "es": "Atras", "fr": "Retour", + "hi": "वापस", "ja": "バック", + "ko": "뒤", "nl": "Terug", "pt": "Voltar", "ru": "Назад", + "zh-chs": "背部", "xloc": [ "default.handlebars->container->column_l->p10->1->1->0->1->p10title->p10BackButton", "default.handlebars->container->column_l->p11->p11title->p11deviceNameHeader->p11BackButton", @@ -3073,7 +4188,7 @@ "error404-mobile.handlebars->container->footer->1->1->0->3->1", "error404.handlebars->container->footer->1->1->0->3->0", "terms-mobile.handlebars->container->footer->1->1->0->3->1", - "terms.handlebars->container->footer->1->1->0->3->0" + "terms.handlebars->container->footer->1->1->0->3->backLink" ] }, { @@ -3081,10 +4196,14 @@ "de": "Zurück zur Anmeldung", "en": "Back to login", "es": "Regresar al Inicio de Sesion", + "fr": "Revenir à l'authentification", + "hi": "लॉगिन पर वापस जाएं", "ja": "ログインに戻る", + "ko": "로그인으로 돌아 가기", "nl": "Terug naar inloggen", "pt": "Volte ao login", "ru": "Обратно к экрану входа", + "zh-chs": "回到登入", "xloc": [ "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->createpanel->1->1->12", "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->resetpanel->1->10", @@ -3103,12 +4222,16 @@ "de": "Hintergrund & interaktiv", "en": "Background & interactive", "es": "Segundo plano & Interactivo", + "fr": "Ligne de commande & bureau distant", + "hi": "पृष्ठभूमि और इंटरैक्टिव", "ja": "背景とインタラクティブ", + "ko": "배경 및 대화식", "nl": "Achtergrond & interactief", "pt": "Segundo plano e interativo", "ru": "Фоновый и интерактивный", + "zh-chs": "背景與互動", "xloc": [ - "default.handlebars->25->321" + "default.handlebars->27->308" ] }, { @@ -3116,12 +4239,18 @@ "de": "Hintergrund und interaktiv", "en": "Background and interactive", "es": "Segundo Plano e interactivo", + "fr": "Ligne de commande et bureau distant", + "hi": "पृष्ठभूमि और इंटरैक्टिव", "ja": "背景とインタラクティブ", + "ko": "배경 및 대화식", "nl": "Achtergrond en interactief", "pt": "Segundo plano e interativo", "ru": "Фоновый и интерактивный", + "zh-chs": "背景與互動", "xloc": [ - "default.handlebars->25->299" + "default.handlebars->27->1256", + "default.handlebars->27->1263", + "default.handlebars->27->286" ] }, { @@ -3129,13 +4258,19 @@ "de": "Nur Hintergrund", "en": "Background only", "es": "Segundo Plano solamente", + "fr": "Ligne de commande uniquement", + "hi": "बैकग्राउंड ही", "ja": "背景のみ", + "ko": "배경 만", "nl": "Alleen achtergrond", "pt": "Apenas em segundo plano", "ru": "Только фоновый", + "zh-chs": "僅背景", "xloc": [ - "default.handlebars->25->300", - "default.handlebars->25->322" + "default.handlebars->27->1257", + "default.handlebars->27->1264", + "default.handlebars->27->287", + "default.handlebars->27->309" ] }, { @@ -3144,10 +4279,13 @@ "en": "Backspace", "es": "Borrar", "fr": "Retour arrière", + "hi": "बैकस्पेस", "ja": "バックスペース", + "ko": "역행 키이", "nl": "Backspace", "pt": "Excluir", "ru": "Backspace", + "zh-chs": "退格鍵", "xloc": [ "default.handlebars->container->column_l->p12->termTable->1->1->6->1->3" ] @@ -3157,12 +4295,16 @@ "de": "Sicherungscodes", "en": "Backup Codes", "es": "Codigos de Respaldo", + "fr": "Codes de récupération", + "hi": "बैकअप कोड", "ja": "バックアップコード", + "ko": "백업 코드", "nl": "Back-up codes", "pt": "Códigos de backup", "ru": "Резервные коды", + "zh-chs": "備用碼", "xloc": [ - "default.handlebars->25->1345" + "default.handlebars->27->1479" ] }, { @@ -3170,10 +4312,16 @@ "de": "Ungültige Unterschrift", "en": "Bad Signature", "es": "Firma Erronea", + "fr": "Signature erronée", + "hi": "खराब हस्ताक्षर", + "ja": "悪い署名", + "ko": "나쁜 서명", "nl": "Ongeldige handtening", + "pt": "Assinatura ruim", "ru": "Плохой ключ", + "zh-chs": "錯誤的簽名", "xloc": [ - "default.handlebars->25->1405" + "default.handlebars->27->1552" ] }, { @@ -3181,22 +4329,32 @@ "de": "Ungültiges Web-Zertifikat", "en": "Bad Web Certificate", "es": "Cenrtificado Web Erroneo", + "fr": "Mauvais certificat web", + "hi": "खराब वेब प्रमाणपत्र", + "ja": "不正なWeb証明書", + "ko": "잘못된 웹 인증서", "nl": "Onjuist webcertificaat", + "pt": "Certificado da Web inválido", "ru": "Плохой веб-сертификат", + "zh-chs": "錯誤的網絡證書", "xloc": [ - "default.handlebars->25->1404" + "default.handlebars->27->1551" ] }, { "cs": "baskičtina", "de": "Baskisch", "en": "Basque", + "fr": "basque", + "hi": "बस्क", "ja": "バスク", - "nl": "baskisch", + "ko": "바스크 사람", + "nl": "Baskisch", "pt": "Basco", "ru": "Баскский", + "zh-chs": "巴斯克", "xloc": [ - "default.handlebars->25->746" + "default.handlebars->27->850" ] }, { @@ -3204,10 +4362,14 @@ "de": "Stapel-Erzeugung vieler Benutzerkonten", "en": "Batch create many user accounts", "es": "Crear Muchas Cuentas de Usuario (Batch)", + "fr": "Création par lots de comptes utilisateurs", + "hi": "बैच कई उपयोगकर्ता खाते बनाते हैं", "ja": "多数のユーザーアカウントをバッチ作成する", + "ko": "많은 사용자 계정을 일괄 생성", "nl": "Gebruikersaccounts aanmaken in batch", "pt": "Lote criar muitas contas de usuário", "ru": "Пакетное создание нескольких учетных записей пользователей", + "zh-chs": "批量創建多個用戶帳戶", "xloc": [ "default.handlebars->container->column_l->p4->3->1->0->3->1->5" ] @@ -3216,48 +4378,80 @@ "cs": "běloruština", "de": "Belarussisch", "en": "Belarusian", + "fr": "Biélorusse", + "hi": "बेलारूसी", "ja": "ベラルーシ語", + "ko": "벨로루시 어", "nl": "Wit-Rusland", "pt": "Bielorrusso", "ru": "Белорусский", + "zh-chs": "白俄羅斯語", "xloc": [ - "default.handlebars->25->748" + "default.handlebars->27->852" ] }, { "cs": "bengálština", "de": "Bengali", "en": "Bengali", + "fr": "Bengalais", + "hi": "बंगाली", "ja": "ベンガル語", + "ko": "벵골 사람", "nl": "Bengalees", "pt": "Bengali", "ru": "Бенгальский", + "zh-chs": "孟加拉", "xloc": [ - "default.handlebars->25->749" + "default.handlebars->27->853" + ] + }, + { + "cs": "S pozdravem,", + "de": "Freundliche Grüße,", + "en": "Best regards,", + "fr": "Meilleures salutations,", + "nl": "Vriendelijke groeten,", + "ja": "宜しくお願いします、", + "ru": "С уважением,", + "zh-chs": "最好的祝福,", + "xloc": [ + "account-invite.html->2", + "account-invite.txt", + "mesh-invite.html->2", + "mesh-invite.txt" ] }, { "cs": "bosenština", "de": "Bosnisch", "en": "Bosnian", + "fr": "Bosniaque", + "hi": "बोस्नियाई", "ja": "ボスニア語", + "ko": "보스니아 어", "nl": "Bosnisch", "pt": "Bósnia", "ru": "Боснийский", + "zh-chs": "波斯尼亞人", "xloc": [ - "default.handlebars->25->750" + "default.handlebars->27->854" ] }, { "cs": "bretonština", "de": "Bretonisch", "en": "Breton", + "fr": "Breton", + "hi": "ब्रेटन", "ja": "ブルトン", + "ko": "브르타뉴 어", "nl": "Breton", "pt": "Breton", "ru": "Бретонский", + "zh-chs": "布列塔尼", "xloc": [ - "default.handlebars->25->751" + "default.handlebars->27->855" ] }, { @@ -3266,12 +4460,15 @@ "en": "Broadcast", "es": "Broadcast", "fr": "Diffuser", + "hi": "प्रसारण", "ja": "放送", - "nl": "Uitzending", + "ko": "방송", + "nl": "Bericht verzending", "pt": "Broadcast", "ru": "Отправить сообщение", + "zh-chs": "廣播", "xloc": [ - "default.handlebars->25->1286", + "default.handlebars->27->1422", "default.handlebars->container->column_l->p4->3->1->0->3->1" ] }, @@ -3281,12 +4478,15 @@ "en": "Broadcast Message", "es": "Mensaje de Broadcast", "fr": "Diffusion d'un Message", + "hi": "प्रसारण संदेश", "ja": "同報メッセージ", + "ko": "방송 메시지", "nl": "Bericht uitzenden", "pt": "Mensagem de transmissão", "ru": "Отправить сообщение", + "zh-chs": "廣播消息", "xloc": [ - "default.handlebars->25->1243" + "default.handlebars->27->1378" ] }, { @@ -3294,36 +4494,48 @@ "de": "Eine Nachricht an alle verbundenen Benutzer senden.", "en": "Broadcast a message to all connected users.", "es": "Mensaje de Broadcast a todos los usuarios conectados.", + "fr": "Diffuser un message à tous les utilisateurs connectés", + "hi": "सभी कनेक्टेड उपयोगकर्ताओं के लिए एक संदेश प्रसारित करें।", "ja": "接続されているすべてのユーザーにメッセージをブロードキャストします。", + "ko": "연결된 모든 사용자에게 메시지를 브로드 캐스트합니다.", "nl": "Verzend een bericht naar alle verbonden gebruikers.", "pt": "Transmita uma mensagem para todos os usuários conectados.", "ru": "Отправить сообщение всем подключенным пользователям.", + "zh-chs": "向所有連接的用戶廣播消息。", "xloc": [ - "default.handlebars->25->1242" + "default.handlebars->27->1377" ] }, { "cs": "bulharština", "de": "Bulgarisch", "en": "Bulgarian", + "fr": "Bulgare", + "hi": "बल्गेरियाई", "ja": "ブルガリア語", + "ko": "불가리아 사람", "nl": "Bulgaars", "pt": "Búlgaria", "ru": "Болгарский", + "zh-chs": "保加利亞語", "xloc": [ - "default.handlebars->25->747" + "default.handlebars->27->851" ] }, { "cs": "barmština", "de": "Birmanisch", "en": "Burmese", + "fr": "Birman", + "hi": "बर्मी", "ja": "ビルマ語", + "ko": "버마 사람", "nl": "Birmaans", "pt": "Birmanês", "ru": "Бирманский", + "zh-chs": "緬甸人", "xloc": [ - "default.handlebars->25->752" + "default.handlebars->27->856" ] }, { @@ -3331,13 +4543,17 @@ "de": "CCM", "en": "CCM", "es": "CCM", + "fr": "CCM", + "hi": "सीसीएम", "ja": "CCM", + "ko": "CCM", "nl": "CCM", "pt": "CCM", "ru": "CCM", + "zh-chs": "CCM", "xloc": [ - "default-mobile.handlebars->9->181", - "default.handlebars->25->460" + "default-mobile.handlebars->9->185", + "default.handlebars->27->467" ] }, { @@ -3345,16 +4561,20 @@ "de": "CIRA", "en": "CIRA", "es": "CIRA", + "fr": "CIRA", + "hi": "सीआईआरए", "ja": "CIRA", + "ko": "시라", "nl": "CIRA", "pt": "CIRA", "ru": "CIRA", + "zh-chs": "CIRA", "xloc": [ - "default-mobile.handlebars->9->122", - "default.handlebars->25->1051", - "default.handlebars->25->1056", - "default.handlebars->25->186", - "default.handlebars->25->373" + "default-mobile.handlebars->9->126", + "default.handlebars->27->1155", + "default.handlebars->27->1160", + "default.handlebars->27->170", + "default.handlebars->27->363" ] }, { @@ -3362,12 +4582,16 @@ "de": "CIRA-Server", "en": "CIRA Server", "es": "Servidor CIRA", + "fr": "Serveur CIRA", + "hi": "CIRA सर्वर", "ja": "CIRAサーバー", + "ko": "CIRA 서버", "nl": "CIRA Server", "pt": "Servidor CIRA", "ru": "CIRA Сервер", + "zh-chs": "CIRA服務器", "xloc": [ - "default.handlebars->25->1453" + "default.handlebars->27->1602" ] }, { @@ -3375,12 +4599,16 @@ "de": "CIRA-Serverbefehle", "en": "CIRA Server Commands", "es": "Comandos del servidor CIRA", + "fr": "Commandes du serveur CIRA", + "hi": "CIRA सर्वर कमांड्स", "ja": "CIRAサーバーコマンド", + "ko": "CIRA 서버 명령", "nl": "CIRA Server opdrachten", "pt": "Comandos do servidor CIRA", "ru": "CIRA Сервер команды", + "zh-chs": "CIRA服務器命令", "xloc": [ - "default.handlebars->25->1454" + "default.handlebars->27->1603" ] }, { @@ -3388,10 +4616,16 @@ "de": "CPU-Auslastung", "en": "CPU Load", "es": "Carga en el CPU", + "fr": "Charge CPU", + "hi": "सीपीयू लोड", + "ja": "CPU負荷", + "ko": "CPU로드", "nl": "CPU gebruik", + "pt": "Carga da CPU", "ru": "Загрузка CPU", + "zh-chs": "CPU負載", "xloc": [ - "default.handlebars->25->1419" + "default.handlebars->27->1566" ] }, { @@ -3399,12 +4633,16 @@ "de": "CPU-Auslastung der vergangenen 15 Minuten", "en": "CPU load in the last 15 minutes", "es": "Carga en el CPU en los ultimos 15 minutos", + "fr": "Charge CPU dans les 15 dernières minutes", + "hi": "पिछले 15 मिनट में सीपीयू लोड हुआ", "ja": "過去15分間のCPU負荷", + "ko": "지난 15 분 동안의 CPU로드", "nl": "CPU-belasting in de afgelopen 15 minuten", "pt": "Carga da CPU nos últimos 15 minutos", "ru": "Загрузка CPU за последние 15 минут", + "zh-chs": "最近15分鐘的CPU負載", "xloc": [ - "default.handlebars->25->1422" + "default.handlebars->27->1569" ] }, { @@ -3412,12 +4650,16 @@ "de": "CPU-Auslastung der vergangenen 5 Minuten", "en": "CPU load in the last 5 minutes", "es": "Carga en el CPU en los ultimos 5 minutos", + "fr": "Charge CPU dans les 5 dernières minutes", + "hi": "पिछले 5 मिनट में सीपीयू लोड हुआ", "ja": "過去5分間のCPU負荷", + "ko": "지난 5 분 동안의 CPU로드", "nl": "CPU-belasting in de afgelopen 5 minuten", "pt": "Carga da CPU nos últimos 5 minutos", "ru": "Загрузка CPU за последние 5 минут", + "zh-chs": "最近5分鐘的CPU負載", "xloc": [ - "default.handlebars->25->1421" + "default.handlebars->27->1568" ] }, { @@ -3425,12 +4667,16 @@ "de": "CPU-Auslastung der vergangenen Minute", "en": "CPU load in the last minute", "es": "Carga en el CPU en el ultimo minuto", + "fr": "Charge CPU dans la dernière minute", + "hi": "अंतिम समय में सीपीयू लोड", "ja": "直前のCPU負荷", + "ko": "마지막 순간의 CPU로드", "nl": "CPU-belasting in de laatste minuut", "pt": "Carga da CPU no último minuto", "ru": "Загрузка CPU за последнюю минуту", + "zh-chs": "最後一分鐘的CPU負載", "xloc": [ - "default.handlebars->25->1420" + "default.handlebars->27->1567" ] }, { @@ -3438,13 +4684,17 @@ "de": "CR+LF", "en": "CR+LF", "es": "CR+LF", + "fr": "CR+LF", + "hi": "सीआर + वामो", "ja": "CR + LF", + "ko": "CR + LF", "nl": "CR+LF", - "pt": "CR + LF", + "pt": "CR+LF", "ru": "CR+LF", + "zh-chs": "CR +低頻", "xloc": [ - "default.handlebars->25->635", - "default.handlebars->25->644", + "default.handlebars->27->684", + "default.handlebars->27->693", "default.handlebars->container->column_l->p12->termTable->1->1->6->1->1->terminalSettingsButtons" ] }, @@ -3453,13 +4703,18 @@ "de": "CSV-Format", "en": "CSV Format", "es": "Formato CSV", + "fr": "Format CSV", + "hi": "सीएसवी प्रारूप", "ja": "CSV形式", + "ko": "CSV 형식", "nl": "CSV Formaat", "pt": "Formato CSV", "ru": "Формат CSV", + "zh-chs": "CSV格式", "xloc": [ - "default.handlebars->25->1195", - "default.handlebars->25->1234" + "default.handlebars->27->1325", + "default.handlebars->27->1369", + "default.handlebars->27->390" ] }, { @@ -3468,12 +4723,15 @@ "en": "Call Error", "es": "Error en la Llamada", "fr": "Erreur d'appel", + "hi": "कॉल त्रुटि", "ja": "呼び出しエラー", + "ko": "통화 오류", "nl": "Oproepfout", "pt": "Erro de chamada", "ru": "Ошибка вызова", + "zh-chs": "通話錯誤", "xloc": [ - "default.handlebars->25->1463" + "default.handlebars->27->1615" ] }, { @@ -3482,14 +4740,17 @@ "en": "Cancel", "es": "Cancelar", "fr": "Annuler", + "hi": "रद्द करना", "ja": "キャンセル", + "ko": "취소", "nl": "Annuleren", "pt": "Cancelar", "ru": "Отмена", + "zh-chs": "取消", "xloc": [ - "default-mobile.handlebars->9->41", + "default-mobile.handlebars->9->44", "default-mobile.handlebars->dialog->idx_dlgButtonBar", - "default.handlebars->25->971", + "default.handlebars->27->1076", "default.handlebars->container->dialog->idx_dlgButtonBar", "login-mobile.handlebars->dialog->idx_dlgButtonBar", "login.handlebars->dialog->idx_dlgButtonBar", @@ -3502,12 +4763,16 @@ "de": "Kapazität / Geschwindigkeit", "en": "Capacity / Speed", "es": "Capacidad / Velocidad", + "fr": "Capcité / Vitesse", + "hi": "क्षमता / गति", "ja": "容量/速度", + "ko": "용량 / 속도", "nl": "Capaciteit / snelheid", "pt": "Capacidade / velocidade", "ru": "Объем / Скорость", + "zh-chs": "容量/速度", "xloc": [ - "default.handlebars->25->76" + "default.handlebars->27->787" ] }, { @@ -3515,12 +4780,16 @@ "de": "Katalanisch", "en": "Catalan", "es": "Catalan", + "fr": "catalan", + "hi": "कैटलन", "ja": "カタロニア語", + "ko": "카탈로니아 사람", "nl": "Catalaans", "pt": "Catalão", "ru": "Каталонский", + "zh-chs": "加泰羅尼亞語", "xloc": [ - "default.handlebars->25->753" + "default.handlebars->27->857" ] }, { @@ -3528,13 +4797,16 @@ "de": "Karte hier zentrieren", "en": "Center map here", "es": "Centrar mapa aqui", - "fr": "Centré la carte ici", + "fr": "Centrer la carte ici", + "hi": "केंद्र का नक्शा यहाँ", "ja": "センターマップはこちら", + "ko": "여기 중심지도", "nl": "Centreer kaart hier", "pt": "Centralize o mapa aqui", "ru": "Установить центр карты здесь", + "zh-chs": "中心地圖在這裡", "xloc": [ - "default.handlebars->25->426" + "default.handlebars->27->430" ] }, { @@ -3542,12 +4814,16 @@ "de": "Chamorro", "en": "Chamorro", "es": "Chamorro", + "fr": "Chamorro", + "hi": "चमोर्रो", "ja": "チャモロ", + "ko": "차모로", "nl": "Chamorro", "pt": "Chamorro", "ru": "Чаморро", + "zh-chs": "查莫羅", "xloc": [ - "default.handlebars->25->754" + "default.handlebars->27->858" ] }, { @@ -3555,12 +4831,16 @@ "de": "E-Mail für {0} ändern", "en": "Change Email for {0}", "es": "Cambiar dirección de correo para {0}", + "fr": "Changer l'email pour {0]", + "hi": "{0} के लिए ईमेल बदलें", "ja": "{0}のメールを変更", + "ko": "{0}의 이메일 변경", "nl": "Verander e-mail voor {0}", "pt": "Alterar email para {0}", "ru": "Смена email для {0}", + "zh-chs": "更改{0}的電子郵件", "xloc": [ - "default.handlebars->25->1358" + "default.handlebars->27->1496" ] }, { @@ -3568,14 +4848,18 @@ "de": "Gruppe wechseln", "en": "Change Group", "es": "Cambiar Grupo", + "fr": "Changer de groupe", + "hi": "समूह बदलें", "ja": "グループを変更", + "ko": "그룹 변경", "nl": "verander groep", "pt": "Alterar grupo", "ru": "Смена группы", + "zh-chs": "變更組", "xloc": [ - "default.handlebars->25->501", - "default.handlebars->25->565", - "default.handlebars->25->566" + "default.handlebars->27->508", + "default.handlebars->27->612", + "default.handlebars->27->613" ] }, { @@ -3583,14 +4867,18 @@ "de": "Passwort ändern", "en": "Change Password", "es": "Cambiar contraseña", + "fr": "Changer le mot de passe", + "hi": "पासवर्ड बदलें", "ja": "パスワードを変更する", + "ko": "비밀번호 변경", "nl": "Verander wachtwoord", "pt": "Mudar senha", "ru": "Смена пароля", + "zh-chs": "更改密碼", "xloc": [ - "default-mobile.handlebars->9->49", - "default.handlebars->25->1353", - "default.handlebars->25->947" + "default-mobile.handlebars->9->52", + "default.handlebars->27->1052", + "default.handlebars->27->1489" ] }, { @@ -3598,12 +4886,16 @@ "de": "Passwort für {0} ändern", "en": "Change Password for {0}", "es": "Cambiar contraseña para {0}", + "fr": "Changer le mot de passe pour {0}", + "hi": "{0} के लिए पासवर्ड बदलें", "ja": "{0}のパスワードを変更", + "ko": "{0}의 비밀번호 변경", "nl": "Verander wachtwoord voor {0}", "pt": "Alterar senha para {0}", "ru": "Смена пароля для {0}", + "zh-chs": "更改{0}的密碼", "xloc": [ - "default.handlebars->25->1365" + "default.handlebars->27->1503" ] }, { @@ -3611,10 +4903,14 @@ "de": "E-Mail-Adresse ändern", "en": "Change email address", "es": "Cambiar dirección de correo", + "fr": "Modifier l'adresse mail", + "hi": "ईमेल पता बदलें", "ja": "メールアドレスを変更する", + "ko": "이메일 주소 변경", "nl": "Verander e-mailadres", "pt": "Mude o endereço de email", "ru": "Смена email", + "zh-chs": "更改電子郵件地址", "xloc": [ "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3AccountActions->7->3->changeEmailId->0", "default.handlebars->container->column_l->p2->p2AccountActions->3->p2AccountPassActions->accountChangeEmailAddressSpan->0" @@ -3625,10 +4921,14 @@ "de": "Passwort ändern", "en": "Change password", "es": "Cambiar contraseña", + "fr": "Changer le mot de passe", + "hi": "पासवर्ड बदलें", "ja": "パスワードを変更する", + "ko": "비밀번호 변경", "nl": "Verander wachtwoord", "pt": "Mudar senha", "ru": "Смена пароля", + "zh-chs": "更改密碼", "xloc": [ "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3AccountActions->7->5->0", "default.handlebars->container->column_l->p2->p2AccountActions->3->p2AccountPassActions->3" @@ -3639,23 +4939,47 @@ "de": "Das JavaScript-Codemodul des Agenten wechseln", "en": "Change the agent Java Script code module", "es": "Cambiar el módulo de código de Java Script del Agente", + "fr": "Changer le code Java Script de l'agent", + "hi": "एजेंट जावा स्क्रिप्ट कोड मॉड्यूल बदलें", "ja": "エージェントのJava Scriptコードモジュールを変更する", + "ko": "에이전트 Java 스크립트 코드 모듈 변경", "nl": "Wijzig de Javascript code module van de agent", "pt": "Alterar o módulo de código Java Script do agente", "ru": "Изменить модуль кода Java Script агента", + "zh-chs": "更改代理Java腳本代碼模塊", "xloc": [ "default.handlebars->container->column_l->p15->consoleTable->1->0->1->1" ] }, + { + "cs": "Změňte heslo pro tohoto uživatele", + "de": "Ändern Sie das Passwort für diesen Benutzer", + "en": "Change the password for this user", + "fr": "Changer le mot de passe de cet utilisateur", + "hi": "इस उपयोगकर्ता के लिए पासवर्ड बदलें", + "ja": "このユーザーのパスワードを変更します", + "ko": "이 사용자의 비밀번호 변경", + "nl": "Wijzig het wachtwoord voor deze gebruiker", + "pt": "Alterar a senha para este usuário", + "ru": "Изменить пароль для этого пользователя", + "zh-chs": "更改該用戶的密碼", + "xloc": [ + "default.handlebars->27->1488" + ] + }, { "cs": "Změnit stav napájení vzdáleného stroje", "de": "Den Energiezustand der entfernten Maschine ändern", "en": "Change the power state of the remote machine", "es": "Cambiar el estado de energía de la máquina remota", + "fr": "Allumer/Éteindre la machine distante", + "hi": "रिमोट मशीन की शक्ति स्थिति को बदलें", "ja": "リモートマシンの電源状態を変更する", + "ko": "원격 시스템의 전원 상태 변경", "nl": "Wijzig de stroomstatus van het externe apparaat", "pt": "Alterar o estado de energia da máquina remota", "ru": "Изменить состояние питания удаленного компьютера", + "zh-chs": "更改遠程機器的電源狀態", "xloc": [ "default.handlebars->container->column_l->p11->deskarea0->deskarea1->1" ] @@ -3665,12 +4989,16 @@ "de": "Ändern Sie hier Ihre Konto-E-Mail-Adresse.", "en": "Change your account email address here.", "es": "Cambie la dirección de correo electrónico de su cuenta aquí.", + "fr": "Changer l'adresse email de votre compte ici.", + "hi": "यहां अपना खाता ईमेल पता बदलें।", "ja": "ここでアカウントのメールアドレスを変更します。", + "ko": "여기에서 계정 이메일 주소를 변경하십시오.", "nl": "Wijzig hier het e-mailadres van uw account.", "pt": "Mude o endereço de e-mail da sua conta aqui.", "ru": "Измените адрес электронной почты вашей учетной записи здесь.", + "zh-chs": "在此處更改您的帳戶電子郵件地址。", "xloc": [ - "default.handlebars->25->934" + "default.handlebars->27->1039" ] }, { @@ -3678,12 +5006,16 @@ "de": "Ändern Sie Ihr Kontopasswort, indem Sie das alte und das neue Passwort zweimal in die Felder unten eingeben.", "en": "Change your account password by entering the old password and new password twice in the boxes below.", "es": "Cambie la contraseña de su cuenta ingresando la contraseña anterior y la contraseña nueva dos veces en los sigueintes cuadros.", + "fr": "Changer votre mot de passe en entrant l'actuel puis deux fois le nouveau.", + "hi": "नीचे दिए गए बॉक्स में दो बार पुराने पासवर्ड और नए पासवर्ड को दर्ज करके अपना खाता पासवर्ड बदलें।", "ja": "下のボックスに古いパスワードと新しいパスワードを2回入力して、アカウントのパスワードを変更します。", + "ko": "아래 상자에 기존 비밀번호와 새 비밀번호를 두 번 입력하여 계정 비밀번호를 변경하십시오.", "nl": "Wijzig uw wachtwoord door het invoeren van het oude en het nieuwe wachtwoord twee keer in de vakken hieronder.", "pt": "Altere a senha da sua conta digitando a senha antiga e a nova senha duas vezes nas caixas abaixo.", "ru": "Измените пароль своей учетной записи, введя старый пароль и дважды новый пароль в поля ниже.", + "zh-chs": "在下面的框中兩次輸入舊密碼和新密碼,以更改帳戶密碼。", "xloc": [ - "default.handlebars->25->940" + "default.handlebars->27->1045" ] }, { @@ -3691,12 +5023,16 @@ "de": "Das Ändern der Sprache erfordert eine Aktualisierung der Seite.", "en": "Changing the language will require a refresh of the page.", "es": "Cambiar el idioma requerirá una actualización de la página.", + "fr": "Changer de langue requiert de rafraîchir la page.", + "hi": "भाषा बदलने पर पेज को रिफ्रेश करना होगा।", "ja": "言語を変更するには、ページを更新する必要があります。", + "ko": "언어를 변경하면 페이지를 새로 고쳐야합니다.", "nl": "Als u de taal wilt wijzigen, moet de pagina worden ververst.", "pt": "Alterar o idioma exigirá uma atualização da página.", "ru": "Изменение языка потребует перезагрузить страницу.", + "zh-chs": "更改語言將需要刷新頁面。", "xloc": [ - "default.handlebars->25->919" + "default.handlebars->27->1024" ] }, { @@ -3704,12 +5040,18 @@ "de": "Chat", "en": "Chat", "es": "Chat", + "fr": "Discussion instantanée", + "hi": "चैट", "ja": "チャット", + "ko": "잡담", "nl": "Chat", "pt": "Chat", "ru": "Чат", + "zh-chs": "聊天室", "xloc": [ - "default.handlebars->25->1212" + "default.handlebars->27->1342", + "default.handlebars->27->554", + "default.handlebars->27->573" ] }, { @@ -3717,15 +5059,19 @@ "de": "Chat & Benachrichtigen", "en": "Chat & Notify", "es": "Chatear y Notificar", + "fr": "Discussion instantanée et notification", + "hi": "चैट करें और सूचित करें", "ja": "チャットと通知", + "ko": "채팅 및 알림", "nl": "Chat & Melden", "pt": "Chat & Notificação", "ru": "Чаты и уведомления", + "zh-chs": "聊天並通知", "xloc": [ - "default-mobile.handlebars->9->307", - "default-mobile.handlebars->9->325", - "default.handlebars->25->1106", - "default.handlebars->25->1129" + "default-mobile.handlebars->9->311", + "default-mobile.handlebars->9->329", + "default.handlebars->27->1214", + "default.handlebars->27->1242" ] }, { @@ -3733,12 +5079,16 @@ "de": "Tschetschenisch", "en": "Chechen", "es": "Checheno", + "fr": "Tchétchène", + "hi": "चेचन", "ja": "チェチェン", + "ko": "체첸", "nl": "Tsjetsjeense", "pt": "Checheno", "ru": "Чеченский", + "zh-chs": "車臣", "xloc": [ - "default.handlebars->25->755" + "default.handlebars->27->859" ] }, { @@ -3746,12 +5096,16 @@ "de": "Haken setzen und OK klicken, um das Fehlerprotokoll zu löschen.", "en": "Check and click OK to clear error log.", "es": "Verifique y haga clic en Aceptar para borrar el registro de errores.", + "fr": "Cocher la case et cliquer sur OK pour nettoyer les journaux d'erreurs", + "hi": "जाँचें और त्रुटि लॉग को साफ़ करने के लिए ठीक क्लिक करें।", "ja": "チェックして[OK]をクリックし、エラーログをクリアします。", + "ko": "확인을 클릭하고 오류 로그를 지우십시오.", "nl": "Controleer en klik op OK om het foutenlogboek te wissen.", "pt": "Verifique e clique em OK para limpar o log de erros.", "ru": "Установите флажок и нажмите ОК для очищения журнала ошибок.", + "zh-chs": "檢查並單擊確定以清除錯誤日誌。", "xloc": [ - "default.handlebars->25->119" + "default.handlebars->27->102" ] }, { @@ -3759,12 +5113,16 @@ "de": "Haken setzen und OK klicken, um die Server-Selbstaktualisierung zu starten.", "en": "Check and click OK to start server self-update.", "es": "Marque y haga clic en Aceptar para iniciar la actualización automática del servidor.", + "fr": "Cocher la case et cliquer sur OK pour activer les mises à jour automatiques du serveur.", + "hi": "सर्वर सेल्फ-अपडेट शुरू करने के लिए चेक और ओके पर क्लिक करें।", "ja": "チェックして[OK]をクリックし、サーバーの自己更新を開始します。", + "ko": "확인을 클릭하고 확인을 클릭하여 서버 자체 업데이트를 시작하십시오.", "nl": "Controleer en klik op OK om de serverupdate te starten.", "pt": "Marque e clique em OK para iniciar a atualização automática do servidor.", "ru": "Установите флажок и нажмите ОК для начала самообновления.", + "zh-chs": "檢查並單擊確定以開始服務器自我更新。", "xloc": [ - "default.handlebars->25->114" + "default.handlebars->27->97" ] }, { @@ -3772,10 +5130,14 @@ "de": "Server auf Aktualisierung überprüfen", "en": "Check server version", "es": "Verifique la versión del servidor", + "fr": "Vérifier la version de meshcentral", + "hi": "सर्वर संस्करण की जाँच करें", "ja": "サーバーのバージョンを確認する", + "ko": "서버 버전 확인", "nl": "Controleer server versie", "pt": "Verifique a versão do servidor", "ru": "Проверить наличие обновлений", + "zh-chs": "檢查服務器版本", "xloc": [ "default.handlebars->container->column_l->p6->p2ServerActions->3->p2ServerActionsVersion->0" ] @@ -3785,13 +5147,17 @@ "de": "Überprüfen...", "en": "Checking...", "es": "Comprobando...", + "fr": "Vérification ...", + "hi": "जांच रहा है ...", "ja": "確認しています...", + "ko": "확인 중...", "nl": "Controleren...", "pt": "Verificando ...", "ru": "Проверка...", + "zh-chs": "檢查...", "xloc": [ - "default.handlebars->25->1459", - "default.handlebars->25->721" + "default.handlebars->27->1609", + "default.handlebars->27->825" ] }, { @@ -3799,60 +5165,94 @@ "de": "Chinesisch", "en": "Chinese", "es": "Chino", + "fr": "Chinois", + "hi": "चीनी", "ja": "中国語", + "ko": "중국말", "nl": "Chinees", "pt": "Chinês", "ru": "Китайский", + "zh-chs": "中文", "xloc": [ - "default.handlebars->25->756" + "default.handlebars->27->860" ] }, { "cs": "čínština (Hong Kong)", "de": "Chinesisch (Hong Kong)", "en": "Chinese (Hong Kong)", + "fr": "Chinois (Hong Kong)", + "hi": "चीनी (हांगकांग)", "ja": "中国語(香港)", + "ko": "중국어 (홍콩)", "nl": "Chinees (Hong Kong)", "pt": "Chinês (Hong Kong)", "ru": "Китайский (Гонконг)", + "zh-chs": "中文(香港)", "xloc": [ - "default.handlebars->25->757" + "default.handlebars->27->861" ] }, { "cs": "čínština (PRC)", "de": "Chinesisch (VR China)", "en": "Chinese (PRC)", + "fr": "Chinois (continental)", + "hi": "चीनी (PRC)", "ja": "中国語(PRC)", + "ko": "중국어 (PRC)", "nl": "Chinees (PRC)", "pt": "Chinês (PRC)", "ru": "Китайский (КНР)", + "zh-chs": "中文(中國)", "xloc": [ - "default.handlebars->25->758" + "default.handlebars->27->862" + ] + }, + { + "cs": "Zjednodušená čínština)", + "de": "Vereinfachtes Chinesisch", + "en": "Chinese (Simplified)", + "fr": "Chinois simplifié)", + "ja": "中国語(簡体字)", + "nl": "Chinees (Vereenvoudigd)", + "pt": "Chinês (simplificado)", + "ru": "Упрощенный китайский)", + "zh-chs": "简体中文)", + "xloc": [ + "default.handlebars->27->1022" ] }, { "cs": "čínština (Singapur)", "de": "Chinesisch (Singapur)", "en": "Chinese (Singapore)", + "fr": "Chinois (Singapore)", + "hi": "चीनी (सिंगापुर)", "ja": "中国語(シンガポール)", + "ko": "중국어 (싱가포르)", "nl": "Chinees (Singapore)", "pt": "Chinês (Singapura)", "ru": "Китайский (Сингапур)", + "zh-chs": "中文(新加坡)", "xloc": [ - "default.handlebars->25->759" + "default.handlebars->27->863" ] }, { "cs": "čínština (Taiwan)", "de": "Chinesisch (Taiwan)", "en": "Chinese (Taiwan)", + "fr": "Chinois (Taiwan)", + "hi": "चीनी (ताइवान)", "ja": "中国語(台湾)", + "ko": "중국어 (대만)", "nl": "Chinees (Taiwan)", "pt": "Chinês (Taiwan)", "ru": "Китайский (Тайвань)", + "zh-chs": "中文(台灣)", "xloc": [ - "default.handlebars->25->760" + "default.handlebars->27->864" ] }, { @@ -3860,25 +5260,33 @@ "de": "ChromeOS", "en": "ChromeOS", "es": "ChromeOS", + "fr": "ChromeOS", + "hi": "क्रोम ओएस", "ja": "ChromeOS", + "ko": "ChromeOS", "nl": "ChromeOS", "pt": "ChromeOS", "ru": "ChromeOS", + "zh-chs": "ChromeOS", "xloc": [ - "default-mobile.handlebars->9->160", - "default.handlebars->25->30" + "default-mobile.handlebars->9->164", + "default.handlebars->27->30" ] }, { "cs": "čuvaština", "de": "Tschuwaschisch", "en": "Chuvash", + "fr": "Tchouvache", + "hi": "चूवाश", "ja": "チュヴァシュ", + "ko": "추 바시", "nl": "Chuvash", "pt": "Chuvash", "ru": "Чувашский", + "zh-chs": "楚瓦什", "xloc": [ - "default.handlebars->25->761" + "default.handlebars->27->865" ] }, { @@ -3886,12 +5294,16 @@ "de": "CIRA bereinigen", "en": "Cleanup CIRA", "es": "Limpiar CIRA", + "fr": "Nettoyage CIRA", + "hi": "क्लीनअप CIRA", "ja": "CIRAのクリーンアップ", + "ko": "CIRA 정리", "nl": "Opruimen CIRA", "pt": "Limpeza CIRA", "ru": "Очистка CIRA", + "zh-chs": "清理CIRA", "xloc": [ - "default.handlebars->25->264" + "default.handlebars->27->248" ] }, { @@ -3899,22 +5311,26 @@ "de": "Leeren", "en": "Clear", "es": "Borrar", + "fr": "Nettoyer", + "hi": "स्पष्ट", "ja": "クリア", + "ko": "명확한", "nl": "Wissen", "pt": "Limpo", "ru": "Очистить", + "zh-chs": "明確", "xloc": [ - "default-mobile.handlebars->9->262", - "default-mobile.handlebars->9->264", "default-mobile.handlebars->9->266", "default-mobile.handlebars->9->268", + "default-mobile.handlebars->9->270", + "default-mobile.handlebars->9->272", "default-mobile.handlebars->9->28", - "default-mobile.handlebars->9->91", - "default.handlebars->25->1189", - "default.handlebars->25->670", - "default.handlebars->25->672", - "default.handlebars->25->674", - "default.handlebars->25->676", + "default-mobile.handlebars->9->94", + "default.handlebars->27->1319", + "default.handlebars->27->719", + "default.handlebars->27->721", + "default.handlebars->27->723", + "default.handlebars->27->725", "default.handlebars->container->column_l->p15->consoleTable->1->6->1->1->1->0->7", "default.handlebars->container->column_l->p41->3->1", "messenger.handlebars->xbottom" @@ -3925,12 +5341,16 @@ "de": "Token löschen", "en": "Clear Tokens", "es": "Borrar Tokens", + "fr": "Nettoyer les jetons", + "hi": "स्पष्ट टोकन", "ja": "クリアトークン", + "ko": "클리어 토큰", "nl": "Wis Tokens", "pt": "Limpar Tokens", "ru": "Очистить токены", + "zh-chs": "清除令牌", "xloc": [ - "default.handlebars->25->136" + "default.handlebars->27->119" ] }, { @@ -3938,12 +5358,16 @@ "de": "Den Kern löschen", "en": "Clear the core", "es": "Inicializar", + "fr": "Nettoyer le coeur", + "hi": "कोर साफ़ करें", "ja": "コアをクリアする", + "ko": "핵심을 지우십시오", "nl": "Maak de kern leeg", "pt": "Limpe o núcleo", "ru": "Очистить ядро", + "zh-chs": "清除核心", "xloc": [ - "default.handlebars->25->702" + "default.handlebars->27->803" ] }, { @@ -3951,12 +5375,55 @@ "de": "Löschen Sie das Geheimnis aus der Anwendung und versuchen Sie es erneut.Sie haben nur wenige Minuten Zeit, um den richtigen Code einzugeben.", "en": "Clear the secret from the application and try again. You only have a few minutes to enter the proper code.", "es": "Borre el secreto de la aplicación e intente nuevamente. Solo tiene unos minutos para ingresar el código adecuado.", + "fr": "Supprimez la phrase secrète de l'application et réessayez. Vous disposez de quelques minutes pour saisir le bon code.", + "hi": "एप्लिकेशन से रहस्य साफ़ करें और पुनः प्रयास करें। आपके पास उचित कोड दर्ज करने के लिए केवल कुछ मिनट हैं।", "ja": "アプリケーションから秘密をクリアして、再試行してください。適切なコードを入力するのに数分しかかかりません。", + "ko": "응용 프로그램에서 비밀을 지우고 다시 시도하십시오. 올바른 코드를 입력하는 데 몇 분 밖에 걸리지 않습니다.", "nl": "Wis het geheim van de applicatie en probeer het opnieuw. Je hebt maar een paar minuten om de juiste code in te voeren.", "pt": "Limpe o segredo do aplicativo e tente novamente. Você tem apenas alguns minutos para inserir o código correto.", "ru": "Удалите ключ из приложения и попробуйте еще раз. У вас есть всего несколько минут, чтобы ввести правильный код.", + "zh-chs": "從應用程序中清除機密,然後重試。您只有幾分鐘的時間來輸入正確的代碼。", "xloc": [ - "default.handlebars->25->126" + "default.handlebars->27->109" + ] + }, + { + "cs": "Zrušte toto oznámení", + "de": "Löschen Sie diese Benachrichtigung", + "en": "Clear this notification", + "fr": "Effacez cette notification", + "ja": "この通知をクリア", + "nl": "Wis deze melding", + "ru": "Очистить это уведомление", + "zh-chs": "清除此通知", + "xloc": [ + "default.handlebars->27->1539" + ] + }, + { + "cs": "Kliknutím sem stáhnete MeshAgent pro Apple OSX.", + "de": "Klicken Sie hier, um den MeshAgent für Apple OSX herunterzuladen.", + "en": "Click here to download the MeshAgent for Apple OSX.", + "fr": "Cliquez ici pour télécharger le MeshAgent pour Apple OSX.", + "nl": "Klik hier om de MeshAgent te downloaden voor Apple OSX.", + "ja": "ここをクリックして、Apple OSX用のMeshAgentをダウンロードしてください。", + "ru": "Нажмите здесь, чтобы загрузить MeshAgent для Apple OSX.", + "zh-chs": "单击此处下载适用于Apple OSX的MeshAgent。", + "xloc": [ + "mesh-invite.html->2->11->1->0" + ] + }, + { + "cs": "Kliknutím sem stáhnete MeshAgent pro Windows.", + "de": "Klicken Sie hier, um den MeshAgent für Windows herunterzuladen.", + "en": "Click here to download the MeshAgent for Windows.", + "fr": "Cliquez ici pour télécharger le MeshAgent pour Windows.", + "nl": "Klik hier om de MeshAgent te downloaden voor Windows.", + "ja": "Windows用のMeshAgentをダウンロードするには、ここをクリックしてください。", + "ru": "Нажмите здесь, чтобы загрузить MeshAgent для Windows.", + "zh-chs": "单击此处下载适用于Windows的MeshAgent。", + "xloc": [ + "mesh-invite.html->2->9->1->1" ] }, { @@ -3964,12 +5431,42 @@ "de": "Hier klicken, um den serverseitigen Gerätenamen zu bearbeiten", "en": "Click here to edit the server-side device name", "es": "Haga clic aquí para editar el nombre del dispositivo del lado del servidor", + "fr": "Cliquez ici pour modifier le nom de l'appareil sur le serveur", + "hi": "सर्वर-साइड डिवाइस का नाम संपादित करने के लिए यहां क्लिक करें", "ja": "サーバー側のデバイス名を編集するにはここをクリックしてください", + "ko": "서버 측 장치 이름을 편집하려면 여기를 클릭하십시오", "nl": "Klik hier om de apparaatnaam van de server te bewerken", "pt": "clique aqui para criar um grupo de dispositivos", "ru": "Для изменения имени устройства на сервере нажмите сюда", + "zh-chs": "單擊此處編輯服務器端設備名稱", "xloc": [ - "default.handlebars->25->440" + "default.handlebars->27->444" + ] + }, + { + "cs": "Kliknutím sem obnovíte heslo svého účtu.", + "de": "Klicken Sie hier, um Ihr Kontopasswort zurückzusetzen.", + "en": "Click here to reset your account password.", + "fr": "Cliquez ici pour réinitialiser le mot de passe de votre compte.", + "nl": "Klik hier om je wachtwoord opnieuw in te stellen.", + "ja": "ここをクリックしてアカウントのパスワードをリセットしてください。", + "ru": "Нажмите здесь, чтобы сбросить пароль учетной записи.", + "zh-chs": "单击此处重置您的帐户密码。", + "xloc": [ + "account-reset.html->2->5->1" + ] + }, + { + "cs": "Kliknutím sem ověřte svou e-mailovou adresu.", + "de": "Klicken Sie hier, um Ihre E-Mail-Adresse zu bestätigen.", + "en": "Click here to verify your e-mail address.", + "fr": "Cliquez ici pour vérifier votre adresse e-mail.", + "nl": "Klik hier om uw e-mailadres te verifiëren.", + "ja": "ここをクリックして、電子メールアドレスを確認してください。", + "ru": "Нажмите здесь, чтобы подтвердить свой адрес электронной почты.", + "zh-chs": "单击此处以验证您的电子邮件地址。", + "xloc": [ + "account-check.html->2->5->1" ] }, { @@ -3977,13 +5474,17 @@ "de": "Auf OK klicken, um eine Bestätigungsmail an folgende Adresse zu senden:", "en": "Click ok to send a verification mail to:", "es": "Haga clic en Aceptar para enviar un correo de verificación a:", + "fr": "Envoyer un mail de confirmation à :", + "hi": "सत्यापन मेल भेजने के लिए ठीक क्लिक करें:", "ja": "[OK]をクリックして確認メールを送信します:", + "ko": "확인 메일을 보내려면 확인을 클릭하십시오.", "nl": "Klik op OK om een verificatiebericht te sturen naar:", "pt": "Clique em ok para enviar um email de verificação para:", "ru": "Нажмите ОК для отправки подтверждения по электронной почте:", + "zh-chs": "單擊確定將驗證郵件發送到:", "xloc": [ - "default-mobile.handlebars->9->34", - "default.handlebars->25->931" + "default-mobile.handlebars->9->37", + "default.handlebars->27->1036" ] }, { @@ -3991,26 +5492,51 @@ "de": "Hier klicken, um aktuelle Benachrichtigungen anzuzeigen", "en": "Click to view current notifications", "es": "Haga clic para ver las notificaciones actuales", + "fr": "Voir les dernières notifications", + "hi": "करेंट नोटिफिकेशन देखने के लिए क्लिक करें", "ja": "クリックして現在の通知を表示します", + "ko": "현재 알림을 보려면 클릭", "nl": "Klik om de huidige meldingen te bekijken", "pt": "Clique para visualizar as notificações atuais", "ru": "Нажмите для просмотра текущий уведомлений", + "zh-chs": "點擊查看當前通知", "xloc": [ "default.handlebars->container->masthead->7" ] }, + { + "cs": "Client Control Mode (CCM)", + "de": "Client Control Mode (CCM)", + "en": "Client Control Mode (CCM)", + "es": "Client Control Mode (CCM)", + "fr": "Client Control Mode (CCM)", + "hi": "ग्राहक नियंत्रण मोड (CCM)", + "ja": "クライアント制御モード(CCM)", + "ko": "클라이언트 제어 모드 (CCM)", + "nl": "Client Control Mode (CCM)", + "pt": "Client Control Mode (CCM)", + "ru": "Режим управления клиентом (CCM)", + "zh-chs": "客戶端控制模式(CCM)", + "xloc": [ + "default.handlebars->27->767" + ] + }, { "cs": "Vzdálený přístup iniciováný klientem", "de": "Client Initiated Remote Access", "en": "Client Initiated Remote Access", "es": "Acceso Remoto Iniciado por el Cliente (CIRA)", + "fr": "Accès distant démaré", + "hi": "क्लाइंट ने रिमोट एक्सेस की शुरुआत की", "ja": "クライアントが開始したリモートアクセス", + "ko": "클라이언트 시작 원격 액세스", "nl": "Gebruiker geïnitieerde externe toegang", "pt": "Acesso remoto iniciado pelo cliente", "ru": "Клиент инициировал удаленный доступ", + "zh-chs": "客戶端啟動的遠程訪問", "xloc": [ - "default.handlebars->25->1050", - "default.handlebars->25->1055" + "default.handlebars->27->1154", + "default.handlebars->27->1159" ] }, { @@ -4018,10 +5544,14 @@ "de": "Zwischenablage", "en": "Clipboard", "es": "Portapapeles", + "fr": "Presse-papiers", + "hi": "क्लिपबोर्ड", "ja": "クリップボード", + "ko": "클립 보드", "nl": "Klembord", "pt": "Área de transferência", "ru": "Буфер обмена", + "zh-chs": "剪貼板", "xloc": [ "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3" ] @@ -4031,15 +5561,19 @@ "de": "Schließen", "en": "Close", "es": "Cerrar", + "fr": "Fermer", + "hi": "बंद करे", "ja": "閉じる", + "ko": "닫기", "nl": "Sluiten", "pt": "Fechar", "ru": "Закрыть", + "zh-chs": "關", "xloc": [ "default-mobile.handlebars->9->26", - "default.handlebars->25->134", - "default.handlebars->25->142", - "default.handlebars->25->628" + "default.handlebars->27->117", + "default.handlebars->27->125", + "default.handlebars->27->677" ] }, { @@ -4047,10 +5581,14 @@ "de": "Spalten", "en": "Columns", "es": "Columnas", + "fr": "Colonnes", + "hi": "कॉलम", "ja": "列", + "ko": "열", "nl": "kolommen", "pt": "Colunas", "ru": "Колонки", + "zh-chs": "列", "xloc": [ "default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->9->devListToolbarView->viewselect->1", "default.handlebars->container->column_l->p1->p1title->devListToolbarViewIcons" @@ -4061,11 +5599,33 @@ "de": "Gemeinsame Gerätegruppen", "en": "Common Device Groups", "es": "Grupos de Dispositivos Comunes", + "fr": "Groupes d'appareils", + "hi": "सामान्य उपकरण समूह", + "ja": "共通デバイスグループ", + "ko": "공통 장치 그룹", "nl": "Gemeenschappelijke apparaatgroepen", + "pt": "Grupos de dispositivos comuns", "ru": "Общие группы устройств", + "zh-chs": "通用設備組", "xloc": [ - "default.handlebars->25->1294", - "default.handlebars->25->1368" + "default.handlebars->27->1430", + "default.handlebars->27->1513" + ] + }, + { + "cs": "Společná zařízení", + "de": "Allgemeine Geräte", + "en": "Common Devices", + "fr": "Périphériques communs", + "hi": "आम उपकरण", + "ja": "共通デバイス", + "ko": "공통 장치", + "nl": "Gemeenschappelijke apparaten", + "pt": "Dispositivos comuns", + "ru": "Общие устройства", + "zh-chs": "通用設備", + "xloc": [ + "default.handlebars->27->1507" ] }, { @@ -4073,13 +5633,17 @@ "de": "Bestätigen Sie das {0} von {1} Einträgen{2} an diesen Ort?", "en": "Confim {0} of {1} entrie{2} to this location?", "es": "¿Confirma {0} de {1} entrada {2} a esta ubicación?", + "fr": "Confim {0} de {1} entrée {2} à cet emplacement?", + "hi": "{1} के {0} की पुष्टि करें {2} इस स्थान पर?", "ja": "{1}エントリ{2}のうち{0}をこの場所に拘束しますか?", + "ko": "이 위치로 {1} entrie {2}의 {0}을 (를) 확인 하시겠습니까?", "nl": "Bevestig {0} van {1} bestand {2} naar deze locatie?", "pt": "Confirme {0} da {1} entrada {2} para este local?", "ru": "Подтвердить {0} из {1} записей в это расположение?", + "zh-chs": "將{1}入口{2}中的{0}限製到此位置?", "xloc": [ - "default-mobile.handlebars->9->86", - "default.handlebars->25->1184" + "default-mobile.handlebars->9->89", + "default.handlebars->27->1314" ] }, { @@ -4087,18 +5651,22 @@ "de": "Bestätigen", "en": "Confirm", "es": "Confirme", + "fr": "Confirmer", + "hi": "पुष्टि करें", "ja": "確認する", + "ko": "확인", "nl": "Bevestig", "pt": "Confirme", "ru": "Подтвердить", + "zh-chs": "確認", "xloc": [ - "default-mobile.handlebars->9->220", - "default-mobile.handlebars->9->287", - "default.handlebars->25->1064", - "default.handlebars->25->1309", - "default.handlebars->25->396", - "default.handlebars->25->560", - "default.handlebars->25->569" + "default-mobile.handlebars->9->224", + "default-mobile.handlebars->9->291", + "default.handlebars->27->1168", + "default.handlebars->27->1442", + "default.handlebars->27->387", + "default.handlebars->27->607", + "default.handlebars->27->616" ] }, { @@ -4106,13 +5674,17 @@ "de": "Bestätigen Sie das Kopieren von 1 Eintrag an diesen Ort?", "en": "Confirm copy of 1 entrie to this location?", "es": "¿Confirme copia de una entrada a esta ubicación?", + "fr": "Confirmer la copie de 1 entrée à cet emplacement?", + "hi": "इस स्थान पर 1 एन्ट्री की प्रतिलिपि की पुष्टि करें?", "ja": "この場所への1つのエントリのコピーを確認しますか?", + "ko": "이 위치에 1 개의 엔트리 사본을 확인 하시겠습니까?", "nl": "Bevestig kopiëren van 1 bestand naar deze locatie?", "pt": "Confirmar cópia de 1 entrada para este local?", "ru": "Подтвердить копирование 1 записи в это расположение?", + "zh-chs": "確認將1個副本複製到此位置?", "xloc": [ - "default-mobile.handlebars->9->257", - "default.handlebars->25->665" + "default-mobile.handlebars->9->261", + "default.handlebars->27->714" ] }, { @@ -4120,13 +5692,17 @@ "de": "Bestätigen Sie das Kopieren von {0} Einträgen an diesen Ort?", "en": "Confirm copy of {0} entries's to this location?", "es": "¿Confirme copia de {1} entradas a esta ubicación?", + "fr": "Confirmer la copie de {0} entrées à cet emplacement?", + "hi": "इस स्थान पर {0} प्रविष्टियों की प्रतिलिपि की पुष्टि करें?", "ja": "{0}エントリのコピーをこの場所に確認しますか?", + "ko": "이 위치에 {0} 항목의 사본을 확인 하시겠습니까?", "nl": "Bevestig kopiëren van {0} bestanden naar deze locatie?", "pt": "Confirmar cópia de {0} entradas para este local?", "ru": "Подтвердить копирование {0} записей в это расположение?", + "zh-chs": "確認{0}個條目的副本到此位置?", "xloc": [ - "default-mobile.handlebars->9->256", - "default.handlebars->25->664" + "default-mobile.handlebars->9->260", + "default.handlebars->27->713" ] }, { @@ -4134,12 +5710,32 @@ "de": "Bestätigen Sie das Löschen der ausgewählten Geräte?", "en": "Confirm delete selected devices(s)?", "es": "¿Eliminar dispositivos seleccionados?", + "fr": "Supprimer les appareils sélectionnés ?", + "hi": "चयनित उपकरणों को हटाने की पुष्टि करें?", "ja": "選択したデバイスの削除を確認しますか?", + "ko": "선택한 장치를 삭제 하시겠습니까?", "nl": "Bevestig geselecteerde apparaten verwijderen?", "pt": "Confirmar a exclusão dos dispositivos selecionados?", "ru": "Подтвердить удаление выбранных устройств?", + "zh-chs": "確認刪除所選設備?", "xloc": [ - "default.handlebars->25->395" + "default.handlebars->27->386" + ] + }, + { + "cs": "Potvrdit odstranění uživatele {0}?", + "de": "Löschen von Benutzer {0} bestätigen?", + "en": "Confirm deletion of user {0}?", + "fr": "Confirmer la suppression de l'utilisateur {0}?", + "hi": "उपयोगकर्ता को हटाने की पुष्टि करें {0}?", + "ja": "ユーザー{0}の削除を確認しますか?", + "ko": "사용자 {0}의 삭제를 확인 하시겠습니까?", + "nl": "Verwijdering van gebruiker {0} bevestigen?", + "pt": "Confirmar exclusão do usuário {0}?", + "ru": "Подтвердить удаление пользователя {0}?", + "zh-chs": "確認刪除用戶{0}?", + "xloc": [ + "default.handlebars->27->1505" ] }, { @@ -4147,13 +5743,17 @@ "de": "Bestätigen Sie das Verschieben von 1 Eintrag an diesen Ort?", "en": "Confirm move of 1 entrie to this location?", "es": "¿Confirme el movimiento de 1 entrada a esta ubicación?", + "fr": "Confirmer le déplacement de 1 entrée vers cet emplacement?", + "hi": "इस स्थान पर 1 एंट्री की पुष्टि करें?", "ja": "1エントリのこの場所への移動を確認しますか?", + "ko": "이 위치로 1 개의 입구를 이동 했습니까?", "nl": "Verplaatsing van 1 bestand naar deze locatie bevestigen?", "pt": "Confirmar a movimentação de 1 entrada para este local?", "ru": "Подтвердить перемещение 1 записи в это расположение?", + "zh-chs": "確認將1個入口移動到此位置?", "xloc": [ - "default-mobile.handlebars->9->259", - "default.handlebars->25->667" + "default-mobile.handlebars->9->263", + "default.handlebars->27->716" ] }, { @@ -4161,13 +5761,17 @@ "de": "Bestätigen Sie das Verschieben von {0} Einträgen an diesen Ort?", "en": "Confirm move of {0} entries's to this location?", "es": "¿Confirme el movimiento de {1} entradas a esta ubicación?", + "fr": "Confirmer le déplacement de {0} entrées vers cet emplacement?", + "hi": "इस स्थान पर {0} प्रविष्टियों की पुष्टि करें?", "ja": "{0}エントリのこの場所への移動を確認しますか?", + "ko": "{0} 항목이이 위치로 이동 했습니까?", "nl": "Verplaatsing van {0} bestanden naar deze locatie bevestigen?", "pt": "Confirmar a movimentação de {0} entradas para este local?", "ru": "Подтвердить перемещение {0} записей в это расположение?", + "zh-chs": "確認將{0}個條目移到此位置?", "xloc": [ - "default-mobile.handlebars->9->258", - "default.handlebars->25->666" + "default-mobile.handlebars->9->262", + "default.handlebars->27->715" ] }, { @@ -4175,11 +5779,16 @@ "de": "Bestätigen Sie das Überschreiben?", "en": "Confirm overwrite?", "es": "¿Sobrescribir?", + "fr": "Ecraser ?", + "hi": "ओवरराइट करने की पुष्टि करें?", "ja": "上書きを確認しますか?", + "ko": "덮어 쓰기를 확인 하시겠습니까?", "nl": "Bevestig overschrijven?", + "pt": "Confirmar substituição?", "ru": "Подтвердить перезапись?", + "zh-chs": "確認覆蓋?", "xloc": [ - "default.handlebars->25->1183" + "default.handlebars->27->1313" ] }, { @@ -4187,13 +5796,17 @@ "de": "Bestätigen Sie das Entfernen der Zweifaktor-Anmeldung mittels Authentifikator-Applikation?", "en": "Confirm removal of authenticator application 2-step login?", "es": "¿Eliminar el inicio de sesión usando autenticación de 2 pasos?", + "fr": "Confirmer la suppression de l'authentification à double facteur?", + "hi": "प्रामाणिकता एप्लिकेशन 2-चरण लॉगिन को हटाने की पुष्टि करें?", "ja": "認証アプリケーションの削除2段階ログインを確認しますか?", + "ko": "인증 자 애플리케이션 2 단계 로그인 제거를 확인 하시겠습니까?", "nl": "Bevestig de verwijdering van de Tweestapsverificatie applicatie?", "pt": "Confirmar remoção do login do aplicativo autenticador em duas etapas?", "ru": "Подтвердить удаление приложения аутентификации двухэтапного входа в систему?", + "zh-chs": "確認刪除身份驗證器應用程序兩步登錄?", "xloc": [ - "default-mobile.handlebars->9->33", - "default.handlebars->25->711" + "default-mobile.handlebars->9->36", + "default.handlebars->27->815" ] }, { @@ -4201,11 +5814,30 @@ "de": "Bestätigen Sie das Löschen der Gerätegruppe {0}?", "en": "Confirm removal of device group {0}?", "es": "¿Eliminar el grupo de dispositivos {0}?", + "fr": "Êtes vous sûr de vouloir supprimer le groupe d'appareils {0}?", + "hi": "डिवाइस समूह {0} को हटाने की पुष्टि करें?", + "ja": "デバイスグループ{0}の削除を確認しますか?", + "ko": "장치 그룹 {0}의 제거를 확인 하시겠습니까?", "nl": "Bevestig het verwijderen van de apparaatgroep {0}?", + "pt": "Confirmar remoção do grupo de dispositivos {0}?", "ru": "Подтвердить удаление группы устройств {0}?", + "zh-chs": "確認刪除設備組{0}?", "xloc": [ - "default.handlebars->25->1304", - "default.handlebars->25->1388" + "default.handlebars->27->1437", + "default.handlebars->27->1534" + ] + }, + { + "cs": "Potvrdit odebrání zařízení {0}?", + "de": "Entfernen des Geräts {0} bestätigen?", + "en": "Confirm removal of device {0}?", + "fr": "Confirmer la suppression de l'appareil {0}?", + "ja": "デバイス{0}の削除を確認しますか?", + "nl": "Bevestig het verwijderen van apparaat {0}?", + "ru": "Подтвердите удаление устройства {0}?", + "zh-chs": "确认移除设备{0}?", + "xloc": [ + "default.handlebars->27->1525" ] }, { @@ -4213,10 +5845,16 @@ "de": "Bestätigen Sie das Löschen der Gruppe {0}?", "en": "Confirm removal of group {0}?", "es": "¿Eliminar el grupo {0}?", + "fr": "Êtes vous sûr de vouloir supprimer le groupe {0}?", + "hi": "समूह {0} को हटाने की पुष्टि करें?", + "ja": "グループ{0}の削除を確認しますか?", + "ko": "그룹 {0}의 제거를 확인 하시겠습니까?", "nl": "Bevestig het verwijderen van de groep {0}?", + "pt": "Confirmar remoção do grupo {0}?", "ru": "Подтвердить удаление группы {0}?", + "zh-chs": "確認刪除組{0}?", "xloc": [ - "default.handlebars->25->1384" + "default.handlebars->27->1530" ] }, { @@ -4224,14 +5862,19 @@ "de": "Bestätigen Sie das Entfernen des Benutzers {0}?", "en": "Confirm removal of user {0}?", "es": "¿Eliminae el usuario {0}?", + "fr": "Supprimer l'utilisateur {0} ?", + "hi": "उपयोगकर्ता को हटाने की पुष्टि {0}?", "ja": "ユーザー{0}の削除を確認しますか?", + "ko": "사용자 {0}의 제거를 확인 하시겠습니까?", "nl": "Bevestig de verwijdering van gebruiker {0}?", "pt": "Confirmar remoção do usuário {0}?", "ru": "Подтвердить удаление пользователя {0}?", + "zh-chs": "確認刪除用戶{0}?", "xloc": [ - "default-mobile.handlebars->9->333", - "default.handlebars->25->1138", - "default.handlebars->25->1312" + "default-mobile.handlebars->9->337", + "default.handlebars->27->1251", + "default.handlebars->27->1445", + "default.handlebars->27->1527" ] }, { @@ -4239,16 +5882,20 @@ "de": "Verbinden", "en": "Connect", "es": "Conectar", + "fr": "Se connecter", + "hi": "जुडिये", "ja": "つなぐ", + "ko": "잇다", "nl": "Verbinden", "pt": "Conectar", "ru": "Подключиться", + "zh-chs": "連接", "xloc": [ - "default-mobile.handlebars->9->236", + "default-mobile.handlebars->9->240", "default-mobile.handlebars->container->page_content->column_l->p10->p10desktop->deskarea1->1->3", "default-mobile.handlebars->container->page_content->column_l->p10->p10files->p13toolbar->1->0->1->3", - "default.handlebars->25->1002", - "default.handlebars->25->647", + "default.handlebars->27->1107", + "default.handlebars->27->696", "default.handlebars->container->column_l->p11->deskarea0->deskarea1->3->connectbutton1span", "default.handlebars->container->column_l->p12->termTable->1->1->0->1->3->connectbutton2span", "default.handlebars->container->column_l->p13->p13toolbar->1->0->1->3", @@ -4260,12 +5907,16 @@ "de": "Alle verbinden", "en": "Connect All", "es": "Conectar con Todos", + "fr": "Se connecter à tous", + "hi": "सभी को कनेक्ट करें", "ja": "すべて接続", + "ko": "모두 연결", "nl": "Alles verbinden", "pt": "Conectar todos", "ru": "Подключиться ко всем", + "zh-chs": "全部連接", "xloc": [ - "default.handlebars->25->217", + "default.handlebars->27->201", "default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->kvmListToolbar" ] }, @@ -4274,13 +5925,17 @@ "de": "Mit Server verbinden", "en": "Connect to server", "es": "Conectar al Servidor", + "fr": "Se connecter au serveur", + "hi": "सर्वर से कनेक्ट करें", "ja": "サーバーに接続する", + "ko": "서버에 연결", "nl": "Verbinden met de server", "pt": "Conecte-se ao servidor", "ru": "Подключиться к серверу", + "zh-chs": "連接到服務器", "xloc": [ - "default.handlebars->25->1054", - "default.handlebars->25->1058" + "default.handlebars->27->1158", + "default.handlebars->27->1162" ] }, { @@ -4289,9 +5944,13 @@ "en": "Connect to your home or office devices from anywhere in the world using MeshCentral, the real time, open source remote monitoring and management web site. You will need to download and install a management agent on your computers. Once installed, computers will show up in the \"My Devices\" section of this web site and you will be able to monitor them and take control of them.", "es": "Conéctese a los dispositivos de su hogar u oficina desde cualquier parte del mundo utilizando MeshCentral, el sitio web de administración y monitoreo remoto de código abierto en tiempo real. Deberá descargar e instalar un agente de administración en sus computadoras. Una vez instaladas, las computadoras aparecerán en la sección \"Mis dispositivos\" de este sitio web y usted podrá monitorearlas y controlarlas.", "fr": "Connectez-vous à vos ordinateurs à la maison ou au bureau depuis n'importe où dans le monde avec MeshCentral, le site web open source de surveillance et de gestion d’ordinateur à distance en temps réel. Vous devrez télécharger et installer un agent de gestion sur vos ordinateurs. Une fois installés, les ordinateurs apparaîtront dans la section \"Mes appareils\" de ce site et vous pourrez les surveiller et en prendre le contrôle.", + "hi": "दुनिया में कहीं से भी अपने घर या दफ्तर के उपकरणों से कनेक्ट करें, जो कि मेषस्थ्रल, रियल टाइम, ओपन सोर्स रिमोट मॉनिटरिंग और मैनेजमेंट वेब साइट का उपयोग करते हैं। आपको अपने कंप्यूटर पर एक प्रबंधन एजेंट को डाउनलोड और इंस्टॉल करना होगा। एक बार स्थापित होने के बाद, कंप्यूटर इस वेब साइट के \"माई डिवाइसेस\" अनुभाग में दिखाई देंगे और आप उनकी निगरानी कर पाएंगे और उनका नियंत्रण ले पाएंगे।", "ja": "リアルタイムのオープンソースのリモート監視および管理WebサイトであるMeshCentralを使用して、世界中のどこからでも自宅またはオフィスのデバイスに接続します。コンピューターに管理エージェントをダウンロードしてインストールする必要があります。インストールすると、コンピューターはこのWebサイトの[デバイス]セクションに表示され、コンピューターを監視して制御できるようになります。", + "ko": "실시간 오픈 소스 원격 모니터링 및 관리 웹 사이트 인 MeshCentral을 사용하여 전세계 어디에서나 집 또는 사무실 장치에 연결하십시오. 컴퓨터에 관리 에이전트를 다운로드하여 설치해야합니다. 컴퓨터가 설치되면이 웹 사이트의 \"내 장치\"섹션에 컴퓨터가 표시되며 컴퓨터를 모니터링하고 제어 할 수 있습니다.", "nl": "Maak overal ter wereld verbinding met uw thuis- of kantoorapparatuur via MeshCentral, de realtime, open source externe monitoring- en managementwebsite. U moet een beheeragent op uw computers downloaden en installeren. Na installatie verschijnen computers in het gedeelte \"Mijn apparaten\" van deze website en kunt u ze volgen en de controle over hen nemen.", + "pt": "Conecte-se aos seus dispositivos domésticos ou de escritório de qualquer lugar do mundo usando o MeshCentral, o site de gerenciamento e monitoramento remoto de código aberto em tempo real. Você precisará baixar e instalar um agente de gerenciamento em seus computadores. Uma vez instalados, os computadores aparecerão na seção \"Meus dispositivos\" deste site e você poderá monitorá-los e controlá-los.", "ru": "Подключайтесь к домашним или офисным устройствам из любой точки мира с помощью веб-сайта MeshCentral в режиме реального времени с открытым исходным кодом для удаленного мониторинга и управления. Вам нужно будет загрузить и установить агент управления на свои компьютеры. После установки компьютеры будут отображаться в разделе «Мои устройства» на этом веб-сайте, и вы сможете контролировать их и управлять ими.", + "zh-chs": "使用MeshCentral(實時,開源的遠程監視和管理網站),可以從世界任何地方連接到您的家庭或辦公室設備。您將需要在計算機上下載並安裝管理代理。安裝後,計算機將顯示在此網站的“我的設備”部分中,您將能夠對其進行監視和控制。", "xloc": [ "login.handlebars->container->column_l->welcomeText" ] @@ -4301,9 +5960,14 @@ "de": "Verbinden per Intel-AMT-Hardware-KVM", "en": "Connect using Intel AMT hardware KVM", "es": "Conectar usando el hardware Intel AMT KVM", + "fr": "Se connecter en utilisant le KVM d'Intel AMT", + "hi": "Intel AMT हार्डवेयर KVM का उपयोग करके कनेक्ट करें", "ja": "Intel AMTハードウェアKVMを使用して接続する", + "ko": "Intel AMT 하드웨어 KVM을 사용하여 연결", "nl": "Maak verbinding met Intel AMT hardware KVM", + "pt": "Conectar-se usando o KVM de hardware Intel AMT", "ru": "Подключение с использованием аппаратного обеспечения Intel AMT KVM", + "zh-chs": "使用Intel AMT硬件KVM連接", "xloc": [ "default.handlebars->container->column_l->p11->deskarea0->deskarea1->3->connectbutton1hspan", "default.handlebars->container->column_l->p12->termTable->1->1->0->1->3->connectbutton2hspan" @@ -4314,13 +5978,17 @@ "de": "Verbunden", "en": "Connected", "es": "Conectado", + "fr": "Connecté", + "hi": "जुड़े हुए", "ja": "接続済み", + "ko": "연결됨", "nl": "Verbonden", "pt": "Conectado", "ru": "Подключено", + "zh-chs": "連接的", "xloc": [ "default-mobile.handlebars->9->4", - "default.handlebars->25->11", + "default.handlebars->27->11", "xterm.handlebars->9->4" ] }, @@ -4329,10 +5997,16 @@ "de": "Verbinden per Intel® AMT", "en": "Connected Intel® AMT", "es": "Conectado Intel AMT", + "fr": "Nombre d'appareils Intel® AMT connectés", + "hi": "कनेक्टेड Intel® AMT", + "ja": "接続されたインテル®AMT", + "ko": "연결된 인텔 ® AMT", "nl": "Verbonden Intel® AMT", + "pt": "Intel® AMT conectado", "ru": "Подключено Intel® AMT", + "zh-chs": "連接的英特爾®AMT", "xloc": [ - "default.handlebars->25->1410" + "default.handlebars->27->1557" ] }, { @@ -4340,10 +6014,32 @@ "de": "Verbundene Benutzer", "en": "Connected Users", "es": "Usuarios Conectados", + "fr": "Nombre d'utilisateurs connectés", + "hi": "कनेक्ट किए गए उपयोगकर्ता", + "ja": "接続ユーザー", + "ko": "연결된 사용자", "nl": "Verbonden gebruikers", + "pt": "Usuários conectados", "ru": "Подключенные пользователи", + "zh-chs": "關聯用戶", "xloc": [ - "default.handlebars->25->1415" + "default.handlebars->27->1562" + ] + }, + { + "cs": "Připojeno hned", + "de": "Jetzt verbunden", + "en": "Connected now", + "fr": "Connecté maintenant", + "hi": "अभी जुड़े हुए हैं", + "ja": "今すぐ接続", + "ko": "지금 연결", + "nl": "Nu verbonden", + "pt": "Conectado agora", + "ru": "Подключено сейчас", + "zh-chs": "現在已連接", + "xloc": [ + "default.handlebars->27->746" ] }, { @@ -4351,10 +6047,14 @@ "de": "Verbunden.", "en": "Connected.", "es": "Conectado.", + "fr": "Connecté.", + "hi": "जुड़े हुए।", "ja": "接続済み。", + "ko": "연결되었습니다.", "nl": "Verbonden.", "pt": "Conectado.", "ru": "Подключено.", + "zh-chs": "連接的。", "xloc": [ "messenger.handlebars->13->7" ] @@ -4364,19 +6064,23 @@ "de": "Verbinden...", "en": "Connecting...", "es": "Conectando....", + "fr": "En cours de connexion ...", + "hi": "कनेक्ट ...", "ja": "接続しています...", + "ko": "연결 중 ...", "nl": "Verbinden...", "pt": "Conectando...", "ru": "Подключение...", + "zh-chs": "正在連線...", "xloc": [ "default-mobile.handlebars->9->2", - "default-mobile.handlebars->9->272", + "default-mobile.handlebars->9->276", "default-mobile.handlebars->9->6", - "default.handlebars->25->211", - "default.handlebars->25->214", - "default.handlebars->25->220", - "default.handlebars->25->688", - "default.handlebars->25->9", + "default.handlebars->27->195", + "default.handlebars->27->198", + "default.handlebars->27->204", + "default.handlebars->27->737", + "default.handlebars->27->9", "xterm.handlebars->9->2" ] }, @@ -4385,12 +6089,16 @@ "de": "Verbindungsanzahl", "en": "Connection Count", "es": "Conteo de Conexion.", + "fr": "Nombre de connexions", + "hi": "कनेक्शन गणना", "ja": "接続数", + "ko": "연결 수", "nl": "Aantal verbindingen", "pt": "Contagem de conexões", "ru": "Подключений ", + "zh-chs": "連接數", "xloc": [ - "default.handlebars->25->1426" + "default.handlebars->27->1573" ] }, { @@ -4398,12 +6106,16 @@ "de": "Verbindungsweiterleitung", "en": "Connection Relay", "es": "Relay de Conexion", + "fr": "Relais de connexion", + "hi": "कनेक्शन रिले", "ja": "接続リレー", + "ko": "연결 릴레이", "nl": "Verbindings Relay", "pt": "Encaminhador de conexão", "ru": "Ретранслятор подключения", + "zh-chs": "連接繼電器", "xloc": [ - "default.handlebars->25->1452" + "default.handlebars->27->1601" ] }, { @@ -4411,10 +6123,14 @@ "de": "Verbindung geschlossen.", "en": "Connection closed.", "es": "Conexión cerrada.", + "fr": "Connection terminée.", + "hi": "कनेक्शन बंद।", "ja": "接続が閉じられました。", + "ko": "연결이 닫혔습니다.", "nl": "Verbinding gesloten.", "pt": "Conexão fechada.", "ru": "Подключение прервано.", + "zh-chs": "連接已關閉。", "xloc": [ "messenger.handlebars->13->3" ] @@ -4424,10 +6140,14 @@ "de": "Verbindungen", "en": "Connections", "es": "Conexiones", + "fr": "Connections", + "hi": "सम्बन्ध", "ja": "接続", + "ko": "사이", "nl": "Verbindingen", "pt": "Conexões", "ru": "Подключения", + "zh-chs": "連接數", "xloc": [ "default.handlebars->container->column_l->p40->3->1->p40type->1" ] @@ -4437,15 +6157,19 @@ "de": "Konnektivität", "en": "Connectivity", "es": "Conectividad", + "fr": "Connectivité", + "hi": "कनेक्टिविटी", "ja": "接続性", - "nl": "connectiviteit", + "ko": "연결성", + "nl": "Connectiviteit", "pt": "Conectividade", "ru": "Связь", + "zh-chs": "連接性", "xloc": [ - "default-mobile.handlebars->9->195", - "default.handlebars->25->1154", - "default.handlebars->25->202", - "default.handlebars->25->492", + "default-mobile.handlebars->9->199", + "default.handlebars->27->1282", + "default.handlebars->27->186", + "default.handlebars->27->499", "default.handlebars->container->column_l->p21->3->1->meshConnChartDiv->1" ] }, @@ -4454,11 +6178,17 @@ "de": "Konsole", "en": "Console", "es": "Consola", + "fr": "Terminal", + "hi": "कंसोल", "ja": "コンソール", + "ko": "콘솔", "nl": "Console", "pt": "Console", "ru": "Консоль", + "zh-chs": "安慰", "xloc": [ + "default.handlebars->27->549", + "default.handlebars->27->568", "default.handlebars->container->topbar->1->1->MainSubMenuSpan->MainSubMenu->1->0->MainDevConsole", "default.handlebars->container->topbar->1->1->ServerSubMenuSpan->ServerSubMenu->1->0->ServerConsole", "default.handlebars->contextMenu->cxconsole" @@ -4469,12 +6199,30 @@ "de": "Konsole - ", "en": "Console - ", "es": "Consola -", + "fr": "Terminal -", + "hi": "कंसोल -", "ja": "コンソール -", + "ko": "콘솔-", "nl": "Console - ", "pt": "Console - ", "ru": "Консоль - ", + "zh-chs": "安慰 -", "xloc": [ - "default.handlebars->25->441" + "default.handlebars->27->445" + ] + }, + { + "cs": "Řízení", + "de": "Steuerung", + "en": "Control", + "fr": "Contrôle", + "ja": "コントロール", + "nl": "Controle", + "ru": "контроль", + "zh-chs": "控制", + "xloc": [ + "default.handlebars->27->548", + "default.handlebars->27->567" ] }, { @@ -4482,12 +6230,16 @@ "de": "Cookie-Kodierer", "en": "Cookie encoder", "es": "Codificador de Cookie", + "fr": "Encodeur de cookies", + "hi": "कुकी एनकोडर", "ja": "Cookieエンコーダー", + "ko": "쿠키 인코더", "nl": "Cookie encoder", "pt": "Codificador de cookies", "ru": "Cookie-кодировщик", + "zh-chs": "Cookie編碼器", "xloc": [ - "default.handlebars->25->1440" + "default.handlebars->27->1587" ] }, { @@ -4495,10 +6247,14 @@ "de": "Kopie", "en": "Copy", "es": "Copiar", + "fr": "Copier", + "hi": "प्रतिलिपि", "ja": "コピー", + "ko": "부", "nl": "Kopiëren", "pt": "Copiar", "ru": "Копировать", + "zh-chs": "複製", "xloc": [ "default-mobile.handlebars->container->page_content->column_l->p10->p10files->p13toolbar->1->2->1->3", "default-mobile.handlebars->container->page_content->column_l->p5->p5myfiles->p5toolbar->1->0->1->3", @@ -4511,13 +6267,17 @@ "de": "MAC-Adresse in Zwischenablage kopieren", "en": "Copy MAC address to clipboard", "es": "Copiar Direccion MAC al portapapeles", + "fr": "Copier l'adresse MAC dans le presse-papiers", + "hi": "मैक पते को क्लिपबोर्ड पर कॉपी करें", "ja": "MACアドレスをクリップボードにコピー", + "ko": "MAC 주소를 클립 보드에 복사", "nl": "Kopieer MAC adres naar het klembord", "pt": "Copiar endereço MAC para a área de transferência", "ru": "Скопировать МАС адрес в буфер обмена", + "zh-chs": "將MAC地址複製到剪貼板", "xloc": [ - "default.handlebars->25->107", - "default.handlebars->25->99" + "default.handlebars->27->82", + "default.handlebars->27->90" ] }, { @@ -4525,12 +6285,42 @@ "de": "MacOS-Agenten-URL in Zwischenablage kopieren", "en": "Copy MacOS agent URL to clipboard", "es": "Copiar URL del Agente para MacOS al portapapeles", + "fr": "Copier l'URL de l'agent MacOS dans le presse-papiers", + "hi": "MacOS एजेंट URL को क्लिपबोर्ड पर कॉपी करें", "ja": "MacOSエージェントのURLをクリップボードにコピーします", + "ko": "MacOS 에이전트 URL을 클립 보드에 복사", "nl": "Kopieer MacOS agent link naar het klembord", "pt": "Copiar o URL do agente MacOS para a área de transferência", "ru": "Скопировать ссылку MacOS agent в буфер обмена", + "zh-chs": "將MacOS代理URL複製到剪貼板", "xloc": [ - "default.handlebars->25->337" + "default.handlebars->27->327" + ] + }, + { + "cs": "Zkopírujte adresu URL agenta Windows 32bit do schránky", + "de": "Kopieren Sie die Windows 32-Bit-Agenten-URL in die Zwischenablage", + "en": "Copy Windows 32bit agent URL to clipboard", + "fr": "Copier l'URL de l'agent Windows 32 bits dans le presse-papiers", + "ja": "Windows 32ビットエージェントのURLをクリップボードにコピー", + "nl": "Kopieer de Windows 32bit-agent URL naar het klembord", + "ru": "Скопировать URL-адрес агента Windows 32bit в буфер обмена", + "zh-chs": "将Windows 32位代理URL复制到剪贴板", + "xloc": [ + "default.handlebars->27->315" + ] + }, + { + "cs": "Zkopírujte adresu URL agenta Windows 64bit do schránky", + "de": "Kopieren Sie die Windows 64-Bit-Agenten-URL in die Zwischenablage", + "en": "Copy Windows 64bit agent URL to clipboard", + "fr": "Copier l'URL de l'agent Windows 64 bits dans le presse-papiers", + "ja": "Windows 64ビットエージェントのURLをクリップボードにコピー", + "nl": "Kopieer de Windows 64bit-agent URL naar het klembord", + "ru": "Скопировать URL-адрес агента Windows 64bit в буфер обмена", + "zh-chs": "将Windows 64位代理URL复制到剪贴板", + "xloc": [ + "default.handlebars->27->319" ] }, { @@ -4538,16 +6328,21 @@ "de": "Adresse in Zwischenablage kopieren", "en": "Copy address to clipboard", "es": "Copiar direccion al portapapeles", + "fr": "Copier l'adresse dans la presse-papiers", + "hi": "क्लिपबोर्ड पर पता कॉपी करें", "ja": "クリップボードにアドレスをコピー", + "ko": "주소를 클립 보드에 복사", "nl": "Kopieer adres naar het klembord", "pt": "Copiar endereço para a área de transferência", "ru": "Скопировать адрес в буфер обмена", + "zh-chs": "將地址複製到剪貼板", "xloc": [ - "default.handlebars->25->101", - "default.handlebars->25->103", - "default.handlebars->25->105", - "default.handlebars->25->90", - "default.handlebars->25->92" + "default.handlebars->27->71", + "default.handlebars->27->73", + "default.handlebars->27->75", + "default.handlebars->27->84", + "default.handlebars->27->86", + "default.handlebars->27->88" ] }, { @@ -4555,12 +6350,18 @@ "de": "Link in Zwischenablage kopieren", "en": "Copy link to clipboard", "es": "Copiar enlance al portapapeles", + "fr": "Copier le lien dans le presse-papiers", + "hi": "क्लिपबोर्ड पर कॉपी लिंक", "ja": "リンクをクリップボードにコピー", + "ko": "클립 보드에 링크 복사", "nl": "Kopieer link naar het klembord", "pt": "Copiar link para a área de transferência", "ru": "Скопировать ссылку в буфер обмена", + "zh-chs": "複製鏈接到剪貼板", "xloc": [ - "default.handlebars->25->312" + "default.handlebars->27->1287", + "default.handlebars->27->1301", + "default.handlebars->27->299" ] }, { @@ -4568,12 +6369,16 @@ "de": "Name in Zwischenablage kopieren", "en": "Copy name to clipboard", "es": "Copiar nombre al portapapeles", + "fr": "Copier le nom dans le presse-papiers", + "hi": "क्लिपबोर्ड पर कॉपी नाम", "ja": "名前をクリップボードにコピー", + "ko": "클립 보드에 이름 복사", "nl": "Kopieer de naam naar het klembord", "pt": "Copiar nome para a área de transferência", "ru": "Скопировать имя в буфер обмена", + "zh-chs": "將名稱複製到剪貼板", "xloc": [ - "default.handlebars->25->97" + "default.handlebars->27->80" ] }, { @@ -4581,10 +6386,14 @@ "de": "In Zwischenablage kopieren", "en": "Copy to clipboard", "es": "Copiar al portapapeles", + "fr": "Copier dans le presse-papiers", + "hi": "क्लिपबोर्ड पर कॉपी करें", "ja": "クリップボードにコピー", + "ko": "클립 보드에 복사", "nl": "Kopieer naar het klembord", "pt": "Copiar para área de transferência", "ru": "Скопировать в буфер обмена", + "zh-chs": "複製到剪貼板", "xloc": [ "agentinvite.handlebars->container->column_l->5->linuxtab", "agentinvite.handlebars->container->column_l->5->linuxtab" @@ -4595,21 +6404,30 @@ "de": "Gültige Codes in Zwischenablage kopieren", "en": "Copy valid codes to clipboard", "es": "Copiar codigos validos al portapapeles", + "fr": "Copier les codes dans le presse-papiers", + "hi": "मान्य कोड को क्लिपबोर्ड पर कॉपी करें", "ja": "有効なコードをクリップボードにコピー", + "ko": "유효한 코드를 클립 보드에 복사", "nl": "Kopieer de geldige code's naar het klembord", "pt": "Copiar códigos válidos para a área de transferência", "ru": "Скопировать действительные коды в буфер обмена", + "zh-chs": "將有效代碼複製到剪貼板", "xloc": [ - "default.handlebars->25->137" + "default.handlebars->27->120" ] }, { "cs": "Autorská práva © 2011 Joel Martin Tato podoba ve formě zdrojových kódů podléhá podmínkám Mozilla Public licence, v. 2.0. Pokud jste společně s tímto souborem neobdrželi kopii licence, je k dispozici na adrese http://mozilla.org/MPL/2.0/", + "de": "Copyright (C) 2011 Joel Martin Dieses Quellcode-Formular unterliegt den Bestimmungen der Mozilla Public License, Version 2.0. Wenn eine Kopie der MPL nicht mit dieser Datei verteilt wurde, können Sie eine unter http://mozilla.org/MPL/2.0/ erhalten.", "en": "Copyright (C) 2011 Joel Martin This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.", + "fr": "Copyright (C) 2011 Joel Martin Ce formulaire de code source est soumis aux termes de la licence publique de Mozilla, v. 2.0. Si une copie de la MPL n'a pas été distribuée avec ce fichier, vous pouvez en obtenir une sur http://mozilla.org/MPL/2.0/.", + "hi": "कॉपीराइट (C) 2011 जोएल मार्टिन यह स्रोत कोड फॉर्म मोज़िला पब्लिक लाइसेंस, वी। 2.0 की शर्तों के अधीन है। यदि इस फ़ाइल के साथ MPL की एक प्रति वितरित नहीं की गई थी, तो आप http://mozilla.org/MPL/2.0/ पर एक प्राप्त कर सकते हैं।", "ja": "Copyright(C)2011 Joel Martinこのソースコードフォームには、Mozilla Public License v。2.0の条件が適用されます。 MPLのコピーがこのファイルとともに配布されていない場合は、http://mozilla.org/MPL/2.0/から入手できます。", + "ko": "Copyright (C) 2011 Joel Martin이 소스 코드 양식은 Mozilla Public License, v. 2.0의 약관에 따릅니다. MPL 사본이이 파일과 함께 분배되지 않은 경우 http://mozilla.org/MPL/2.0/에서 얻을 수 있습니다.", "nl": "Copyright (C) 2011 Joel Martin Dit broncodeformulier is onderworpen aan de voorwaarden van de Mozilla Public License, v. 2.0. Als een kopie van de MPL niet met dit bestand is verspreid, kunt u er een verkrijgen op http://mozilla.org/MPL/2.0/.", "pt": "Copyright (C) 2011 Joel Martin Este formulário de código-fonte está sujeito aos termos da Licença Pública Mozilla, v.2.0 0.Se uma cópia da MPL não foi distribuída com este arquivo, você pode obter uma em http: // mozilla.org / MPL / 2.0 /.", "ru": "Copyright (C) 2011 Joel Martin Данная форма исходного кода регулируется условиями Общественной лицензии Mozilla, v. 2.0. Если копия MPL не была распространена с этим файлом, ее можно получить по адресу http://mozilla.org/MPL/2.0/.", + "zh-chs": "版權所有(C)2011 Joel Martin此源代碼表受Mozilla公共許可證v。2.0條款的約束。如果未隨該文件分發MPL的副本,則可以在http://mozilla.org/MPL/2.0/上獲得一份。", "xloc": [ "terms-mobile.handlebars->container->page_content->column_l->63->1", "terms.handlebars->container->column_l->63->1" @@ -4617,11 +6435,16 @@ }, { "cs": "Autorská práva © 1998-2011 The OpenSSL Project. Všechna práva vyhrazena.", + "de": "Copyright (c) 1998-2011 Das OpenSSL-Projekt. Alle Rechte vorbehalten.", "en": "Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved.", + "fr": "Copyright (c) 1998-2011 The OpenSSL Project. Tous droits réservés.", + "hi": "कॉपीराइट (c) 1998-2011 ओपनएसएसएल प्रोजेक्ट। सभी अधिकार सुरक्षित।", "ja": "Copyright(c)1998-2011 The OpenSSL Project。全著作権所有。", + "ko": "Copyright (c) 1998-2011 OpenSSL 프로젝트. 판권 소유.", "nl": "Copyright (c) 1998-2011 The OpenSSL Project. Alle rechten voorbehouden.", "pt": "Copyright (c) 1998-2011 O Projeto OpenSSL.Todos os direitos reservados.", "ru": "Copyright (c) 1998-2011 The OpenSSL Project. Все права защищены.", + "zh-chs": "版權所有(c)1998-2011 The OpenSSL Project。版權所有。", "xloc": [ "terms-mobile.handlebars->container->page_content->column_l->27->1", "terms.handlebars->container->column_l->27->1" @@ -4629,11 +6452,16 @@ }, { "cs": "Autorská práva © 2009, CodePlex Foundation. Všechna práva vyhrazena.", + "de": "Copyright (c) 2009, CodePlex Foundation. Alle Rechte vorbehalten.", "en": "Copyright (c) 2009, CodePlex Foundation. All rights reserved.", + "fr": "Copyright (c) 2009, CodePlex Foundation. Tous droits réservés.", + "hi": "कॉपीराइट (c) 2009, कोडप्लेक्स फाउंडेशन। सभी अधिकार सुरक्षित।", "ja": "Copyright(c)2009、CodePlex Foundation。全著作権所有。", + "ko": "저작권 (c) 2009, CodePlex Foundation. 판권 소유.", "nl": "Copyright (c) 2009, CodePlex Foundation. Alle rechten voorbehouden.", "pt": "Direitos autorais (c) 2009, CodePlex Foundation.Todos os direitos reservados.", "ru": "Copyright (c) 2009, CodePlex Foundation. Все права защищены.", + "zh-chs": "CodePlex Foundation版權所有(c)2009。版權所有。", "xloc": [ "terms-mobile.handlebars->container->page_content->column_l->11->1", "terms.handlebars->container->column_l->11->1" @@ -4641,11 +6469,16 @@ }, { "cs": "Autorská práva © 2010 Wojciech „RRH“ Ryrych", + "de": "Copyright (c) 2010 Wojciech 'RRH' Ryrych", "en": "Copyright (c) 2010 Wojciech 'RRH' Ryrych", + "fr": "Copyright (c) 2010 Wojciech 'RRH' Ryrych", + "hi": "कॉपीराइट (c) 2010 Wojciech 'RRH' Ryrych", "ja": "Copyright(c)2010 Wojciech 'RRH' Ryrych", + "ko": "저작권 (c) 2010 Wojciech 'RRH'Ryrych", "nl": "Copyright (c) 2010 Wojciech 'RRH' Ryrych", "pt": "Copyright (c) 2010 Wojciech 'RRH' Ryrych", "ru": "Copyright (c) 2010 Wojciech 'RRH' Ryrych", + "zh-chs": "版權所有(c)2010 Wojciech'RRH'Ryrych", "xloc": [ "terms-mobile.handlebars->container->page_content->column_l->69->1", "terms.handlebars->container->column_l->69->1" @@ -4653,11 +6486,16 @@ }, { "cs": "Autorská práva © 2013 nadace jQuery Foundation a ostatní přispěvatelé", + "de": "Copyright 2013 jQuery Foundation und andere Mitwirkende", "en": "Copyright 2013 jQuery Foundation and other contributors", + "fr": "Copyright 2013 jQuery Foundation et autres contributeurs", + "hi": "कॉपीराइट 2013 jQuery फाउंडेशन और अन्य योगदानकर्ताओं", "ja": "Copyright 2013 jQuery Foundationおよびその他の貢献者", + "ko": "저작권 2013 jQuery Foundation 및 기타 기고자", "nl": "Copyright 2013 jQuery Foundation en andere bijdragers", "pt": "Copyright 2013 jQuery Foundation e outros colaboradores", "ru": "Copyright 2013 jQuery Foundation и другие участники", + "zh-chs": "版權所有2013 jQuery Foundation和其他貢獻者", "xloc": [ "terms-mobile.handlebars->container->page_content->column_l->47->1", "terms.handlebars->container->column_l->47->1" @@ -4665,11 +6503,16 @@ }, { "cs": "Autorská práva © 2013 nadace jQuery Foundation a ostatní přispěvatelé,", + "de": "Copyright 2013 jQuery Foundation und andere Mitwirkende,", "en": "Copyright 2013 jQuery Foundation and other contributors,", + "fr": "Copyright 2013 jQuery Foundation et autres contributeurs,", + "hi": "कॉपीराइट 2013 jQuery फाउंडेशन और अन्य योगदानकर्ताओं,", "ja": "Copyright 2013 jQuery Foundationおよびその他の貢献者、", + "ko": "저작권 2013 jQuery Foundation 및 기타 기고자", "nl": "Copyright 2013 jQuery Foundation en andere bijdragers,", "pt": "Copyright 2013 jQuery Foundation e outros colaboradores,", "ru": "Copyright 2013 jQuery Foundation и другие участники,", + "zh-chs": "版權所有2013 jQuery Foundation和其他貢獻者,", "xloc": [ "terms-mobile.handlebars->container->page_content->column_l->53->1", "terms.handlebars->container->column_l->53->1" @@ -4680,24 +6523,32 @@ "de": "Kernserver", "en": "Core Server", "es": "Servidor central", + "fr": "Serveur central", + "hi": "कोर सर्वर", "ja": "コアサーバー", + "ko": "핵심 서버", "nl": "Core Server", "pt": "Servidor Core", "ru": "Основной сервер", + "zh-chs": "核心服務器", "xloc": [ - "default.handlebars->25->1439" + "default.handlebars->27->1586" ] }, { "cs": "korsičtina", "de": "Korsisch", "en": "Corsican", + "fr": "Corse", + "hi": "कोर्सीकन", "ja": "コルシカ", + "ko": "코르시카 어", "nl": "Corsicaans", "pt": "Corso", "ru": "Kорсиканский", + "zh-chs": "科西嘉人", "xloc": [ - "default.handlebars->25->762" + "default.handlebars->27->866" ] }, { @@ -4705,12 +6556,16 @@ "de": "Konto erstellen", "en": "Create Account", "es": "Crear una cuenta", + "fr": "Créer un compte", + "hi": "खाता बनाएं", "ja": "アカウントを作成する", + "ko": "계정 만들기", "nl": "Account aanmaken", "pt": "Criar conta", "ru": "Создать учетную запись", + "zh-chs": "創建帳號", "xloc": [ - "default.handlebars->25->1254", + "default.handlebars->27->1389", "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->createpanel->1->1->9->1->12->1->1", "login.handlebars->container->column_l->centralTable->1->0->logincell->createpanel->1->9->1->12->1->1" ] @@ -4720,12 +6575,16 @@ "de": "Gerätegruppe erstellen", "en": "Create Device Group", "es": "Crear grupo de dispositivos", + "fr": "Créer un groupe d'appareils", + "hi": "डिवाइस ग्रुप बनाएं", "ja": "デバイスグループを作成する", + "ko": "장치 그룹 생성", "nl": "Apparaatgroep aanmaken", "pt": "Criar grupo de dispositivo", "ru": "Создать группу устройств", + "zh-chs": "創建設備組", "xloc": [ - "default-mobile.handlebars->9->61" + "default-mobile.handlebars->9->64" ] }, { @@ -4733,10 +6592,16 @@ "de": "Benutzergruppe erstellen", "en": "Create User Group", "es": "Crear grupo de usuarios", + "fr": "Créer un groupe utilisateur", + "hi": "उपयोगकर्ता समूह बनाएँ", + "ja": "ユーザーグループを作成", + "ko": "사용자 그룹 생성", "nl": "Maak een gebruikersgroep.", + "pt": "Criar grupo de usuários", "ru": "Создать группу пользователей", + "zh-chs": "創建用戶組", "xloc": [ - "default.handlebars->25->1277" + "default.handlebars->27->1413" ] }, { @@ -4744,12 +6609,16 @@ "de": "Eine neue Gerätegruppe mit den folgenden Optionen erstellen.", "en": "Create a new device group using the options below.", "es": "Cree un nuevo grupo de dispositivos utilizando las siguientes opciones.", + "fr": "Créer un nouveau groupe d'appareils avec les options suivantes.", + "hi": "नीचे दिए गए विकल्पों का उपयोग करके एक नया उपकरण समूह बनाएं।", "ja": "以下のオプションを使用して、新しいデバイスグループを作成します。", + "ko": "아래 옵션을 사용하여 새 장치 그룹을 만듭니다.", "nl": "Maak een nieuwe apparaatgroep met behulp van de onderstaande opties.", "pt": "Crie um novo grupo de dispositivos usando as opções abaixo.", "ru": "Создайте новую группу устройств, используя параметры ниже.", + "zh-chs": "使用以下選項創建一個新的設備組。", "xloc": [ - "default.handlebars->25->954" + "default.handlebars->27->1059" ] }, { @@ -4757,12 +6626,16 @@ "de": "Eine neue Gerätegruppe erstellen.", "en": "Create a new group of devices.", "es": "Crea un nuevo grupo de dispositivos.", + "fr": "Créer un groupe d'appareils", + "hi": "उपकरणों का एक नया समूह बनाएँ।", "ja": "デバイスの新しいグループを作成します。", + "ko": "새로운 장치 그룹을 만듭니다.", "nl": "Maak een nieuwe apparaatgroep.", "pt": "Crie um novo grupo de dispositivos.", "ru": "Создать новую группу устройств.", + "zh-chs": "創建一個新的設備組。", "xloc": [ - "default.handlebars->25->204" + "default.handlebars->27->188" ] }, { @@ -4770,12 +6643,16 @@ "de": "Erzeuge viele Konten auf einmal durch Import einer JSON-Datei mit dem folgenden Format:", "en": "Create many accounts at once by importing a JSON file with the following format:", "es": "Cree muchas cuentas a la vez importando un archivo JSON con el siguiente formato:", + "fr": "Créer des comptes en important un fichier JSON au format suivant :", + "hi": "निम्नलिखित प्रारूप के साथ JSON फ़ाइल आयात करके एक साथ कई खाते बनाएँ:", "ja": "次の形式のJSONファイルをインポートして、一度に多くのアカウントを作成します。", + "ko": "다음 형식의 JSON 파일을 가져 와서 한 번에 많은 계정을 만듭니다.", "nl": "Maak meerdere accounts tegelijk door een JSON-bestand met de volgende indeling te importeren:", "pt": "Crie várias contas ao mesmo tempo importando um arquivo JSON com o seguinte formato:", "ru": "Создайте сразу несколько учетных записей, импортировав файл JSON в следующем формате:", + "zh-chs": "通過導入以下格式的JSON文件一次創建多個帳戶:", "xloc": [ - "default.handlebars->25->1225" + "default.handlebars->27->1360" ] }, { @@ -4783,10 +6660,14 @@ "de": "Erstelle eines", "en": "Create one", "es": "Crea uno", + "fr": "Créer un", + "hi": "एक बनाए", "ja": "一つ作る", + "ko": "하나 만들기", "nl": "Creëer er een", "pt": "Crie um", "ru": "Создать", + "zh-chs": "創建一個", "xloc": [ "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->loginpanel->1->newAccountDiv->1", "login.handlebars->container->column_l->centralTable->1->0->logincell->loginpanel->1->newAccountDiv->1" @@ -4797,12 +6678,16 @@ "de": "Erzeugung", "en": "Creation", "es": "Creación", + "fr": "Création", + "hi": "सृष्टि", "ja": "作成", + "ko": "창조", "nl": "Aanmaken", "pt": "Criação", "ru": "Создано", + "zh-chs": "創建", "xloc": [ - "default.handlebars->25->1331" + "default.handlebars->27->1465" ] }, { @@ -4810,10 +6695,14 @@ "de": "Erzeugungs-Token:", "en": "Creation Token:", "es": "Creación de Token:", + "fr": "Jeton de création:", + "hi": "निर्माण टोकन:", "ja": "作成トークン:", + "ko": "창조 토큰 :", "nl": "Token aanmaken:", "pt": "Token de criação", "ru": "Создание токена:", + "zh-chs": "創建令牌:", "xloc": [ "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->createpanel->1->1->9->1->newAccountPass->1", "login.handlebars->container->column_l->centralTable->1->0->logincell->createpanel->1->9->1->newAccountPass->nuToken" @@ -4823,24 +6712,32 @@ "cs": "kríjština", "de": "Cree", "en": "Cree", + "fr": "Cri", + "hi": "क्री", "ja": "クリー語", + "ko": "크리어", "nl": "Cree", "pt": "Cree", "ru": "Кри (Канадский язык)", + "zh-chs": "克里", "xloc": [ - "default.handlebars->25->763" + "default.handlebars->27->867" ] }, { "cs": "chorvatština", "de": "Kroatisch", "en": "Croatian", + "fr": "croate", + "hi": "क्रोएशियाई", "ja": "クロアチア語", + "ko": "크로아티아어", "nl": "Kroatisch", "pt": "Croata", "ru": "Хорватский", + "zh-chs": "克羅地亞語", "xloc": [ - "default.handlebars->25->764" + "default.handlebars->27->868" ] }, { @@ -4848,10 +6745,14 @@ "de": "Strg+C", "en": "Ctl-C", "es": "Ctl-C", + "fr": "Ctl-C", + "hi": "सीटीएल-सी", "ja": "Ctl-C", + "ko": "Ctl-C", "nl": "Ctl-C", "pt": "CTRL-C", "ru": "Ctl-C", + "zh-chs": "Ctl-C", "xloc": [ "default.handlebars->container->column_l->p12->termTable->1->1->6->1->3" ] @@ -4861,10 +6762,14 @@ "de": "Strg+X", "en": "Ctl-X", "es": "Ctl-X", + "fr": "Ctl-X", + "hi": "सीटीएल एक्स", "ja": "Ctl-X", + "ko": "Ctl-X", "nl": "Ctl-X", "pt": "CTRL-X", "ru": "Ctl-X", + "zh-chs": "Ctl-X", "xloc": [ "default.handlebars->container->column_l->p12->termTable->1->1->6->1->3" ] @@ -4874,12 +6779,16 @@ "de": "Strg", "en": "Ctrl", "es": "Ctrl", + "fr": "Ctrl", + "hi": "Ctrl", "ja": "Ctrl", + "ko": "Ctrl", "nl": "Ctrl", "pt": "CTRL", "ru": "Ctrl", + "zh-chs": "Ctrl", "xloc": [ - "default.handlebars->25->46" + "default.handlebars->27->46" ] }, { @@ -4887,10 +6796,14 @@ "de": "Strg+Alt+Entf", "en": "Ctrl+Alt+Del", "es": "Ctrl+Alt+Del", + "fr": "Ctrl+Alt+Del", + "hi": "Ctrl + Alt + Del", "ja": "Ctrl + Alt + Del", + "ko": "Ctrl + Alt + Del", "nl": "Ctrl+Alt+Del", "pt": "CTRL+ALT+DEL", "ru": "Ctrl+Alt+Del", + "zh-chs": "Ctrl + Alt + Del", "xloc": [ "default-mobile.handlebars->dialog->3->dialog3->deskkeys->1", "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->deskkeys->1" @@ -4901,10 +6814,14 @@ "de": "Strg+W", "en": "Ctrl-W", "es": "Ctrl-W", + "fr": "Ctrl-W", + "hi": "Ctrl-W", "ja": "Ctrl-W", + "ko": "Ctrl-W", "nl": "Ctrl-W", "pt": "CTRL-W", "ru": "Ctrl-W", + "zh-chs": "Ctrl-W", "xloc": [ "default-mobile.handlebars->dialog->3->dialog3->deskkeys->21", "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->deskkeys->19" @@ -4915,12 +6832,16 @@ "de": "Aktuelle Version", "en": "Current Version", "es": "Version Actual", + "fr": "Version", + "hi": "वर्तमान संस्करण", "ja": "現行版", + "ko": "현재 버전", "nl": "Huidige versie", "pt": "Versão Atual", "ru": "Текущая версия", + "zh-chs": "當前版本", "xloc": [ - "default.handlebars->25->110" + "default.handlebars->27->93" ] }, { @@ -4928,10 +6849,14 @@ "de": "Ausschneiden", "en": "Cut", "es": "Cortar", + "fr": "Couper", + "hi": "कट गया", "ja": "カット", + "ko": "절단", "nl": "Knippen", "pt": "Cortar", "ru": "Вырезать", + "zh-chs": "切", "xloc": [ "default-mobile.handlebars->container->page_content->column_l->p10->p10files->p13toolbar->1->2->1->3", "default-mobile.handlebars->container->page_content->column_l->p5->p5myfiles->p5toolbar->1->0->1->3", @@ -4943,12 +6868,16 @@ "cs": "čeština", "de": "Tschechisch", "en": "Czech", + "fr": "Tchèque", + "hi": "चेक", "ja": "チェコ語", + "ko": "체코 사람", "nl": "Tsjechisch", "pt": "Tcheco", "ru": "Чешский", + "zh-chs": "捷克文", "xloc": [ - "default.handlebars->25->765" + "default.handlebars->27->869" ] }, { @@ -4956,24 +6885,32 @@ "de": "DNS-Suffix", "en": "DNS suffix", "es": "Sufijo DNS", + "fr": "Suffixe DNS", + "hi": "डीएनएस प्रत्यय", "ja": "DNSサフィックス", + "ko": "DNS 접미사", "nl": "DNS-achtervoegsel", "pt": "Sufixo DNS", "ru": "DNS-суффикс", + "zh-chs": "DNS後綴", "xloc": [ - "default.handlebars->25->96" + "default.handlebars->27->79" ] }, { "cs": "dánština", "de": "Dänisch", "en": "Danish", + "fr": "Danois", + "hi": "दानिश", "ja": "デンマーク語", + "ko": "덴마크 말", "nl": "Deens", "pt": "Dinamarquês", "ru": "Датский", + "zh-chs": "丹麥文", "xloc": [ - "default.handlebars->25->766" + "default.handlebars->27->870" ] }, { @@ -4981,12 +6918,16 @@ "de": "DataChannel", "en": "DataChannel", "es": "Canal de Datos", + "fr": "DataChannel", + "hi": "DataChannel", "ja": "データチャネル", + "ko": "DataChannel", "nl": "Data kanaal", "pt": "DataChannel", "ru": "DataChannel", + "zh-chs": "數據通道", "xloc": [ - "default.handlebars->25->605" + "default.handlebars->27->653" ] }, { @@ -4994,12 +6935,16 @@ "de": "Datum & Uhrzeit", "en": "Dates & Time", "es": "Fecha & Hora", + "fr": "dates et heure", + "hi": "दिनांक और समय", "ja": "日時", + "ko": "날짜와 시간", "nl": "Datum & Tiid", "pt": "Datas e Horário", "ru": "Дата & Время", + "zh-chs": "日期和時間", "xloc": [ - "default.handlebars->25->922" + "default.handlebars->27->1027" ] }, { @@ -5007,12 +6952,16 @@ "de": "Tag", "en": "Day", "es": "Dia", + "fr": "Jour", + "hi": "दिन", "ja": "日", + "ko": "일", "nl": "Dag", "pt": "Dia", "ru": "День", + "zh-chs": "天", "xloc": [ - "default.handlebars->25->544" + "default.handlebars->27->591" ] }, { @@ -5020,12 +6969,16 @@ "de": "Client Control Mode (CCM) deaktivieren", "en": "Deactivate Client Control Mode (CCM)", "es": "Desactivar Client Control Mode (CCM)", + "fr": "Désactiver le contrôle du client (CCM)", + "hi": "ग्राहक नियंत्रण मोड (CCM) निष्क्रिय करें", "ja": "クライアント制御モード(CCM)を無効にする", + "ko": "클라이언트 제어 모드 (CCM) 비활성화", "nl": "Deactiveer Client Control Mode (CCM)", "pt": "Desativar o modo de controle do cliente (CCM)", "ru": "Деактивировать режим управления клиентом (CCM)", + "zh-chs": "停用客戶端控制模式(CCM)", "xloc": [ - "default.handlebars->25->1042" + "default.handlebars->27->1146" ] }, { @@ -5033,13 +6986,17 @@ "de": "Tiefschlaf", "en": "Deep Sleep", "es": "Sueño profundo", + "fr": "Veuille profonde", + "hi": "गहरी नींद", "ja": "深い眠り", + "ko": "깊은 잠", "nl": "Slaapstand", "pt": "Deep Sleep", "ru": "Глубокий сон", + "zh-chs": "沉睡", "xloc": [ - "default-mobile.handlebars->9->110", - "default.handlebars->25->356" + "default-mobile.handlebars->9->114", + "default.handlebars->27->346" ] }, { @@ -5047,20 +7004,26 @@ "de": "Löschen", "en": "Delete", "es": "Borrar", + "fr": "Supprimer", + "hi": "हटाएं", "ja": "削除する", + "ko": "지우다", "nl": "Verwijderen", "pt": "Deletar", "ru": "Удалить", + "zh-chs": "刪除", "xloc": [ - "default-mobile.handlebars->9->249", - "default-mobile.handlebars->9->81", + "default-mobile.handlebars->9->253", + "default-mobile.handlebars->9->84", "default-mobile.handlebars->container->page_content->column_l->p10->p10files->p13toolbar->1->2->1->1", "default-mobile.handlebars->container->page_content->column_l->p5->p5myfiles->p5toolbar->1->0->1->1", - "default.handlebars->25->1178", - "default.handlebars->25->657", + "default.handlebars->27->1308", + "default.handlebars->27->417", + "default.handlebars->27->706", "default.handlebars->container->column_l->p13->p13toolbar->1->2->1->3", "default.handlebars->container->column_l->p5->p5toolbar->1->0->p5filehead->3", "default.handlebars->container->dialog->idx_dlgButtonBar->5", + "default.handlebars->filesContextMenu->cxfiledelete->0", "player.handlebars->p11->dialog->idx_dlgButtonBar->5", "xterm.handlebars->p11->dialog->idx_dlgButtonBar->5" ] @@ -5070,13 +7033,17 @@ "de": "Konto löschen", "en": "Delete Account", "es": "Borrar cuenta", + "fr": "Supprimer mon compte", + "hi": "खाता हटा दो", "ja": "アカウントを削除する", + "ko": "계정 삭제", "nl": "Verwijder account", "pt": "Deletar Conta", "ru": "Удалить учетную запись", + "zh-chs": "刪除帳戶", "xloc": [ - "default-mobile.handlebars->9->43", - "default.handlebars->25->939" + "default-mobile.handlebars->9->46", + "default.handlebars->27->1044" ] }, { @@ -5084,13 +7051,17 @@ "de": "Gerät löschen", "en": "Delete Device", "es": "Borrar dispositivo", + "fr": "Supprimer l'appareil", + "hi": "डिवाइस हटाएं", "ja": "デバイスを削除", + "ko": "장치 삭제", "nl": "Verwijder apparaat", "pt": "Excluir dispositivo", "ru": "Удалить устройство", + "zh-chs": "刪除裝置", "xloc": [ - "default-mobile.handlebars->9->199", - "default.handlebars->25->503" + "default-mobile.handlebars->9->203", + "default.handlebars->27->510" ] }, { @@ -5098,15 +7069,19 @@ "de": "Gruppe löschen", "en": "Delete Group", "es": "Borrar Grupo", + "fr": "Supprimer le groupe", + "hi": "समूह हटाएँ", "ja": "グループを削除", + "ko": "그룹 삭제", "nl": "Verwijder groep", "pt": "Excluir grupo", "ru": "Удалить группу", + "zh-chs": "刪除群組", "xloc": [ - "default-mobile.handlebars->9->285", - "default-mobile.handlebars->9->288", - "default.handlebars->25->1035", - "default.handlebars->25->1065" + "default-mobile.handlebars->9->289", + "default-mobile.handlebars->9->292", + "default.handlebars->27->1139", + "default.handlebars->27->1169" ] }, { @@ -5114,13 +7089,17 @@ "de": "Knoten löschen", "en": "Delete Node", "es": "Borrar Nodo", + "fr": "Supprimer le noeud", + "hi": "नोड हटाएं", "ja": "ノードを削除", + "ko": "노드 삭제", "nl": "Verwijder apparaat", "pt": "Excluir nó", "ru": "Удалить устройство", + "zh-chs": "刪除節點", "xloc": [ - "default-mobile.handlebars->9->218", - "default.handlebars->25->570" + "default-mobile.handlebars->9->222", + "default.handlebars->27->617" ] }, { @@ -5128,12 +7107,16 @@ "de": "Knoten löschen", "en": "Delete Nodes", "es": "Borrar Nodos", + "fr": "Supprimer les noeuds", + "hi": "नोड्स हटाएं", "ja": "ノードを削除する", + "ko": "노드 삭제", "nl": "Verwijder apparaten", "pt": "Excluir nós", "ru": "Удалить устройства", + "zh-chs": "刪除節點", "xloc": [ - "default.handlebars->25->397" + "default.handlebars->27->388" ] }, { @@ -5141,10 +7124,16 @@ "de": "Benutzer löschen", "en": "Delete User", "es": "Borrar usuario", + "fr": "Supprimer l'utilisateur", + "hi": "उपभोक्ता मिटायें", + "ja": "ユーザーを削除", + "ko": "사용자 삭제", "nl": "Verwijder gebruiker", + "pt": "Deletar usuário", "ru": "Удалить пользователя", + "zh-chs": "刪除用戶", "xloc": [ - "default.handlebars->25->1352" + "default.handlebars->27->1487" ] }, { @@ -5152,11 +7141,17 @@ "de": "Benutzergruppe löschen", "en": "Delete User Group", "es": "Eliminar Grupo de Usuarios", + "fr": "Supprimer le groupe utilisateurs", + "hi": "उपयोगकर्ता समूह हटाएं", + "ja": "ユーザーグループを削除", + "ko": "사용자 그룹 삭제", "nl": "Verwijder de gebruikersgroep", + "pt": "Excluir grupo de usuários", "ru": "Удалить группу пользователей", + "zh-chs": "刪除用戶組", "xloc": [ - "default.handlebars->25->1302", - "default.handlebars->25->1310" + "default.handlebars->27->1435", + "default.handlebars->27->1443" ] }, { @@ -5164,12 +7159,16 @@ "de": "Benutzer {0} löschen", "en": "Delete User {0}", "es": "Borrar usuario {0}", + "fr": "Supprimer l'utilisateur {0}", + "hi": "उपयोगकर्ता को हटाएं {0}", "ja": "ユーザーを削除{0}", + "ko": "사용자 {0} 삭제", "nl": "Verwijder gebruiker {0}", "pt": "Excluir usuário {0}", "ru": "Удалить пользователя {0}", + "zh-chs": "刪除用戶{0}", "xloc": [ - "default.handlebars->25->1366" + "default.handlebars->27->1504" ] }, { @@ -5177,10 +7176,14 @@ "de": "Konto löschen", "en": "Delete account", "es": "Borrar cuenta", + "fr": "Supprimer le compte", + "hi": "खाता हटा दो", "ja": "アカウントを削除する", + "ko": "계정 삭제", "nl": "Verwijder account", "pt": "Deletar conta", "ru": "Удалить учетную запись", + "zh-chs": "刪除帳戶", "xloc": [ "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3AccountActions->7->7->0", "default.handlebars->container->column_l->p2->p2AccountActions->3->p2AccountPassActions->7" @@ -5191,12 +7194,32 @@ "de": "Geräte löschen", "en": "Delete devices", "es": "Borrar dispositivos", + "fr": "Supprimer les appareils", + "hi": "उपकरणों को हटा दें", "ja": "デバイスを削除する", + "ko": "기기 삭제", "nl": "Verwijder apparaten", "pt": "Excluir Dispositivos", "ru": "Удалить устройства", + "zh-chs": "刪除設備", "xloc": [ - "default.handlebars->25->392" + "default.handlebars->27->383" + ] + }, + { + "cs": "Smazat položku?", + "de": "Element löschen?", + "en": "Delete item?", + "fr": "Supprimer l'item ?", + "hi": "चीज़ें हटाएं?", + "ja": "アイテムを削除しますか?", + "ko": "항목을 삭제 하시겠습니까?", + "nl": "Verwijder item?", + "pt": "Apagar item?", + "ru": "Удалить пункт?", + "zh-chs": "刪除項目?", + "xloc": [ + "default.handlebars->27->418" ] }, { @@ -5204,15 +7227,19 @@ "de": "Ausgewähltes Element löschen?", "en": "Delete selected item?", "es": "¿Eliminar elemento seleccionado?", + "fr": "Supprimer cet élément ?", + "hi": "चयनित आइटम हटाएं?", "ja": "選択したアイテムを削除しますか?", + "ko": "선택한 항목을 삭제 하시겠습니까?", "nl": "Verwijder geselecteerde item?", "pt": "Excluir item selecionado?", "ru": "Удалить выбранные элементы?", + "zh-chs": "刪除所選項目?", "xloc": [ - "default-mobile.handlebars->9->251", - "default-mobile.handlebars->9->83", - "default.handlebars->25->1180", - "default.handlebars->25->659" + "default-mobile.handlebars->9->255", + "default-mobile.handlebars->9->86", + "default.handlebars->27->1310", + "default.handlebars->27->708" ] }, { @@ -5220,10 +7247,16 @@ "de": "Benutzergruppe {0} löschen?", "en": "Delete user group {0}?", "es": "Eliminar Grupo de Usuarios {0}?", + "fr": "Supprimer le groupe utilisateur {0} ?", + "hi": "उपयोगकर्ता समूह {0} हटाएं?", + "ja": "ユーザーグループ{0}を削除しますか?", + "ko": "사용자 그룹 {0}을 (를) 삭제 하시겠습니까?", "nl": "Verwijder gebruikersgroep {0}?", + "pt": "Excluir grupo de usuários {0}?", "ru": "Удалить группу пользователей {0}?", + "zh-chs": "刪除用戶組{0}?", "xloc": [ - "default.handlebars->25->1308" + "default.handlebars->27->1441" ] }, { @@ -5231,15 +7264,19 @@ "de": "{0} ausgewählte Elemente löschen?", "en": "Delete {0} selected items?", "es": "¿Eliminar {0} elementos seleccionados?", + "fr": "Supprimer ces {0} éléments ?", + "hi": "{0} चयनित आइटम हटाएं?", "ja": "選択したアイテム{0}を削除しますか?", + "ko": "선택한 항목 {0}을 (를) 삭제 하시겠습니까?", "nl": "Verwijder {0} gelecteerde items?", "pt": "Excluir {0} itens selecionados?", "ru": "Удалить {0} выбранных элементов?", + "zh-chs": "刪除{0}個所選項目?", "xloc": [ - "default-mobile.handlebars->9->250", - "default-mobile.handlebars->9->82", - "default.handlebars->25->1179", - "default.handlebars->25->658" + "default-mobile.handlebars->9->254", + "default-mobile.handlebars->9->85", + "default.handlebars->27->1309", + "default.handlebars->27->707" ] }, { @@ -5247,12 +7284,16 @@ "de": "{0} löschen?", "en": "Delete {0}?", "es": "Borrar {0}?", + "fr": "Supprimer {0}?", + "hi": "{0} हटाएं?", "ja": "{0}を削除しますか?", + "ko": "{0}을 (를) 삭제 하시겠습니까?", "nl": "Verwijder {0}?", "pt": "Excluir {0}?", "ru": "Удалить {0}?", + "zh-chs": "刪除{0}?", "xloc": [ - "default-mobile.handlebars->9->219" + "default-mobile.handlebars->9->223" ] }, { @@ -5260,10 +7301,14 @@ "de": "Nach Datum absteigend", "en": "Descend by date", "es": "Descendente por fecha", + "fr": "Tri décroissant par date", + "hi": "तिथि के अनुसार उतरना", "ja": "日付で降順", + "ko": "날짜별로 내림차순", "nl": "Aflopend op datum", "pt": "Descrescente por data", "ru": "По дате по убыванию", + "zh-chs": "按日期降序", "xloc": [ "default-mobile.handlebars->container->page_content->column_l->p10->p10files->p13toolbar->1->4->1->1->1->0->3->p13sortdropdown->11", "default-mobile.handlebars->container->page_content->column_l->p5->p5myfiles->p5toolbar->1->2->1->1->1->0->3->p5sortdropdown->11", @@ -5276,10 +7321,14 @@ "de": "Nach Name absteigend", "en": "Descend by name", "es": "Descendente por nombre", + "fr": "Tri décroissant par nom", + "hi": "नाम से उतरना", "ja": "名前で降順", + "ko": "이름으로 내림차순", "nl": "Aflopend op naam", "pt": "Decrescente por nome", "ru": "По имени по убыванию", + "zh-chs": "按名稱降序", "xloc": [ "default-mobile.handlebars->container->page_content->column_l->p10->p10files->p13toolbar->1->4->1->1->1->0->3->p13sortdropdown->7", "default-mobile.handlebars->container->page_content->column_l->p5->p5myfiles->p5toolbar->1->2->1->1->1->0->3->p5sortdropdown->7", @@ -5292,10 +7341,14 @@ "de": "Nach Größe absteigend", "en": "Descend by size", "es": "Descendente por tamano", + "fr": "Tri décroissant par taille", + "hi": "आकार द्वारा उतरना", "ja": "サイズで降順", + "ko": "크기로 내림차순", "nl": "Aflopend op grootte", "pt": "Decrescente por tamanho", "ru": "По размеру по убыванию", + "zh-chs": "按大小下降", "xloc": [ "default-mobile.handlebars->container->page_content->column_l->p10->p10files->p13toolbar->1->4->1->1->1->0->3->p13sortdropdown->9", "default-mobile.handlebars->container->page_content->column_l->p5->p5myfiles->p5toolbar->1->2->1->1->1->0->3->p5sortdropdown->9", @@ -5308,28 +7361,33 @@ "de": "Beschreibung", "en": "Description", "es": "Descripción", + "fr": "Description", + "hi": "विवरण", "ja": "説明", + "ko": "기술", "nl": "Omschrijving", "pt": "Descrição", "ru": "Описание", + "zh-chs": "描述", "xloc": [ - "default-mobile.handlebars->9->141", - "default-mobile.handlebars->9->142", - "default-mobile.handlebars->9->224", - "default-mobile.handlebars->9->277", - "default-mobile.handlebars->9->290", - "default-mobile.handlebars->9->60", - "default.handlebars->25->1067", - "default.handlebars->25->1276", - "default.handlebars->25->1281", - "default.handlebars->25->1283", - "default.handlebars->25->1306", - "default.handlebars->25->450", - "default.handlebars->25->451", - "default.handlebars->25->601", - "default.handlebars->25->95", - "default.handlebars->25->959", - "default.handlebars->25->983", + "default-mobile.handlebars->9->145", + "default-mobile.handlebars->9->146", + "default-mobile.handlebars->9->228", + "default-mobile.handlebars->9->281", + "default-mobile.handlebars->9->294", + "default-mobile.handlebars->9->63", + "default.handlebars->27->1064", + "default.handlebars->27->1088", + "default.handlebars->27->1171", + "default.handlebars->27->1412", + "default.handlebars->27->1417", + "default.handlebars->27->1419", + "default.handlebars->27->1439", + "default.handlebars->27->457", + "default.handlebars->27->458", + "default.handlebars->27->649", + "default.handlebars->27->752", + "default.handlebars->27->78", "default.handlebars->container->column_l->p42->p42tbl->1->0->3" ] }, @@ -5338,23 +7396,31 @@ "de": "DeskControl", "en": "DeskControl", "es": "Control de escritorio", + "fr": "DeskControl", + "hi": "DeskControl", "ja": "DeskControl", + "ko": "데스크 컨트롤", "nl": "Besturing", "pt": "DeskControl", - "ru": "Управление рабочего стола" + "ru": "Управление рабочего стола", + "zh-chs": "桌面控制" }, { "cs": "Plocha", "de": "Desktop", "en": "Desktop", "es": "Escritorio", + "fr": "Bureau", + "hi": "डेस्कटॉप", "ja": "デスクトップ", + "ko": "데스크탑", "nl": "Bureaublad", "pt": "Área de Trabalho", "ru": "Рабочий стол", + "zh-chs": "桌面", "xloc": [ - "default.handlebars->25->1069", - "default.handlebars->25->419", + "default.handlebars->27->1173", + "default.handlebars->27->423", "default.handlebars->container->topbar->1->1->MainSubMenuSpan->MainSubMenu->1->0->MainDevDesktop", "default.handlebars->contextMenu->cxdesktop" ] @@ -5364,10 +7430,14 @@ "de": "Desktop -", "en": "Desktop -", "es": "Escritorio -", + "fr": "Bureau -", + "hi": "डेस्कटॉप -", "ja": "デスクトップ-", + "ko": "데스크톱-", "nl": "Bureaublad - ", "pt": "Área de Trabalho - ", "ru": "Рабочий стол - ", + "zh-chs": "桌面 -", "xloc": [ "default.handlebars->container->column_l->p11->p11title->p11deviceNameHeader->5" ] @@ -5377,12 +7447,16 @@ "de": "Desktop-Benachrichtigung", "en": "Desktop Notify", "es": "Notificación de escritorio", + "fr": "Notifier l'utilisateur (Bureau)", + "hi": "डेस्कटॉप सूचित करें", "ja": "デスクトップ通知", + "ko": "데스크톱 알림", "nl": "Bureaublad melding", "pt": "Notificação na área de trabalho", "ru": "Уведомление на рабочем столе", + "zh-chs": "桌面通知", "xloc": [ - "default.handlebars->25->993" + "default.handlebars->27->1098" ] }, { @@ -5390,12 +7464,16 @@ "de": "Desktop-Einverständnis", "en": "Desktop Prompt", "es": "Mensaje de escritorio", + "fr": "Confirmation de l'utilisateur (Bureau)", + "hi": "डेस्कटॉप प्रॉम्प्ट", "ja": "デスクトッププロンプト", + "ko": "데스크탑 프롬프트", "nl": "Bureaublad vraag", "pt": "Prompt da área de trabalho", "ru": "Запрос рабочего стола", + "zh-chs": "桌面提示", "xloc": [ - "default.handlebars->25->992" + "default.handlebars->27->1097" ] }, { @@ -5403,12 +7481,16 @@ "de": "Desktop-Einverständnis & -Werkzeugleiste", "en": "Desktop Prompt+Toolbar", "es": "Mensaje de escritorio + barra de herramientas", + "fr": "Invite du bureau + barre d'outils", + "hi": "डेस्कटॉप प्रॉम्प्ट + टूलबार", "ja": "デスクトッププロンプト+ツールバー", + "ko": "데스크톱 프롬프트 + 도구 모음", "nl": "Bureaublad vraag en werkbalk", "pt": "Prompt da área de trabalho + barra de ferramentas", "ru": "Запрос рабочего стола + панель инструментов", + "zh-chs": "桌面提示+工具欄", "xloc": [ - "default.handlebars->25->990" + "default.handlebars->27->1095" ] }, { @@ -5416,12 +7498,16 @@ "de": "Desktop-Werkzeugleiste", "en": "Desktop Toolbar", "es": "Barra de herramientas de escritorio", + "fr": "Barre d'outils du bureau", + "hi": "डेस्कटॉप टूलबार", "ja": "デスクトップツールバー", + "ko": "데스크탑 툴바", "nl": "Bureaublad werkbalk", "pt": "Barra de ferramentas da área de trabalho", "ru": "Панель инструментов рабочего стола", + "zh-chs": "桌面工具欄", "xloc": [ - "default.handlebars->25->991" + "default.handlebars->27->1096" ] }, { @@ -5429,10 +7515,14 @@ "de": "Desktops", "en": "Desktops", "es": "Escritorios", + "fr": "Bureaux", + "hi": "डेस्कटॉप", "ja": "デスクトップ", + "ko": "데스크탑", "nl": "Bureaubladen", "pt": "Áreas de trabalho", "ru": "Экраны", + "zh-chs": "台式機", "xloc": [ "default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->9->devListToolbarView->viewselect->5", "default.handlebars->container->column_l->p1->p1title->devListToolbarViewIcons" @@ -5443,10 +7533,14 @@ "de": "Details", "en": "Details", "es": "Detalles", + "fr": "Détails", + "hi": "विवरण", "ja": "詳細", + "ko": "세부", "nl": "Details", "pt": "Detalhes", "ru": "Детали", + "zh-chs": "細節", "xloc": [ "default.handlebars->container->topbar->1->1->MainSubMenuSpan->MainSubMenu->1->0->MainDevInfo" ] @@ -5456,10 +7550,14 @@ "de": "Details -", "en": "Details -", "es": "Detalles -", + "fr": "Détails -", + "hi": "विवरण -", "ja": "詳細-", + "ko": "세부 사항-", "nl": "Details -", "pt": "Detalhes - ", "ru": "Детали - ", + "zh-chs": "細節 -", "xloc": [ "default.handlebars->container->column_l->p17->p17title->3" ] @@ -5469,11 +7567,17 @@ "de": "Gerät", "en": "Device", "es": "Dispositivo", + "fr": "Appareil", + "hi": "युक्ति", "ja": "デバイス", + "ko": "장치", "nl": "Apparaat", "pt": "Dispositivo", "ru": "Устройство", + "zh-chs": "設備", "xloc": [ + "default.handlebars->27->1195", + "default.handlebars->27->1510", "default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->9->devListToolbarSort->sortselect->5" ] }, @@ -5482,13 +7586,17 @@ "de": "Geräteaktion", "en": "Device Action", "es": "Acción del dispositivo", + "fr": "Action du périphérique", + "hi": "डिवाइस एक्शन", "ja": "デバイスアクション", + "ko": "장치 동작", "nl": "Apparaatactie", "pt": "Ação do dispositivo", "ru": "Управление устройством", + "zh-chs": "設備動作", "xloc": [ - "default-mobile.handlebars->9->211", - "default.handlebars->25->543" + "default-mobile.handlebars->9->215", + "default.handlebars->27->590" ] }, { @@ -5496,14 +7604,20 @@ "de": "Gerätegruppe", "en": "Device Group", "es": "Grupo de dispositivos", + "fr": "Groupe d'appareils", + "hi": "डिवाइस समूह", + "ja": "デバイスグループ", + "ko": "장치 그룹", "nl": "Apparaat Groep", + "pt": "Grupo de dispositivos", "ru": "Группа устройства", + "zh-chs": "設備組", "xloc": [ - "default.handlebars->25->1086", - "default.handlebars->25->1088", - "default.handlebars->25->1300", - "default.handlebars->25->1374", - "default.handlebars->25->1380" + "default.handlebars->27->1191", + "default.handlebars->27->1193", + "default.handlebars->27->1194", + "default.handlebars->27->1433", + "default.handlebars->27->1516" ] }, { @@ -5511,13 +7625,17 @@ "de": "Gerätegruppenbenutzer", "en": "Device Group User", "es": "Usuario de grupo de dispositivos", + "fr": "Utilisateur du groupe", + "hi": "डिवाइस समूह उपयोगकर्ता", "ja": "デバイスグループユーザー", + "ko": "장치 그룹 사용자", "nl": "Apparaatgroep gebruiker", "pt": "Usuário do grupo de dispositivos", "ru": "Пользователь группы устройств", + "zh-chs": "設備組用戶", "xloc": [ - "default-mobile.handlebars->9->331", - "default.handlebars->25->1136" + "default-mobile.handlebars->9->335", + "default.handlebars->27->1249" ] }, { @@ -5525,30 +7643,54 @@ "de": "Gerätegruppen", "en": "Device Groups", "es": "Grupos de dispositivos", + "fr": "Groupes d'appareils", + "hi": "डिवाइस समूह", "ja": "デバイスグループ", + "ko": "장치 그룹", "nl": "Apparaatgroepen", "pt": "Grupos de dispositivos", "ru": "Группы устройств", + "zh-chs": "設備組", "xloc": [ "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->3", - "default.handlebars->25->1272", - "default.handlebars->25->1285", - "default.handlebars->25->1340", - "default.handlebars->25->1413", + "default.handlebars->27->1408", + "default.handlebars->27->1421", + "default.handlebars->27->1474", + "default.handlebars->27->1560", "default.handlebars->container->column_l->p2->9" ] }, + { + "cs": "Export informací o zařízení", + "de": "Geräteinformationsexport", + "en": "Device Information Export", + "fr": "Export des informations sur les appareils", + "hi": "डिवाइस सूचना निर्यात", + "ja": "デバイス情報のエクスポート", + "ko": "장치 정보 내보내기", + "nl": "Apparaat informatie export", + "pt": "Exportação de informações do dispositivo", + "ru": "Экспорт информации об устройстве", + "zh-chs": "設備信息導出", + "xloc": [ + "default.handlebars->27->394" + ] + }, { "cs": "Umístění zařízení", "de": "Gerätestandort", "en": "Device Location", "es": "Ubicación del dispositivo", + "fr": "Emplacement de l'appareil", + "hi": "उपकरण का स्थान", "ja": "デバイスの場所", + "ko": "장치 위치", "nl": "Apparaat locatie", "pt": "Localização do dispositivo", "ru": "Местонахождение устройства", + "zh-chs": "設備位置", "xloc": [ - "default.handlebars->25->571" + "default.handlebars->27->618" ] }, { @@ -5556,14 +7698,18 @@ "de": "Gerätename", "en": "Device Name", "es": "Nombre del dispositivo", + "fr": "Nom de l'appareil", + "hi": "यन्त्र का नाम", "ja": "装置名", + "ko": "장치 이름", "nl": "Apparaat naam", "pt": "Nome do Dispositivo", "ru": "Имя устройства", + "zh-chs": "設備名稱", "xloc": [ - "default-mobile.handlebars->9->222", - "default.handlebars->25->238", - "default.handlebars->25->599", + "default-mobile.handlebars->9->226", + "default.handlebars->27->222", + "default.handlebars->27->647", "player.handlebars->3->9" ] }, @@ -5572,12 +7718,16 @@ "de": "Gerätebenachrichtigung", "en": "Device Notification", "es": "Notificación de dispositivo", + "fr": "Notification de l'appareil", + "hi": "डिवाइस अधिसूचना", "ja": "デバイス通知", + "ko": "장치 알림", "nl": "Apparaatmelding", "pt": "Notificação de dispositivo", "ru": "Уведомление устройства", + "zh-chs": "設備通知", "xloc": [ - "default.handlebars->25->534" + "default.handlebars->27->581" ] }, { @@ -5585,12 +7735,16 @@ "de": "Geräte-Toast", "en": "Device Toast", "es": "Dispositivo tostado", + "fr": "Toast de l'appareil", + "hi": "डिवाइस टोस्ट", "ja": "デバイストースト", + "ko": "장치 토스트", "nl": "Device Toast", "pt": "Brinde do dispositivo", "ru": "Уведомление устройства в трее", + "zh-chs": "設備吐司", "xloc": [ - "default-mobile.handlebars->9->204" + "default-mobile.handlebars->9->208" ] }, { @@ -5598,13 +7752,17 @@ "de": "Geräteverbindungen.", "en": "Device connections.", "es": "Conexiones de dispositivo.", + "fr": "Connexions des appareils.", + "hi": "डिवाइस कनेक्शन।", "ja": "デバイス接続。", + "ko": "장치 연결.", "nl": "Apparaat verbindingen.", "pt": "Conexões de dispositivos.", "ru": "Подключения устройств.", + "zh-chs": "設備連接。", "xloc": [ - "default.handlebars->25->1140", - "default.handlebars->25->927" + "default.handlebars->27->1032", + "default.handlebars->27->1268" ] }, { @@ -5612,13 +7770,17 @@ "de": "Gerätetrennungen.", "en": "Device disconnections.", "es": "Desconexiones de dispositivos.", + "fr": "Déconnexions des appareils.", + "hi": "डिवाइस डिस्कनेक्ट।", "ja": "デバイスの切断。", + "ko": "장치 연결이 끊어졌습니다.", "nl": "Apparaat verbroken.", "pt": "Desconexões de dispositivos.", "ru": "Отключения устройств.", + "zh-chs": "設備斷開連接。", "xloc": [ - "default.handlebars->25->1141", - "default.handlebars->25->928" + "default.handlebars->27->1033", + "default.handlebars->27->1269" ] }, { @@ -5626,12 +7788,16 @@ "de": "Gerätegruppennotizen können von anderen Gerätegruppenadministratoren eingesehen und verändert werden.", "en": "Device group notes can be viewed and changed by other device group administrators.", "es": "Las notas del grupo de dispositivos pueden ser vistas y modificadas por otros administradores de grupos de dispositivos.", + "fr": "Les notes de groupes peuvent être vues et modifiées par les autres administrateurs de groupes.", + "hi": "डिवाइस समूह नोटों को अन्य डिवाइस ग्रुप एडमिनिस्ट्रेटर द्वारा देखा और बदला जा सकता है।", "ja": "デバイスグループのメモは、他のデバイスグループ管理者が表示および変更できます。", + "ko": "다른 장치 그룹 관리자가 장치 그룹 메모를보고 변경할 수 있습니다.", "nl": "Apparaatgroepnotities kunnen worden bekeken en gewijzigd door andere apparaatgroepbeheerders.", "pt": "As notas do grupo de dispositivos podem ser visualizadas e alteradas por outros administradores do grupo de dispositivos.", "ru": "Примечания могут быть просмотрены и изменены другими администраторами.", + "zh-chs": "其他設備組管理員可以查看和更改設備組註釋。", "xloc": [ - "default.handlebars->25->532" + "default.handlebars->27->579" ] }, { @@ -5639,12 +7805,16 @@ "de": "Gerät wurde erkannt, aber der Energiezustand konnte nicht ermittelt werden.", "en": "Device is detected but power state could not be obtained.", "es": "Se detecta el dispositivo pero no se pudo obtener el estado de alimentación.", + "fr": "L'appareil est détecté mais impossible de déterminer l'état de l'alimentation.", + "hi": "डिवाइस का पता चला है लेकिन पावर स्टेट प्राप्त नहीं किया जा सका है।", "ja": "デバイスは検出されましたが、電源状態を取得できませんでした。", + "ko": "장치가 감지되었지만 전원 상태를 얻을 수 없습니다.", "nl": "Apparaat is gedetecteerd, maar de status kon niet worden verkregen.", "pt": "O dispositivo foi detectado, mas não foi possível obter o estado de energia.", "ru": "Устройство обнаружено, но состояние питания не может быть получено.", + "zh-chs": "檢測到設備,但無法獲得電源狀態。", "xloc": [ - "default.handlebars->25->361" + "default.handlebars->27->351" ] }, { @@ -5652,13 +7822,17 @@ "de": "Gerät ist im Ruhezustand (S4)", "en": "Device is hibernating (S4)", "es": "El dispositivo está hibernando (S4)", + "fr": "L'appareil est en veille profonde (S4)", + "hi": "डिवाइस हाइबरनेट कर रहा है (S4)", "ja": "デバイスは休止状態です(S4)", + "ko": "장치가 최대 절전 모드입니다 (S4)", "nl": "Apparaat is in slaapstand (S4)", "pt": "O dispositivo está hibernando (S4)", "ru": "Устройство находится в режиме гибернации (S4)", + "zh-chs": "設備正在休眠(S4)", "xloc": [ - "default-mobile.handlebars->9->118", - "default.handlebars->25->367" + "default-mobile.handlebars->9->122", + "default.handlebars->27->357" ] }, { @@ -5666,13 +7840,17 @@ "de": "Gerät befindet sich im Tiefschlafzustand (S3)", "en": "Device is in deep sleep state (S3)", "es": "El dispositivo está en estado de reposo (S3)", + "fr": "L'appareil est en veille profonde (S3)", + "hi": "डिवाइस गहरी नींद की स्थिति में है (S3)", "ja": "デバイスはディープスリープ状態です(S3)", + "ko": "장치가 최대 절전 상태에 있음 (S3)", "nl": "Apparaat bevindt zich in diepe slaapstand (S3)", "pt": "O dispositivo está no estado de sono profundo (S3)", "ru": "Устройство находится в состоянии глубокого сна (S3)", + "zh-chs": "設備處於深度睡眠狀態(S3)", "xloc": [ - "default-mobile.handlebars->9->117", - "default.handlebars->25->366" + "default-mobile.handlebars->9->121", + "default.handlebars->27->356" ] }, { @@ -5680,12 +7858,16 @@ "de": "Gerät befindet sich im Tiefschlafzustand (S3).", "en": "Device is in deep sleep state (S3).", "es": "El dispositivo está en estado de reposo (S3)", + "fr": "L'appareil est en veille profonde (S3).", + "hi": "डिवाइस गहरी नींद की स्थिति (S3) में है।", "ja": "デバイスはディープスリープ状態(S3)です。", + "ko": "장치가 최대 절전 상태입니다 (S3).", "nl": "Apparaat bevindt zich in diepe slaapstand (S3).", "pt": "O dispositivo está no estado de suspensão profunda (S3).", "ru": "Устройство находится в состоянии глубокого сна (S3).", + "zh-chs": "設備處於深度睡眠狀態(S3)。", "xloc": [ - "default.handlebars->25->355" + "default.handlebars->27->345" ] }, { @@ -5693,12 +7875,16 @@ "de": "Gerät befindet sich im Ruhezustand (S4).", "en": "Device is in hibernating state (S4).", "es": "El dispositivo está en estado de hibernacion (S4)", + "fr": "L'appareil est en veille profonde (S4).", + "hi": "डिवाइस हाइबरनेटिंग स्थिति (S4) में है।", "ja": "デバイスは休止状態です(S4)。", + "ko": "장치가 최대 절전 상태입니다 (S4).", "nl": "Apparaat bevindt zich in de slaapstand (S4).", "pt": "O dispositivo está no estado de hibernação (S4).", "ru": "Устройство находится в режиме гибернации (S4).", + "zh-chs": "設備處於休眠狀態(S4)。", "xloc": [ - "default.handlebars->25->357" + "default.handlebars->27->347" ] }, { @@ -5706,12 +7892,16 @@ "de": "Gerät ist ausgeschaltet (S5).", "en": "Device is in powered off state (S5).", "es": "El dispositivo está apagado (S5)", + "fr": "L'appareil est arrêté (S5)", + "hi": "डिवाइस पावर्ड ऑफ स्टेट (S5) में है।", "ja": "デバイスは電源オフ状態です(S5)。", + "ko": "장치의 전원이 꺼진 상태입니다 (S5).", "nl": "Apparaat is uitgeschakeld (S5).", "pt": "O dispositivo está no estado desligado (S5).", "ru": "Устройство находится в выключенном состоянии (S5).", + "zh-chs": "設備處於關機狀態(S5)。", "xloc": [ - "default.handlebars->25->359" + "default.handlebars->27->349" ] }, { @@ -5719,13 +7909,17 @@ "de": "Gerät befindet sich im Schlafzustand (S1)", "en": "Device is in sleep state (S1)", "es": "El dispositivo está en estado de suspensión (S1)", + "fr": "L'appareil est en veille (S1)", + "hi": "डिवाइस स्लीप अवस्था में है (S1)", "ja": "デバイスはスリープ状態です(S1)", + "ko": "장치가 절전 상태입니다 (S1)", "nl": "Apparaat bevindt zich in slaapstand (S1)", "pt": "O dispositivo está no estado de suspensão (S1)", "ru": "Устройство находится в спящем режиме (S1)", + "zh-chs": "設備處於睡眠狀態(S1)", "xloc": [ - "default-mobile.handlebars->9->115", - "default.handlebars->25->364" + "default-mobile.handlebars->9->119", + "default.handlebars->27->354" ] }, { @@ -5733,12 +7927,16 @@ "de": "Gerät befindet sich im Schlafzustand (S1).", "en": "Device is in sleep state (S1).", "es": "El dispositivo está en estado de suspensión (S1)", + "fr": "L'appareil est en veille (S1).", + "hi": "डिवाइस स्लीप अवस्था (S1) में है।", "ja": "デバイスはスリープ状態(S1)です。", + "ko": "장치가 절전 상태입니다 (S1).", "nl": "Apparaat bevindt zich in slaapstand (S1).", "pt": "O dispositivo está no estado de suspensão (S1).", "ru": "Устройство находится в спящем режиме (S1).", + "zh-chs": "設備處於睡眠狀態(S1)。", "xloc": [ - "default.handlebars->25->351" + "default.handlebars->27->341" ] }, { @@ -5746,13 +7944,17 @@ "de": "Gerät befindet sich im Schlafzustand (S2)", "en": "Device is in sleep state (S2)", "es": "El dispositivo está en estado de suspensión (S2)", + "fr": "L'appareil est en veille (S2)", + "hi": "डिवाइस स्लीप अवस्था में है (S2)", "ja": "デバイスはスリープ状態です(S2)", + "ko": "장치가 절전 상태입니다 (S2)", "nl": "Apparaat bevindt zich in slaapstand (S2)", "pt": "O dispositivo está no estado de suspensão (S2)", "ru": "Устройство находится в спящем режиме (S2)", + "zh-chs": "設備處於睡眠狀態(S2)", "xloc": [ - "default-mobile.handlebars->9->116", - "default.handlebars->25->365" + "default-mobile.handlebars->9->120", + "default.handlebars->27->355" ] }, { @@ -5760,12 +7962,16 @@ "de": "Gerät befindet sich im Schlafzustand (S2).", "en": "Device is in sleep state (S2).", "es": "El dispositivo está en estado de suspensión (S2)", + "fr": "L'appareil est en veille (S2).", + "hi": "डिवाइस स्लीप अवस्था (S2) में है।", "ja": "デバイスはスリープ状態(S2)です。", + "ko": "장치가 절전 상태입니다 (S2).", "nl": "Apparaat bevindt zich in slaapstand (S2).", "pt": "O dispositivo está no estado de suspensão (S2).", "ru": "Устройство находится в спящем режиме (S2).", + "zh-chs": "設備處於睡眠狀態(S2)。", "xloc": [ - "default.handlebars->25->353" + "default.handlebars->27->343" ] }, { @@ -5773,13 +7979,17 @@ "de": "Gerät ist im Soft-Off-Zustand (S5)", "en": "Device is in soft-off state (S5)", "es": "El dispositivo está en estado de apagado (S5)", + "fr": "L'appareil est arrêté (S5)", + "hi": "डिवाइस नरम-बंद स्थिति (S5) में है", "ja": "デバイスはソフトオフ状態です(S5)", + "ko": "장치가 소프트 오프 상태입니다 (S5)", "nl": "Apparaat is uitgeschakeld (S5)", "pt": "O dispositivo está no estado soft-off (S5)", "ru": "Устройство находится в выключенном состоянии (S5)", + "zh-chs": "設備處於軟斷開狀態(S5)", "xloc": [ - "default-mobile.handlebars->9->119", - "default.handlebars->25->368" + "default-mobile.handlebars->9->123", + "default.handlebars->27->358" ] }, { @@ -5787,13 +7997,17 @@ "de": "Gerät ist eingeschaltet", "en": "Device is powered", "es": "El dispositivo está conectado", + "fr": "L'appareil est allumé", + "hi": "डिवाइस संचालित है", "ja": "デバイスに電源が入っています", + "ko": "장치 전원 공급", "nl": "Apparaat is ingeschakeld", "pt": "O dispositivo está ligado", "ru": "Устройство включено", + "zh-chs": "設備已上電", "xloc": [ - "default-mobile.handlebars->9->114", - "default.handlebars->25->363" + "default-mobile.handlebars->9->118", + "default.handlebars->27->353" ] }, { @@ -5801,12 +8015,16 @@ "de": "Gerät ist eingeschaltet.", "en": "Device is powered on.", "es": "El dispositivo está prendido.", + "fr": "L'appareil est mis sous tension.", + "hi": "डिवाइस चालू है।", "ja": "デバイスの電源が入っています。", + "ko": "장치의 전원이 켜져 있습니다.", "nl": "Apparaat is ingeschakeld.", "pt": "O dispositivo está ligado.", "ru": "Устройство включено.", + "zh-chs": "設備上電。", "xloc": [ - "default.handlebars->25->349" + "default.handlebars->27->339" ] }, { @@ -5814,13 +8032,17 @@ "de": "Gerät ist präsent, aber der Energiezustand kann nicht ermittelt werden", "en": "Device is present, but power state cannot be determined", "es": "El dispositivo está presente, pero no se puede determinar el estado de energía", + "fr": "L'appareil est connecté mais impossible de déterminer l'état de l'alimentation", + "hi": "डिवाइस मौजूद है, लेकिन पावर स्टेट निर्धारित नहीं किया जा सकता है", "ja": "デバイスは存在しますが、電源状態を判別できません", + "ko": "장치가 있지만 전원 상태를 확인할 수 없습니다", "nl": "Apparaat is aanwezig, maar de status kan niet worden bepaald", "pt": "O dispositivo está presente, mas o estado de energia não pode ser determinado", "ru": "Устройство присутствует, но состояние питания не может быть определено", + "zh-chs": "設備存在,但無法確定電源狀態", "xloc": [ - "default-mobile.handlebars->9->120", - "default.handlebars->25->369" + "default-mobile.handlebars->9->124", + "default.handlebars->27->359" ] }, { @@ -5828,12 +8050,16 @@ "de": "Gerätename", "en": "Device name", "es": "Nombre del dispositivo", + "fr": "Nom de l'appareil", + "hi": "यन्त्र का नाम", "ja": "装置名", + "ko": "장치 이름", "nl": "Apparaat naam", "pt": "Nome do dispositivo", "ru": "Имя устройства", + "zh-chs": "設備名稱", "xloc": [ - "default.handlebars->25->431" + "default.handlebars->27->435" ] }, { @@ -5841,12 +8067,16 @@ "de": "DeviceCheckbox", "en": "DeviceCheckbox", "es": "Casilla de verificación del dispositivo", + "fr": "DeviceCheckbox", + "hi": "DeviceCheckbox", "ja": "DeviceCheckbox", + "ko": "DeviceCheckbox", "nl": "DeviceCheckbox", "pt": "DeviceCheckbox", "ru": "DeviceCheckbox", + "zh-chs": "設備複選框", "xloc": [ - "default.handlebars->25->394" + "default.handlebars->27->385" ] }, { @@ -5854,12 +8084,16 @@ "de": "Deaktiviert", "en": "Disabled", "es": "Deshabilitado", + "fr": "Désactivé", + "hi": "विकलांग", "ja": "無効", + "ko": "비활성화", "nl": "Uitgeschakeld", "pt": "Desativado", "ru": "Отключено", + "zh-chs": "殘障人士", "xloc": [ - "default.handlebars->25->477" + "default.handlebars->27->484" ] }, { @@ -5867,15 +8101,19 @@ "de": "Trennen", "en": "Disconnect", "es": "Desconectar", + "fr": "Déconnecter", + "hi": "डिस्कनेक्ट", "ja": "切断する", + "ko": "분리", "nl": "Verbreken", "pt": "Desconectar", "ru": "Разъединить", + "zh-chs": "斷開", "xloc": [ - "default-mobile.handlebars->9->237", + "default-mobile.handlebars->9->241", "default-mobile.handlebars->container->page_content->column_l->p10->p10desktop->deskarea1->1->3", - "default.handlebars->25->1003", - "default.handlebars->25->648", + "default.handlebars->27->1108", + "default.handlebars->27->697", "default.handlebars->container->column_l->p11->deskarea0->deskarea1->3->disconnectbutton1span", "default.handlebars->container->column_l->p12->termTable->1->1->0->1->3->disconnectbutton2span", "xterm.handlebars->p11->deskarea0->deskarea1->3" @@ -5886,10 +8124,14 @@ "de": "Alle trennen", "en": "Disconnect All", "es": "Desconectar Todo", + "fr": "Déconnecter tout", + "hi": "सभी को डिस्कनेक्ट करें", "ja": "すべて切断", + "ko": "모두 분리", "nl": "Verbreek alles", "pt": "Desconectar todos", "ru": "Разъединить все", + "zh-chs": "全部斷開", "xloc": [ "default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->kvmListToolbar" ] @@ -5900,19 +8142,22 @@ "en": "Disconnected", "es": "Desconectado", "fr": "Débranché", + "hi": "डिस्कनेक्ट किया गया", "ja": "切断されました", + "ko": "연결 해제", "nl": "Verbroken", "pt": "Desconectado", "ru": "Отключен", + "zh-chs": "斷線", "xloc": [ "default-mobile.handlebars->9->1", "default-mobile.handlebars->container->page_content->column_l->p10->p10desktop->deskarea1->1->3->deskstatus", "default-mobile.handlebars->container->page_content->column_l->p10->p10files->p13toolbar->1->0->1->3->p13Status", - "default.handlebars->25->193", - "default.handlebars->25->210", - "default.handlebars->25->213", - "default.handlebars->25->219", - "default.handlebars->25->8", + "default.handlebars->27->177", + "default.handlebars->27->194", + "default.handlebars->27->197", + "default.handlebars->27->203", + "default.handlebars->27->8", "default.handlebars->container->column_l->p11->deskarea0->deskarea1->3->deskstatus", "default.handlebars->container->column_l->p12->termTable->1->1->0->1->3->termstatus", "default.handlebars->container->column_l->p13->p13toolbar->1->0->1->3->p13Status", @@ -5924,10 +8169,14 @@ "de": "Eine Benachrichtigung auf dem entfernten Rechner anzeigen", "en": "Display a notification on the remote computer", "es": "Mostrar una notificación en la computadora remota", + "fr": "Afficher une notification sur l'ordinateur distant", + "hi": "दूरस्थ कंप्यूटर पर एक सूचना प्रदर्शित करें", "ja": "リモートコンピューターに通知を表示する", + "ko": "원격 컴퓨터에 알림 표시", "nl": "Toon een melding op de externe computer", "pt": "Exibir uma notificação no computador remoto", "ru": "Отобразить уведомление на удаленном компьютере", + "zh-chs": "在遠程計算機上顯示通知", "xloc": [ "default.handlebars->container->column_l->p11->deskarea0->deskarea4->1" ] @@ -5937,10 +8186,16 @@ "de": "Gerätegruppenname anzeigen", "en": "Display device group name", "es": "Mostrar el nombre del grupo de dispositivos", + "fr": "Afficher le nom du groupe d'appareil", + "hi": "डिवाइस समूह का नाम प्रदर्शित करें", + "ja": "デバイスグループ名を表示する", + "ko": "장치 그룹 이름 표시", "nl": "Toon apparaatgroepsnaam", + "pt": "Exibir nome do grupo de dispositivos", "ru": "Отобразить имя группы устройств", + "zh-chs": "顯示設備組名稱", "xloc": [ - "default.handlebars->25->926" + "default.handlebars->27->1031" ] }, { @@ -5948,12 +8203,29 @@ "de": "Anzeigename", "en": "Display name", "es": "Nombre para mostrar", + "fr": "Nom", + "hi": "प्रदर्शित होने वाला नाम", "ja": "表示名", + "ko": "이름 표시하기", "nl": "Schermnaam", "pt": "Mostrar nome", "ru": "Отображаемое имя", + "zh-chs": "顯示名稱", "xloc": [ - "default.handlebars->25->619" + "default.handlebars->27->668" + ] + }, + { + "cs": "Zobrazit veřejný odkaz", + "de": "Öffentlichen Link anzeigen", + "en": "Display public link", + "fr": "Afficher le lien public", + "ja": "公開リンクを表示", + "nl": "Openbare link weergeven", + "ru": "Показать публичную ссылку", + "zh-chs": "显示公共链接", + "xloc": [ + "default.handlebars->27->1286" ] }, { @@ -5961,12 +8233,16 @@ "de": "Nichts tun", "en": "Do nothing", "es": "No Hacer Nada...", + "fr": "Ne rien faire", + "hi": "कुछ मत करो", "ja": "何もしない", + "ko": "아무것도하지 마세요", "nl": "Doe niets", "pt": "Fazer nada", "ru": "Ничего не делать", + "zh-chs": "沒做什麼", "xloc": [ - "default.handlebars->25->1048" + "default.handlebars->27->1152" ] }, { @@ -5974,10 +8250,14 @@ "de": "Sie haben kein Konto?", "en": "Don't have an account?", "es": "No tienes una cuenta?", + "fr": "Pas encore de compte ?", + "hi": "खाता नहीं है?", "ja": "アカウントを持っていないのですか?", + "ko": "계정이 없습니까?", "nl": "Heb je nog geen account?", "pt": "Não possui uma conta?", "ru": "Нет учетной записи?", + "zh-chs": "還沒有帳號?", "xloc": [ "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->loginpanel->1->newAccountDiv", "login.handlebars->container->column_l->centralTable->1->0->logincell->loginpanel->1->newAccountDiv" @@ -5988,13 +8268,17 @@ "de": "Nicht konfigurieren", "en": "Don\\'t configure", "es": "No configurar", + "fr": "Ne pas configurer", + "hi": "कॉन्फ़िगर नहीं है", "ja": "設定しないでください", + "ko": "구성하지 마십시오", "nl": "Niet configureren", "pt": "Não configure", "ru": "Не настраивать", + "zh-chs": "不要配置", "xloc": [ - "default.handlebars->25->1052", - "default.handlebars->25->1057" + "default.handlebars->27->1156", + "default.handlebars->27->1161" ] }, { @@ -6002,12 +8286,16 @@ "de": "Nicht mit Server verbinden", "en": "Don\\'t connect to server", "es": "No te conectes al servidor", + "fr": "Ne pas se connecter au serveur", + "hi": "सर्वर से कनेक्ट नहीं है", "ja": "サーバーに接続しない", + "ko": "서버에 연결하지 마십시오", "nl": "Maak geen verbinding met de server", "pt": "Não conecte ao servidor", "ru": "Не подключаться к серверу", + "zh-chs": "不連接服務器", "xloc": [ - "default.handlebars->25->1053" + "default.handlebars->27->1157" ] }, { @@ -6016,10 +8304,13 @@ "en": "Download", "es": "Descargar", "fr": "Télécharger", + "hi": "डाउनलोड", "ja": "ダウンロード", + "ko": "다운로드", "nl": "Download", "pt": "Baixar", "ru": "Скачать", + "zh-chs": "下載", "xloc": [ "download.handlebars->container->page_content->column_l->1" ] @@ -6029,10 +8320,14 @@ "de": "Ereignisse herunterladen", "en": "Download Events", "es": "Descargar eventos", + "fr": "Télécharger les évènements", + "hi": "घटनाक्रम डाउनलोड करें", "ja": "イベントをダウンロードする", + "ko": "이벤트 다운로드", "nl": "Download gebeurtenissen", "pt": "Download de Eventos", "ru": "Скачать события", + "zh-chs": "下載活動", "xloc": [ "default.handlebars->container->column_l->p16->3->1->0->5->3", "default.handlebars->container->column_l->p3->3->1->0->3->3", @@ -6044,13 +8339,17 @@ "de": "Datei herunterladen", "en": "Download File", "es": "Descargar Archivo", + "fr": "Télécharger le fichier", + "hi": "फ़ाइल डाउनलोड करें", "ja": "ダウンロードファイル", + "ko": "파일 다운로드", "nl": "Download Bestand", "pt": "⇬ Fazer download do arquivo", "ru": "Скачать файл", + "zh-chs": "下載文件", "xloc": [ - "default-mobile.handlebars->9->270", - "default.handlebars->25->677" + "default-mobile.handlebars->9->274", + "default.handlebars->27->726" ] }, { @@ -6058,12 +8357,16 @@ "de": "MeshCentral Router herunterladen, ein TCP-Port-Mapping-Tool.", "en": "Download MeshCentral Router, a TCP port mapping tool.", "es": "Descargue MeshCentral Router, una herramienta de mapeo de puertos TCP.", + "fr": "Télécharger MeshCentral Router (utilitaire de redirection de ports TCP)", + "hi": "मेषप्रोसेसर राउटर, एक टीसीपी पोर्ट मैपिंग टूल डाउनलोड करें।", "ja": "TCPポートマッピングツールであるMeshCentralルーターをダウンロードします。", + "ko": "TCP 포트 매핑 도구 인 MeshCentral Router를 다운로드하십시오.", "nl": "Download MeshCentral Router, een hulpmiddel voor het toewijzen van TCP-poorten.", "pt": "Faça o download do MeshCentral Router, uma ferramenta de mapeamento de portas TCP.", "ru": "Скачать MeshCentral Router, инструмент сопоставления TCP портов.", + "zh-chs": "下載MeshCentral Router,一個TCP端口映射工具。", "xloc": [ - "default.handlebars->25->208" + "default.handlebars->27->192" ] }, { @@ -6071,12 +8374,16 @@ "de": "MeshCmd herunterladen", "en": "Download MeshCmd", "es": "Descargar MeshCmd", + "fr": "Télécharger MeshCmd", + "hi": "डाउनलोड MeshCmd", "ja": "MeshCmdをダウンロード", + "ko": "MeshCmd 다운로드", "nl": "Download MeshCmd", "pt": "Baixar MeshCmd", "ru": "Скачать MeshCmd", + "zh-chs": "下載MeshCmd", "xloc": [ - "default.handlebars->25->590" + "default.handlebars->27->638" ] }, { @@ -6084,12 +8391,16 @@ "de": "MeshCmd herunterladen, ein Befehlszeilenprogramm, das viele Aufgaben ausführt.", "en": "Download MeshCmd, a command line tool that performs many functions.", "es": "Descargue MeshCmd, una herramienta de línea de comandos que realiza muchas funciones.", + "fr": "Télécharger MeshCmd (utilitaire en ligne de commande)", + "hi": "MeshCmd डाउनलोड करें, एक कमांड लाइन टूल जो कई फ़ंक्शन करता है।", "ja": "多くの機能を実行するコマンドラインツール、MeshCmdをダウンロードします。", + "ko": "많은 기능을 수행하는 명령 행 도구 MeshCmd를 다운로드하십시오.", "nl": "Download MeshCmd, een opdrachtregelprogramma dat vele functies uitvoert.", "pt": "Faça o download do MeshCmd, uma ferramenta de linha de comando que executa muitas funções.", "ru": "Скачать MeshCmd, инструмент командной строки, выполняющий множество функций.", + "zh-chs": "下載MeshCmd,這是一個執行許多功能的命令行工具。", "xloc": [ - "default.handlebars->25->206" + "default.handlebars->27->190" ] }, { @@ -6097,20 +8408,33 @@ "de": "Plugin herunterladen", "en": "Download Plugin", "es": "Descargar plugin", + "fr": "Télécharger le module", + "hi": "प्लगइन डाउनलोड करें", "ja": "プラグインをダウンロード", + "ko": "플러그인 다운로드", "nl": "Download Plugin", + "pt": "Download do plugin", "ru": "Скачать плагин", + "zh-chs": "下載插件", "xloc": [ "default.handlebars->container->column_l->p42->3->3" ] }, { + "cs": "Stáhněte \\\"meshcmd \\\" se souborem akcí pro směrování provozu přes tento server do tohoto zařízení. Nezapomeňte upravit meshaction.txt a přidat heslo k účtu nebo provést potřebné změny.", + "de": "Laden Sie \\\"meshcmd\\\" mit einer Aktionsdatei herunter, um den Datenverkehr über diesen Server an dieses Gerät weiterzuleiten. Stellen Sie sicher, dass Sie meshaction.txt bearbeiten und Ihr Kontokennwort hinzufügen, oder nehmen Sie die erforderlichen Änderungen vor.", "en": "Download \\\"meshcmd\\\" with an action file to route traffic thru this server to this device. Make sure to edit meshaction.txt and add your account password or make any changes needed.", "es": "Descargue \\\"meshcmd\\\" con un archivo de acción para enrutar el tráfico a través de este servidor a este dispositivo. Asegúrese de editar meshaction.txt y agregue la contraseña de su cuenta o realice los cambios necesarios.", + "fr": "Téléchargez \\\"meshcmd \\\" avec un fichier d'action pour acheminer le trafic via ce serveur vers cet appareil. Assurez-vous de modifier meshaction.txt et ajoutez le mot de passe de votre compte ou apportez les modifications nécessaires.", + "hi": "इस डिवाइस पर इस सर्वर के माध्यम से ट्रैफ़िक को रूट करने के लिए एक एक्शन फ़ाइल के साथ \\\"meshcmd \\\" डाउनलोड करें। Meshaction.txt को संपादित करना सुनिश्चित करें और अपना खाता पासवर्ड जोड़ें या आवश्यक बदलाव करें।", + "ja": "このサーバーを通過するトラフィックをこのデバイスにルーティングするには、アクションファイルとともに\\\"meshcmd \\\"をダウンロードします。 meshaction.txtを編集してアカウントパスワードを追加するか、必要な変更を加えてください。", + "ko": "이 서버를 통해이 장치로 트래픽을 라우팅하려면 작업 파일과 함께 \\\"meshcmd \\\"를 다운로드하십시오. meshaction.txt를 편집하고 계정 비밀번호를 추가하거나 필요한 사항을 변경하십시오.", "nl": "Download \\\"meshcmd\\\" met het actiebestand om verkeer via deze server naar dit apparaat te leiden. Zorg ervoor dat u meshaction.txt bewerkt en uw accountwachtwoord toevoegt of breng de nodige wijzigingen aan.", + "pt": "Faça o download de \\\"meshcmd\\\" com um arquivo de ação para rotear o tráfego desse servidor para este dispositivo. Certifique-se de editar o meshaction.txt e adicionar a senha da sua conta ou fazer as alterações necessárias.", "ru": "Скачайте \\\"meshcmd\\\" с файлом команд для маршрутизации трафика к этому устройству через сервер. Не забудьте указать пароль от своей учетной записи в meshaction.txt и сделать другие правки при необходимости.", + "zh-chs": "下載帶有動作文件的“ meshcmd”,以將通過此服務器的流量路由到該設備。確保編輯meshaction.txt並添加您的帳戶密碼或進行任何必要的更改。", "xloc": [ - "default.handlebars->25->583" + "default.handlebars->27->631" ] }, { @@ -6118,10 +8442,14 @@ "de": "Konsolentext herunterladen", "en": "Download console text", "es": "Descargar texto de consola", + "fr": "Télécharger le texte de la console", + "hi": "कंसोल टेक्स्ट डाउनलोड करें", "ja": "コンソールテキストをダウンロードする", + "ko": "콘솔 텍스트 다운로드", "nl": "Consoletekst downloaden", "pt": "Baixar do texto do console", "ru": "Скачать текст из консоли", + "zh-chs": "下載控制台文字", "xloc": [ "default.handlebars->container->column_l->p15->consoleTable->1->0->1->1" ] @@ -6131,10 +8459,14 @@ "de": "Datenpunkte herunterladen (.csv)", "en": "Download data points (.csv)", "es": "Descargar puntos de datos (.csv)", + "fr": "Télécharger (.csv)", + "hi": "डेटा बिंदु (.csv) डाउनलोड करें", "ja": "データポイント(.csv)をダウンロードする", + "ko": "데이터 포인트 다운로드 (.csv)", "nl": "Gegevenspunten downloaden (.csv)", "pt": "Baixar pontos de dados (.csv)", "ru": "Скачать data points (.csv)", + "zh-chs": "下載數據點(.csv)", "xloc": [ "default.handlebars->container->column_l->p40->3->1" ] @@ -6144,12 +8476,16 @@ "de": "Fehlerprotokoll herunterladen", "en": "Download error log", "es": "Descargar registro de errores", + "fr": "Télécharger le journal d'erreurs", + "hi": "त्रुटि लॉग डाउनलोड करें", "ja": "エラーログをダウンロードする", + "ko": "오류 로그 다운로드", "nl": "Foutenlogboek downloaden", "pt": "Baixar log de erro", "ru": "Скачать журнал ошибок", + "zh-chs": "下載錯誤日誌", "xloc": [ - "default.handlebars->25->118" + "default.handlebars->27->101" ] }, { @@ -6157,12 +8493,16 @@ "de": "Energiezustandsereignisse herunterladen", "en": "Download power events", "es": "Descargar eventos de encendido", + "fr": "Télécharger les données sur l'alimentation", + "hi": "बिजली की घटनाओं को डाउनलोड करें", "ja": "電源イベントをダウンロードする", + "ko": "파워 이벤트 다운로드", "nl": "Downloaden Power gebeurtenissen", "pt": "Download de eventos de energia", "ru": "Скачать события состояния питания", + "zh-chs": "下載電源事件", "xloc": [ - "default.handlebars->25->545" + "default.handlebars->27->592" ] }, { @@ -6170,10 +8510,14 @@ "de": "Server-Datensicherung herunterladen", "en": "Download server backup", "es": "Descargar copia de seguridad del servidor", + "fr": "Télécharger une sauvegarde", + "hi": "सर्वर बैकअप डाउनलोड करें", "ja": "サーバーのバックアップをダウンロード", + "ko": "서버 백업 다운로드", "nl": "Download server back-up", "pt": "Fazer o download do backup do servidor", "ru": "Скачать резервную копию сервера", + "zh-chs": "下載服務器備份", "xloc": [ "default.handlebars->container->column_l->p6->p2ServerActions->3->p2ServerActionsBackup->0" ] @@ -6183,25 +8527,49 @@ "de": "Den Installer hier herunterladen", "en": "Download the installer here", "es": "Descargue el instalador aquí", + "fr": "Télécharger l'installeur ici", + "hi": "यहां इंस्टॉलर डाउनलोड करें", "ja": "ここからインストーラーをダウンロードしてください", + "ko": "설치 프로그램을 여기에서 다운로드하십시오", "nl": "Download het installatieprogramma hier", "pt": "Faça o download do instalador aqui", "ru": "Скачайте программу по этой ссылке", + "zh-chs": "在此處下載安裝程序", "xloc": [ "agentinvite.handlebars->container->column_l->5->macostab->3->macosurl" ] }, + { + "cs": "Stáhněte si seznam zařízení s jedním z níže uvedených formátů souborů.", + "de": "Laden Sie die Liste der Geräte mit einem der folgenden Dateiformate herunter.", + "en": "Download the list of devices with one of the file formats below.", + "fr": "Télécharger la liste des appareils au format :", + "hi": "नीचे फ़ाइल स्वरूपों में से एक के साथ उपकरणों की सूची डाउनलोड करें।", + "ja": "以下のファイル形式のいずれかでデバイスのリストをダウンロードします。", + "ko": "아래 파일 형식 중 하나를 사용하여 장치 목록을 다운로드하십시오.", + "nl": "Download de lijst met apparaten in een van de onderstaande bestandsindelingen.", + "pt": "Faça o download da lista de dispositivos com um dos formatos de arquivo abaixo.", + "ru": "Загрузите список устройств с одним из форматов файлов ниже.", + "zh-chs": "使用以下一種文件格式下載設備列表。", + "xloc": [ + "default.handlebars->27->389" + ] + }, { "cs": "Stáhněte si seznam událostí v níže uvedeném formátu.", "de": "Die Ereignisliste in einem der folgenden Dateiformate herunterladen.", "en": "Download the list of events with one of the file formats below.", "es": "Descargue la lista de eventos con uno de los formatos de archivo a continuación.", + "fr": "Télécharger les évènements au format :", + "hi": "नीचे फ़ाइल स्वरूपों में से एक के साथ घटनाओं की सूची डाउनलोड करें।", "ja": "以下のファイル形式のいずれかでイベントのリストをダウンロードします。", + "ko": "아래 파일 형식 중 하나를 사용하여 이벤트 목록을 다운로드하십시오.", "nl": "Download de lijst met gebeurtenissen in een van de onderstaande bestandsindelingen.", "pt": "Faça o download da lista de eventos com um dos formatos de arquivo abaixo.", "ru": "Скачать список событий в одном из форматов ниже.", + "zh-chs": "使用以下一種文件格式下載事件列表。", "xloc": [ - "default.handlebars->25->1194" + "default.handlebars->27->1324" ] }, { @@ -6209,12 +8577,16 @@ "de": "Die Benutzerliste in einem der folgenden Dateiformate herunterladen.", "en": "Download the list of users with one of the file formats below.", "es": "Descargue la lista de usuarios con uno de los formatos de archivo a continuación.", + "fr": "Télécharger la liste des utilisateurs au format :", + "hi": "नीचे फ़ाइल स्वरूपों में से एक के साथ उपयोगकर्ताओं की सूची डाउनलोड करें।", "ja": "以下のファイル形式のいずれかでユーザーのリストをダウンロードします。", + "ko": "아래 파일 형식 중 하나를 가진 사용자 목록을 다운로드하십시오.", "nl": "Download de lijst met gebruikers in een van de onderstaande bestandsindelingen.", "pt": "Baixe a lista de usuários com um dos formatos de arquivo abaixo.", "ru": "Скачать список пользователей в одном из форматов ниже.", + "zh-chs": "使用以下一種文件格式下載用戶列表。", "xloc": [ - "default.handlebars->25->1233" + "default.handlebars->27->1368" ] }, { @@ -6222,10 +8594,14 @@ "de": "Die Software hier herunterladen", "en": "Download the software here", "es": "Descargue el software aquí", + "fr": "Télécharger le logiciel ici", + "hi": "सॉफ्टवेयर यहाँ डाउनलोड करें", "ja": "ここからソフトウェアをダウンロードしてください", + "ko": "여기에서 소프트웨어를 다운로드하십시오", "nl": "Download de software hier", "pt": "Faça o download do software aqui", "ru": "Скачайте программу по этой ссылке", + "zh-chs": "在此處下載軟件", "xloc": [ "agentinvite.handlebars->container->column_l->5->wintab32->3->win32url", "agentinvite.handlebars->container->column_l->5->wintab64->3->win64url" @@ -6236,10 +8612,14 @@ "de": "Trace herunterladen (.csv)", "en": "Download trace (.csv)", "es": "Descargar trace (.csv)", + "fr": "Télécharger la trace (.csv)", + "hi": "ट्रेस डाउनलोड करें (.csv)", "ja": "トレースのダウンロード(.csv)", + "ko": "추적 다운로드 (.csv)", "nl": "Download sporen (.csv)", "pt": "Rastreio de download (.csv)", "ru": "Скачать трассировку (.csv)", + "zh-chs": "下載跟踪(.csv)", "xloc": [ "default.handlebars->container->column_l->p41->3->1" ] @@ -6249,10 +8629,14 @@ "de": "Benutzerinformationen herunterladen", "en": "Download user information", "es": "Descargar información del usuario", + "fr": "Télécharger les informations utilisateurs", + "hi": "उपयोगकर्ता जानकारी डाउनलोड करें", "ja": "ユーザー情報をダウンロードする", + "ko": "사용자 정보 다운로드", "nl": "Download gebruikers informatie", "pt": "Baixar informações do usuário", "ru": "Скачать информацию о пользователе", + "zh-chs": "下載用戶信息", "xloc": [ "default.handlebars->container->column_l->p4->3->1->0->3->1->3" ] @@ -6262,12 +8646,16 @@ "de": "Lassen Sie eine .mcrec-Datei hier fallen oder klicken Sie auf \\\"Datei öffnen...\\\"", "en": "Drag & drop a .mcrec file or click \\\"Open File...\\\"", "es": "Arrastre y suelte un archivo .mcrec o haga clic en \\\"Abrir archivo...\\\"", + "fr": "Glisser & Déposer un fichier .mcrec ou cliquer sur \"\\Ouvrir fichier...\\\"", + "hi": "एक .mcrec फ़ाइल को खींचें और छोड़ दें या \\\"फ़ाइल खोलें ... \\\" पर क्लिक करें", "ja": ".mcrecファイルをドラッグアンドドロップするか、[ファイルを開く...]をクリックします", + "ko": ".mcrec 파일을 끌어다 놓거나 \\\"파일 열기 ... \\\"를 클릭하십시오.", "nl": "Sleep een .mcrec-bestand of klik op \\\"Bestand openen ...\\\"", "pt": "Arraste e solte um arquivo .mcrec ou clique em \\\"Abrir arquivo...\\\"", "ru": "Перетащите .mcrec файл или нажмите \\\"Открыть файл ... \\\"", + "zh-chs": "拖放.mcrec文件或單擊 “打開文件...”", "xloc": [ - "player.handlebars->3->18" + "player.handlebars->3->20" ] }, { @@ -6275,10 +8663,16 @@ "de": "Agent-Duplikat", "en": "Duplicate Agent", "es": "Agente duplicado", + "fr": "Cloner l'agent", + "hi": "डुप्लीकेट एजेंट", + "ja": "重複エージェント", + "ko": "중복 에이전트", "nl": "Duplicaat Agent", + "pt": "Agente duplicado", "ru": "Скопировать агент", + "zh-chs": "代理重複", "xloc": [ - "default.handlebars->25->1409" + "default.handlebars->27->1556" ] }, { @@ -6286,8 +8680,14 @@ "de": "Dupliziere Gruppe...", "en": "Duplicate Group...", "es": "Grupo duplicado ...", + "fr": "Cloner le groupe ...", + "hi": "डुप्लीकेट समूह ...", + "ja": "グループを複製...", + "ko": "중복 그룹 ...", "nl": "Dupliceer Groep...", + "pt": "Grupo duplicado ...", "ru": "Скопировать группу...", + "zh-chs": "重複的群組...", "xloc": [ "default.handlebars->container->column_l->p50->3->1->0->3->3" ] @@ -6297,10 +8697,16 @@ "de": "Dupliziere Benutzergruppe", "en": "Duplicate User Group", "es": "Grupo de usuarios duplicados", + "fr": "Cloner le groupe utilisateur", + "hi": "डुप्लिकेट उपयोगकर्ता समूह", + "ja": "重複ユーザーグループ", + "ko": "중복 된 사용자 그룹", "nl": "Dupliceer Gebruikers Groep", + "pt": "Grupo de usuários duplicados", "ru": "Скопировать группу пользователей", + "zh-chs": "重複的用戶組", "xloc": [ - "default.handlebars->25->1278" + "default.handlebars->27->1414" ] }, { @@ -6308,10 +8714,14 @@ "de": "Dauer", "en": "Duration", "es": "Duración", + "fr": "Durée", + "hi": "अवधि", "ja": "期間", + "ko": "지속", "nl": "Looptijd", "pt": "Duração", "ru": "Длительность", + "zh-chs": "持續時間", "xloc": [ "player.handlebars->3->2" ] @@ -6321,36 +8731,48 @@ "de": "Während der Aktivierung hat der Agent Zugriff auf das Administratorkennwort.", "en": "During activation, the agent will have access to admin password infomation.", "es": "Durante la activación, el agente tendrá acceso a la información de contraseña de administrador.", + "fr": "Pendant l'activation, l'agent aura accès au mot de passe administateur.", + "hi": "सक्रियण के दौरान, एजेंट के पास पासवर्ड इन्फ़ोमेशन के लिए एक्सेस होगा।", "ja": "アクティベーション中、エージェントは管理者パスワード情報にアクセスできます。", + "ko": "활성화하는 동안 에이전트는 관리자 비밀번호 정보에 액세스 할 수 있습니다.", "nl": "Tijdens activering heeft de agent toegang tot beheerderswachtwoordinformatie.", "pt": "Durante a ativação, o agente terá acesso às informações da senha do administrador.", "ru": "Во время активации агент будет иметь доступ к паролю администратора.", + "zh-chs": "在激活期間,代理將有權訪問管理員密碼信息。", "xloc": [ - "default.handlebars->25->1062" + "default.handlebars->27->1166" ] }, { "cs": "nizozemština (Belgie)", "de": "Niederländisch (Belgisch)", "en": "Dutch (Belgian)", + "fr": "Néerlandais (Belgique)", + "hi": "डच (बेल्जियम)", "ja": "オランダ語(ベルギー)", + "ko": "네덜란드어 (벨기에)", "nl": "Nederlands (Belgisch)", "pt": "Holandês (belga)", "ru": "Голландский (Бельгийский)", + "zh-chs": "荷蘭語(比利時)", "xloc": [ - "default.handlebars->25->768" + "default.handlebars->27->872" ] }, { "cs": "nizozemština (standardní)", "de": "Niederländisch (Standard)", "en": "Dutch (Standard)", + "fr": "Néerlandais (Standard)", + "hi": "डच (मानक)", "ja": "オランダ語(標準)", + "ko": "네덜란드어 (표준)", "nl": "Nederlands (Standaard)", "pt": "Holandês (padrão)", "ru": "Голландский (Стандартный)", + "zh-chs": "荷蘭語(標準)", "xloc": [ - "default.handlebars->25->767" + "default.handlebars->27->871" ] }, { @@ -6359,12 +8781,15 @@ "en": "ERROR: ", "es": "Error: ", "fr": "ERREUR:", + "hi": "त्रुटि:", "ja": "エラー:", + "ko": "오류:", "nl": "FOUT:", "pt": "ERRO:", "ru": "ОШИБКА:", + "zh-chs": "錯誤:", "xloc": [ - "default.handlebars->25->153" + "default.handlebars->27->136" ] }, { @@ -6373,12 +8798,15 @@ "en": "ERROR: Unable to add key.", "es": "Error: No se puede agregar la llave.", "fr": "ERREUR: Impossible d'ajouter la clé.", + "hi": "त्रुटि: कुंजी जोड़ने में असमर्थ।", "ja": "エラー:キーを追加できません。", + "ko": "오류 : 키를 추가 할 수 없습니다.", "nl": "FOUT: kan sleutel niet toevoegen.", "pt": "ERRO: Não foi possível adicionar a chave.", "ru": "ОШИБКА: Невозможно добавить ключ.", + "zh-chs": "錯誤:無法添加密鑰。", "xloc": [ - "default.handlebars->25->149" + "default.handlebars->27->132" ] }, { @@ -6386,10 +8814,14 @@ "de": "Esc", "en": "ESC", "es": "ESC", + "fr": "ESC", + "hi": "ESC", "ja": "ESC", + "ko": "ESC", "nl": "ESC", "pt": "ESC", "ru": "ESC", + "zh-chs": "退出", "xloc": [ "default.handlebars->container->column_l->p12->termTable->1->1->6->1->3" ] @@ -6399,12 +8831,17 @@ "de": "Bearbeiten", "en": "Edit", "es": "Editar", + "fr": "Modifier", + "hi": "संपादित करें", "ja": "編集", + "ko": "편집하다", "nl": "Bewerk", "pt": "Editar", "ru": "Редактировать", + "zh-chs": "編輯", "xloc": [ - "default.handlebars->container->column_l->p13->p13toolbar->1->2->1->3" + "default.handlebars->container->column_l->p13->p13toolbar->1->2->1->3", + "default.handlebars->filesContextMenu->cxfileedit->0" ] }, { @@ -6412,13 +8849,17 @@ "de": "Gerät bearbeiten", "en": "Edit Device", "es": "Editar dispositivo", + "fr": "Modifier l'appareil", + "hi": "उपकरण संपादित करें", "ja": "デバイスを編集", + "ko": "장치 편집", "nl": "Bewerk apparaat", "pt": "Editar dispositivo", "ru": "Редактировать устройство", + "zh-chs": "編輯裝置", "xloc": [ - "default-mobile.handlebars->9->227", - "default.handlebars->25->604" + "default-mobile.handlebars->9->231", + "default.handlebars->27->652" ] }, { @@ -6426,17 +8867,21 @@ "de": "Gerätegruppe bearbeiten", "en": "Edit Device Group", "es": "Editar grupo de dispositivos", + "fr": "Modifier le groupe d'appareil", + "hi": "उपकरण समूह संपादित करें", "ja": "デバイスグループの編集", + "ko": "장치 그룹 편집", "nl": "Bewerk apparaatgroep", "pt": "Editar grupo de dispositivos", "ru": "Редактировать группу устройств", + "zh-chs": "編輯設備組", "xloc": [ - "default-mobile.handlebars->9->291", - "default-mobile.handlebars->9->293", - "default-mobile.handlebars->9->311", - "default.handlebars->25->1068", - "default.handlebars->25->1092", - "default.handlebars->25->1115" + "default-mobile.handlebars->9->295", + "default-mobile.handlebars->9->297", + "default-mobile.handlebars->9->315", + "default.handlebars->27->1172", + "default.handlebars->27->1199", + "default.handlebars->27->1227" ] }, { @@ -6444,12 +8889,16 @@ "de": "Gerätegruppenmerkmale bearbeiten", "en": "Edit Device Group Features", "es": "Editar características del grupo de dispositivos", + "fr": "Modifier les fonctionnalités du groupe d'appareils", + "hi": "उपकरण समूह सुविधाएँ संपादित करें", "ja": "デバイスグループ機能の編集", + "ko": "장치 그룹 기능 편집", "nl": "Functies van apparaatgroep bewerken", "pt": "Editar recursos do grupo de dispositivos", "ru": "Редактировать функции группы устройств", + "zh-chs": "編輯設備組功能", "xloc": [ - "default.handlebars->25->1082" + "default.handlebars->27->1186" ] }, { @@ -6457,10 +8906,16 @@ "de": "Gerätegruppenberechtigungen bearbeiten", "en": "Edit Device Group Permissions", "es": "Editar permisos de grupo de dispositivos", + "fr": "Modifier les droits du groupe d'appareils", + "hi": "डिवाइस समूह अनुमतियाँ संपादित करें", + "ja": "デバイスグループのアクセス許可を編集する", + "ko": "장치 그룹 권한 편집", "nl": "Bewerk apparaatgroep rechten", + "pt": "Editar permissões do grupo de dispositivos", "ru": "Редактировать права группы устройств", + "zh-chs": "編輯設備組權限", "xloc": [ - "default.handlebars->25->1112" + "default.handlebars->27->1224" ] }, { @@ -6468,12 +8923,16 @@ "de": "Gerätegruppen-Nutzereinwilligung bearbeiten", "en": "Edit Device Group User Consent", "es": "Editar consentimiento del usuario del grupo de dispositivos", + "fr": "Gestion des consentements utilisateurs", + "hi": "डिवाइस समूह उपयोगकर्ता सहमति संपादित करें", "ja": "デバイスグループユーザーの同意の編集", + "ko": "장치 그룹 사용자 동의 편집", "nl": "Toestemming gebruikersgroep bewerken", "pt": "Editar consentimento do usuário do grupo de dispositivos", "ru": "Редактировать согласие пользователя группы устройств", + "zh-chs": "編輯設備組用戶同意", "xloc": [ - "default.handlebars->25->1079" + "default.handlebars->27->1183" ] }, { @@ -6481,13 +8940,43 @@ "de": "Geräte-Notizen bearbeiten", "en": "Edit Device Notes", "es": "Editar notas del dispositivo", + "fr": "Modifier les notes sur l'appareil", + "hi": "डिवाइस नोट्स संपादित करें", "ja": "デバイスノートの編集", + "ko": "장치 메모 편집", "nl": "Apparaatnotities bewerken", "pt": "Editar notas do dispositivo", "ru": "Редактировать примечания устройства", + "zh-chs": "編輯設備說明", "xloc": [ - "default-mobile.handlebars->9->305", - "default.handlebars->25->1104" + "default-mobile.handlebars->9->309", + "default.handlebars->27->1212" + ] + }, + { + "cs": "Upravit oprávnění zařízení", + "de": "Geräteberechtigungen bearbeiten", + "en": "Edit Device Permissions", + "fr": "Modifier les autorisations de périphérique", + "ja": "デバイスの権限を編集する", + "nl": "Bewerk apparaatrechten", + "ru": "Изменить разрешения устройства", + "zh-chs": "编辑设备权限", + "xloc": [ + "default.handlebars->27->1221" + ] + }, + { + "cs": "Upravit skupinu", + "de": "Gruppe bearbeiten", + "en": "Edit Group", + "fr": "Modifier le groupe", + "ja": "グループを編集", + "nl": "Bewerk groep", + "ru": "Редактировать группу", + "zh-chs": "编辑组", + "xloc": [ + "default.handlebars->27->558" ] }, { @@ -6495,15 +8984,19 @@ "de": "Zugangsdaten für Intel® AMT bearbeiten", "en": "Edit Intel® AMT credentials", "es": "Editar Credenciales de Intel & AMT", + "fr": "Éditer les certificats Intel® AMT", + "hi": "Intel® AMT क्रेडेंशियल संपादित करें", "ja": "Intelを編集® AMTクレデンシャル", + "ko": "인텔 ® AMT 자격 증명 편집", "nl": "Bewerk Intel® AMT-gegevens", "pt": "Editar Intel & reg; Credenciais AMT", "ru": "Редактировать учетные данные Intel® AMT", + "zh-chs": "編輯英特爾®AMT憑據", "xloc": [ - "default-mobile.handlebars->9->217", - "default.handlebars->25->465", - "default.handlebars->25->468", - "default.handlebars->25->552" + "default-mobile.handlebars->9->221", + "default.handlebars->27->472", + "default.handlebars->27->475", + "default.handlebars->27->599" ] }, { @@ -6512,13 +9005,16 @@ "en": "Edit Notes", "es": "Editar notas", "fr": "Modifier les notes", + "hi": "नोट्स संपादित करें", "ja": "メモを編集", + "ko": "메모 수정", "nl": "Notities bewerken", "pt": "Editar notas", "ru": "Редактировать примечания", + "zh-chs": "編輯筆記", "xloc": [ - "default-mobile.handlebars->9->318", - "default.handlebars->25->1122" + "default-mobile.handlebars->9->322", + "default.handlebars->27->1234" ] }, { @@ -6526,12 +9022,29 @@ "de": "Benutzer-Gerätegruppenberechtigungen bearbeiten", "en": "Edit User Device Group Permissions", "es": "Editar permisos de grupo de dispositivos de usuario", + "fr": "Modifier les permissions du groupe d'appareil", + "hi": "उपयोगकर्ता डिवाइस समूह अनुमतियाँ संपादित करें", "ja": "ユーザーデバイスグループ権限の編集", + "ko": "사용자 장치 그룹 권한 편집", "nl": "Gebruikersrechten apparaatgroep bewerken", "pt": "Editar permissões do grupo de dispositivos do usuário", "ru": "Редактировать права пользователя для группы устройств", + "zh-chs": "編輯用戶設備組權限", "xloc": [ - "default.handlebars->25->1113" + "default.handlebars->27->1225" + ] + }, + { + "cs": "Upravit oprávnění uživatelského zařízení", + "de": "Benutzergeräteberechtigungen bearbeiten", + "en": "Edit User Device Permissions", + "fr": "Modifier les autorisations des périphériques utilisateur", + "ja": "ユーザーデバイスの権限を編集する", + "nl": "Bewerk gebruikersapparaatrechten", + "ru": "Изменить разрешения для пользовательских устройств", + "zh-chs": "编辑用户设备权限", + "xloc": [ + "default.handlebars->27->1222" ] }, { @@ -6539,10 +9052,16 @@ "de": "Benutzergruppe bearbeiten", "en": "Edit User Group", "es": "Editar grupo de usuarios", + "fr": "Modifier le groupe utilisateurs", + "hi": "उपयोगकर्ता समूह संपादित करें", + "ja": "ユーザーグループを編集", + "ko": "사용자 그룹 편집", "nl": "Bewerk de gebruikersgroep", + "pt": "Editar grupo de usuários", "ru": "Редактировать группу пользователей", + "zh-chs": "編輯用戶組", "xloc": [ - "default.handlebars->25->1307" + "default.handlebars->27->1440" ] }, { @@ -6550,10 +9069,14 @@ "de": "Einstellungen für entfernten Desktop bearbeiten", "en": "Edit remote desktop settings", "es": "Editar configuraciones de escritorio remoto", + "fr": "Modifier les paramètres du bureau distant", + "hi": "दूरस्थ डेस्कटॉप सेटिंग्स संपादित करें", "ja": "リモートデスクトップ設定を編集する", + "ko": "원격 데스크톱 설정 편집", "nl": "Bewerk externe bureaubladinstellingen", "pt": "Editar configurações da área de trabalho remota", "ru": "Редактировать настройки удаленного рабочего стола", + "zh-chs": "編輯遠程桌面設置", "xloc": [ "default.handlebars->container->column_l->p11->deskarea0->deskarea1->1" ] @@ -6563,17 +9086,23 @@ "de": "E-Mail", "en": "Email", "es": "Correo electrónico", + "fr": "Email", + "hi": "ईमेल", "ja": "Eメール", + "ko": "이메일", "nl": "E-mail", "pt": "Email", "ru": "Email", + "zh-chs": "電子郵件", "xloc": [ - "default-mobile.handlebars->9->37", - "default.handlebars->25->1245", - "default.handlebars->25->1327", - "default.handlebars->25->1328", - "default.handlebars->25->1356", - "default.handlebars->25->283" + "default-mobile.handlebars->9->40", + "default.handlebars->27->1380", + "default.handlebars->27->1461", + "default.handlebars->27->1462", + "default.handlebars->27->1492", + "default.handlebars->27->270", + "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->tokenpanel->1->7->1->4->1->3", + "login.handlebars->container->column_l->centralTable->1->0->logincell->tokenpanel->1->7->1->4->1->3" ] }, { @@ -6581,13 +9110,47 @@ "de": "E-Mail-Adresse ändern", "en": "Email Address Change", "es": "Cambio de dirección de correo electrónico", + "fr": "Changement d'adresse mail", + "hi": "ईमेल पता बदलें", "ja": "メールアドレスの変更", + "ko": "이메일 주소 변경", "nl": "E-mailadres wijzigen", "pt": "Alteração de endereço de email", "ru": "Изменение адреса email", + "zh-chs": "電郵地址變更", "xloc": [ - "default-mobile.handlebars->9->38", - "default.handlebars->25->935" + "default-mobile.handlebars->9->41", + "default.handlebars->27->1040" + ] + }, + { + "cs": "Ověřování e-mailem", + "de": "E-Mail-Authentifikation", + "en": "Email Authentication", + "fr": "Authentification par courriel", + "hi": "ईमेल प्रमाणीकरण", + "ja": "メール認証", + "ko": "이메일 인증", + "nl": "E-mail authenticatie", + "pt": "Autenticação do email", + "ru": "Аутентификация электронной почты", + "zh-chs": "郵件認證", + "xloc": [ + "default-mobile.handlebars->9->30", + "default.handlebars->27->809" + ] + }, + { + "cs": "E-mailový provoz", + "de": "E-Mail-Verkehr", + "en": "Email Traffic", + "fr": "Trafic des e-mails", + "ja": "メールトラフィック", + "nl": "E-mailverkeer", + "ru": "Почтовый трафик", + "zh-chs": "电子邮件流量", + "xloc": [ + "default.handlebars->27->1595" ] }, { @@ -6595,13 +9158,37 @@ "de": "E-Mail-Verifizierung", "en": "Email Verification", "es": "Verificacion de Correo electrónico", + "fr": "Vérification de l'email", + "hi": "ई - मेल सत्यापन", "ja": "メール確認", + "ko": "이메일 확인", "nl": "E-mail verificatie", "pt": "verificação de e-mail", "ru": "Подтверждение email", + "zh-chs": "電子郵件驗證", "xloc": [ - "default-mobile.handlebars->9->36", - "default.handlebars->25->933" + "default-mobile.handlebars->9->39", + "default.handlebars->27->1038" + ] + }, + { + "en": "Email invitation", + "nl": "E-mail uitnodiging", + "xloc": [ + "default.handlebars->27->267" + ] + }, + { + "cs": "Email není ověřen", + "de": "E-Mail ist nicht verifiziert", + "en": "Email is not verified", + "fr": "L'email n'est pas verifié", + "ja": "メールは検証されていない", + "nl": "E-mail is niet geverifieerd", + "ru": "Электронная почта не подтверждена", + "zh-chs": "邮件未验证", + "xloc": [ + "default.handlebars->27->1353" ] }, { @@ -6609,12 +9196,17 @@ "de": "E-Mail ist bestätigt", "en": "Email is verified", "es": "Correo electrónico verificado", + "fr": "Email vérifié", + "hi": "ईमेल सत्यापित है", "ja": "メールが確認されました", + "ko": "이메일 확인", "nl": "E-mail is geverifieerd", "pt": "O email foi verificado", "ru": "Email подтвержден", + "zh-chs": "電子郵件已驗證", "xloc": [ - "default.handlebars->25->1324" + "default.handlebars->27->1354", + "default.handlebars->27->1458" ] }, { @@ -6622,12 +9214,16 @@ "de": "E-Mail ist bestätigt.", "en": "Email is verified.", "es": "Correo electrónico verificado.", + "fr": "Email vérifié.", + "hi": "ईमेल सत्यापित है।", "ja": "メールが確認されました。", + "ko": "이메일이 확인되었습니다.", "nl": "E-mail is geverifieerd.", "pt": "O email foi verificado.", "ru": "Email подтвержден.", + "zh-chs": "電子郵件已驗證。", "xloc": [ - "default.handlebars->25->1251" + "default.handlebars->27->1386" ] }, { @@ -6635,12 +9231,33 @@ "de": "E-Mail nicht bestätigt", "en": "Email not verified", "es": "Correo electrónico no verificado", + "fr": "Email non vérifié", + "hi": "ईमेल सत्यापित नहीं है", "ja": "メールが確認されていません", + "ko": "확인되지 않은 이메일", "nl": "E-mail is niet geverifieerd", "pt": "Email não verificado", "ru": "Email не подтвержден", + "zh-chs": "電子郵件未驗證", "xloc": [ - "default.handlebars->25->1325" + "default.handlebars->27->1459" + ] + }, + { + "cs": "Email odeslán.", + "de": "E-Mail gesendet.", + "en": "Email sent.", + "fr": "Email envoyé.", + "hi": "ईमेल भेजा।", + "ja": "メールを送信しました。", + "ko": "이메일이 발송되었습니다.", + "nl": "E-mail verzonden.", + "pt": "Email enviado.", + "ru": "Письмо отправлено.", + "zh-chs": "郵件已發送。", + "xloc": [ + "login-mobile.handlebars->5->2", + "login.handlebars->5->2" ] }, { @@ -6648,41 +9265,86 @@ "de": "E-Mail:", "en": "Email:", "es": "Correo electrónico:", + "fr": "Email:", + "hi": "ईमेल:", "ja": "Eメール:", + "ko": "이메일:", "nl": "E-mail:", "pt": "Email:", "ru": "Email:", + "zh-chs": "電子郵件:", "xloc": [ - "login-mobile.handlebars->5->17", + "login-mobile.handlebars->5->18", "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->createpanel->1->1->9->1->2->1", "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->resetpanel->1->7->1->0->1", - "login.handlebars->5->17", + "login.handlebars->5->18", "login.handlebars->container->column_l->centralTable->1->0->logincell->createpanel->1->9->1->2->nuEmail", "login.handlebars->container->column_l->centralTable->1->0->logincell->resetpanel->1->7->1->0->1" ] }, + { + "cs": "Povolit kódy pozvání", + "de": "Einladungscodes aktivieren", + "en": "Enable Invite Codes", + "fr": "Activer les codes d'invitation", + "hi": "निमंत्रण कोड सक्षम करें", + "ja": "招待コードを有効にする", + "ko": "초대 코드 사용", + "nl": "Schakel uitnodigingscodes in", + "pt": "Ativar códigos de convite", + "ru": "Включить коды приглашения", + "zh-chs": "啟用邀請代碼", + "xloc": [ + "default.handlebars->27->1253" + ] + }, { "cs": "Zapnout upozorňování v prohlížeči", "de": "Browser-Benachrichtigung aktivieren", "en": "Enable browser notification", "es": "Habilitar notificación del navegador", + "fr": "Autoriser les notifications", + "hi": "ब्राउज़र अधिसूचना सक्षम करें", "ja": "ブラウザ通知を有効にする", + "ko": "브라우저 알림 사용", "nl": "Schakel browsermelding in", "pt": "Ativar notificação do navegador", "ru": "Включить уведомления в браузере", + "zh-chs": "啟用瀏覽器通知", "xloc": [ "messenger.handlebars->xtop->1" ] }, + { + "cs": "Povolit e-mailovou dvoufaktorovou autentizaci.", + "de": "Aktivieren Sie die E-Mail-Zwei-Faktor-Authentifizierung.", + "en": "Enable email two-factor authenticaiton.", + "fr": "Activer l'authentification à deux facteurs par e-mail.", + "hi": "ईमेल दो-कारक प्रमाणिकता सक्षम करें।", + "ja": "メールの2要素認証を有効にします。", + "ko": "이메일 2 단계 인증을 사용합니다.", + "nl": "Schakel e-mail tweefactorauthenticatie in.", + "pt": "Habilite a autenticação de dois fatores por email.", + "ru": "Включить двухфакторную аутентификацию электронной почты.", + "zh-chs": "啟用電子郵件兩因素驗證。", + "xloc": [ + "default-mobile.handlebars->9->32", + "default.handlebars->27->811" + ] + }, { "cs": "Zapnout upozorňování z webu v prohlížeči", "de": "Web-Benachrichtigungen aktivieren", "en": "Enable web notifications", "es": "Habilitar notificaciones web", + "fr": "Autoriser les notifications web", + "hi": "वेब सूचनाएं सक्षम करें", "ja": "Web通知を有効にする", + "ko": "웹 알림 사용", "nl": "Schakel webmeldingen in", "pt": "Ativar notificações da web", "ru": "Включить веб уведомления", + "zh-chs": "啟用網絡通知", "xloc": [ "default.handlebars->container->column_l->p2->p2AccountActions->3->accountEnableNotificationsSpan->0" ] @@ -6692,10 +9354,14 @@ "de": "Kodierung", "en": "Encoding", "es": "Codificación", + "fr": "Encodage", + "hi": "एन्कोडिंग", "ja": "エンコーディング", - "nl": "codering", + "ko": "부호화", + "nl": "Codering", "pt": "Codificação", "ru": "Кодировка", + "zh-chs": "編碼方式", "xloc": [ "default-mobile.handlebars->dialog->3->dialog7->d7amtkvm->3->3" ] @@ -6705,120 +9371,160 @@ "de": "Englisch", "en": "English", "es": "Ingles", + "fr": "Anglais", + "hi": "अंग्रेज़ी", "ja": "英語", + "ko": "영어", "nl": "Engels", "pt": "Inglês", "ru": "Английский", + "zh-chs": "英語", "xloc": [ - "default.handlebars->25->769" + "default.handlebars->27->873" ] }, { "cs": "angličtina (Austrálie)", "de": "Englisch (Australien)", "en": "English (Australia)", + "fr": "Anglais (Australie)", + "hi": "अंग्रेजी (ऑस्ट्रेलिया)", "ja": "英語(オーストラリア)", + "ko": "영어 (호주)", "nl": "Engels (Australië)", "pt": "Inglês (Austrália)", "ru": "Английский (Австралия)", + "zh-chs": "英文(澳洲)", "xloc": [ - "default.handlebars->25->770" + "default.handlebars->27->874" ] }, { "cs": "angličtina (Belize)", "de": "Englisch (Belize)", "en": "English (Belize)", + "fr": "English (Bélize)", + "hi": "अंग्रेजी (बेलीज)", "ja": "英語(ベリーズ)", + "ko": "영어 (벨리즈)", "nl": "Engels (Belize)", "pt": "Inglês (Belize)", "ru": "Английский (Белиз)", + "zh-chs": "英語(伯利茲)", "xloc": [ - "default.handlebars->25->771" + "default.handlebars->27->875" ] }, { "cs": "angličtina (Kanada)", "de": "Englisch (Kanada)", "en": "English (Canada)", + "fr": "Anglais (Canada)", + "hi": "अंग्रेजी (कनाडा)", "ja": "英語(カナダ)", + "ko": "영어 (캐나다)", "nl": "Engels (Canada)", "pt": "Inglês (Canadá)", "ru": "Английский (Канада)", + "zh-chs": "英文(加拿大)", "xloc": [ - "default.handlebars->25->772" + "default.handlebars->27->876" ] }, { "cs": "angličtina (Irsko)", "de": "Englisch (Irland)", "en": "English (Ireland)", + "fr": "Anglais (Irelande)", + "hi": "अंग्रेजी (आयरलैंड)", "ja": "英語(アイルランド)", + "ko": "영어 (아일랜드)", "nl": "Engels (Ierland)", "pt": "Inglês (Irlanda)", "ru": "Английский (Ирландия)", + "zh-chs": "英文(愛爾蘭)", "xloc": [ - "default.handlebars->25->773" + "default.handlebars->27->877" ] }, { "cs": "angličtina (Jamajka)", "de": "Englisch (Jamaika)", "en": "English (Jamaica)", + "fr": "Anglais (Jamaïque)", + "hi": "अंग्रेजी (जमैका)", "ja": "英語(ジャマイカ)", + "ko": "영어 (자메이카)", "nl": "Engels (Jamaica)", "pt": "Inglês (Jamaica)", "ru": "Английский (Ямайка)", + "zh-chs": "英文(牙買加)", "xloc": [ - "default.handlebars->25->774" + "default.handlebars->27->878" ] }, { "cs": "angličtina (Nový Zéland)", "de": "Englisch (Neuseeland)", "en": "English (New Zealand)", + "fr": "Anglais (Nouvelle-Zélande)", + "hi": "अंग्रेजी (न्यूजीलैंड)", "ja": "英語(ニュージーランド)", + "ko": "영어 (뉴질랜드)", "nl": "Engels (Nieuw Zeeland)", "pt": "Inglês (Nova Zelândia)", "ru": "Английский (Новая Зеландия)", + "zh-chs": "英文(紐西蘭)", "xloc": [ - "default.handlebars->25->775" + "default.handlebars->27->879" ] }, { "cs": "angličtina (Filipíny)", "de": "Englisch (Philippinen)", "en": "English (Philippines)", + "fr": "Anglais (Philippines)", + "hi": "अंग्रेजी (फिलीपींस)", "ja": "英語(フィリピン)", + "ko": "영어 (필리핀)", "nl": "Engels (Filippijnen)", "pt": "Inglês (Filipinas)", "ru": "Английский (Филиппины)", + "zh-chs": "英文(菲律賓)", "xloc": [ - "default.handlebars->25->776" + "default.handlebars->27->880" ] }, { "cs": "angličtina (Jihoafrická Republika)", "de": "Englisch (Südafrika)", "en": "English (South Africa)", + "fr": "Anglais (Afrique du Sud)", + "hi": "अंग्रेजी (दक्षिण अफ्रीका)", "ja": "英語(南アフリカ)", + "ko": "영어 (남아프리카)", "nl": "Engels (Zuid Africa)", "pt": "Inglês (África do Sul)", "ru": "Английский (Южная Африка)", + "zh-chs": "英語(南非)", "xloc": [ - "default.handlebars->25->777" + "default.handlebars->27->881" ] }, { "cs": "angličtina (Trinidad a Tobago)", "de": "Englisch (Trinidad Tobago)", "en": "English (Trinidad & Tobago)", + "fr": "Anglais (Trinidad & Tobago)", + "hi": "अंग्रेजी (त्रिनिदाद और टोबैगो)", "ja": "英語(トリニダードトバゴ)", + "ko": "영어 (트리니다드 토바고)", "nl": "Engels (Trinidad & Tobago)", "pt": "Inglês (Trinidad Tobago)", "ru": "Английский (Тринидад и Тобаго)", + "zh-chs": "英文(特立尼達和多巴哥)", "xloc": [ - "default.handlebars->25->778" + "default.handlebars->27->882" ] }, { @@ -6826,12 +9532,15 @@ "de": "Englisch (Vereinigtes Königreich)", "en": "English (United Kingdom)", "fr": "Anglais (Royaume Uni)", + "hi": "अंग्रेजी यूनाइटेड किंगडम)", "ja": "英語(イギリス)", + "ko": "영어 (영국)", "nl": "Engels (Verenigd Koninkrijk)", "pt": "Inglês (Reino Unido)", "ru": "Английский (Великобритания)", + "zh-chs": "英文(英國)", "xloc": [ - "default.handlebars->25->779" + "default.handlebars->27->883" ] }, { @@ -6839,12 +9548,15 @@ "de": "Englisch (USA)", "en": "English (United States)", "fr": "Anglais (États Unis)", + "hi": "अंग्रेजी संयुक्त राज्य)", "ja": "英語(米国)", + "ko": "영어 (미국)", "nl": "Engels (Verenigde staten van America)", "pt": "Inglês (Estados Unidos)", "ru": "Английский (Соединенные Штаты)", + "zh-chs": "美國英語)", "xloc": [ - "default.handlebars->25->780" + "default.handlebars->27->884" ] }, { @@ -6852,12 +9564,15 @@ "de": "Englisch (Simbabwe)", "en": "English (Zimbabwe)", "fr": "Anglais (Zimbabwe)", + "hi": "अंग्रेजी (जिम्बाब्वे)", "ja": "英語(ジンバブエ)", + "ko": "영어 (짐바브웨)", "nl": "Engels (Zimbabwe)", "pt": "Inglês (Zimbábue)", "ru": "Английский (Зимбабве)", + "zh-chs": "英文(津巴布韋)", "xloc": [ - "default.handlebars->25->781" + "default.handlebars->27->885" ] }, { @@ -6865,13 +9580,17 @@ "de": "Eingabe", "en": "Enter", "es": "Enter", + "fr": "Entrer", + "hi": "दर्ज", "ja": "入る", + "ko": "시작하다", "nl": "invoeren", "pt": "Entrar", "ru": "Ввод", + "zh-chs": "輸入", "xloc": [ - "default.handlebars->25->961", - "default.handlebars->25->962" + "default.handlebars->27->1066", + "default.handlebars->27->1067" ] }, { @@ -6879,12 +9598,16 @@ "de": "Geben Sie eine durch Kommas getrennte Liste der Namen der Verwaltungsbereiche ein.", "en": "Enter a comma seperate list of administrative realms names.", "es": "Ingrese una lista separada por comas de nombres de reinos administrativos.", + "fr": "Saisir une liste séparée par des virgules de noms de domaines administratifs.", + "hi": "प्रशासनिक क्षेत्र के नामों की अल्पविराम से अलग सूची दर्ज करें।", "ja": "管理レルム名のコンマ区切りリストを入力します。", + "ko": "쉼표로 구분 된 관리 영역 이름 목록을 입력하십시오.", "nl": "Voer een door komma's gescheiden lijst met beheerdersnamen in.", "pt": "Insira uma lista separada por vírgulas de nomes de regiões administrativas.", "ru": "Введите разделенный запятыми список имен административных областей.", + "zh-chs": "輸入管理領域名稱的逗號分隔列表。", "xloc": [ - "default.handlebars->25->1255" + "default.handlebars->27->1390" ] }, { @@ -6892,12 +9615,16 @@ "de": "Geben Sie einen Bereich von IP-Adressen ein, um nach Intel-AMT-Geräten zu suchen.", "en": "Enter a range of IP addresses to scan for Intel AMT devices.", "es": "Ingrese un rango de direcciones IP para buscar dispositivos Intel AMT.", + "fr": "Saisir une plage d'adresse IP pour détecter les appareils Intel AMT.", + "hi": "इंटेल एएमटी उपकरणों के लिए स्कैन करने के लिए आईपी पते की एक श्रृंखला दर्ज करें।", "ja": "IPアドレスの範囲を入力して、Intel AMTデバイスをスキャンします。", + "ko": "Intel AMT 장치를 검색 할 IP 주소 범위를 입력하십시오.", "nl": "Voer een reeks IP-adressen in om te scannen op Intel AMT-apparaten.", "pt": "Digite um intervalo de endereços IP para procurar dispositivos Intel AMT.", "ru": "Введите диапазон IP-адресов для сканирования Intel AMT устройств.", + "zh-chs": "輸入IP地址範圍以掃描Intel AMT設備。", "xloc": [ - "default.handlebars->25->253" + "default.handlebars->27->237" ] }, { @@ -6905,12 +9632,16 @@ "de": "Geben Sie Text ein und klicken Sie auf OK, um ihn über eine US-englische Tastatur aus der Ferne einzugeben. Stellen Sie sicher, dass sich der Remote-Cursor an der richtigen Position befindet, bevor Sie fortfahren.", "en": "Enter text and click OK to remotely type it using a US english keyboard. Make sure to place the remote cursor at the correct position before proceeding.", "es": "Ingrese el texto y haga clic en Aceptar para escribirlo de forma remota con un teclado de inglés de EE. UU. Asegúrese de colocar el cursor remoto en la posición correcta antes de continuar.", + "fr": "Entrer le texte et cliquer sur OK pour le saisir avec un clavier américain. Vérifier avant la position du curseur distant.", + "hi": "पाठ दर्ज करें और एक अमेरिकी अंग्रेजी कीबोर्ड का उपयोग करके इसे दूर से टाइप करने के लिए ठीक क्लिक करें। आगे बढ़ने से पहले रिमोट कर्सर को सही स्थिति में रखना सुनिश्चित करें।", "ja": "テキストを入力し、[OK]をクリックして、米国英語キーボードを使用してリモートで入力します。続行する前に、リモートカーソルを正しい位置に配置してください。", + "ko": "텍스트를 입력하고 확인을 클릭하여 미국 영어 키보드를 사용하여 원격으로 입력하십시오. 계속하기 전에 원격 커서를 올바른 위치에 놓으십시오.", "nl": "Voer tekst in en klik op OK om deze op afstand te typen met een Amerikaans Engels toetsenbord. Zorg ervoor dat u de externe cursor op de juiste positie plaatst voordat u doorgaat.", "pt": "Digite o texto e clique em OK para digitá-lo remotamente usando um teclado em inglês dos EUA.Certifique-se de colocar o cursor remoto na posição correta antes de continuar.", "ru": "Для удаленного набора введите текст, используя английскую раскладку и нажмите OK. Перед продолжением убедитесь, что курсор на удаленном компьютере установлен в правильное положение.", + "zh-chs": "輸入文本,然後單擊“確定”以使用美式英語鍵盤遠程輸入文本。在繼續操作之前,請確保將遠程光標放置在正確的位置。", "xloc": [ - "default.handlebars->25->614" + "default.handlebars->27->662" ] }, { @@ -6918,10 +9649,14 @@ "de": "Geben Sie das Kontoerstellungstoken ein", "en": "Enter the account creation token", "es": "Ingrese el token de creación de cuenta", + "fr": "Saisissez le jeton de création de compte", + "hi": "खाता निर्माण टोकन दर्ज करें", "ja": "アカウント作成トークンを入力してください", + "ko": "계정 생성 토큰을 입력하십시오", "nl": "Voer het token voor het maken van een account in", "pt": "Insira o token de criação da conta", "ru": "Введите токен создания аккаунта", + "zh-chs": "輸入帳戶創建令牌", "xloc": [ "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->createpanel->1->1->9->1", "login.handlebars->container->column_l->centralTable->1->0->logincell->createpanel->1->9->1" @@ -6932,12 +9667,16 @@ "de": "Geben Sie hier den Token für Zweifaktor-Anmeldung ein:", "en": "Enter the token here for 2-step login:", "es": "Ingrese el token aquí para iniciar sesión en 2 pasos:", + "fr": "Saisir le jeton de double authentification ici:", + "hi": "2-चरण लॉगिन के लिए यहां टोकन दर्ज करें:", "ja": "2段階ログインのトークンをここに入力します。", + "ko": "2 단계 로그인을 위해 여기에 토큰을 입력하십시오 :", "nl": "Voer hier het token in voor tweestaps-aanmelding:", "pt": "Digite o token aqui para o login em duas etapas:", "ru": "Для двухэтапного входа введите токен здесь:", + "zh-chs": "在此處輸入令牌以進行兩步登錄:", "xloc": [ - "default.handlebars->25->121" + "default.handlebars->27->104" ] }, { @@ -6945,12 +9684,16 @@ "de": "Fehler, Schlüssel kann nicht hinzugefügt werden.", "en": "Error, Unable to add key.", "es": "Error, no se puede agregar la llave.", + "fr": "Erreur, impossible d'ajouter la clé.", + "hi": "त्रुटि, कुंजी जोड़ने में असमर्थ।", "ja": "エラー、キーを追加できません。", + "ko": "오류, 키를 추가 할 수 없습니다.", "nl": "Fout, kan sleutel niet toevoegen.", "pt": "Erro, não foi possível adicionar a chave.", "ru": "Ошибка, Невозможно добавить код.", + "zh-chs": "錯誤,無法添加密鑰。", "xloc": [ - "default.handlebars->25->147" + "default.handlebars->27->130" ] }, { @@ -6958,10 +9701,14 @@ "de": "Fehler: Kein Verbindungsschlüssel angegeben.", "en": "Error: No connection key specified.", "es": "Error: No se ha especificado una clave de conexión.", + "fr": "Erreur : la clé de connexion n'a pas été spécifiée.", + "hi": "त्रुटि: कोई कनेक्शन कुंजी निर्दिष्ट नहीं है।", "ja": "エラー:接続キーが指定されていません。", + "ko": "오류 : 연결 키가 지정되지 않았습니다.", "nl": "Fout: geen verbindingssleutel opgegeven.", "pt": "Erro: Nenhuma chave de conexão especificada.", "ru": "Ошибка: Не указан ключ подключения.", + "zh-chs": "錯誤:未指定連接密鑰。", "xloc": [ "messenger.handlebars->13->8" ] @@ -6970,24 +9717,32 @@ "cs": "esperanto", "de": "Esperanto", "en": "Esperanto", + "fr": "espéranto", + "hi": "एस्पेरांतो", "ja": "エスペラント", + "ko": "에스페란토 말", "nl": "Esperanto", "pt": "Esperanto", "ru": "Эсперанто", + "zh-chs": "世界語", "xloc": [ - "default.handlebars->25->782" + "default.handlebars->27->886" ] }, { "cs": "estonština", "de": "Estnisch", "en": "Estonian", + "fr": "Estonien", + "hi": "एस्तोनियावासी", "ja": "エストニア語", + "ko": "에스토니아 사람", "nl": "Estlands", "pt": "Estoniano", "ru": "Эстонский", + "zh-chs": "愛沙尼亞語", "xloc": [ - "default.handlebars->25->783" + "default.handlebars->27->887" ] }, { @@ -6995,12 +9750,16 @@ "de": "Ereignisdetails", "en": "Event Details", "es": "Detalles del evento", + "fr": "Détails de l'évènement", + "hi": "घटना की जानकारी", "ja": "イベントの詳細", + "ko": "이벤트 상세", "nl": "Gebeurtenis details", "pt": "Detalhes do evento", "ru": "Детали события", + "zh-chs": "活動詳情", "xloc": [ - "default.handlebars->25->690" + "default.handlebars->27->739" ] }, { @@ -7008,12 +9767,16 @@ "de": "Ereignisliste exportieren", "en": "Event List Export", "es": "Exportar lista de eventos", + "fr": "Export de la liste des évènements", + "hi": "इवेंट सूची निर्यात", "ja": "イベントリストのエクスポート", + "ko": "이벤트리스트 내보내기", "nl": "Gebeurtenissenlijst exporteren", "pt": "Exportação da lista de eventos", "ru": "Экспорт списка событий", + "zh-chs": "活動列表導出", "xloc": [ - "default.handlebars->25->1199" + "default.handlebars->27->1329" ] }, { @@ -7022,10 +9785,13 @@ "en": "Events", "es": "Eventos", "fr": "Événements", + "hi": "आयोजन", "ja": "イベント", + "ko": "행사", "nl": "Gebeurtenissen", "pt": "Eventos", "ru": "События", + "zh-chs": "大事記", "xloc": [ "default.handlebars->container->topbar->1->1->MainSubMenuSpan->MainSubMenu->1->0->MainDevEvents", "default.handlebars->container->topbar->1->1->UserSubMenuSpan->UserSubMenu->1->0->UserEvents", @@ -7038,10 +9804,13 @@ "en": "Events -", "es": "Eventos -", "fr": "Événements -", + "hi": "आयोजन -", "ja": "イベント-", + "ko": "이벤트-", "nl": "Gebeurtenissen -", "pt": "Eventos -", "ru": "События - ", + "zh-chs": "活動-", "xloc": [ "default.handlebars->container->column_l->p16->p16title->3", "default.handlebars->container->column_l->p31->p31title->3" @@ -7052,12 +9821,33 @@ "de": "Bestehendes Konto mit dieser E-Mail-Adresse.", "en": "Existing account with this email address.", "es": "Cuenta existente con esta dirección de correo electrónico.", + "fr": "Un compte existe déjà avec cet email.", + "hi": "इस ईमेल पते के साथ मौजूदा खाता।", "ja": "このメールアドレスを持つ既存のアカウント。", + "ko": "이 이메일 주소를 가진 기존 계정.", "nl": "Bestaand account met dit e-mailadres.", + "pt": "Conta existente com este endereço de email.", "ru": "Существующий аккаунт с этим адресом email.", + "zh-chs": "使用此電子郵件地址的現有帳戶。", "xloc": [ - "login-mobile.handlebars->5->4", - "login.handlebars->5->4" + "login-mobile.handlebars->5->5", + "login.handlebars->5->5" + ] + }, + { + "cs": "Export informací o zařízení", + "de": "Geräteinformationen exportieren", + "en": "Export device information", + "fr": "Exporter les données des appareils sélectionnés", + "hi": "डिवाइस जानकारी निर्यात करें", + "ja": "デバイス情報をエクスポートする", + "ko": "장치 정보 내보내기", + "nl": "Exporteer apparaat informatie", + "pt": "Exportar informações do dispositivo", + "ru": "Экспорт информации об устройстве", + "zh-chs": "導出設備信息", + "xloc": [ + "default.handlebars->27->381" ] }, { @@ -7065,12 +9855,16 @@ "de": "Erweitertes ASCII", "en": "Extended ASCII", "es": "ASCII extendido", + "fr": "ASCII étendu", + "hi": "विस्तारित ASCII", "ja": "拡張ASCII", + "ko": "확장 ASCII", "nl": "Extended ASCII", "pt": "ASCII estendido", "ru": "Расширенный ASCII", + "zh-chs": "擴展ASCII", "xloc": [ - "default.handlebars->25->639" + "default.handlebars->27->688" ] }, { @@ -7078,10 +9872,14 @@ "de": "Erweitertes ASCII", "en": "Extended Ascii", "es": "Ascii extendido", + "fr": "Ascii étendu", + "hi": "विस्तारित अस्सी", "ja": "拡張アスキー", + "ko": "확장 된 아스키", "nl": "Extended Ascii", "pt": "Ascii estendido", "ru": "Расширенные Ascii", + "zh-chs": "擴展ASCII", "xloc": [ "default.handlebars->container->column_l->p12->termTable->1->1->6->1->1->terminalSettingsButtons" ] @@ -7091,10 +9889,16 @@ "de": "Extern", "en": "External", "es": "Externo", + "fr": "Externe", + "hi": "बाहरी", + "ja": "外部", + "ko": "외부", "nl": "Extern", + "pt": "Externo", "ru": "Внешний", + "zh-chs": "外部", "xloc": [ - "default.handlebars->25->1433" + "default.handlebars->27->1580" ] }, { @@ -7102,24 +9906,31 @@ "de": "Mazedonisch (EJRM)", "en": "FYRO Macedonian", "fr": "ARY Macédonien", + "hi": "FYRO मैसेडोनियन", "ja": "マケドニア語", + "ko": "FYRO 마케도니아 어", "nl": "FYRO Macedonisch", "pt": "FYRO Macedonian", "ru": "Mакедонский (БЮР)", + "zh-chs": "FYRO馬其頓語", "xloc": [ - "default.handlebars->25->833" + "default.handlebars->27->937" ] }, { "cs": "faerština", "de": "Färöisch", "en": "Faeroese", + "fr": "Féroïen", + "hi": "फ़ैरोईज़", "ja": "フェロー語", + "ko": "페로 어", "nl": "Faeroese", "pt": "O servidor remoto retornou um erro: (429) Too Many Requests.", "ru": "Фарерский", + "zh-chs": "法羅語", "xloc": [ - "default.handlebars->25->784" + "default.handlebars->27->888" ] }, { @@ -7128,12 +9939,15 @@ "en": "Failed", "es": "Fallo", "fr": "Échoué", + "hi": "अनुत्तीर्ण होना", "ja": "失敗しました", + "ko": "실패한", "nl": "Mislukt", "pt": "Falhou", "ru": "Не удалось", + "zh-chs": "失敗的", "xloc": [ - "default.handlebars->25->85" + "default.handlebars->27->67" ] }, { @@ -7141,12 +9955,15 @@ "de": "Persisch", "en": "Farsi (Persian)", "fr": "Farsi (Persan)", + "hi": "फ़ारसी (फ़ारसी)", "ja": "ペルシア語(ペルシャ語)", + "ko": "페르시아어", "nl": "Perzisch (Perzisch)", "pt": "Persa (persa)", "ru": "Фарси (Персидский)", + "zh-chs": "波斯語(波斯語)", "xloc": [ - "default.handlebars->25->785" + "default.handlebars->27->889" ] }, { @@ -7155,10 +9972,13 @@ "en": "Fast", "es": "Rápida", "fr": "Vite", + "hi": "तेज", "ja": "速い", + "ko": "빠른", "nl": "Snel", "pt": "Rápido", "ru": "Быстро", + "zh-chs": "快速", "xloc": [ "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->7->d7framelimiter->1", "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->7->d7framelimiter->1" @@ -7169,24 +9989,32 @@ "de": "Eigenschaften", "en": "Features", "es": "Caracteristicas", + "fr": "Fonctionnalités", + "hi": "विशेषताएं", "ja": "特徴", + "ko": "풍모", "nl": "Kenmerken", "pt": "Recursos", "ru": "Функции", + "zh-chs": "特徵", "xloc": [ - "default.handlebars->25->989" + "default.handlebars->27->1094" ] }, { "cs": "fidžijština", "de": "Fidschianisch", "en": "Fijian", + "fr": "Fidjien", + "hi": "फिजी", "ja": "フィジー人", + "ko": "피지 안", "nl": "Fijian", "pt": "Fijiano", "ru": "Фиджи", + "zh-chs": "斐濟", "xloc": [ - "default.handlebars->25->786" + "default.handlebars->27->890" ] }, { @@ -7195,13 +10023,17 @@ "en": "File Editor", "es": "Editor de archivos", "fr": "Éditeur de fichier", + "hi": "फ़ाइल संपादक", "ja": "ファイルエディター", + "ko": "파일 편집기", "nl": "Bestandsberwerker", "pt": "Editor de Arquivos", "ru": "Редактор файлов", + "zh-chs": "文件編輯器", "xloc": [ - "default-mobile.handlebars->9->254", - "default.handlebars->25->662" + "default-mobile.handlebars->9->258", + "default.handlebars->27->415", + "default.handlebars->27->711" ] }, { @@ -7210,10 +10042,13 @@ "en": "File Selection", "es": "Selección de archivo", "fr": "Sélection de fichier", + "hi": "फ़ाइल चयन", "ja": "ファイル選択", + "ko": "파일 선택", "nl": "Bestandsselectie", "pt": "Seleção de arquivo", "ru": "Выбор файла", + "zh-chs": "文件選擇", "xloc": [ "default.handlebars->container->dialog->dialogBody->dialog3->d3upload->1" ] @@ -7223,12 +10058,16 @@ "de": "Dateisystemtreiber", "en": "FileSystemDriver", "es": "FileSystemDriver", + "fr": "FileSystemDriver", + "hi": "FileSystemDriver", "ja": "FileSystemDriver", + "ko": "FileSystemDriver", "nl": "Bestandssysteem stuurprogramma", "pt": "Driver do sistema de arquivos", "ru": "Драйвер файловой системы", + "zh-chs": "FileSystemDriver", "xloc": [ - "default.handlebars->25->622" + "default.handlebars->27->671" ] }, { @@ -7237,12 +10076,15 @@ "en": "Files", "es": "Archivos", "fr": "Dossiers", + "hi": "फ़ाइलें", "ja": "ファイル", + "ko": "파일", "nl": "Bestanden", "pt": "Arquivos", "ru": "Файлы", + "zh-chs": "檔案", "xloc": [ - "default.handlebars->25->1076", + "default.handlebars->27->1180", "default.handlebars->container->topbar->1->1->MainSubMenuSpan->MainSubMenu->1->0->MainDevFiles", "default.handlebars->contextMenu->cxfiles" ] @@ -7252,11 +10094,14 @@ "de": "Dateien -", "en": "Files -", "es": "Archivos -", - "fr": "Dossiers –", + "fr": "Dossiers -", + "hi": "फ़ाइलें -", "ja": "ファイル-", + "ko": "파일-", "nl": "Bestanden -", "pt": "Arquivos - ", "ru": "Файлы - ", + "zh-chs": "文件-", "xloc": [ "default.handlebars->container->column_l->p13->p13title->3" ] @@ -7266,12 +10111,16 @@ "de": "Dateien-Benachrichtigung", "en": "Files Notify", "es": "Notificación de archivos", + "fr": "Notifier les fichiers", + "hi": "फ़ाइलें सूचित करें", "ja": "ファイル通知", + "ko": "파일 알림", "nl": "Bestanden Melden", "pt": "Notificação arquivos", "ru": "Уведомление файлов", + "zh-chs": "文件通知", "xloc": [ - "default.handlebars->25->997" + "default.handlebars->27->1102" ] }, { @@ -7279,12 +10128,16 @@ "de": "Dateien-Einverständnis", "en": "Files Prompt", "es": "Solicitud de archivos", + "fr": "Invite de fichiers", + "hi": "फ़ाइलें शीघ्र", "ja": "ファイルプロンプト", + "ko": "파일 프롬프트", "nl": "Bestanden vragen", "pt": "Arquivos do prompt", "ru": "Запрос файлов", + "zh-chs": "文件提示", "xloc": [ - "default.handlebars->25->996" + "default.handlebars->27->1101" ] }, { @@ -7293,10 +10146,13 @@ "en": "Filter", "es": "Filtrar", "fr": "Filtre", + "hi": "फ़िल्टर", "ja": "フィルタ", + "ko": "필터", "nl": "Filter", "pt": "Filtro", "ru": "Фильтр", + "zh-chs": "過濾", "xloc": [ "default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->devListToolbar", "default.handlebars->container->column_l->p4->3->1->0->3->3" @@ -7308,12 +10164,15 @@ "en": "Finnish", "es": "Finlandés", "fr": "Finlandais", + "hi": "फिनिश", "ja": "フィンランド語", + "ko": "핀란드어", "nl": "Fins", "pt": "Finlandês", "ru": "Финский", + "zh-chs": "芬蘭", "xloc": [ - "default.handlebars->25->787" + "default.handlebars->27->891" ] }, { @@ -7322,14 +10181,18 @@ "en": "Fixed width interface", "es": "Interfaz de ancho fijo", "fr": "Interface à largeur fixe", + "hi": "निश्चित चौड़ाई इंटरफ़ेस", "ja": "固定幅インターフェイス", + "ko": "고정 폭 인터페이스", "nl": "Interface met vaste breedte", "pt": "Interface de largura fixa", "ru": "Интерфейс с фиксированной шириной", + "zh-chs": "固定寬度接口", "xloc": [ "agentinvite.handlebars->container->topbar->uiMenuButton->uiMenu", "default.handlebars->container->topbar->1->1->uiMenuButton->uiMenu", "error404.handlebars->container->topbar->uiMenuButton->uiMenu", + "invite.handlebars->container->topbar->uiMenuButton->uiMenu", "login.handlebars->container->topbar->uiMenuButton->uiMenu", "terms.handlebars->container->topbar->uiMenuButton->uiMenu" ] @@ -7339,10 +10202,14 @@ "de": "Alles fokussieren", "en": "Focus All", "es": "Enfocar todo", + "fr": "Tout concentrer", + "hi": "सभी पर ध्यान दें", "ja": "すべてにフォーカス", + "ko": "모든 초점", "nl": "Focus alles", "pt": "Focus All", "ru": "Фокусировать все", + "zh-chs": "全部關注", "xloc": [ "default.handlebars->container->column_l->p11->deskarea0->deskarea1->1" ] @@ -7353,27 +10220,74 @@ "en": "Folder", "es": "Carpeta", "fr": "Dossier", + "hi": "फ़ोल्डर", "ja": "フォルダ", + "ko": "폴더", "nl": "Map", "pt": "Pasta", "ru": "Папка", + "zh-chs": "夾", "xloc": [ "default-mobile.handlebars->container->page_content->column_l->p10->p10files->p13toolbar->1->2->1->1", "default-mobile.handlebars->container->page_content->column_l->p5->p5myfiles->p5toolbar->1->0->1->1" ] }, + { + "cs": "V případě systému Apple OSX dokončete proces pomocí následujícího odkazu:", + "de": "Nagivieren Sie unter Apple OSX den folgenden Link, um den Vorgang abzuschließen:", + "en": "For Apple OSX, nagivate to the following link to complete the process:", + "nl": "Voor Apple OSX ga je naar de volgende link om het proces te voltooien:", + "fr": "Pour Apple OSX, accédez au lien suivant pour terminer le processus:", + "ja": "Apple OSXの場合、次のリンクに移動してプロセスを完了します。", + "ru": "Для Apple OSX перейдите по следующей ссылке, чтобы завершить процесс:", + "zh-chs": "对于Apple OSX,请导航至以下链接以完成该过程:", + "xloc": [ + "mesh-invite.txt" + ] + }, + { + "cs": "V případě systému Linux vyjměte a vložte do terminálu a nainstalujte agenta:", + "de": "Schneiden Sie unter Linux Folgendes aus und fügen Sie es in ein Terminal ein, um den Agenten zu installieren:", + "en": "For Linux, cut & paste the following in a terminal to install the agent:", + "fr": "Pour Linux, copiez et collez les éléments suivants dans un terminal pour installer l'agent:", + "nl": "Voor Linux, knip het volgende en plak dit in een terminal om de agent te installeren:", + "ja": "Linuxの場合は、ターミナルで以下をカットアンドペーストしてエージェントをインストールします。", + "ru": "Для Linux вырезайте и вставляйте в терминал следующее, чтобы установить агент:", + "zh-chs": "对于Linux,将以下内容剪切并粘贴到终端中以安装代理程序:", + "xloc": [ + "mesh-invite.html->2->13->1", + "mesh-invite.txt" + ] + }, + { + "cs": "V případě systému Windows dokončete proces pomocí následujícího odkazu:", + "de": "Nagivieren Sie unter Windows den folgenden Link, um den Vorgang abzuschließen:", + "en": "For Windows, nagivate to the following link to complete the process:", + "nl": "Voor Windows, ga je naar de volgende link om het proces te voltooien:", + "fr": "Pour Windows, accédez au lien suivant pour terminer le processus:", + "ja": "Windowsの場合、次のリンクに移動してプロセスを完了します。", + "ru": "Для Windows откройте следующую ссылку, чтобы завершить процесс:", + "zh-chs": "对于Windows,请导航至以下链接以完成该过程:", + "xloc": [ + "mesh-invite.txt" + ] + }, { "cs": "Vynutit reset hesla při dalším přihlášení.", "de": "Passwort beim nächsten Login zurücksetzen.", "en": "Force password reset on next login.", "es": "Forzar restablecimiento de contraseña en el próximo inicio de sesión.", + "fr": "Forcer la réinitialisation du mot de passe à la prochaine connexion.", + "hi": "अगले लॉगिन पर फोर्स पासवर्ड रीसेट।", "ja": "次回ログイン時にパスワードを強制的にリセットします。", + "ko": "다음에 로그인 할 때 비밀번호를 강제로 재설정하십시오.", "nl": "Forceer wachtwoord wijziging bij de volgende aanmelding.", "pt": "Forçar redefinição de senha no próximo login.", "ru": "Принудительно сбросить пароль при следующем входе в систему.", + "zh-chs": "下次登錄時強制重置密碼。", "xloc": [ - "default.handlebars->25->1249", - "default.handlebars->25->1363" + "default.handlebars->27->1384", + "default.handlebars->27->1501" ] }, { @@ -7382,13 +10296,16 @@ "en": "Forgot password?", "es": "¿Se te olvidó tu contraseña?", "fr": "Mot de passe oublié?", + "hi": "पासवर्ड भूल गए?", "ja": "パスワードをお忘れですか?", + "ko": "비밀번호를 잊으 셨나요?", "nl": "Wachtwoord vergeten?", "pt": "Esqueceu a senha?", "ru": "Забыли пароль?", + "zh-chs": "忘記密碼?", "xloc": [ - "login-mobile.handlebars->5->18", - "login.handlebars->5->18" + "login-mobile.handlebars->5->19", + "login.handlebars->5->19" ] }, { @@ -7396,10 +10313,14 @@ "de": "Benutzername/Passwort vergessen?", "en": "Forgot user/password?", "es": "¿Olvidó su usuario / contraseña?", + "fr": "Identifiant / Mot de passe oubliés ?", + "hi": "उपयोगकर्ता / पासवर्ड भूल गए?", "ja": "ユーザー/パスワードを忘れましたか?", + "ko": "사용자 / 비밀번호를 잊어 버리셨습니까?", "nl": "Gebruikersnaam/wachtwoord vergeten?", "pt": "Esqueceu usuário / senha?", "ru": "Забыли логин/пароль?", + "zh-chs": "忘記用戶名/密碼了嗎?", "xloc": [ "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->loginpanel->1->resetAccountDiv->resetAccountSpan" ] @@ -7409,10 +10330,14 @@ "de": "Benutzername/Passwort vergessen?", "en": "Forgot username/password?", "es": "¿Olvidó su nombre de usuario / contraseña?", + "fr": "Nom d'utilisateur / Mot de passe oublié ?", + "hi": "उपयोगकर्ता नाम / पासवर्ड भूल गए?", "ja": "ユーザー名/パスワードを忘れましたか?", + "ko": "아이디 / 비밀번호를 잊어 버리셨습니까?", "nl": "Gebruikersnaam/wachtwoord vergeten?", "pt": "Esqueceu seu nome de usuário / senha?", "ru": "Забыли логин/пароль?", + "zh-chs": "忘記用戶名/密碼了嗎?", "xloc": [ "login.handlebars->container->column_l->centralTable->1->0->logincell->loginpanel->1->resetAccountDiv->resetAccountSpan" ] @@ -7422,10 +10347,14 @@ "de": "Bildrate", "en": "Frame rate", "es": "Cuadros por segundo", + "fr": "Taux de rafraîchissement", + "hi": "फ्रेम रेट", "ja": "フレームレート", + "ko": "프레임 속도", "nl": "Frameverhouding", "pt": "Taxa de quadros", "ru": "Частота кадров", + "zh-chs": "影格速率", "xloc": [ "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->7->1" ] @@ -7436,13 +10365,16 @@ "en": "Free", "es": "Gratis", "fr": "Libre", + "hi": "नि: शुल्क", "ja": "無料", + "ko": "비어 있는", "nl": "Vrij", "pt": "Livre", "ru": "Свободно", + "zh-chs": "自由", "xloc": [ - "default.handlebars->25->1394", - "default.handlebars->25->1396" + "default.handlebars->27->1541", + "default.handlebars->27->1543" ] }, { @@ -7450,13 +10382,17 @@ "de": "FreeBSD x86-64", "en": "FreeBSD x86-64", "es": "FreeBSD x86-64", + "fr": "FreeBSD x86-64", + "hi": "फ्रीबीएसडी x86-64", "ja": "FreeBSD x86-64", + "ko": "FreeBSD x86-64", "nl": "FreeBSD x86-64", "pt": "FreeBSD x86-64", "ru": "FreeBSD x86-64", + "zh-chs": "FreeBSD x86-64", "xloc": [ - "default-mobile.handlebars->9->173", - "default.handlebars->25->43" + "default-mobile.handlebars->9->177", + "default.handlebars->27->43" ] }, { @@ -7464,12 +10400,15 @@ "de": "Französisch (Belgien)", "en": "French (Belgium)", "fr": "Français (Belgique)", + "hi": "फ्रेंच (बेल्जियम)", "ja": "フランス語(ベルギー)", + "ko": "프랑스어 (벨기에)", "nl": "Frans (België)", "pt": "Francês (Bélgica)", "ru": "Французский (Бельгия)", + "zh-chs": "法語(比利時)", "xloc": [ - "default.handlebars->25->789" + "default.handlebars->27->893" ] }, { @@ -7477,12 +10416,15 @@ "de": "Französisch (Kanada)", "en": "French (Canada)", "fr": "Français (Canada)", + "hi": "फ्रेंच (कनाडा)", "ja": "フランス語(カナダ)", + "ko": "프랑스어 (캐나다)", "nl": "Frans (Canada)", "pt": "Francês (Canadá)", "ru": "Французский (Канада)", + "zh-chs": "法語(加拿大)", "xloc": [ - "default.handlebars->25->790" + "default.handlebars->27->894" ] }, { @@ -7490,12 +10432,15 @@ "de": "Französisch (Frankreich)", "en": "French (France)", "fr": "Français (France)", + "hi": "फ्रेंच फ्रांस)", "ja": "フランス語(フランス)", + "ko": "프랑스어 (프랑스)", "nl": "Frans (Frankrijk)", "pt": "Francês (França)", "ru": "Французский (Франция)", + "zh-chs": "法語(法國)", "xloc": [ - "default.handlebars->25->791" + "default.handlebars->27->895" ] }, { @@ -7503,12 +10448,15 @@ "de": "Französisch (Luxemburg)", "en": "French (Luxembourg)", "fr": "Français (Luxembourg)", + "hi": "फ्रेंच (लक्समबर्ग)", "ja": "フランス語(ルクセンブルグ)", + "ko": "프랑스어 (룩셈부르크)", "nl": "Frans (Luxemburg)", "pt": "Francês (Luxemburgo)", "ru": "Французский (Люксембург)", + "zh-chs": "法語(盧森堡)", "xloc": [ - "default.handlebars->25->792" + "default.handlebars->27->896" ] }, { @@ -7516,12 +10464,15 @@ "de": "Französisch (Monaco)", "en": "French (Monaco)", "fr": "Français (Monaco)", + "hi": "फ्रेंच (मोनाको)", "ja": "フランス語(モナコ)", + "ko": "프랑스어 (모나코)", "nl": "Frans (Monaco)", "pt": "Francês (Mônaco)", "ru": "Французский (Монако)", + "zh-chs": "法語(摩納哥)", "xloc": [ - "default.handlebars->25->793" + "default.handlebars->27->897" ] }, { @@ -7529,12 +10480,15 @@ "de": "Französisch (Standard)", "en": "French (Standard)", "fr": "Français (standard)", + "hi": "फ्रेंच (मानक)", "ja": "フランス語(標準)", + "ko": "프랑스어 (표준)", "nl": "Frans (standaard)", "pt": "Francês (Padrão)", "ru": "Французский (Стандартный)", + "zh-chs": "法語(標準)", "xloc": [ - "default.handlebars->25->788" + "default.handlebars->27->892" ] }, { @@ -7542,12 +10496,15 @@ "de": "Französisch (Schweiz)", "en": "French (Switzerland)", "fr": "Français (Suisse)", + "hi": "फ्रेंच (स्विट्जरलैंड)", "ja": "フランス語(スイス)", + "ko": "프랑스어 (스위스)", "nl": "Frans (Zwitserland)", "pt": "Francês (Suíça)", "ru": "Французский (Швейцария)", + "zh-chs": "法語(瑞士)", "xloc": [ - "default.handlebars->25->794" + "default.handlebars->27->898" ] }, { @@ -7555,12 +10512,15 @@ "de": "Friesisch", "en": "Frisian", "fr": "Frison", + "hi": "फ़्रिसियाई", "ja": "フリジア語", + "ko": "프리지아 어", "nl": "Fries", "pt": "Frísio", "ru": "Фризский", + "zh-chs": "弗里斯蘭語", "xloc": [ - "default.handlebars->25->795" + "default.handlebars->27->899" ] }, { @@ -7568,12 +10528,15 @@ "de": "Friaulisch", "en": "Friulian", "fr": "Frioulan", + "hi": "फ्रीयुलीयान", "ja": "フリウリアン", + "ko": "프리 울리 안", "nl": "Friulian", "pt": "Friuliano", "ru": "Фриульский", + "zh-chs": "弗留利", "xloc": [ - "default.handlebars->25->796" + "default.handlebars->27->900" ] }, { @@ -7582,18 +10545,21 @@ "en": "Full Administrator", "es": "Administrador Completo", "fr": "Administrateur Complet", + "hi": "पूर्ण प्रशासक", "ja": "完全な管理者", + "ko": "전체 관리자", "nl": "Volledige beheerder", "pt": "Administrador completo", "ru": "Администратор с полным доступом", + "zh-chs": "正式管理員", "xloc": [ - "default-mobile.handlebars->9->283", - "default-mobile.handlebars->9->292", - "default-mobile.handlebars->9->310", - "default-mobile.handlebars->9->64", - "default.handlebars->25->1091", - "default.handlebars->25->1260", - "default.handlebars->25->968" + "default-mobile.handlebars->9->287", + "default-mobile.handlebars->9->296", + "default-mobile.handlebars->9->314", + "default-mobile.handlebars->9->67", + "default.handlebars->27->1073", + "default.handlebars->27->1198", + "default.handlebars->27->1396" ] }, { @@ -7602,12 +10568,15 @@ "en": "Full Administrator (all rights)", "es": "Administrador Completo (todos los permisos)", "fr": "Administrateur Complet (tous droits)", + "hi": "पूर्ण प्रशासक (सभी अधिकार)", "ja": "完全な管理者(すべての権利)", + "ko": "전체 관리자 (모든 권한)", "nl": "Volledige beheerder (met alle rechten)", "pt": "Administrador Pleno (todos os direitos)", "ru": "Администратор с полным доступом (все права)", + "zh-chs": "正式管理員(保留所有權利)", "xloc": [ - "default.handlebars->25->1114" + "default.handlebars->27->1226" ] }, { @@ -7615,12 +10584,42 @@ "de": "Gesamt-Gerätegruppenadministrator", "en": "Full Device Group Administrator", "es": "Administrador de grupo completo de dispositivos", + "fr": "Administrateur global ", + "hi": "फुल डिवाइस ग्रुप एडमिनिस्ट्रेटर", + "ja": "完全なデバイスグループ管理者", + "ko": "전체 장치 그룹 관리자", "nl": "Volledige apparaatgroep beheerder", + "pt": "Administrador de grupo de dispositivos completo", "ru": "Администратор группы устройств с полным доступом", + "zh-chs": "完整的設備組管理員" + }, + { + "cs": "Úplná práva na zařízení", + "de": "Volle Geräterechte", + "en": "Full Device Rights", + "fr": "Droits complets sur l'appareil", + "hi": "पूर्ण उपकरण अधिकार", + "ja": "完全なデバイスの権利", + "ko": "모든 장치 권한", + "nl": "Volledige apparaatrechten", + "pt": "Direitos completos do dispositivo", + "ru": "Полные права на устройство", + "zh-chs": "完整的設備權限", "xloc": [ - "default.handlebars->25->1031", - "default.handlebars->25->1297", - "default.handlebars->25->1371" + "default.handlebars->27->541" + ] + }, + { + "cs": "Plná práva", + "de": "Volle Rechte", + "en": "Full Rights", + "fr": "Droits complets", + "ja": "完全な権利", + "nl": "Volledige rechten", + "ru": "Полные права", + "zh-chs": "完全权利", + "xloc": [ + "default.handlebars->27->557" ] }, { @@ -7629,10 +10628,13 @@ "en": "Full Screen. Hold shift to browser full screen.", "es": "Pantalla completa. Mantenga presionada la tecla Mayús a pantalla completa del navegador", "fr": "Plein écran. Maintenez la touche Maj enfoncée dans le navigateur en plein écran.", + "hi": "पूर्ण स्क्रीन। ब्राउज़र को पूर्ण स्क्रीन पर शिफ्ट रखें।", "ja": "全画面表示。ブラウザの全画面表示に移行します。", + "ko": "전체 화면. 브라우저를 전체 화면으로 전환합니다.", "nl": "Volledig scherm. Houd shift ingedrukt om de browser op volledig scherm weer te geven.", "pt": "Tela cheia. Mantenha a tecla Shift pressionada no navegador em tela cheia.", "ru": "Полноэкранный режим. Удерживайте shift для полноэкранного режима браузера.", + "zh-chs": "全屏。按住shift鍵以全屏瀏覽器。", "xloc": [ "default.handlebars->container->column_l->p11->p11title->p11deviceNameHeader->devListToolbarViewIcons", "default.handlebars->container->column_l->p12->p12title->devListToolbarViewIcons2", @@ -7645,12 +10647,15 @@ "en": "Full administrator", "es": "Administrador Completo", "fr": "Administrateur complet", + "hi": "पूर्ण प्रशासक", "ja": "完全な管理者", + "ko": "전체 관리자", "nl": "Volledige beheerder", "pt": "Administrador completo", "ru": "Администратор с полным доступом", + "zh-chs": "正式管理員", "xloc": [ - "default.handlebars->25->1320" + "default.handlebars->27->1454" ] }, { @@ -7658,12 +10663,15 @@ "de": "Gälisch (Irisch)", "en": "Gaelic (Irish)", "fr": "Gaélique (irlandais)", + "hi": "गेलिक (आयरिश)", "ja": "ゲール語(アイルランド語)", + "ko": "게 일어 (아일랜드어)", "nl": "Gaelic (Iers)", "pt": "Gaélico (irlandês)", "ru": "Гэльский (Ирландский)", + "zh-chs": "蓋爾語(愛爾蘭)", "xloc": [ - "default.handlebars->25->798" + "default.handlebars->27->902" ] }, { @@ -7671,12 +10679,15 @@ "de": "Gälisch (Schottisch)", "en": "Gaelic (Scots)", "fr": "Gaélique (écossais)", + "hi": "गेलिक (स्कॉट्स)", "ja": "ゲール語(スコットランド)", + "ko": "게 일어 (Scots)", "nl": "Gaelic (Schots)", "pt": "Gaélico (escocês)", "ru": "Гэльский (Шотландия)", + "zh-chs": "蓋爾語(蘇格蘭語)", "xloc": [ - "default.handlebars->25->797" + "default.handlebars->27->901" ] }, { @@ -7684,12 +10695,15 @@ "de": "Galicisch", "en": "Galacian", "fr": "Galicien", + "hi": "गालेशियाई", "ja": "ガラシアン", + "ko": "갈라 시아", "nl": "Galacian", "pt": "Galego", "ru": "Галицкий", + "zh-chs": "加拉契人", "xloc": [ - "default.handlebars->25->799" + "default.handlebars->27->903" ] }, { @@ -7698,12 +10712,15 @@ "en": "Gateway MAC", "es": "MAC del Gateway", "fr": "Passerelle MAC", + "hi": "गेटवे मैक", "ja": "ゲートウェイMAC", + "ko": "게이트웨이 MAC", "nl": "Gateway MAC", "pt": "Gateway MAC", "ru": "MAC шлюза", + "zh-chs": "網關MAC", "xloc": [ - "default.handlebars->25->106" + "default.handlebars->27->89" ] }, { @@ -7712,10 +10729,13 @@ "en": "General", "es": "General", "fr": "Général", + "hi": "सामान्य", "ja": "全般", + "ko": "일반", "nl": "Algemeen", "pt": "Geral", "ru": "Сводка", + "zh-chs": "一般", "xloc": [ "default.handlebars->container->topbar->1->1->MainSubMenuSpan->MainSubMenu->1->0->MainDev", "default.handlebars->container->topbar->1->1->MeshSubMenuSpan->MeshSubMenu->1->0->MeshGeneral", @@ -7729,10 +10749,13 @@ "en": "General -", "es": "General -", "fr": "Général -", + "hi": "सामान्य -", "ja": "全般-", + "ko": "일반 -", "nl": "Algemeen -", "pt": "Geral - ", "ru": "Сводка - ", + "zh-chs": "一般 -", "xloc": [ "default.handlebars->container->column_l->p10->1->1->0->1->p10title->3", "default.handlebars->container->column_l->p20->p20title->5", @@ -7745,12 +10768,15 @@ "en": "General information", "es": "Información General", "fr": "Informations générales", + "hi": "सामान्य जानकारी", "ja": "一般情報", + "ko": "일반 정보", "nl": "Algemene informatie", "pt": "Informações gerais", "ru": "Общая информация", + "zh-chs": "一般信息", "xloc": [ - "default.handlebars->25->418" + "default.handlebars->27->422" ] }, { @@ -7759,12 +10785,15 @@ "en": "Generate New Tokens", "es": "Generar Nuevo Token", "fr": "Générer de nouveaux jetons", + "hi": "नए स्तन उत्पन्न करें", "ja": "新しいトークンを生成する", + "ko": "새로운 토큰 생성", "nl": "Genereer nieuwe tokens", "pt": "Gere novos tokens", "ru": "Генерация новых токенов", + "zh-chs": "生成新令牌", "xloc": [ - "default.handlebars->25->135" + "default.handlebars->27->118" ] }, { @@ -7772,84 +10801,111 @@ "de": "georgisch", "en": "Georgian", "fr": "Géorgien", + "hi": "जॉर्जियाई", "ja": "グルジア語", + "ko": "조르지아 주 사람", "nl": "Georgisch", "pt": "Georgiano", "ru": "Грузинский", + "zh-chs": "格魯吉亞人", "xloc": [ - "default.handlebars->25->800" + "default.handlebars->27->904" ] }, { "cs": "němčina (Rakousko)", "de": "Deutsch (Österreich)", "en": "German (Austria)", + "fr": "Allemand (Autriche)", + "hi": "जर्मन (ऑस्ट्रिया)", "ja": "ドイツ語(オーストリア)", + "ko": "독일어 (오스트리아)", "nl": "Duits (Oostenrijk)", "pt": "Alemão (Áustria)", "ru": "Немецкий (Австрия)", + "zh-chs": "德語(奧地利)", "xloc": [ - "default.handlebars->25->802" + "default.handlebars->27->906" ] }, { "cs": "němčina (Německo)", "de": "Deutsch (Deutschland)", "en": "German (Germany)", + "fr": "Allemand (Allemagne)", + "hi": "जर्मन जर्मनी)", "ja": "ドイツ語(ドイツ)", + "ko": "독일어 (독일)", "nl": "Duits (duitsland)", "pt": "Alemão (Alemanha)", "ru": "Немецкий (Германия)", + "zh-chs": "德文(德國)", "xloc": [ - "default.handlebars->25->803" + "default.handlebars->27->907" ] }, { "cs": "němčina (Lichtenštejnsko)", "de": "Deutsch (Liechtenstein)", "en": "German (Liechtenstein)", + "fr": "Allemand (Liechtenstein)", + "hi": "जर्मन (लिकटेंस्टीन)", "ja": "ドイツ語(リヒテンシュタイン)", + "ko": "독일어 (리히텐슈타인)", "nl": "Duits (Liechtenstein)", "pt": "Alemão (Liechtenstein)", "ru": "Немецкий (Лихтенштейн)", + "zh-chs": "德文(列支敦士登)", "xloc": [ - "default.handlebars->25->804" + "default.handlebars->27->908" ] }, { "cs": "němčina (Lucembursko)", "de": "Deutsch (Luxemburg)", "en": "German (Luxembourg)", + "fr": "Allemand (Luxembourg)", + "hi": "जर्मन (लक्समबर्ग)", "ja": "ドイツ語(ルクセンブルグ)", + "ko": "독일어 (룩셈부르크)", "nl": "Duits (Luxemburg)", "pt": "Alemão (Luxemburgo)", "ru": "Немецкий (Люксембург)", + "zh-chs": "德語(盧森堡)", "xloc": [ - "default.handlebars->25->805" + "default.handlebars->27->909" ] }, { "cs": "němčina (standardní)", "de": "Deutsch (Standard)", "en": "German (Standard)", + "fr": "Allemand (Standard)", + "hi": "जर्मन (मानक)", "ja": "ドイツ語(標準)", + "ko": "독일어 (표준)", "nl": "Duits (standaard)", "pt": "Alemão (Padrão)", "ru": "Немецкий (Стандартный)", + "zh-chs": "德語(標準)", "xloc": [ - "default.handlebars->25->801" + "default.handlebars->27->905" ] }, { "cs": "němčina (Švýcarsko)", "de": "Deutsch (Schweiz)", "en": "German (Switzerland)", + "fr": "Allemand (Suisse)", + "hi": "जर्मन (स्विट्जरलैंड)", "ja": "ドイツ語(スイス)", + "ko": "독일어 (스위스)", "nl": "Duits (Zwitserland)", "pt": "Alemão (Suíça)", "ru": "Немецкий (Швейцария)", + "zh-chs": "德語(瑞士)", "xloc": [ - "default.handlebars->25->806" + "default.handlebars->27->910" ] }, { @@ -7857,12 +10913,16 @@ "de": "MQTT-Zugangsdaten für dieses Gerät abrufen.", "en": "Get MQTT login credentials for this device.", "es": "Obtenga Credenciales de inicio de sesión MQTT para este dispositivo.", + "fr": "Obtenir des identifiants MQTT pour cet appareil.", + "hi": "इस डिवाइस के लिए MQTT लॉगिन क्रेडेंशियल प्राप्त करें।", "ja": "このデバイスのMQTTログイン資格情報を取得します。", + "ko": "이 장치의 MQTT 로그인 자격 증명을 가져옵니다.", "nl": "Ontvang MQTT-inloggegevens voor dit apparaat.", "pt": "Obtenha credenciais de login do MQTT para este dispositivo.", "ru": "Получить учетные данные MQTT для этого устройства.", + "zh-chs": "獲取此設備的MQTT登錄憑據。", "xloc": [ - "default.handlebars->25->518" + "default.handlebars->27->525" ] }, { @@ -7871,10 +10931,13 @@ "en": "Get started here!", "es": "¡Comience aquí!", "fr": "Commencez ici!", + "hi": "यहाँ से शुरुआत करें!", "ja": "ここから始めましょう!", + "ko": "여기서 시작하십시오!", "nl": "Begin hier!", "pt": "Comece aqui!", "ru": "Начните здесь!", + "zh-chs": "從這裡開始!", "xloc": [ "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3noMeshFound->p3createMeshLink2->1->0", "default.handlebars->container->column_l->p2->p2noMeshFound->p2createMeshLink2->1->0" @@ -7886,10 +10949,13 @@ "en": "Go to main site", "es": "Ir al sitio principal", "fr": "Aller sur le site principal", + "hi": "मुख्य साइट पर जाएं", "ja": "メインサイトに行く", + "ko": "메인 사이트로 이동", "nl": "Ga naar hoofdsite", "pt": "Ir para o site principal", "ru": "Перейти на главный сайт", + "zh-chs": "前往主要網站", "xloc": [ "error404-mobile.handlebars->container->page_content->column_l->5->0->0", "error404.handlebars->container->column_l->5->0->0" @@ -7901,12 +10967,15 @@ "en": "Good", "es": "Bueno", "fr": "Bien", + "hi": "अच्छा", "ja": "良い", + "ko": "좋은", "nl": "Goed", "pt": "Bom", "ru": "Хорошо", + "zh-chs": "好", "xloc": [ - "default.handlebars->25->964" + "default.handlebars->27->1069" ] }, { @@ -7915,15 +10984,18 @@ "en": "Good Password", "es": "Buena contraseña", "fr": "Bon mot de passe", + "hi": "अच्छा पासवर्ड", "ja": "良いパスワード", + "ko": "좋은 비밀번호", "nl": "Goed wachtwoord", "pt": "Boa senha", "ru": "Хороший пароль", + "zh-chs": "好的密碼", "xloc": [ - "login-mobile.handlebars->5->21", - "login-mobile.handlebars->5->25", - "login.handlebars->5->21", - "login.handlebars->5->25" + "login-mobile.handlebars->5->24", + "login-mobile.handlebars->5->28", + "login.handlebars->5->24", + "login.handlebars->5->28" ] }, { @@ -7931,12 +11003,15 @@ "de": "Griechisch", "en": "Greek", "fr": "Grec", + "hi": "यूनानी", "ja": "ギリシャ語", + "ko": "그리스 어", "nl": "Grieks", "pt": "Grego", "ru": "Греческий", + "zh-chs": "希臘語", "xloc": [ - "default.handlebars->25->807" + "default.handlebars->27->911" ] }, { @@ -7945,13 +11020,16 @@ "en": "Group", "es": "Grupo", "fr": "Groupe", + "hi": "समूह", "ja": "グループ", + "ko": "그룹", "nl": "Groep", "pt": "Grupo", "ru": "Группа", + "zh-chs": "組", "xloc": [ - "default-mobile.handlebars->9->134", - "default.handlebars->25->443", + "default-mobile.handlebars->9->138", + "default.handlebars->27->447", "default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->9->devListToolbarSort->sortselect->1" ] }, @@ -7960,13 +11038,16 @@ "de": "Gruppenaktion", "en": "Group Action", "es": "Acción grupal", - "fr": "Action de groupe", + "fr": "Action groupée", + "hi": "समूह क्रिया", "ja": "グループアクション", + "ko": "그룹 액션", "nl": "Groepsactie", "pt": "Ações do grupo", "ru": "Групповое действие", + "zh-chs": "集體行動", "xloc": [ - "default.handlebars->25->393", + "default.handlebars->27->384", "default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->devListToolbar" ] }, @@ -7975,10 +11056,16 @@ "de": "Gruppenmitglieder", "en": "Group Members", "es": "Miembros del grupo", + "fr": "Membres du groupe", + "hi": "समूह के सदस्य", + "ja": "グループの人(仲間)たち", + "ko": "그룹 멤버", "nl": "Groeps leden", + "pt": "Membros do grupo", "ru": "Члены группы", + "zh-chs": "小組成員", "xloc": [ - "default.handlebars->25->1289" + "default.handlebars->27->1425" ] }, { @@ -7987,12 +11074,15 @@ "en": "Group permissions for user {0}.", "es": "Permisos de grupo para el usuario {0}.", "fr": "Autorisations de groupe pour l'utilisateur {0}.", + "hi": "उपयोगकर्ता के लिए समूह अनुमतियाँ {0}।", "ja": "ユーザー{0}のグループ権限。", + "ko": "사용자 {0}에 대한 그룹 권한.", "nl": "Groepsrechten voor gebruiker {0}.", "pt": "Permissões de grupo para o usuário {0}.", "ru": "Права на группу для пользователя {0}.", + "zh-chs": "用戶{0}的組權限。", "xloc": [ - "default.handlebars->25->1090" + "default.handlebars->27->1197" ] }, { @@ -8000,10 +11090,16 @@ "de": "Gruppenberechtigungen für {0}.", "en": "Group permissions for {0}.", "es": "Permisos de grupo para {0}.", + "fr": "Autorisations de groupe pour {0}.", + "hi": "{0} के लिए समूह अनुमतियाँ।", + "ja": "{0}のグループ権限。", + "ko": "{0}에 대한 그룹 권한", "nl": "Groepsrechten voor {0}.", + "pt": "Permissões de grupo para {0}.", "ru": "Права на группу для {0}.", + "zh-chs": "{0}的組權限。", "xloc": [ - "default.handlebars->25->1089" + "default.handlebars->27->1196" ] }, { @@ -8012,12 +11108,15 @@ "en": "Group1, Group2, Group3", "es": "Grupo1, Grupo2, Grupo3", "fr": "Groupe1, Groupe2, Groupe3", + "hi": "ग्रुप 1, ग्रुप 2, ग्रूव", "ja": "Group1、Group2、Group3", + "ko": "그룹 1, 그룹 2, 그룹 3", "nl": "Groep1, Groep2, Groep3", "pt": "Grupo1, Grupo2, Grupo3", "ru": "Группа1, Группа2, Группа3", + "zh-chs": "組1,組2,組3", "xloc": [ - "default-mobile.handlebars->9->226" + "default-mobile.handlebars->9->230" ] }, { @@ -8025,10 +11124,16 @@ "de": "Gruppen", "en": "Groups", "es": "Grupos", + "fr": "Groupes", + "hi": "समूह", + "ja": "グループ", + "ko": "여러 떼", "nl": "Groepen", + "pt": "Grupos", "ru": "Группы", + "zh-chs": "團體", "xloc": [ - "default.handlebars->25->1204", + "default.handlebars->27->1334", "default.handlebars->container->topbar->1->1->UsersSubMenuSpan->UsersSubMenu->1->0->UsersGroups" ] }, @@ -8037,12 +11142,15 @@ "de": "Gujurati", "en": "Gujurati", "fr": "Gujarati", + "hi": "Gujurati", "ja": "グジュラティ", + "ko": "구주 라티", "nl": "Gujurati", "pt": "Gujarati", "ru": "Гуджарати", + "zh-chs": "古久拉提", "xloc": [ - "default.handlebars->25->808" + "default.handlebars->27->912" ] }, { @@ -8051,10 +11159,13 @@ "en": "HW Connect", "es": "Conectarse al HW", "fr": "Connexion AMT", + "hi": "एचडब्ल्यू कनेक्ट", "ja": "HW Connect", + "ko": "HW Connect", "nl": "HW verbinden", "pt": "Conectar HW", "ru": "Аппаратное соединение", + "zh-chs": "硬件連接", "xloc": [ "default-mobile.handlebars->container->page_content->column_l->p10->p10desktop->deskarea1->1->3", "default.handlebars->container->column_l->p11->deskarea0->deskarea1->3->connectbutton1hspan", @@ -8066,12 +11177,15 @@ "de": "Haitianisch", "en": "Haitian", "fr": "Haïtien", + "hi": "हाईटियन", "ja": "ハイチ語", + "ko": "아이티 섬 사람", "nl": "Haïtiaanse", "pt": "Haitiano", "ru": "Гаитянский", + "zh-chs": "海地", "xloc": [ - "default.handlebars->25->809" + "default.handlebars->27->913" ] }, { @@ -8080,10 +11194,13 @@ "en": "Hang up", "es": "Colgar", "fr": "Raccrocher", + "hi": "फोन रख देना", "ja": "電話を切る", + "ko": "끊다", "nl": "Vastlopen", "pt": "Desligar", "ru": "Прервать", + "zh-chs": "掛斷", "xloc": [ "messenger.handlebars->xtop->1" ] @@ -8094,12 +11211,15 @@ "en": "Hard disconnect agent", "es": "Agente (Desconexión dura)", "fr": "Déconnexion forcée de l'agent", + "hi": "हार्ड डिस्कनेक्ट एजेंट", "ja": "ハード切断エージェント", + "ko": "하드 분리 에이전트", "nl": "Harde ontkoppeling agent", "pt": "Forçar desconexão do agente", "ru": "Жесткое отключение агента", + "zh-chs": "硬斷開劑", "xloc": [ - "default.handlebars->25->706" + "default.handlebars->27->807" ] }, { @@ -8107,9 +11227,16 @@ "de": "Heap gesamt", "en": "Heap Total", "es": "Heap Total", + "fr": "Total de tas", + "hi": "हीप टोटल", + "ja": "ヒープ合計", + "ko": "힙 총계", "nl": "Heap Totaal", + "pt": "Total da pilha", + "ru": "Всего кучи", + "zh-chs": "堆總數", "xloc": [ - "default.handlebars->25->1435" + "default.handlebars->27->1582" ] }, { @@ -8117,9 +11244,16 @@ "de": "Heap verwendet", "en": "Heap Used", "es": "Heap Used", + "fr": "Tas utilisé", + "hi": "हीप का इस्तेमाल किया", + "ja": "使用ヒープ", + "ko": "사용 된 힙", "nl": "Heap gebruikt", + "pt": "Pilha usada", + "ru": "Куча используется", + "zh-chs": "堆使用", "xloc": [ - "default.handlebars->25->1434" + "default.handlebars->27->1581" ] }, { @@ -8127,12 +11261,30 @@ "de": "Hebräisch", "en": "Hebrew", "es": "Hebreo", + "fr": "Hébreu", + "hi": "यहूदी", "ja": "ヘブライ語", + "ko": "헤브라이 사람", "nl": "Hebreeuws", "pt": "Hebraico", "ru": "Иврит", + "zh-chs": "希伯來語", "xloc": [ - "default.handlebars->25->810" + "default.handlebars->27->914" + ] + }, + { + "cs": "Dobrý den, [[[NAME]]],", + "de": "Hallo [[[NAME]]],", + "en": "Hello [[[NAME]]],", + "fr": "Bonjour [[[NAME]]],", + "nl": "Hallo [[[NAME]]],", + "ja": "[[[NAME]]]様", + "ru": "Здравствуйте, [[[NAME]]],", + "zh-chs": "您好[[[NAME]]],", + "xloc": [ + "mesh-invite.html->2->3->1", + "mesh-invite.txt" ] }, { @@ -8140,11 +11292,56 @@ "de": "Hilf bei der Übersetzung von MeshCentral", "en": "Help translate MeshCentral", "es": "Ayuda traducir MeshCentral", + "fr": "Traduire MeshCentral", + "hi": "मदद", "ja": "MeshCentralの翻訳を支援", + "ko": "MeshCentral 번역을 도와주세요", "nl": "Help bij het vertalen van MeshCentral", + "pt": "Ajude a traduzir o MeshCentral", "ru": "Помочь перевести MeshCentral", + "zh-chs": "幫助翻譯MeshCentral", "xloc": [ - "default.handlebars->25->923" + "default.handlebars->27->1028" + ] + }, + { + "cs": "Ahoj [[[USERNAME]]],", + "de": "Hallo [[[USERNAME]]],", + "en": "Hi [[[USERNAME]]],", + "fr": "Bonjour [[[USERNAME]]],", + "nl": "Hallo [[[USERNAME]]],", + "ja": "[[[USERNAME]]]様", + "ru": "Привет [[[USERNAME]]],", + "zh-chs": "[[[USERNAME]],你好,", + "xloc": [ + "account-check.html->2->3", + "account-reset.html->2->3" + ] + }, + { + "cs": "Ahoj [[[USERNAME]]], [[[SERVERNAME]]] ([[[SERVERURL]]]) provádí ověření e-mailem. Chcete-li proces dokončit, přejděte na následující odkaz:", + "de": "Hallo [[[USERNAME]]], [[[SERVERNAME]]] ([[[SERVERURL]]]) führt eine E-Mail-Überprüfung durch. Klicken Sie auf den folgenden Link, um den Vorgang abzuschließen:", + "en": "Hi [[[USERNAME]]], [[[SERVERNAME]]] ([[[SERVERURL]]]) is performing an e-mail verification. Nagivate to the following link to complete the process:", + "nl": "Hallo [[[USERNAME]]], [[[SERVERNAME]]] ([[[SERVERURL]]]) voert een e-mailverificatie uit. Ga naar de volgende link om het proces te voltooien:", + "fr": "Bonjour [[[USERNAME]]], [[[SERVERNAME]]] ([[[SERVERURL]]]) effectue une vérification par e-mail. Accédez au lien suivant pour terminer le processus:", + "ja": "こんにちは[[[USERNAME]]]、[[[SERVERNAME]]]([[[SERVERURL]]])は電子メールの検証を実行しています。プロセスを完了するには、次のリンクに移動します。", + "ru": "Здравствуйте, [[[USERNAME]]], [[[SERVERNAME]]] ([[[SERVERURL]]]) выполняет проверку электронной почты. Для завершения процесса перейдите по следующей ссылке:", + "zh-chs": "嗨[[[USERNAME]]],[[[SERVERNAME]]]([[[SERVERURL]]])正在执行电子邮件验证。导航至以下链接以完成该过程:", + "xloc": [ + "account-check.txt" + ] + }, + { + "cs": "Ahoj [[[USERNAME]]], [[[SERVERNAME]]] ([[[SERVERURL]]])) požaduje obnovení hesla k účtu. Chcete-li proces dokončit, přejděte na následující odkaz:", + "de": "Hallo [[[USERNAME]]], [[[SERVERNAME]]] ([[[SERVERURL]]]) fordert ein Zurücksetzen des Kontokennworts an. Klicken Sie auf den folgenden Link, um den Vorgang abzuschließen:", + "en": "Hi [[[USERNAME]]], [[[SERVERNAME]]] ([[[SERVERURL]]]) is requesting an account password reset. Nagivate to the following link to complete the process:", + "nl": "Hallo [[[USERNAME]]], [[[SERVERNAME]]] ([[[SERVERURL]]]) vraagt om het opnieuw instellen van het account wachtwoord. Ga naar de volgende link om het proces te voltooien:", + "fr": "Bonjour [[[USERNAME]]], [[[SERVERNAME]]] ([[[SERVERURL]]]) demande une réinitialisation du mot de passe du compte. Accédez au lien suivant pour terminer le processus:", + "ja": "こんにちは[[[USERNAME]]]、[[[SERVERNAME]]]([[[SERVERURL]]])はアカウントパスワードのリセットをリクエストしています。プロセスを完了するには、次のリンクに移動します。", + "ru": "Здравствуйте, [[[USERNAME]]], [[[SERVERNAME]]] ([[[SERVERURL]]]) запрашивает сброс пароля учетной записи. Для завершения процесса перейдите по следующей ссылке:", + "zh-chs": "[[[USERNAME]],您好:[[[SERVERNAME]]]([[[SERVERURL]]])正在请求重置帐户密码。导航至以下链接以完成该过程:", + "xloc": [ + "account-reset.txt" ] }, { @@ -8152,16 +11349,19 @@ "de": "Ruhezustand", "en": "Hibernating", "es": "Hibernando", - "fr": "Hibernation", + "fr": "Veille prolongée", + "hi": "सुप्तावस्था", "ja": "冬眠", + "ko": "겨울잠", "nl": "Slaapstand", "pt": "Hibernando", "ru": "Гибернация", + "zh-chs": "冬眠", "xloc": [ - "default-mobile.handlebars->9->104", - "default-mobile.handlebars->9->111", - "default.handlebars->25->358", - "default.handlebars->25->5" + "default-mobile.handlebars->9->108", + "default-mobile.handlebars->9->115", + "default.handlebars->27->348", + "default.handlebars->27->5" ] }, { @@ -8169,12 +11369,16 @@ "de": "Hindi", "en": "Hindi", "es": "Hindi", + "fr": "hindi", + "hi": "हिंदी", "ja": "ヒンディー語", + "ko": "힌디 어", "nl": "Hindi", "pt": "Hindi", "ru": "Хинди", + "zh-chs": "印地語", "xloc": [ - "default.handlebars->25->811" + "default.handlebars->27->915" ] }, { @@ -8183,9 +11387,13 @@ "en": "Hold on, reset mail sent.", "es": "Espera, restablece el correo enviado.", "fr": "Attends, le courrier est envoyé.", + "hi": "भेजे गए मेल को रीसेट करें, दबाए रखें।", "ja": "お待ちください、送信されたメールをリセットします。", + "ko": "잠시만 기다려주세요.", "nl": "even wachten, reset e-mail verzonden.", + "pt": "Aguarde, redefina o email enviado.", "ru": "Подождите, письмо для сброса отправлено.", + "zh-chs": "稍等,重置已發送的郵件。", "xloc": [ "login-mobile.handlebars->5->1", "login.handlebars->5->1" @@ -8196,13 +11404,17 @@ "de": "Halte 1 Eintrag zum Kopieren", "en": "Holding 1 entrie for copy", "es": "Sosteniendo 1 entrada para copia", + "fr": "Tenir 1 entrée pour copie", + "hi": "नकल के लिए 1 एंट्री पकड़ना", "ja": "コピー用に1つのエントリを保持", + "ko": "사본 1 개 보유", "nl": "1 item vasthouden voor kopiëren", "pt": "Mantendo 1 entrada para cópia", "ru": "Задержана 1 запись для копирования", + "zh-chs": "持有1份副本", "xloc": [ - "default-mobile.handlebars->9->263", - "default.handlebars->25->671" + "default-mobile.handlebars->9->267", + "default.handlebars->27->720" ] }, { @@ -8210,13 +11422,17 @@ "de": "Halte 1 Eintrag zum Verschieben", "en": "Holding 1 entrie for move", "es": "Sosteniendo 1 entrada para mover", + "fr": "Tenir 1 entrée pour se déplacer", + "hi": "मूव के लिए 1 एंट्री पकड़ना", "ja": "移動のために1つのエントリを保持", + "ko": "이사 1 엔트리 개최", "nl": "1 item vasthouden voor verplaatsen", "pt": "Segurando 1 entrada para mover", "ru": "Задержана 1 запись для перемещения", + "zh-chs": "持有1個搬家公司", "xloc": [ - "default-mobile.handlebars->9->267", - "default.handlebars->25->675" + "default-mobile.handlebars->9->271", + "default.handlebars->27->724" ] }, { @@ -8224,13 +11440,17 @@ "de": "Halte {0} Einträge zum Kopieren", "en": "Holding {0} entries for copy", "es": "Manteniendo {0} entradas para copiar", + "fr": "Conservation de {0} entrées pour la copie", + "hi": "कॉपी के लिए {0} प्रविष्टियाँ रखना", "ja": "コピー用に{0}エントリを保持しています", + "ko": "복사 할 {0} 항목 보유", "nl": "{0} items vasthouden voor kopiëren", "pt": "Mantendo {0} entradas para cópia", "ru": "Задержано {0} записей для копирования", + "zh-chs": "保留{0}個條目進行複制", "xloc": [ - "default-mobile.handlebars->9->261", - "default.handlebars->25->669" + "default-mobile.handlebars->9->265", + "default.handlebars->27->718" ] }, { @@ -8238,13 +11458,17 @@ "de": "Halte {0} Einträge zum Verschieben", "en": "Holding {0} entries for move", "es": "Manteniendo {0} entradas para mover", + "fr": "Conservation de {0} entrées pour le déplacement", + "hi": "चाल के लिए {0} प्रविष्टियाँ रखना", "ja": "移動のために{0}エントリを保持しています", + "ko": "이동할 {0} 항목 보유", "nl": "{0} items vasthouden voor verplaatsen", "pt": "Manter {0} entradas para mover", "ru": "Задержано {0} записей для перемещения", + "zh-chs": "保留{0}個條目以進行移動", "xloc": [ - "default-mobile.handlebars->9->265", - "default.handlebars->25->673" + "default-mobile.handlebars->9->269", + "default.handlebars->27->722" ] }, { @@ -8252,13 +11476,17 @@ "de": "Halte {0} Einträge{1} zum {2}", "en": "Holding {0} entrie{1} for {2}", "es": "Manteniendo {0} entrada {1} para {2}", + "fr": "Tenir {0} entrée {1} pour {2}", + "hi": "{2} के लिए {0} entrie {1} पकड़े", "ja": "{2}の{0}エントリを保持しています{1}", + "ko": "{2}에 대해 {0} 항목 {1}을 (를) 보유", "nl": "Houd {0} item {1} vast voor {2}", "pt": "Mantendo {0} entrada {1} para {2}", "ru": "Задержано {0} записей для {2}", + "zh-chs": "保持{2}的{0}入口{1}", "xloc": [ - "default-mobile.handlebars->9->88", - "default.handlebars->25->1186" + "default-mobile.handlebars->9->91", + "default.handlebars->27->1316" ] }, { @@ -8266,20 +11494,24 @@ "de": "Hostname", "en": "Hostname", "es": "Nombre de host", + "fr": "Nom d'hôte", + "hi": "होस्ट का नाम", "ja": "ホスト名", + "ko": "호스트 이름", "nl": "Hostnaam", "pt": "Hostname", "ru": "Имя хоста", + "zh-chs": "主機名", "xloc": [ - "default-mobile.handlebars->9->136", - "default-mobile.handlebars->9->137", - "default-mobile.handlebars->9->139", - "default-mobile.handlebars->9->223", - "default.handlebars->25->239", - "default.handlebars->25->445", - "default.handlebars->25->446", - "default.handlebars->25->448", - "default.handlebars->25->600" + "default-mobile.handlebars->9->140", + "default-mobile.handlebars->9->141", + "default-mobile.handlebars->9->143", + "default-mobile.handlebars->9->227", + "default.handlebars->27->223", + "default.handlebars->27->452", + "default.handlebars->27->453", + "default.handlebars->27->455", + "default.handlebars->27->648" ] }, { @@ -8287,24 +11519,32 @@ "de": "Hostname synchronisieren", "en": "Hostname Sync", "es": "Syncronizar Nombre de host", + "fr": "Synchroniser le nom d'hôte", + "hi": "होस्टनाम सिंक", "ja": "ホスト名の同期", + "ko": "호스트 이름 동기화", "nl": "Hostnaam Sync", "pt": "Sincronização de nome de host", "ru": "Синхронизация имени хоста", + "zh-chs": "主機名同步", "xloc": [ - "default.handlebars->25->987" + "default.handlebars->27->1092" ] }, { "cs": "maďarština", "de": "Ungarisch", "en": "Hungarian", + "fr": "Hongrois", + "hi": "हंगेरी", "ja": "ハンガリー語", + "ko": "헝가리 인", "nl": "Hongaars", "pt": "Húngaro", "ru": "Венгерский", + "zh-chs": "匈牙利", "xloc": [ - "default.handlebars->25->812" + "default.handlebars->27->916" ] }, { @@ -8312,12 +11552,16 @@ "de": "IP-Bereich", "en": "IP Range", "es": "Rango de IP", + "fr": "Plage IP", + "hi": "आईपी ​​रेंज", "ja": "IP範囲", + "ko": "IP 범위", "nl": "IP-bereik", "pt": "IP Range", "ru": "Диапазон IP", + "zh-chs": "IP範圍", "xloc": [ - "default.handlebars->25->254" + "default.handlebars->27->238" ] }, { @@ -8325,12 +11569,67 @@ "de": "IP-Adresse gesperrt, versuchen Sie es später erneut.", "en": "IP address blocked, try again later.", "es": "Dirección IP bloqueada, intente nuevamente más tarde.", + "fr": "Adresse IP bloquée, réessayez plus tard.", + "hi": "IP पता अवरुद्ध, बाद में पुन: प्रयास करें।", "ja": "IPアドレスがブロックされています。しばらくしてからもう一度お試しください。", + "ko": "IP 주소가 차단되었습니다. 나중에 다시 시도하십시오.", "nl": "IP-adres geblokkeerd, probeer het later opnieuw.", + "pt": "Endereço IP bloqueado, tente novamente mais tarde.", "ru": "IP адрес заблокирован, повторите попытку позже.", + "zh-chs": "IP位址已封鎖,請稍後再試。", "xloc": [ - "login-mobile.handlebars->5->16", - "login.handlebars->5->16" + "login-mobile.handlebars->5->17", + "login.handlebars->5->17" + ] + }, + { + "cs": "IP: {0}", + "de": "IP: {0}", + "en": "IP: {0}", + "es": "IP: {0}", + "fr": "IP: {0}", + "hi": "आईपी: {0}", + "ja": "IP:{0}", + "ko": "IP : {0}", + "nl": "IP: {0}", + "pt": "IP: {0}", + "ru": "IP: {0}", + "zh-chs": "IP:{0}", + "xloc": [ + "default.handlebars->27->760" + ] + }, + { + "cs": "IP: {0}, Maska: {1}, Brána: {2}", + "de": "IP: {0}, Maske: {1}, Gateway: {2}", + "en": "IP: {0}, Mask: {1}, Gateway: {2}", + "fr": "IP: {0}, masque: {1}, passerelle: {2}", + "hi": "IP: {0}, मास्क: {1}, गेटवे: {2}", + "ja": "IP:{0}、マスク:{1}、ゲートウェイ:{2}", + "ko": "IP : {0}, 마스크 : {1}, 게이트웨이 : {2}", + "nl": "IP: {0}, Mask: {1}, Gateway: {2}", + "pt": "IP: {0}, Máscara: {1}, Gateway: {2}", + "ru": "IP: {0}, маска: {1}, шлюз: {2}", + "zh-chs": "IP:{0},掩碼:{1},網關:{2}", + "xloc": [ + "default.handlebars->27->758" + ] + }, + { + "cs": "Vrstva IPv4", + "de": "IPv4-Schicht", + "en": "IPv4 Layer", + "fr": "Couche IPv4", + "hi": "IPv4 लेयर", + "ja": "IPv4レイヤー", + "ko": "IPv4 레이어", + "nl": "IPv4 Laag", + "pt": "Camada IPv4", + "ru": "Уровень IPv4", + "zh-chs": "IPv4層", + "xloc": [ + "default.handlebars->27->757", + "default.handlebars->27->759" ] }, { @@ -8338,12 +11637,16 @@ "de": "IPv4-Adresse", "en": "IPv4 address", "es": "Dirección IPv4", + "fr": "Adresse IPv4", + "hi": "IPv4 पता", "ja": "IPv4アドレス", + "ko": "IPv4 주소", "nl": "IPv4 adres", "pt": "Endereço IPv4", "ru": "IPv4 адрес", + "zh-chs": "IPv4地址", "xloc": [ - "default.handlebars->25->100" + "default.handlebars->27->83" ] }, { @@ -8351,12 +11654,16 @@ "de": "IPv4-Gateway", "en": "IPv4 gateway", "es": "Puerta de enlace IPv4", + "fr": "Passerelle IPv4", + "hi": "IPv4 गेटवे", "ja": "IPv4ゲートウェイ", + "ko": "IPv4 게이트웨이", "nl": "IPv4 gateway", "pt": "Gateway IPv4", "ru": "IPv4 шлюз", + "zh-chs": "IPv4網關", "xloc": [ - "default.handlebars->25->104" + "default.handlebars->27->87" ] }, { @@ -8364,12 +11671,16 @@ "de": "IPv4-Netzmaske", "en": "IPv4 mask", "es": "Mascara IPv4", + "fr": "MAsque IPv4", + "hi": "IPv4 मास्क", "ja": "IPv4マスク", + "ko": "IPv4 마스크", "nl": "IPv4 mask", "pt": "Máscara IPv4", "ru": "IPv4 маска", + "zh-chs": "IPv4掩碼", "xloc": [ - "default.handlebars->25->102" + "default.handlebars->27->85" ] }, { @@ -8377,12 +11688,15 @@ "de": "Isländisch", "en": "Icelandic", "fr": "Islandais", + "hi": "आइसलैंड का", "ja": "アイスランド語", + "ko": "아이슬란드 어", "nl": "IJslands", "pt": "islandês", "ru": "Исландский", + "zh-chs": "冰島的", "xloc": [ - "default.handlebars->25->813" + "default.handlebars->27->917" ] }, { @@ -8391,13 +11705,16 @@ "en": "Icon Selection", "es": "Seleccion de Icono", "fr": "Sélection de l'icôn", + "hi": "आइकन चयन", "ja": "アイコンの選択", + "ko": "아이콘 선택", "nl": "Pictogram selectie", "pt": "Seleção de ícone", "ru": "Выбор иконки", + "zh-chs": "圖標選擇", "xloc": [ - "default-mobile.handlebars->9->221", - "default.handlebars->25->598" + "default-mobile.handlebars->9->225", + "default.handlebars->27->646" ] }, { @@ -8406,37 +11723,109 @@ "en": "Identifier", "es": "Identificador", "fr": "Identifiant", + "hi": "पहचानकर्ता", "ja": "識別子", + "ko": "식별자", "nl": "Identifier", "pt": "Identificador", "ru": "Идентификатор", + "zh-chs": "識別碼", "xloc": [ - "default.handlebars->25->74" + "default.handlebars->27->785" ] }, + { + "cs": "Pokud jste tento požadavek nezačali, ignorujte tento e-mail.", + "de": "Wenn Sie diese Anfrage nicht initiiert haben, ignorieren Sie diese Mail bitte.", + "en": "If you did not initiate this request, please ignore this mail.", + "fr": "Si vous n'avez pas initié cette demande, veuillez ignorer ce courrier.", + "nl": "Als u dit verzoek niet heeft ingediend, dan kunt u deze e-mail negeren.", + "ja": "このリクエストを開始していない場合は、このメールを無視してください。", + "ru": "Если вы не инициировали этот запрос, игнорируйте это письмо.", + "zh-chs": "如果您没有发起此请求,请忽略此邮件。", + "xloc": [ + "account-check.html->2", + "account-check.txt", + "account-reset.html->2", + "account-reset.txt", + "mesh-invite.html->2->17", + "mesh-invite.txt" + ] + }, + { + "cs": "Neplatné vyvolání", + "de": "Illegaler Aufruf", + "en": "Illegal invocation", + "fr": "Invocation illégale", + "hi": "अवैध मंगलाचरण", + "ja": "不正な呼び出し", + "ko": "잘못된 호출", + "nl": "Ongeldige aanroep", + "pt": "Invocação ilegal", + "ru": "Незаконное обращение", + "zh-chs": "非法調用" + }, { "cs": "Kódovaní obrazu", "de": "Bildkodierung", "en": "Image Encoding", "es": "Codificación de imagen", + "fr": "Encodage de l'image", + "hi": "छवि एनकोडिंग", "ja": "画像エンコーディング", + "ko": "이미지 인코딩", "nl": "Beeldcodering", "pt": "Codificação de Imagem", "ru": "Кодировка изображения", + "zh-chs": "圖像編碼", "xloc": [ "default.handlebars->container->dialog->dialogBody->dialog7->d7amtkvm->3->1" ] }, + { + "cs": "Indexováno každých {0} sekund", + "de": "Indiziert alle {0} Sekunden", + "en": "Indexed every {0} seconds", + "fr": "Indexé toutes les {0} seconde(s)", + "hi": "प्रत्येक {0} सेकंड अनुक्रमित", + "ja": "{0}秒ごとにインデックス付けされます", + "ko": "{0} 초마다 색인 생성", + "nl": "Geïndexeerd om de {0} seconden", + "pt": "Indexado a cada {0} segundos", + "ru": "Индексируется каждые {0} секунд", + "zh-chs": "每{0}秒索引一次", + "xloc": [ + "player.handlebars->3->17" + ] + }, + { + "cs": "Jednotlivá zařízení", + "de": "Einzelne Geräte", + "en": "Individual Devices", + "fr": "Appareils individuels", + "ja": "個々のデバイス", + "nl": "Individuele apparaten", + "ru": "Индивидуальные устройства", + "zh-chs": "个别装置", + "xloc": [ + "default-mobile.handlebars->9->96", + "default.handlebars->27->164" + ] + }, { "cs": "indonézština", "de": "Indonesisch", "en": "Indonesian", + "fr": "Indonésien", + "hi": "इन्डोनेशियाई", "ja": "インドネシア人", + "ko": "인도네시아 인", "nl": "Indonesisch", "pt": "Indonésia", "ru": "Индонезийский", + "zh-chs": "印度尼西亞", "xloc": [ - "default.handlebars->25->814" + "default.handlebars->27->918" ] }, { @@ -8445,10 +11834,13 @@ "en": "Information", "es": "Información", "fr": "Information", + "hi": "जानकारी", "ja": "情報", + "ko": "정보", "nl": "Informatie", "pt": "Informação", "ru": "Информация", + "zh-chs": "信息", "xloc": [ "default.handlebars->contextMenu->cxinfo->0" ] @@ -8459,10 +11851,13 @@ "en": "Information about current core running on this agent", "es": "Información sobre el núcleo actual que se ejecuta en este agente", "fr": "Informations sur le noyau en cours d'exécution sur cet agent", + "hi": "इस एजेंट पर चल रहे वर्तमान कोर के बारे में जानकारी", "ja": "このエージェントで実行されている現在のコアに関する情報", + "ko": "이 에이전트에서 실행중인 현재 코어에 대한 정보", "nl": "Informatie over de huidige kern die op deze agent wordt uitgevoerd", "pt": "Informações sobre o núcleo atual em execução neste agente", "ru": "Информация о текущем ядре, работающем на этом агенте", + "zh-chs": "有關在此代理上運行的當前核心的信息", "xloc": [ "default.handlebars->container->column_l->p15->consoleTable->1->0->1->1" ] @@ -8472,10 +11867,14 @@ "de": "Eingabe", "en": "Input", "es": "Entrada", + "fr": "Entrée", + "hi": "इनपुट", "ja": "入力", + "ko": "입력", "nl": "Invoer", "pt": "Entrada", "ru": "Ввод", + "zh-chs": "輸入值", "xloc": [ "default-mobile.handlebars->container->page_content->column_l->p10->p10desktop->deskarea4->1->3->11->DeskControlSpan", "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->9->DeskControlSpan" @@ -8487,24 +11886,31 @@ "en": "Install", "es": "Instalar", "fr": "Installer", + "hi": "इंस्टॉल", "ja": "インストール", + "ko": "설치", "nl": "Installeren", "pt": "Instalar", "ru": "Установка", + "zh-chs": "安裝", "xloc": [ - "default.handlebars->25->1026" + "default.handlebars->27->1133" ] }, { "cs": "Nainstalujte si Google Authenticator nebo kompatibilní aplikaci a naskenujte kód, použijte tento odkaz nebo vložte tajemství. Pak vložte aktuální 6 číselný token pro aktivaci 2-faktorového přihlašování.", "de": "Installiere Google Authenticator oder eine kompatible Applikation und scanne den Barcode, verwende diesen Link oder gebe das Geheimnis manuell unten ein. Anschließend gebe den aktuellen 6-stelligen Token nachfolgend ein, um die Zweifaktor-Anmeldung zu aktivieren.", "en": "Install Google Authenticator or a compatible application and scan the barcode, use this link or enter the secret. Then, enter the current 6 digit token below to activate 2-Step login.", - "es": "Instale Google Authenticator o una aplicación compatible y escanee el código de barras, use este enlace o ingrese el secreto. Luego, ingrese el token actual de 6 dígitos a continuación para activar el inicio de sesión en 2 pasos.", + "es": "Instale Google Authenticator o una aplicación compatible y escanee el código de barras, use este enlace o ingrese el secreto. Luego, ingrese el token actual de 6 dígitos a continuación para activar el inicio de sesión en 2 pasos.", + "fr": "Installez Google Authenticator ou une application compatible et scannez le code-barres, utilisez ce lien ou entrez le secret. Ensuite, entrez le jeton actuel à 6 chiffres ci-dessous pour activer la connexion en 2 étapes.", "ja": "インストールGoogle Authenticatorまたは互換性のあるアプリケーションでバーコードをスキャンするには、このリンクを使用するか、秘密。次に、現在の6桁のトークンを入力して、2段階ログインを有効にします。", + "ko": " Google 인증 기 설치 또는 호환되는 응용 프로그램에서 바코드를 스캔하려면 이 링크 를 사용하거나 비밀을 입력하십시오. 그런 다음 아래에 현재 6 자리 토큰을 입력하여 2 단계 로그인을 활성화하십시오.", "nl": "Installeer Google Authenticator of een compatibele applicatie en scan de streepjescode, gebruik deze link of voer de link in geheim. Voer vervolgens het huidige 6-cijferige token hieronder in om 2-staps aanmelding te activeren.", + "pt": "Instale o Google Authenticator ou um aplicativo compatível e digitalize o código de barras, use esse link ou digite o segredo. Em seguida, insira o token atual de 6 dígitos abaixo para ativar o login em duas etapas.", "ru": "Установите Google Authenticator или совместимое приложение и отсканируйте штрих-код, используйте эту ссылку или введите код. Затем введите ниже текущий токен из 6 цифр для активации двухшаговой авторизации.", + "zh-chs": "安裝 Google身份驗證器或兼容的應用程序並掃描條形碼,使用此鏈接或輸入密碼。然後,在下面輸入當前的6位數令牌以激活兩步登錄。", "xloc": [ - "default.handlebars->25->120" + "default.handlebars->27->103" ] }, { @@ -8512,9 +11918,13 @@ "de": "Installiere Google Authenticator oder eine kompatible Applikation und verwende diesen Link oder gebe das Geheimnis manuell unten ein. Anschließend gebe den aktuellen 6-stelligen Token nachfolgend ein, um die Zweifaktor-Anmeldung zu aktivieren.", "en": "Install Google Authenticator or a compatible application, use this link or enter the secret below. Then, enter the current 6 digit token to activate 2-Step login.", "es": "Instale Google Authenticator o una aplicación compatible, use este enlace o ingrese el secreto a continuación. Luego, ingrese el token actual de 6 dígitos para activar el inicio de sesión en 2 pasos.", + "fr": "Installez Google Authenticator ou une application compatible, utilisez ce lien ou entrez le secret ci-dessous. Ensuite, entrez le jeton actuel à 6 chiffres pour activer la connexion en 2 étapes.", "ja": "インストール Google Authenticator または互換性のあるアプリケーションの場合、このリンクを使用するか、下に秘密を入力します。次に、現在の6桁のトークンを入力して、2段階ログインを有効にします。", + "ko": " Google 인증 기 설치 또는 호환되는 응용 프로그램을 사용하려면 이 링크 를 사용하거나 아래의 비밀을 입력하십시오. 그런 다음 현재 6 자리 토큰을 입력하여 2 단계 로그인을 활성화하십시오.", "nl": "Installeer Google Authenticator of een compatibele toepassing, gebruik deze link of voer hieronder het geheim in. Voer vervolgens het huidige 6-cijferige token in om 2-staps aanmelding te activeren.", + "pt": "Instale o Google Authenticator ou um aplicativo compatível, use este link ou digite o segredo abaixo. Em seguida, insira o token atual de 6 dígitos para ativar o login em duas etapas.", "ru": "Установите Google Authenticator или совместимое приложение, используйте эту ссылку или введите код ниже. Затем введите ниже текущий токен из 6 цифр для активации двухшаговой авторизации.", + "zh-chs": "安裝 Google身份驗證器或兼容的應用程序,請使用此鏈接或在下面輸入密碼。然後,輸入當前的6位數令牌以激活兩步登錄。", "xloc": [ "default-mobile.handlebars->9->17" ] @@ -8525,12 +11935,15 @@ "en": "Install CIRA", "es": "Instalar CIRA", "fr": "Installer CIRA", + "hi": "CIRA स्थापित करें", "ja": "CIRAをインストールする", + "ko": "CIRA 설치", "nl": "Installeer CIRA", "pt": "Instalar CIRA", "ru": "Установка CIRA", + "zh-chs": "安裝CIRA", "xloc": [ - "default.handlebars->25->1018" + "default.handlebars->27->1125" ] }, { @@ -8538,12 +11951,16 @@ "de": "Lokal installieren", "en": "Install local", "es": "Instalar local", + "fr": "Installation locale", + "hi": "स्थानीय स्थापित करें", "ja": "ローカルにインストール", + "ko": "로컬 설치", "nl": "Installeer lokaal", "pt": "Instalação local", "ru": "Локальная установка", + "zh-chs": "安裝本地", "xloc": [ - "default.handlebars->25->1020" + "default.handlebars->27->1127" ] }, { @@ -8551,13 +11968,19 @@ "de": "Installationstyp", "en": "Installation Type", "es": "Tipo de instalación", + "fr": "Type d'installation", + "hi": "स्थापना प्रकार", "ja": "設置タイプ", + "ko": "설치 유형", "nl": "Installatie type", "pt": "Tipo de instalação ", "ru": "Тип установки", + "zh-chs": "安裝類型", "xloc": [ - "default.handlebars->25->298", - "default.handlebars->25->320" + "default.handlebars->27->1255", + "default.handlebars->27->1262", + "default.handlebars->27->285", + "default.handlebars->27->307" ] }, { @@ -8565,12 +11988,16 @@ "de": "Intel (F10 = ESC+[OM)", "en": "Intel (F10 = ESC+[OM)", "es": "Intel (F10 = ESC+[OM)", - "ja": "Intel(F10 = ESC + [OM)", + "fr": "Intel (F10 = ESC + [OM)", + "hi": "इंटेल (F10 = ESC + [OM)", + "ja": "Intel(F10 = ESC+[OM)", + "ko": "인텔 (F10 = ESC + [OM)", "nl": "Intel (F10 = ESC+[OM)", "pt": "Intel (F10 = ESC+[OM)", "ru": "Intel (F10 = ESC+[OM)", + "zh-chs": "英特爾(F10 = ESC + [OM)", "xloc": [ - "default.handlebars->25->641", + "default.handlebars->27->690", "default.handlebars->container->column_l->p12->termTable->1->1->6->1->1->terminalSettingsButtons" ] }, @@ -8579,15 +12006,19 @@ "de": "Intel AMT", "en": "Intel AMT", "es": "Intel AMT", + "fr": "Intel AMT", + "hi": "इंटेल एएमटी", "ja": "Intel AMT", + "ko": "인텔 AMT", "nl": "Intel AMT", "pt": "Intel AMT", "ru": "Intel AMT", + "zh-chs": "英特爾AMT", "xloc": [ - "default.handlebars->25->1146", - "default.handlebars->25->1152", - "default.handlebars->25->1431", - "default.handlebars->25->1451" + "default.handlebars->27->1274", + "default.handlebars->27->1280", + "default.handlebars->27->1578", + "default.handlebars->27->1600" ] }, { @@ -8595,12 +12026,16 @@ "de": "Intel AMT CIRA verbunden", "en": "Intel AMT CIRA connected", "es": "Intel AMT CIRA conectado", + "fr": "Intel AMT CIRA connecté", + "hi": "इंटेल AMT CIRA जुड़ा हुआ है", "ja": "Intel AMT CIRAが接続されました", + "ko": "Intel AMT CIRA 연결", "nl": "Intel AMT CIRA verbonden", "pt": "Intel AMT CIRA conectado", "ru": "Подключен Intel AMT CIRA", + "zh-chs": "英特爾AMT CIRA已連接", "xloc": [ - "default.handlebars->25->156" + "default.handlebars->27->139" ] }, { @@ -8608,12 +12043,16 @@ "de": "Intel AMT CIRA getrennt", "en": "Intel AMT CIRA disconnected", "es": "Intel AMT CIRA desconectado", + "fr": "Intel AMT CIRA déconnecté", + "hi": "इंटेल AMT CIRA डिस्कनेक्ट हो गया", "ja": "Intel AMT CIRAが切断されました", + "ko": "Intel AMT CIRA 연결이 끊어졌습니다", "nl": "Intel AMT CIRA verbroken", "pt": "Intel AMT CIRA desconectado", "ru": "Отключен Intel AMT CIRA", + "zh-chs": "英特爾AMT CIRA斷開連接", "xloc": [ - "default.handlebars->25->160" + "default.handlebars->27->143" ] }, { @@ -8622,12 +12061,15 @@ "en": "Intel AMT detected", "es": "Intel AMT detectado", "fr": "Intel AMT détecté", + "hi": "इंटेल एएमटी का पता चला", "ja": "Intel AMTが検出されました", + "ko": "인텔 AMT 감지", "nl": "Intel AMT gedetecteerd", "pt": "Intel AMT detectado", "ru": "Обнаружен Intel AMT", + "zh-chs": "檢測到英特爾AMT", "xloc": [ - "default.handlebars->25->155" + "default.handlebars->27->138" ] }, { @@ -8635,12 +12077,16 @@ "de": "Intel AMT ist im Admin Control Mode aktiviert", "en": "Intel AMT is activated in Admin Control Mode", "es": "Intel AMT esta activado en Admin Control Mode (ACM)", + "fr": "Intel AMT est activé en mode administrateur", + "hi": "इंटेल एएमटी एडमिन कंट्रोल मोड में सक्रिय है", "ja": "Intel AMTは管理制御モードでアクティブ化されます", + "ko": "관리 제어 모드에서 Intel AMT가 활성화 됨", "nl": "Intel AMT wordt geactiveerd in de beheerdersmodus", "pt": "O Intel AMT é ativado no modo de controle de administrador", "ru": "Intel AMT активирован в режиме администратора", + "zh-chs": "在管理控制模式下激活了Intel AMT", "xloc": [ - "default.handlebars->25->461" + "default.handlebars->27->468" ] }, { @@ -8648,12 +12094,16 @@ "de": "Intel AMT ist im Client Control Mode aktiviert", "en": "Intel AMT is activated in Client Control Mode", "es": "Intel AMT is activated in Client Control Mode (CCM)", + "fr": "Intel AMT est activé en mode client", + "hi": "Intel AMT क्लाइंट कंट्रोल मोड में सक्रिय है", "ja": "Intel AMTはクライアントコントロールモードでアクティブ化されます", + "ko": "클라이언트 제어 모드에서 Intel AMT가 활성화 됨", "nl": "Intel AMT wordt geactiveerd in Client Control Mode", "pt": "O Intel AMT é ativado no modo de controle do cliente", "ru": "Intel AMT активирован в режиме клиента", + "zh-chs": "英特爾AMT在客戶端控制模式下被激活", "xloc": [ - "default.handlebars->25->459" + "default.handlebars->27->466" ] }, { @@ -8661,12 +12111,16 @@ "de": "Intel AMT ist mit TLS-Netzwerksicherheit eingerichtet", "en": "Intel AMT is setup with TLS network security", "es": "Intel AMT está configurado con seguridad de red TLS", + "fr": "Intel AMT est configuré avec une sécurité réseau TLS", + "hi": "इंटेल एएमटी टीएलएस नेटवर्क सुरक्षा के साथ सेटअप है", "ja": "Intel AMTはTLSネットワークセキュリティでセットアップされています", + "ko": "Intel AMT는 TLS 네트워크 보안으로 설정", "nl": "Intel AMT is ingesteld met TLS-netwerkbeveiliging", "pt": "O Intel AMT está configurado com segurança de rede TLS", "ru": "Intel AMT настроен с TLS безопасностью сети", + "zh-chs": "英特爾AMT已設置TLS網絡安全性", "xloc": [ - "default.handlebars->25->463" + "default.handlebars->27->470" ] }, { @@ -8675,12 +12129,15 @@ "en": "Intel AMT not detected", "es": "Intel AMT no detectado", "fr": "Intel AMT non détecté", + "hi": "इंटेल एएमटी का पता नहीं चला", "ja": "Intel AMTが検出されません", + "ko": "인텔 AMT가 감지되지 않습니다", "nl": "Intel AMT niet gedetecteerd", "pt": "Intel AMT não detectado", "ru": "Intel AMT не обнаружен", + "zh-chs": "未檢測到英特爾AMT", "xloc": [ - "default.handlebars->25->159" + "default.handlebars->27->142" ] }, { @@ -8688,12 +12145,16 @@ "de": "Intel AMT benötigt einen gesetzten Trusted FQDN im MEBx oder eine drahtgebundene Verbindung zum LAN:", "en": "Intel AMT will need to be set with a Trusted FQDN in MEBx or have a wired LAN on the network:", "es": "Intel AMT deberá configurarse con un FQDN de confianza en MEBx o tener una LAN con cable en la red:", + "fr": "Intel AMT devra être configuré avec un FQDN approuvé dans MEBx ou avoir un LAN câblé sur le réseau:", + "hi": "इंटेल एएमटी को एमईबीएक्स में एक विश्वसनीय एफक्यूडीएन के साथ सेट करने की आवश्यकता होगी या नेटवर्क पर एक वायर्ड लैन होगा:", "ja": "Intel AMTは、MEBxで信頼できるFQDNを使用して設定するか、ネットワーク上に有線LANが必要です。", + "ko": "Intel AMT는 MEBx에서 Trusted FQDN으로 설정하거나 네트워크에 유선 LAN이 있어야합니다.", "nl": "Intel AMT moet worden ingesteld met een vertrouwd FQDN in MEBx of een bekabeld LAN op het netwerk hebben:", "pt": "A Intel AMT precisará ser configurada com um FQDN confiável na MEBx ou ter uma LAN com fio na rede:", "ru": "Intel AMT необходимо установить с доверенным FQDN в MEBx или иметь кабельное подключение к локальной сети:", + "zh-chs": "英特爾AMT將需要在MEBx中設置為受信任的FQDN,或者在網絡上具有有線局域網:", "xloc": [ - "default.handlebars->25->251" + "default.handlebars->27->235" ] }, { @@ -8701,32 +12162,40 @@ "de": "Intel ASCII", "en": "Intel ASCII", "es": "Intel ASCII", + "fr": "Intel ASCII", + "hi": "इंटेल ASCII", "ja": "Intel ASCII", + "ko": "인텔 ASCII", "nl": "Intel ASCII", "pt": "Intel ASCII", "ru": "Intel ASCII", + "zh-chs": "英特爾ASCII", "xloc": [ - "default.handlebars->25->640" + "default.handlebars->27->689" ] }, { - "cs": "Intel® AMT", + "cs": "Intel® AMT", "de": "Intel® AMT", "en": "Intel® AMT", "es": "Intel® AMT", + "fr": "Intel® AMT", + "hi": "इंटेल® एएमटी", "ja": "Intel® AMT", + "ko": "인텔 ® AMT", "nl": "Intel® AMT", "pt": "Intel® AMT", "ru": "Intel® AMT", + "zh-chs": "英特爾®AMT", "xloc": [ - "default-mobile.handlebars->9->123", - "default-mobile.handlebars->9->187", - "default-mobile.handlebars->9->192", - "default.handlebars->25->1004", - "default.handlebars->25->1012", - "default.handlebars->25->421", - "default.handlebars->25->471", - "default.handlebars->25->487" + "default-mobile.handlebars->9->127", + "default-mobile.handlebars->9->191", + "default-mobile.handlebars->9->196", + "default.handlebars->27->1109", + "default.handlebars->27->1119", + "default.handlebars->27->425", + "default.handlebars->27->478", + "default.handlebars->27->494" ] }, { @@ -8734,13 +12203,17 @@ "de": "Intel® AMT CIRA", "en": "Intel® AMT CIRA", "es": "Intel® AMT CIRA", + "fr": "Intel® AMT CIRA", + "hi": "इंटेल® AMT CIRA", "ja": "Intel® AMT CIRA", + "ko": "인텔 ® AMT CIRA", "nl": "Intel® AMT CIRA", "pt": "Intel® AMT CIRA", "ru": "Intel® AMT CIRA", + "zh-chs": "英特爾®AMT CIRA", "xloc": [ - "default-mobile.handlebars->9->191", - "default.handlebars->25->485" + "default-mobile.handlebars->9->195", + "default.handlebars->27->492" ] }, { @@ -8748,14 +12221,18 @@ "de": "Intel® AMT CIRA ist verbunden und einsatzbereit.", "en": "Intel® AMT CIRA is connected and ready for use.", "es": "Intel & reg; AMT CIRA está conectado y listo para usar.", + "fr": "Intel® AMT CIRA est connecté et prêt à être utilisé.", + "hi": "Intel® AMT CIRA जुड़ा हुआ है और उपयोग के लिए तैयार है।", "ja": "Intel® AMT CIRAが接続され、使用できる状態になりました。", + "ko": "인텔 ® AMT CIRA가 연결되어 사용할 준비가되었습니다.", "nl": "Intel® AMT CIRA is verbonden en klaar voor gebruik.", "pt": "Intel® O AMT CIRA está conectado e pronto para uso.", "ru": "Intel® AMT CIRA подключен и готов к использованию.", + "zh-chs": "英特爾®AMT CIRA已連接並可以使用。", "xloc": [ - "default.handlebars->25->185", - "default.handlebars->25->372", - "default.handlebars->25->484" + "default.handlebars->27->169", + "default.handlebars->27->362", + "default.handlebars->27->491" ] }, { @@ -8763,13 +12240,17 @@ "de": "Intel® AMT verbunden", "en": "Intel® AMT Connected", "es": "Intel® AMT Conectado", + "fr": "Intel® AMT Connecté", + "hi": "Intel® AMT कनेक्टेड है", "ja": "Intel®接続されたAMT", + "ko": "인텔 ® AMT 연결", "nl": "Intel® AMT verbonden", "pt": "Intel® AMT conectado", "ru": "Intel® AMT подключен", + "zh-chs": "英特爾®AMT已連接", "xloc": [ "default-mobile.handlebars->9->5", - "default.handlebars->25->12", + "default.handlebars->27->12", "xterm.handlebars->9->5" ] }, @@ -8778,12 +12259,16 @@ "de": "Intel® AMT Regelwerk", "en": "Intel® AMT Policy", "es": "Intel & reg; Política de AMT", + "fr": "Restrictions Intel® AMT", + "hi": "Intel® AMT नीति", "ja": "Intel® AMTポリシー", + "ko": "인텔 ® AMT 정책", "nl": "Intel® AMT beleid", "pt": "Intel® Política da AMT", "ru": "Политика Intel® AMT", + "zh-chs": "英特爾®AMT政策", "xloc": [ - "default.handlebars->25->1044" + "default.handlebars->27->1148" ] }, { @@ -8791,10 +12276,14 @@ "de": "Intel® AMT Umleitung", "en": "Intel® AMT Redirection", "es": "Intel & reg; Redirección AMT", + "fr": "Redirection Intel® AMT", + "hi": "Intel® AMT पुनर्निर्देशन", "ja": "Intel® AMTリダイレクト", + "ko": "인텔 ® AMT 리디렉션", "nl": "Intel® AMT omleiding", "pt": "Intel® Redirecionamento AMT", "ru": "Перенаправление Intel® AMT", + "zh-chs": "英特爾®AMT重定向", "xloc": [ "player.handlebars->3->14" ] @@ -8804,12 +12293,16 @@ "de": "Intel® AMT Kennzeichen", "en": "Intel® AMT Tag", "es": "Intel & reg; Etiqueta AMT", + "fr": "Étiquette Intel® AMT", + "hi": "Intel® AMT टैग", "ja": "Intel® AMTタグ", + "ko": "인텔 ® AMT 태그", "nl": "Intel® AMT Tag", "pt": "Intel® Tag AMT ", "ru": "Intel® AMT Тег", + "zh-chs": "英特爾®AMT標籤", "xloc": [ - "default.handlebars->25->475" + "default.handlebars->27->482" ] }, { @@ -8817,10 +12310,14 @@ "de": "Intel® AMT WSMAN", "en": "Intel® AMT WSMAN", "es": "Intel® AMT WSMAN", + "fr": "Intel® AMT WSMAN", + "hi": "इंटेल® AMT WSMAN", "ja": "Intel® AMT WSMAN", + "ko": "인텔 ® AMT WSMAN", "nl": "Intel® AMT WSMAN", "pt": "Intel® AMT WSMAN", "ru": "Intel® AMT WSMAN", + "zh-chs": "英特爾®AMT WSMAN", "xloc": [ "player.handlebars->3->13" ] @@ -8830,13 +12327,17 @@ "de": "Intel® AMT Aktivierung", "en": "Intel® AMT activation", "es": "Intel® activacion AMT", + "fr": "Activation Intel® AMT", + "hi": "Intel® AMT सक्रियण", "ja": "Intel® AMTアクティベーション", + "ko": "인텔 ® AMT 활성화", "nl": "Intel® AMT activatie", "pt": "Intel® Ativação AMT", "ru": "Активация Intel® AMT", + "zh-chs": "英特爾®AMT激活", "xloc": [ - "default.handlebars->25->249", - "default.handlebars->25->252" + "default.handlebars->27->233", + "default.handlebars->27->236" ] }, { @@ -8844,14 +12345,18 @@ "de": "Intel® AMT verbunden", "en": "Intel® AMT connected", "es": "Intel® AMT conectado", + "fr": "Intel® AMT connecté", + "hi": "Intel® AMT जुड़ा हुआ है", "ja": "Intel®接続されたAMT", + "ko": "인텔 ® AMT 연결", "nl": "Intel® AMT verbonden", "pt": "Intel® AMT conectado", "ru": "Intel® AMT подключен", + "zh-chs": "英特爾®AMT已連接", "xloc": [ - "default-mobile.handlebars->9->201", - "default.handlebars->25->522", - "default.handlebars->25->523" + "default-mobile.handlebars->9->205", + "default.handlebars->27->529", + "default.handlebars->27->530" ] }, { @@ -8859,13 +12364,17 @@ "de": "Intel® AMT Desktop- und Seriell-Ereignisse.", "en": "Intel® AMT desktop and serial events.", "es": "Intel & reg; Escritorio AMT y eventos en serie.", + "fr": "Événements de bureau et série Intel® AMT.", + "hi": "Intel® AMT डेस्कटॉप और सीरियल इवेंट।", "ja": "Intel® AMTデスクトップおよびシリアルイベント。", + "ko": "인텔 ® AMT 데스크탑 및 직렬 이벤트.", "nl": "Intel® AMT desktop- en seriële gebeurtenissen.", "pt": "Intel® Área de trabalho AMT e eventos seriais.", "ru": "События Intel® AMT desktop или serial.", + "zh-chs": "英特爾®AMT桌面和串行事件。", "xloc": [ - "default.handlebars->25->1142", - "default.handlebars->25->929" + "default.handlebars->27->1034", + "default.handlebars->27->1270" ] }, { @@ -8873,14 +12382,18 @@ "de": "Intel® AMT erkannt", "en": "Intel® AMT detected", "es": "Intel & reg; AMT detectado", + "fr": "Intel® AMT detecté", + "hi": "Intel® AMT का पता चला", "ja": "Intel® AMTが検出されました", + "ko": "인텔 ® AMT 감지", "nl": "Intel® AMT gedetecteerd", "pt": "Intel® AMT detectado", "ru": "Intel® AMT обнаружен", + "zh-chs": "檢測到英特爾®AMT", "xloc": [ - "default-mobile.handlebars->9->202", - "default.handlebars->25->524", - "default.handlebars->25->525" + "default-mobile.handlebars->9->206", + "default.handlebars->27->531", + "default.handlebars->27->532" ] }, { @@ -8888,12 +12401,16 @@ "de": "Intel® AMT ist routebar und einsatzbereit.", "en": "Intel® AMT is routable and ready for use.", "es": "Intel & reg; AMT es enrutable y está listo para usar.", + "fr": "Intel® AMT est routable et prêt à l'emploi.", + "hi": "Intel® AMT राउटेबल है और उपयोग के लिए तैयार है।", "ja": "Intel® AMTはルーティング可能であり、すぐに使用できます。", + "ko": "인텔 ® AMT는 라우팅 가능하며 사용할 준비가되었습니다.", "nl": "Intel® AMT is routeerbaar en klaar voor gebruik.", "pt": "Intel® O AMT é roteável e pronto para uso.", "ru": "Intel® AMT маршрутизируется и готов к использованию.", + "zh-chs": "英特爾®AMT可路由並可以使用。", "xloc": [ - "default.handlebars->25->486" + "default.handlebars->27->493" ] }, { @@ -8901,13 +12418,17 @@ "de": "Intel® AMT ist routebar.", "en": "Intel® AMT is routable.", "es": "Intel & reg; AMT es enrutable.", + "fr": "Intel® AMT est routable.", + "hi": "Intel® AMT राउटेबल है।", "ja": "Intel® AMTはルーティング可能です。", + "ko": "인텔 ® AMT는 라우팅 가능합니다.", "nl": "Intel® AMT is routeerbaar.", "pt": "Intel® AMT é roteável.", "ru": "Intel® AMT маршрутизируется.", + "zh-chs": "英特爾®AMT是可路由的。", "xloc": [ - "default.handlebars->25->187", - "default.handlebars->25->374" + "default.handlebars->27->171", + "default.handlebars->27->364" ] }, { @@ -8915,12 +12436,16 @@ "de": "Nur Intel® AMT", "en": "Intel® AMT only", "es": "Intel & reg; Solo AMT", + "fr": "Intel® AMT uniquement", + "hi": "केवल Intel® AMT", "ja": "Intel® AMTのみ", + "ko": "인텔 ® AMT 만", "nl": "Alleen Intel® AMT", "pt": "Intel® Apenas AMT", "ru": "Только Intel® AMT", + "zh-chs": "僅限英特爾®AMT", "xloc": [ - "default-mobile.handlebars->9->59" + "default-mobile.handlebars->9->62" ] }, { @@ -8928,14 +12453,18 @@ "de": "Nur Intel® AMT, kein Agent", "en": "Intel® AMT only, no agent", "es": "Intel & reg; Solo AMT, sin agente", + "fr": "Intel® AMT uniquement, aucun agent", + "hi": "Intel® AMT केवल, कोई एजेंट नहीं", "ja": "Intel® AMTのみ、エージェントなし", + "ko": "인텔 ® AMT 만 해당, 에이전트 없음", "nl": "Alleen Intel® AMT, geen agent", "pt": "Intel® Apenas AMT, nenhum agente", "ru": "Только Intel® AMT, без агента", + "zh-chs": "僅限英特爾®AMT,無代理", "xloc": [ - "default-mobile.handlebars->9->274", - "default.handlebars->25->958", - "default.handlebars->25->980" + "default-mobile.handlebars->9->278", + "default.handlebars->27->1063", + "default.handlebars->27->1085" ] }, { @@ -8943,12 +12472,33 @@ "de": "Intel® Active Management Technology", "en": "Intel® Active Management Technology", "es": "Intel® Active Management Technology", + "fr": "Technologie Intel® Active Management", + "hi": "इंटेल® सक्रिय प्रबंधन प्रौद्योगिकी", "ja": "Intel®アクティブ管理テクノロジー", + "ko": "인텔 ® 액티브 관리 기술", "nl": "Intel® Active Management Technology", "pt": "Intel® Tecnologia de gerenciamento ativo", "ru": "Технология Intel® Active Management", + "zh-chs": "英特爾®主動管理技術", "xloc": [ - "default.handlebars->25->470" + "default.handlebars->27->477" + ] + }, + { + "cs": "Intel® Active Management Technology (Intel® AMT)", + "de": "Intel® Active Management Technology (Intel® AMT)", + "en": "Intel® Active Management Technology (Intel® AMT)", + "es": "Intel® Active Management Technology (Intel® AMT)", + "fr": "Intel® Active Management Technology (Intel® AMT)", + "hi": "Intel® सक्रिय प्रबंधन प्रौद्योगिकी (Intel® AMT)", + "ja": "インテル®アクティブ管理テクノロジー(インテル®AMT)", + "ko": "인텔 ® 액티브 관리 기술 (인텔 ® AMT)", + "nl": "Intel® Active Management Technology (Intel® AMT)", + "pt": "Intel® Active Management Technology (Intel® AMT)", + "ru": "Intel® Active Management Technology (Intel® AMT)", + "zh-chs": "英特爾®主動管理技術(英特爾®AMT)", + "xloc": [ + "default.handlebars->27->777" ] }, { @@ -8956,13 +12506,17 @@ "de": "Intel® ME", "en": "Intel® ME", "es": "Intel® ME", + "fr": "Intel® ME", + "hi": "Intel® ME", "ja": "Intel®私", + "ko": "인텔 ® ME", "nl": "Intel® ME", "pt": "Intel® ME", "ru": "Intel® ME", + "zh-chs": "英特爾®ME", "xloc": [ - "default-mobile.handlebars->9->186", - "default.handlebars->25->469" + "default-mobile.handlebars->9->190", + "default.handlebars->27->476" ] }, { @@ -8970,13 +12524,17 @@ "de": "Intel® SM", "en": "Intel® SM", "es": "Intel® SM", + "fr": "Intel® SM", + "hi": "इंटेल® एस.एम.", "ja": "Intel® SM", + "ko": "인텔 ® SM", "nl": "Intel® SM", "pt": "Intel® SM", "ru": "Intel® SM", + "zh-chs": "英特爾®SM", "xloc": [ - "default-mobile.handlebars->9->188", - "default.handlebars->25->473" + "default-mobile.handlebars->9->192", + "default.handlebars->27->480" ] }, { @@ -8984,12 +12542,16 @@ "de": "Intel® Standard Manageability", "en": "Intel® Standard Manageability", "es": "Intel & reg; Capacidad de gestión estándar", + "fr": "Gestion standard Intel®", + "hi": "इंटेल® मानक प्रबंधन क्षमता", "ja": "Intel®標準の管理性", + "ko": "인텔 ® 표준 관리 성", "nl": "Standaard beheerbaarheid van Intel®", "pt": "Intel® Gerenciamento padrão", "ru": "Intel® Standard Manageability", + "zh-chs": "英特爾®標準可管理性", "xloc": [ - "default.handlebars->25->472" + "default.handlebars->27->479" ] }, { @@ -8997,20 +12559,28 @@ "de": "Intel® AMT", "en": "Intel® AMT", "es": "Intel® AMT", - "ja": "Intel® AMT", + "fr": "Intel® AMT", + "hi": "इंटेल® एएमटी", + "ja": "インテル®AMT", + "ko": "인텔 ® AMT", "nl": "Intel® AMT", "pt": "Intel® AMT", - "ru": "Intel® AMT" + "ru": "Intel® AMT", + "zh-chs": "英特爾®AMT" }, { "cs": "Intel® AMT –", "de": "Intel® AMT -", "en": "Intel® AMT -", "es": "Intel® AMT -", + "fr": "Intel® AMT -", + "hi": "Intel® AMT -", "ja": "Intel® AMT -", + "ko": "인텔 ® AMT-", "nl": "Intel® AMT -", "pt": "Intel® AMT -", "ru": "Intel® AMT -", + "zh-chs": "英特爾®AMT-", "xloc": [ "default.handlebars->container->column_l->p14->p14title->5" ] @@ -9020,10 +12590,14 @@ "de": "Intel® AMT Hardware-KVM", "en": "Intel® AMT Hardware KVM", "es": "Intel® AMT Hardware KVM", + "fr": "Intel® AMT Hardware KVM", + "hi": "Intel® AMT हार्डवेयर KVM", "ja": "Intel® AMTハードウェアKVM", + "ko": "인텔 ® AMT 하드웨어 KVM", "nl": "Intel® AMT Hardware KVM", "pt": "Intel® AMT Hardware KVM", "ru": "Intel® AMT Hardware KVM", + "zh-chs": "英特爾®AMT硬件KVM", "xloc": [ "default-mobile.handlebars->dialog->3->dialog7->d7amtkvm->1", "default.handlebars->container->dialog->dialogBody->dialog7->d7amtkvm->1" @@ -9034,10 +12608,14 @@ "de": "Intel® AMT Umleitungsport oder KVM-Eigenschaft ist deaktiviert", "en": "Intel® AMT Redirection port or KVM feature is disabled", "es": "Intel® AMT el puerto de redireccion o la función KVM están deshabilitados", + "fr": "Le port de redirection Intel® AMT ou la fonctionnalité KVM est désactivé", + "hi": "Intel® AMT पुनर्निर्देशन पोर्ट या KVM सुविधा अक्षम है", "ja": "Intel® AMTリダイレクトポートまたはKVM機能が無効になっています", + "ko": "인텔 ® AMT 리디렉션 포트 또는 KVM 기능이 비활성화되었습니다", "nl": "Intel® AMT omleidingspoort of KVM-functie is uitgeschakeld", "pt": "Intel® Porta de redirecionamento AMT ou recurso KVM desativado", "ru": "Функция Intel® AMT Redirection port или KVM отключены", + "zh-chs": "英特爾®AMT重定向端口或KVM功能已禁用", "xloc": [ "default.handlebars->container->column_l->p11->p11warning->3", "default.handlebars->container->column_l->p12->p12warning->3" @@ -9045,11 +12623,17 @@ }, { "cs": "Intel®AMT", - "de": "Intel® AMT", + "de": "Intel®AMT", "en": "Intel®AMT", "es": "Intel®AMT", + "fr": "Intel®AMT", + "hi": "Intel®AMT", + "ja": "Intel®AMT", + "ko": "인텔 ®AMT", "nl": "Intel®AMT", + "pt": "Intel®AMT", "ru": "Intel®AMT", + "zh-chs": "英特爾®AMT", "xloc": [ "default.handlebars->container->topbar->1->1->MainSubMenuSpan->MainSubMenu->1->0->MainDevAmt" ] @@ -9059,12 +12643,16 @@ "de": "Interaktiv", "en": "Interactive", "es": "Interactivo", + "fr": "Interactif", + "hi": "इंटरएक्टिव", "ja": "インタラクティブ", + "ko": "인터렉티브", "nl": "Interactief", "pt": "Interativo", "ru": "Интерактивный", + "zh-chs": "互動", "xloc": [ - "default.handlebars->25->623" + "default.handlebars->27->672" ] }, { @@ -9072,13 +12660,19 @@ "de": "Nur interaktiv", "en": "Interactive only", "es": "Solo Interactivo", + "fr": "Interactif seulement", + "hi": "केवल इंटरएक्टिव", "ja": "インタラクティブのみ", + "ko": "대화식 만", "nl": "Alleen interactief", "pt": "Apenas interativo", "ru": "Только интерактивный режим", + "zh-chs": "僅限互動", "xloc": [ - "default.handlebars->25->301", - "default.handlebars->25->323" + "default.handlebars->27->1258", + "default.handlebars->27->1265", + "default.handlebars->27->288", + "default.handlebars->27->310" ] }, { @@ -9087,12 +12681,15 @@ "en": "Interfaces", "es": "Interfaces", "fr": "Interfaces", + "hi": "इंटरफेस", "ja": "インターフェース", + "ko": "인터페이스", "nl": "Interfaces", "pt": "Interfaces", "ru": "Интерфейсы", + "zh-chs": "介面", "xloc": [ - "default.handlebars->25->505" + "default.handlebars->27->512" ] }, { @@ -9100,12 +12697,15 @@ "de": "Inuktitut", "en": "Inuktitut", "fr": "Inuktitut", + "hi": "इनूकीटूत्", "ja": "イヌクティトゥット語", + "ko": "이 누크 티 투트", "nl": "Inuktitut", "pt": "Inuktitut", "ru": "Инуктитут", + "zh-chs": "因紐特人", "xloc": [ - "default.handlebars->25->815" + "default.handlebars->27->919" ] }, { @@ -9113,10 +12713,16 @@ "de": "Ungültiger Gerätegruppentyp", "en": "Invalid Device Group Type", "es": "Tipo de grupo de dispositivo no válido", + "fr": "Type de groupe de périphériques non valide", + "hi": "अमान्य उपकरण समूह प्रकार", + "ja": "無効なデバイスグループタイプ", + "ko": "잘못된 장치 그룹 유형", "nl": "Ongeldige apparaatgroep type", + "pt": "Tipo de grupo de dispositivos inválido", "ru": "Некорректный тип группы устройств", + "zh-chs": "無效的設備組類型", "xloc": [ - "default.handlebars->25->1408" + "default.handlebars->27->1555" ] }, { @@ -9124,10 +12730,16 @@ "de": "Ungültiges JSON", "en": "Invalid JSON", "es": "JSON inválido.", + "fr": "Json invalide", + "hi": "अमान्य JSON", + "ja": "無効なJSON", + "ko": "잘못된 JSON", "nl": "Onjuiste JSON", + "pt": "JSON inválido", "ru": "Некорректный JSON", + "zh-chs": "無效的JSON", "xloc": [ - "default.handlebars->25->1402" + "default.handlebars->27->1549" ] }, { @@ -9135,13 +12747,17 @@ "de": "Ungültiges JSON-Dateiformat.", "en": "Invalid JSON file format.", "es": "Formato de Archivo JSON inválido.", + "fr": "Fichier JSON invalide.", + "hi": "अमान्य JSON फ़ाइल स्वरूप।", "ja": "JSONファイル形式が無効です。", + "ko": "잘못된 JSON 파일 형식입니다.", "nl": "Ongeldige JSON-bestandsindeling.", "pt": "Formato de arquivo JSON inválido.", "ru": "Некорректный формат файла JSON.", + "zh-chs": "無效的JSON文件格式。", "xloc": [ - "default.handlebars->25->1230", - "default.handlebars->25->1232" + "default.handlebars->27->1365", + "default.handlebars->27->1367" ] }, { @@ -9149,12 +12765,16 @@ "de": "Ungültige JSON-Datei: {0}.", "en": "Invalid JSON file: {0}.", "es": "Formato de Archivo JSON: {0}.", + "fr": "Fichier JSON Invalide : {0}.", + "hi": "अमान्य JSON फ़ाइल: {0}।", "ja": "無効なJSONファイル:{0}。", + "ko": "유효하지 않은 JSON 파일 : {0}.", "nl": "Ongeldig JSON-bestand: {0}.", "pt": "Arquivo JSON inválido: {0}.", "ru": "Некорректный файл JSON: {0}.", + "zh-chs": "無效的JSON文件:{0}。", "xloc": [ - "default.handlebars->25->1228" + "default.handlebars->27->1363" ] }, { @@ -9162,10 +12782,16 @@ "de": "Ungültige PKCS-Signatur", "en": "Invalid PKCS signature", "es": "Firma PKCS inválida", + "fr": "Signature PKCS invalide", + "hi": "अमान्य PKCS हस्ताक्षर", + "ja": "無効なPKCS署名", + "ko": "잘못된 PKCS 서명", "nl": "Onjuiste PKCS handtekening", + "pt": "Assinatura PKCS inválida", "ru": "Некорректная сигнатура PKCS", + "zh-chs": "無效的PKCS簽名", "xloc": [ - "default.handlebars->25->1400" + "default.handlebars->27->1547" ] }, { @@ -9173,10 +12799,16 @@ "de": "Ungültige RSA-Signatur", "en": "Invalid RSA siguature", "es": "La firma RSA no es válida", + "fr": "Signature RSA invalide", + "hi": "अमान्य RSA संयुक्ताक्षर", + "ja": "無効なRSA署名", + "ko": "잘못된 RSA siguature", "nl": "Ongeldige RSA handtekening", + "pt": "Siguatura RSA inválida", "ru": "Некорректная сигнатура RSA", + "zh-chs": "無效的RSA密碼", "xloc": [ - "default.handlebars->25->1401" + "default.handlebars->27->1548" ] }, { @@ -9184,12 +12816,17 @@ "de": "Ungültiges Kontoerstellungstoken.", "en": "Invalid account creation token.", "es": "Token de creación de cuenta no válido.", + "fr": "Jeton de création de compte invalide.", + "hi": "अमान्य खाता निर्माण टोकन।", "ja": "アカウント作成トークンが無効です。", + "ko": "잘못된 계정 생성 토큰.", "nl": "Ongeldig token voor het maken van een account.", + "pt": "Token de criação de conta inválido.", "ru": "Некорректный токен создания учетной записи.", + "zh-chs": "無效的帳戶創建令牌。", "xloc": [ - "login-mobile.handlebars->5->5", - "login.handlebars->5->5" + "login-mobile.handlebars->5->6", + "login.handlebars->5->6" ] }, { @@ -9197,12 +12834,33 @@ "de": "Ungültige E-Mail.", "en": "Invalid email.", "es": "Correo Electronico inválido.", + "fr": "Email invalide.", + "hi": "अवैध ईमेल।", "ja": "無効なメール。", + "ko": "잘못된 이메일입니다.", "nl": "Ongeldige e-mail.", + "pt": "E-mail inválido.", "ru": "Некорректный email.", + "zh-chs": "不合規電郵。", "xloc": [ - "login-mobile.handlebars->5->8", - "login.handlebars->5->8" + "login-mobile.handlebars->5->9", + "login.handlebars->5->9" + ] + }, + { + "cs": "Neplatný kód pozvánky.", + "de": "Ungültiger Einladungscode.", + "en": "Invalid invitation code.", + "fr": "Code d'invitation non valide.", + "hi": "अमान्य आमंत्रण कोड।", + "ja": "招待コードが無効です。", + "ko": "초대 코드가 잘못되었습니다.", + "nl": "Ongeldige uitnodigingscode.", + "pt": "Código de convite inválido.", + "ru": "Неверный код приглашения.", + "zh-chs": "邀請碼無效。", + "xloc": [ + "invite.handlebars->3->1" ] }, { @@ -9210,25 +12868,47 @@ "de": "Ungültiges Token, versuchen Sie es erneut.", "en": "Invalid token, try again.", "es": "Token no válido, intente nuevamente.", + "fr": "Jeton invalide, réessayer.", + "hi": "अमान्य टोकन, पुनः प्रयास करें।", "ja": "トークンが無効です。もう一度お試しください。", + "ko": "잘못된 토큰입니다. 다시 시도하십시오.", "nl": "Ongeldig token, probeer het opnieuw.", + "pt": "Token inválido, tente novamente.", "ru": "Некорректный токен, попробуйте еще.", + "zh-chs": "令牌無效,請重試。", "xloc": [ - "login-mobile.handlebars->5->10", - "login.handlebars->5->10" + "login-mobile.handlebars->5->11", + "login.handlebars->5->11" ] }, + { + "cs": "Kód pozvánky", + "de": "Einladungscode", + "en": "Invitation Code", + "fr": "code d'invitation", + "hi": "आमंत्रण संकेत", + "ja": "招待コード", + "ko": "초대 코드", + "nl": "Uitnodigingscode", + "pt": "Código de Convite", + "ru": "Код приглашения", + "zh-chs": "邀請碼" + }, { "cs": "Odkaz na pozvánku ({0})", "de": "Einladungslink ({0})", "en": "Invitation Link ({0})", "es": "Enlace de invitación ({0})", + "fr": "Lien de l'invitation ({0})", + "hi": "निमंत्रण लिंक ({0})", "ja": "招待リンク({0})", + "ko": "초대 링크 ({0})", "nl": "Uitnodigingslink ({0})", "pt": "Link de convite ({0})", "ru": "Ссылка для приглашения ({0})", + "zh-chs": "邀請鏈接({0})", "xloc": [ - "default.handlebars->25->174" + "default.handlebars->27->157" ] }, { @@ -9237,12 +12917,44 @@ "en": "Invitation Type", "es": "Tipo de invitación", "fr": "Type d'invitation", + "hi": "निमंत्रण का प्रकार", "ja": "招待タイプ", + "ko": "초대 유형", "nl": "Type uitnodiging", "pt": "Tipo de convite", "ru": "Тип приглашения", + "zh-chs": "邀請類型", "xloc": [ - "default.handlebars->25->280" + "default.handlebars->27->265" + ] + }, + { + "cs": "Kódy pozvání může použít kdokoli pro připojení zařízení k této skupině zařízení pomocí následujícího veřejného odkazu:", + "de": "Einladungscodes können von jedem verwendet werden, um Geräte über den folgenden öffentlichen Link mit dieser Gerätegruppe zu verbinden:", + "en": "Invitation codes can be used by anyone to join devices to this device group using the following public link:", + "fr": "Les codes d'invitation peuvent être utilisés par n'importe qui pour joindre des appareils à ce groupe d'appareils en utilisant le lien public suivant:", + "hi": "निम्नलिखित सार्वजनिक लिंक का उपयोग करके इस उपकरण समूह में उपकरणों से जुड़ने के लिए निमंत्रण कोड का उपयोग किसी द्वारा भी किया जा सकता है:", + "ja": "招待コードは誰でも使用でき、次の公開リンクを使用してデバイスをこのデバイスグループに参加させることができます。", + "ko": "초대 코드는 누구나 다음 공개 링크를 사용하여 장치를이 장치 그룹에 참가시키는 데 사용할 수 있습니다.", + "nl": "Uitnodigingscodes kunnen door iedereen worden gebruikt om apparaten toe te voegen aan deze apparaatgroep via de volgende openbare link:", + "pt": "Os códigos de convite podem ser usados ​​por qualquer pessoa para associar dispositivos a este grupo de dispositivos usando o seguinte link público:", + "ru": "Коды приглашений могут использоваться любым пользователем для присоединения устройств к этой группе устройств по следующей общедоступной ссылке:", + "zh-chs": "任何人都可以使用邀請代碼通過以下公共鏈接將設備加入該設備組:", + "xloc": [ + "default.handlebars->27->1260" + ] + }, + { + "cs": "Kód pozvánky", + "de": "Einladungscode", + "en": "Invitation Code", + "nl": "Uitnodigingscode", + "fr": "Code d'invitation", + "ja": "招待コード", + "ru": "Код приглашения", + "zh-chs": "邀请码", + "xloc": [ + "invite.handlebars->container->column_l->5->1->0->3->1" ] }, { @@ -9251,14 +12963,37 @@ "en": "Invite", "es": "Invitación", "fr": "Inviter", + "hi": "आमंत्रण", "ja": "招待する", + "ko": "초대", "nl": "Uitnodigen", "pt": "Convite", "ru": "Пригласить", + "zh-chs": "邀請", "xloc": [ - "default.handlebars->25->1028", - "default.handlebars->25->236", - "default.handlebars->25->313" + "default.handlebars->27->1135", + "default.handlebars->27->220", + "default.handlebars->27->300" + ] + }, + { + "cs": "Pozvat kódy", + "de": "Codes einladen", + "en": "Invite Codes", + "fr": "Inviter des codes", + "hi": "कोड आमंत्रित करें", + "ja": "コードを招待", + "ko": "코드 초대", + "nl": "Uitnodigingscode", + "pt": "Códigos de convite", + "ru": "Пригласительные коды", + "zh-chs": "邀請碼", + "xloc": [ + "default.handlebars->27->1113", + "default.handlebars->27->1254", + "default.handlebars->27->1259", + "default.handlebars->27->1261", + "default.handlebars->27->1266" ] }, { @@ -9267,12 +13002,15 @@ "en": "Invite someone to install the mesh agent by sharing an invitation link. This link points the user to installation instructions for the \\\"{0}\\\" device group. The link is public and no account for this server is needed.", "es": "Invite a alguien a instalar el agente de malla compartiendo un enlace de invitación. Este enlace le indica al usuario las instrucciones de instalación para el grupo de dispositivos \\\"{0}\\\". El enlace es público y no se necesita una cuenta para este servidor.", "fr": "Invitez quelqu'un à installer l'agent de maillage en partageant un lien d'invitation. Ce lien renvoie l'utilisateur aux instructions d'installation du groupe de périphériques \\\"{0}\\\". Le lien est public et aucun compte n'est requis pour ce serveur.", + "hi": "आमंत्रण लिंक साझा करके मेष एजेंट को स्थापित करने के लिए किसी को आमंत्रित करें। यह लिंक उपयोगकर्ता को \\\"{0} \\\" उपकरण समूह के लिए इंस्टॉलेशन निर्देश इंगित करता है। लिंक सार्वजनिक है और इस सर्वर के लिए किसी खाते की आवश्यकता नहीं है।", "ja": "招待リンクを共有して、メッシュエージェントをインストールする人を招待します。このリンクは、ユーザーに\\\"{0}\\\"デバイスグループのインストール手順を示します。リンクは公開されており、このサーバーのアカウントは必要ありません。", + "ko": "초대 링크를 공유하여 누군가 메쉬 에이전트를 설치하도록 초대하십시오. 이 링크는 사용자에게 \\\"{0} \\\"장치 그룹의 설치 지시 사항을 지시합니다. 링크는 공개이며이 서버에 대한 계정이 필요하지 않습니다.", "nl": "Nodig iemand uit om de mesh-agent te installeren door een uitnodigingslink te delen. Deze koppeling verwijst de gebruiker naar installatie-instructies voor de apparaatgroep \\\"{0}\\\". De link is openbaar en er is geen account voor deze server nodig.", "pt": "Convide alguém para instalar o agente de malha compartilhando um link de convite.Este link indica ao usuário instruções de instalação para o grupo de dispositivos \\\"{0}\\\". O link é público e nenhuma conta para este servidor é necessária.", "ru": "Пригласите установить Mesh Agent поделившись ссылкой. Эта ссылка ведет на инструкции для установки для группы устройств \\\"{0}\\\". Ссылка общедоступна и не требует наличия учетной записи на сервере.", + "zh-chs": "通過共享邀請鏈接來邀請某人安裝網格代理。該鏈接為用戶提供 “{0}” 設備組的安裝說明。該鏈接是公共的,不需要該服務器的帳戶。", "xloc": [ - "default.handlebars->25->304" + "default.handlebars->27->291" ] }, { @@ -9281,13 +13019,16 @@ "en": "Invite someone to install the mesh agent on this mesh.", "es": "Invite a alguien a instalar el agente de mesh en este server.", "fr": "Invitez quelqu'un à installer l'agent de maillage sur ce maillage.", + "hi": "इस जाली पर मेष एजेंट को स्थापित करने के लिए किसी को आमंत्रित करें।", "ja": "このメッシュにメッシュエージェントをインストールするように招待します。", + "ko": "이 메쉬에 메쉬 에이전트를 설치하도록 누군가 초대하십시오.", "nl": "Nodig iemand uit om de mesh-agent op deze mesh te installeren.", "pt": "Convide alguém para instalar o agente de malha nessa malha.", "ru": "Отправить приглашение на установку Mesh Agent", + "zh-chs": "邀請某人在此網格上安裝網格代理。", "xloc": [ - "default.handlebars->25->1027", - "default.handlebars->25->235" + "default.handlebars->27->1134", + "default.handlebars->27->219" ] }, { @@ -9296,12 +13037,15 @@ "en": "Invite someone to install the mesh agent. An email with be sent with the link to the mesh agent installation for the \\\"{0}\\\" device group.", "es": "Invite a alguien a instalar el agente de mesh. Se enviará un correo electrónico con el enlace a la instalación del agente de mesh para el grupo de dispositivos \\\"{0}\\\".", "fr": "Invitez quelqu'un à installer l'agent de maillage. Un email doit être envoyé avec le lien vers l’installation de l’agent de maillage pour le groupe de périphériques \\\"{0}\\\".", + "hi": "मेष एजेंट को स्थापित करने के लिए किसी को आमंत्रित करें। \\\"{0} \\\" डिवाइस समूह के लिए मेष एजेंट स्थापना के लिंक के साथ एक ईमेल भेजा जाना चाहिए।", "ja": "メッシュエージェントをインストールする人を招待します。 \\\"{0}\\\"デバイスグループのメッシュエージェントインストールへのリンクが記載されたメール。", + "ko": "누군가 메쉬 에이전트를 설치하도록 초대하십시오. \\\"{0} \\\"디바이스 그룹의 메시 에이전트 설치 링크가 포함 된 이메일이 발송됩니다.", "nl": "Nodig iemand uit om de mesh-agent te installeren. Er wordt een e-mail verzonden met de link naar de installatie van de mesh-agent voor de apparaatgroep \\\"{0}\\\".", "pt": "Convide alguém para instalar o agente de malha.Um email será enviado com o link para a instalação do agente de malha para o grupo de dispositivos \\\"{0}\\\".", "ru": "Пригласите установить Mesh Agent. Ссылка на установку для группы \\\"{0}\\\" будет отправлена по электронной почте.", + "zh-chs": "邀請某人安裝網狀代理。將發送一封電子郵件,其中包含指向 “{0}” 設備組的網狀代理安裝的鏈接。", "xloc": [ - "default.handlebars->25->281" + "default.handlebars->27->268" ] }, { @@ -9310,12 +13054,15 @@ "en": "Irish", "es": "Irlandesa", "fr": "Irlandais", + "hi": "आयरिश", "ja": "アイルランド人", + "ko": "아일랜드의", "nl": "Iers", "pt": "Irish", "ru": "Ирландский", + "zh-chs": "愛爾蘭人", "xloc": [ - "default.handlebars->25->816" + "default.handlebars->27->920" ] }, { @@ -9323,12 +13070,15 @@ "de": "Italienisch (Standard)", "en": "Italian (Standard)", "fr": "Italien (standard)", + "hi": "इतालवी (मानक)", "ja": "イタリア語(標準)", + "ko": "이탈리아어 (표준)", "nl": "Italiaans (standaard)", "pt": "Italiano (Padrão)", "ru": "Итальянский (Стандартный)", + "zh-chs": "意大利語(標準)", "xloc": [ - "default.handlebars->25->817" + "default.handlebars->27->921" ] }, { @@ -9336,12 +13086,15 @@ "de": "Italienisch (Schweiz)", "en": "Italian (Switzerland)", "fr": "Italien (Suisse)", + "hi": "इतालवी (स्विट्जरलैंड)", "ja": "イタリア語(スイス)", + "ko": "이탈리아어 (스위스)", "nl": "Italiaans (Zwitserland)", "pt": "Italiano (Suíça)", "ru": "Итальянский (Швейцария)", + "zh-chs": "義大利文(瑞士)", "xloc": [ - "default.handlebars->25->818" + "default.handlebars->27->922" ] }, { @@ -9350,13 +13103,17 @@ "en": "JSON Format", "es": "Formato JSON", "fr": "Format JSON", + "hi": "JSON प्रारूप", "ja": "JSON形式", + "ko": "JSON 형식", "nl": "JSON-indeling", "pt": "Formato JSON", "ru": "Формат JSON", + "zh-chs": "JSON格式", "xloc": [ - "default.handlebars->25->1197", - "default.handlebars->25->1236" + "default.handlebars->27->1327", + "default.handlebars->27->1371", + "default.handlebars->27->392" ] }, { @@ -9365,48 +13122,63 @@ "en": "Japanese", "es": "Japones", "fr": "Japonais", + "hi": "जापानी", "ja": "日本人", + "ko": "일본어", "nl": "Japans", "pt": "japonês", "ru": "Японский", + "zh-chs": "日本", "xloc": [ - "default.handlebars->25->819" + "default.handlebars->27->923" ] }, { "cs": "kannadština", "de": "Kannada", "en": "Kannada", + "fr": "Kannada", + "hi": "कन्नड़", "ja": "カンナダ語", + "ko": "칸나다어", "nl": "Kannada", "pt": "Kannada", "ru": "Каннада", + "zh-chs": "卡納達語", "xloc": [ - "default.handlebars->25->820" + "default.handlebars->27->924" ] }, { "cs": "kašmírština", "de": "Kashmiri", "en": "Kashmiri", + "fr": "Cachemire", + "hi": "कश्मीरी", "ja": "カシミール", + "ko": "카시미르 말", "nl": "kasjmier", "pt": "Caxemira", "ru": "Кашмирский", + "zh-chs": "克什米爾語", "xloc": [ - "default.handlebars->25->821" + "default.handlebars->27->925" ] }, { "cs": "kazaština", "de": "Kasachisch", "en": "Kazakh", + "fr": "Kazakh", + "hi": "कजाख", "ja": "カザフ", + "ko": "카자흐어", "nl": "Kazachse", "pt": "Cazaque", "ru": "Казахский", + "zh-chs": "哈薩克語", "xloc": [ - "default.handlebars->25->822" + "default.handlebars->27->926" ] }, { @@ -9414,12 +13186,16 @@ "de": "Kernel-Treiber", "en": "KernelDriver", "es": "KernelDriver", + "fr": "KernelDriver", + "hi": "KernelDriver", "ja": "KernelDriver", + "ko": "커널 드라이버", "nl": "KernelDriver", "pt": "KernelDriver", "ru": "Драйвер ядра", + "zh-chs": "內核驅動程序", "xloc": [ - "default.handlebars->25->624" + "default.handlebars->27->673" ] }, { @@ -9428,13 +13204,16 @@ "en": "Key Name", "es": "Nombre Llave", "fr": "Nom de la clé", + "hi": "मुख्य नाम", "ja": "キー名", + "ko": "키 이름", "nl": "Sleutelnaam", "pt": "Nome da chave", "ru": "Имя ключа", + "zh-chs": "鍵名", "xloc": [ - "default.handlebars->25->713", - "default.handlebars->25->716" + "default.handlebars->27->817", + "default.handlebars->27->820" ] }, { @@ -9443,10 +13222,13 @@ "en": "Keyboard", "es": "Teclado", "fr": "Clavier", + "hi": "कीबोर्ड", "ja": "キーボード", + "ko": "건반", "nl": "Toetsenbord", "pt": "Teclado", "ru": "Клавиатура", + "zh-chs": "鍵盤", "xloc": [ "default-mobile.handlebars->container->page_content->column_l->p10->p10desktop->deskarea4->1->3" ] @@ -9455,36 +13237,64 @@ "cs": "khmerština", "de": "Khmer", "en": "Khmer", + "fr": "Khmer", + "hi": "खमेर", "ja": "クメール", + "ko": "크메르", "nl": "Khmer", "pt": "Khmer", "ru": "Кхмерский", + "zh-chs": "高棉語", "xloc": [ - "default.handlebars->25->823" + "default.handlebars->27->927" ] }, { "cs": "kyrgyzština", "de": "Kirgisisch", "en": "Kirghiz", + "fr": "kirghiz", + "hi": "किरगिज़", "ja": "キルギス", + "ko": "키르기즈 사람", "nl": "Kirgizisch", "pt": "Kirghiz", "ru": "Киргизский", + "zh-chs": "吉爾吉斯", "xloc": [ - "default.handlebars->25->824" + "default.handlebars->27->928" ] }, { "cs": "klingonština", "de": "Klingonisch", "en": "Klingon", + "fr": "Klingon", + "hi": "क्लिंगन", "ja": "クリンゴン", + "ko": "클링 온", "nl": "Klingon", "pt": "Klingon", "ru": "Клингонский", + "zh-chs": "克林貢", "xloc": [ - "default.handlebars->25->825" + "default.handlebars->27->929" + ] + }, + { + "cs": "Známý", + "de": "Bekannt", + "en": "Known", + "fr": "Connu", + "hi": "मालूम", + "ja": "既知の", + "ko": "모두 다 아는", + "nl": "Bekend", + "pt": "Conhecido", + "ru": "Известный", + "zh-chs": "已知的", + "xloc": [ + "default.handlebars->27->776" ] }, { @@ -9492,12 +13302,15 @@ "de": "Koreanisch", "en": "Korean", "fr": "Coréen", + "hi": "कोरियाई", "ja": "韓国語", + "ko": "한국어", "nl": "Koreaans", "pt": "coreano", "ru": "Korean", + "zh-chs": "韓語", "xloc": [ - "default.handlebars->25->826" + "default.handlebars->27->930" ] }, { @@ -9505,12 +13318,15 @@ "de": "Koreanisch (Nordkorea)", "en": "Korean (North Korea)", "fr": "Coréen (Corée du Nord)", + "hi": "कोरियाई (उत्तर कोरिया)", "ja": "韓国語(北朝鮮)", + "ko": "한국어 (북한)", "nl": "Koreaans (Noord-Korea)", "pt": "Coreano (Coréia do Norte)", "ru": "Корейский (Северная Корея)", + "zh-chs": "韓語(朝鮮)", "xloc": [ - "default.handlebars->25->827" + "default.handlebars->27->931" ] }, { @@ -9518,25 +13334,33 @@ "de": "Koreanisch (Südkorea)", "en": "Korean (South Korea)", "fr": "Coréen (Corée du Sud)", + "hi": "कोरियाई (दक्षिण कोरिया)", "ja": "韓国語(韓国)", + "ko": "한국어 (한국)", "nl": "Koreaans (Zuid-Korea)", "pt": "Coreano (Coréia do Sul)", "ru": "Корейский (Южная Корея)", + "zh-chs": "韓語(韓國)", "xloc": [ - "default.handlebars->25->828" + "default.handlebars->27->932" ] }, { "cs": "LF", + "de": "LF", "en": "LF", "es": "LF", + "fr": "LF", + "hi": "वामो", "ja": "LF", + "ko": "LF", "nl": "LF", "pt": "LF", "ru": "LF", + "zh-chs": "如果", "xloc": [ - "default.handlebars->25->636", - "default.handlebars->25->645" + "default.handlebars->27->685", + "default.handlebars->27->694" ] }, { @@ -9545,12 +13369,15 @@ "en": "Language", "es": "Idioma", "fr": "Langages", + "hi": "भाषा: हिन्दी", "ja": "言語", + "ko": "언어", "nl": "Taal", "pt": "Língua", "ru": "Язык", + "zh-chs": "語言", "xloc": [ - "default.handlebars->25->921" + "default.handlebars->27->1026" ] }, { @@ -9559,10 +13386,13 @@ "en": "Large", "es": "Grande", "fr": "Grand", + "hi": "विशाल", "ja": "大", + "ko": "큰", "nl": "Grote", "pt": "ampla", "ru": "Большой/крупный", + "zh-chs": "大", "xloc": [ "default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->9->devListToolbarSize->sizeselect->5" ] @@ -9573,12 +13403,15 @@ "en": "Large Focus", "es": "Gran enfoque", "fr": "Grande mise au point", + "hi": "बड़ा फोकस", "ja": "大焦点", + "ko": "큰 초점", "nl": "Grote focus", "pt": "Foco grande", "ru": "Большой Фокус", + "zh-chs": "大焦點", "xloc": [ - "default.handlebars->25->613" + "default.handlebars->27->661" ] }, { @@ -9587,10 +13420,13 @@ "en": "Last 100", "es": "Ultimos 100", "fr": "100 dernières", + "hi": "अंतिम 100", "ja": "最後の100", + "ko": "마지막 100", "nl": "Laatste 100", "pt": "Últimos 100", "ru": "Последние 100", + "zh-chs": "最近100", "xloc": [ "default.handlebars->container->column_l->p41->3->1->p41limitdropdown->1" ] @@ -9601,10 +13437,13 @@ "en": "Last 1000", "es": "Ultimos 1000", "fr": "1000 derniers", + "hi": "पिछले 1000", "ja": "過去1000", + "ko": "지난 1000", "nl": "Laatste 1000", "pt": "Últimos 1000", "ru": "Последние 1000", + "zh-chs": "最近1000", "xloc": [ "default.handlebars->container->column_l->p16->3->1->0->5->p16limitdropdown->9", "default.handlebars->container->column_l->p3->3->1->0->3->p3limitdropdown->9", @@ -9618,10 +13457,13 @@ "en": "Last 120", "es": "Ultimos 120", "fr": "120 dernières", + "hi": "अंतिम 120", "ja": "最後の120", + "ko": "마지막 120", "nl": "Laatste 120", "pt": "Últimos 120", "ru": "Последние 120", + "zh-chs": "最後120", "xloc": [ "default.handlebars->container->column_l->p16->3->1->0->5->p16limitdropdown->3", "default.handlebars->container->column_l->p3->3->1->0->3->p3limitdropdown->3", @@ -9634,10 +13476,13 @@ "en": "Last 250", "es": "Ultimos 250", "fr": "250 dernières", + "hi": "अंतिम 250", "ja": "過去250", + "ko": "마지막 250", "nl": "Laatste 250", "pt": "Últimos 250", "ru": "Последние 250", + "zh-chs": "最近250", "xloc": [ "default.handlebars->container->column_l->p16->3->1->0->5->p16limitdropdown->5", "default.handlebars->container->column_l->p3->3->1->0->3->p3limitdropdown->5", @@ -9651,10 +13496,13 @@ "en": "Last 3 hours", "es": "Ultimas 3 horas", "fr": "3 dernières heures", + "hi": "पिछले 3 घंटे", "ja": "過去3時間", + "ko": "지난 3 시간", "nl": "Laatste 3 uur", "pt": "Últimas 3 horas", "ru": "Последние 3 часа", + "zh-chs": "最近3小時", "xloc": [ "default.handlebars->container->column_l->p40->3->1->p40time->1" ] @@ -9665,10 +13513,13 @@ "en": "Last 30 days", "es": "Ultimos 30 dias", "fr": "30 derniers jours", + "hi": "पिछले 30 दिनों में", "ja": "過去30日間", + "ko": "지난 30 일", "nl": "Laatste 30 dagen", "pt": "Últimos 30 dias", "ru": "Последние 30 дней", + "zh-chs": "最近30天", "xloc": [ "default.handlebars->container->column_l->p40->3->1->p40time->9" ] @@ -9679,10 +13530,13 @@ "en": "Last 500", "es": "Ultimos 500", "fr": "500 dernières", + "hi": "अंतिम 500", "ja": "最後の500", + "ko": "마지막 500", "nl": "Laatste 500", "pt": "Últimos 500", "ru": "Последние 500", + "zh-chs": "最近500", "xloc": [ "default.handlebars->container->column_l->p16->3->1->0->5->p16limitdropdown->7", "default.handlebars->container->column_l->p3->3->1->0->3->p3limitdropdown->7", @@ -9696,10 +13550,13 @@ "en": "Last 60", "es": "Ultimos 60", "fr": "60 dernières", + "hi": "अंतिम 60", "ja": "最後の60", + "ko": "마지막 60", "nl": "Laatste 60", "pt": "Últimos 60", "ru": "Последние 60", + "zh-chs": "最近60", "xloc": [ "default.handlebars->container->column_l->p16->3->1->0->5->p16limitdropdown->1", "default.handlebars->container->column_l->p3->3->1->0->3->p3limitdropdown->1", @@ -9712,10 +13569,13 @@ "en": "Last 8 hours", "es": "Ultimas 8 horas", "fr": "8 dernières heures", + "hi": "पिछले 8 घंटे", "ja": "過去8時間", + "ko": "지난 8 시간", "nl": "Laatste 8 uur", "pt": "Últimas 8 horas", "ru": "Последние 8 часов", + "zh-chs": "最近8小時", "xloc": [ "default.handlebars->container->column_l->p40->3->1->p40time->3" ] @@ -9726,12 +13586,15 @@ "en": "Last Access", "es": "Ultimo acceso", "fr": "Dernier accès", + "hi": "अंतिम पहुंच", "ja": "最終アクセス", + "ko": "마지막 접근", "nl": "Laatste toegang", "pt": "Último acesso", "ru": "Последний доступ", + "zh-chs": "最後訪問", "xloc": [ - "default.handlebars->25->1205" + "default.handlebars->27->1335" ] }, { @@ -9740,12 +13603,15 @@ "en": "Last Login", "es": "Último acceso", "fr": "Dernière connexion", + "hi": "अंतिम लॉगइन", "ja": "前回のログイン", + "ko": "마지막 로그인", "nl": "Laatste inlog", "pt": "Último login", "ru": "Последний вход в систему", + "zh-chs": "上次登錄", "xloc": [ - "default.handlebars->25->1332" + "default.handlebars->27->1466" ] }, { @@ -9754,14 +13620,20 @@ "en": "Last agent address", "es": "Última dirección del agente", "fr": "Dernière adresse de l'agent", + "hi": "अंतिम एजेंट का पता", "ja": "最後のエージェントのアドレス", + "ko": "마지막 상담원 주소", "nl": "Laatste agentadres", "pt": "Último endereço do agente", "ru": "Последний адрес агента", + "zh-chs": "最後代理商地址", "xloc": [ - "default.handlebars->25->88", - "default.handlebars->25->89", - "default.handlebars->25->91" + "default.handlebars->27->70", + "default.handlebars->27->72", + "default.handlebars->27->74", + "default.handlebars->27->748", + "default.handlebars->27->749", + "default.handlebars->27->750" ] }, { @@ -9770,12 +13642,17 @@ "en": "Last agent connection", "es": "Última conexión del agente", "fr": "Dernière connexion de l'agent", + "hi": "अंतिम एजेंट कनेक्शन", "ja": "最後のエージェント接続", + "ko": "마지막 에이전트 연결", "nl": "Laatste agentverbinding", "pt": "Última conexão do agente", "ru": "Последнее подключение агента", + "zh-chs": "上次代理連接", "xloc": [ - "default.handlebars->25->87" + "default.handlebars->27->69", + "default.handlebars->27->745", + "default.handlebars->27->747" ] }, { @@ -9784,12 +13661,15 @@ "en": "Last changed: {0}", "es": "Última modificación: {0}", "fr": "Dernière modification: {0}", + "hi": "अंतिम परिवर्तित: {0}", "ja": "最終変更:{0}", + "ko": "마지막 변경 : {0}", "nl": "Laatst gewijzigd: {0}", "pt": "Última alteração: {0}", "ru": "Последнее изменение: {0}", + "zh-chs": "上次更改:{0}", "xloc": [ - "default.handlebars->25->1336" + "default.handlebars->27->1470" ] }, { @@ -9798,10 +13678,13 @@ "en": "Last day", "es": "Último día", "fr": "Dernier jour", + "hi": "आखरी दिन", "ja": "最終日", + "ko": "마지막 날", "nl": "Laatste dag", "pt": "Último dia", "ru": "Последний день", + "zh-chs": "最後一天", "xloc": [ "default.handlebars->container->column_l->p40->3->1->p40time->5" ] @@ -9812,12 +13695,15 @@ "en": "Last interfaces update", "es": "Última actualización de interfaces", "fr": "Dernière mise à jour des interfaces", + "hi": "अंतिम इंटरफेस अद्यतन", "ja": "最後のインターフェイスの更新", + "ko": "마지막 인터페이스 업데이트", "nl": "Laatste update van interfaces", "pt": "Última atualização de interfaces", "ru": "Последнее обновление интерфейсов", + "zh-chs": "最後接口更新", "xloc": [ - "default.handlebars->25->93" + "default.handlebars->27->76" ] }, { @@ -9825,12 +13711,16 @@ "de": "Letzte Anmeldung: {0}", "en": "Last login: {0}", "es": "Último acceso: {0}", + "fr": "Dernière connexion: {0}", + "hi": "अंतिम लॉगिन: {0}", "ja": "最終ログイン:{0}", + "ko": "마지막 로그인 : {0}", "nl": "Laatste inlog: {0}", "pt": "Último login: {0}", "ru": "Последний вход в систему: {0}", + "zh-chs": "上次登錄:{0}", "xloc": [ - "default.handlebars->25->1215" + "default.handlebars->27->1345" ] }, { @@ -9839,13 +13729,16 @@ "en": "Last seen:", "es": "Ultima vez visto:", "fr": "Dernière connexion:", + "hi": "अंतिम बार देखा गया:", "ja": "最後に見たのは:", + "ko": "마지막으로 본 :", "nl": "Laatst gezien", "pt": "Visto pela última vez:", "ru": "Последнее посещение:", + "zh-chs": "最後一次露面:", "xloc": [ - "default.handlebars->25->528", - "default.handlebars->25->83" + "default.handlebars->27->535", + "default.handlebars->27->65" ] }, { @@ -9854,10 +13747,13 @@ "en": "Last week", "es": "La semana pasada", "fr": "Dernière semaine", + "hi": "पिछले सप्ताह", "ja": "先週", + "ko": "지난주", "nl": "Vorige week", "pt": "Semana passada", "ru": "Последняя неделя", + "zh-chs": "上個星期", "xloc": [ "default.handlebars->container->column_l->p40->3->1->p40time->7" ] @@ -9868,9 +13764,13 @@ "en": "Latest", "es": "Última", "fr": "Dernier", + "hi": "नवीनतम", "ja": "最新", + "ko": "최근", "nl": "Laatste", + "pt": "Mais recentes", "ru": "Последний", + "zh-chs": "最新", "xloc": [ "default.handlebars->container->column_l->p42->p42tbl->1->0->6" ] @@ -9881,12 +13781,15 @@ "en": "Latest Version", "es": "Ultima versión", "fr": "Dernière version", + "hi": "नवीनतम संस्करण", "ja": "最新バージョン", + "ko": "최신 버전", "nl": "Laatste versie", "pt": "Última versão", "ru": "Последняя версия", + "zh-chs": "最新版本", "xloc": [ - "default.handlebars->25->111" + "default.handlebars->27->94" ] }, { @@ -9895,12 +13798,15 @@ "en": "Latin", "es": "Latin", "fr": "Latin", + "hi": "लैटिन", "ja": "ラテン", + "ko": "라틴어", "nl": "latijns", "pt": "Latim", "ru": "Латинский", + "zh-chs": "拉丁", "xloc": [ - "default.handlebars->25->829" + "default.handlebars->27->933" ] }, { @@ -9908,12 +13814,16 @@ "de": "Lettisch", "en": "Latvian", "es": "Letona", + "fr": "letton", + "hi": "लात्वीयावासी", "ja": "ラトビア", + "ko": "라트비아 사람", "nl": "Lets", "pt": "letão", "ru": "Латышский", + "zh-chs": "拉脫維亞語", "xloc": [ - "default.handlebars->25->830" + "default.handlebars->27->934" ] }, { @@ -9921,14 +13831,19 @@ "de": "Oberfläche mit Leiste links", "en": "Left bar interface", "es": "Interfaz de barra izquierda", + "fr": "Barre de gauche", + "hi": "लेफ्ट बार इंटरफ़ेस", "ja": "左バーインターフェイス", + "ko": "왼쪽 바 인터페이스", "nl": "Linkerbalk interface", "pt": "Interface da barra esquerda", "ru": "Панель инструментов слева", + "zh-chs": "左欄界面", "xloc": [ "agentinvite.handlebars->container->topbar->uiMenuButton->uiMenu", "default.handlebars->container->topbar->1->1->uiMenuButton->uiMenu", "error404.handlebars->container->topbar->uiMenuButton->uiMenu", + "invite.handlebars->container->topbar->uiMenuButton->uiMenu", "login.handlebars->container->topbar->uiMenuButton->uiMenu", "terms.handlebars->container->topbar->uiMenuButton->uiMenu" ] @@ -9939,12 +13854,29 @@ "en": "Less", "es": "Menos", "fr": "Moins", + "hi": "कम", "ja": "もっと少なく", + "ko": "적게", "nl": "Minder", "pt": "Menos", "ru": "Меньше", + "zh-chs": "減", "xloc": [ - "default.handlebars->25->1465" + "default.handlebars->27->1617" + ] + }, + { + "cs": "Omezit události", + "de": "Ereignisse begrenzen", + "en": "Limit Events", + "fr": "Limiter les événements", + "ja": "イベントを制限する", + "nl": "Beperk gebeurtenissen", + "ru": "Предельные события", + "zh-chs": "极限赛事", + "xloc": [ + "default.handlebars->27->553", + "default.handlebars->27->572" ] }, { @@ -9952,10 +13884,14 @@ "de": "Es können maximal 10 Dateien gleichzeitig hochgeladen werden.", "en": "Limit of 10 file uploads at the same time.", "es": "Límite de 10 cargas de archivos al mismo tiempo.", + "fr": "10 chargements maximum en même temps", + "hi": "एक ही समय में 10 फ़ाइल अपलोड की सीमा।", "ja": "同時にアップロードできるファイルの上限は10です。", + "ko": "동시에 10 파일 업로드 제한.", "nl": "Limiet van 10 bestandsuploads tegelijkertijd.", "pt": "Limite de 10 uploads de arquivos ao mesmo tempo.", "ru": "Ограничение загрузки 10 файлов одновременно.", + "zh-chs": "一次最多可上傳10個文件。", "xloc": [ "messenger.handlebars->13->4", "messenger.handlebars->13->5" @@ -9966,13 +13902,19 @@ "de": "Eingeschränkte Eingabe", "en": "Limited Input", "es": "Entrada limitada", + "fr": "Entrée limitée", + "hi": "सीमित इनपुट", "ja": "制限された入力", + "ko": "제한된 입력", "nl": "Beperkte invoer", "pt": "Entrada limitada", "ru": "Ограниченный ввод", + "zh-chs": "有限輸入", "xloc": [ - "default-mobile.handlebars->9->323", - "default.handlebars->25->1127" + "default-mobile.handlebars->9->327", + "default.handlebars->27->1240", + "default.handlebars->27->546", + "default.handlebars->27->565" ] }, { @@ -9980,13 +13922,17 @@ "de": "Nur eingeschränkte Eingabe", "en": "Limited Input Only", "es": "Solo Entrada limitada", + "fr": "Entrée limitée uniquement", + "hi": "लिमिटेड इनपुट केवल", "ja": "限定入力のみ", + "ko": "제한된 입력 만", "nl": "Alleen beperkte invoer", "pt": "Somente entrada limitada", "ru": "Ограничить элементы ввода", + "zh-chs": "僅限於輸入", "xloc": [ - "default-mobile.handlebars->9->298", - "default.handlebars->25->1097" + "default-mobile.handlebars->9->302", + "default.handlebars->27->1204" ] }, { @@ -9995,13 +13941,15 @@ "en": "Link", "es": "Enlace", "fr": "Lien", + "hi": "संपर्क", "ja": "リンク", + "ko": "링크", "nl": "Link", "pt": "Ligação", "ru": "Ссылка", + "zh-chs": "鏈接", "xloc": [ - "default-mobile.handlebars->9->68", - "default.handlebars->25->1158", + "default-mobile.handlebars->9->71", "default.handlebars->container->column_l->p42->p42tbl->1->0->4" ] }, @@ -10011,13 +13959,23 @@ "en": "Link Expiration", "es": "Vencimiento del enlace", "fr": "Expiration du lien", + "hi": "लिंक की समाप्ति", "ja": "リンクの有効期限", + "ko": "링크 만료", "nl": "Link vervaldatum", "pt": "Expiração do link", "ru": "Срок действия ссылки", + "zh-chs": "鏈接過期", "xloc": [ - "default.handlebars->25->291", - "default.handlebars->25->305" + "default.handlebars->27->278", + "default.handlebars->27->292" + ] + }, + { + "en": "Link invitation", + "nl": "Uitnodigingslink", + "xloc": [ + "default.handlebars->27->266" ] }, { @@ -10025,10 +13983,14 @@ "de": "Linux", "en": "Linux", "es": "Linux", + "fr": "Linux", + "hi": "लिनक्स", "ja": "Linux", + "ko": "리눅스", "nl": "Linux", "pt": "Linux", "ru": "Linux", + "zh-chs": "的Linux", "xloc": [ "agentinvite.handlebars->container->column_l->5->1->tlinuxtab", "agentinvite.handlebars->container->column_l->5->linuxtab->1" @@ -10039,12 +14001,16 @@ "de": "Linux / BSD", "en": "Linux / BSD", "es": "Linux / BSD", + "fr": "Linux / BSD", + "hi": "लिनक्स / बीएसडी", "ja": "Linux / BSD", + "ko": "리눅스 / BSD", "nl": "Linux / BSD", "pt": "Linux / BSD", "ru": "Linux / BSD", + "zh-chs": "Linux / BSD", "xloc": [ - "default.handlebars->25->316" + "default.handlebars->27->303" ] }, { @@ -10052,12 +14018,16 @@ "de": "Linux / BSD (Deinstallation)", "en": "Linux / BSD (UnInstall)", "es": "Linux / BSD (UnInstall)", + "fr": "Linux / BSD (désinstaller)", + "hi": "लिनक्स / BSD (UnInstall)", "ja": "Linux / BSD(アンインストール)", + "ko": "리눅스 / BSD (제거)", "nl": "Linux / BSD (de-installeren)", "pt": "Linux / BSD (desinstalação)", "ru": "Linux / BSD (Удаление)", + "zh-chs": "Linux / BSD(卸載)", "xloc": [ - "default.handlebars->25->319" + "default.handlebars->27->306" ] }, { @@ -10065,13 +14035,17 @@ "de": "Linux 32bit", "en": "Linux 32bit", "es": "Linux 32bit", + "fr": "Linux 32bit", + "hi": "लिनक्स 32 बिट", "ja": "Linux 32ビット", + "ko": "리눅스 32 비트", "nl": "Linux 32bit", "pt": "Linux 32 bits", "ru": "Linux 32bit", + "zh-chs": "Linux 32位", "xloc": [ - "default-mobile.handlebars->9->148", - "default.handlebars->25->18" + "default-mobile.handlebars->9->152", + "default.handlebars->27->18" ] }, { @@ -10079,13 +14053,17 @@ "de": "Linux 64bit", "en": "Linux 64bit", "es": "Linux 64bit", + "fr": "Linux 64bit", + "hi": "लिनक्स 64 बिट", "ja": "Linux 64ビット", + "ko": "리눅스 64 비트", "nl": "Linux 64bit", "pt": "Linux 64 bits", "ru": "Linux 64bit", + "zh-chs": "Linux 64位", "xloc": [ - "default-mobile.handlebars->9->149", - "default.handlebars->25->19" + "default-mobile.handlebars->9->153", + "default.handlebars->27->19" ] }, { @@ -10093,13 +14071,17 @@ "de": "Linux ARM", "en": "Linux ARM", "es": "Linux ARM", + "fr": "Linux ARM", + "hi": "लिनक्स एआरएम", "ja": "Linux ARM", + "ko": "리눅스 ARM", "nl": "Linux ARM", "pt": "Linux ARM", "ru": "Linux ARM", + "zh-chs": "Linux ARM", "xloc": [ - "default-mobile.handlebars->9->153", - "default.handlebars->25->23" + "default-mobile.handlebars->9->157", + "default.handlebars->27->23" ] }, { @@ -10107,12 +14089,16 @@ "de": "Linux ARM, Raspberry Pi (32bit)", "en": "Linux ARM, Raspberry Pi (32bit)", "es": "Linux ARM, Raspberry Pi (32bit)", + "fr": "Linux ARM, Raspberry Pi (32bit)", + "hi": "लिनक्स एआरएम, रास्पबेरी पाई (32 बिट)", "ja": "Linux ARM、Raspberry Pi(32ビット)", + "ko": "리눅스 ARM, 라즈베리 파이 (32 비트)", "nl": "Linux ARM, Raspberry Pi (32bit)", "pt": "Linux ARM, Raspberry Pi (32 bits)", "ru": "Linux ARM, Raspberry Pi (32bit)", + "zh-chs": "Linux ARM,Raspberry Pi(32位)", "xloc": [ - "default.handlebars->25->581" + "default.handlebars->27->629" ] }, { @@ -10120,13 +14106,17 @@ "de": "Linux NoKVM x86-32bit", "en": "Linux NoKVM x86-32bit", "es": "Linux NoKVM x86-32bit", + "fr": "Linux NoKVM x86-32bit", + "hi": "लिनक्स NoKVM x86-32bit", "ja": "Linux NoKVM x86-32bit", + "ko": "리눅스 NoKVM x86-32bit", "nl": "Linux NoKVM x86-32bit", "pt": "Linux NoKVM x86-32 bits", "ru": "Linux NoKVM x86-32bit", + "zh-chs": "Linux NoKVM x86-32位", "xloc": [ - "default-mobile.handlebars->9->162", - "default.handlebars->25->32" + "default-mobile.handlebars->9->166", + "default.handlebars->27->32" ] }, { @@ -10134,13 +14124,17 @@ "de": "Linux NoKVM x86-64bit", "en": "Linux NoKVM x86-64bit", "es": "Linux NoKVM x86-64bit", + "fr": "Linux NoKVM x86-64bit", + "hi": "लिनक्स NoKVM x86-64bit", "ja": "Linux NoKVM x86-64ビット", + "ko": "리눅스 NoKVM x86-64 비트", "nl": "Linux NoKVM x86-64bit", "pt": "Linux NoKVM x86-64 bits", "ru": "Linux NoKVM x86-64bit", + "zh-chs": "Linux NoKVM x86-64位", "xloc": [ - "default-mobile.handlebars->9->163", - "default.handlebars->25->33" + "default-mobile.handlebars->9->167", + "default.handlebars->27->33" ] }, { @@ -10148,13 +14142,17 @@ "de": "Linux Poky x86-32bit", "en": "Linux Poky x86-32bit", "es": "Linux Poky x86-32bit", + "fr": "Linux Poky x86-32bit", + "hi": "लिनक्स पोकी x86-32bit", "ja": "Linux Poky x86-32bit", + "ko": "리눅스 포키 x86-32 비트", "nl": "Linux Poky x86-32bit", "pt": "Linux Poky x86-32 bits", "ru": "Linux Poky x86-32bit", + "zh-chs": "Linux Poky x86-32位", "xloc": [ - "default-mobile.handlebars->9->158", - "default.handlebars->25->28" + "default-mobile.handlebars->9->162", + "default.handlebars->27->28" ] }, { @@ -10162,13 +14160,17 @@ "de": "Linux Poky x86-64bit", "en": "Linux Poky x86-64bit", "es": "Linux Poky x86-64bit", + "fr": "Linux Poky x86-64bit", + "hi": "लिनक्स पोकी x86-64bit", "ja": "Linux Poky x86-64bit", + "ko": "리눅스 포키 x86-64 비트", "nl": "Linux Poky x86-64bit", "pt": "Linux Poky x86-64 bits", "ru": "Linux Poky x86-64bit", + "zh-chs": "Linux Poky x86-64位", "xloc": [ - "default-mobile.handlebars->9->161", - "default.handlebars->25->31" + "default-mobile.handlebars->9->165", + "default.handlebars->27->31" ] }, { @@ -10176,12 +14178,16 @@ "de": "nur Linux", "en": "Linux only", "es": "Solo Linux", + "fr": "Linux seulement", + "hi": "केवल लिनक्स", "ja": "Linuxのみ", + "ko": "리눅스 만", "nl": "alleen Linux", "pt": "Apenas Linux", "ru": "Только Linux", + "zh-chs": "僅Linux", "xloc": [ - "default.handlebars->25->290" + "default.handlebars->27->277" ] }, { @@ -10189,12 +14195,16 @@ "de": "Linux x86 (32bit)", "en": "Linux x86 (32bit)", "es": "Linux x86 (32bit)", + "fr": "Linux x86 (32bit)", + "hi": "लिनक्स x86 (32 बिट)", "ja": "Linux x86(32ビット)", + "ko": "Linux x86 (32 비트)", "nl": "Linux x86 (32bit)", "pt": "Linux x86 (32 bits)", "ru": "Linux x86 (32bit)", + "zh-chs": "Linux x86(32位)", "xloc": [ - "default.handlebars->25->578" + "default.handlebars->27->626" ] }, { @@ -10202,12 +14212,16 @@ "de": "Linux x86 (64bit)", "en": "Linux x86 (64bit)", "es": "Linux x86 (64bit)", + "fr": "Linux x86 (64bit)", + "hi": "लिनक्स x86 (64 बिट)", "ja": "Linux x86(64ビット)", + "ko": "Linux x86 (64 비트)", "nl": "Linux x86 (64bit)", "pt": "Linux x86 (64 bits)", "ru": "Linux x86 (64bit)", + "zh-chs": "Linux x86(64位)", "xloc": [ - "default.handlebars->25->579" + "default.handlebars->27->627" ] }, { @@ -10216,10 +14230,13 @@ "en": "List", "es": "Lista", "fr": "Liste", + "hi": "सूची", "ja": "リスト", + "ko": "명부", "nl": "Lijst", "pt": "Lista", "ru": "Список", + "zh-chs": "清單", "xloc": [ "default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->9->devListToolbarView->viewselect->3", "default.handlebars->container->column_l->p1->p1title->devListToolbarViewIcons" @@ -10231,12 +14248,15 @@ "en": "Lithuanian", "es": "Lituano", "fr": "Lituanien", + "hi": "लिथुआनियाई", "ja": "リトアニア語", + "ko": "리투아니아 사람", "nl": "Litouws", "pt": "Lituano", "ru": "Литовский", + "zh-chs": "立陶宛語", "xloc": [ - "default.handlebars->25->831" + "default.handlebars->27->935" ] }, { @@ -10245,16 +14265,19 @@ "en": "Loading...", "es": "Cargando...", "fr": "Chargement...", + "hi": "लोड हो रहा है...", "ja": "読み込み中...", + "ko": "불러오는 중 ...", "nl": "Laden...", "pt": "Carregando...", "ru": "Загрузка...", + "zh-chs": "載入中...", "xloc": [ - "default-mobile.handlebars->9->31", - "default.handlebars->25->573", - "default.handlebars->25->709", - "default.handlebars->25->975", - "default.handlebars->25->977" + "default-mobile.handlebars->9->34", + "default.handlebars->27->1080", + "default.handlebars->27->1082", + "default.handlebars->27->620", + "default.handlebars->27->813" ] }, { @@ -10262,10 +14285,14 @@ "de": "Lokal", "en": "Local", "es": "Local", + "fr": "Local", + "hi": "स्थानीय", "ja": "地元", + "ko": "현지", "nl": "Lokaal", "pt": "Local", "ru": "Локальный", + "zh-chs": "本地", "xloc": [ "messenger.handlebars->localVideo->1" ] @@ -10275,10 +14302,14 @@ "de": "Lokale Tastaturbelegung", "en": "Local Keyboard Map", "es": "Mapa de teclado local", + "fr": "Carte du clavier local", + "hi": "स्थानीय कीबोर्ड मैप", "ja": "ローカルキーボードマップ", + "ko": "로컬 키보드 맵", "nl": "Lokale toetsenbordkaart", "pt": "Mapa do teclado local", "ru": "Раскладка локальной клавиатуры", + "zh-chs": "本地鍵盤圖", "xloc": [ "default.handlebars->container->dialog->dialogBody->dialog7->d7amtkvm->5->d7otherset->5" ] @@ -10288,10 +14319,14 @@ "de": "Lokale Datei hochladen", "en": "Local file upload", "es": "Carga local de archivos", + "fr": "Charger un fichier local", + "hi": "स्थानीय फ़ाइल अपलोड", "ja": "ローカルファイルのアップロード", + "ko": "로컬 파일 업로드", "nl": "Lokaal bestand uploaden", "pt": "Upload de arquivo local", "ru": "Локальная загрузка файлов", + "zh-chs": "本地文件上傳", "xloc": [ "default.handlebars->container->dialog->dialogBody->dialog3->d3upload->d3uploadMode->1" ] @@ -10301,12 +14336,16 @@ "de": "Lokalisierungseinstellungen", "en": "Localization Settings", "es": "Configuraciones de localización", + "fr": "Paramètres de localisation", + "hi": "स्थानीयकरण सेटिंग्स", "ja": "ローカリゼーション設定", + "ko": "현지화 설정", "nl": "Lokalisatie instellingen", "pt": "Configurações de localização", "ru": "Настройки локализации", + "zh-chs": "本地化設置", "xloc": [ - "default.handlebars->25->924", + "default.handlebars->27->1029", "default.handlebars->container->column_l->p2->p2AccountActions->3->5" ] }, @@ -10315,12 +14354,16 @@ "de": "Standort", "en": "Location", "es": "Ubicación", + "fr": "Localisation", + "hi": "स्थान", "ja": "ロケーション", + "ko": "위치", "nl": "Locatie", "pt": "Localização", "ru": "Местонахождение", + "zh-chs": "位置", "xloc": [ - "default.handlebars->25->507" + "default.handlebars->27->514" ] }, { @@ -10328,10 +14371,14 @@ "de": "Standortergebnis", "en": "Location Results", "es": "Resultados de ubicación", + "fr": "Résultats de localisation", + "hi": "स्थान परिणाम", "ja": "ロケーション結果", + "ko": "위치 결과", "nl": "Locatie resultaten", "pt": "Resultados da Localização", "ru": "Результаты местонахождения", + "zh-chs": "位置結果", "xloc": [ "default.handlebars->container->column_l->p1->xdevicesmap->xmapSearchResultsDlg->xmapSearchResultsBck->3" ] @@ -10342,12 +14389,15 @@ "en": "Lock Account", "es": "Bloquear cuenta", "fr": "Verrouiller le compte", + "hi": "खाता लॉक करें", "ja": "アカウントをロック", + "ko": "계정 잠금", "nl": "Account vergrendelen", "pt": "Bloquear conta", "ru": "Заблокировать учетную запись", + "zh-chs": "鎖定賬戶", "xloc": [ - "default.handlebars->25->1266" + "default.handlebars->27->1402" ] }, { @@ -10356,12 +14406,15 @@ "en": "Locked", "es": "Bloqueada", "fr": "Verrouiller", + "hi": "बंद", "ja": "ロック済み", + "ko": "잠김", "nl": "Vergrendeld", "pt": "Bloqueado", "ru": "Заблокирован", + "zh-chs": "已鎖定", "xloc": [ - "default.handlebars->25->1216" + "default.handlebars->27->1346" ] }, { @@ -10370,12 +14423,15 @@ "en": "Locked account", "es": "Cuenta bloqueada", "fr": "Compte verrouillé", + "hi": "बंद खाता", "ja": "ロックされたアカウント", + "ko": "잠긴 계정", "nl": "Vergrendeld account", "pt": "Conta bloqueada", "ru": "Заблокированная учетная запись", + "zh-chs": "賬戶鎖定", "xloc": [ - "default.handlebars->25->1317" + "default.handlebars->27->1451" ] }, { @@ -10383,12 +14439,16 @@ "de": "Ereignis eintragen", "en": "Log Event", "es": "Registro de Evento", + "fr": "Journal des évènements", + "hi": "लॉग इवेंट", "ja": "ログイベント", + "ko": "로그 이벤트", "nl": "Gebeurtenissenlog", "pt": "Log de Evento", "ru": "Добавить событие", + "zh-chs": "記錄事件", "xloc": [ - "default.handlebars->25->498" + "default.handlebars->27->505" ] }, { @@ -10396,10 +14456,14 @@ "de": "Anmelden", "en": "Log In", "es": "Iniciar sesión", + "fr": "Connexion", + "hi": "लॉग इन करें", "ja": "ログイン", + "ko": "로그인", "nl": "Inloggen", "pt": "Entrar", "ru": "Авторизация", + "zh-chs": "登錄", "xloc": [ "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->loginpanel->1->5->1", "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->loginpanel->1->7->1->4->3", @@ -10412,10 +14476,14 @@ "de": "Logarithmische Skala", "en": "Log-X", "es": "Log-X", + "fr": "Log-X", + "hi": "लॉग-X", "ja": "Log-X", + "ko": "로그 -X", "nl": "Log-X", "pt": "Log-X", "ru": "Log-X", + "zh-chs": "對數X", "xloc": [ "default.handlebars->container->column_l->p40->3->3->3" ] @@ -10425,10 +14493,14 @@ "de": "Anmeldung", "en": "Login", "es": "Iniciar sesión", + "fr": "Connexion", + "hi": "लॉग इन करें", "ja": "ログイン", + "ko": "로그인", "nl": "Inloggen", "pt": "Entrar", "ru": "Войти", + "zh-chs": "登錄", "xloc": [ "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->resettokenpanel->1->5->1->2->1->1", "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->tokenpanel->1->7->1->4->1->1", @@ -10437,7 +14509,17 @@ ] }, { + "cs": "Přihlásit se Shell", + "de": "Login Shell", "en": "Login Shell", + "fr": "Login Shell", + "hi": "लॉग इन शेल", + "ja": "ログインシェル", + "ko": "로그인 쉘", + "nl": "Login Shell", + "pt": "Shell de Login", + "ru": "Вход в оболочку", + "zh-chs": "登錄外殼", "xloc": [ "default.handlebars->termShellContextMenuLinux->cxtermps", "xterm.handlebars->termShellContextMenuLinux->cxtermps" @@ -10448,12 +14530,17 @@ "de": "Anmeldung fehlgeschlagen, Benutzername und Passwort prüfen.", "en": "Login failed, check username and password.", "es": "Error de inicio de sesión, verifique nombre de usuario y contraseña.", + "fr": "Erreur de connexion, vérifiez vos identifiants.", + "hi": "लॉगिन विफल, उपयोगकर्ता नाम और पासवर्ड की जाँच करें।", "ja": "ログインに失敗しました。ユーザー名とパスワードを確認してください。", + "ko": "로그인하지 못했습니다. 사용자 이름과 비밀번호를 확인하십시오.", "nl": "Inloggen mislukt, controleer gebruikersnaam en wachtwoord.", + "pt": "O login falhou, verifique o nome de usuário e a senha.", "ru": "Вход не выполнен, проверьте имя пользователя и пароль.", + "zh-chs": "登錄失敗,請檢查用戶名和密碼。", "xloc": [ - "login-mobile.handlebars->5->14", - "login.handlebars->5->14" + "login-mobile.handlebars->5->15", + "login.handlebars->5->15" ] }, { @@ -10461,10 +14548,14 @@ "de": "Anmelde-Token:", "en": "Login token:", "es": "Token de inicio de sesión:", + "fr": "Jeton de connexion:", + "hi": "लॉग इन टोकन:", "ja": "ログイントークン:", + "ko": "로그인 토큰 :", "nl": "Inlog token:", "pt": "Token de logon:", "ru": "Логин токен:", + "zh-chs": "登錄令牌:", "xloc": [ "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->resettokenpanel->1->5->1->0->1", "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->tokenpanel->1->7->1->0->1", @@ -10478,13 +14569,16 @@ "en": "Logout", "es": "Cerrar sesión", "fr": "Déconnexion", + "hi": "लॉग आउट", "ja": "ログアウト", + "ko": "로그 아웃", "nl": "Uitloggen", "pt": "Sair", "ru": "Выйти", + "zh-chs": "登出", "xloc": [ "default-mobile.handlebars->topMenu->logoutMenuOption->0->0", - "default.handlebars->25->45", + "default.handlebars->27->45", "terms.handlebars->3->2" ] }, @@ -10494,12 +14588,32 @@ "en": "Luxembourgish", "es": "Luxemburgués", "fr": "Luxembourgeois", + "hi": "लक्जमबर्गिश", "ja": "ルクセンブルク語", + "ko": "룩셈부르크 어", "nl": "Luxemburgs", "pt": "Luxemburguês", "ru": "Люксембургский", + "zh-chs": "盧森堡語", "xloc": [ - "default.handlebars->25->832" + "default.handlebars->27->936" + ] + }, + { + "cs": "Vrstva MAC", + "de": "MAC-Schicht", + "en": "MAC Layer", + "fr": "Couche MAC", + "hi": "मैक परत", + "ja": "MAC層", + "ko": "MAC 계층", + "nl": "MAC Laag", + "pt": "Camada MAC", + "ru": "MAC-уровень", + "zh-chs": "MAC層", + "xloc": [ + "default.handlebars->27->753", + "default.handlebars->27->755" ] }, { @@ -10508,12 +14622,48 @@ "en": "MAC address", "es": "Dirección MAC", "fr": "Adresse MAC", + "hi": "मैक पते", "ja": "Macアドレス", + "ko": "MAC 주소", "nl": "MAC adres", "pt": "Endereço MAC", "ru": "MAC адрес", + "zh-chs": "MAC地址", "xloc": [ - "default.handlebars->25->98" + "default.handlebars->27->81" + ] + }, + { + "cs": "MAC: {0}", + "de": "MAC: {0}", + "en": "MAC: {0}", + "es": "MAC: {0}", + "fr": "MAC: {0}", + "hi": "मैक: {0}", + "ja": "MAC:{0}", + "ko": "MAC : {0}", + "nl": "MAC: {0}", + "pt": "MAC: {0}", + "ru": "MAC: {0}", + "zh-chs": "MAC:{0}", + "xloc": [ + "default.handlebars->27->756" + ] + }, + { + "cs": "MAC: {0}, Gateway: {1}", + "de": "MAC: {0}, Gateway: {1}", + "en": "MAC: {0}, Gateway: {1}", + "fr": "MAC: {0}, passerelle: {1}", + "hi": "मैक: {0}, गेटवे: {1}", + "ja": "MAC:{0}、ゲートウェイ:{1}", + "ko": "MAC : {0}, 게이트웨이 : {1}", + "nl": "MAC: {0}, Gateway: {1}", + "pt": "MAC: {0}, Gateway: {1}", + "ru": "MAC: {0}, шлюз: {1}", + "zh-chs": "MAC:{0},網關:{1}", + "xloc": [ + "default.handlebars->27->754" ] }, { @@ -10521,13 +14671,17 @@ "de": "MIPS", "en": "MIPS", "es": "MIPS", + "fr": "MIPS", + "hi": "MIPS", "ja": "MIPS", + "ko": "MIPS", "nl": "MIPS", "pt": "MIPS", "ru": "MIPS", + "zh-chs": "MIPS", "xloc": [ - "default-mobile.handlebars->9->150", - "default.handlebars->25->20" + "default-mobile.handlebars->9->154", + "default.handlebars->27->20" ] }, { @@ -10536,13 +14690,16 @@ "en": "MPS Server", "es": "Servidor MPS", "fr": "Serveur MPS", + "hi": "MPS सर्वर", "ja": "MPSサーバー", + "ko": "MPS 서버", "nl": "MPS Server", "pt": "Servidor MPS", "ru": "MPS Сервер", + "zh-chs": "MPS服務器", "xloc": [ - "default.handlebars->25->273", - "default.handlebars->25->278" + "default.handlebars->27->257", + "default.handlebars->27->263" ] }, { @@ -10550,18 +14707,22 @@ "de": "MQTT", "en": "MQTT", "es": "MQTT", + "fr": "MQTT", + "hi": "MQTT", "ja": "MQTT", + "ko": "MQTT", "nl": "MQTT", "pt": "MQTT", "ru": "MQTT", + "zh-chs": "MQTT", "xloc": [ - "default-mobile.handlebars->9->125", - "default-mobile.handlebars->9->194", - "default.handlebars->25->192", - "default.handlebars->25->379", - "default.handlebars->25->491", - "default.handlebars->25->696", - "default.handlebars->25->697", + "default-mobile.handlebars->9->129", + "default-mobile.handlebars->9->198", + "default.handlebars->27->176", + "default.handlebars->27->369", + "default.handlebars->27->498", + "default.handlebars->27->797", + "default.handlebars->27->798", "default.handlebars->container->column_l->p15->consoleTable->1->6->1->1->1->0->p15outputselecttd->p15outputselect->3" ] }, @@ -10570,12 +14731,16 @@ "de": "MQTT-Zugangsdaten", "en": "MQTT Credentials", "es": "Credenciales MQTT", + "fr": "Certificats MQTT", + "hi": "MQTT क्रेडेंशियल", "ja": "MQTT資格情報", + "ko": "MQTT 신임 정보", "nl": "MQTT referenties", "pt": "Credenciais MQTT", "ru": "MQTT Учетные данные", + "zh-chs": "MQTT憑證", "xloc": [ - "default.handlebars->25->176" + "default.handlebars->27->159" ] }, { @@ -10583,12 +14748,16 @@ "de": "MQTT-Anmeldung", "en": "MQTT Login", "es": "Inicio de sesión MQTT", + "fr": "Connexion MQTT", + "hi": "MQTT लॉगिन करें", "ja": "MQTTログイン", + "ko": "MQTT 로그인", "nl": "MQTT Login", "pt": "Login do MQTT", "ru": "MQTT Вход", + "zh-chs": "MQTT登錄", "xloc": [ - "default.handlebars->25->519" + "default.handlebars->27->526" ] }, { @@ -10596,13 +14765,17 @@ "de": "MQTT-Kanal verbunden", "en": "MQTT channel connected", "es": "Canal MQTT conectado", + "fr": "Canal MQTT connecté", + "hi": "MQTT चैनल जुड़ा", "ja": "MQTTチャネルが接続されました", + "ko": "MQTT 채널 연결", "nl": "MQTT-kanaal verbonden", "pt": "Canal MQTT conectado", "ru": "Подключен MQTT канал", + "zh-chs": "MQTT通道已連接", "xloc": [ - "default-mobile.handlebars->9->203", - "default.handlebars->25->527" + "default-mobile.handlebars->9->207", + "default.handlebars->27->534" ] }, { @@ -10610,13 +14783,17 @@ "de": "MQTT verbunden", "en": "MQTT connected", "es": "MQTT conectado", + "fr": "MQTT connecté", + "hi": "MQTT जुड़े", "ja": "MQTT接続済み", + "ko": "MQTT 연결", "nl": "MQTT verbonden", "pt": "MQTT conectado", "ru": "Подключен MQTT", + "zh-chs": "MQTT已連接", "xloc": [ - "default.handlebars->25->157", - "default.handlebars->25->526" + "default.handlebars->27->140", + "default.handlebars->27->533" ] }, { @@ -10624,14 +14801,18 @@ "de": "MQTT-Verbindung zum Gerät ist aktiv.", "en": "MQTT connection to the device is active.", "es": "La conexión MQTT al dispositivo está activa.", + "fr": "La connection MQTT est active pour cet appareil.", + "hi": "डिवाइस के लिए MQTT कनेक्शन सक्रिय है।", "ja": "デバイスへのMQTT接続がアクティブです。", + "ko": "디바이스에 대한 MQTT 연결이 활성화되었습니다.", "nl": "MQTT verbinding met het apparaat is actief.", "pt": "A conexão MQTT com o dispositivo está ativa.", "ru": "MQTT подключение к устройству активно.", + "zh-chs": "與設備的MQTT連接已激活。", "xloc": [ - "default.handlebars->25->191", - "default.handlebars->25->378", - "default.handlebars->25->490" + "default.handlebars->27->175", + "default.handlebars->27->368", + "default.handlebars->27->497" ] }, { @@ -10639,12 +14820,16 @@ "de": "MQTT getrennt", "en": "MQTT disconnected", "es": "MQTT desconectado", + "fr": "MQTT déconnecté", + "hi": "MQTT डिस्कनेक्ट हो गया", "ja": "MQTTが切断されました", + "ko": "MQTT 연결이 끊어졌습니다", "nl": "MQTT verbroken", "pt": "MQTT desconectado", "ru": "MQTT отключено", + "zh-chs": "MQTT已斷開連接", "xloc": [ - "default.handlebars->25->161" + "default.handlebars->27->144" ] }, { @@ -10652,10 +14837,14 @@ "de": "MacOS", "en": "MacOS", "es": "MacOS", + "fr": "MacOS", + "hi": "मैक ओ एस", "ja": "マックOS", + "ko": "맥 OS", "nl": "MacOS", "pt": "MacOS", "ru": "MacOS", + "zh-chs": "蘋果系統", "xloc": [ "agentinvite.handlebars->container->column_l->5->1->tmacostab" ] @@ -10665,12 +14854,16 @@ "de": "MacOS (64bit)", "en": "MacOS (64bit)", "es": "MacOS (64bit)", + "fr": "MacOS (64bit)", + "hi": "MacOS (64 बिट)", "ja": "MacOS(64ビット)", + "ko": "맥 OS (64 비트)", "nl": "MacOS (64bit)", "pt": "MacOS (64 bits)", "ru": "MacOS (64bit)", + "zh-chs": "MacOS(64位)", "xloc": [ - "default.handlebars->25->580" + "default.handlebars->27->628" ] }, { @@ -10678,13 +14871,17 @@ "de": "MacOS 32bit", "en": "MacOS 32bit", "es": "MacOS 32bit", + "fr": "MacOS 32bit", + "hi": "MacOS 32 बिट", "ja": "MacOS 32ビット", + "ko": "맥 OS 32 비트", "nl": "MacOS 32bit", "pt": "MacOS 32 bits", "ru": "MacOS 32bit", + "zh-chs": "MacOS 32位", "xloc": [ - "default-mobile.handlebars->9->154", - "default.handlebars->25->24" + "default-mobile.handlebars->9->158", + "default.handlebars->27->24" ] }, { @@ -10692,13 +14889,17 @@ "de": "MacOS 64bit", "en": "MacOS 64bit", "es": "MacOS 64bit", + "fr": "MacOS 64bit", + "hi": "मैकओएस 64 बिट", "ja": "MacOS 64ビット", + "ko": "맥 OS 64 비트", "nl": "MacOS 64bit", "pt": "MacOS 64 bits", "ru": "MacOS 64bit", + "zh-chs": "MacOS 64位", "xloc": [ - "default-mobile.handlebars->9->159", - "default.handlebars->25->29" + "default-mobile.handlebars->9->163", + "default.handlebars->27->29" ] }, { @@ -10706,12 +14907,16 @@ "de": "Hauptserver-Nachrichten", "en": "Main Server Messages", "es": "Mensajes del Servidor Principal", + "fr": "Messages du serveur principal", + "hi": "मुख्य सर्वर संदेश", "ja": "メインサーバーメッセージ", + "ko": "메인 서버 메시지", "nl": "Hoofdserver berichten", "pt": "Mensagens do servidor principal", "ru": "Сообщения главного сервера", + "zh-chs": "主服務器消息", "xloc": [ - "default.handlebars->25->1442" + "default.handlebars->27->1589" ] }, { @@ -10719,36 +14924,48 @@ "de": "Malaiisch", "en": "Malay", "es": "Malayo", + "fr": "malais", + "hi": "मलायी", "ja": "マレー語", + "ko": "말레이 사람", "nl": "Maleis", "pt": "Malaio", "ru": "Малайский", + "zh-chs": "馬來語", "xloc": [ - "default.handlebars->25->834" + "default.handlebars->27->938" ] }, { "cs": "malajálamština", "de": "Malayalam", "en": "Malayalam", + "fr": "Malayalam", + "hi": "मलयालम", "ja": "マラヤーラム語", + "ko": "말라 얄 람어", "nl": "Malayalam", "pt": "Malaiala", "ru": "Малаяламский", + "zh-chs": "馬拉雅拉姆語", "xloc": [ - "default.handlebars->25->835" + "default.handlebars->27->939" ] }, { "cs": "maltština", "de": "Maltesisch", "en": "Maltese", + "fr": "Maltais", + "hi": "मोलतिज़", "ja": "マルタ語", + "ko": "몰티즈", "nl": "Maltese", "pt": "Maltês", "ru": "Мальтийский", + "zh-chs": "馬耳他語", "xloc": [ - "default.handlebars->25->836" + "default.handlebars->27->940" ] }, { @@ -10756,13 +14973,17 @@ "de": "Sicherungscodes verwalten", "en": "Manage Backup Codes", "es": "Administrar códigos de respaldo", + "fr": "Gérer les codes de récupérations", + "hi": "बैकअप कोड प्रबंधित करें", "ja": "バックアップコードの管理", + "ko": "백업 코드 관리", "nl": "Beheer back-up codes", "pt": "Gerenciar códigos de backup", "ru": "Управление резервными кодами", + "zh-chs": "管理備用碼", "xloc": [ "default-mobile.handlebars->9->29", - "default.handlebars->25->138" + "default.handlebars->27->121" ] }, { @@ -10770,15 +14991,19 @@ "de": "Gerätegruppen-Rechner verwalten", "en": "Manage Device Group Computers", "es": "Administrar equipos del grupo de dispositivos", + "fr": "Gérer les appareils du groupe", + "hi": "डिवाइस ग्रुप कंप्यूटर प्रबंधित करें", "ja": "デバイスグループコンピューターの管理", + "ko": "장치 그룹 컴퓨터 관리", "nl": "Beheer apparaatgroep computers", "pt": "Gerenciar computadores do grupo de dispositivos", "ru": "Управление компьютерами группы устройств", + "zh-chs": "管理設備組計算機", "xloc": [ - "default-mobile.handlebars->9->295", - "default-mobile.handlebars->9->313", - "default.handlebars->25->1094", - "default.handlebars->25->1117" + "default-mobile.handlebars->9->299", + "default-mobile.handlebars->9->317", + "default.handlebars->27->1201", + "default.handlebars->27->1229" ] }, { @@ -10786,15 +15011,32 @@ "de": "Gerätegruppen-Benutzer verwalten", "en": "Manage Device Group Users", "es": "Administrar usuarios del grupo de dispositivos", + "fr": "Gérer les utilisateurs du groupe d'appareils", + "hi": "डिवाइस समूह उपयोगकर्ताओं को प्रबंधित करें", "ja": "デバイスグループユーザーの管理", + "ko": "장치 그룹 사용자 관리", "nl": "Beheer apparaatgroep gebruikers", "pt": "Gerenciar usuários do grupo de dispositivos", "ru": "Управление пользователями группы устройств", + "zh-chs": "管理設備組用戶", "xloc": [ - "default-mobile.handlebars->9->294", - "default-mobile.handlebars->9->312", - "default.handlebars->25->1093", - "default.handlebars->25->1116" + "default-mobile.handlebars->9->298", + "default-mobile.handlebars->9->316", + "default.handlebars->27->1200", + "default.handlebars->27->1228" + ] + }, + { + "cs": "Správa zařízení", + "de": "Geräte verwalten", + "en": "Manage Devices", + "fr": "Gérer les appareils", + "ja": "デバイスを管理する", + "nl": "Beheer apparaten", + "ru": "Управление устройствами", + "zh-chs": "管理设备", + "xloc": [ + "default.handlebars->27->560" ] }, { @@ -10802,12 +15044,16 @@ "de": "Sicherheitsschlüssel verwalten", "en": "Manage Security Keys", "es": "Administrar claves de seguridad", + "fr": "Gérer les clés de sécurité", + "hi": "सुरक्षा कुंजी प्रबंधित करें", "ja": "セキュリティキーを管理する", + "ko": "보안 키 관리", "nl": "Beheer beveiligingssleutels", "pt": "Gerenciar chaves de segurança", "ru": "Управление ключами безопасности", + "zh-chs": "管理安全金鑰", "xloc": [ - "default.handlebars->25->145" + "default.handlebars->27->128" ] }, { @@ -10815,10 +15061,16 @@ "de": "Benutzergruppen verwalten", "en": "Manage User Groups", "es": "Administrar grupos de usuarios", + "fr": "Gérer les groupes d'utilisateurs", + "hi": "उपयोगकर्ता समूह प्रबंधित करें", + "ja": "ユーザーグループを管理する", + "ko": "사용자 그룹 관리", "nl": "Beheer gebruikersgroepen.", + "pt": "Gerenciar grupos de usuários", "ru": "Управление группами пользователя", + "zh-chs": "管理用戶組", "xloc": [ - "default.handlebars->25->1265" + "default.handlebars->27->1401" ] }, { @@ -10827,12 +15079,16 @@ "en": "Manage Users", "es": "Administrar usuarios", "fr": "Gérer les utilisateurs", + "hi": "उपयोगकर्ताओं को प्रबंधित करें", "ja": "ユーザーを管理する", + "ko": "사용자 관리", "nl": "Beheer gebruikers", "pt": "Gerenciar Usuários", "ru": "Управление пользователями", + "zh-chs": "管理用戶", "xloc": [ - "default.handlebars->25->1264" + "default.handlebars->27->1400", + "default.handlebars->27->559" ] }, { @@ -10840,10 +15096,14 @@ "de": "Authentifikator-App verwalten", "en": "Manage authenticator app", "es": "Administrar la aplicación de autenticación", + "fr": "Gérer la double authentification", + "hi": "प्रमाणक ऐप प्रबंधित करें", "ja": "認証アプリを管理する", + "ko": "인증 자 앱 관리", "nl": "Beheer authenticator-app", "pt": "Gerenciar aplicativo autenticador", "ru": "Управление приложением для проверки подлинности", + "zh-chs": "管理身份驗證器應用", "xloc": [ "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3AccountActions->3->manageAuthApp->0", "default.handlebars->container->column_l->p2->p2AccountSecurity->3->manageAuthApp->1->0" @@ -10854,24 +15114,49 @@ "de": "Sicherungscodes verwalten", "en": "Manage backup codes", "es": "Administrar códigos de respaldo", + "fr": "Gérer les codes de récupérations", + "hi": "बैकअप कोड प्रबंधित करें", "ja": "バックアップコードを管理する", + "ko": "백업 코드 관리", "nl": "Beheer back-up codes", "pt": "Gerenciar códigos de backup", "ru": "Управление резервными кодами", + "zh-chs": "管理備用碼", "xloc": [ "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3AccountActions->3->manageOtp->0", "default.handlebars->container->column_l->p2->p2AccountSecurity->3->manageOtp->1->0" ] }, + { + "cs": "Správa ověřování e-mailů", + "de": "E-Mail-Authentifizierung verwalten", + "en": "Manage email authentication", + "fr": "Gérer l'authentification des e-mails", + "hi": "ईमेल प्रमाणीकरण प्रबंधित करें", + "ja": "メール認証を管理する", + "ko": "이메일 인증 관리", + "nl": "Beheer e-mailverificatie", + "pt": "Gerenciar autenticação de email", + "ru": "Управление аутентификацией электронной почты", + "zh-chs": "管理電子郵件身份驗證", + "xloc": [ + "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3AccountActions->3->manageEmail2FA->0", + "default.handlebars->container->column_l->p2->p2AccountSecurity->3->manageEmail2FA->1->0" + ] + }, { "cs": "Spravovat klíče zabezpečení", "de": "Sicherheitsschlüssel verwalten", "en": "Manage security keys", "es": "Administrar claves de seguridad", + "fr": "Gérer les clés de sécurité", + "hi": "सुरक्षा कुंजी प्रबंधित करें", "ja": "セキュリティキーを管理する", + "ko": "보안 키 관리", "nl": "Beheer beveiligingssleutels", "pt": "Gerenciar chaves de segurança", "ru": "Управление ключами безопасности", + "zh-chs": "管理安全密鑰", "xloc": [ "default.handlebars->container->column_l->p2->p2AccountSecurity->3->manageHardwareOtp->1->0" ] @@ -10882,12 +15167,15 @@ "en": "Manage using a software agent", "es": "Administrar usando un agente de software", "fr": "Gérer à l'aide d'un agent logiciel", + "hi": "एक सॉफ्टवेयर एजेंट का उपयोग करके प्रबंधित करें", "ja": "ソフトウェアエージェントを使用して管理する", + "ko": "소프트웨어 에이전트를 사용하여 관리", "nl": "Beheer met behulp van een software-agent", "pt": "Gerenciar usando um agente de software", "ru": "Управление с помощью программного агента", + "zh-chs": "使用軟件代理進行管理", "xloc": [ - "default.handlebars->25->957" + "default.handlebars->27->1062" ] }, { @@ -10896,13 +15184,16 @@ "en": "Managed using a software agent", "es": "Administrar usando un agente de software", "fr": "Géré à l'aide d'un agent logiciel", + "hi": "एक सॉफ्टवेयर एजेंट का उपयोग कर प्रबंधित", "ja": "ソフトウェアエージェントを使用して管理", + "ko": "소프트웨어 에이전트를 사용하여 관리", "nl": "Beheerd met behulp van een software-agent", "pt": "Gerenciado usando um agente de software", "ru": "Управляется с помощью программного агента", + "zh-chs": "使用軟件代理進行管理", "xloc": [ - "default-mobile.handlebars->9->275", - "default.handlebars->25->981" + "default-mobile.handlebars->9->279", + "default.handlebars->27->1086" ] }, { @@ -10910,12 +15201,16 @@ "de": "Verwalter", "en": "Manager", "es": "Manager", + "fr": "Directeur", + "hi": "मैनेजर", "ja": "マネージャー", + "ko": "매니저", "nl": "Beheerder", "pt": "Gerenciador", "ru": "Менеджер", + "zh-chs": "經理", "xloc": [ - "default.handlebars->25->1221" + "default.handlebars->27->1351" ] }, { @@ -10924,12 +15219,15 @@ "en": "Manual Certificate", "es": "Certificado Manual", "fr": "Certificat manuel", + "hi": "मैनुअल प्रमाण पत्र", "ja": "手動証明書", + "ko": "수동 증명서", "nl": "Handmatig certificaat", "pt": "Certificado manual", "ru": "Ручной Сертификат", + "zh-chs": "手動證書", "xloc": [ - "default.handlebars->25->260" + "default.handlebars->27->244" ] }, { @@ -10938,24 +15236,31 @@ "en": "Manual Username/Password", "es": "Nombre de usuario / contraseña manual", "fr": "Nom d'utilisateur / mot de passe manuel", + "hi": "मैनुअल उपयोगकर्ता नाम / पासवर्ड", "ja": "手動ユーザー名/パスワード", + "ko": "수동 사용자 이름 / 비밀번호", "nl": "Handmatige gebruikersnaam/wachtwoord", "pt": "Nome de usuário / senha manual", "ru": "Ручной Имя пользователя/Пароль", + "zh-chs": "手動用戶名/密碼", "xloc": [ - "default.handlebars->25->259" + "default.handlebars->27->243" ] }, { "cs": "maorština", "de": "Maori", "en": "Maori", + "fr": "Maori", + "hi": "माओरी", "ja": "マオリ", + "ko": "마오리족", "nl": "Maori", "pt": "Maori", "ru": "Маори", + "zh-chs": "毛利人", "xloc": [ - "default.handlebars->25->837" + "default.handlebars->27->941" ] }, { @@ -10964,10 +15269,13 @@ "en": "Map", "es": "Mapa", "fr": "Carte", + "hi": "नक्शा", "ja": "地図", + "ko": "지도", "nl": "Kaart", "pt": "Mapa", "ru": "Карта", + "zh-chs": "地圖", "xloc": [ "default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->9->devListToolbarView->viewselect->viewselectmapoption", "default.handlebars->container->column_l->p1->p1title->devListToolbarViewIcons" @@ -10978,12 +15286,15 @@ "de": "Marathi", "en": "Marathi", "fr": "Marathi", + "hi": "मराठी", "ja": "マラーティー語", + "ko": "마라 티어", "nl": "Marathi", "pt": "Marathi", "ru": "Маратхи", + "zh-chs": "馬拉地語", "xloc": [ - "default.handlebars->25->838" + "default.handlebars->27->942" ] }, { @@ -10991,10 +15302,16 @@ "de": "Maximale Sitzungen erreicht", "en": "Max Sessions Reached", "es": "Sesiones máximas alcanzadas", + "fr": "Nombre de sessions maximum atteint", + "hi": "अधिकतम सत्रों में पहुंचे", + "ja": "最大セッション数に達しました", + "ko": "최대 세션 수", "nl": "Max Sessies bereikt", + "pt": "Número máximo de sessões atingidas", "ru": "Достигнуто максимальное число сессий", + "zh-chs": "達到的會話數上限", "xloc": [ - "default.handlebars->25->1406" + "default.handlebars->27->1553" ] }, { @@ -11003,13 +15320,16 @@ "en": "Maximum length of {0}", "es": "Longitud Máxima de {0}", "fr": "Longueur maximale de {0}", + "hi": "{0} की अधिकतम लंबाई", "ja": "{0}の最大長", + "ko": "{0}의 최대 길이", "nl": "Maximale lengte van {0}", "pt": "Comprimento máximo de {0}", "ru": "Максимальная длина {0}", + "zh-chs": "最大長度為{0}", "xloc": [ - "login-mobile.handlebars->5->29", - "login.handlebars->5->29" + "login-mobile.handlebars->5->32", + "login.handlebars->5->32" ] }, { @@ -11018,10 +15338,13 @@ "en": "Medium", "es": "Medio", "fr": "Moyen", + "hi": "मध्यम", "ja": "中", + "ko": "매질", "nl": "Gemiddeld", "pt": "Médio", "ru": "Средний", + "zh-chs": "介質", "xloc": [ "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->7->d7framelimiter->3", "default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->9->devListToolbarSize->sizeselect->3", @@ -11034,12 +15357,15 @@ "en": "Megabytes", "es": "Megabytes", "fr": "Mégaoctets", + "hi": "मेगाबाइट", "ja": "メガバイト", + "ko": "메가 바이트", "nl": "Megabytes", "pt": "Megabytes", "ru": "Мегабайт", + "zh-chs": "兆字節", "xloc": [ - "default.handlebars->25->1432" + "default.handlebars->27->1579" ] }, { @@ -11048,13 +15374,16 @@ "en": "Memory", "es": "Memoria", "fr": "Mémoire", + "hi": "स्मृति", "ja": "記憶", + "ko": "기억", "nl": "Geheugen", "pt": "Memória", "ru": "ОЗУ", + "zh-chs": "記憶", "xloc": [ - "default.handlebars->25->1423", - "default.handlebars->25->75", + "default.handlebars->27->1570", + "default.handlebars->27->790", "default.handlebars->container->column_l->p40->3->1->p40type->3" ] }, @@ -11063,19 +15392,25 @@ "de": "Mesh Agent", "en": "Mesh Agent", "es": "Agente Mesh", + "fr": "Mesh Agent", + "hi": "मेष एजेंट", "ja": "メッシュエージェント", + "ko": "메시 에이전트", "nl": "Mesh Agent", "pt": "Mesh Agent", "ru": "Mesh Agent", + "zh-chs": "網格代理", "xloc": [ - "default-mobile.handlebars->9->200", - "default.handlebars->25->325", - "default.handlebars->25->328", - "default.handlebars->25->336", - "default.handlebars->25->339", - "default.handlebars->25->342", - "default.handlebars->25->452", - "default.handlebars->25->483" + "default-mobile.handlebars->9->204", + "default.handlebars->27->312", + "default.handlebars->27->316", + "default.handlebars->27->325", + "default.handlebars->27->329", + "default.handlebars->27->332", + "default.handlebars->27->459", + "default.handlebars->27->490", + "default.handlebars->27->744", + "default.handlebars->27->751" ] }, { @@ -11083,25 +15418,34 @@ "de": "Mesh-Agent-Konsole", "en": "Mesh Agent Console", "es": "Consola del agente Mesh", + "fr": "Console d'agent de maillage", + "hi": "मेष एजेंट कंसोल", "ja": "メッシュエージェントコンソール", + "ko": "메시 에이전트 콘솔", "nl": "Mesh Agent Console", "pt": "Mesh Agent Console", "ru": "Консоль Mesh Agent", + "zh-chs": "網格代理控制台", "xloc": [ - "default-mobile.handlebars->9->302", - "default.handlebars->25->1101" + "default-mobile.handlebars->9->306", + "default.handlebars->27->1209" ] }, { "cs": "Mesh předávání (relay)", + "de": "Netzrelais", "en": "Mesh Relay", "es": "Relé de Mesh", + "fr": "Relais Mesh", + "hi": "मेष रिले", "ja": "メッシュリレー", + "ko": "메시 릴레이", "nl": "Mesh Relay", "pt": "Mesh Relay", "ru": "Ретранслятор Mesh", + "zh-chs": "網狀中繼", "xloc": [ - "default.handlebars->25->489" + "default.handlebars->27->496" ] }, { @@ -11109,14 +15453,18 @@ "de": "Mesh Agent ist verbunden und bereit.", "en": "Mesh agent is connected and ready for use.", "es": "El agente Mesh está conectado y listo para usar.", + "fr": "L'agent est connecté et prêt à être utilisé.", + "hi": "मेष एजेंट जुड़ा हुआ है और उपयोग के लिए तैयार है।", "ja": "メッシュエージェントが接続され、使用できる状態になりました。", + "ko": "메시 에이전트가 연결되어 사용할 준비가되었습니다.", "nl": "Mesh-agent is verbonden en klaar voor gebruik.", "pt": "O agente de malha está conectado e pronto para uso.", "ru": "Mesh Agent подключен и готов к использованию.", + "zh-chs": "已連接網狀代理並準備使用。", "xloc": [ - "default.handlebars->25->183", - "default.handlebars->25->370", - "default.handlebars->25->482" + "default.handlebars->27->167", + "default.handlebars->27->360", + "default.handlebars->27->489" ] }, { @@ -11124,24 +15472,36 @@ "de": "Mesh Agent ist erreichbar mittels eines anderen Agenten als Vermittler.", "en": "Mesh agent is reachable using another agent as relay.", "es": "Se puede acceder al agente Mesh utilizando otro agente como relé.", + "fr": "L'agent de maillage est accessible en utilisant un autre agent comme relais.", + "hi": "मेष एजेंट रिले के रूप में एक अन्य एजेंट का उपयोग कर उपलब्ध है।", "ja": "メッシュエージェントは、別のエージェントをリレーとして使用して到達可能です。", + "ko": "메시 에이전트는 다른 에이전트를 릴레이로 사용하여 연결할 수 있습니다.", "nl": "Mesh-agent is bereikbaar met een andere agent als relay.", "pt": "O agente de malha é alcançável usando outro agente como retransmissão.", "ru": "Mesh Agent доступен с использованием другого агента в качестве ретранслятора.", + "zh-chs": "使用其他代理作為中繼可以訪問網狀代理。", "xloc": [ - "default.handlebars->25->189", - "default.handlebars->25->376", - "default.handlebars->25->488" + "default.handlebars->27->173", + "default.handlebars->27->366", + "default.handlebars->27->495" ] }, { + "cs": "MeshAction (.txt)", + "de": "MeshAction (.txt)", "en": "MeshAction (.txt)", "es": "MeshAction (.txt)", + "fr": "MeshAction (.txt)", + "hi": "MeshAction (.txt)", + "ja": "MeshAction (.txt)", + "ko": "MeshAction (.txt)", "nl": "MeshAction (.txt)", + "pt": "MeshAction (.txt)", "ru": "MeshAction (.txt)", + "zh-chs": "MeshAction(.txt)", "xloc": [ - "default.handlebars->25->587", - "default.handlebars->25->589" + "default.handlebars->27->635", + "default.handlebars->27->637" ] }, { @@ -11149,11 +15509,16 @@ "de": "Mesh-Agent-Datenverkehr", "en": "MeshAgent traffic", "es": "Tráfico MeshAgent", + "fr": "Trafic MeshAgent", + "hi": "MeshAgent यातायात", "ja": "MeshAgentトラフィック", + "ko": "MeshAgent 트래픽", "nl": "MeshAgent verkeer", + "pt": "Tráfego MeshAgent", "ru": "Трафик MeshAgent", + "zh-chs": "MeshAgent流量", "xloc": [ - "default.handlebars->25->1444" + "default.handlebars->27->1591" ] }, { @@ -11161,11 +15526,16 @@ "de": "Mesh-Agent-Aktualisierung", "en": "MeshAgent update", "es": "Actualización de MeshAgent", + "fr": "Mise à jour de l'agent", + "hi": "MeshAgent अपडेट", "ja": "MeshAgentの更新", + "ko": "MeshAgent 업데이트", "nl": "MeshAgent update", + "pt": "Atualização do MeshAgent", "ru": "Обновление MeshAgent", + "zh-chs": "MeshAgent更新", "xloc": [ - "default.handlebars->25->1445" + "default.handlebars->27->1592" ] }, { @@ -11173,10 +15543,14 @@ "de": "MeshCentral-Desktop", "en": "MeshCentral Desktop", "es": "Escritorio MeshCentral", + "fr": "Bureau MeshCentral", + "hi": "मेश्चरल डेस्कटॉप", "ja": "MeshCentralデスクトップ", + "ko": "MeshCentral 데스크탑", "nl": "MeshCentral Desktop", "pt": "MeshCentral Desktop", "ru": "Рабочий стол MeshCentral", + "zh-chs": "MeshCentral桌面", "xloc": [ "player.handlebars->3->12" ] @@ -11186,12 +15560,16 @@ "de": "MeshCentral-Fehler", "en": "MeshCentral Errors", "es": "Errores MeshCentral ", + "fr": "Erreurs MeshCentral", + "hi": "मेश्चरल एरर्स", "ja": "MeshCentralエラー", + "ko": "MeshCentral 오류", "nl": "MeshCentral fouten", "pt": "MeshCentral Errors", "ru": "Ошибки MeshCentral", + "zh-chs": "網格中心錯誤", "xloc": [ - "default.handlebars->25->976" + "default.handlebars->27->1081" ] }, { @@ -11199,12 +15577,16 @@ "de": "MeshCentral Router", "en": "MeshCentral Router", "es": "Router MeshCentral ", + "fr": "Routeur MeshCentral", + "hi": "मेश्चरल राउटर", "ja": "MeshCentralルーター", + "ko": "MeshCentral 라우터", "nl": "MeshCentral Router", "pt": "MeshCentral Router", "ru": "MeshCentral Router ", + "zh-chs": "MeshCentral路由器", "xloc": [ - "default.handlebars->25->575" + "default.handlebars->27->623" ] }, { @@ -11212,12 +15594,16 @@ "de": "MeshCentral Router ist ein Windows-Werkzeug für die TCP-Portweiterleitung. Sie können beispielsweise über diesen Server in ein Remote-Gerät per RDP erreichen.", "en": "MeshCentral Router is a Windows tool for TCP port mapping. You can, for example, RDP into a remote device thru this server.", "es": "MeshCentral Router es una herramienta de Windows para la asignación de puertos TCP. Puede, por ejemplo, RDP en un dispositivo remoto a través de este servidor.", + "fr": "MeshCentral Router est un utilitaire Windows de redirection de port TCP. Vous pouvez vous connecter à un bureau distant à travers ce serveur.", + "hi": "टीएस पोर्ट पोर्ट मैपिंग के लिए मेश्वाइंट्रल राउटर एक विंडोज टूल है। आप, उदाहरण के लिए, RDP इस सर्वर के माध्यम से एक दूरस्थ डिवाइस में कर सकते हैं।", "ja": "MeshCentralルーターは、TCPポートマッピング用のWindowsツールです。たとえば、このサーバーを介してRDPをリモートデバイスに接続できます。", + "ko": "MeshCentral Router는 TCP 포트 매핑을위한 Windows 도구입니다. 예를 들어이 서버를 통해 원격 장치로 RDP를 수행 할 수 있습니다.", "nl": "MeshCentral Router is een Windows tool voor het toewijzen van TCP poorten. U kunt RDP bijvoorbeeld via deze server naar een extern apparaat sturen.", "pt": "O MeshCentral Router é uma ferramenta do Windows para mapeamento de portas TCP. Você pode, por exemplo, RDP em um dispositivo remoto através deste servidor.", "ru": "MeshCentral Router это инструмент Windows для сопоставления портов TCP. Например, через этот сервер можно установить подключение по RDP к удаленному устройству.", + "zh-chs": "MeshCentral Router是Windows工具,用於TCP端口映射。例如,您可以通過該服務器將RDP放入遠程設備。", "xloc": [ - "default.handlebars->25->574" + "default.handlebars->27->621" ] }, { @@ -11225,13 +15611,17 @@ "de": "MeshCentral-Serverfehler", "en": "MeshCentral Server Errors", "es": "Errores del servidor MeshCentral", + "fr": "Erreurs du serveur MeshCentral", + "hi": "मेश्चरल सर्वर एरर्स", "ja": "MeshCentralサーバーエラー", + "ko": "MeshCentral 서버 오류", "nl": "MeshCentral serverfouten", "pt": "Erros do servidor MeshCentral", "ru": "Ошибки сервера MeshCentral", + "zh-chs": "MeshCentral服務器錯誤", "xloc": [ - "default.handlebars->25->115", - "default.handlebars->25->117" + "default.handlebars->27->100", + "default.handlebars->27->98" ] }, { @@ -11239,12 +15629,16 @@ "de": "MeshCentral-Serverpeering", "en": "MeshCentral Server Peering", "es": "Servidor MeshCentral Peering", + "fr": "Homologation du serveur MeshCentral", + "hi": "मेश्चरल सर्वर पेअरिंग", "ja": "MeshCentralサーバーピアリング", + "ko": "MeshCentral 서버 피어링", "nl": "MeshCentral Server Peering", "pt": "Peering do servidor MeshCentral", "ru": "Соединения сервера MeshCentral", + "zh-chs": "MeshCentral服務器對等", "xloc": [ - "default.handlebars->25->1443" + "default.handlebars->27->1590" ] }, { @@ -11252,10 +15646,14 @@ "de": "MeshCentral-Terminal", "en": "MeshCentral Terminal", "es": "Terminal MeshCentral", + "fr": "Terminal MeshCentral", + "hi": "मेश्चरल टर्मिनल", "ja": "MeshCentralターミナル", + "ko": "MeshCentral 터미널", "nl": "MeshCentral Terminal", "pt": "MeshCentral Terminal", "ru": "Терминал MeshCentral", + "zh-chs": "網狀中央終端", "xloc": [ "player.handlebars->3->11" ] @@ -11265,14 +15663,18 @@ "de": "MeshCentral-Version", "en": "MeshCentral Version", "es": "Version MeshCentral", + "fr": "Version de MeshCentral", + "hi": "मेश्चरल संस्करण", "ja": "MeshCentralバージョン", + "ko": "MeshCentral 버전", "nl": "MeshCentral Versie", "pt": "Versão MeshCentral", "ru": "Версия MeshCentral", + "zh-chs": "MeshCentral版本", "xloc": [ - "default.handlebars->25->112", - "default.handlebars->25->113", - "default.handlebars->25->974" + "default.handlebars->27->1079", + "default.handlebars->27->95", + "default.handlebars->27->96" ] }, { @@ -11280,76 +15682,136 @@ "de": "MeshCmd", "en": "MeshCmd", "es": "MeshCmd", + "fr": "MeshCmd", + "hi": "MeshCmd", "ja": "MeshCmd", + "ko": "MeshCmd", "nl": "MeshCmd", "pt": "MeshCmd", "ru": "MeshCmd", + "zh-chs": "網格命令", "xloc": [ - "default.handlebars->25->207", - "default.handlebars->25->585" + "default.handlebars->27->191", + "default.handlebars->27->633" ] }, { + "cs": "MeshCmd (Linux ARM, 32bit)", + "de": "MeshCmd (Linux ARM, 32bit)", "en": "MeshCmd (Linux ARM, 32bit)", "es": "MeshCmd (Linux ARM, 32bit)", + "fr": "MeshCmd (Linux ARM, 32bit)", + "hi": "मेश्डम (लिनक्स एआरएम, 32 बिट)", + "ja": "MeshCmd(Linux ARM、32ビット)", + "ko": "MeshCmd (Linux ARM, 32 비트)", "nl": "MeshCmd (Linux ARM, 32bit)", + "pt": "MeshCmd (Linux ARM, 32 bits)", "ru": "MeshCmd (Linux ARM, 32bit)", + "zh-chs": "MeshCmd(Linux ARM,32位)", "xloc": [ - "default.handlebars->25->597" + "default.handlebars->27->645" ] }, { + "cs": "MeshCmd (Linux x86, 32bit)", + "de": "MeshCmd (Linux x86, 32bit)", "en": "MeshCmd (Linux x86, 32bit)", "es": "MeshCmd (Linux x86, 32bit)", + "fr": "MeshCmd (Linux x86, 32bit)", + "hi": "मेश्डम (लिनक्स x86, 32 बिट)", + "ja": "MeshCmd(Linux x86、32ビット)", + "ko": "MeshCmd (Linux x86, 32 비트)", "nl": "MeshCmd (Linux x86, 32bit)", + "pt": "MeshCmd (Linux x86, 32bit)", "ru": "MeshCmd (Linux x86, 32bit)", + "zh-chs": "MeshCmd(Linux x86,32bit)", "xloc": [ - "default.handlebars->25->594" + "default.handlebars->27->642" ] }, { + "cs": "MeshCmd (Linux x86, 64bit)", + "de": "MeshCmd (Linux x86, 64bit)", "en": "MeshCmd (Linux x86, 64bit)", "es": "MeshCmd (Linux x86, 64bit)", + "fr": "MeshCmd (Linux x86, 64bit)", + "hi": "मेशकैम (लिनक्स x86, 64 बिट)", + "ja": "MeshCmd(Linux x86、64ビット)", + "ko": "MeshCmd (Linux x86, 64 비트)", "nl": "MeshCmd (Linux x86, 64bit)", + "pt": "MeshCmd (Linux x86, 64bit)", "ru": "MeshCmd (Linux x86, 64bit)", + "zh-chs": "MeshCmd(Linux x86,64bit)", "xloc": [ - "default.handlebars->25->595" + "default.handlebars->27->643" ] }, { + "cs": "MeshCmd (MacOS, 64bit)", + "de": "MeshCmd (MacOS, 64bit)", "en": "MeshCmd (MacOS, 64bit)", "es": "MeshCmd (MacOS, 64bit)", + "fr": "MeshCmd (MacOS, 64bit)", + "hi": "मेशकैम (मैकओएस, 64 बिट)", + "ja": "MeshCmd(MacOS、64ビット)", + "ko": "MeshCmd (MacOS, 64 비트)", "nl": "MeshCmd (MacOS, 64bit)", + "pt": "MeshCmd (MacOS, 64bit)", "ru": "MeshCmd (MacOS, 64bit)", + "zh-chs": "MeshCmd(MacOS,64位)", "xloc": [ - "default.handlebars->25->596" + "default.handlebars->27->644" ] }, { + "cs": "MeshCmd (spustitelný soubor Win32)", + "de": "MeshCmd (ausführbare Win32-Datei)", "en": "MeshCmd (Win32 executable)", "es": "MeshCmd (Win32 ejecutable)", + "fr": "MeshCmd (exécutable Win32)", + "hi": "MeshCmd (Win32 निष्पादन योग्य)", + "ja": "MeshCmd(Win32実行可能ファイル)", + "ko": "MeshCmd (Win32 실행 파일)", "nl": "MeshCmd (Win32 executable)", + "pt": "MeshCmd (executável Win32)", "ru": "MeshCmd (приложение Win32)", + "zh-chs": "MeshCmd(Win32可執行文件)", "xloc": [ - "default.handlebars->25->592" + "default.handlebars->27->640" ] }, { + "cs": "MeshCmd (spustitelný soubor Win64)", + "de": "MeshCmd (ausführbare Win64-Datei)", "en": "MeshCmd (Win64 executable)", "es": "MeshCmd (Win64 ejecutable)", + "fr": "MeshCmd (exécutable Win64)", + "hi": "MeshCmd (Win64 निष्पादन योग्य)", + "ja": "MeshCmd(Win64実行可能ファイル)", + "ko": "MeshCmd (Win64 실행 파일)", "nl": "MeshCmd (Win64 executable)", + "pt": "MeshCmd (executável Win64)", "ru": "MeshCmd (приложение Win64)", + "zh-chs": "MeshCmd(Win64可執行文件)", "xloc": [ - "default.handlebars->25->593" + "default.handlebars->27->641" ] }, { + "cs": "MeshCmd je nástroj příkazového řádku, který provádí mnoho různých operací. Soubor akcí lze volitelně stáhnout a upravit, aby poskytoval informace o serveru a přihlašovací údaje.", + "de": "MeshCmd ist ein Befehlszeilenprogramm, das viele verschiedene Vorgänge ausführt. Die Aktionsdatei kann optional heruntergeladen und bearbeitet werden, um Serverinformationen und Anmeldeinformationen bereitzustellen.", "en": "MeshCmd is a command line tool that performs lots of different operations. The action file can optionally be downloaded and edited to provide server information and credentials.", "es": "MeshCmd es una herramienta de línea de comandos que realiza muchas operaciones diferentes. El archivo de acción se puede descargar y editar opcionalmente para proporcionar información del servidor y credenciales.", + "fr": "MeshCmd est un outil en ligne de commande permettant de réaliser différentes opérations. Le fichier d'actions peut être téléchargé et édité pour fournir des informations sur le serveur.", + "hi": "MeshCmd एक कमांड लाइन टूल है जो बहुत सारे विभिन्न ऑपरेशन करता है। सर्वर जानकारी और क्रेडेंशियल्स प्रदान करने के लिए एक्शन फ़ाइल को वैकल्पिक रूप से डाउनलोड और संपादित किया जा सकता है।", + "ja": "MeshCmdは、さまざまな操作を実行するコマンドラインツールです。オプションで、アクションファイルをダウンロードおよび編集して、サーバー情報と資格情報を提供できます。", + "ko": "MeshCmd는 다양한 작업을 수행하는 명령 줄 도구입니다. 서버 파일 및 신임 정보를 제공하기 위해 조치 파일을 선택적으로 다운로드하고 편집 할 수 있습니다.", "nl": "MeshCmd is een opdrachtregelprogramma dat veel verschillende bewerkingen uitvoert. Het actiebestand is optioneel, en kan worden gedownload en bewerkt om serverinformatie en referenties te verstrekken.", + "pt": "MeshCmd é uma ferramenta de linha de comando que executa várias operações diferentes. Opcionalmente, o arquivo de ação pode ser baixado e editado para fornecer informações e credenciais do servidor.", "ru": "MeshCmd это утилита с командной строкой, которая позволяет выполнить множество операций. Файл с командами может быть опционально скачан и отредактирован для указания информации о сервере и учетных данных.", + "zh-chs": "MeshCmd是執行許多不同操作的命令行工具。可以選擇下載和編輯操作文件以提供服務器信息和憑據。", "xloc": [ - "default.handlebars->25->582" + "default.handlebars->27->630" ] }, { @@ -11357,12 +15819,16 @@ "de": "MeshCommander-Script", "en": "MeshCommander Script", "es": "Script de MeshCommander ", + "fr": "Script MeshCommander", + "hi": "MeshCommander स्क्रिप्ट", "ja": "MeshCommanderスクリプト", + "ko": "MeshCommander 스크립트", "nl": "MeshCommander Script", "pt": "MeshCommander Script", "ru": "MeshCommander Script", + "zh-chs": "MeshCommander腳本", "xloc": [ - "default.handlebars->25->258" + "default.handlebars->27->242" ] }, { @@ -11370,10 +15836,14 @@ "de": "MeshMessenger", "en": "MeshMessenger", "es": "MeshMessenger", + "fr": "MeshMessenger", + "hi": "MeshMessenger", "ja": "MeshMessenger", + "ko": "메시 메신저", "nl": "MeshMessenger", "pt": "MeshMessenger", "ru": "MeshMessenger", + "zh-chs": "網格信使", "xloc": [ "messenger.handlebars->13->1", "messenger.handlebars->13->2", @@ -11382,14 +15852,20 @@ }, { "cs": "MeshServerRootCert.cer", + "de": "MeshServerRootCert.cer", "en": "MeshServerRootCert.cer", "es": "MeshServerRootCert.cer", + "fr": "MeshServerRootCert.cer", + "hi": "MeshServerRootCert.cer", "ja": "MeshServerRootCert.cer", + "ko": "MeshServerRootCert.cer", "nl": "MeshServerRootCert.cer", "pt": "MeshServerRootCert.cer", "ru": "MeshServerRootCert.cer", + "zh-chs": "MeshServerRootCert.cer", "xloc": [ - "default.handlebars->25->269" + "default.handlebars->27->253", + "default.handlebars->27->260" ] }, { @@ -11397,13 +15873,17 @@ "de": "Nachricht", "en": "Message", "es": "Mensaje", + "fr": "Message", + "hi": "संदेश", "ja": "メッセージ", + "ko": "메시지", "nl": "Bericht", "pt": "Mensagem", "ru": "Сообщение", + "zh-chs": "信息", "xloc": [ - "default.handlebars->25->302", - "default.handlebars->25->554" + "default.handlebars->27->289", + "default.handlebars->27->601" ] }, { @@ -11411,12 +15891,42 @@ "de": "Nachrichten-Verteiler", "en": "Message Dispatcher", "es": "Despachador de mensajes", + "fr": "Répartiteur de messages", + "hi": "संदेश डिस्पैचर", "ja": "メッセージディスパッチャー", + "ko": "메시지 디스패처", "nl": "Bericht Dispatcher", "pt": "Despachante de mensagens", "ru": "Диспетчер сообщения", + "zh-chs": "郵件調度程序", "xloc": [ - "default.handlebars->25->1441" + "default.handlebars->27->1588" + ] + }, + { + "cs": "Zpráva:", + "de": "Botschaft:", + "en": "Message:", + "fr": "Message:", + "nl": "Bericht:", + "ja": "メッセージ:", + "ru": "Сообщение:", + "zh-chs": "信息:", + "xloc": [ + "mesh-invite.html->2->7->1" + ] + }, + { + "cs": "Zpráva: [[[MSG]]]", + "de": "Nachricht: [[[MSG]]]", + "en": "Message: [[[MSG]]]", + "nl": "Bericht: [[[MSG]]]", + "fr": "Message: [[[MSG]]]", + "ja": "メッセージ:[[[MSG]]]", + "ru": "Сообщение: [[[MSG]]]", + "zh-chs": "讯息:[[[MSG]]]", + "xloc": [ + "mesh-invite.txt" ] }, { @@ -11424,10 +15934,14 @@ "de": "Microsoft™ Windows 32bit", "en": "Microsoft™ Windows 32bit", "es": "Microsoft™ Windows 32bits", + "fr": "Microsoft™ Windows 32bit", + "hi": "Microsoft ™ विंडोज 32 बिट", "ja": "Microsoft™Windows 32ビット", + "ko": "Microsoft ™ Windows 32 비트", "nl": "Microsoft™ Windows 32bit", "pt": "Microsoft™ Windows 32 bits", "ru": "Microsoft™ Windows 32-разрядная", + "zh-chs": "Microsoft™Windows 32位", "xloc": [ "agentinvite.handlebars->container->column_l->5->wintab32->1" ] @@ -11437,10 +15951,14 @@ "de": "Microsoft™ Windows 64bit", "en": "Microsoft™ Windows 64bit", "es": "Microsoft™ Windows 64bits", + "fr": "Microsoft™ Windows 64bit", + "hi": "Microsoft ™ विंडोज 64 बिट", "ja": "Microsoft™Windows 64ビット", + "ko": "Microsoft ™ Windows 64 비트", "nl": "Microsoft™ Windows 64bit", "pt": "Microsoft™ Windows 64 bits", "ru": "Microsoft™ Windows 64-разрядная", + "zh-chs": "Microsoft™Windows 64位", "xloc": [ "agentinvite.handlebars->container->column_l->5->wintab64->1" ] @@ -11450,13 +15968,17 @@ "de": "Mindestlänge von {0}", "en": "Minimum length of {0}", "es": "Longitud mínima de {0}", + "fr": "Longueur minimale de {0}", + "hi": "{0} की न्यूनतम लंबाई", "ja": "最小長{0}", + "ko": "최소 길이 {0}", "nl": "Minimale lengte van {0}", "pt": "Comprimento mínimo de {0}", "ru": "Минимальная длина {0}", + "zh-chs": "最小長度為{0}", "xloc": [ - "login-mobile.handlebars->5->28", - "login.handlebars->5->28" + "login-mobile.handlebars->5->31", + "login.handlebars->5->31" ] }, { @@ -11464,24 +15986,32 @@ "de": "Knotenstandort ändern", "en": "Modify node location", "es": "Modificar ubicación del nodo", + "fr": "Modifier la localisation du noeud", + "hi": "नोड स्थान संशोधित करें", "ja": "ノードの場所を変更する", + "ko": "노드 위치 수정", "nl": "Wijzig knooppuntlocatie", "pt": "Modificar localização do nó", "ru": "Изменить позицию узла", + "zh-chs": "修改節點位置", "xloc": [ - "default.handlebars->25->415" + "default.handlebars->27->419" ] }, { "cs": "moldavština", "de": "Moldawisch", "en": "Moldavian", + "fr": "Moldave", + "hi": "मोलदावियन", "ja": "モルダビア", + "ko": "몰다비아 사람", "nl": "Moldavisch ", "pt": "Moldavian", "ru": "Молдавский", + "zh-chs": "摩爾達維亞人", "xloc": [ - "default.handlebars->25->839" + "default.handlebars->27->943" ] }, { @@ -11490,12 +16020,15 @@ "en": "More", "es": "Mas", "fr": "Plus", + "hi": "अधिक", "ja": "もっと", + "ko": "더", "nl": "Meer", "pt": "Mais", "ru": "Еще", + "zh-chs": "更多", "xloc": [ - "default.handlebars->25->1464" + "default.handlebars->27->1616" ] }, { @@ -11504,12 +16037,15 @@ "en": "Motherboard", "es": "Motherboard", "fr": "Carte mère", + "hi": "मदरबोर्ड", "ja": "マザーボード", + "ko": "마더 보드", "nl": "Moederbord", "pt": "Placa-mãe", "ru": "Материнская плата", + "zh-chs": "母板", "xloc": [ - "default.handlebars->25->69" + "default.handlebars->27->786" ] }, { @@ -11517,12 +16053,16 @@ "de": "Dieses Gerät in eine andere Gerätegruppe verschieben", "en": "Move this device to a different device group", "es": "Mover este dispositivo a un grupo de dispositivos diferente", + "fr": "Déplacer l'appareil dans un autre groupe", + "hi": "इस डिवाइस को एक अलग डिवाइस ग्रुप में ले जाएं", "ja": "このデバイスを別のデバイスグループに移動する", + "ko": "이 장치를 다른 장치 그룹으로 이동", "nl": "Verplaats dit apparaat naar een andere apparaatgroep", "pt": "Mova este dispositivo para um grupo de dispositivos diferente", "ru": "Переместить это устройство в другую группу устройств", + "zh-chs": "將此設備移到其他設備組", "xloc": [ - "default.handlebars->25->500" + "default.handlebars->27->507" ] }, { @@ -11531,12 +16071,15 @@ "en": "Move to device group", "es": "Mover al grupo de dispositivos", "fr": "Déplacer vers un groupe d'appareils", + "hi": "डिवाइस समूह पर जाएं", "ja": "デバイスグループに移動", + "ko": "장치 그룹으로 이동", "nl": "Verplaatsen naar apparaatgroep", "pt": "Mover para o grupo de dispositivos", "ru": "Переместить в группу устройств", + "zh-chs": "移至設備組", "xloc": [ - "default.handlebars->25->391" + "default.handlebars->27->382" ] }, { @@ -11545,10 +16088,13 @@ "en": "Multi-Desktop", "es": "Multi-escritorio", "fr": "Multi-bureau", + "hi": "बहु डेस्कटॉप", "ja": "マルチデスクトップ", + "ko": "다중 데스크탑", "nl": "Multi Desktop", "pt": "Multi-Desktop", "ru": "Многоэкранный", + "zh-chs": "多桌面", "xloc": [ "default.handlebars->contextMenu->cxmdesktop" ] @@ -11559,10 +16105,13 @@ "en": "My Account", "es": "Mi cuenta", "fr": "Mon Compte", + "hi": "मेरा खाता", "ja": "マイアカウント", + "ko": "내 계정", "nl": "Mijn Account", "pt": "Minha conta", "ru": "Моя учетная запись", + "zh-chs": "我的帳戶", "xloc": [ "default-mobile.handlebars->topMenu->3", "default.handlebars->container->column_l->p2->p2title->0", @@ -11575,11 +16124,14 @@ "de": "Meine Geräte", "en": "My Devices", "es": "Mis dispositivos", - "fr": "Mes Appareils", + "fr": "Mes appareils", + "hi": "मेरे उपकरण", "ja": "私のデバイス", + "ko": "내 장치", "nl": "Mijn apparaten", "pt": "Meus dispositivos", "ru": "Мои устройства", + "zh-chs": "我的裝置", "xloc": [ "default.handlebars->container->column_l->p1->p1title->2->0", "default.handlebars->container->page_leftbar", @@ -11592,10 +16144,13 @@ "en": "My Events", "es": "Mis eventos", "fr": "Mes Événements", + "hi": "मेरी घटनाएँ", "ja": "私のイベント", + "ko": "내 이벤트", "nl": "Mijn gebeurtenissen", "pt": "Meus Eventos", "ru": "Мои события", + "zh-chs": "我的活動", "xloc": [ "default.handlebars->container->column_l->p3->p3title->0", "default.handlebars->container->page_leftbar", @@ -11607,11 +16162,14 @@ "de": "Meine Dateien", "en": "My Files", "es": "Mis Archivos", - "fr": "Mes Dossiers", + "fr": "Mes Dossiers et Fichiers", + "hi": "मेरी फ़ाइलें", "ja": "私のファイル", + "ko": "내 서류들", "nl": "Mijn bestanden", "pt": "Meus arquivos", "ru": "Мои файлы", + "zh-chs": "我的文件", "xloc": [ "default-mobile.handlebars->container->page_content->column_l->p5->1->1->0->5->1->1", "default-mobile.handlebars->topMenu->1", @@ -11626,10 +16184,13 @@ "en": "My Server", "es": "Mi Servidor", "fr": "Mon Serveur", + "hi": "मेरा सर्वर", "ja": "私のサーバー", + "ko": "내 서버", "nl": "Mijn server", "pt": "Meu servidor", "ru": "Мой сервер", + "zh-chs": "我的服務器", "xloc": [ "default.handlebars->container->column_l->p6->p6title->3", "default.handlebars->container->page_leftbar", @@ -11642,12 +16203,15 @@ "en": "My Server Console", "es": "Mi Server Console", "fr": "Console de mon serveur", + "hi": "मेरा सर्वर कंसोल", "ja": "私のサーバーコンソール", + "ko": "내 서버 콘솔", "nl": "Mijn server console", "pt": "Console do meu servidor", "ru": "Консоль моего сервера", + "zh-chs": "我的服務器控制台", "xloc": [ - "default.handlebars->25->691" + "default.handlebars->27->792" ] }, { @@ -11655,10 +16219,14 @@ "de": "Meine Server-Plugins", "en": "My Server Plugins", "es": "Mis Plugins de Server ", - "fr": "Mes plugins serveur", + "fr": "Mes modules complémentaires", + "hi": "मेरा सर्वर प्लगइन्स", "ja": "私のサーバープラグイン", + "ko": "내 서버 플러그인", "nl": "Mijn serverplug-ins", + "pt": "Meus plugins de servidor", "ru": "Плагины моего сервера", + "zh-chs": "我的服務器插件", "xloc": [ "default.handlebars->container->column_l->p42->1" ] @@ -11668,10 +16236,14 @@ "de": "Meine Server-Plugins -", "en": "My Server Plugins -", "es": "Mis Plugins de Server -", - "fr": "Mes plugins serveur -", + "fr": "Mes modules complémentaires -", + "hi": "मेरा सर्वर प्लगइन्स -", "ja": "私のサーバープラグイン-", + "ko": "내 서버 플러그인-", "nl": "Mijn serverplug-ins -", + "pt": "Meus plugins de servidor -", "ru": "Плагины моего сервера - ", + "zh-chs": "我的服務器插件-", "xloc": [ "default.handlebars->container->column_l->p43->3" ] @@ -11682,10 +16254,13 @@ "en": "My Server Stats", "es": "Estadisticas del Server", "fr": "Statistiques de mon serveur", + "hi": "मेरा सर्वर आँकड़े", "ja": "私のサーバー統計", + "ko": "내 서버 통계", "nl": "Mijn serverstatistieken", "pt": "Estatísticas do meu servidor", "ru": "Статистика моего сервера", + "zh-chs": "我的服務器統計", "xloc": [ "default.handlebars->container->column_l->p40->p40title->0" ] @@ -11696,10 +16271,13 @@ "en": "My Server Tracing", "es": "Mi Seguimiento al Servidor", "fr": "Suivi de mon serveur", + "hi": "मेरा सर्वर ट्रेसिंग", "ja": "私のサーバートレース", + "ko": "내 서버 추적", "nl": "Mijn server traceren", "pt": "Rastreio do meu servidor", "ru": "Трассировка моего сервера", + "zh-chs": "我的服務器跟踪", "xloc": [ "default.handlebars->container->column_l->p41->p41title->0" ] @@ -11709,8 +16287,14 @@ "de": "Meine Benutzergruppen", "en": "My User Groups", "es": "Mis grupos de usuarios", + "fr": "Mes groupes utilisateurs", + "hi": "मेरे उपयोगकर्ता समूह", + "ja": "私のユーザーグループ", + "ko": "내 사용자 그룹", "nl": "Mijn gebruikersgroepen", + "pt": "Meus grupos de usuários", "ru": "Мои группы пользователей", + "zh-chs": "我的用戶組", "xloc": [ "default.handlebars->container->column_l->p50->p50title->0" ] @@ -11721,10 +16305,13 @@ "en": "My Users", "es": "Mis usuarios", "fr": "Mes Utilisateurs", + "hi": "मेरे उपयोगकर्ता", "ja": "私のユーザー", + "ko": "내 사용자", "nl": "Mijn gebruikers", "pt": "Meus usuários", "ru": "Мои пользователи", + "zh-chs": "我的用戶", "xloc": [ "default.handlebars->container->column_l->p4->p4title->0", "default.handlebars->container->page_leftbar", @@ -11737,13 +16324,16 @@ "en": "MyKey", "es": "Mi Llave", "fr": "MaClé", + "hi": "मेरी कुँजी", "ja": "私の鍵", + "ko": "마이키", "nl": "Mijn sleutel", "pt": "Minha chave", "ru": "Мой ключ", + "zh-chs": "我的鑰匙", "xloc": [ - "default.handlebars->25->714", - "default.handlebars->25->717" + "default.handlebars->27->818", + "default.handlebars->27->821" ] }, { @@ -11752,29 +16342,33 @@ "en": "Name", "es": "Nombre", "fr": "Nom", + "hi": "नाम", "ja": "名", + "ko": "이름", "nl": "Naam", "pt": "Nome", "ru": "Имя", + "zh-chs": "名稱", "xloc": [ - "default-mobile.handlebars->9->135", - "default-mobile.handlebars->9->276", - "default-mobile.handlebars->9->289", - "default-mobile.handlebars->9->56", + "default-mobile.handlebars->9->139", + "default-mobile.handlebars->9->280", + "default-mobile.handlebars->9->293", + "default-mobile.handlebars->9->59", "default-mobile.handlebars->container->page_content->column_l->p10->p10desktop->deskarea3->deskarea3x->DeskTools->5->1->1", - "default.handlebars->25->1066", - "default.handlebars->25->1203", - "default.handlebars->25->1271", - "default.handlebars->25->1275", - "default.handlebars->25->1280", - "default.handlebars->25->1282", - "default.handlebars->25->1305", - "default.handlebars->25->618", - "default.handlebars->25->71", - "default.handlebars->25->80", - "default.handlebars->25->94", - "default.handlebars->25->955", - "default.handlebars->25->982", + "default.handlebars->27->1060", + "default.handlebars->27->1087", + "default.handlebars->27->1170", + "default.handlebars->27->1333", + "default.handlebars->27->1407", + "default.handlebars->27->1411", + "default.handlebars->27->1416", + "default.handlebars->27->1418", + "default.handlebars->27->1438", + "default.handlebars->27->450", + "default.handlebars->27->667", + "default.handlebars->27->740", + "default.handlebars->27->77", + "default.handlebars->27->782", "default.handlebars->container->column_l->p11->deskarea0->deskarea3x->DeskTools->deskToolsArea->DeskToolsProcessTab->deskToolsHeader->3", "default.handlebars->container->column_l->p11->deskarea0->deskarea3x->DeskTools->deskToolsArea->DeskToolsServiceTab->deskToolsServiceHeader->3", "default.handlebars->container->column_l->p42->p42tbl->1->0->2" @@ -11786,12 +16380,15 @@ "en": "Name (optional)", "es": "Nombre (opcional)", "fr": "Nom: (optionnel)", + "hi": "नाम: (वैकल्पिक)", "ja": "名前(オプション)", + "ko": "이름 (선택 사항)", "nl": "Naam (Optioneel)", "pt": "Nome (Opcional)", "ru": "Имя (не обязательно)", + "zh-chs": "名稱(可選)", "xloc": [ - "default.handlebars->25->282" + "default.handlebars->27->269" ] }, { @@ -11800,12 +16397,15 @@ "en": "Name1, Name2, Name3", "es": "Nombre1, Nombre2, Nombre3", "fr": "Nom1, Nom2, Nom3", + "hi": "Name1, Name2, Name3", "ja": "Name1、Name2、Name3", + "ko": "이름 1, 이름 2, 이름 3", "nl": "Naam1, Naam2, Naam3", "pt": "Nome1, Nome2, Nome3", "ru": "Имя1, Имя2, Имя3", + "zh-chs": "名稱1,名稱2,名稱3", "xloc": [ - "default.handlebars->25->1257" + "default.handlebars->27->1392" ] }, { @@ -11813,12 +16413,15 @@ "de": "Navajo", "en": "Navajo", "fr": "Navajo", + "hi": "नावाजो", "ja": "ナバホ", + "ko": "나바호", "nl": "Navajo", "pt": "Navajo", "ru": "Навахо", + "zh-chs": "納瓦霍人", "xloc": [ - "default.handlebars->25->840" + "default.handlebars->27->944" ] }, { @@ -11826,12 +16429,15 @@ "de": "Ndonga", "en": "Ndonga", "fr": "Ndonga", + "hi": "डोन्गा", "ja": "ンドンガ", + "ko": "은동가", "nl": "Ndonga", "pt": "Ndonga", "ru": "Ндонга", + "zh-chs": "恩東加", "xloc": [ - "default.handlebars->25->841" + "default.handlebars->27->945" ] }, { @@ -11839,12 +16445,15 @@ "de": "Nepali", "en": "Nepali", "fr": "Népalais", + "hi": "नेपाली", "ja": "ネパール語", + "ko": "네팔어", "nl": "Nepalees", "pt": "Nepali", "ru": "Непальский", + "zh-chs": "尼泊爾文", "xloc": [ - "default.handlebars->25->842" + "default.handlebars->27->946" ] }, { @@ -11853,12 +16462,15 @@ "en": "Network Interfaces", "es": "Interfaces de red", "fr": "Interfaces réseau", + "hi": "नेटवर्क इंटरफेस", "ja": "ネットワークインターフェース", + "ko": "네트워크 인터페이스", "nl": "Netwerk Interfaces", "pt": "Interfaces de rede", "ru": "Сетевые интерфейсы", + "zh-chs": "網絡接口", "xloc": [ - "default.handlebars->25->572" + "default.handlebars->27->619" ] }, { @@ -11867,12 +16479,31 @@ "en": "Network Router", "es": "Enrutador de red", "fr": "Routeur réseau", + "hi": "नेटवर्क राउटर", "ja": "ネットワークルーター", + "ko": "네트워크 라우터", "nl": "Netwerk Router", "pt": "Roteador de rede", "ru": "Network Router", + "zh-chs": "網絡路由器", "xloc": [ - "default.handlebars->25->591" + "default.handlebars->27->639" + ] + }, + { + "cs": "Sítě", + "de": "Vernetzung", + "en": "Networking", + "fr": "La mise en réseau", + "hi": "नेटवर्किंग", + "ja": "ネットワーキング", + "ko": "네트워킹", + "nl": "Netwerken", + "pt": "Trabalho em rede", + "ru": "сетей", + "zh-chs": "聯網", + "xloc": [ + "default.handlebars->27->761" ] }, { @@ -11881,10 +16512,13 @@ "en": "New", "es": "Nuevo", "fr": "Nouveau", + "hi": "नया", "ja": "新しい", + "ko": "새로운", "nl": "Nieuw", "pt": "Novo", "ru": "Создать", + "zh-chs": "新", "xloc": [ "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3createMeshLink1->1", "default.handlebars->container->column_l->p2->p2createMeshLink1->1" @@ -11896,10 +16530,13 @@ "en": "New Account...", "es": "Nueva cuenta...", "fr": "Nouveau Compte...", + "hi": "नया खाता...", "ja": "新しいアカウント...", + "ko": "새 계정 ...", "nl": "Nieuw account...", "pt": "Nova conta...", "ru": "Создать учетную запись...", + "zh-chs": "新賬戶...", "xloc": [ "default.handlebars->container->column_l->p4->3->1->0->3->3" ] @@ -11910,15 +16547,18 @@ "en": "New Device Group", "es": "Nuevo grupo de dispositivos", "fr": "Nouveau Group", + "hi": "नया डिवाइस ग्रुप", "ja": "新しいデバイスグループ", + "ko": "새로운 장치 그룹", "nl": "Nieuwe apparaatgroep", "pt": "Novo grupo de dispositivos", "ru": "Новая группа устройств", + "zh-chs": "新設備組", "xloc": [ - "default-mobile.handlebars->9->50", - "default.handlebars->25->564", - "default.handlebars->25->948", - "default.handlebars->25->960" + "default-mobile.handlebars->9->53", + "default.handlebars->27->1053", + "default.handlebars->27->1065", + "default.handlebars->27->611" ] }, { @@ -11927,15 +16567,18 @@ "en": "New Folder", "es": "Nueva carpeta", "fr": "Nouveau Dossier", + "hi": "नया फोल्डर", "ja": "新しいフォルダ", + "ko": "새 폴더", "nl": "Nieuwe map", "pt": "Nova pasta", "ru": "Новая папка", + "zh-chs": "新建文件夾", "xloc": [ - "default-mobile.handlebars->9->247", - "default-mobile.handlebars->9->79", - "default.handlebars->25->1176", - "default.handlebars->25->655", + "default-mobile.handlebars->9->251", + "default-mobile.handlebars->9->82", + "default.handlebars->27->1306", + "default.handlebars->27->704", "default.handlebars->container->column_l->p13->p13toolbar->1->2->1->3", "default.handlebars->container->column_l->p5->p5toolbar->1->0->p5filehead->3" ] @@ -11945,8 +16588,14 @@ "de": "Neue Gruppe...", "en": "New Group...", "es": "Nuevo grupo...", + "fr": "Nouveau groupe ...", + "hi": "नया समूह...", + "ja": "新しい集団...", + "ko": "새 그룹 ...", "nl": "Nieuwe Groep...", + "pt": "Novo grupo...", "ru": "Новая группа...", + "zh-chs": "新組...", "xloc": [ "default.handlebars->container->column_l->p50->3->1->0->3->3" ] @@ -11957,10 +16606,13 @@ "en": "New Tokens", "es": "Nuevo Token", "fr": "Nouveaux Jetons", + "hi": "नए स्तन", "ja": "新しいトークン", + "ko": "새로운 토큰", "nl": "Nieuw token", "pt": "Novos tokens", "ru": "Новые токены", + "zh-chs": "新代幣", "xloc": [ "default-mobile.handlebars->9->27" ] @@ -11971,15 +16623,34 @@ "en": "New password:", "es": "Nueva contraseña:", "fr": "Nouveau mot de passe:", + "hi": "नया पासवर्ड:", "ja": "新しいパスワード:", + "ko": "새 비밀번호:", "nl": "Nieuw wachtwoord:", "pt": "Nova senha:", "ru": "Новый пароль:", + "zh-chs": "新密碼:", "xloc": [ - "default-mobile.handlebars->9->45", - "default-mobile.handlebars->9->46", - "default.handlebars->25->943", - "default.handlebars->25->944" + "default-mobile.handlebars->9->48", + "default-mobile.handlebars->9->49", + "default.handlebars->27->1048", + "default.handlebars->27->1049" + ] + }, + { + "cs": "Žádné AMT", + "de": "Kein AMT", + "en": "No AMT", + "es": "Sin AMT", + "fr": "Pas d'appareil AMT", + "ja": "AMTなし", + "nl": "Geen AMT", + "pt": "Nenhum AMT", + "ru": "Нет AMT", + "zh-chs": "没有AMT", + "xloc": [ + "default.handlebars->27->545", + "default.handlebars->27->564" ] }, { @@ -11987,13 +16658,30 @@ "de": "Keine aktiven Token", "en": "No Active Tokens", "es": "No hay tokens activos", + "fr": "Aucun jeton actif", + "hi": "कोई सक्रिय टोकन नहीं", "ja": "アクティブなトークンがありません", + "ko": "활성 토큰이 없습니다", "nl": "geen actieve tokens", "pt": "Nenhum token ativo", "ru": "Активных токенов нет", + "zh-chs": "沒有有效令牌", "xloc": [ "default-mobile.handlebars->9->25", - "default.handlebars->25->133" + "default.handlebars->27->116" + ] + }, + { + "cs": "Žádná přidaná práva", + "de": "Keine zusätzlichen Rechte", + "en": "No Added Rights", + "fr": "Aucun droit ajouté", + "ja": "追加された権利なし", + "nl": "Geen toegevoegde rechten", + "ru": "Нет добавленных прав", + "zh-chs": "没有增加的权利", + "xloc": [ + "default.handlebars->27->556" ] }, { @@ -12001,15 +16689,53 @@ "de": "Keine Zugangsdaten", "en": "No Credentials", "es": "Sin credenciales", + "fr": "Aucun certificat", + "hi": "कोई साख नहीं", "ja": "資格情報なし", + "ko": "자격 증명 없음", "nl": "Geen referenties", "pt": "Sem credenciais", "ru": "Учетных данных нет", + "zh-chs": "沒有憑證", "xloc": [ - "default-mobile.handlebars->9->184", - "default-mobile.handlebars->9->185", - "default.handlebars->25->466", - "default.handlebars->25->467" + "default-mobile.handlebars->9->188", + "default-mobile.handlebars->9->189", + "default.handlebars->27->473", + "default.handlebars->27->474" + ] + }, + { + "cs": "Žádná plocha", + "de": "Kein Desktop", + "en": "No Desktop", + "fr": "Pas de bureau", + "hi": "कोई डेस्कटॉप नहीं", + "ja": "デスクトップなし", + "ko": "데스크탑 없음", + "nl": "Geen bureaublad", + "pt": "No Desktop", + "ru": "Нет рабочего стола", + "zh-chs": "沒有桌面", + "xloc": [ + "default.handlebars->27->1236", + "default.handlebars->27->547", + "default.handlebars->27->566" + ] + }, + { + "cs": "Žádný přístup na plochu", + "de": "Kein Desktop-Zugriff", + "en": "No Desktop Access", + "fr": "Pas d'accès au bureau", + "hi": "कोई डेस्कटॉप एक्सेस नहीं", + "ja": "デスクトップアクセスなし", + "ko": "데스크톱 액세스 불가", + "nl": "Geen bureaublad toegang", + "pt": "Sem acesso à área de trabalho", + "ru": "Нет доступа к рабочему столу", + "zh-chs": "沒有桌面訪問", + "xloc": [ + "default.handlebars->27->1205" ] }, { @@ -12018,14 +16744,17 @@ "en": "No Events Found", "es": "No se encontraron eventos", "fr": "Aucun événement trouvé", + "hi": "कोई ईवेंट नहीं मिला", "ja": "イベントが見つかりません", + "ko": "이벤트가 없습니다", "nl": "Geen gebeurtenissen gevonden", "pt": "Nenhum evento encontrado", "ru": "События не найдены", + "zh-chs": "找不到活動", "xloc": [ - "default.handlebars->25->1193", - "default.handlebars->25->1389", - "default.handlebars->25->689" + "default.handlebars->27->1323", + "default.handlebars->27->1535", + "default.handlebars->27->738" ] }, { @@ -12034,13 +16763,16 @@ "en": "No File Access", "es": "Sin acceso a archivos", "fr": "Pas d'accès au fichier", + "hi": "कोई फ़ाइल एक्सेस नहीं", "ja": "ファイルアクセスなし", + "ko": "파일 접근 금지", "nl": "Geen bestandstoegang", "pt": "Sem acesso a arquivos", "ru": "Нет доступа к файлам", + "zh-chs": "沒有文件訪問", "xloc": [ - "default-mobile.handlebars->9->300", - "default.handlebars->25->1099" + "default-mobile.handlebars->9->304", + "default.handlebars->27->1207" ] }, { @@ -12049,13 +16781,32 @@ "en": "No Files", "es": "Sin archivos", "fr": "Aucun fichier", + "hi": "फ़ाइल नहीं", "ja": "ファイルなし", + "ko": "파일이 없습니다", "nl": "Geen bestanden", "pt": "Sem arquivos", "ru": "Файлов нет", + "zh-chs": "沒有文件", "xloc": [ - "default-mobile.handlebars->9->321", - "default.handlebars->25->1125" + "default-mobile.handlebars->9->325", + "default.handlebars->27->1238", + "default.handlebars->27->544", + "default.handlebars->27->563" + ] + }, + { + "cs": "Žádný vstup", + "de": "Keine Eingabe", + "en": "No Input", + "fr": "Pas d'entrée", + "ja": "入力なし", + "nl": "Geen input", + "ru": "Нет ввода", + "zh-chs": "无输入", + "xloc": [ + "default.handlebars->27->542", + "default.handlebars->27->561" ] }, { @@ -12063,15 +16814,19 @@ "de": "Kein Intel® AMT", "en": "No Intel® AMT", "es": "Sin Intel & reg; AMT", + "fr": "Pas d'appareil Intel® AMT", + "hi": "कोई Intel® AMT नहीं", "ja": "Intel®なしAMT", + "ko": "인텔 ® AMT 없음", "nl": "Geen Intel® AMT", "pt": "Nenhum Intel® AMT", "ru": "Нет Intel® AMT", + "zh-chs": "沒有英特爾®AMT", "xloc": [ - "default-mobile.handlebars->9->301", - "default-mobile.handlebars->9->322", - "default.handlebars->25->1100", - "default.handlebars->25->1126" + "default-mobile.handlebars->9->305", + "default-mobile.handlebars->9->326", + "default.handlebars->27->1208", + "default.handlebars->27->1239" ] }, { @@ -12079,12 +16834,16 @@ "de": "Keine Intel®-AMT-Geräte in dieser Gruppe", "en": "No Intel® AMT devices in this group", "es": "Sin Intel & reg; Dispositivos AMT en este grupo", + "fr": "Aucun appareil Intel® AMT dans ce groupe", + "hi": "इस समूह में कोई Intel® AMT डिवाइस नहीं है", "ja": "Intel®なしこのグループのAMTデバイス", + "ko": "이 그룹에 인텔 ® AMT 장치가 없습니다", "nl": "Geen Intel® AMT-apparaten in deze groep", "pt": "Nenhum Intel® AMT devices in this group", "ru": "Intel® AMT устройств в этой группе нет", + "zh-chs": "該組中沒有英特爾®AMT設備", "xloc": [ - "default-mobile.handlebars->9->96" + "default-mobile.handlebars->9->100" ] }, { @@ -12092,12 +16851,16 @@ "de": "Keine Intel®-AMT-Geräte in diesem Mesh", "en": "No Intel® AMT devices in this mesh", "es": "Sin Intel & reg; Dispositivos AMT en este MESH", + "fr": "Aucun périphérique Intel® AMT dans ce maillage", + "hi": "इस जाल में कोई Intel® AMT उपकरण नहीं है", "ja": "Intel®なしこのメッシュのAMTデバイス", + "ko": "이 메시에 인텔 ® AMT 장치가 없습니다", "nl": "Geen Intel® AMT-apparaten in deze mesh", "pt": "Nenhum Intel® dispositivos AMT nessa malha", "ru": "Intel® AMT устройств в этой сети нет", + "zh-chs": "此網格中沒有英特爾®AMT設備", "xloc": [ - "default.handlebars->25->196" + "default.handlebars->27->180" ] }, { @@ -12105,12 +16868,16 @@ "de": "Keine Schlüssel konfiguriert", "en": "No Keys Configured", "es": "No hay claves configuradas", + "fr": "Aucun clé configurée", + "hi": "कोई कुंजी कॉन्फ़िगर नहीं है", "ja": "キーが設定されていません", + "ko": "구성된 키가 없습니다", "nl": "Geen sleutels geconfigureerd", "pt": "Nenhuma chave configurada", "ru": "Ключи не настроены", + "zh-chs": "未配置任何鍵", "xloc": [ - "default.handlebars->25->141" + "default.handlebars->27->124" ] }, { @@ -12118,10 +16885,16 @@ "de": "Keine Mitglieder", "en": "No Members", "es": "Sin miembros", + "fr": "Aucun membre", + "hi": "कोई सदस्य नहीं", + "ja": "メンバーなし", + "ko": "회원이 없습니다", "nl": "Geen leden", + "pt": "Nenhum membro", "ru": "Нет членов", + "zh-chs": "沒有會員", "xloc": [ - "default.handlebars->25->1292" + "default.handlebars->27->1428" ] }, { @@ -12129,12 +16902,16 @@ "de": "Keine neuen Gerätegruppen", "en": "No New Device Groups", "es": "No hay nuevos grupos de dispositivos", + "fr": "Pas de nouveau groupe d'appareils", + "hi": "कोई नया उपकरण समूह नहीं", "ja": "新しいデバイスグループはありません", + "ko": "새로운 장치 그룹이 없음", "nl": "Geen nieuwe apparaatgroepen", "pt": "Não há novos grupos de dispositivos", "ru": "Запретить создание групп устройств", + "zh-chs": "沒有新的設備組", "xloc": [ - "default.handlebars->25->1267" + "default.handlebars->27->1403" ] }, { @@ -12142,14 +16919,18 @@ "de": "Keine Richtlinie", "en": "No Policy", "es": "Ninguna política", + "fr": "Aucune restriction", + "hi": "कोई नीति नहीं", "ja": "ポリシーなし", + "ko": "정책 없음", "nl": "Geen beleid", "pt": "Nenhuma política", "ru": "Политик нет", + "zh-chs": "沒有政策", "xloc": [ - "default.handlebars->25->1007", - "default.handlebars->25->1038", - "default.handlebars->25->1041" + "default.handlebars->27->1114", + "default.handlebars->27->1142", + "default.handlebars->27->1145" ] }, { @@ -12157,19 +16938,21 @@ "de": "Keine Berechtigungen", "en": "No Rights", "es": "Sin Acceso", + "fr": "Aucun droit", + "hi": "कोई अधिकार नहीं", "ja": "権利なし", + "ko": "권리 없음", "nl": "Geen rechten", "pt": "Sem direitos", "ru": "Нет прав", + "zh-chs": "沒有權利", "xloc": [ - "default-mobile.handlebars->9->284", - "default-mobile.handlebars->9->327", - "default-mobile.handlebars->9->65", - "default.handlebars->25->1032", - "default.handlebars->25->1131", - "default.handlebars->25->1298", - "default.handlebars->25->1372", - "default.handlebars->25->969" + "default-mobile.handlebars->9->288", + "default-mobile.handlebars->9->331", + "default-mobile.handlebars->9->68", + "default.handlebars->27->1074", + "default.handlebars->27->1244", + "default.handlebars->27->575" ] }, { @@ -12178,14 +16961,17 @@ "en": "No TLS security", "es": "Sin Seguridad TLS", "fr": "Pas de sécurité TLS", + "hi": "कोई टीएलएस सुरक्षा नहीं", "ja": "TLSセキュリティなし", + "ko": "TLS 보안 없음", "nl": "Geen TLS beveiliging", "pt": "Sem segurança TLS", "ru": "Нет безопасности TLS", + "zh-chs": "沒有TLS安全性", "xloc": [ - "default-mobile.handlebars->9->215", - "default.handlebars->25->245", - "default.handlebars->25->550" + "default-mobile.handlebars->9->219", + "default.handlebars->27->229", + "default.handlebars->27->597" ] }, { @@ -12193,13 +16979,19 @@ "de": "Kein Terminal", "en": "No Terminal", "es": "Sin Terminal", + "fr": "Aucun terminal", + "hi": "कोई टर्मिनल नहीं", "ja": "ターミナルなし", + "ko": "터미널 없음", "nl": "Geen terminal", "pt": "Sem terminal", "ru": "Нет терминала", + "zh-chs": "沒有終端", "xloc": [ - "default-mobile.handlebars->9->320", - "default.handlebars->25->1124" + "default-mobile.handlebars->9->324", + "default.handlebars->27->1237", + "default.handlebars->27->543", + "default.handlebars->27->562" ] }, { @@ -12207,13 +16999,17 @@ "de": "Kein Terminalzugriff", "en": "No Terminal Access", "es": "Sin Acceso a la Terminal", + "fr": "Pas d'accès à ligne de commande", + "hi": "कोई टर्मिनल एक्सेस नहीं", "ja": "ターミナルアクセスなし", + "ko": "터미널 액세스 불가", "nl": "Geen terminal toegang", "pt": "Sem acesso ao terminal", "ru": "Нет доступа к терминалу", + "zh-chs": "沒有終端訪問", "xloc": [ - "default-mobile.handlebars->9->299", - "default.handlebars->25->1098" + "default-mobile.handlebars->9->303", + "default.handlebars->27->1206" ] }, { @@ -12221,12 +17017,16 @@ "de": "Keine Werkzeuge (MeshCmd/Router)", "en": "No Tools (MeshCmd/Router)", "es": "Sin tools (MeshCmd/Router)", + "fr": "Aucun outil (MeshCmd / Router)", + "hi": "कोई उपकरण (MeshCmd / रूटर)", "ja": "ツールなし(MeshCmd / Router)", + "ko": "도구 없음 (MeshCmd / Router)", "nl": "Geen Tools (MeshCmd/Router)", "pt": "Sem ferramentas (MeshCmd / Roteador)", "ru": "Нет инструментов (MeshCmd/Router)", + "zh-chs": "沒有工具(MeshCmd /路由器)", "xloc": [ - "default.handlebars->25->1268" + "default.handlebars->27->1404" ] }, { @@ -12234,11 +17034,17 @@ "de": "Keine gemeinsamen Gerätegruppen", "en": "No device groups in common", "es": "No hay grupos de dispositivos en común", + "fr": "Aucun groupe d'appareils", + "hi": "कोई उपकरण समूह सामान्य में नहीं", + "ja": "共通のデバイスグループはありません", + "ko": "공통된 장치 그룹이 없습니다.", "nl": "Geen gemeenschappelijke apparaatgroepen", + "pt": "Nenhum grupo de dispositivos em comum", "ru": "Нет общих групп устройств", + "zh-chs": "沒有共同的設備組", "xloc": [ - "default.handlebars->25->1301", - "default.handlebars->25->1375" + "default.handlebars->27->1434", + "default.handlebars->27->1517" ] }, { @@ -12247,10 +17053,13 @@ "en": "No device groups.", "es": "No hay grupos de dispositivos.", "fr": "Aucun groupe d'appareils.", + "hi": "कोई उपकरण समूह नहीं।", "ja": "デバイスグループはありません。", + "ko": "장치 그룹이 없습니다.", "nl": "Geen apparaatgroepen.", "pt": "Nenhum grupo de dispositivos.", "ru": "Нет групп устройств.", + "zh-chs": "沒有設備組。", "xloc": [ "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3noMeshFound", "default.handlebars->container->column_l->p1->NoMeshesPanel->1->1->0->3->getStarted2", @@ -12263,25 +17072,32 @@ "en": "No devices", "es": "Sin dispositivos", "fr": "Aucun appareil", + "hi": "कोई उपकरण नहीं", "ja": "デバイスなし", + "ko": "기기가 없습니다", "nl": "Geen apparaten", "pt": "Nenhum dispositivo", "ru": "Устройств нет", + "zh-chs": "沒有裝置", "xloc": [ - "default-mobile.handlebars->9->98" + "default-mobile.handlebars->9->102" ] }, { "cs": "Zařízení nejsou zařazena do žádných skupin – u konkrétního zařízení vždy klikněte na „Skupiny“ a přidejte ho do nějaké.", "de": "Keine Geräte in beliebigen Gruppen enthalten, klicken Sie auf \\\"Gruppen\\\" innerhalb eines Geräts, um eine Gruppe hinzuzufügen.", "en": "No devices are included in any groups, click on a device\\'s \\\"Groups\\\" to add to a group.", - "es": "No se incluyen dispositivos en ningún grupo, haga clic en un dispositivo \\ 's \\\"Grupos\\\" para agregar a un grupo.", + "es": "No se incluyen dispositivos en ningún grupo, haga clic en un dispositivo \\'s \\\"Grupos\\\" para agregar a un grupo.", + "fr": "Aucun appareil n'est inclus dans aucun groupe, cliquez sur \\\"Groupes\\\" d'un appareil pour l'ajouter à un groupe.", + "hi": "कोई भी उपकरण किसी भी समूह में शामिल नहीं हैं, एक समूह में जोड़ने के लिए एक उपकरण \\\"समूह \\\" पर क्लिक करें।", "ja": "どのグループにもデバイスは含まれていません。デバイスの\\\"グループ\\\"をクリックしてグループに追加してください。", + "ko": "그룹에 장치가 포함되어 있지 않으면 장치의 \\\"그룹 \\\"을 클릭하여 그룹에 추가하십시오.", "nl": "Er zijn geen apparaten opgenomen in groepen, klik op een apparaat \\\"Groepen\\\" om toe te voegen aan een groep.", "pt": "Nenhum dispositivo está incluído em nenhum grupo, clique no \\\"Grupo\\\" de um dispositivo para adicionar a um grupo", "ru": "Ни одно устройство не включено ни в одну из групп, чтобы добавить группу нажмите \\\"Группы\\\" устройств.", + "zh-chs": "任何組中均不包含任何設備,請單擊設備的“組”以添加到組中。", "xloc": [ - "default.handlebars->25->194" + "default.handlebars->27->178" ] }, { @@ -12290,12 +17106,31 @@ "en": "No devices found.", "es": "No se encontraron dispositivos.", "fr": "Aucun périphérique trouvé.", + "hi": "कोई यंत्र नहीं मिले।", "ja": "デバイスが見つかりません。", + "ko": "장치를 찾을 수 없습니다.", "nl": "Geen apparaten gevonden.", "pt": "Nenhum dispositivo encontrado.", "ru": "Устройства не найдены.", + "zh-chs": "找不到設備。", "xloc": [ - "default.handlebars->25->432" + "default.handlebars->27->436" + ] + }, + { + "cs": "Žádná společná zařízení", + "de": "Keine Geräte gemeinsam", + "en": "No devices in common", + "fr": "Aucun appareil en commun", + "hi": "आम में कोई उपकरण नहीं", + "ja": "共通のデバイスはありません", + "ko": "공통된 장치가 없음", + "nl": "Geen gemeenschappelijke apparaten", + "pt": "Nenhum dispositivo em comum", + "ru": "Нет общих устройств", + "zh-chs": "沒有共同的設備", + "xloc": [ + "default.handlebars->27->1511" ] }, { @@ -12303,10 +17138,16 @@ "de": "Keine Geräte in dieser Gerätegruppe.", "en": "No devices in this device group.", "es": "No hay dispositivos en este grupo de dispositivos.", + "fr": "Aucun appareil dans ce groupe.", + "hi": "इस उपकरण समूह में कोई उपकरण नहीं है।", + "ja": "このデバイスグループにデバイスはありません。", + "ko": "이 장치 그룹에 장치가 없습니다.", "nl": "Geen apparaten in deze apparaatgroep.", + "pt": "Nenhum dispositivo neste grupo de dispositivos.", "ru": "В группе нет устройств.", + "zh-chs": "該設備組中沒有設備。", "xloc": [ - "default.handlebars->25->1155" + "default.handlebars->27->1283" ] }, { @@ -12315,13 +17156,16 @@ "en": "No devices in this group", "es": "No hay dispositivos en este grupo.", "fr": "Aucun appareil dans ce groupe", + "hi": "इस समूह में कोई उपकरण नहीं है", "ja": "このグループにデバイスはありません", + "ko": "이 그룹에 기기가 없습니다", "nl": "Geen apparaten in deze groep", "pt": "Nenhum dispositivo neste grupo", "ru": "В этой группе нет устройств", + "zh-chs": "該組中沒有設備", "xloc": [ - "default-mobile.handlebars->9->97", - "default.handlebars->25->198" + "default-mobile.handlebars->9->101", + "default.handlebars->27->182" ] }, { @@ -12330,12 +17174,15 @@ "en": "No devices matching this search.", "es": "No hay dispositivos que coincidan con esta búsqueda.", "fr": "Aucun appareil ne correspond à cette recherche.", + "hi": "इस खोज से मेल खाने वाला कोई उपकरण नहीं है।", "ja": "この検索に一致するデバイスはありません。", + "ko": "이 검색과 일치하는 기기가 없습니다.", "nl": "Geen apparaten die overeenkomen met deze zoekopdracht.", "pt": "Nenhum dispositivo correspondente a esta pesquisa.", "ru": "Нет устройств, соответствующих этому запросу.", + "zh-chs": "沒有與此搜索匹配的設備。", "xloc": [ - "default.handlebars->25->195" + "default.handlebars->27->179" ] }, { @@ -12343,10 +17190,16 @@ "de": "Keine Geräte mit Tags gefunden.", "en": "No devices with tags found.", "es": "No se encontraron dispositivos con etiquetas.", + "fr": "Aucun appareil avec des balises trouvé.", + "hi": "टैग वाले कोई उपकरण नहीं मिले।", + "ja": "タグ付きのデバイスが見つかりません。", + "ko": "태그가있는 장치가 없습니다.", "nl": "Geen apparaten tags gevonden.", + "pt": "Nenhum dispositivo com tags encontrado.", "ru": "Не найдено устройств с тегом.", + "zh-chs": "找不到帶有標籤的設備。", "xloc": [ - "default.handlebars->25->203" + "default.handlebars->27->187" ] }, { @@ -12354,10 +17207,16 @@ "de": "Keine Gruppen gefunden.", "en": "No groups found.", "es": "No se encontraron grupos.", + "fr": "Aucun groupe trouvé.", + "hi": "कोई समूह नहीं मिला।", + "ja": "グループが見つかりません。", + "ko": "그룹이 없습니다.", "nl": "Geen groepen gevonden.", + "pt": "Nenhum grupo encontrado.", "ru": "Группы не найдены.", + "zh-chs": "找不到群組。", "xloc": [ - "default.handlebars->25->1270" + "default.handlebars->27->1406" ] }, { @@ -12365,12 +17224,16 @@ "de": "Keine Informationen zu diesem Gerät.", "en": "No information for this device.", "es": "No hay información para este dispositivo.", + "fr": "Aucune information sur cet appareil.", + "hi": "इस उपकरण के लिए कोई जानकारी नहीं।", "ja": "このデバイスに関する情報はありません。", + "ko": "이 장치에 대한 정보가 없습니다.", "nl": "Geen informatie over dit apparaat.", "pt": "Nenhuma informação para este dispositivo.", "ru": "Информации об этом устройстве нет", + "zh-chs": "沒有此設備的信息。", "xloc": [ - "default.handlebars->25->65" + "default.handlebars->27->791" ] }, { @@ -12378,12 +17241,16 @@ "de": "Kein Standort gefunden.", "en": "No location found.", "es": "No se ha encontrado ninguna ubicación.", + "fr": "Aucune localisation.", + "hi": "कोई स्थान नहीं मिला।", "ja": "場所が見つかりません。", + "ko": "위치를 찾을 수 없습니다.", "nl": "Geen locatie gevonden.", "pt": "Nenhum local encontrado.", "ru": "Местоположение не найдено.", + "zh-chs": "找不到位置。", "xloc": [ - "default.handlebars->25->434" + "default.handlebars->27->438" ] }, { @@ -12391,12 +17258,16 @@ "de": "Keine Netzwerkschnittstelleninformationen für dieses Gerät verfügbar.", "en": "No network interface information available for this device.", "es": "No hay información de interfaz de red disponible para este dispositivo.", + "fr": "Aucune interface n'est disponible pour cet appareil.", + "hi": "इस उपकरण के लिए कोई नेटवर्क इंटरफ़ेस जानकारी उपलब्ध नहीं है।", "ja": "このデバイスで利用可能なネットワークインターフェイス情報はありません。", + "ko": "이 장치에 사용 가능한 네트워크 인터페이스 정보가 없습니다.", "nl": "geen netwerkinterface informatie beschikbaar voor dit apparaat.", "pt": "Nenhuma informação de interface de rede disponível para este dispositivo.", "ru": "Информации о сетевых интерфейсах этого устройства нет.", + "zh-chs": "沒有適用於此設備的網絡接口信息。", "xloc": [ - "default.handlebars->25->86" + "default.handlebars->27->68" ] }, { @@ -12404,12 +17275,16 @@ "de": "Es existiert keine andere Gerätegruppe des selben Typs.", "en": "No other device group of same type exists.", "es": "No existe otro grupo de dispositivos del mismo tipo.", + "fr": "Aucun autre groupe de périphériques du même type n'existe.", + "hi": "एक ही प्रकार का कोई अन्य उपकरण समूह मौजूद नहीं है।", "ja": "同じタイプの他のデバイスグループは存在しません。", + "ko": "동일한 유형의 다른 장치 그룹이 없습니다.", "nl": "Er bestaat geen andere apparaatgroep van hetzelfde type.", "pt": "Não existe outro grupo de dispositivos do mesmo tipo.", "ru": "Других групп устройств такого же типа не существует.", + "zh-chs": "沒有其他相同類型的設備組。", "xloc": [ - "default.handlebars->25->567" + "default.handlebars->27->614" ] }, { @@ -12417,9 +17292,14 @@ "de": "Keine Plugins auf dem Server.", "en": "No plugins on server.", "es": "No hay plugins en el servidor.", + "fr": "Aucun module sur le serveur.", + "hi": "सर्वर पर कोई प्लगइन्स नहीं।", "ja": "サーバーにプラグインはありません。", + "ko": "서버에 플러그인이 없습니다.", "nl": "Geen plug-ins op server.", + "pt": "Não há plugins no servidor.", "ru": "Плагинов на сервере нет.", + "zh-chs": "服務器上沒有插件。", "xloc": [ "default.handlebars->container->column_l->p42->pluginNoneNotice->0" ] @@ -12429,12 +17309,16 @@ "de": "Keine Serverberechtigungen", "en": "No server rights", "es": "Sin Acceso al Server", + "fr": "Aucun droit de serveur", + "hi": "कोई सर्वर अधिकार नहीं", "ja": "サーバーの権利なし", + "ko": "서버 권한이 없습니다", "nl": "Geen server rechten", "pt": "Sem direitos de servidor", "ru": "Нет серверных прав", + "zh-chs": "沒有服務器權限", "xloc": [ - "default.handlebars->25->1318" + "default.handlebars->27->1452" ] }, { @@ -12442,10 +17326,16 @@ "de": "Keine Benutzergruppenmitgliedschaften", "en": "No user group memberships", "es": "No hay elmentos en el grupo de usuarios", + "fr": "Aucune appartenance à un groupe d'utilisateurs", + "hi": "कोई उपयोगकर्ता समूह सदस्यता नहीं", + "ja": "ユーザーグループメンバーシップなし", + "ko": "사용자 그룹 멤버십이 없습니다", "nl": "Geen gebruikersgroep lidmaatschap", + "pt": "Nenhuma participação no grupo de usuários", "ru": "Нет членства в группах пользователей", + "zh-chs": "沒有用戶組成員身份", "xloc": [ - "default.handlebars->25->1381" + "default.handlebars->27->1523" ] }, { @@ -12453,12 +17343,29 @@ "de": "Keine Benutzer gefunden.", "en": "No users found.", "es": "No se encontraron usuarios.", + "fr": "Aucun utilisateur trouvé.", + "hi": "कोई उपयोग्कर्ता नहीं मिले।", "ja": "ユーザが見つかりませんでした。", + "ko": "사용자가 없습니다.", "nl": "Geen gebruikers gevonden", "pt": "Usuários não encontrados.", "ru": "Пользователи не найдены.", + "zh-chs": "未找到相應的用戶。", "xloc": [ - "default.handlebars->25->1211" + "default.handlebars->27->1341" + ] + }, + { + "cs": "Žádní uživatelé se zvláštními oprávněními zařízení", + "de": "Keine Benutzer mit speziellen Geräteberechtigungen", + "en": "No users with special device permissions", + "fr": "Aucun utilisateur avec des autorisations spéciales sur les appareils", + "ja": "特別なデバイス権限を持つユーザーはいません", + "nl": "Geen gebruikers met speciale apparaatrechten", + "ru": "Нет пользователей со специальными правами доступа к устройству", + "zh-chs": "没有拥有特殊设备权限的用户", + "xloc": [ + "default.handlebars->27->540" ] }, { @@ -12466,10 +17373,14 @@ "de": "NodeID", "en": "NodeID", "es": "ID de Nodo", + "fr": "NodeID", + "hi": "NodeID", "ja": "NodeID", + "ko": "노드 ID", "nl": "NodeID", "pt": "NodeID", "ru": "NodeID", + "zh-chs": "節點ID", "xloc": [ "player.handlebars->3->10" ] @@ -12479,13 +17390,17 @@ "de": "NodeJS", "en": "NodeJS", "es": "NodeJS", + "fr": "NodeJS", + "hi": "NodeJS", "ja": "NodeJS", + "ko": "NodeJS", "nl": "NodeJS", "pt": "NodeJS", "ru": "NodeJS", + "zh-chs": "節點JS", "xloc": [ - "default-mobile.handlebars->9->166", - "default.handlebars->25->36" + "default-mobile.handlebars->9->170", + "default.handlebars->27->36" ] }, { @@ -12494,36 +17409,40 @@ "en": "None", "es": "Ninguno", "fr": "Aucun", + "hi": "कोई नहीं", "ja": "なし", + "ko": "없음", "nl": "Geen", "pt": "Nenhum", "ru": "Пусто", + "zh-chs": "沒有", "xloc": [ - "default-mobile.handlebars->9->133", - "default-mobile.handlebars->9->138", - "default-mobile.handlebars->9->140", - "default-mobile.handlebars->9->196", - "default-mobile.handlebars->9->245", - "default-mobile.handlebars->9->278", - "default-mobile.handlebars->9->75", - "default-mobile.handlebars->9->93", - "default-mobile.handlebars->9->95", - "default.handlebars->25->1000", - "default.handlebars->25->1005", - "default.handlebars->25->1164", - "default.handlebars->25->1279", - "default.handlebars->25->1337", - "default.handlebars->25->1341", - "default.handlebars->25->166", - "default.handlebars->25->181", - "default.handlebars->25->182", - "default.handlebars->25->439", - "default.handlebars->25->447", - "default.handlebars->25->449", - "default.handlebars->25->493", - "default.handlebars->25->63", - "default.handlebars->25->984", - "default.handlebars->25->988", + "default-mobile.handlebars->9->137", + "default-mobile.handlebars->9->142", + "default-mobile.handlebars->9->144", + "default-mobile.handlebars->9->200", + "default-mobile.handlebars->9->249", + "default-mobile.handlebars->9->282", + "default-mobile.handlebars->9->78", + "default-mobile.handlebars->9->97", + "default-mobile.handlebars->9->99", + "default.handlebars->27->1089", + "default.handlebars->27->1093", + "default.handlebars->27->1105", + "default.handlebars->27->1110", + "default.handlebars->27->1112", + "default.handlebars->27->1293", + "default.handlebars->27->1415", + "default.handlebars->27->1471", + "default.handlebars->27->1475", + "default.handlebars->27->149", + "default.handlebars->27->165", + "default.handlebars->27->166", + "default.handlebars->27->443", + "default.handlebars->27->454", + "default.handlebars->27->456", + "default.handlebars->27->500", + "default.handlebars->27->63", "default.handlebars->container->column_l->p41->3->3->p41traceStatus" ] }, @@ -12533,10 +17452,13 @@ "en": "Normal Speed", "es": "Velocidad normal", "fr": "Vitesse normale", + "hi": "सामान्य गति", "ja": "通常速度", + "ko": "정상 속도", "nl": "Normale snelheid", "pt": "Velocidade normal", "ru": "Нормальная скорость", + "zh-chs": "正常的速度", "xloc": [ "player.handlebars->p11->deskarea0->deskarea4->3->PlaySpeed->5" ] @@ -12546,12 +17468,15 @@ "de": "Norwegisch", "en": "Norwegian", "fr": "Norvégien", + "hi": "नार्वेजियन", "ja": "ノルウェー語", + "ko": "노르웨이 인", "nl": "Noors", "pt": "norueguês", "ru": "Норвежский", + "zh-chs": "挪威", "xloc": [ - "default.handlebars->25->843" + "default.handlebars->27->947" ] }, { @@ -12559,12 +17484,15 @@ "de": "Norwegisch (Bokmal)", "en": "Norwegian (Bokmal)", "fr": "Norvégien (Bokmal)", + "hi": "नॉर्वेजियन (बोकमल)", "ja": "ノルウェー語(ボクマル)", + "ko": "노르웨이어 (Bokmal)", "nl": "Noors (Bokmal)", "pt": "Norueguês (Bokmal)", "ru": "Норвежский (Букмол)", + "zh-chs": "挪威文(Bokmal)", "xloc": [ - "default.handlebars->25->844" + "default.handlebars->27->948" ] }, { @@ -12572,38 +17500,51 @@ "de": "Norwegisch (Nynorsk)", "en": "Norwegian (Nynorsk)", "fr": "Norvégien (Nynorsk)", + "hi": "नॉर्वेजियन (Nynorsk)", "ja": "ノルウェー語(ニーノシュク)", + "ko": "노르웨이어 (니 노르 스크)", "nl": "Noors (Nynorsk)", "pt": "Norueguês (Nynorsk)", "ru": "Норвежский (Нюнорск)", + "zh-chs": "挪威文(尼諾斯克)", "xloc": [ - "default.handlebars->25->845" + "default.handlebars->27->949" ] }, { "cs": "Neaktivováno (v)", "de": "Nicht aktiviert (In)", "en": "Not Activated (In)", + "fr": "Non activé (en)", + "hi": "सक्रिय नहीं (में)", "ja": "アクティブ化されていない(イン)", + "ko": "활성화되지 않음 (In)", "nl": "Niet geactiveerd (In)", "pt": "Não ativado (entrada)", "ru": "Не активированно (In)", + "zh-chs": "未激活(輸入)", "xloc": [ - "default-mobile.handlebars->9->176", - "default.handlebars->25->454" + "default-mobile.handlebars->9->180", + "default.handlebars->27->461", + "default.handlebars->27->765" ] }, { "cs": "Neaktivováno (před)", "de": "Nicht aktiviert (Pre)", "en": "Not Activated (Pre)", + "fr": "Non activé (pré)", + "hi": "सक्रिय नहीं (पूर्व)", "ja": "アクティブ化されていない(前)", + "ko": "활성화되지 않음 (사전)", "nl": "Niet geactiveerd (Pre)", "pt": "Não ativado (pré)", "ru": "Не активированно (Pre)", + "zh-chs": "未激活(預)", "xloc": [ - "default-mobile.handlebars->9->175", - "default.handlebars->25->453" + "default-mobile.handlebars->9->179", + "default.handlebars->27->460", + "default.handlebars->27->764" ] }, { @@ -12611,11 +17552,33 @@ "de": "Getrennt", "en": "Not Connected", "es": "No conectado", + "fr": "Non connecté", + "hi": "जुड़े नहीं हैं", + "ja": "接続されていません", + "ko": "연결되지 않은", "nl": "Niet verbonden", + "pt": "Não conectado", "ru": "Не подключен", + "zh-chs": "未連接", "xloc": [ - "default.handlebars->25->1144", - "default.handlebars->25->1150" + "default.handlebars->27->1272", + "default.handlebars->27->1278" + ] + }, + { + "cs": "Neznámý", + "de": "Nicht bekannt", + "en": "Not Known", + "fr": "Pas connu", + "hi": "ज्ञात नहीं है", + "ja": "不明", + "ko": "불명", + "nl": "Onbekend", + "pt": "Não conhecido", + "ru": "Неизвестный", + "zh-chs": "未知", + "xloc": [ + "default.handlebars->27->775" ] }, { @@ -12623,12 +17586,32 @@ "de": "Nicht gesetzt", "en": "Not set", "es": "No establecido", + "fr": "Non défini", + "hi": "सेट नहीं", "ja": "設定されていません", + "ko": "미 설정", "nl": "Niet ingesteld", "pt": "Não configurado", "ru": "Не задано", + "zh-chs": "沒有設置", "xloc": [ - "default.handlebars->25->1323" + "default.handlebars->27->1457" + ] + }, + { + "cs": "Neověřeno", + "de": "Nicht verifiziert", + "en": "Not verified", + "fr": "non vérifié", + "hi": "प्रमाणित नहीं है", + "ja": "検証されていない", + "ko": "확인되지 않음", + "nl": "niet geverifieerd", + "pt": "Não verificado", + "ru": "не подтверждено", + "zh-chs": "未經審核的", + "xloc": [ + "default.handlebars->27->1494" ] }, { @@ -12637,15 +17620,20 @@ "en": "Notes", "es": "Notas:", "fr": "Remarques", + "hi": "टिप्पणियाँ", "ja": "ノート", + "ko": "노트", "nl": "Notities", "pt": "Notas", "ru": "Примечания", + "zh-chs": "筆記", "xloc": [ - "default.handlebars->25->1013", - "default.handlebars->25->1348", - "default.handlebars->25->496", - "default.handlebars->25->531" + "default.handlebars->27->1120", + "default.handlebars->27->1482", + "default.handlebars->27->503", + "default.handlebars->27->552", + "default.handlebars->27->571", + "default.handlebars->27->578" ] }, { @@ -12653,9 +17641,14 @@ "de": "Hinweis:", "en": "Notice:", "es": "Informacion:", + "fr": "Remarquer:", + "hi": "नोटिस:", "ja": "通知:", + "ko": "주의:", "nl": "Opmerking:", + "pt": "Aviso prévio:", "ru": "Уведомление:", + "zh-chs": "注意:", "xloc": [ "default.handlebars->container->column_l->p42->pluginRestartNotice->3->1->0" ] @@ -12665,13 +17658,17 @@ "de": "Benachrichtungseinstellungen", "en": "Notification Settings", "es": "Configuración de las notificaciones", + "fr": "Paramètres des notifications", + "hi": "अधिसूचना सेटिंग", "ja": "通知設定", + "ko": "알림 설정", "nl": "meldingsinstellingen", "pt": "Configurações de notificação", "ru": "Настройки уведомлений", + "zh-chs": "通知設置", "xloc": [ - "default.handlebars->25->1143", - "default.handlebars->25->930", + "default.handlebars->27->1035", + "default.handlebars->27->1271", "default.handlebars->container->column_l->p2->p2AccountActions->3->8" ] }, @@ -12680,10 +17677,16 @@ "de": "Benachrichtigungseinstellungen müssen ebenfalls in den Kontoeinstellungen eingeschaltet sein.", "en": "Notification settings must also be turned on in account settings.", "es": "La configuración de notificaciones también debe estar activada en la configuración de la cuenta.", + "fr": "Les notifications doivent aussi être activées dans les paramètres du compte.", + "hi": "खाता सेटिंग्स में अधिसूचना सेटिंग्स भी चालू होनी चाहिए।", + "ja": "アカウント設定で通知設定もオンにする必要があります。", + "ko": "계정 설정에서도 알림 설정을 켜야합니다.", "nl": "Meldingsinstellingen moeten ook worden ingeschakeld in accountinstellingen.", + "pt": "As configurações de notificação também devem estar ativadas nas configurações da conta.", "ru": "Уведомления также должны быть включены в настройках учетной записи.", + "zh-chs": "通知設置還必須在帳戶設置中啟用。", "xloc": [ - "default.handlebars->25->1139" + "default.handlebars->27->1267" ] }, { @@ -12691,12 +17694,16 @@ "de": "Benachrichtigungston.", "en": "Notification sound.", "es": "Sonido de notificación.", + "fr": "Notification sonore.", + "hi": "सूचना ध्वनि।", "ja": "通知音。", + "ko": "알림 소리.", "nl": "Meldingsgeluid.", "pt": "Som de notificação.", "ru": "Звук уведомления", + "zh-chs": "通知聲音。", "xloc": [ - "default.handlebars->25->925" + "default.handlebars->27->1030" ] }, { @@ -12704,12 +17711,16 @@ "de": "Benachrichtigungen", "en": "Notifications", "es": "Notificaciones", + "fr": "Notifications", + "hi": "सूचनाएं", "ja": "通知", + "ko": "알림", "nl": "Meldingen", "pt": "Notificações", "ru": "Уведомления", + "zh-chs": "通知事項", "xloc": [ - "default.handlebars->25->1006" + "default.handlebars->27->1111" ] }, { @@ -12717,12 +17728,16 @@ "de": "Benachrichtigen", "en": "Notify", "es": "Notificar", + "fr": "Notifier", + "hi": "सूचित करें", "ja": "通知する", + "ko": "통지", "nl": "Melden", "pt": "Notificar", "ru": "Уведомить", + "zh-chs": "通知", "xloc": [ - "default.handlebars->25->1350" + "default.handlebars->27->1484" ] }, { @@ -12731,14 +17746,17 @@ "en": "Notify user", "es": "Notificar al usuario", "fr": "Notifier l'utilisateur", + "hi": "उपयोगकर्ता को सूचित करें", "ja": "ユーザーに通知", + "ko": "사용자에게 알림", "nl": "Gebruiker informeren", "pt": "Notificar usuário", "ru": "Уведомить пользователя", + "zh-chs": "通知使用者", "xloc": [ - "default.handlebars->25->1070", - "default.handlebars->25->1074", - "default.handlebars->25->1077" + "default.handlebars->27->1174", + "default.handlebars->27->1178", + "default.handlebars->27->1181" ] }, { @@ -12746,12 +17764,16 @@ "de": "{0} benachrichtigen", "en": "Notify {0}", "es": "Notificar {0}", + "fr": "Notifier {0}", + "hi": "सूचित करें {0}", "ja": "{0}に通知", + "ko": "{0}에게 알림", "nl": "Melden {0}", "pt": "Notificar {0}", "ru": "Уведомить {0}", + "zh-chs": "通知{0}", "xloc": [ - "default.handlebars->25->1223" + "default.handlebars->27->1358" ] }, { @@ -12759,15 +17781,19 @@ "de": "OK", "en": "OK", "es": "OK", + "fr": "ОК", + "hi": "ठीक", "ja": "OK", + "ko": "확인", "nl": "OK", "pt": "Ok", "ru": "ОК", + "zh-chs": "好", "xloc": [ - "default-mobile.handlebars->9->42", + "default-mobile.handlebars->9->45", "default-mobile.handlebars->dialog->idx_dlgButtonBar", - "default.handlebars->25->479", - "default.handlebars->25->972", + "default.handlebars->27->1077", + "default.handlebars->27->486", "default.handlebars->container->dialog->idx_dlgButtonBar", "login-mobile.handlebars->dialog->idx_dlgButtonBar", "login.handlebars->dialog->idx_dlgButtonBar", @@ -12781,10 +17807,13 @@ "en": "OS Name", "es": "Nombre del Sistema Operativo", "fr": "Nom du système", + "hi": "OS का नाम", "ja": "OS名", + "ko": "OS 이름", "nl": "Besturingssysteem naam", "pt": "Nome do SO", "ru": "настоящее имя", + "zh-chs": "操作系統名稱", "xloc": [ "default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->devListToolbar->7->1" ] @@ -12793,12 +17822,16 @@ "cs": "okcitánština", "de": "Okzitanisch", "en": "Occitan", + "fr": "Occitan", + "hi": "ओसीटान", "ja": "オクシタン", + "ko": "오크 어", "nl": "Occitaans", "pt": "Occitânico", "ru": "Окситанский", + "zh-chs": "歐舒丹", "xloc": [ - "default.handlebars->25->846" + "default.handlebars->27->950" ] }, { @@ -12807,12 +17840,15 @@ "en": "Occured at {0}", "es": "Ocurrió en {0}", "fr": "Survenu à {0}", + "hi": "{0} पर हुआ", "ja": "{0}で発生しました", + "ko": "{0}에 발생", "nl": "Heeft plaatsgevonden op {0}", "pt": "Ocorreu em {0}", "ru": "Произошло в {0}", + "zh-chs": "發生在{0}", "xloc": [ - "default.handlebars->25->1392" + "default.handlebars->27->1538" ] }, { @@ -12821,12 +17857,15 @@ "en": "Offline Users", "es": "Usuarios sin conexión", "fr": "Utilisateurs hors ligne", + "hi": "ऑफ़लाइन उपयोगकर्ता", "ja": "オフラインユーザー", + "ko": "오프라인 사용자", "nl": "Offline gebruikers", "pt": "Usuários offline", "ru": "Оффлайн пользователи", + "zh-chs": "離線用戶", "xloc": [ - "default.handlebars->25->1208" + "default.handlebars->27->1338" ] }, { @@ -12835,13 +17874,16 @@ "en": "Old password:", "es": "Contraseña anterior:", "fr": "Ancien mot de passe:", + "hi": "पुराना पासवर्ड:", "ja": "以前のパスワード:", + "ko": "기존 비밀번호:", "nl": "Oud wachtwoord:", "pt": "Senha Antiga:", "ru": "Старый пароль:", + "zh-chs": "舊密碼:", "xloc": [ - "default-mobile.handlebars->9->44", - "default.handlebars->25->942" + "default-mobile.handlebars->9->47", + "default.handlebars->27->1047" ] }, { @@ -12849,13 +17891,17 @@ "de": "Einmal-Token können als sekundäre Authentifizierung verwendet werden. Erstellen Sie ein Set, drucken Sie es aus und bewahren Sie es an einem sicheren Ort auf.", "en": "One time tokens can be used as secondary authentication. Generate a set, print them and keep them in a safe place.", "es": "Los tokens únicos se pueden usar como autenticación secundaria. Genere un conjunto, imprímalos y guárdelos en un lugar seguro.", + "fr": "Les jetons à usage unique peuvent être utilisés pour la double authentification. Générez les et gardez les dans un endroit sûr.", + "hi": "एक समय के टोकन को माध्यमिक प्रमाणीकरण के रूप में उपयोग किया जा सकता है। एक सेट बनाएं, उन्हें प्रिंट करें और उन्हें सुरक्षित स्थान पर रखें।", "ja": "ワンタイムトークンは、セカンダリ認証として使用できます。セットを生成して印刷し、安全な場所に保管してください。", + "ko": "일회성 토큰을 보조 인증으로 사용할 수 있습니다. 세트를 생성하고 인쇄하여 안전한 장소에 보관하십시오.", "nl": "Eenmalige tokens kunnen worden gebruikt als secundaire authenticatie. Genereer een set, druk ze af en bewaar ze op een veilige plaats.", "pt": "Os tokens únicos podem ser usados como autenticação secundária. Gere um conjunto, imprima-os e mantenha-os em um local seguro.", "ru": "Однократные токены можно использовать как вторичную аутентификацию. Сгенерируйте, распечатайте и храните их в надежном месте.", + "zh-chs": "一次性令牌可以用作輔助身份驗證。生成一組,打印並保存在安全的地方。", "xloc": [ "default-mobile.handlebars->9->24", - "default.handlebars->25->132" + "default.handlebars->27->115" ] }, { @@ -12864,12 +17910,15 @@ "en": "Online Users", "es": "Usuarios en línea", "fr": "Utilisateurs en ligne", + "hi": "ऑनलाइन उपयोगकर्ता", "ja": "オンラインユーザー", + "ko": "온라인 사용자", "nl": "Online gebruikers", "pt": "Usuários Online", "ru": "Онлайн пользователи", + "zh-chs": "在線用戶", "xloc": [ - "default.handlebars->25->1207" + "default.handlebars->27->1337" ] }, { @@ -12877,13 +17926,18 @@ "de": "Nur Dateien kleiner als 200 kB können bearbeitet werden.", "en": "Only files less than 200k can be edited.", "es": "Solo se pueden editar archivos de menos de 200k.", + "fr": "Seuls les fichiers de moins de 200k peuvent être modifiés.", + "hi": "केवल 200k से कम फ़ाइलों को ही संपादित किया जा सकता है।", "ja": "編集できるのは200k未満のファイルのみです。", + "ko": "200k 미만의 파일 만 편집 할 수 있습니다.", "nl": "Alleen bestanden kleiner dan 200k kunnen worden bewerkt.", "pt": "Somente arquivos com menos de 200k podem ser editados.", "ru": "Редактировать файлы можно только размером менее 200КБ.", + "zh-chs": "只能編輯小於200k的文件。", "xloc": [ - "default-mobile.handlebars->9->255", - "default.handlebars->25->663" + "default-mobile.handlebars->9->259", + "default.handlebars->27->416", + "default.handlebars->27->712" ] }, { @@ -12891,12 +17945,16 @@ "de": "Datei öffnen...", "en": "Open File...", "es": "Abrir archivo...", + "fr": "Ouvrir le fichier...", + "hi": "खुली फाइल...", "ja": "ファイルを開く...", + "ko": "파일 열기 ...", "nl": "Open bestand...", "pt": "Abrir arquivo...", "ru": "Открыть файл...", + "zh-chs": "打開文件...", "xloc": [ - "player.handlebars->3->19", + "player.handlebars->3->21", "player.handlebars->p11->deskarea0->deskarea1->3" ] }, @@ -12905,20 +17963,32 @@ "de": "Öffne Seite auf Gerät", "en": "Open Page on Device", "es": "Abrir página en dispositivo", + "fr": "Ouvrir la page sur l'appareil", + "hi": "डिवाइस पर पेज खोलें", "ja": "デバイスでページを開く", + "ko": "장치에서 페이지 열기", "nl": "Open pagina op apparaat", "pt": "Abrir página no dispositivo", "ru": "Открыть страницу на устройстве", + "zh-chs": "在設備上打開頁面", "xloc": [ - "default.handlebars->25->533" + "default.handlebars->27->580" ] }, { + "cs": "Otevřete terminál XTerm", + "de": "Öffnen Sie das XTerm-Terminal", "en": "Open XTerm terminal", + "fr": "Ouvrir un terminal XTerm", + "hi": "XTerm टर्मिनल खोलें", + "ja": "XTermターミナルを開きます", + "ko": "XTerm 터미널 열기", "nl": "Open XTerm terminal", + "pt": "Abra o terminal XTerm", "ru": "Открыть терминал XTerm", + "zh-chs": "打開XTerm終端", "xloc": [ - "default.handlebars->25->510" + "default.handlebars->27->517" ] }, { @@ -12926,9 +17996,14 @@ "de": "Eine Web-Adresse auf dem entfernten Rechner öffnen", "en": "Open a web address on the remote computer", "es": "Abra una dirección web en la computadora remota", + "fr": "Ouvrir une url sur l'ordinateur distant", + "hi": "दूरस्थ कंप्यूटर पर एक वेब पता खोलें", "ja": "リモートコンピューターでWebアドレスを開く", + "ko": "원격 컴퓨터에서 웹 주소를 엽니 다", "nl": "Open een webadres op de externe computer", + "pt": "Abra um endereço da web no computador remoto", "ru": "Открыть ссылку на удаленном компьютере", + "zh-chs": "在遠程計算機上打開一個網址", "xloc": [ "default.handlebars->container->column_l->p11->deskarea0->deskarea4->1" ] @@ -12939,10 +18014,13 @@ "en": "Open chat window to this computer", "es": "Abrir ventana de chat en esta computadora", "fr": "Ouvrir la fenêtre de discussion sur cet ordinateur", + "hi": "इस कंप्यूटर पर चैट विंडो खोलें", "ja": "このコンピューターへのチャットウィンドウを開く", + "ko": "이 컴퓨터로 대화창 열기", "nl": "Open chatvenster op deze computer", "pt": "Abra a janela de bate-papo neste computador", "ru": "Открыть окно чата на этом компьютере", + "zh-chs": "打開此計算機的聊天窗口", "xloc": [ "default.handlebars->container->column_l->p11->deskarea0->deskarea4->1" ] @@ -12952,17 +18030,20 @@ "de": "Betriebssystem", "en": "Operating System", "es": "Sistema operativo", - "fr": "Système opérateur", + "fr": "Système d'exploitation", + "hi": "ऑपरेटिंग सिस्टम", "ja": "オペレーティング・システム", + "ko": "운영 체제", "nl": "Besturingssysteem", "pt": "Sistema operacional", "ru": "Операционная система", + "zh-chs": "操作系統", "xloc": [ - "default.handlebars->25->285", - "default.handlebars->25->314", - "default.handlebars->25->476", - "default.handlebars->25->584", - "default.handlebars->25->79" + "default.handlebars->27->272", + "default.handlebars->27->301", + "default.handlebars->27->483", + "default.handlebars->27->632", + "default.handlebars->27->743" ] }, { @@ -12971,14 +18052,17 @@ "en": "Operation", "es": "Operación", "fr": "Opération", + "hi": "ऑपरेशन", "ja": "操作", + "ko": "조작", "nl": "Operatie", "pt": "Operação", "ru": "Операция", + "zh-chs": "運作方式", "xloc": [ - "default-mobile.handlebars->9->210", - "default.handlebars->25->386", - "default.handlebars->25->542" + "default-mobile.handlebars->9->214", + "default.handlebars->27->376", + "default.handlebars->27->589" ] }, { @@ -12987,36 +18071,47 @@ "en": "Organization", "es": "Organización", "fr": "Organisation", + "hi": "संगठन", "ja": "組織", + "ko": "조직", "nl": "Organisatie", "pt": "Organização", "ru": "Организация", + "zh-chs": "組織", "xloc": [ - "default.handlebars->25->277" + "default.handlebars->27->262" ] }, { "cs": "urijština", "de": "Oriya", "en": "Oriya", + "fr": "Oriya", + "hi": "ओरिया", "ja": "オリヤ", + "ko": "오리 야", "nl": "Oriya", "pt": "Oriya", "ru": "Ория", + "zh-chs": "奧里亞", "xloc": [ - "default.handlebars->25->847" + "default.handlebars->27->951" ] }, { "cs": "oromština", "de": "Oromo", "en": "Oromo", + "fr": "Oromo", + "hi": "ओरोमो", "ja": "オロモ", + "ko": "오 로모", "nl": "Oromo", "pt": "Oromo", "ru": "Оромо", + "zh-chs": "奧羅莫", "xloc": [ - "default.handlebars->25->848" + "default.handlebars->27->952" ] }, { @@ -13025,10 +18120,13 @@ "en": "Other", "es": "Otros", "fr": "Autre", + "hi": "अन्य", "ja": "その他", + "ko": "다른", "nl": "anders", "pt": "Outro", "ru": "Другие", + "zh-chs": "其他", "xloc": [ "default-mobile.handlebars->dialog->3->dialog7->d7amtkvm->5->3" ] @@ -13039,10 +18137,13 @@ "en": "Other Settings", "es": "Otros ajustes", "fr": "Autres réglages", + "hi": "अन्य सेटिंग", "ja": "その他の設定", + "ko": "다른 설정", "nl": "Andere instellingen", "pt": "Outros ajustes", "ru": "Другие настройки", + "zh-chs": "其他設定", "xloc": [ "default.handlebars->container->dialog->dialogBody->dialog7->d7amtkvm->5->1" ] @@ -13053,12 +18154,15 @@ "en": "Out of date", "es": "Desactualizado", "fr": "Périmé", + "hi": "तारीख से बहार", "ja": "時代遅れ", + "ko": "오래된", "nl": "Verouderd", "pt": "Desatualizado", "ru": "Устаревший", + "zh-chs": "過時的", "xloc": [ - "default.handlebars->25->478" + "default.handlebars->27->485" ] }, { @@ -13066,12 +18170,16 @@ "de": "Eigener Prozess", "en": "OwnProcess", "es": "Tomar Proceso", + "fr": "OwnProcess", + "hi": "OwnProcess", "ja": "OwnProcess", + "ko": "자신의 프로세스", "nl": "Eigen proces", "pt": "Processo próprio", "ru": "Собственный процесс", + "zh-chs": "自己的過程", "xloc": [ - "default.handlebars->25->625" + "default.handlebars->27->674" ] }, { @@ -13079,13 +18187,17 @@ "de": "PID", "en": "PID", "es": "PID", + "fr": "PID", + "hi": "पीआईडी", "ja": "PID", + "ko": "PID", "nl": "PID", "pt": "PID", "ru": "PID", + "zh-chs": "PID", "xloc": [ "default-mobile.handlebars->container->page_content->column_l->p10->p10desktop->deskarea3->deskarea3x->DeskTools->5->1->0", - "default.handlebars->25->621", + "default.handlebars->27->670", "default.handlebars->container->column_l->p11->deskarea0->deskarea3x->DeskTools->deskToolsArea->DeskToolsProcessTab->deskToolsHeader->1" ] }, @@ -13095,12 +18207,15 @@ "en": "Part Number", "es": "Numero de Parte", "fr": "Numéro d'article", + "hi": "भाग संख्या", "ja": "品番", + "ko": "부품 번호", "nl": "Onderdeel nummer", "pt": "Número Parcial", "ru": "Part Number", + "zh-chs": "零件號", "xloc": [ - "default.handlebars->25->78" + "default.handlebars->27->789" ] }, { @@ -13109,12 +18224,15 @@ "en": "Partial", "es": "Parcial", "fr": "Partiel", + "hi": "आंशिक", "ja": "部分的", + "ko": "부분", "nl": "Gedeeltelijk", "pt": "Parcial", "ru": "Частично", + "zh-chs": "部分的", "xloc": [ - "default.handlebars->25->1222" + "default.handlebars->27->1352" ] }, { @@ -13122,27 +18240,45 @@ "de": "Partielle Gerätegruppenrechte", "en": "Partial Device Group Rights", "es": "Derechos parciales de grupo de dispositivos", + "fr": "Droits limités sur le groupe", + "hi": "आंशिक उपकरण समूह अधिकार", + "ja": "部分的なデバイスグループ権限", + "ko": "부분 장치 그룹 권한", "nl": "Gedeeltelijke apparaatgroep rechten", + "pt": "Direitos de grupo de dispositivos parciais", "ru": "Частичные права на группу устройств", - "xloc": [ - "default.handlebars->25->1030", - "default.handlebars->25->1295", - "default.handlebars->25->1369" - ] + "zh-chs": "部分設備組權限" + }, + { + "cs": "Částečná práva zařízení", + "de": "Teilgeräterechte", + "en": "Partial Device Rights", + "fr": "Droits partiels sur les appareils", + "hi": "आंशिक उपकरण अधिकार", + "ja": "部分的なデバイスの権利", + "ko": "부분 장치 권한", + "nl": "Gedeeltelijke apparaatrechten", + "pt": "Direitos Parciais do Dispositivo", + "ru": "Частичные права на устройство", + "zh-chs": "部分設備權利" }, { "cs": "Částečná práva", "de": "Partielle Rechte", "en": "Partial Rights", "es": "Privilegios Parciales", + "fr": "Droits limités", + "hi": "आंशिक अधिकार", "ja": "部分的権利", + "ko": "부분적인 권리", "nl": "Gedeeltelijke rechten", "pt": "Direitos parciais", "ru": "Частичные права", + "zh-chs": "部分權利", "xloc": [ - "default-mobile.handlebars->9->282", - "default-mobile.handlebars->9->63", - "default.handlebars->25->967" + "default-mobile.handlebars->9->286", + "default-mobile.handlebars->9->66", + "default.handlebars->27->1072" ] }, { @@ -13150,12 +18286,16 @@ "de": "Partielle Rechte", "en": "Partial rights", "es": "Privilegios Parciales", + "fr": "Droits limités", + "hi": "आंशिक अधिकार", "ja": "部分的権利", + "ko": "부분적인 권리", "nl": "Gedeeltelijke rechten", "pt": "Direitos parciais", "ru": "Частичные права", + "zh-chs": "部分權利", "xloc": [ - "default.handlebars->25->1321" + "default.handlebars->27->1455" ] }, { @@ -13163,10 +18303,14 @@ "de": "Pass-Tipp:", "en": "Pass Hint:", "es": "Pista de la contraseña:", + "fr": "Indice de réussite:", + "hi": "पास का संकेत:", "ja": "ヒントを渡す:", + "ko": "패스 힌트 :", "nl": "wachtwoord hint:", "pt": "Dica de passe:", "ru": "Подсказка пароля:", + "zh-chs": "通過提示:", "xloc": [ "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->createpanel->1->1->9->1->createPanelHint->1" ] @@ -13177,21 +18321,24 @@ "en": "Password", "es": "Contraseña", "fr": "Mot de passe", + "hi": "कुंजिका", "ja": "パスワード", + "ko": "암호", "nl": "wachtwoord", "pt": "Senha", "ru": "Пароль", + "zh-chs": "密碼", "xloc": [ - "default-mobile.handlebars->9->213", - "default.handlebars->25->1246", - "default.handlebars->25->1247", - "default.handlebars->25->1333", - "default.handlebars->25->1335", - "default.handlebars->25->1359", - "default.handlebars->25->1360", - "default.handlebars->25->243", - "default.handlebars->25->272", - "default.handlebars->25->548" + "default-mobile.handlebars->9->217", + "default.handlebars->27->1381", + "default.handlebars->27->1382", + "default.handlebars->27->1467", + "default.handlebars->27->1469", + "default.handlebars->27->1497", + "default.handlebars->27->1498", + "default.handlebars->27->227", + "default.handlebars->27->256", + "default.handlebars->27->595" ] }, { @@ -13199,13 +18346,17 @@ "de": "Passwort-Tipp", "en": "Password Hint", "es": "Pista de la contraseña:", + "fr": "Indice pour le mot de passe", + "hi": "पासवर्ड संकेत", "ja": "パスワードのヒント", + "ko": "비밀번호 힌트", "nl": "wachtwoord hint", "pt": "Dica de Senha", "ru": "Подсказка пароля", + "zh-chs": "密碼提示", "xloc": [ - "login-mobile.handlebars->5->19", - "login.handlebars->5->19" + "login-mobile.handlebars->5->22", + "login.handlebars->5->22" ] }, { @@ -13213,10 +18364,14 @@ "de": "Passwort-Tipp:", "en": "Password Hint:", "es": "Pista de la contraseña:", + "fr": "Indice pour le mot de passe:", + "hi": "पासवर्ड संकेत:", "ja": "パスワードのヒント:", + "ko": "비밀번호 힌트:", "nl": "wachtwoord hint:", "pt": "Dica de senha", "ru": "Подсказка пароля:", + "zh-chs": "密碼提示:", "xloc": [ "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->resetpasswordpanel->1->7->1->resetpasswordpanelHint->rnuHint", "login.handlebars->container->column_l->centralTable->1->0->logincell->createpanel->1->9->1->createPanelHint->nuHint", @@ -13228,16 +18383,20 @@ "de": "Passwort-Richtlinie", "en": "Password Policy", "es": "Política de contraseñas", + "fr": "Politique de mots de passe", + "hi": "पासवर्ड नीति", "ja": "パスワードポリシー", + "ko": "비밀번호 정책", "nl": "Wachtwoord beleid", "pt": "Política de senha", "ru": "Политика пароля", + "zh-chs": "密碼政策", "xloc": [ - "login-mobile.handlebars->5->23", - "login-mobile.handlebars->5->27", - "login.handlebars->5->23", - "login.handlebars->5->27", - "login.handlebars->5->34" + "login-mobile.handlebars->5->26", + "login-mobile.handlebars->5->30", + "login.handlebars->5->26", + "login.handlebars->5->30", + "login.handlebars->5->37" ] }, { @@ -13246,12 +18405,16 @@ "en": "Password change requested.", "es": "Cambio de Contraseña requerido.", "fr": "Changement de mot de passe demandé.", + "hi": "पासवर्ड परिवर्तन का अनुरोध किया।", "ja": "パスワードの変更が要求されました。", + "ko": "비밀번호 변경이 요청되었습니다.", "nl": "Wachtwoordwijziging aangevraagd.", + "pt": "Alteração de senha solicitada.", "ru": "Требуется смена пароля.", + "zh-chs": "要求更改密碼。", "xloc": [ - "login-mobile.handlebars->5->15", - "login.handlebars->5->15" + "login-mobile.handlebars->5->16", + "login.handlebars->5->16" ] }, { @@ -13259,12 +18422,16 @@ "de": "Passwort-Tipp", "en": "Password hint", "es": "Pista de la contraseña:", + "fr": "Indice pour le mot de passe", + "hi": "पासवर्ड संकेत", "ja": "パスワードのヒント", + "ko": "비밀번호 힌트", "nl": "wachtwoord hint", "pt": "Dica de senha", "ru": "Подсказка пароля", + "zh-chs": "密碼提示", "xloc": [ - "default.handlebars->25->1361" + "default.handlebars->27->1499" ] }, { @@ -13272,13 +18439,17 @@ "de": "Passwort-Tipp:", "en": "Password hint:", "es": "Pista de la contraseña:", + "fr": "Indice pour le mot de passe:", + "hi": "पासवर्ड संकेत:", "ja": "パスワードのヒント:", + "ko": "비밀번호 힌트:", "nl": "wachtwoord hint:", "pt": "Dica de senha", "ru": "Подсказка пароля:", + "zh-chs": "密碼提示:", "xloc": [ - "default-mobile.handlebars->9->47", - "default.handlebars->25->945" + "default-mobile.handlebars->9->50", + "default.handlebars->27->1050" ] }, { @@ -13286,12 +18457,16 @@ "de": "Passwörter stimmen nicht überein", "en": "Password mismatch", "es": "Contraseña no coincide", + "fr": "Le mot de passe ne concorde pas", + "hi": "पासवर्ड का मेल नहीं हुआ", "ja": "パスワード", + "ko": "암호 불일치", "nl": "Wachtwoord komt niet overeen", "pt": "Senha incorreta", "ru": "Пароль не совпадает", + "zh-chs": "密碼不符合", "xloc": [ - "default.handlebars->25->1047" + "default.handlebars->27->1151" ] }, { @@ -13300,12 +18475,16 @@ "en": "Password rejected, use a different one.", "es": "Contraseña rechazada, use una diferente.", "fr": "Mot de passe rejeté, utilisez-en un autre.", + "hi": "पासवर्ड खारिज कर दिया, एक अलग का उपयोग करें।", "ja": "パスワードが拒否されました。別のパスワードを使用してください。", + "ko": "비밀번호가 거부되었습니다. 다른 비밀번호를 사용하십시오.", "nl": "Wachtwoord geweigerd, gebruik een ander.", + "pt": "Senha rejeitada, use uma diferente.", "ru": "Пароль не принят, используйте другой.", + "zh-chs": "密碼被拒絕,請使用其他密碼。", "xloc": [ - "login-mobile.handlebars->5->7", - "login.handlebars->5->7" + "login-mobile.handlebars->5->8", + "login.handlebars->5->8" ] }, { @@ -13314,13 +18493,16 @@ "en": "Password*", "es": "Contraseña*", "fr": "Mot de passe*", + "hi": "कुंजिका*", "ja": "パスワード*", + "ko": "암호*", "nl": "Wachtwoord*", "pt": "Senha*", "ru": "Пароль*", + "zh-chs": "密碼*", "xloc": [ - "default.handlebars->25->1045", - "default.handlebars->25->1046" + "default.handlebars->27->1149", + "default.handlebars->27->1150" ] }, { @@ -13329,15 +18511,19 @@ "en": "Password:", "es": "Contraseña:", "fr": "Mot de passe:", + "hi": "कुंजिका:", "ja": "パスワード:", + "ko": "암호:", "nl": "Wachtwoord:", "pt": "Senha:", "ru": "Пароль:", + "zh-chs": "密碼:", "xloc": [ - "default-mobile.handlebars->9->39", - "default-mobile.handlebars->9->40", - "default.handlebars->25->937", - "default.handlebars->25->938", + "account-invite.html->2->5", + "default-mobile.handlebars->9->42", + "default-mobile.handlebars->9->43", + "default.handlebars->27->1042", + "default.handlebars->27->1043", "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->createpanel->1->1->9->1->4->1", "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->createpanel->1->1->9->1->6->1", "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->loginpanel->1->7->1->2->1", @@ -13356,18 +18542,21 @@ "en": "Paste", "es": "Pegar", "fr": "Coller", + "hi": "पेस्ट करें", "ja": "ペースト", + "ko": "풀", "nl": "Plakken", "pt": "Colar", "ru": "Вставить", + "zh-chs": "糊", "xloc": [ - "default-mobile.handlebars->9->260", - "default-mobile.handlebars->9->87", + "default-mobile.handlebars->9->264", + "default-mobile.handlebars->9->90", "default-mobile.handlebars->container->page_content->column_l->p10->p10files->p13toolbar->1->2->1->3", "default-mobile.handlebars->container->page_content->column_l->p5->p5myfiles->p5toolbar->1->0->1->3", - "default.handlebars->25->1185", - "default.handlebars->25->646", - "default.handlebars->25->668", + "default.handlebars->27->1315", + "default.handlebars->27->695", + "default.handlebars->27->717", "default.handlebars->container->column_l->p12->termTable->1->1->6->1->3", "default.handlebars->container->column_l->p13->p13toolbar->1->2->1->3", "default.handlebars->container->column_l->p5->p5toolbar->1->0->p5filehead->3" @@ -13379,10 +18568,13 @@ "en": "Paste text into the terminal", "es": "Pegar texto en la terminal", "fr": "Coller du texte dans le terminal", + "hi": "टेक्स्ट को टर्मिनल में पेस्ट करें", "ja": "端末にテキストを貼り付けます", + "ko": "터미널에 텍스트 붙여 넣기", "nl": "Plak tekst in de terminal", "pt": "Cole o texto no terminal", "ru": "Вставить текст в терминал", + "zh-chs": "將文本粘貼到終端中", "xloc": [ "default.handlebars->container->column_l->p12->termTable->1->1->6->1->3" ] @@ -13393,10 +18585,13 @@ "en": "Pause", "es": "Pausa", "fr": "Pause", + "hi": "ठहराव", "ja": "一時停止", + "ko": "중지", "nl": "Pause", "pt": "Pausa", "ru": "Пауза", + "zh-chs": "暫停", "xloc": [ "player.handlebars->p11->deskarea0->deskarea4->3" ] @@ -13407,12 +18602,15 @@ "en": "Perform Agent Action", "es": "Realizar acción en el agente", "fr": "Effectuer une action sur l'agent", + "hi": "एजेंट एक्शन करें", "ja": "エージェントアクションの実行", + "ko": "에이전트 작업 수행", "nl": "Agentactie uitvoeren", "pt": "Executar ação do agente", "ru": "Произвести действие агента", + "zh-chs": "執行代理動作", "xloc": [ - "default.handlebars->25->699" + "default.handlebars->27->800" ] }, { @@ -13420,12 +18618,16 @@ "de": "Aktivierung von Intel AMT im Admin Control Mode (ACM) in Gruppe \\\"{0}\\\" durchführen durch Herunterladen des MeshCMD-Werkzeugs und Ausführen wie folgt:", "en": "Perform Intel AMT admin control mode (ACM) activation to group \\\"{0}\\\" by downloading the MeshCMD tool and running it like this:", "es": "Realice la activación del modo de control de administración - Intel AMT (ACM) para agrupar \\\"{0}\\\" descargando la herramienta MeshCMD y ejecutándola así:", + "fr": "Effectuez l'activation du mode de contrôle d'administration (ACM) Intel AMT pour regrouper \\\"{0}\\\" en téléchargeant l'outil MeshCMD et en l'exécutant comme suit:", + "hi": "Intel AMT एडमिन कंट्रोल मोड (ACM) एक्टिवेशन को ग्रुप \\\"{0}\\\" पर करके, MeshCMD टूल डाउनलोड करके इसे इस तरह से चलाएं:", "ja": "MeshCMDツールをダウンロードして次のように実行することにより、グループ\\\"{0}\\\"にIntel AMT管理制御モード(ACM)アクティベーションを実行します。", + "ko": "MeshCMD 도구를 다운로드하고 다음과 같이 실행하여 \\\"{0}\\\"그룹에 대한 Intel AMT 관리자 제어 모드 (ACM) 활성화를 수행하십시오.", "nl": "Voer Intel AMT admin control mode (ACM) activering uit naar groep \\\"{0}\\\" door het hulpprogramma MeshCMD te downloaden en als volgt uit te voeren:", "pt": "Execute a ativação do modo de controle de administração Intel AMT (ACM) para agrupar \\\"{0}\\\" baixando a ferramenta MeshCMD e executando-a assim:", "ru": "Выполнить активацию Intel AMT в режиме управления администратора (ACM) для группы \\\"{0}\\\",скачав инструмент MeshCMD и запустив его следующим образом:", + "zh-chs": "通過下載MeshCMD工具並像下面這樣運行它,以執行Intel AMT管理員控制模式(ACM)激活以將 “{0}” 組:", "xloc": [ - "default.handlebars->25->250" + "default.handlebars->27->234" ] }, { @@ -13433,13 +18635,17 @@ "de": "Aktivierung von Intel AMT im Admin Control Mode (ACM) durchführen.", "en": "Perform Intel AMT admin control mode (ACM) activation.", "es": "Realice la activación del modo de control de administración Intel AMT (ACM).", + "fr": "Effectuez l'activation du mode de contrôle administrateur (ACM) Intel AMT.", + "hi": "Intel AMT व्यवस्थापक नियंत्रण मोड (ACM) सक्रियण करें।", "ja": "Intel AMT管理制御モード(ACM)アクティベーションを実行します。", + "ko": "Intel AMT 관리자 제어 모드 (ACM) 활성화를 수행하십시오.", "nl": "Voer Intel AMT admin control mode (ACM) activering uit.", "pt": "Execute a ativação do modo de controle de administração Intel AMT (ACM).", "ru": "Выполнить активацию Intel AMT в режиме управления администратора (ACM).", + "zh-chs": "執行英特爾AMT管理員控制模式(ACM)激活。", "xloc": [ - "default.handlebars->25->1023", - "default.handlebars->25->231" + "default.handlebars->27->1130", + "default.handlebars->27->215" ] }, { @@ -13447,12 +18653,16 @@ "de": "Aktivierung von Intel AMT im Client Control Mode (CCM) in Gruppe \\\"{0}\\\" durchführen durch Herunterladen des MeshCMD-Werkzeugs und Ausführen wie folgt:", "en": "Perform Intel AMT client control mode (CCM) activation to group \\\"{0}\\\" by downloading the MeshCMD tool and running it like this:", "es": "Realice la activación del modo de control de cliente Intel AMT (CCM) para agrupar \\\"{0}\\\" descargando la herramienta MeshCMD y ejecutándola así:", + "fr": "Exécutez l'activation du mode de contrôle client Intel AMT (CCM) pour regrouper \\\"{0}\\\" en téléchargeant l'outil MeshCMD et en l'exécutant comme suit:", + "hi": "Intel AMT क्लाइंट कंट्रोल मोड (CCM) को ग्रुप \\\"{0}\\\" पर एक्टिवेट करके MeshCMD टूल डाउनलोड करें और इसे इस तरह से चलाएं:", "ja": "MeshCMDツールをダウンロードして次のように実行することにより、グループ\\\"{0}\\\"にIntel AMTクライアントコントロールモード(CCM)アクティベーションを実行します。", + "ko": "MeshCMD 도구를 다운로드하고 다음과 같이 실행하여 \\\"{0}\\\"그룹에 대한 Intel AMT CCM (Client Control Mode) 활성화를 수행하십시오.", "nl": "Voer Intel AMT client control mode (CCM) activering uit naar groep \\\"{0}\\\" door het hulpprogramma MeshCMD te downloaden en als volgt uit te voeren:", "pt": "Execute a ativação do modo de controle de cliente Intel AMT (CCM) para agrupar \\\"{0}\\\" baixando a ferramenta MeshCMD e executando-a assim:", "ru": "Выполнить активацию Intel AMT в режиме управления клиента (CCM) для группы \\\"{0}\\\",скачав инструмент MeshCMD и запустив его следующим образом:", + "zh-chs": "通過下載MeshCMD工具並像下面這樣運行,來執行Intel AMT客戶端控制模式(CCM)激活以將\\“{0}\\”分組:", "xloc": [ - "default.handlebars->25->248" + "default.handlebars->27->232" ] }, { @@ -13460,13 +18670,17 @@ "de": "Aktivierung von Intel AMT im Client Control Mode (CCM) durchführen.", "en": "Perform Intel AMT client control mode (CCM) activation.", "es": "Realice la activación del modo de control de cliente Intel AMT (CCM).", + "fr": "Effectuez l'activation du mode de contrôle client Intel AMT (CCM).", + "hi": "Intel AMT क्लाइंट कंट्रोल मोड (CCM) सक्रियण करें।", "ja": "Intel AMTクライアント制御モード(CCM)アクティベーションを実行します。", + "ko": "Intel AMT 클라이언트 제어 모드 (CCM) 활성화를 수행하십시오.", "nl": "Voer Intel AMT client control mode (CCM) activering uit.", "pt": "Execute a ativação do modo de controle do cliente Intel AMT (CCM).", "ru": "Выполнить активацию Intel AMT в режиме управления клиента (CCM).", + "zh-chs": "執行英特爾AMT客戶端控制模式(CCM)激活。", "xloc": [ - "default.handlebars->25->1021", - "default.handlebars->25->229" + "default.handlebars->27->1128", + "default.handlebars->27->213" ] }, { @@ -13475,12 +18689,15 @@ "en": "Perform power actions on the device", "es": "Realizar acciones de energía en el dispositivo", "fr": "Effectuer des actions d'alimentation sur le périphérique", + "hi": "डिवाइस पर पावर क्रियाएं करें", "ja": "デバイスの電源操作を実行します", + "ko": "장치에서 전원 작업 수행", "nl": "Voer power acties uit op het apparaat", "pt": "Execute ações de energia no dispositivo", "ru": "Управление питанием устройства", + "zh-chs": "在設備上執行電源操作", "xloc": [ - "default.handlebars->25->495", + "default.handlebars->27->502", "default.handlebars->container->column_l->p11->deskarea0->deskarea1->1", "default.handlebars->container->column_l->p12->termTable->1->1->0->1->1", "default.handlebars->container->column_l->p13->p13toolbar->1->0->1->1" @@ -13492,14 +18709,17 @@ "en": "Permissions", "es": "Permisos", "fr": "Permissions", + "hi": "अनुमतियां", "ja": "許可", + "ko": "권한", "nl": "machtigingen", "pt": "Permissões", "ru": "Права", + "zh-chs": "權限", "xloc": [ - "default-mobile.handlebars->9->329", - "default.handlebars->25->1134", - "default.handlebars->25->1206" + "default-mobile.handlebars->9->333", + "default.handlebars->27->1247", + "default.handlebars->27->1336" ] }, { @@ -13507,31 +18727,47 @@ "de": "Persisch (Iran)", "en": "Persian/Iran", "es": "Persa / Irán", + "fr": "Perse/Iranien", + "hi": "फारसी / ईरान", "ja": "ペルシャ語/イラン", + "ko": "페르시아어 /이란", "nl": "Perzisch / Iran", "pt": "Persa / Irã", "ru": "Персидский/Иран", + "zh-chs": "波斯/伊朗", "xloc": [ - "default.handlebars->25->849" + "default.handlebars->27->953" ] }, { + "cs": "Umístěte odkaz do tohoto zařízení do schránky", + "de": "Platzieren Sie den Link zu diesem Gerät in der Zwischenablage", "en": "Place link to this device in the clipboard", "es": "Coloque el enlace a este dispositivo en el portapapeles", + "fr": "Mettre le lien dans le presse-papier de cet appareil", + "hi": "इस डिवाइस का लिंक क्लिपबोर्ड में रखें", + "ja": "このデバイスへのリンクをクリップボードに配置します", + "ko": "이 장치에 대한 링크를 클립 보드에 배치", "nl": "Plaats de link naar dit apparaat op het klembord", - "ru": "Скопировать ссылку на это устройство в буфер обмена" + "pt": "Coloque o link para este dispositivo na área de transferência", + "ru": "Скопировать ссылку на это устройство в буфер обмена", + "zh-chs": "將指向此設備的鏈接放在剪貼板中" }, { "cs": "Umístit uzel sem", "de": "Knoten hier ablegen", "en": "Place node here", "es": "Coloque el nodo aquí", + "fr": "Placer un noeud ici", + "hi": "यहाँ नोड रखें", "ja": "ここにノードを配置", + "ko": "여기에 노드를 배치", "nl": "Plaats hier een knooppunt", "pt": "Coloque o nó aqui", "ru": "Поместить узел сюда", + "zh-chs": "將節點放在這裡", "xloc": [ - "default.handlebars->25->427" + "default.handlebars->27->431" ] }, { @@ -13540,10 +18776,13 @@ "en": "Play", "es": "Iniciar", "fr": "Jouer", + "hi": "खेल", "ja": "遊びます", + "ko": "플레이", "nl": "Afspelen", "pt": "Play", "ru": "Воспроизвести", + "zh-chs": "玩", "xloc": [ "player.handlebars->p11->deskarea0->deskarea4->3" ] @@ -13554,12 +18793,15 @@ "en": "Please add two-factor backup codes. If the current factor is lost, there is not way to recover this account.", "es": "Agregue códigos de respaldo de dos factores. Si se pierde el factor actual, no hay forma de recuperar esta cuenta.", "fr": "Veuillez ajouter un autre facteur. Si le facteur actuel est perdu, il n'y a pas moyen de récupérer ce compte.", + "hi": "कृपया दो-कारक बैकअप कोड जोड़ें। यदि वर्तमान कारक खो गया है, तो इस खाते को पुनर्प्राप्त करने का कोई तरीका नहीं है।", "ja": "二要素バックアップコードを追加してください。現在の要因が失われた場合、このアカウントを回復する方法はありません。", + "ko": "2 단계 백업 코드를 추가하십시오. 현재 요소가 손실되면이 계정을 복구 할 수 없습니다.", "nl": "Voeg back-upcodes met twee factoren toe. Als de huidige factor verloren gaat, is er geen manier om dit account te herstellen.", "pt": "Adicione códigos de backup de dois fatores. Se o fator atual for perdido, não há como recuperar esta conta.", "ru": "Пожалуйста, добавьте двухфакторные резервные коды. Если текущий фактор потерян, восстановить эту учетную запись будет невозможно.", + "zh-chs": "請添加兩個因素的備用驗證碼。如果丟失了當前因素,則無法恢復該帳戶。", "xloc": [ - "default.handlebars->25->49" + "default.handlebars->27->49" ] }, { @@ -13567,11 +18809,16 @@ "de": "Bitte beachten Sie, dass ein Downgrade nicht empfohlen wird. Bitte tun Sie dies nur für den Fall, dass ein kürzlich durchgeführtes Upgrade einen Defekt aufweist.", "en": "Please be aware that downgrading is not recommended. Please only do so in the event that a recent upgrade has broken something.", "es": "Tenga en cuenta que no se recomienda bajar de version. Solo hágalo en caso de que una actualización reciente haya roto algo.", + "fr": "Attention l'installation d'une version antérieure n'est pas recommandée. Ne faite cette opération que si un évènement récent empêche le fonctionnement normal.", + "hi": "कृपया ध्यान रखें कि डाउनग्रेड करने की अनुशंसा नहीं की जाती है। कृपया केवल इस घटना में ऐसा करें कि हाल ही में अपग्रेड कुछ टूट गया है।", "ja": "ダウングレードは推奨されないことに注意してください。最近のアップグレードで何かが壊れた場合にのみ行ってください。", + "ko": "다운 그레이드는 권장되지 않습니다. 최근 업그레이드로 인해 문제가 발생한 경우에만 수행하십시오.", "nl": "Houd er rekening mee dat downgraden niet wordt aanbevolen. Doe dit alleen als een recente upgrade iets heeft gebroken.", + "pt": "Esteja ciente de que a desclassificação não é recomendada. Faça isso apenas no caso de uma atualização recente ter quebrado alguma coisa.", "ru": "Внимание, понижение версии не рекомендуется. Делайте это только в том случае, если недавнее обновление что-то сломало.", + "zh-chs": "請注意,不建議降級。請僅在最近的升級損壞了某些情況時才這樣做。", "xloc": [ - "default.handlebars->25->178" + "default.handlebars->27->161" ] }, { @@ -13579,10 +18826,14 @@ "de": "Bitte wenden Sie sich bezüglich der Nutzungsbedingungen an den Site-Administrator.", "en": "Please contact the site administrator for terms of use.", "es": "Póngase en contacto con el administrador del sitio para conocer los términos de uso.", + "fr": "Contactez l'administrateur du site pour obtenir les CGU", + "hi": "उपयोग की शर्तों के लिए कृपया साइट व्यवस्थापक से संपर्क करें।", "ja": "利用規約については、サイト管理者にお問い合わせください。", + "ko": "이용 약관에 대해서는 사이트 관리자에게 문의하십시오.", "nl": "Neem contact op met de sitebeheerder voor gebruiksvoorwaarden.", "pt": "Entre em contato com o administrador do site para obter os termos de uso.", "ru": "Свяжитесь с администратором сайта для получения условий пользования.", + "zh-chs": "請與站點管理員聯繫以獲取使用條款。", "xloc": [ "terms-mobile.handlebars->container->page_content->column_l->3", "terms.handlebars->container->column_l->3" @@ -13593,13 +18844,17 @@ "de": "Bitte warten Sie einige Minuten, um die Bestätigung zu erhalten.", "en": "Please wait a few minute to receive the verification.", "es": "Espere unos minutos para recibir la verificación.", + "fr": "Merci de patienter quelques minutes pour recevoir la vérification.", + "hi": "कृपया सत्यापन प्राप्त करने के लिए कुछ मिनट प्रतीक्षा करें।", "ja": "確認を受けるまで数分お待ちください。", + "ko": "확인을 받으려면 몇 분 정도 기다려주십시오.", "nl": "Wacht enkele minuten om de verificatie te ontvangen.", "pt": "Aguarde alguns minutos para receber a verificação.", "ru": "Подождите пару минут для получения подтверждения.", + "zh-chs": "請等待幾分鐘以接收驗證。", "xloc": [ - "default-mobile.handlebars->9->35", - "default.handlebars->25->932" + "default-mobile.handlebars->9->38", + "default.handlebars->27->1037" ] }, { @@ -13607,12 +18862,17 @@ "de": "Plugin-Aktion", "en": "Plugin Action", "es": "Plugin Action", + "fr": "Action du plugin", + "hi": "प्लगिन एक्शन", "ja": "プラグインアクション", + "ko": "플러그인 액션", "nl": "Plugin Actie", + "pt": "Ação do Plugin", "ru": "Действие плагина", + "zh-chs": "插件動作", "xloc": [ - "default.handlebars->25->1461", - "default.handlebars->25->177" + "default.handlebars->27->160", + "default.handlebars->27->1613" ] }, { @@ -13620,20 +18880,33 @@ "de": "Plugin-Fehler", "en": "Plugin Error", "es": "Error en el Plugin", + "fr": "Erreur du module", + "hi": "प्लगिन त्रुटि", "ja": "プラグインエラー", + "ko": "플러그인 오류", "nl": "Plugin fout", + "pt": "Erro de plug-in", "ru": "Ошибка плагина", + "zh-chs": "插件錯誤", "xloc": [ - "default.handlebars->25->179" + "default.handlebars->27->162" ] }, { "cs": "PluginHandler nemohlo zprávu události: ", + "de": "PluginHandler konnte keine Ereignismeldung anzeigen:", "en": "PluginHandler could not event message: ", "es": "PluginHandler no pudo enviar el mensaje de evento:", + "fr": "PluginHandler n'a pas pu message d'événement:", + "hi": "PluginHandler संदेश को ईवेंट नहीं कर सका:", + "ja": "PluginHandlerはイベントメッセージを取得できませんでした:", + "ko": "PluginHandler가 이벤트 메시지를 작성할 수 없습니다.", "nl": "PluginHandler kon geen gebeurtenisbericht weergeven: ", + "pt": "O PluginHandler não pôde receber a mensagem:", + "ru": "PluginHandler не смог сообщение о событии:", + "zh-chs": "PluginHandler無法事件消息:", "xloc": [ - "default.handlebars->25->167" + "default.handlebars->27->150" ] }, { @@ -13641,10 +18914,14 @@ "de": "Plugins", "en": "Plugins", "es": "Plugins", + "fr": "Modules", + "hi": "प्लगइन्स", "ja": "プラグイン", + "ko": "플러그인", "nl": "Plugins", "pt": "Plugins", "ru": "Плагины", + "zh-chs": "外掛程式", "xloc": [ "default.handlebars->container->topbar->1->1->MainSubMenuSpan->MainSubMenu->1->0->MainDevPlugins", "default.handlebars->container->topbar->1->1->ServerSubMenuSpan->ServerSubMenu->1->0->ServerPlugins" @@ -13655,10 +18932,14 @@ "de": "Plugins -", "en": "Plugins -", "es": "Plugins -", + "fr": "Modules -", + "hi": "प्लगइन्स -", "ja": "プラグイン-", + "ko": "플러그인-", "nl": "Plugins -", "pt": "Plugins -", "ru": "Плагины - ", + "zh-chs": "插件-", "xloc": [ "default.handlebars->container->column_l->p19->p19title->3" ] @@ -13668,9 +18949,14 @@ "de": "Plugins wurden geändert. Dies erfordert möglicherweise eine Aktualisierung der Agentenkerne.", "en": "Plugins have been altered, this may require agent core update.", "es": "Se han modificado los plugins, esto puede requerir la actualización del núcleo del agente.", + "fr": "Les modules ont été modifiés, une mise à jour des agents est nécesssaire", + "hi": "प्लगइन्स को बदल दिया गया है, इसके लिए एजेंट कोर अपडेट की आवश्यकता हो सकती है।", "ja": "プラグインが変更されたため、エージェントコアの更新が必要になる場合があります。", + "ko": "플러그인이 변경되었습니다. 에이전트 코어 업데이트가 필요할 수 있습니다.", "nl": "Plug-ins zijn gewijzigd, dit kan een update van de agent vereisen.", + "pt": "Os plug-ins foram alterados, isso pode exigir atualização do núcleo do agente.", "ru": "Плагины были изменены, это может потребовать обновление ядра агента.", + "zh-chs": "插件已更改,這可能需要代理核心更新。", "xloc": [ "default.handlebars->container->column_l->p42->pluginRestartNotice->3->1" ] @@ -13680,13 +18966,17 @@ "de": "PogoPlug ARM", "en": "PogoPlug ARM", "es": "PogoPlug ARM", + "fr": "PogoPlug ARM", + "hi": "पोगोप्लग एआरएम", "ja": "PogoPlug ARM", + "ko": "포고 플러그 ARM", "nl": "PogoPlug ARM", "pt": "PogoPlug ARM", "ru": "PogoPlug ARM", + "zh-chs": "PogoPlug ARM", "xloc": [ - "default-mobile.handlebars->9->156", - "default.handlebars->25->26" + "default-mobile.handlebars->9->160", + "default.handlebars->27->26" ] }, { @@ -13695,13 +18985,16 @@ "en": "Policy", "es": "Política", "fr": "Politique", + "hi": "नीति", "ja": "方針", + "ko": "수단", "nl": "Beleid", "pt": "Política", "ru": "Политика", + "zh-chs": "政策", "xloc": [ - "default-mobile.handlebars->9->62", - "default.handlebars->25->966" + "default-mobile.handlebars->9->65", + "default.handlebars->27->1071" ] }, { @@ -13709,12 +19002,16 @@ "de": "Polnisch", "en": "Polish", "es": "Polaco", + "fr": "Polonais", + "hi": "पोलिश", "ja": "研磨", + "ko": "광택", "nl": "Pools", "pt": "polonês", "ru": "Польский", + "zh-chs": "拋光", "xloc": [ - "default.handlebars->25->850" + "default.handlebars->27->954" ] }, { @@ -13722,12 +19019,16 @@ "de": "Portugiesisch", "en": "Portuguese", "es": "Portugues", + "fr": "Portugais", + "hi": "पुर्तगाली", "ja": "ポルトガル語", + "ko": "포르투갈 인", "nl": "Portugees", "pt": "Português", "ru": "Португальский", + "zh-chs": "葡萄牙語", "xloc": [ - "default.handlebars->25->851" + "default.handlebars->27->955" ] }, { @@ -13735,12 +19036,16 @@ "de": "Portugiesisch (Brasilien)", "en": "Portuguese (Brazil)", "es": "Portugues (Brazil)", + "fr": "Portugais (Brésil)", + "hi": "पुर्तगाली (ब्राज़ील)", "ja": "ポルトガル語(ブラジル)", + "ko": "포르투갈어 (브라질)", "nl": "Portugees (Brazilië)", "pt": "Português (Brasil)", "ru": "Португальский (Бразилия)", + "zh-chs": "葡萄牙語(巴西)", "xloc": [ - "default.handlebars->25->852" + "default.handlebars->27->956" ] }, { @@ -13748,10 +19053,14 @@ "de": "Energiezustand", "en": "Power", "es": "Encender", + "fr": "Allumé", + "hi": "शक्ति", "ja": "力", + "ko": "힘", "nl": "Power", "pt": "Ligar", "ru": "Питание", + "zh-chs": "功率", "xloc": [ "default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->9->devListToolbarSort->sortselect->3" ] @@ -13761,10 +19070,14 @@ "de": "Energiezustandsaktionen", "en": "Power Actions...", "es": "Acciones de encendido ...", + "fr": "Actions de puissance ...", + "hi": "पावर एक्शन ...", "ja": "電源アクション...", + "ko": "전원 동작 ...", "nl": "Power Actie's...", "pt": "Ações de energia (Ligar/Desligar)", "ru": "Управление питанием...", + "zh-chs": "電源動作...", "xloc": [ "default-mobile.handlebars->container->page_content->column_l->p10->p10desktop->deskarea4->1->3", "default.handlebars->container->column_l->p11->deskarea0->deskarea1->1" @@ -13775,10 +19088,16 @@ "de": "Energiezustände", "en": "Power States", "es": "Estados de Encendido", + "fr": "Statistiques d'alimentation", + "hi": "पावर स्टेट्स", + "ja": "電力状態", + "ko": "전원 상태", "nl": "Power Status", + "pt": "Estados de potência", "ru": "Состояния питания", + "zh-chs": "電力國", "xloc": [ - "default.handlebars->25->1148", + "default.handlebars->27->1276", "default.handlebars->container->column_l->p21->3->1->meshPowerChartDiv->1" ] }, @@ -13788,15 +19107,18 @@ "en": "Power off", "es": "Apagar", "fr": "Éteindre", + "hi": "बिजली बंद", "ja": "電源を切る", + "ko": "전원 끄기", "nl": "Uitzetten", "pt": "Desligar", "ru": "Выключить", + "zh-chs": "斷電", "xloc": [ - "default-mobile.handlebars->9->105", - "default-mobile.handlebars->9->209", - "default.handlebars->25->539", - "default.handlebars->25->6" + "default-mobile.handlebars->9->109", + "default-mobile.handlebars->9->213", + "default.handlebars->27->586", + "default.handlebars->27->6" ] }, { @@ -13805,12 +19127,15 @@ "en": "Power off devices", "es": "Apagar dispositivos", "fr": "Éteindre les appareils", + "hi": "उपकरणों को बंद करें", "ja": "デバイスの電源を切る", + "ko": "장치 전원 끄기", "nl": "Schakel apparaten uit", "pt": "Desligar dispositivos", "ru": "Выключить устройства", + "zh-chs": "關閉設備電源", "xloc": [ - "default.handlebars->25->390" + "default.handlebars->27->380" ] }, { @@ -13819,15 +19144,18 @@ "en": "Powered", "es": "Encendido", "fr": "Alimenté", + "hi": "संचालित", "ja": "パワード", + "ko": "강화", "nl": "ingeschakeld", "pt": "Ligado", "ru": "Включено", + "zh-chs": "供電", "xloc": [ - "default-mobile.handlebars->9->100", - "default-mobile.handlebars->9->107", - "default.handlebars->25->1", - "default.handlebars->25->350" + "default-mobile.handlebars->9->104", + "default-mobile.handlebars->9->111", + "default.handlebars->27->1", + "default.handlebars->27->340" ] }, { @@ -13836,15 +19164,18 @@ "en": "Present", "es": "Presente", "fr": "Présent", + "hi": "वर्तमान", "ja": "プレゼント", + "ko": "선물", "nl": "Aanwezig", "pt": "Presente", "ru": "Текущее состояние", + "zh-chs": "當下", "xloc": [ - "default-mobile.handlebars->9->106", - "default-mobile.handlebars->9->113", - "default.handlebars->25->362", - "default.handlebars->25->7" + "default-mobile.handlebars->9->110", + "default-mobile.handlebars->9->117", + "default.handlebars->27->352", + "default.handlebars->27->7" ] }, { @@ -13853,13 +19184,16 @@ "en": "Press [space] to play/pause.", "es": "Presiona [espacio] para reproducir / pausar.", "fr": "Appuyez sur [espace] pour jouer/mettre en pause.", + "hi": "प्रेस [स्थान] खेलने के लिए / रोकें।", "ja": "[スペース]を押して再生/一時停止します。", + "ko": "재생 / 일시 정지하려면 [space]를 누르십시오.", "nl": "Druk op [spatie] om te spelen / pauzeren.", "pt": "Pressione [espaço] para reproduzir / pausar.", "ru": "Нажмите [пробел] для проигрывания/паузы.", + "zh-chs": "按[空格]播放/暫停。", "xloc": [ - "player.handlebars->3->16", - "player.handlebars->3->17" + "player.handlebars->3->18", + "player.handlebars->3->19" ] }, { @@ -13868,12 +19202,15 @@ "en": "Press the key button now.", "es": "Presione una tecla ahora.", "fr": "Appuyez sur le bouton de la clé maintenant.", + "hi": "अब कुंजी बटन दबाएं।", "ja": "ここでキーボタンを押します。", + "ko": "지금 키 버튼을 누르십시오.", "nl": "Druk nu op de sleutelknop.", "pt": "Pressione o botão da tecla agora.", "ru": "Нажмите кнопку ключа сейчас.", + "zh-chs": "現在按下按鍵。", "xloc": [ - "default.handlebars->25->150" + "default.handlebars->27->133" ] }, { @@ -13881,13 +19218,17 @@ "de": "Prozesskontrolle", "en": "Process Control", "es": "Control de procesos", + "fr": "Contrôle de processus", + "hi": "प्रक्रिया नियंत्रण", "ja": "プロセス制御", + "ko": "공정 제어", "nl": "Proces controle", "pt": "Controle do processo", "ru": "Управление процессами", + "zh-chs": "過程控制", "xloc": [ - "default-mobile.handlebars->9->234", - "default.handlebars->25->633" + "default-mobile.handlebars->9->238", + "default.handlebars->27->682" ] }, { @@ -13896,10 +19237,13 @@ "en": "Processes", "es": "Procesos", "fr": "Processus", + "hi": "प्रक्रियाओं", "ja": "プロセス", + "ko": "프로세스", "nl": "Processen", "pt": "Processos", "ru": "Процессы", + "zh-chs": "工藝流程", "xloc": [ "default-mobile.handlebars->container->page_content->column_l->p10->p10desktop->deskarea3->deskarea3x->DeskTools->DeskToolsBar", "default.handlebars->container->column_l->p11->deskarea0->deskarea3x->DeskTools->deskToolsAreaTop->deskToolsTopTabProcess" @@ -13911,14 +19255,17 @@ "en": "Prompt for user consent", "es": "Solicitar consentimiento del usuario", "fr": "Demander le consentement de l'utilisateur", + "hi": "उपयोगकर्ता की सहमति के लिए शीघ्र", "ja": "ユーザーの同意を求める", + "ko": "사용자 동의 요청", "nl": "Vraag gebruikerstoestemming", "pt": "Solicitar consentimento do usuário", "ru": "Запрос согласия пользователя", + "zh-chs": "提示用戶同意", "xloc": [ - "default.handlebars->25->1071", - "default.handlebars->25->1075", - "default.handlebars->25->1078" + "default.handlebars->27->1175", + "default.handlebars->27->1179", + "default.handlebars->27->1182" ] }, { @@ -13927,63 +19274,110 @@ "en": "Protocol", "es": "Protocolo", "fr": "Protocole", + "hi": "मसविदा बनाना", "ja": "プロトコル", + "ko": "실험 계획안", "nl": "Protocol", "pt": "Protocolo", "ru": "Протокол", + "zh-chs": "協議", "xloc": [ "player.handlebars->3->15" ] }, + { + "cs": "Režim poskytování", + "de": "Bereitstellungsmodus", + "en": "Provisioning Mode", + "fr": "Mode d'approvisionnement", + "hi": "प्रावधान मोड", + "ja": "プロビジョニングモード", + "ko": "프로비저닝 모드", + "nl": "Provisioning Modus", + "pt": "Modo de provisionamento", + "ru": "Режим обеспечения", + "zh-chs": "供應模式" + }, + { + "cs": "Poskytující stát", + "de": "Bereitstellungsstaat", + "en": "Provisioning State", + "fr": "État d'approvisionnement", + "hi": "प्रावधान राज्य", + "ja": "プロビジョニング状態", + "ko": "프로비저닝 상태", + "nl": "Provisioning Staat", + "pt": "Estado de provisionamento", + "ru": "Предоставление государства", + "zh-chs": "供應國", + "xloc": [ + "default.handlebars->27->769" + ] + }, { "cs": "Veřejný odkaz", "de": "Öffentlicher Link", "en": "Public Link", "es": "Enlace publico", "fr": "Lien public", + "hi": "सार्वजनिक लिंक", "ja": "公開リンク", + "ko": "공개 링크", "nl": "Publieke link", "pt": "Link Público", "ru": "Публичная ссылка", + "zh-chs": "公開連結", "xloc": [ - "default-mobile.handlebars->9->74", - "default.handlebars->25->1171" + "default-mobile.handlebars->9->77", + "default.handlebars->27->1300" ] }, { "cs": "paňdžábština", "de": "Punjabi", "en": "Punjabi", + "fr": "Punjabi", + "hi": "पंजाबी", "ja": "パンジャブ語", + "ko": "펀 자브", "nl": "Punjabi", "pt": "Punjabi", "ru": "Пенджаби", + "zh-chs": "旁遮普語", "xloc": [ - "default.handlebars->25->853" + "default.handlebars->27->957" ] }, { "cs": "paňdžábština (Indie)", "de": "Punjabi (Indien)", "en": "Punjabi (India)", + "fr": "Punjabi (Inde)", + "hi": "पंजाबी (भारत)", "ja": "パンジャブ語(インド)", + "ko": "펀자 브어 (인도)", "nl": "Punjabi (India)", "pt": "Punjabi (Índia)", "ru": "Пенджаби (Индия)", + "zh-chs": "旁遮普(印度)", "xloc": [ - "default.handlebars->25->854" + "default.handlebars->27->958" ] }, { "cs": "paňdžábština (Pákistán)", "de": "Punjabi (Pakistan)", "en": "Punjabi (Pakistan)", + "fr": "Punjabi (Pakistan)", + "hi": "पंजाबी (पाकिस्तान)", "ja": "パンジャブ語(パキスタン)", + "ko": "펀자 브어 (파키스탄)", "nl": "Punjabi (Pakistan)", "pt": "Punjabi (Paquistão)", "ru": "Пенджаби (Пакистан)", + "zh-chs": "旁遮普(巴基斯坦)", "xloc": [ - "default.handlebars->25->855" + "default.handlebars->27->959" ] }, { @@ -13991,12 +19385,16 @@ "de": "Putty", "en": "Putty", "es": "Putty", + "fr": "Putty", + "hi": "पोटीन", "ja": "パテ", + "ko": "퍼티", "nl": "Putty", "pt": "Putty", "ru": "Putty", + "zh-chs": "油灰", "xloc": [ - "default.handlebars->25->515" + "default.handlebars->27->522" ] }, { @@ -14005,10 +19403,13 @@ "en": "Quality", "es": "Calidad", "fr": "Qualité", + "hi": "गुणवत्ता", "ja": "品質", + "ko": "품질", "nl": "Kwaliteit", "pt": "Qualidade", "ru": "Качество", + "zh-chs": "質量", "xloc": [ "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->3->3", "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->3->1" @@ -14018,12 +19419,16 @@ "cs": "kečuánština", "de": "Quechua", "en": "Quechua", + "fr": "Quechua", + "hi": "क्वेशुआ", "ja": "ケチュア", + "ko": "케 추아 어", "nl": "Quechua", "pt": "Quechua", "ru": "Кечуа", + "zh-chs": "蓋丘亞族", "xloc": [ - "default.handlebars->25->856" + "default.handlebars->27->960" ] }, { @@ -14032,10 +19437,13 @@ "en": "RAW16, Very Slow", "es": "RAW16, Muy Lento", "fr": "RAW16, très lent", + "hi": "RAW16, बहुत धीमा", "ja": "RAW16、非常に遅い", + "ko": "RAW16, 매우 느림", "nl": "RAW16, Zeer langzaam", "pt": "RAW16, muito lento", "ru": "RAW16, очень медленно", + "zh-chs": "RAW16,非常慢", "xloc": [ "default-mobile.handlebars->dialog->3->dialog7->d7amtkvm->3->d7desktopmode->7", "default.handlebars->container->dialog->dialogBody->dialog7->d7amtkvm->3->d7desktopmode->7" @@ -14047,10 +19455,13 @@ "en": "RAW8, Slow", "es": "RAW8, Lento", "fr": "RAW8, lent", + "hi": "RAW8, धीमा", "ja": "RAW8、遅い", + "ko": "RAW8, 느림", "nl": "RAW8, langzaam", "pt": "RAW8, lento", "ru": "RAW8, медленно", + "zh-chs": "RAW8,慢", "xloc": [ "default-mobile.handlebars->dialog->3->dialog7->d7amtkvm->3->d7desktopmode->5", "default.handlebars->container->dialog->dialogBody->dialog7->d7amtkvm->3->d7desktopmode->5" @@ -14060,37 +19471,64 @@ "cs": "RDP", "de": "RDP", "en": "RDP", + "es": "RDP", + "fr": "RDP", + "hi": "आरडीपी", "ja": "RDP", + "ko": "RDP", "nl": "RDP", "pt": "RDP", "ru": "RDP", + "zh-chs": "RDP", "xloc": [ - "default.handlebars->25->513" + "default.handlebars->27->520" ] }, { + "cs": "Připojení RDP", + "de": "RDP-Verbindung", "en": "RDP Connection", + "fr": "Connection RDP", + "hi": "RDP कनेक्शन", + "ja": "RDP接続", + "ko": "RDP 연결", "nl": "RDP verbinding", + "pt": "Conexão RDP", "ru": "Подключение RDP", + "zh-chs": "RDP連接", "xloc": [ - "default.handlebars->25->413" + "default.handlebars->27->413" ] }, { + "cs": "Port vzdáleného připojení RDP:", + "de": "RDP-Remoteverbindungsport:", "en": "RDP remote connection port:", + "fr": "Port RDP distant :", + "hi": "RDP रिमोट कनेक्शन पोर्ट:", + "ja": "RDPリモート接続ポート:", + "ko": "RDP 원격 연결 포트 :", "nl": "RDP externe verbindings poort:", + "pt": "Porta de conexão remota RDP:", "ru": "Порт RDP:", + "zh-chs": "RDP遠程連接端口:", "xloc": [ - "default.handlebars->25->412" + "default.handlebars->27->412" ] }, { + "cs": "RDP2", + "de": "RDP2", "en": "RDP2", + "es": "RDP2", + "fr": "RDP2", + "hi": "RDP2", + "ja": "RDP2", + "ko": "RDP2", "nl": "RDP2", + "pt": "RDP2", "ru": "RDP2", - "xloc": [ - "default.handlebars->25->414" - ] + "zh-chs": "RDP2" }, { "cs": "RLE16, doporučeno", @@ -14098,10 +19536,13 @@ "en": "RLE16, Recommended", "es": "RLE16, recomendado", "fr": "RLE16, recommandé", + "hi": "RLE16, अनुशंसित", "ja": "RLE16、推奨", + "ko": "RLE16, 권장", "nl": "RLE16, Aanbevolen", "pt": "RLE16, Recomendado", "ru": "RLE16, рекомендуется", + "zh-chs": "RLE16,推薦", "xloc": [ "default-mobile.handlebars->dialog->3->dialog7->d7amtkvm->3->d7desktopmode->3", "default.handlebars->container->dialog->dialogBody->dialog7->d7amtkvm->3->d7desktopmode->3" @@ -14113,10 +19554,13 @@ "en": "RLE8, Fastest", "es": "RLE8, más rápido", "fr": "RLE8, le plus rapide", + "hi": "RLE8, सबसे तेज", "ja": "RLE8、最速", + "ko": "가장 빠른 RLE8", "nl": "RLE8, snelste", "pt": "RLE8, mais rápido", "ru": "RLE8, самая быстрая", + "zh-chs": "RLE8,最快", "xloc": [ "default-mobile.handlebars->dialog->3->dialog7->d7amtkvm->3->d7desktopmode->1", "default.handlebars->container->dialog->dialogBody->dialog7->d7amtkvm->3->d7desktopmode->1" @@ -14127,10 +19571,16 @@ "de": "RSS", "en": "RSS", "es": "RSS", + "fr": "RSS", + "hi": "आरएसएस", + "ja": "RSS", + "ko": "RSS", "nl": "RSS", + "pt": "RSS", "ru": "RSS", + "zh-chs": "的RSS", "xloc": [ - "default.handlebars->25->1436" + "default.handlebars->27->1583" ] }, { @@ -14139,12 +19589,15 @@ "en": "Randomize the password.", "es": "Contraseña Aleatoria.", "fr": "Mot de passe aléatoire.", + "hi": "पासवर्ड रेंडम करें।", "ja": "パスワードをランダム化します。", + "ko": "비밀번호를 무작위로 지정하십시오.", "nl": "Randomiseer het wachtwoord.", "pt": "Randomize a senha.", "ru": "Случайный пароль.", + "zh-chs": "隨機化密碼。", "xloc": [ - "default.handlebars->25->1248" + "default.handlebars->27->1383" ] }, { @@ -14152,10 +19605,14 @@ "de": "Rate", "en": "Rate", "es": "Velocidad", + "fr": "Taux", + "hi": "मूल्यांकन करें", "ja": "レート", + "ko": "율", "nl": "Beoordeel", "pt": "Taxa", "ru": "Скорость", + "zh-chs": "率", "xloc": [ "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->7->3" ] @@ -14165,12 +19622,16 @@ "de": "Intel® AMT reaktivieren", "en": "Reactivate Intel® AMT", "es": "Reactivar Intel® AMT", + "fr": "Réactiver Intel® AMT", + "hi": "Intel® AMT को पुनः सक्रिय करें", "ja": "インテルを再アクティブ化® AMT", + "ko": "인텔 ® AMT 재 활성화", "nl": "Heractiveer Intel® AMT", "pt": "Reativar Intel®AMT", "ru": "Реактивировать Intel® AMT", + "zh-chs": "重新激活英特爾®AMT", "xloc": [ - "default.handlebars->25->1049" + "default.handlebars->27->1153" ] }, { @@ -14178,12 +19639,16 @@ "de": "Bereiche", "en": "Realms", "es": "Realms", + "fr": "Royaumes", + "hi": "रियल्म्स", "ja": "レルム", + "ko": "영역", "nl": "Realms", "pt": "Realms", "ru": "Области", + "zh-chs": "境界", "xloc": [ - "default.handlebars->25->1256" + "default.handlebars->27->1391" ] }, { @@ -14192,25 +19657,33 @@ "en": "Recursive delete", "es": "Borrar Recuersivamente", "fr": "Suppression récursive", + "hi": "रिकर्सिव डिलीट", "ja": "再帰削除", + "ko": "재귀 삭제", "nl": "Recursieve verwijdering", "pt": "Exclusão recursiva", "ru": "Рекурсивное удаление", + "zh-chs": "遞歸刪除", "xloc": [ - "default-mobile.handlebars->9->248", - "default-mobile.handlebars->9->80", - "default.handlebars->25->1177", - "default.handlebars->25->656" + "default-mobile.handlebars->9->252", + "default-mobile.handlebars->9->83", + "default.handlebars->27->1307", + "default.handlebars->27->705" ] }, { "cs": "Šíření dál a použití ve formě zdrojových kódů nebo zkompilované binární podobě, ať už tak jak je, nebo s úpravami, je povoleno za předpokladu, že jsou splněny následující podmínky:", + "de": "Die Weiterverteilung und Verwendung in Quell- und Binärform mit oder ohne Änderung ist zulässig, sofern folgende Bedingungen erfüllt sind:", "en": "Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:", "es": "Se permite la redistribución y el uso en formas fuente y binaria, con o sin modificación, siempre que se cumplan las siguientes condiciones:", + "fr": "La redistribution et l'utilisation sous forme source et binaire, avec ou sans modification, sont autorisées à condition que les conditions suivantes soient remplies:", + "hi": "संशोधन के साथ या बिना स्रोत और द्विआधारी रूपों में पुनर्वितरण और उपयोग की अनुमति है, बशर्ते कि निम्नलिखित शर्तें पूरी हों:", "ja": "ソースおよびバイナリ形式での再配布および使用は、変更の有無にかかわらず、次の条件が満たされている場合に許可されます。", + "ko": "다음 조건이 충족되는 경우 수정하거나 수정하지 않고 소스 및 이진 형식으로 재배포 및 사용할 수 있습니다.", "nl": "Herdistributie en gebruik in bron- en binaire vorm, met of zonder wijziging, zijn toegestaan mits aan de volgende voorwaarden wordt voldaan:", "pt": "A redistribuição e uso nas formas de origem e binárias, com ou sem modificação, são permitidas desde que as seguintes condições sejam atendidas:", "ru": "Перераспределение и использование в исходной и двоичной формах, с изменениями или без них, разрешено при условии соблюдения следующих условий:", + "zh-chs": "如果滿足以下條件,則允許以源代碼和二進制形式進行重新分發和使用,無論是否經過修改,都可以:", "xloc": [ "terms-mobile.handlebars->container->page_content->column_l->13->1", "terms-mobile.handlebars->container->page_content->column_l->29->1", @@ -14224,15 +19697,18 @@ "en": "Refresh", "es": "Actualizar", "fr": "Rafraîchir", + "hi": "ताज़ा करना", "ja": "リフレッシュ", - "nl": "Ververs", + "ko": "새롭게 하다", + "nl": "Verversen", "pt": "Atualizar", "ru": "Обновить", + "zh-chs": "刷新", "xloc": [ "default-mobile.handlebars->container->page_content->column_l->p10->p10desktop->deskarea3->deskarea3x->DeskTools->DeskToolsRefreshButton", "default-mobile.handlebars->container->page_content->column_l->p10->p10files->p13toolbar->1->2->1->3", "default-mobile.handlebars->container->page_content->column_l->p5->p5myfiles->p5toolbar->1->0->1->3", - "default.handlebars->25->424", + "default.handlebars->27->428", "default.handlebars->container->column_l->p11->deskarea0->deskarea3x->DeskTools->deskToolsAreaTop->DeskToolsRefreshButton", "default.handlebars->container->column_l->p13->p13toolbar->1->2->1->3", "default.handlebars->container->column_l->p40->3->3" @@ -14243,9 +19719,14 @@ "de": "Agentenkerne aktualisieren", "en": "Refresh Agent Cores", "es": "Actualizar Core del Agente", + "fr": "Actualiser les cœurs d'agent", + "hi": "एजेंट को ताज़ा करें", "ja": "エージェントコアの更新", + "ko": "에이전트 코어 새로 고침", "nl": "Agentcores vernieuwen", + "pt": "Atualizar núcleos do agente", "ru": "Обновить ядра агентов", + "zh-chs": "刷新代理核心", "xloc": [ "default.handlebars->container->column_l->p42->pluginRestartNotice->1" ] @@ -14255,14 +19736,18 @@ "de": "Weiterleitung", "en": "Relay", "es": "Relé", + "fr": "Relais", + "hi": "रिले", "ja": "リレー", + "ko": "계전기", "nl": "Relay", "pt": "Retransmissão", "ru": "Ретранслятор", + "zh-chs": "中繼", "xloc": [ - "default-mobile.handlebars->9->124", - "default.handlebars->25->190", - "default.handlebars->25->377" + "default-mobile.handlebars->9->128", + "default.handlebars->27->174", + "default.handlebars->27->367" ] }, { @@ -14270,10 +19755,16 @@ "de": "Weiterleitungsanzahl", "en": "Relay Count", "es": "Contador del Rele", + "fr": "Nombre de relais", + "hi": "रिले गिनती", + "ja": "リレー数", + "ko": "릴레이 카운트", "nl": "Relay geteld", + "pt": "Contagem de relés", "ru": "Число ретрансляций", + "zh-chs": "中繼計數", "xloc": [ - "default.handlebars->25->1418" + "default.handlebars->27->1565" ] }, { @@ -14281,10 +19772,16 @@ "de": "Weiterleitungsfehler", "en": "Relay Errors", "es": "Errores del Relay", + "fr": "Erreurs de relais", + "hi": "रिले त्रुटियां", + "ja": "リレーエラー", + "ko": "릴레이 오류", "nl": "Relay fouten", + "pt": "Erros de retransmissão", "ru": "Ошибки ретранслятора", + "zh-chs": "中繼錯誤", "xloc": [ - "default.handlebars->25->1411" + "default.handlebars->27->1558" ] }, { @@ -14292,30 +19789,46 @@ "de": "Weiterleitungssitzungen", "en": "Relay Sessions", "es": "Sesiones Relay", + "fr": "Séances de relais", + "hi": "रिले सत्र", "ja": "中継セッション", + "ko": "릴레이 세션", "nl": "Relay Sessies", "pt": "Retransmissão de sessão ", "ru": "Сессии ретранслятора", + "zh-chs": "接力會議", "xloc": [ - "default.handlebars->25->1417", - "default.handlebars->25->1430" + "default.handlebars->27->1564", + "default.handlebars->27->1577" ] }, { "cs": "Sdělovač předávání (relay)", + "de": "Relais-Kassierer", "en": "Relay teller", "es": "Retransmisor", - "nl": "Relay teller" + "fr": "Guichetier relais", + "hi": "रिले टेलर", + "ja": "中継窓口", + "ko": "릴레이 텔러", + "nl": "Relay teller", + "pt": "Caixa de retransmissão", + "ru": "Реле-кассир", + "zh-chs": "中繼櫃員" }, { "cs": "Zapamatovat toto zařízení na 30 dní.", "de": "Dieses Gerät für 30 Tage merken.", "en": "Remember this device for 30 days.", "es": "Recuerde este dispositivo por 30 días.", - "fr": "Rappelez cet appareil pour 30 jours.", + "fr": "Se souvenir de cet appareil pendant 30 jours.", + "hi": "इस डिवाइस को 30 दिनों तक याद रखें।", "ja": "このデバイスを30日間記憶します。", + "ko": "이 장치를 30 일 동안 기억하십시오.", "nl": "Onthoud dit apparaat gedurende 30 dagen.", + "pt": "Lembre-se deste dispositivo por 30 dias.", "ru": "Запомнить это устройство на 30 дней.", + "zh-chs": "記住此設備30天。", "xloc": [ "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->tokenpanel->1->7->1->2->1->1", "login.handlebars->container->column_l->centralTable->1->0->logincell->tokenpanel->1->7->1->2->1->1" @@ -14326,10 +19839,14 @@ "de": "Entfernt", "en": "Remote", "es": "Remoto", + "fr": "Éloigné", + "hi": "रिमोट", "ja": "リモート", + "ko": "먼", "nl": "Extern", "pt": "Remoto", "ru": "Удаленно", + "zh-chs": "遠程", "xloc": [ "messenger.handlebars->remoteVideo->1" ] @@ -14340,17 +19857,29 @@ "en": "Remote Agent Installation", "es": "Instalación remota de agente", "fr": "Installation de l'agent", + "hi": "दूरस्थ एजेंट स्थापना", "ja": "リモートエージェントのインストール", + "ko": "원격 에이전트 설치", "nl": "Remote Agent installatie", "pt": "Instalação remota do agente", "ru": "Установка удаленного агента", + "zh-chs": "遠程代理安裝", "xloc": [ "agentinvite.handlebars->container->column_l->1->groupname" ] }, { + "cs": "Vzdálená instalace agenta pro {0}", + "de": "Remote Agent Installation für {0}", "en": "Remote Agent Installation for {0}", + "fr": "Installation distante de l'agent pour {0}", + "hi": "दूरस्थ एजेंट स्थापना {0} के लिए", + "ja": "{0}のリモートエージェントインストール", + "ko": "{0}에 대한 원격 에이전트 설치", + "nl": "Externe Agent Installatie voor {0}", + "pt": "Instalação de agente remoto para {0}", "ru": "Установка агента для {0}", + "zh-chs": "{0}的遠程代理安裝", "xloc": [ "agentinvite.handlebars->3->1" ] @@ -14361,12 +19890,15 @@ "en": "Remote Clipboard", "es": "Portapapeles remoto", "fr": "Presse-papier à distance", + "hi": "रिमोट क्लिपबोर्ड", "ja": "リモートクリップボード", + "ko": "원격 클립 보드", "nl": "extern klembord", "pt": "Área de transferência remota", "ru": "Удаленный буфер обмена", + "zh-chs": "遠程剪貼板", "xloc": [ - "default.handlebars->25->617" + "default.handlebars->27->665" ] }, { @@ -14375,15 +19907,18 @@ "en": "Remote Control", "es": "Control Remoto", "fr": "Télécommande", + "hi": "रिमोट कंट्रोल", "ja": "リモコン", + "ko": "리모콘", "nl": "Extern beheer", "pt": "Controle remoto", "ru": "Удаленное управление", + "zh-chs": "遙控", "xloc": [ - "default-mobile.handlebars->9->296", - "default-mobile.handlebars->9->314", - "default.handlebars->25->1095", - "default.handlebars->25->1118" + "default-mobile.handlebars->9->300", + "default-mobile.handlebars->9->318", + "default.handlebars->27->1202", + "default.handlebars->27->1230" ] }, { @@ -14392,14 +19927,17 @@ "en": "Remote Desktop Settings", "es": "Configuración de escritorio remoto", "fr": "Paramètres du bureau à distance", + "hi": "दूरस्थ डेस्कटॉप सेटिंग्स", "ja": "リモートデスクトップ設定", + "ko": "원격 데스크톱 설정", "nl": "Instellingen extern bureaublad", "pt": "Configurações da área de trabalho remota", "ru": "Настройки удаленного рабочего стола", + "zh-chs": "遠程桌面設置", "xloc": [ - "default-mobile.handlebars->9->229", - "default.handlebars->25->222", - "default.handlebars->25->609" + "default-mobile.handlebars->9->233", + "default.handlebars->27->206", + "default.handlebars->27->657" ] }, { @@ -14408,12 +19946,15 @@ "en": "Remote Keyboard Entry", "es": "Entrada remota de teclado", "fr": "Entrée au clavier à distance", + "hi": "रिमोट कीबोर्ड एंट्री", "ja": "リモートキーボード入力", + "ko": "원격 키보드 입력", "nl": "Toetsenbordinvoer op afstand", "pt": "Entrada remota do teclado", "ru": "Ввод с удаленной клавиатуры", + "zh-chs": "遠程鍵盤輸入", "xloc": [ - "default.handlebars->25->615" + "default.handlebars->27->663" ] }, { @@ -14421,13 +19962,17 @@ "de": "Entfernter Mesh-Benutzer", "en": "Remote Mesh User", "es": "Usuario Mesh remoto", + "fr": "Utilisateur de maillage à distance", + "hi": "रिमोट मेष उपयोगकर्ता", "ja": "リモートメッシュユーザー", + "ko": "원격 메시 사용자", "nl": "externe Mesh gebruiker", "pt": "Usuário de malha remota", "ru": "Удаленный пользователь Mesh", + "zh-chs": "遠程網狀用戶", "xloc": [ - "default-mobile.handlebars->9->332", - "default.handlebars->25->1137" + "default-mobile.handlebars->9->336", + "default.handlebars->27->1250" ] }, { @@ -14435,10 +19980,16 @@ "de": "Entfernter Benutzer", "en": "Remote User", "es": "Usuario remoto", + "fr": "Utilisateur distant", + "hi": "दूरस्थ उपयोगकर्ता", + "ja": "リモートユーザー", + "ko": "원격 사용자", "nl": "Externe gebruiker", + "pt": "Usuário remoto", "ru": "Удаленный пользователь", + "zh-chs": "遠程用戶", "xloc": [ - "default.handlebars->25->1311" + "default.handlebars->27->1444" ] }, { @@ -14446,15 +19997,19 @@ "de": "Nur entfernte Ansicht", "en": "Remote View Only", "es": "Vista remota solamente", + "fr": "Affichage à distance uniquement", + "hi": "केवल रिमोट देखें", "ja": "リモートビューのみ", + "ko": "원격보기 만", "nl": "Alleen extern meekijken", "pt": "Somente visualização remota", "ru": "Только просмотр экрана без ввода", + "zh-chs": "僅遠程查看", "xloc": [ - "default-mobile.handlebars->9->297", - "default-mobile.handlebars->9->319", - "default.handlebars->25->1096", - "default.handlebars->25->1123" + "default-mobile.handlebars->9->301", + "default-mobile.handlebars->9->323", + "default.handlebars->27->1203", + "default.handlebars->27->1235" ] }, { @@ -14463,12 +20018,15 @@ "en": "Remote clipboard is valid for 60 seconds.", "es": "El portapapeles remoto es válido por 60 segundos.", "fr": "Le presse-papier à distance est valide pendant 60 secondes.", + "hi": "रिमोट क्लिपबोर्ड 60 सेकंड के लिए मान्य है।", "ja": "リモートクリップボードは60秒間有効です。", + "ko": "원격 클립 보드는 60 초 동안 유효합니다.", "nl": "Het externe klembord is 60 seconden geldig.", "pt": "A área de transferência remota é válida por 60 segundos.", "ru": "Удаленный буфер обмена действителен в течении 60 секунд.", + "zh-chs": "遠程剪貼板的有效期為60秒。", "xloc": [ - "default.handlebars->25->616" + "default.handlebars->27->664" ] }, { @@ -14477,10 +20035,13 @@ "en": "Remote computer is not powered on, click here to issue a power command.", "es": "La computadora remota no está encendida, haga clic aquí para enviar el comando de encendido.", "fr": "L'ordinateur distant n'est pas sous tension, cliquez ici pour émettre une commande d'alimentation.", + "hi": "रिमोट कंप्यूटर चालू नहीं है, पावर कमांड जारी करने के लिए यहां क्लिक करें।", "ja": "リモートコンピューターの電源が入っていません。ここをクリックして電源コマンドを発行してください。", + "ko": "원격 컴퓨터의 전원이 켜져 있지 않으면 여기를 클릭하여 전원 명령을 실행하십시오.", "nl": "Externe computer is niet ingeschakeld, klik hier om een stroomopdracht uit te voeren.", "pt": "O computador remoto não está ligado, clique aqui para emitir um comando de energia.", "ru": "Удаленный компьютер не включен, нажмите сюда, чтобы отправить команду включения питания.", + "zh-chs": "遠程計算機未打開電源,請單擊此處以發出電源命令。", "xloc": [ "default.handlebars->container->column_l->p11->p11warning2->3", "default.handlebars->container->column_l->p12->p12warning2->3" @@ -14492,12 +20053,28 @@ "en": "Remove", "es": "Eliminar", "fr": "Retirer", + "hi": "हटाना", "ja": "削除する", + "ko": "없애다", "nl": "verwijderen", "pt": "Remover", "ru": "Удалить", + "zh-chs": "去掉", "xloc": [ - "default.handlebars->25->140" + "default.handlebars->27->123" + ] + }, + { + "cs": "Odebrat zařízení", + "de": "Gerät entfernen", + "en": "Remove Device", + "fr": "Enlevez l'appareil", + "ja": "デバイスを削除", + "nl": "Verwijder apparaat", + "ru": "Удалить устройство", + "zh-chs": "删除设备", + "xloc": [ + "default.handlebars->27->1524" ] }, { @@ -14505,11 +20082,17 @@ "de": "Gerätegruppe entfernen", "en": "Remove Device Group", "es": "Eliminar grupo de dispositivos", + "fr": "Supprimer le groupe d'appareils", + "hi": "डिवाइस समूह निकालें", + "ja": "デバイスグループを削除", + "ko": "장치 그룹 제거", "nl": "Verwijder apparaatgroep", + "pt": "Remover grupo de dispositivos", "ru": "Удалить группу устройств.", + "zh-chs": "刪除設備組", "xloc": [ - "default.handlebars->25->1303", - "default.handlebars->25->1387" + "default.handlebars->27->1436", + "default.handlebars->27->1533" ] }, { @@ -14517,10 +20100,17 @@ "de": "Benutzer entfernen", "en": "Remove User", "es": "Eliminar usuario", + "fr": "Supprimer l'utilisateur", + "hi": "उपयोगकर्ता निकालें", + "ja": "ユーザーを削除", + "ko": "사용자 제거", "nl": "Verwijder gebruiker", + "pt": "Remover usuário", "ru": "Удалить пользователя", + "zh-chs": "刪除用戶", "xloc": [ - "default.handlebars->25->1383" + "default.handlebars->27->1526", + "default.handlebars->27->1529" ] }, { @@ -14528,12 +20118,16 @@ "de": "Alle Zweifaktorauthentifizierung entfernen.", "en": "Remove all 2nd factor authentication.", "es": "Eliminar toda la autenticación de segundo factor.", + "fr": "Supprimer toutes les authentifications à double facteur.", + "hi": "सभी 2 फैक्टर प्रमाणीकरण निकालें।", "ja": "すべての2要素認証を削除します。", + "ko": "2 단계 인증을 모두 제거하십시오.", "nl": "Verwijder alle Tweestapsverificatie.", "pt": "Remova toda a autenticação do segundo fator.", "ru": "Удалить все двухфакторные аутентификации.", + "zh-chs": "刪除所有第二因素驗證。", "xloc": [ - "default.handlebars->25->1364" + "default.handlebars->27->1502" ] }, { @@ -14541,10 +20135,16 @@ "de": "Alle vorhergehenden Ereignisse für diese Benutzer-ID entfernen.", "en": "Remove all previous events for this userid.", "es": "Elimine todos los eventos anteriores para este ID de usuario.", + "fr": "Supprimer l'historique pour cet identifiant de compte", + "hi": "इस उपयोगकर्ता के लिए पिछली सभी घटनाओं को हटा दें।", + "ja": "このユーザーIDの以前のイベントをすべて削除します。", + "ko": "이 사용자 ID에 대한 모든 이전 이벤트를 제거하십시오.", "nl": "Verwijder alle eerdere gebeurtenissen voor dit gebruikers-ID.", + "pt": "Remova todos os eventos anteriores para este ID do usuário.", "ru": "Удалить все прошлые события для этого userid.", + "zh-chs": "刪除此用戶標識的所有先前事件。", "xloc": [ - "default.handlebars->25->1250" + "default.handlebars->27->1385" ] }, { @@ -14552,10 +20152,16 @@ "de": "Gerät nach Trennung entfernen", "en": "Remove device on disconnect", "es": "Eliminar el dispositivo al desconectar", + "fr": "Masquer les appareils déconnectés", + "hi": "डिस्कनेक्ट पर डिवाइस निकालें", + "ja": "切断時にデバイスを削除する", + "ko": "연결 해제시 장치 제거", "nl": "Verwijder apparaat bij verbreken", + "pt": "Remova o dispositivo ao desconectar", "ru": "Удалить устройство при отключении", + "zh-chs": "斷開連接後移除設備", "xloc": [ - "default.handlebars->25->1080" + "default.handlebars->27->1184" ] }, { @@ -14563,12 +20169,16 @@ "de": "Gerätestandort entfernen", "en": "Remove node location", "es": "Eliminar ubicación del nodo", + "fr": "Retirer l'appareil de la carte", + "hi": "नोड स्थान निकालें", "ja": "ノードの場所を削除", + "ko": "노드 위치 제거", "nl": "Verwijder knooppuntlocatie", "pt": "Remover localização do nó", "ru": "Удалить местоположение узла", + "zh-chs": "刪除節點位置", "xloc": [ - "default.handlebars->25->416" + "default.handlebars->27->420" ] }, { @@ -14577,12 +20187,28 @@ "en": "Remove this device", "es": "Eliminar este dispositivo", "fr": "Retirer ce périphérique", + "hi": "इस उपकरण को निकालें", "ja": "このデバイスを削除", + "ko": "이 장치를 제거", "nl": "Verwijder dit apparaat", "pt": "Remova este dispositivo", "ru": "Удалить это устройство", + "zh-chs": "刪除此設備", "xloc": [ - "default.handlebars->25->502" + "default.handlebars->27->509" + ] + }, + { + "cs": "Odebrat tohoto uživatele", + "de": "Entfernen Sie diesen Benutzer", + "en": "Remove this user", + "fr": "Supprimer cet utilisateur", + "ja": "このユーザーを削除", + "nl": "Verwijder deze gebruiker", + "ru": "Удалить этого пользователя", + "zh-chs": "删除该用户", + "xloc": [ + "default.handlebars->27->1486" ] }, { @@ -14590,10 +20216,16 @@ "de": "Benutzergruppenmitgliedschaft entfernen", "en": "Remove user group membership", "es": "Eliminar ususrio de este grupo", + "fr": "Supprimer l'utilisateur du groupe", + "hi": "उपयोगकर्ता समूह सदस्यता निकालें", + "ja": "ユーザーグループメンバーシップを削除する", + "ko": "사용자 그룹 멤버십 제거", "nl": "Verwijder de groepslidmaatschap", + "pt": "Remover associação ao grupo de usuários", "ru": "Удалить членство пользователя в группе", + "zh-chs": "刪除用戶組成員身份", "xloc": [ - "default.handlebars->25->1379" + "default.handlebars->27->1521" ] }, { @@ -14601,10 +20233,16 @@ "de": "Benutzergruppenrechte an dieser Gerätegruppe entfernen", "en": "Remove user group rights to this device group", "es": "Eliminar los derechos del grupo de usuarios a este grupo de dispositivos", + "fr": "Supprimer les droits du groupe utilisateurs", + "hi": "इस उपकरण समूह के उपयोगकर्ता समूह अधिकारों को निकालें", + "ja": "このデバイスグループに対するユーザーグループ権限を削除します", + "ko": "이 장치 그룹에 대한 사용자 그룹 권한 제거", "nl": "Verwijder gebruikers groepsrechten van deze apparaatgroep", + "pt": "Remova os direitos do grupo de usuários para este grupo de dispositivos", "ru": "Удалить права группы пользователей для этой группы устройств", + "zh-chs": "刪除該設備組的用戶組權限", "xloc": [ - "default.handlebars->25->1299" + "default.handlebars->27->1432" ] }, { @@ -14613,14 +20251,19 @@ "en": "Remove user rights to this device group", "es": "Eliminar privilegios de usuario de este grupo de dispositivos", "fr": "Supprimer les droits d'utilisateur sur ce groupe de périphériques", + "hi": "इस उपकरण समूह के लिए उपयोगकर्ता अधिकार निकालें", "ja": "このデバイスグループのユーザー権限を削除します", + "ko": "이 장치 그룹에 대한 사용자 권한 제거", "nl": "Gebruikersrechten voor deze apparaatgroep verwijderen", "pt": "Remova os direitos de usuário deste grupo de dispositivos", "ru": "Удалить права пользователя для этой группы устройств", + "zh-chs": "刪除此設備組的用戶權限", "xloc": [ - "default.handlebars->25->1033", - "default.handlebars->25->1290", - "default.handlebars->25->1373" + "default.handlebars->27->1137", + "default.handlebars->27->1426", + "default.handlebars->27->1509", + "default.handlebars->27->1515", + "default.handlebars->27->538" ] }, { @@ -14629,19 +20272,24 @@ "en": "Rename", "es": "Renombrar", "fr": "Renommer", + "hi": "नाम बदलें", "ja": "リネーム", + "ko": "이름 바꾸기", "nl": "Hernoemen", "pt": "Renomear", "ru": "Переименовать", + "zh-chs": "改名", "xloc": [ - "default-mobile.handlebars->9->252", - "default-mobile.handlebars->9->84", + "default-mobile.handlebars->9->256", + "default-mobile.handlebars->9->87", "default-mobile.handlebars->container->page_content->column_l->p10->p10files->p13toolbar->1->2->1->1", "default-mobile.handlebars->container->page_content->column_l->p5->p5myfiles->p5toolbar->1->0->1->1", - "default.handlebars->25->1181", - "default.handlebars->25->660", + "default.handlebars->27->1311", + "default.handlebars->27->414", + "default.handlebars->27->709", "default.handlebars->container->column_l->p13->p13toolbar->1->2->1->3", - "default.handlebars->container->column_l->p5->p5toolbar->1->0->p5filehead->3" + "default.handlebars->container->column_l->p5->p5toolbar->1->0->p5filehead->3", + "default.handlebars->filesContextMenu->cxfilerename->0" ] }, { @@ -14650,12 +20298,15 @@ "en": "Requirements: ", "es": "Requirimientos: ", "fr": "Exigences:", + "hi": "आवश्यकताएँ:", "ja": "要件:", + "ko": "요구 사항 :", "nl": "Vereisten:", "pt": "Requisitos:", "ru": "Требования: ", + "zh-chs": "要求:", "xloc": [ - "default.handlebars->25->946" + "default.handlebars->27->1051" ] }, { @@ -14664,14 +20315,17 @@ "en": "Requirements: {0}.", "es": "Requirimientos: {0}.", "fr": "Exigences: {0}.", + "hi": "आवश्यकताएँ: {0}।", "ja": "要件:{0}。", + "ko": "요구 사항 : {0}.", "nl": "Vereisten: {0}.", "pt": "Requisitos: {0}.", "ru": "Требования: {0}.", + "zh-chs": "要求:{0}。", "xloc": [ - "default-mobile.handlebars->9->48", - "default.handlebars->25->1253", - "default.handlebars->25->1362" + "default-mobile.handlebars->9->51", + "default.handlebars->27->1388", + "default.handlebars->27->1500" ] }, { @@ -14680,12 +20334,15 @@ "en": "Requires Microsoft ClickOnce support in your browser", "es": "Requiere soporte de Microsoft ClickOnce en su navegador", "fr": "Requiert Microsoft ClickOnce dans votre navigateur", + "hi": "आपके ब्राउज़र में Microsoft ClickOnce समर्थन की आवश्यकता है", "ja": "ブラウザでMicrosoft ClickOnceサポートが必要です", + "ko": "브라우저에서 Microsoft ClickOnce 지원 필요", "nl": "Vereist Microsoft ClickOnce-ondersteuning in uw browser", "pt": "Requer o suporte Microsoft ClickOnce no seu navegador", "ru": "Требуется поддержка Microsoft ClickOnce в вашем браузере", + "zh-chs": "需要瀏覽器中的Microsoft ClickOnce支持", "xloc": [ - "default.handlebars->25->512" + "default.handlebars->27->519" ] }, { @@ -14694,13 +20351,16 @@ "en": "Requires Microsoft ClickOnce support in your browser.", "es": "Requiere soporte de Microsoft ClickOnce en su navegador.", "fr": "Requiert Microsoft ClickOnce dans votre navigateur.", + "hi": "आपके ब्राउज़र में Microsoft ClickOnce समर्थन की आवश्यकता है।", "ja": "ブラウザでMicrosoft ClickOnceサポートが必要です。", + "ko": "브라우저에서 Microsoft ClickOnce 지원이 필요합니다.", "nl": "Vereist Microsoft ClickOnce-ondersteuning in uw browser", "pt": "Requer o suporte Microsoft ClickOnce no seu navegador.", "ru": "Требуется поддержка Microsoft ClickOnce в вашем браузере.", + "zh-chs": "在瀏覽器中需要Microsoft ClickOnce支持。", "xloc": [ - "default.handlebars->25->514", - "default.handlebars->25->516" + "default.handlebars->27->521", + "default.handlebars->27->523" ] }, { @@ -14709,13 +20369,16 @@ "en": "Reset", "es": "Reiniciar", "fr": "Réinitialiser", + "hi": "रीसेट", "ja": "リセットする", + "ko": "초기화", "nl": "Herstarten", "pt": "Redefinir", "ru": "Перезагрузить", + "zh-chs": "重啟", "xloc": [ - "default-mobile.handlebars->9->208", - "default.handlebars->25->538", + "default-mobile.handlebars->9->212", + "default.handlebars->27->585", "default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->devMapToolbar" ] }, @@ -14725,10 +20388,13 @@ "en": "Reset Account", "es": "Restablecer Cuenta", "fr": "Réinitialiser le Compte", + "hi": "खाता रीसेट करें", "ja": "アカウントをリセット", + "ko": "계정 재설정", "nl": "Account opnieuw instellen", "pt": "Redefinir Conta", "ru": "Сбросить учетную запись", + "zh-chs": "重設帳戶", "xloc": [ "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->resetpanel->1->7->1->2->1->1", "login.handlebars->container->column_l->centralTable->1->0->logincell->resetpanel->1->7->1->2->1->1" @@ -14740,10 +20406,13 @@ "en": "Reset Password", "es": "Restablecer la contraseña", "fr": "Réinitialiser le mot de passe", + "hi": "पासवर्ड रीसेट", "ja": "パスワードを再設定する", + "ko": "암호를 재설정", "nl": "Reset wachtwoord", "pt": "Redefinir senha", "ru": "Сбросить пароль", + "zh-chs": "重設密碼", "xloc": [ "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->resetpasswordpanel->1->7->1->6->1->1", "login.handlebars->container->column_l->centralTable->1->0->logincell->resetpasswordpanel->1->7->1->6->1->1" @@ -14755,10 +20424,13 @@ "en": "Reset account", "es": "Restablecer cuenta", "fr": "Réinitialiser le compte", + "hi": "खाता रीसेट करें", "ja": "アカウントをリセット", + "ko": "계정 재설정", "nl": "Account opnieuw instellen", "pt": "Redefinir conta", "ru": "Сбросить учетную запись", + "zh-chs": "重設帳戶", "xloc": [ "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->loginpanel->1->resetAccountDiv->3", "login.handlebars->container->column_l->centralTable->1->0->logincell->loginpanel->1->resetAccountDiv->3" @@ -14770,12 +20442,15 @@ "en": "Reset devices", "es": "Restablecer Dispositivo", "fr": "Réinitialiser les appareils", + "hi": "डिवाइस रीसेट करें", "ja": "デバイスをリセットする", + "ko": "기기 초기화", "nl": "Herstart apparaten", "pt": "Redefinir dispositivos", "ru": "Отправить в перезагрузку", + "zh-chs": "重置設備", "xloc": [ - "default.handlebars->25->389" + "default.handlebars->27->379" ] }, { @@ -14784,10 +20459,13 @@ "en": "Reset map view", "es": "Restablecer vista del mapa", "fr": "Réinitialiser l'affichage de la carte", + "hi": "मानचित्र दृश्य रीसेट करें", "ja": "マップビューをリセット", + "ko": "지도보기 재설정", "nl": "Reset kaartweergave", "pt": "Redefinir visualização de mapa", "ru": "Сбросить вид карты", + "zh-chs": "重置地圖視圖", "xloc": [ "default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->devMapToolbar" ] @@ -14798,12 +20476,15 @@ "en": "Restart", "es": "Reiniciar", "fr": "Redémarrer", + "hi": "पुनर्प्रारंभ करें", "ja": "再起動", + "ko": "재시작", "nl": "Herstarten", "pt": "Reiniciar", "ru": "Перезапуск", + "zh-chs": "重新開始", "xloc": [ - "default.handlebars->25->631", + "default.handlebars->27->680", "player.handlebars->p11->deskarea0->deskarea4->3" ] }, @@ -14813,12 +20494,15 @@ "en": "Restore Server", "es": "Restaurar servidor", "fr": "Restaurer le serveur", + "hi": "सर्वर को पुनर्स्थापित करें", "ja": "サーバーの復元", + "ko": "서버 복원", "nl": "Server herstellen", "pt": "Restaurar servidor", "ru": "Восстановить сервер", + "zh-chs": "還原伺服器", "xloc": [ - "default.handlebars->25->973" + "default.handlebars->27->1078" ] }, { @@ -14827,10 +20511,13 @@ "en": "Restore server with backup", "es": "Restaurar servidor con copia de seguridad.", "fr": "Restaurer le serveur avec sauvegarde", + "hi": "बैकअप के साथ सर्वर को पुनर्स्थापित करें", "ja": "バックアップでサーバーを復元する", + "ko": "백업으로 서버 복원", "nl": "Herstel server met back-up", "pt": "Restaurar servidor com backup", "ru": "Восстановить сервер из резервной копии", + "zh-chs": "通過備份還原服務器", "xloc": [ "default.handlebars->container->column_l->p6->p2ServerActions->3->p2ServerActionsRestore->0" ] @@ -14840,12 +20527,16 @@ "de": "Server unter Verwendung einer Sicherungskopie wiederherstellen, Dies wird die existierenden Server-Daten löschen. Fahren Sie nur fort, wenn Sie wissen, was Sie tun.", "en": "Restore the server using a backup, this will delete the existing server data. Only do this if you know what you are doing.", "es": "Restaure el servidor utilizando una copia de seguridad, , esto eliminará los datos del servidor existentes . Solo haga esto si sabe lo que está haciendo :).", + "fr": "La restauration du serveur à partir d'une sauvegarde supprimera toutes les données existantes. Si vous avez conscience de ce que vous faites, une sauvegarde est une bonne idée avant de continuer.", + "hi": "बैकअप का उपयोग करके सर्वर को पुनर्स्थापित करें, यह मौजूदा सर्वर डेटा को हटा देगा । ऐसा तभी करें जब आपको पता हो कि आप क्या कर रहे हैं।", "ja": "バックアップを使用してサーバーを復元します。これにより既存のサーバーデータが削除されます。あなたが何をしているかを知っている場合にのみ、これを行ってください。", + "ko": " 기존 서버 데이터를 삭제합니다 백업을 사용하여 서버를 복원합니다. 하고있는 일을 알고있는 경우에만이 작업을 수행하십시오.", "nl": "Herstel de server met een back-up, hiermee worden de bestaande servergegevens verwijderd . Doe dit alleen als je weet wat je doet.", "pt": "Restaurar o servidor usando um backup, isso excluirá os dados existentes do servidor. Faça isso apenas se você souber o que está fazendo.", "ru": "Восстановить сервер из резервной копии, это удалит существующие данные сервера . Продолжайте дальше только если знаете, что делаете.", + "zh-chs": "使用備份還原服務器,這將刪除現有服務器數據。僅當您知道自己在做什麼時才這樣做。", "xloc": [ - "default.handlebars->25->970" + "default.handlebars->27->1075" ] }, { @@ -14854,24 +20545,31 @@ "en": "Restrictions", "es": "Restricciones", "fr": "Restrictions", + "hi": "प्रतिबंध", "ja": "制限事項", + "ko": "제한 사항", "nl": "Beperkingen", "pt": "Restrições", "ru": "Ограничения", + "zh-chs": "限制條件", "xloc": [ - "default.handlebars->25->1322" + "default.handlebars->27->1456" ] }, { "cs": "rétorománština", "de": "Rätoromanisch", "en": "Rhaeto-Romanic", + "fr": "Rhéto-romane", + "hi": "राएतो-रोमन", "ja": "Rhaeto-Romanic", + "ko": "Rhaeto- 로마 닉", "nl": "Rhetoromaans", "pt": "Rhaeto-Romanic", "ru": "Ретороманский", + "zh-chs": "修羅羅馬式", "xloc": [ - "default.handlebars->25->857" + "default.handlebars->27->961" ] }, { @@ -14879,12 +20577,15 @@ "de": "Rumänisch", "en": "Romanian", "fr": "Roumain", + "hi": "रोमानियाई", "ja": "ルーマニア語", + "ko": "루마니아 사람", "nl": "Roemeense", "pt": "Romena", "ru": "Румынский", + "zh-chs": "羅馬尼亞語", "xloc": [ - "default.handlebars->25->858" + "default.handlebars->27->962" ] }, { @@ -14892,12 +20593,15 @@ "de": "Rumänisch (Moldawien)", "en": "Romanian (Moldavia)", "fr": "Roumain (Moldavie)", + "hi": "रोमानियाई (मोलदाविया)", "ja": "ルーマニア語(モルダビア)", + "ko": "루마니아어 (몰다비아)", "nl": "Roemeens (Moldavië)", "pt": "Romeno (Moldávia)", "ru": "Румынский (Молдавия)", + "zh-chs": "羅馬尼亞文(摩爾達維亞)", "xloc": [ - "default.handlebars->25->859" + "default.handlebars->27->963" ] }, { @@ -14906,15 +20610,18 @@ "en": "Root", "es": "Root", "fr": "Racine", + "hi": "जड़", "ja": "ルート", + "ko": "뿌리", "nl": "Root", "pt": "Raiz", "ru": "Root/Корень", + "zh-chs": "根", "xloc": [ - "default-mobile.handlebars->9->242", - "default-mobile.handlebars->9->66", - "default.handlebars->25->1156", - "default.handlebars->25->650" + "default-mobile.handlebars->9->246", + "default-mobile.handlebars->9->69", + "default.handlebars->27->1284", + "default.handlebars->27->699" ] }, { @@ -14923,13 +20630,16 @@ "en": "Root Certificate", "es": "Certificado Raiz", "fr": "Certificat Racine", + "hi": "रूट प्रमाणपत्र", "ja": "ルート証明書", + "ko": "루트 인증서", "nl": "Hoofd certificaat", "pt": "Certificado raiz", "ru": "Корневой сертификат", + "zh-chs": "根證書", "xloc": [ - "default.handlebars->25->268", - "default.handlebars->25->275" + "default.handlebars->27->252", + "default.handlebars->27->259" ] }, { @@ -14938,13 +20648,16 @@ "en": "Root Certificate File", "es": "Archivo de certificado raíz", "fr": "Fichier de Certificate Racine", + "hi": "रूट प्रमाणपत्र फ़ाइल", "ja": "ルート証明書ファイル", + "ko": "루트 인증서 파일", "nl": "Hoofd certificaat bestand", "pt": "Arquivo de certificado raiz", "ru": "Файл корневого сертификата", + "zh-chs": "根證書文件", "xloc": [ - "default.handlebars->25->270", - "default.handlebars->25->276" + "default.handlebars->27->254", + "default.handlebars->27->261" ] }, { @@ -14952,9 +20665,14 @@ "de": "Root-Shell", "en": "Root Shell", "es": "Shell Root", + "fr": "Coquille de racine", + "hi": "जड़ शैल", "ja": "ルートシェル", + "ko": "루트 쉘", "nl": "Root Shell", + "pt": "Root Shell", "ru": "Root Shell", + "zh-chs": "根殼", "xloc": [ "default.handlebars->termShellContextMenuLinux->cxtermnorm->0", "xterm.handlebars->termShellContextMenuLinux->cxtermnorm->0" @@ -14966,10 +20684,13 @@ "en": "Rotate Left", "es": "Girar a la izquierda", "fr": "Tourne à gauche", + "hi": "बायीं ओर घुमाओ", "ja": "左に回転", + "ko": "왼쪽으로 회전", "nl": "Draai naar links", "pt": "Vire à esquerda", "ru": "Повернуть влево", + "zh-chs": "向左旋轉", "xloc": [ "default.handlebars->container->column_l->p11->deskarea0->deskarea1->1" ] @@ -14980,10 +20701,13 @@ "en": "Rotate Right", "es": "Gira a la derecha", "fr": "Tourner à droite", + "hi": "दाएं घुमाएं", "ja": "右に回る", + "ko": "오른쪽으로 회전", "nl": "Draai naar rechts", "pt": "Vire à direita", "ru": "Повернуть вправо", + "zh-chs": "右旋", "xloc": [ "default.handlebars->container->column_l->p11->deskarea0->deskarea1->1" ] @@ -14993,13 +20717,17 @@ "de": "Router", "en": "Router", "es": "Router", + "fr": "Routeur", + "hi": "रूटर", "ja": "ルーター", + "ko": "라우터", "nl": "Router", "pt": "Roteador", "ru": "Router", + "zh-chs": "路由器", "xloc": [ - "default.handlebars->25->209", - "default.handlebars->25->509" + "default.handlebars->27->193", + "default.handlebars->27->516" ] }, { @@ -15008,12 +20736,15 @@ "en": "Russian", "es": "Ruso", "fr": "Russe", + "hi": "रूसी", "ja": "ロシア", + "ko": "러시아인", "nl": "Russisch", "pt": "Russo", "ru": "Русский", + "zh-chs": "俄語", "xloc": [ - "default.handlebars->25->860" + "default.handlebars->27->964" ] }, { @@ -15022,12 +20753,15 @@ "en": "Russian (Moldavia)", "es": "Ruso (Moldavia)", "fr": "Russe (Moldavie)", + "hi": "रूसी (मोलदाविया)", "ja": "ロシア語(モルダビア)", + "ko": "러시아어 (몰다비아)", "nl": "Russisch (Moldavië)", "pt": "Russo (Moldávia)", "ru": "Русский (Молдавия)", + "zh-chs": "俄文(摩爾達維亞)", "xloc": [ - "default.handlebars->25->861" + "default.handlebars->27->965" ] }, { @@ -15036,24 +20770,31 @@ "en": "Same as device name", "es": "Igual que el nombre del dispositivo", "fr": "Identique au nom de l'appareil", + "hi": "डिवाइस नाम के समान", "ja": "デバイス名と同じ", + "ko": "장치 이름과 동일", "nl": "Hetzelfde als de apparaatnaam", "pt": "Igual ao nome do dispositivo", "ru": "Такое же как имя устройства", + "zh-chs": "與設備名稱相同", "xloc": [ - "default.handlebars->25->240" + "default.handlebars->27->224" ] }, { "cs": "sámština (Lulejská)", "de": "Sami (Lappisch)", "en": "Sami (Lappish)", + "fr": "Sami (lapon)", + "hi": "सामी (लापिश)", "ja": "サミ(ラップ語)", + "ko": "사미 (Lappish)", "nl": "Sami (Lapse)", "pt": "Sami (lapão)", "ru": "Саамский", + "zh-chs": "薩米(拉普蘭)", "xloc": [ - "default.handlebars->25->862" + "default.handlebars->27->966" ] }, { @@ -15061,48 +20802,64 @@ "de": "Beispiele für IP-Bereichswerte
192.168.0.100
192.168.1.0/24
192.167.0.1-192.168.0.100", "en": "Sample IP range values
192.168.0.100
192.168.1.0/24
192.167.0.1-192.168.0.100", "es": "Valores de rango de IP de muestra
192.168.0.100
192.168.1.0/24
192.167.0.1-192.168.0.100", + "fr": "Exemple de plages d'adresses IP
192.168.0.100
192.168.1.0/24
192.167.0.1-192.168.0.100", + "hi": "नमूना IP श्रेणी मान
192.168.0.100
192.168.1.0/24
192.167.0.1-192.168.0.100", "ja": "サンプルIP範囲値
192.168.0.100
192.168.1.0/24
192.167.0.1-192.168.0.100", + "ko": "샘플 IP 범위 값
192.168.0.100
192.168.1.0/24
192.167.0.1-192.168.0.100", "nl": "Voorbeeld van IP-bereikwaarden
192.168.0.100
192.168.1.0/24
192.167.0.1-192.168.0.100", "pt": "Valores de intervalo de IP de amostra
192.168.0.100
192.168.1.0/24
192.167.0.1-192.168.0.100", "ru": "Пример значений диапазона IP
192.168.0.100
192.168.1.0/24
192.167.0.1-192.168.0.100", + "zh-chs": "IP範圍值樣本
192.168.0.100
192.168.1.0/24
25->163" + "default.handlebars->27->146" ] }, { "cs": "sanžština", "de": "Sango", "en": "Sango", + "fr": "Sango", + "hi": "सांगो", "ja": "サンゴ", + "ko": "상고", "nl": "Sango", "pt": "Sango", "ru": "Санго", + "zh-chs": "三鄉", "xloc": [ - "default.handlebars->25->863" + "default.handlebars->27->967" ] }, { "cs": "sanskrt", "de": "Sanskrit", "en": "Sanskrit", + "fr": "sanskrit", + "hi": "संस्कृत", "ja": "サンスクリット", + "ko": "산스크리트", "nl": "Sanskriet", "pt": "Sanskrit", "ru": "Санскритский", + "zh-chs": "梵文", "xloc": [ - "default.handlebars->25->864" + "default.handlebars->27->968" ] }, { "cs": "sardinština", "de": "Sardisch", "en": "Sardinian", + "fr": "Sarde", + "hi": "Sardinian", "ja": "サルデーニャ", + "ko": "사르디니아 사람", "nl": "Sardijns", "pt": "Sardinian", "ru": "Сардинский", + "zh-chs": "撒丁島", "xloc": [ - "default.handlebars->25->865" + "default.handlebars->27->969" ] }, { @@ -15111,10 +20868,13 @@ "en": "Save a screenshot of the remote desktop", "es": "Guardar una captura de pantalla del escritorio remoto.", "fr": "Enregistrer une capture d'écran du bureau distant", + "hi": "दूरस्थ डेस्कटॉप का स्क्रीनशॉट सहेजें", "ja": "リモートデスクトップのスクリーンショットを保存する", + "ko": "원격 데스크톱의 스크린 샷 저장", "nl": "Bewaar een screenshot van het externe bureaublad", "pt": "Salvar uma captura de tela da área de trabalho remota", "ru": "Сохранить снимок экрана удаленного рабочего стола", + "zh-chs": "保存遠程桌面的屏幕截圖", "xloc": [ "default.handlebars->container->column_l->p11->deskarea0->deskarea1->1" ] @@ -15125,12 +20885,15 @@ "en": "Save node location", "es": "Guardar ubicación del nodo", "fr": "Enregistrer l'emplacement", + "hi": "नोड स्थान सहेजें", "ja": "ノードの場所を保存", + "ko": "노드 위치 저장", "nl": "Knooppuntlocatie opslaan", "pt": "Salvar localização do nó", "ru": "Сохранить расположение узла", + "zh-chs": "保存節點位置", "xloc": [ - "default.handlebars->25->417" + "default.handlebars->27->421" ] }, { @@ -15139,10 +20902,13 @@ "en": "Save...", "es": "Guardar...", "fr": "Sauver...", + "hi": "सहेजें...", "ja": "セーブ...", + "ko": "저장...", "nl": "Opslaan...", "pt": "Salvar...", "ru": "Сохранить...", + "zh-chs": "保存...", "xloc": [ "default.handlebars->container->column_l->p11->deskarea0->deskarea1->1" ] @@ -15153,10 +20919,13 @@ "en": "Scaling", "es": "Scaling", "fr": "Mise à l'échelle", + "hi": "स्केलिंग", "ja": "スケーリング", + "ko": "스케일링", "nl": "Schalen", "pt": "Dimensionamento", "ru": "Маштабирование", + "zh-chs": "縮放比例", "xloc": [ "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->5->3", "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->5->1" @@ -15168,12 +20937,15 @@ "en": "Scan", "es": "Escanear", "fr": "Analyse", + "hi": "स्कैन", "ja": "スキャン", + "ko": "주사", "nl": "Scan", "pt": "Scan", "ru": "Сканировать", + "zh-chs": "掃瞄", "xloc": [ - "default.handlebars->25->255" + "default.handlebars->27->239" ] }, { @@ -15182,12 +20954,15 @@ "en": "Scan Network", "es": "Escanear Red", "fr": "Scan réseau", + "hi": "स्कैन नेटवर्क", "ja": "スキャンネットワーク", + "ko": "스캔 네트워크", "nl": "Scan Netwerk", "pt": "Escaneamento via rede", "ru": "Сканировать сеть", + "zh-chs": "掃描網絡", "xloc": [ - "default.handlebars->25->228" + "default.handlebars->27->212" ] }, { @@ -15196,12 +20971,15 @@ "en": "Scan for Intel® AMT devices", "es": "Escanear en busca de Intel & reg; Dispositivos AMT", "fr": "Rechercher des périphériques Intel® AMT", + "hi": "Intel® AMT उपकरणों के लिए स्कैन करें", "ja": "Intelをスキャン® AMTデバイス", + "ko": "인텔 ® AMT 장치 검색", "nl": "Scannen naar Intel® AMT-apparaten", "pt": "Digitalizar para Intel® dispositivos AMT", "ru": "Сканировать на наличие Intel® AMT устройств", + "zh-chs": "掃描英特爾®AMT設備", "xloc": [ - "default.handlebars->25->256" + "default.handlebars->27->240" ] }, { @@ -15210,12 +20988,15 @@ "en": "Scanning...", "es": "Escaneo...", "fr": "Balayage...", + "hi": "स्कैनिंग ...", "ja": "走査...", + "ko": "스캐닝...", "nl": "Scannen van ...", "pt": "Escaneando...", "ru": "Сканирование...", + "zh-chs": "掃描...", "xloc": [ - "default.handlebars->25->257" + "default.handlebars->27->241" ] }, { @@ -15224,12 +21005,15 @@ "en": "Search", "es": "Buscar", "fr": "Chercher", + "hi": "खोज", "ja": "サーチ", + "ko": "검색", "nl": "Zoeken", "pt": "Procurar", "ru": "Поиск", + "zh-chs": "搜索", "xloc": [ - "default.handlebars->25->430", + "default.handlebars->27->434", "default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->devMapToolbar" ] }, @@ -15239,10 +21023,13 @@ "en": "Search Location", "es": "Buscar ubicación", "fr": "Recherche de lieu", + "hi": "स्थान खोजें", "ja": "場所を検索", + "ko": "위치 검색", "nl": "Zoek locatie", "pt": "Pesquisar Localização", "ru": "Поиск местоположения", + "zh-chs": "搜索位置", "xloc": [ "default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->devMapToolbar" ] @@ -15253,29 +21040,69 @@ "en": "Search for location", "es": "Buscar ubicación", "fr": "Recherche de lieu", + "hi": "स्थान की खोज करें", "ja": "場所を検索", + "ko": "위치 검색", "nl": "Zoeken naar locatie", "pt": "Pesquisar localização", "ru": "Поиск местоположения", + "zh-chs": "搜索位置", "xloc": [ "default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->devMapToolbar" ] }, + { + "cs": "Zabezpečené přihlášení", + "de": "Sicherheits Login", + "en": "Secure Login", + "fr": "Connexion sécurisée", + "hi": "सुरक्षित लॉगइन", + "ja": "安全なログイン", + "ko": "안전한 로그인", + "nl": "Beveiligde login", + "pt": "Login seguro", + "ru": "Безопасный вход", + "zh-chs": "安全登錄", + "xloc": [ + "login-mobile.handlebars->5->20", + "login.handlebars->5->20" + ] + }, + { + "cs": "Zabezpečeno pomocí TLS", + "de": "Mit TLS gesichert", + "en": "Secured using TLS", + "fr": "Sécurisé à l'aide de TLS", + "hi": "TLS का उपयोग करके सुरक्षित", + "ja": "TLSを使用して保護", + "ko": "TLS를 사용하여 보안", + "nl": "Beveiligd met TLS", + "pt": "Protegido usando TLS", + "ru": "Защищено с помощью TLS", + "zh-chs": "使用TLS保護", + "xloc": [ + "default.handlebars->27->772" + ] + }, { "cs": "Zabezpečení", "de": "Sicherheit", "en": "Security", "es": "Seguridad", "fr": "Sécurité", + "hi": "सुरक्षा", "ja": "セキュリティ", + "ko": "보안", "nl": "Veiligheid", "pt": "Segurança", "ru": "Защита", + "zh-chs": "安全", "xloc": [ - "default-mobile.handlebars->9->214", - "default.handlebars->25->1346", - "default.handlebars->25->244", - "default.handlebars->25->549" + "default-mobile.handlebars->9->218", + "default.handlebars->27->1480", + "default.handlebars->27->228", + "default.handlebars->27->596", + "default.handlebars->27->771" ] }, { @@ -15284,12 +21111,31 @@ "en": "Security Key", "es": "Llave de Seguridad", "fr": "Clef de sécurité", + "hi": "सुरक्षा कुंजी", "ja": "セキュリティキー", + "ko": "보안 키", "nl": "Veiligheidssleutel", "pt": "Chave de segurança", "ru": "Ключ безопасности", + "zh-chs": "安全密鑰", "xloc": [ - "default.handlebars->25->1344" + "default.handlebars->27->1478" + ] + }, + { + "cs": "Hledám", + "de": "Ich suche", + "en": "Seeking", + "fr": "Cherchant", + "hi": "तलाश", + "ja": "探している", + "ko": "찾는 중", + "nl": "Op zoek naar", + "pt": "Procurando", + "ru": "Ищу", + "zh-chs": "尋求", + "xloc": [ + "player.handlebars->3->16" ] }, { @@ -15298,15 +21144,18 @@ "en": "Select All", "es": "Seleccionar todo", "fr": "Tout Sélectionner", + "hi": "सभी का चयन करे", "ja": "すべて選択", + "ko": "모두 선택", "nl": "Selecteer alles", "pt": "Selecionar tudo", "ru": "Выбрать все", + "zh-chs": "全選", "xloc": [ - "default.handlebars->25->1173", - "default.handlebars->25->382", - "default.handlebars->25->652", - "default.handlebars->25->654", + "default.handlebars->27->1303", + "default.handlebars->27->372", + "default.handlebars->27->701", + "default.handlebars->27->703", "default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->devListToolbar", "default.handlebars->container->column_l->p13->p13toolbar->1->2->1->3", "default.handlebars->container->column_l->p5->p5toolbar->1->0->p5filehead->3", @@ -15319,14 +21168,17 @@ "en": "Select None", "es": "No seleccionar ninguno", "fr": "Rien sélectionner", + "hi": "किसी का चयन न करें", "ja": "なしを選択", + "ko": "없음을 선택하십시오", "nl": "Selecteer niets", "pt": "Selecione nenhum", "ru": "Очистить все", + "zh-chs": "選擇無", "xloc": [ - "default.handlebars->25->1172", - "default.handlebars->25->381", - "default.handlebars->25->653", + "default.handlebars->27->1302", + "default.handlebars->27->371", + "default.handlebars->27->702", "default.handlebars->meshContextMenu->cxselectnone" ] }, @@ -15335,12 +21187,16 @@ "de": "Wähle eine neue Gruppe für die ausgewählten Geräte", "en": "Select a new group for selected devices", "es": "Seleccione un nuevo grupo para los dispositivos seleccionados.", + "fr": "Sélectionner un nouveau groupe pour ces appareils", + "hi": "चयनित उपकरणों के लिए एक नया समूह चुनें", "ja": "選択したデバイスの新しいグループを選択します", + "ko": "선택한 장치에 대한 새 그룹을 선택하십시오", "nl": "Selecteer een nieuwe groep voor geselecteerde apparaten", "pt": "Selecione um novo grupo para dispositivos selecionados", "ru": "Выберите новую группу для выбранных устройств", + "zh-chs": "為所選設備選擇一個新組", "xloc": [ - "default.handlebars->25->563" + "default.handlebars->27->610" ] }, { @@ -15348,12 +21204,16 @@ "de": "Wähle eine neue Gruppe für dieses Gerät", "en": "Select a new group for this device", "es": "Seleccione un nuevo grupo para este dispositivo", + "fr": "Sélectionner un nouveau groupe pour l'appareil", + "hi": "इस उपकरण के लिए एक नया समूह चुनें", "ja": "このデバイスの新しいグループを選択してください", + "ko": "이 기기의 새 그룹을 선택하십시오", "nl": "Selecteer een nieuwe groep voor dit apparaat", "pt": "Selecione um novo grupo para este dispositivo", "ru": "Выберите новую группу для этого устройства", + "zh-chs": "選擇此設備的新組", "xloc": [ - "default.handlebars->25->562" + "default.handlebars->27->609" ] }, { @@ -15361,12 +21221,16 @@ "de": "Wähle einen Knoten zum Ablegen", "en": "Select a node to place", "es": "Seleccione un nodo para colocar", + "fr": "Sélectionnez un nœud à placer", + "hi": "जगह के लिए एक नोड का चयन करें", "ja": "配置するノードを選択します", + "ko": "배치 할 노드를 선택하십시오", "nl": "Selecteer een knooppunt om te plaatsen", "pt": "Selecione um nó para colocar", "ru": "Выберите узел для размещения", + "zh-chs": "選擇要放置的節點", "xloc": [ - "default.handlebars->25->433" + "default.handlebars->27->437" ] }, { @@ -15374,12 +21238,16 @@ "de": "Wählen Sie eine Operation für die Durchführung auf allen ausgewählten Geräten. Aktionen werden nur bei passenden Rechten durchgeführt.", "en": "Select an operation to perform on all selected devices. Actions will be performed only with proper rights.", "es": "Seleccione una operación para realizar en todos los dispositivos seleccionados. Las acciones se realizarán solo con los derechos correspondientes.", + "fr": "Choisir une opération à réaliser sur les appareils sélectionnés (dépend de vos droits).", + "hi": "सभी चयनित उपकरणों पर प्रदर्शन करने के लिए एक ऑपरेशन का चयन करें। उचित अधिकारों के साथ ही कार्रवाई की जाएगी।", "ja": "選択したすべてのデバイスで実行する操作を選択します。アクションは適切な権限でのみ実行されます。", + "ko": "선택한 모든 장치에서 수행 할 작업을 선택하십시오. 조치는 적절한 권한으로 만 수행됩니다.", "nl": "Selecteer een bewerking die op alle geselecteerde apparaten moet worden uitgevoerd. Acties worden alleen uitgevoerd met de juiste rechten.", "pt": "Selecione uma operação para executar em todos os dispositivos selecionados. As ações serão executadas apenas com os direitos adequados.", "ru": "Выберите действие для осуществления на всех выбранных устройствах. Действия будут выполнены только при наличии соответствующих прав.", + "zh-chs": "選擇要在所有選定設備上執行的操作。僅在擁有適當權限的情況下才能執行操作。", "xloc": [ - "default.handlebars->25->385" + "default.handlebars->27->375" ] }, { @@ -15387,13 +21255,17 @@ "de": "Wählen Sie eine Operation für die Durchführung auf diesem Gerät.", "en": "Select an operation to perform on this device.", "es": "Seleccione una operación para realizar en este dispositivo.", + "fr": "Sélectionner l'opération à réaliser sur l'appareil", + "hi": "इस डिवाइस पर प्रदर्शन करने के लिए एक ऑपरेशन का चयन करें।", "ja": "このデバイスで実行する操作を選択します。", + "ko": "이 장치에서 수행 할 작업을 선택하십시오.", "nl": "Selecteer een bewerking die u op dit apparaat wilt uitvoeren.", "pt": "Selecione uma operação para executar neste dispositivo.", "ru": "Выберите действие для осуществления на этом устройстве.", + "zh-chs": "選擇要在此設備上執行的操作。", "xloc": [ - "default-mobile.handlebars->9->205", - "default.handlebars->25->535" + "default-mobile.handlebars->9->209", + "default.handlebars->27->582" ] }, { @@ -15402,10 +21274,13 @@ "en": "SelectAll", "es": "Seleccionar Todos", "fr": "ToutSélectionner", + "hi": "सभी का चयन करे", "ja": "すべて選択", + "ko": "모두 선택", "nl": "Selecteer alles", "pt": "Selecionar tudo", "ru": "Выбрать все", + "zh-chs": "全選", "xloc": [ "default-mobile.handlebars->container->page_content->column_l->p10->p10files->p13toolbar->1->2->1->1", "default-mobile.handlebars->container->page_content->column_l->p5->p5myfiles->p5toolbar->1->0->1->1" @@ -15416,13 +21291,17 @@ "de": "Nur eigene Ereignisse", "en": "Self Events Only", "es": "Solamente Self Eventos", + "fr": "Événements personnels uniquement", + "hi": "सेल्फ इवेंट्स ओनली", "ja": "自己イベントのみ", + "ko": "자체 이벤트 만", "nl": "Alleen eigen gebeurtenissen", "pt": "Somente Eventos Próprios", "ru": "Только собственные события", + "zh-chs": "僅自我事件", "xloc": [ - "default-mobile.handlebars->9->324", - "default.handlebars->25->1128" + "default-mobile.handlebars->9->328", + "default.handlebars->27->1241" ] }, { @@ -15431,10 +21310,13 @@ "en": "Send", "es": "Enviar", "fr": "Envoyer", + "hi": "संदेश", "ja": "送る", + "ko": "보내다", "nl": "verzenden", "pt": "Enviar", "ru": "Отправить", + "zh-chs": "發送", "xloc": [ "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3", "default.handlebars->container->column_l->p12->termTable->1->1->6->1->1->specialKeyDropDown", @@ -15447,13 +21329,16 @@ "en": "Send MQTT Message", "es": "Enviar mensaje MQTT", "fr": "Envoyer un Message MQTT", + "hi": "MQTT संदेश भेजें", "ja": "MQTTメッセージを送信", + "ko": "MQTT 메시지 보내기", "nl": "Verzend MQTT bericht", "pt": "Enviar Mensagem MQTT", "ru": "Отправить MQTT сообщение", + "zh-chs": "發送MQTT消息", "xloc": [ - "default.handlebars->25->383", - "default.handlebars->25->540" + "default.handlebars->27->373", + "default.handlebars->27->587" ] }, { @@ -15462,12 +21347,15 @@ "en": "Send MQTT message", "es": "Enviar mensaje MQTT", "fr": "Envoyer un message MQTT", + "hi": "MQTT संदेश भेजें", "ja": "MQTTメッセージを送信", + "ko": "MQTT 메시지 보내기", "nl": "Verzend MQTT bericht", "pt": "Enviar mensagem MQTT", "ru": "Отправить MQTT сообщение", + "zh-chs": "發送MQTT消息", "xloc": [ - "default.handlebars->25->555" + "default.handlebars->27->602" ] }, { @@ -15475,10 +21363,16 @@ "de": "Sende eine Mitteilung an alle Benutzer in dieser Gruppe.", "en": "Send a notice to all users in this group.", "es": "Enviar un mensaje a todos los usuarios de este grupo.", + "fr": "Envoyer une notification à tous les utilisateurs du groupe.", + "hi": "इस समूह के सभी उपयोगकर्ताओं को एक सूचना भेजें।", + "ja": "このグループのすべてのユーザーに通知を送信します。", + "ko": "이 그룹의 모든 사용자에게 알림을 보냅니다.", "nl": "Stuur een bericht naar alle gebruikers in deze groep.", + "pt": "Envie um aviso para todos os usuários deste grupo.", "ru": "Отправить уведомление всем пользователям этой группы.", + "zh-chs": "向該組中的所有用戶發送通知。", "xloc": [ - "default.handlebars->25->1287" + "default.handlebars->27->1423" ] }, { @@ -15487,12 +21381,28 @@ "en": "Send a text notification to this user.", "es": "Enviar un mensaje de texto a este usuario.", "fr": "Envoyez une notification à cet utilisateur.", + "hi": "इस उपयोगकर्ता को एक पाठ सूचना भेजें।", "ja": "このユーザーにテキスト通知を送信します。", + "ko": "이 사용자에게 문자 알림을 보냅니다.", "nl": "Stuur een tekstbericht naar deze gebruiker.", "pt": "Envie uma notificação de texto para este usuário.", "ru": "Отправить текстовое уведомление этому пользователю.", + "zh-chs": "向該用戶發送文本通知。", "xloc": [ - "default.handlebars->25->1224" + "default.handlebars->27->1359" + ] + }, + { + "cs": "Odeslat e-mail uživateli", + "de": "E-Mail an Benutzer senden", + "en": "Send email to user", + "fr": "Envoyer un e-mail à l'utilisateur", + "ja": "ユーザーにメールを送信", + "nl": "Stuur e-mail naar de gebruiker", + "ru": "Отправить письмо пользователю", + "zh-chs": "发送电子邮件给用户", + "xloc": [ + "default.handlebars->27->1355" ] }, { @@ -15501,12 +21411,15 @@ "en": "Send installation link", "es": "Enviar enlace de instalación.", "fr": "Envoyer le lien d'installation", + "hi": "स्थापना लिंक भेजें", "ja": "インストールリンクを送信", + "ko": "설치 링크 보내기", "nl": "Verzend installatie link", "pt": "Enviar link de instalação", "ru": "Отправить ссылку для установки", + "zh-chs": "發送安裝鏈接", "xloc": [ - "default.handlebars->25->286" + "default.handlebars->27->273" ] }, { @@ -15515,12 +21428,15 @@ "en": "Send invitation email.", "es": "Enviar correo electrónico de invitación.", "fr": "Envoyer un email d'invitation.", + "hi": "निमंत्रण ईमेल भेजें।", "ja": "招待メールを送信します。", + "ko": "초대 이메일을 보내십시오.", "nl": "Verzend uitnodigingsmail.", "pt": "Enviar email de convite.", "ru": "Отправить приглашение по email.", + "zh-chs": "發送邀請電子郵件。", "xloc": [ - "default.handlebars->25->1252" + "default.handlebars->27->1387" ] }, { @@ -15528,38 +21444,66 @@ "de": "Sende den ausgewählten Spezialschlüssel", "en": "Send the selected special key", "es": "Enviar la clave especial seleccionada", + "fr": "Envoyer la clé sélectionnée", + "hi": "चयनित विशेष कुंजी भेजें", "ja": "選択した特殊キーを送信します", + "ko": "선택한 특수 키를 보냅니다.", "nl": "Verzend de geselecteerde speciale sleutel", "pt": "Enviar a chave especial selecionada", "ru": "Отправить выбранную специальную клавишу", + "zh-chs": "發送選定的特殊鍵", "xloc": [ "default.handlebars->container->column_l->p12->termTable->1->1->6->1->1->specialKeyDropDown" ] }, + { + "cs": "Odeslat token na zaregistrovanou e-mailovou adresu?", + "de": "Token an registrierte E-Mail-Adresse senden?", + "en": "Send token to registed email address?", + "fr": "Envoyer un jeton à une adresse e-mail enregistrée?", + "hi": "प्राप्त ईमेल पते पर टोकन भेजें?", + "ja": "登録済みのメールアドレスにトークンを送信しますか?", + "ko": "등록 된 이메일 주소로 토큰을 보내시겠습니까?", + "nl": "Token verzenden naar geregistreerd e-mailadres?", + "pt": "Enviar token para o endereço de e-mail registrado?", + "ru": "Отправить токен на зарегистрированный адрес электронной почты?", + "zh-chs": "將令牌發送到註冊的電子郵件地址?", + "xloc": [ + "login-mobile.handlebars->5->21", + "login.handlebars->5->21" + ] + }, { "cs": "Poslat upozornění uživateli", "de": "Sende Benutzerbenachrichtigung", "en": "Send user notification", "es": "Enviar notificación de usuario", "fr": "Envoyer une notification utilisateur", + "hi": "उपयोगकर्ता अधिसूचना भेजें", "ja": "ユーザー通知を送信する", + "ko": "사용자 알림 보내기", "nl": "Stuur gebruikersmelding", "pt": "Enviar notificação do usuário", "ru": "Отправить уведомление пользователю", + "zh-chs": "發送用戶通知", "xloc": [ - "default.handlebars->25->1351" + "default.handlebars->27->1485" ] }, { "cs": "srbština", "de": "Serbisch", "en": "Serbian", + "fr": "Serbe", + "hi": "सर्बियाई", "ja": "セルビア語", + "ko": "세르비아 사람", "nl": "Servisch", "pt": "Sérvia", "ru": "Сербский", + "zh-chs": "塞爾維亞", "xloc": [ - "default.handlebars->25->868" + "default.handlebars->27->972" ] }, { @@ -15567,12 +21511,16 @@ "de": "Seriennummer", "en": "Serial", "es": "Serial", + "fr": "En série", + "hi": "धारावाहिक", "ja": "シリアル", + "ko": "연속물", "nl": "Serie nummer", "pt": "Serial", "ru": "Серийный номер", + "zh-chs": "序列號", "xloc": [ - "default.handlebars->25->72" + "default.handlebars->27->783" ] }, { @@ -15580,12 +21528,16 @@ "de": "Server-Datensicherung", "en": "Server Backup", "es": "Copia de seguridad del servidor", + "fr": "Sauvegarde du serveur", + "hi": "सर्वर बैकअप", "ja": "サーバーバックアップ", + "ko": "서버 백업", "nl": "Server Back-up", "pt": "Backup do servidor", "ru": "Резервное копирование сервера", + "zh-chs": "服務器備份", "xloc": [ - "default.handlebars->25->1261" + "default.handlebars->27->1397" ] }, { @@ -15593,11 +21545,32 @@ "de": "Server-Zertifikat", "en": "Server Certificate", "es": "Certificado del servidor", + "fr": "Certificat de serveur", + "hi": "सर्वर प्रमाणपत्र", "ja": "サーバー証明書", + "ko": "서버 인증서", "nl": "Server Certificaat", + "pt": "Certificado do servidor", "ru": "Сертификат сервера", + "zh-chs": "服務器證書", "xloc": [ - "default.handlebars->25->1446" + "default.handlebars->27->1593" + ] + }, + { + "cs": "Databáze serveru", + "de": "Server-Datenbank", + "en": "Server Database", + "fr": "Base de données du serveur", + "hi": "सर्वर डेटाबेस", + "ja": "サーバーデータベース", + "ko": "서버 데이터베이스", + "nl": "Server Database", + "pt": "Banco de Dados do Servidor", + "ru": "База данных сервера", + "zh-chs": "服務器數據庫", + "xloc": [ + "default.handlebars->27->1594" ] }, { @@ -15605,16 +21578,22 @@ "de": "Server-Dateien", "en": "Server Files", "es": "Archivos del servidor", + "fr": "Serveur de fichiers", + "hi": "सर्वर फ़ाइलें", "ja": "サーバーファイル", + "ko": "서버 파일", "nl": "Serverbestanden", "pt": "Arquivos do servidor", "ru": "Серверные файлы", + "zh-chs": "服務器文件", "xloc": [ - "default-mobile.handlebars->9->303", - "default-mobile.handlebars->9->316", - "default.handlebars->25->1102", - "default.handlebars->25->1120", - "default.handlebars->25->1259" + "default-mobile.handlebars->9->307", + "default-mobile.handlebars->9->320", + "default.handlebars->27->1210", + "default.handlebars->27->1232", + "default.handlebars->27->1394", + "default.handlebars->27->550", + "default.handlebars->27->569" ] }, { @@ -15622,13 +21601,17 @@ "de": "Server-Berechtigungen", "en": "Server Permissions", "es": "Permisos de servidor", + "fr": "Permissions du serveur", + "hi": "सर्वर अनुमतियाँ", "ja": "サーバーの許可", + "ko": "서버 권한", "nl": "Serverrechten", "pt": "Permissões do servidor", "ru": "Разрешения сервера", + "zh-chs": "服務器權限", "xloc": [ - "default.handlebars->25->1217", - "default.handlebars->25->1269" + "default.handlebars->27->1347", + "default.handlebars->27->1405" ] }, { @@ -15636,12 +21619,16 @@ "de": "Server-Kontingent", "en": "Server Quota", "es": "Cuota de servidor", + "fr": "Quota serveur", + "hi": "सर्वर कोटा", "ja": "サーバークォータ", + "ko": "서버 할당량", "nl": "Serverquotum", "pt": "Cota do servidor", "ru": "Квота сервера", + "zh-chs": "服務器配額", "xloc": [ - "default.handlebars->25->1330" + "default.handlebars->27->1464" ] }, { @@ -15649,12 +21636,16 @@ "de": "Server-Wiederherstellung", "en": "Server Restore", "es": "Restauración del servidor", + "fr": "Restauration du serveur", + "hi": "सर्वर पुनर्स्थापित", "ja": "サーバーの復元", + "ko": "서버 복원", "nl": "Server herstellen", "pt": "Restauração do servidor", "ru": "Восстановление сервера", + "zh-chs": "服務器還原", "xloc": [ - "default.handlebars->25->1262" + "default.handlebars->27->1398" ] }, { @@ -15663,12 +21654,15 @@ "en": "Server Rights", "es": "Privilegios del servidor", "fr": "Droits du serveur", + "hi": "सर्वर अधिकार", "ja": "サーバーの権利", + "ko": "서버 권한", "nl": "Serverrechten", "pt": "Direitos do servidor", "ru": "Права", + "zh-chs": "服務器權限", "xloc": [ - "default.handlebars->25->1329" + "default.handlebars->27->1463" ] }, { @@ -15676,10 +21670,16 @@ "de": "Server-Zustand", "en": "Server State", "es": "Estado del servidor", + "fr": "Chiffres clés", + "hi": "सर्वर स्थिति", + "ja": "サーバー状態", + "ko": "서버 상태", "nl": "Server Status", + "pt": "Estado do servidor", "ru": "Состояние сервера", + "zh-chs": "服務器狀態", "xloc": [ - "default.handlebars->25->1397" + "default.handlebars->27->1544" ] }, { @@ -15687,11 +21687,14 @@ "de": "Server-Statistiken", "en": "Server Statistics", "es": "Estadísticas del servidor", - "fr": "Statistiques du serveur", + "fr": "Statistiques", + "hi": "सर्वर सांख्यिकी", "ja": "サーバー統計", + "ko": "서버 통계", "nl": "Serverstatistieken", "pt": "Estatísticas do servidor", "ru": "Статистика сервера", + "zh-chs": "服務器統計", "xloc": [ "default.handlebars->container->column_l->p6->6" ] @@ -15702,12 +21705,15 @@ "en": "Server Tracing", "es": "Seguimiento del servidor", "fr": "Suivi du serveur", + "hi": "सर्वर ट्रेसिंग", "ja": "サーバートレース", + "ko": "서버 추적", "nl": "Server traceren", "pt": "Rastreamento de servidor", "ru": "Трассировка сервера", + "zh-chs": "服務器跟踪", "xloc": [ - "default.handlebars->25->1455" + "default.handlebars->27->1604" ] }, { @@ -15716,12 +21722,15 @@ "en": "Server Updates", "es": "Actualizaciones del servidor", "fr": "Mises à jour du serveur", + "hi": "सर्वर अपडेट", "ja": "サーバーの更新", + "ko": "서버 업데이트", "nl": "Serverupdates", "pt": "Atualizações do Servidor", "ru": "Обновление сервера", + "zh-chs": "服務器更新", "xloc": [ - "default.handlebars->25->1263" + "default.handlebars->27->1399" ] }, { @@ -15730,9 +21739,13 @@ "en": "Server Warnings", "es": "Advertencias del servidor", "fr": "Avertissements du serveur", + "hi": "सर्वर चेतावनी", "ja": "サーバー警告", + "ko": "서버 경고", "nl": "Serverwaarschuwingen", + "pt": "Avisos do servidor", "ru": "Предупреждения сервера", + "zh-chs": "服務器警告", "xloc": [ "default.handlebars->container->column_l->p6->serverWarningsDiv->2" ] @@ -15742,10 +21755,14 @@ "de": "Server-Aktionen", "en": "Server actions", "es": "Acciones del servidor", + "fr": "Actions du serveur", + "hi": "सर्वर क्रिया", "ja": "サーバーアクション", + "ko": "서버 동작", "nl": "Server acties", "pt": "Ações do servidor", "ru": "Действия сервера", + "zh-chs": "服務器動作", "xloc": [ "default.handlebars->container->column_l->p6->p2ServerActions->1->0" ] @@ -15755,10 +21772,14 @@ "de": "Server getrennt", "en": "Server disconnected", "es": "Servidor desconectado", + "fr": "Le serveur est déconnecté", + "hi": "सर्वर काट दिया गया", "ja": "サーバーが切断されました", + "ko": "서버 연결이 끊어졌습니다", "nl": "Server verbroken", "pt": "Servidor desconectado", "ru": "Сервер отключен", + "zh-chs": "服務器已斷開連接", "xloc": [ "default-mobile.handlebars->container->page_content->column_l->p0->1->p0message->p0span", "default.handlebars->container->column_l->p0->p0message->p0span" @@ -15769,10 +21790,14 @@ "de": "Server-Dateiauswahl", "en": "Server file selection", "es": "Selección de archivo del servidor", + "fr": "Sélection de fichiers serveur", + "hi": "सर्वर फ़ाइल चयन", "ja": "サーバーファイルの選択", + "ko": "서버 파일 선택", "nl": "Selectie serverbestand", "pt": "Seleção de arquivo do servidor", "ru": "Выбор серверного файла", + "zh-chs": "服務器文件選擇", "xloc": [ "default.handlebars->container->dialog->dialogBody->dialog3->d3upload->d3uploadMode->3" ] @@ -15782,12 +21807,16 @@ "de": "Server besitzt kein Fehlerprotokoll.", "en": "Server has no error log.", "es": "El servidor no tiene registro de errores.", + "fr": "Aucune erreur pour ce serveur.", + "hi": "सर्वर में कोई त्रुटि लॉग नहीं है।", "ja": "サーバーにはエラーログがありません。", + "ko": "서버에 오류 로그가 없습니다.", "nl": "Server heeft geen foutenlogboek.", "pt": "O servidor não possui log de erros.", "ru": "На сервере нет журнала ошибок.", + "zh-chs": "服務器沒有錯誤日誌。", "xloc": [ - "default.handlebars->25->116" + "default.handlebars->27->99" ] }, { @@ -15795,10 +21824,14 @@ "de": "Server zeichnet diese Sitzung auf", "en": "Server is recording this session", "es": "El servidor está grabando esta sesión.", + "fr": "Session en cours d'enregistrement", + "hi": "सर्वर इस सत्र की रिकॉर्डिंग कर रहा है", "ja": "サーバーはこのセッションを記録しています", + "ko": "서버가이 세션을 기록하고 있습니다", "nl": "Server neemt deze sessie op", "pt": "O servidor está gravando esta sessão", "ru": "Сервер проводит запись этой сессии", + "zh-chs": "服務器正在記錄此會話", "xloc": [ "default.handlebars->container->column_l->p11->deskarea0->deskarea1->1", "default.handlebars->container->column_l->p12->termTable->1->1->0->1->1", @@ -15807,14 +21840,19 @@ }, { "cs": "ServerStats.csv", + "de": "ServerStats.csv", "en": "ServerStats.csv", "es": "ServerStats.csv", + "fr": "ServerStats.csv", + "hi": "ServerStats.csv", "ja": "ServerStats.csv", + "ko": "ServerStats.csv", "nl": "ServerStats.csv", "pt": "ServerStats.csv", "ru": "ServerStats.csv", + "zh-chs": "ServerStats.csv", "xloc": [ - "default.handlebars->25->1438" + "default.handlebars->27->1585" ] }, { @@ -15822,12 +21860,16 @@ "de": "Dienst-Details", "en": "Service Details", "es": "Detalles del Servicio", + "fr": "Détails du service", + "hi": "सेवा का विवरण", "ja": "サービスの詳細", + "ko": "서비스 내용", "nl": "Servicegegevens", "pt": "Detalhes do serviço", "ru": "Детали службы", + "zh-chs": "服務詳情", "xloc": [ - "default.handlebars->25->632" + "default.handlebars->27->681" ] }, { @@ -15835,10 +21877,14 @@ "de": "Dienste", "en": "Services", "es": "Servicios", + "fr": "Prestations de service", + "hi": "सेवाएं", "ja": "サービス", + "ko": "서비스", "nl": "Services", "pt": "Serviços", "ru": "Службы", + "zh-chs": "服務", "xloc": [ "default.handlebars->container->column_l->p11->deskarea0->deskarea3x->DeskTools->deskToolsAreaTop->deskToolsTopTabService" ] @@ -15849,10 +21895,13 @@ "en": "Session time", "es": "Tiempo de sesión", "fr": "Temps de session", + "hi": "सत्र का समय", "ja": "セッション時間", + "ko": "세션 시간", "nl": "Sessie tijd", "pt": "Tempo de sessão", "ru": "Время сессии", + "zh-chs": "上課時間", "xloc": [ "default.handlebars->container->column_l->p11->deskarea0->deskarea4->1", "default.handlebars->container->column_l->p12->termTable->1->1->6->1->1" @@ -15864,10 +21913,13 @@ "en": "SessionID", "es": "ID de sesión", "fr": "ID de session", + "hi": "सत्र आईडी", "ja": "セッションID", + "ko": "SessionID", "nl": "SessieID", "pt": "ID da sessão", "ru": "ID сессии", + "zh-chs": "會話ID", "xloc": [ "player.handlebars->3->6" ] @@ -15878,10 +21930,13 @@ "en": "Settings", "es": "Configuraciones", "fr": "Paramètres", + "hi": "समायोजन", "ja": "設定", + "ko": "설정", "nl": "Instellingen", "pt": "Configurações", "ru": "Настройки", + "zh-chs": "設定值", "xloc": [ "default-mobile.handlebars->container->page_content->column_l->p10->p10desktop->deskarea4->1->3", "default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->kvmListToolbar" @@ -15893,12 +21948,15 @@ "en": "Settings File", "es": "Archivo de configuración", "fr": "Fichier de Paramètres", + "hi": "सेटिंग्स फ़ाइल", "ja": "設定ファイル", + "ko": "설정 파일", "nl": "Instellingenbestand", "pt": "Arquivo de configurações", "ru": "Файл с настройками", + "zh-chs": "設定文件", "xloc": [ - "default.handlebars->25->331" + "default.handlebars->27->320" ] }, { @@ -15907,10 +21965,13 @@ "en": "Settings...", "es": "Configuraciones ...", "fr": "Paramètres...", + "hi": "समायोजन...", "ja": "設定...", + "ko": "설정 ...", "nl": "Instellingen ...", "pt": "Configurações...", "ru": "Настройки...", + "zh-chs": "設定...", "xloc": [ "default.handlebars->container->column_l->p11->deskarea0->deskarea1->1" ] @@ -15920,12 +21981,16 @@ "de": "CIRA einrichten", "en": "Setup CIRA", "es": "Configurar CIRA", + "fr": "Configuration CIRA", + "hi": "सेटअप CIRA", "ja": "CIRAのセットアップ", + "ko": "CIRA 설정", "nl": "CIRA instellen", "pt": "Configuração CIRA", "ru": "Установить CIRA", + "zh-chs": "設置CIRA", "xloc": [ - "default.handlebars->25->263" + "default.handlebars->27->247" ] }, { @@ -15933,12 +21998,16 @@ "de": "Einrichtungsmethode", "en": "Setup Method", "es": "Método de configuración", + "fr": "Méthode de configuration", + "hi": "सेटअप विधि", "ja": "設定方法", + "ko": "설정 방법", "nl": "Setup methode", "pt": "Método de instalação", "ru": "Метод установки", + "zh-chs": "設定方法", "xloc": [ - "default.handlebars->25->261" + "default.handlebars->27->245" ] }, { @@ -15947,16 +22016,19 @@ "en": "Setup...", "es": "Configurar ...", "fr": "Traitement...", + "hi": "सेट अप...", "ja": "セットアップ...", + "ko": "설정...", "nl": "Setup...", "pt": "Configurando...", "ru": "Установка...", + "zh-chs": "設定...", "xloc": [ "default-mobile.handlebars->9->3", - "default.handlebars->25->10", - "default.handlebars->25->212", - "default.handlebars->25->215", - "default.handlebars->25->221", + "default.handlebars->27->10", + "default.handlebars->27->196", + "default.handlebars->27->199", + "default.handlebars->27->205", "xterm.handlebars->9->3" ] }, @@ -15966,10 +22038,13 @@ "en": "Share a file", "es": "Comparte un archivo", "fr": "Partager un fichier", + "hi": "एक फ़ाइल साझा करें", "ja": "ファイルを共有する", + "ko": "파일 공유", "nl": "Deel een bestand", "pt": "Compartilhar um arquivo", "ru": "Поделиться файлом", + "zh-chs": "分享檔案", "xloc": [ "messenger.handlebars->xtop->1" ] @@ -15979,12 +22054,16 @@ "de": "Geteilter Prozess", "en": "SharedProcess", "es": "Procesos compartidos", + "fr": "Processus partagés", + "hi": "SharedProcess", "ja": "SharedProcess", + "ko": "공유 프로세스", "nl": "Gedeeld proces", "pt": "Processo compartilhado", "ru": "Общий процесс", + "zh-chs": "共享過程", "xloc": [ - "default.handlebars->25->626" + "default.handlebars->27->675" ] }, { @@ -15992,10 +22071,14 @@ "de": "Umschalten+Win+M", "en": "Shift+Win+M", "es": "Shift+Win+M", + "fr": "Maj + Win + M", + "hi": "Shift + विन + M", "ja": "Shift + Win + M", + "ko": "Shift + Win + M", "nl": "Shift+Win+M", "pt": "Shift+Win+M", "ru": "Shift+Win+M", + "zh-chs": "Shift + Win + M", "xloc": [ "default-mobile.handlebars->dialog->3->dialog3->deskkeys->15", "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->deskkeys->13" @@ -16007,10 +22090,13 @@ "en": "Show", "es": "Mostrar", "fr": "Afficher", + "hi": "प्रदर्शन", "ja": "ショー", + "ko": "보여 주다", "nl": "Tonen", "pt": "Mostrar", "ru": "Показать", + "zh-chs": "節目", "xloc": [ "default.handlebars->container->column_l->p16->3->1->0->5", "default.handlebars->container->column_l->p3->3->1->0->3", @@ -16023,10 +22109,14 @@ "de": "Fokus-Werkzeug anzeigen", "en": "Show Focus Tool", "es": "Mostrar herramienta de enfoque", + "fr": "Afficher l'outil de mise au point", + "hi": "फोकस टूल दिखाएं", "ja": "フォーカスツールを表示", + "ko": "초점 도구 표시", "nl": "Toon focus tool", "pt": "Mostrar ferramenta de foco", "ru": "Показать инструмент фокусировки", + "zh-chs": "顯示焦點工具", "xloc": [ "default-mobile.handlebars->dialog->3->dialog7->d7amtkvm->5->1->1", "default.handlebars->container->dialog->dialogBody->dialog7->d7amtkvm->5->d7otherset->1" @@ -16038,10 +22128,13 @@ "en": "Show Hint", "es": "Mostrar pista", "fr": "Dévoiler indice", + "hi": "संकेत दिखाएं", "ja": "ヒントを見せて", + "ko": "힌트 표시", "nl": "Toon hint", "pt": "Mostrar dica", "ru": "Показать подсказку", + "zh-chs": "顯示提示", "xloc": [ "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->loginpanel->1->7->1->4->1->showPassHintLink->0", "login.handlebars->container->column_l->centralTable->1->0->logincell->loginpanel->1->7->1->4->1->showPassHintLink->0" @@ -16052,10 +22145,14 @@ "de": "Lokalen Mauszeiger anzeigen", "en": "Show Local Mouse Cursor", "es": "Mostrar cursor del mouse local", + "fr": "Afficher le curseur local", + "hi": "स्थानीय माउस कर्सर दिखाएँ", "ja": "ローカルマウスカーソルを表示", + "ko": "로컬 마우스 커서 표시", "nl": "Lokale muiscursor weergeven", "pt": "Mostrar Cursor do Mouse Local", "ru": "Показать локальный курсор мыши", + "zh-chs": "顯示本地鼠標光標", "xloc": [ "default-mobile.handlebars->dialog->3->dialog7->d7amtkvm->5->1->4", "default.handlebars->container->dialog->dialogBody->dialog7->d7amtkvm->5->d7otherset->3" @@ -16066,13 +22163,17 @@ "de": "Nur eigene Ereignisse anzeigen", "en": "Show Only Own Events", "es": "Mostrar solo eventos propios", + "fr": "Voir ses propres évènements", + "hi": "केवल स्वयं ईवेंट दिखाएं", "ja": "自分のイベントのみを表示", + "ko": "자신의 이벤트 만 표시", "nl": "Toon alleen eigen gebeurtenissen", "pt": "Mostrar apenas eventos próprios", "ru": "Показывать только собственные события", + "zh-chs": "只顯示自己的事件", "xloc": [ - "default-mobile.handlebars->9->306", - "default.handlebars->25->1105" + "default-mobile.handlebars->9->310", + "default.handlebars->27->1213" ] }, { @@ -16081,12 +22182,15 @@ "en": "Show connection toolbar", "es": "Mostrar barra de herramientas de conexión", "fr": "Afficher la barre d'outils de connexion", + "hi": "कनेक्शन टूलबार दिखाएं", "ja": "接続ツールバーを表示", + "ko": "연결 도구 모음 표시", "nl": "Toon verbindingswerkbalk", "pt": "Mostrar barra de ferramentas de conexão", "ru": "Показывать панель-уведомление", + "zh-chs": "顯示連接工具欄", "xloc": [ - "default.handlebars->25->1072" + "default.handlebars->27->1176" ] }, { @@ -16094,12 +22198,16 @@ "de": "Geräte-Standortinformationen anzeigen", "en": "Show device locations information", "es": "Mostrar información de ubicaciones del dispositivo", + "fr": "Voir l'emplacement", + "hi": "डिवाइस स्थानों की जानकारी दिखाएं", "ja": "デバイスの位置情報を表示する", + "ko": "장치 위치 정보 표시", "nl": "Informatie over apparaatlocaties weergeven", "pt": "Mostrar informações de localizações do dispositivo", "ru": "Показать информацию о расположении устройства", + "zh-chs": "顯示設備位置信息", "xloc": [ - "default.handlebars->25->506" + "default.handlebars->27->513" ] }, { @@ -16107,12 +22215,16 @@ "de": "Geräte-Netzwerkschnittstelleninformationen anzeigen", "en": "Show device network interface information", "es": "Mostrar información de la interfaz de red del dispositivo", + "fr": "Voir les informations de l'interface réseau", + "hi": "डिवाइस नेटवर्क इंटरफ़ेस जानकारी दिखाएं", "ja": "デバイスのネットワークインターフェイス情報を表示する", + "ko": "장치 네트워크 인터페이스 정보 표시", "nl": "Toon apparaat netwerk interface informatie", "pt": "Mostrar informações da interface de rede do dispositivo", "ru": "Показать информацию о сетевом интерфейсе устройства", + "zh-chs": "顯示設備網絡接口信息", "xloc": [ - "default.handlebars->25->504" + "default.handlebars->27->511" ] }, { @@ -16120,10 +22232,14 @@ "de": "Geräte-Betriebssystemname anzeigen", "en": "Show devices operating system name", "es": "Mostrar el nombre del sistema operativo de los dispositivos", + "fr": "Voir le nom de l'OS des appareils", + "hi": "ऑपरेटिंग सिस्टम नाम डिवाइस दिखाएं", "ja": "デバイスのオペレーティングシステム名を表示する", + "ko": "장치 운영 체제 이름 표시", "nl": "Toon apparaten besturingssysteemnaam", "pt": "Mostrar o nome do sistema operacional dos dispositivos", "ru": "Фильтр по имени хоста, заданному в настройках ОС", + "zh-chs": "顯示設備操作系統名稱", "xloc": [ "default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->devListToolbar->7" ] @@ -16134,10 +22250,13 @@ "en": "Show server error log", "es": "Mostrar registro de errores del servidor", "fr": "Afficher le journal des erreurs du serveur", + "hi": "सर्वर त्रुटि लॉग दिखाएं", "ja": "サーバーエラーログを表示", + "ko": "서버 오류 로그 표시", "nl": "Serverlogboek weergeven", "pt": "Mostrar log de erros do servidor", "ru": "Показать журнал ошибок сервера", + "zh-chs": "顯示服務器錯誤日誌", "xloc": [ "default.handlebars->container->column_l->p6->p2ServerActions->3->p2ServerActionsErrors->0" ] @@ -16147,13 +22266,17 @@ "de": "Einfacher Admin Control Mode (ACM)", "en": "Simple Admin Control Mode (ACM)", "es": "Modo de Control de Administrador Simple (ACM)", + "fr": "Contrôle administrateur simple (ACM)", + "hi": "सरल व्यवस्थापक नियंत्रण मोड (ACM)", "ja": "シンプル管理制御モード(ACM)", + "ko": "간단한 관리 제어 모드 (ACM)", "nl": "Eenvoudige Admin Control Mode (ACM)", "pt": "Modo de controle de administrador simples (ACM)", "ru": "Простой режим управления администратора (ACM)", + "zh-chs": "簡單管理員控制模式(ACM)", "xloc": [ - "default.handlebars->25->1010", - "default.handlebars->25->1036" + "default.handlebars->27->1117", + "default.handlebars->27->1140" ] }, { @@ -16161,14 +22284,18 @@ "de": "Einfacher Client Control Mode (CCM)", "en": "Simple Client Control Mode (CCM)", "es": "Modo de control de cliente simple (CCM)", + "fr": "Contrôle client simple (CCM)", + "hi": "सरल ग्राहक नियंत्रण मोड (CCM)", "ja": "シンプルクライアントコントロールモード(CCM)", + "ko": "단순 클라이언트 제어 모드 (CCM)", "nl": "Eenvoudige Client Control Mode (CCM)", "pt": "Modo de Controle de Cliente Simples (CCM)", "ru": "Простой режим управления клиента (CCM)", + "zh-chs": "簡單客戶端控制模式(CCM)", "xloc": [ - "default.handlebars->25->1008", - "default.handlebars->25->1039", - "default.handlebars->25->1043" + "default.handlebars->27->1115", + "default.handlebars->27->1143", + "default.handlebars->27->1147" ] }, { @@ -16176,12 +22303,15 @@ "de": "Sindhi", "en": "Sindhi", "fr": "Sindhi", + "hi": "सिंधी", "ja": "シンディ", + "ko": "신디", "nl": "Sindhi", "pt": "Sindhi", "ru": "Синдхи", + "zh-chs": "信地", "xloc": [ - "default.handlebars->25->866" + "default.handlebars->27->970" ] }, { @@ -16189,12 +22319,15 @@ "de": "Singhalesisch", "en": "Singhalese", "fr": "Cingalais", + "hi": "लंका का", "ja": "シンハラ語", + "ko": "싱할 레스", "nl": "Sinhalees", "pt": "Cingalês", "ru": "Сингальский", + "zh-chs": "僧伽羅語", "xloc": [ - "default.handlebars->25->867" + "default.handlebars->27->971" ] }, { @@ -16203,10 +22336,13 @@ "en": "Size", "es": "Tamaño", "fr": "Taille", + "hi": "आकार", "ja": "サイズ", + "ko": "크기", "nl": "Grootte", "pt": "Tamanho", "ru": "Размер", + "zh-chs": "尺寸", "xloc": [ "default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->9->devListToolbarSize" ] @@ -16216,10 +22352,16 @@ "de": "Größe: 100%", "en": "Size: 100%", "es": "Tamaño: 100%", + "fr": "Taille : 100%", + "hi": "आकार: 100%", + "ja": "サイズ:100%", + "ko": "사이즈 : 100 %", "nl": "Grootte: 150%", + "pt": "Tamanho: 100%", "ru": "Размер: 100%", + "zh-chs": "尺寸:100%", "xloc": [ - "default.handlebars->25->680" + "default.handlebars->27->729" ] }, { @@ -16227,10 +22369,16 @@ "de": "Größe: 125%", "en": "Size: 125%", "es": "Tamaño: 125%", + "fr": "Taille : 125%", + "hi": "आकार: 125%", + "ja": "サイズ:125%", + "ko": "크기 : 125 %", "nl": "Grootte: 150%", + "pt": "Tamanho: 125%", "ru": "Размер: 125%", + "zh-chs": "尺寸:125%", "xloc": [ - "default.handlebars->25->681" + "default.handlebars->27->730" ] }, { @@ -16238,10 +22386,16 @@ "de": "Größe: 150%", "en": "Size: 150%", "es": "Tamaño: 150%", + "fr": "Taille : 150%", + "hi": "आकार: 150%", + "ja": "サイズ:150%", + "ko": "크기 : 150 %", "nl": "Grootte: 150%", + "pt": "Tamanho: 150%", "ru": "Размер: 150%", + "zh-chs": "尺寸:150%", "xloc": [ - "default.handlebars->25->682" + "default.handlebars->27->731" ] }, { @@ -16249,10 +22403,16 @@ "de": "Größe: 200%", "en": "Size: 200%", "es": "Tamaño: 200%", + "fr": "Taille : 200%", + "hi": "आकार: 200%", + "ja": "サイズ:200%", + "ko": "크기 : 200 %", "nl": "Grootte: 200%", + "pt": "Tamanho: 200%", "ru": "Размер: 200%", + "zh-chs": "尺寸:200%", "xloc": [ - "default.handlebars->25->683" + "default.handlebars->27->732" ] }, { @@ -16260,20 +22420,23 @@ "de": "Schlafen", "en": "Sleep", "es": "Dormir", - "fr": "Endormir", + "fr": "Mettre en veille", + "hi": "नींद", "ja": "睡眠", + "ko": "자다", "nl": "Slaapstand", "pt": "Hibernar", "ru": "Отправить в сон", + "zh-chs": "睡覺", "xloc": [ - "default-mobile.handlebars->9->101", - "default-mobile.handlebars->9->102", - "default-mobile.handlebars->9->103", - "default-mobile.handlebars->9->207", - "default.handlebars->25->2", - "default.handlebars->25->3", - "default.handlebars->25->4", - "default.handlebars->25->537" + "default-mobile.handlebars->9->105", + "default-mobile.handlebars->9->106", + "default-mobile.handlebars->9->107", + "default-mobile.handlebars->9->211", + "default.handlebars->27->2", + "default.handlebars->27->3", + "default.handlebars->27->4", + "default.handlebars->27->584" ] }, { @@ -16281,12 +22444,16 @@ "de": "Geräte schlafenlegen", "en": "Sleep devices", "es": "Dispositivos dormidos", + "fr": "Mettre en veille les appareils sélectionnés", + "hi": "नींद के उपकरण", "ja": "スリープデバイス", + "ko": "수면 장치", "nl": "Slaap apparaten", "pt": "Hibernar dispositivo", "ru": "Отправить в сон", + "zh-chs": "睡眠裝置", "xloc": [ - "default.handlebars->25->388" + "default.handlebars->27->378" ] }, { @@ -16295,15 +22462,18 @@ "en": "Sleeping", "es": "Durmiendo", "fr": "Dormir", + "hi": "सोया हुआ", "ja": "睡眠", + "ko": "슬리핑", "nl": "Slapen", "pt": "Hibernando", "ru": "В режиме сна", + "zh-chs": "睡眠", "xloc": [ - "default-mobile.handlebars->9->108", - "default-mobile.handlebars->9->109", - "default.handlebars->25->352", - "default.handlebars->25->354" + "default-mobile.handlebars->9->112", + "default-mobile.handlebars->9->113", + "default.handlebars->27->342", + "default.handlebars->27->344" ] }, { @@ -16311,12 +22481,15 @@ "de": "Slowakisch", "en": "Slovak", "fr": "Slovaque", + "hi": "स्लोवाक", "ja": "スロバキア", + "ko": "슬로바키아 사람", "nl": "Slowaaks", "pt": "Eslovaco", "ru": "Словацкий", + "zh-chs": "斯洛伐克文", "xloc": [ - "default.handlebars->25->869" + "default.handlebars->27->973" ] }, { @@ -16324,12 +22497,15 @@ "de": "Slowenisch", "en": "Slovenian", "fr": "Slovène", + "hi": "स्लोवेनियाई", "ja": "スロベニア語", + "ko": "슬로베니아", "nl": "Sloveens", "pt": "Esloveno", "ru": "Словенский", + "zh-chs": "斯洛文尼亞文", "xloc": [ - "default.handlebars->25->870" + "default.handlebars->27->974" ] }, { @@ -16338,10 +22514,13 @@ "en": "Slow", "es": "Lento", "fr": "Lent", + "hi": "धीरे", "ja": "スロー", + "ko": "느린", "nl": "Traag", "pt": "Lento", "ru": "Медленно", + "zh-chs": "慢", "xloc": [ "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->7->d7framelimiter->5", "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->7->d7framelimiter->5" @@ -16353,10 +22532,13 @@ "en": "Small", "es": "Pequeño", "fr": "Petit", + "hi": "छोटा", "ja": "小さい", + "ko": "작은", "nl": "Klein", "pt": "Pequeno", "ru": "Малый", + "zh-chs": "小", "xloc": [ "default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->9->devListToolbarSize->sizeselect->1", "default.handlebars->container->dialog->dialogBody->dialog4" @@ -16367,12 +22549,16 @@ "de": "Kleiner Fokus", "en": "Small Focus", "es": "Enfoque Pequeño", + "fr": "Petit focus", + "hi": "छोटा फोकस", "ja": "小焦点", + "ko": "작은 초점", "nl": "Kleine focus", "pt": "Foco pequeno", "ru": "Малая фокусировка", + "zh-chs": "小焦點", "xloc": [ - "default.handlebars->25->612" + "default.handlebars->27->660" ] }, { @@ -16380,12 +22566,16 @@ "de": "Agenten sanft trennen", "en": "Soft disconnect agent", "es": "Agente de desconexión suave", + "fr": "Déconnecter l'agent", + "hi": "नरम डिस्कनेक्ट एजेंट", "ja": "ソフト切断エージェント", + "ko": "소프트 분리 에이전트", "nl": "Softwarematig verbreken agent", "pt": "Agente de desconexão suave", "ru": "Програмное отключение агента", + "zh-chs": "軟斷開劑", "xloc": [ - "default.handlebars->25->705" + "default.handlebars->27->806" ] }, { @@ -16393,13 +22583,17 @@ "de": "Soft-Off", "en": "Soft-Off", "es": "Soft-Off", + "fr": "Arrêt progressif", + "hi": "शीतल-ऑफ", "ja": "ソフトオフ", + "ko": "소프트 오프", "nl": "softwarematig uit", "pt": "Soft-Off", "ru": "Soft-Off", + "zh-chs": "軟關", "xloc": [ - "default-mobile.handlebars->9->112", - "default.handlebars->25->360" + "default-mobile.handlebars->9->116", + "default.handlebars->27->350" ] }, { @@ -16408,36 +22602,47 @@ "en": "Software Agent Group", "es": "Grupo Agentes de Software", "fr": "Groupe d'agents logiciels", + "hi": "सॉफ्टवेयर एजेंट समूह", "ja": "ソフトウェアエージェントグループ", + "ko": "소프트웨어 에이전트 그룹", "nl": "Software Agent Groep", "pt": "Grupo de agentes de software", "ru": "Группа программных агентов", + "zh-chs": "軟件代理組", "xloc": [ - "default-mobile.handlebars->9->58" + "default-mobile.handlebars->9->61" ] }, { "cs": "Somani", "de": "Somani", "en": "Somani", + "fr": "Somani", + "hi": "सोमानी", "ja": "ソマニ", + "ko": "소 마니", "nl": "Somani", "pt": "Somani", "ru": "Сомани", + "zh-chs": "索馬尼", "xloc": [ - "default.handlebars->25->871" + "default.handlebars->27->975" ] }, { "cs": "lužická srbština", "de": "Sorbisch", "en": "Sorbian", + "fr": "Sorabe", + "hi": "सॉर्बियन", "ja": "ソルビアン", + "ko": "소르 비아 어", "nl": "Sorbisch", "pt": "Sorbian", "ru": "Сорбский", + "zh-chs": "索比亞人", "xloc": [ - "default.handlebars->25->872" + "default.handlebars->27->976" ] }, { @@ -16445,11 +22650,14 @@ "de": "Sortieren", "en": "Sort", "es": "Ordenar", - "fr": "Trier", + "fr": "Trier par ", + "hi": "तरह", "ja": "ソート", + "ko": "종류", "nl": "Sorteer", "pt": "Classificar", "ru": "Сортировка", + "zh-chs": "分類", "xloc": [ "default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->9->devListToolbarSort" ] @@ -16460,10 +22668,13 @@ "en": "Sort by date", "es": "Ordenar por fecha", "fr": "Trier par date", + "hi": "दिनांक के हिसाब से अलग करे", "ja": "日付けで並び替え", + "ko": "날짜순으로 정렬", "nl": "Sorteren op datum", "pt": "Classificar por data", "ru": "Сортировать по дате", + "zh-chs": "按日期排序", "xloc": [ "default-mobile.handlebars->container->page_content->column_l->p10->p10files->p13toolbar->1->4->1->1->1->0->3->p13sortdropdown->5", "default-mobile.handlebars->container->page_content->column_l->p5->p5myfiles->p5toolbar->1->2->1->1->1->0->3->p5sortdropdown->5", @@ -16477,10 +22688,13 @@ "en": "Sort by name", "es": "Ordenar por nombre", "fr": "Trier par nom", + "hi": "नाम द्वारा क्रमबद्ध करें", "ja": "名前順", + "ko": "이름으로 분류하다", "nl": "Sorteren op naam", "pt": "Classificar por nome", "ru": "Сортировать по имени", + "zh-chs": "按名稱分類", "xloc": [ "default-mobile.handlebars->container->page_content->column_l->p10->p10files->p13toolbar->1->4->1->1->1->0->3->p13sortdropdown->1", "default-mobile.handlebars->container->page_content->column_l->p5->p5myfiles->p5toolbar->1->2->1->1->1->0->3->p5sortdropdown->1", @@ -16496,10 +22710,13 @@ "en": "Sort by process id", "es": "Ordenar por id de proceso", "fr": "Trier par identifiant de processus", + "hi": "प्रक्रिया आईडी के आधार पर छाँटें", "ja": "プロセスIDで並べ替え", + "ko": "프로세스 ID별로 정렬", "nl": "Sorteer op proces ID", "pt": "Classificar por ID do processo", "ru": "Сортировать по id процесса", + "zh-chs": "按進程ID排序", "xloc": [ "default.handlebars->container->column_l->p11->deskarea0->deskarea3x->DeskTools->deskToolsArea->DeskToolsProcessTab->deskToolsHeader" ] @@ -16510,10 +22727,13 @@ "en": "Sort by size", "es": "Ordenado por tamaño", "fr": "Trier par taille", + "hi": "आकारानुसार सजाओ", "ja": "サイズで並べ替え", + "ko": "크기별로 정렬", "nl": "Sorteren op grootte", "pt": "Classificar por tamanho", "ru": "Сортировать по размеру", + "zh-chs": "按大小排序", "xloc": [ "default-mobile.handlebars->container->page_content->column_l->p10->p10files->p13toolbar->1->4->1->1->1->0->3->p13sortdropdown->3", "default-mobile.handlebars->container->page_content->column_l->p5->p5myfiles->p5toolbar->1->2->1->1->1->0->3->p5sortdropdown->3", @@ -16527,10 +22747,13 @@ "en": "Sort by state", "es": "Ordenar por estado", "fr": "Trier par état", + "hi": "राज्य के आधार पर छाँटें", "ja": "状態で並べ替え", + "ko": "상태별로 정렬", "nl": "Sorteer op status", "pt": "Classificar por estado", "ru": "Сортировать по состоянию", + "zh-chs": "按州排序", "xloc": [ "default.handlebars->container->column_l->p11->deskarea0->deskarea3x->DeskTools->deskToolsArea->DeskToolsServiceTab->deskToolsServiceHeader" ] @@ -16541,132 +22764,175 @@ "en": "Spanish", "es": "Español", "fr": "Espagnol", + "hi": "स्पेनिश", "ja": "スペイン語", + "ko": "스페인의", "nl": "Spaans", "pt": "Espanhol", "ru": "Испанский", + "zh-chs": "西班牙文", "xloc": [ - "default.handlebars->25->873" + "default.handlebars->27->977" ] }, { "cs": "španělština (Argentina)", "de": "Spanisch (Argentinien)", "en": "Spanish (Argentina)", + "fr": "Espagnol (Argentine)", + "hi": "स्पेनिश (अर्जेंटीना)", "ja": "スペイン語(アルゼンチン)", + "ko": "스페인어 (아르헨티나)", "nl": "Spaans (Argentinië)", "pt": "Espanhol (Argentina)", "ru": "Испанский (Аргентина)", + "zh-chs": "西班牙文(阿根廷)", "xloc": [ - "default.handlebars->25->874" + "default.handlebars->27->978" ] }, { "cs": "španělština (Bolívie)", "de": "Spanisch (Bolivien)", "en": "Spanish (Bolivia)", + "fr": "Espagnol (Bolivie)", + "hi": "स्पेनिश (बोलीविया)", "ja": "スペイン語(ボリビア)", + "ko": "스페인어 (볼리비아)", "nl": "Spaans (Bolivia)", "pt": "Espanhol (Bolívia)", "ru": "Испанский (Боливия)", + "zh-chs": "西班牙語(玻利維亞)", "xloc": [ - "default.handlebars->25->875" + "default.handlebars->27->979" ] }, { "cs": "španělština (Chile)", "de": "Spanisch (Chile)", "en": "Spanish (Chile)", + "fr": "Espagnol (Chili)", + "hi": "स्पेनिश (चिली)", "ja": "スペイン語(チリ)", + "ko": "스페인어 (칠레)", "nl": "Spaans (Chili)", "pt": "Espanhol (Chile)", "ru": "Испанский (Чили)", + "zh-chs": "西班牙語(智利)", "xloc": [ - "default.handlebars->25->876" + "default.handlebars->27->980" ] }, { "cs": "španělština (Kolumbie)", "de": "Spanisch (Kolumbien)", "en": "Spanish (Colombia)", + "fr": "Espagnol (Colombie)", + "hi": "स्पेनिश (कोलंबिया)", "ja": "スペイン語(コロンビア)", + "ko": "스페인어 (콜롬비아)", "nl": "Spaans (Colombia)", "pt": "Espanhol (Colômbia)", "ru": "Испанский (Колумбия)", + "zh-chs": "西班牙語(哥倫比亞)", "xloc": [ - "default.handlebars->25->877" + "default.handlebars->27->981" ] }, { "cs": "španělština (Kostarika)", "de": "Spanisch (Costa Rica)", "en": "Spanish (Costa Rica)", + "fr": "Espagnol (Costa Rica)", + "hi": "स्पेनिश (कोस्टा रिका)", "ja": "スペイン語(コスタリカ)", + "ko": "스페인어 (코스타리카)", "nl": "Spaans (Costa Rica)", "pt": "Espanhol (Costa Rica)", "ru": "Испанский (Коста-Рика)", + "zh-chs": "西班牙語(哥斯達黎加)", "xloc": [ - "default.handlebars->25->878" + "default.handlebars->27->982" ] }, { "cs": "španělština (Dominikánská republika)", "de": "Spanisch (Dominikanische Republik)", "en": "Spanish (Dominican Republic)", + "fr": "Espagnol (République dominicaine)", + "hi": "स्पेनिश (डोमिनिकन गणराज्य)", "ja": "スペイン語(ドミニカ共和国)", + "ko": "스페인어 (도미니카 공화국)", "nl": "Spaans (Dominicaanse Republiek)", "pt": "Espanhol (República Dominicana)", "ru": "Испанский (Доминиканская Республика)", + "zh-chs": "西班牙語(多米尼加共和國)", "xloc": [ - "default.handlebars->25->879" + "default.handlebars->27->983" ] }, { "cs": "španělština (Ekvádor)", "de": "Spanisch (Ecuador)", "en": "Spanish (Ecuador)", + "fr": "Espagnol (Equateur)", + "hi": "स्पेनिश (इक्वाडोर)", "ja": "スペイン語(エクアドル)", + "ko": "스페인어 (에콰도르)", "nl": "Spaans (Ecuador)", "pt": "Espanhol (Equador)", "ru": "Испанский (Эквадор)", + "zh-chs": "西班牙語(厄瓜多爾)", "xloc": [ - "default.handlebars->25->880" + "default.handlebars->27->984" ] }, { "cs": "španělština (Salvador)", "de": "Spanisch (El Salvador)", "en": "Spanish (El Salvador)", + "fr": "Espagnol (Salvador)", + "hi": "स्पेनिश (एल साल्वाडोर)", "ja": "スペイン語(エルサルバドル)", + "ko": "스페인어 (엘살바도르)", "nl": "Spaans (El Salvador)", "pt": "Espanhol (El Salvador)", "ru": "Испанский (Сальвадор)", + "zh-chs": "西班牙語(薩爾瓦多)", "xloc": [ - "default.handlebars->25->881" + "default.handlebars->27->985" ] }, { "cs": "španělština (Guatemala)", "de": "Spanisch (Guatemala)", "en": "Spanish (Guatemala)", + "fr": "Espagnol (Guatemala)", + "hi": "स्पेनिश (ग्वाटेमाला)", "ja": "スペイン語(グアテマラ)", + "ko": "스페인어 (과테말라)", "nl": "Spaans (Guatemala)", "pt": "Espanhol (Guatemala)", "ru": "Испанский (Гватемала)", + "zh-chs": "西班牙語(危地馬拉)", "xloc": [ - "default.handlebars->25->882" + "default.handlebars->27->986" ] }, { "cs": "španělština (Honduras)", "de": "Spanisch (Honduras)", "en": "Spanish (Honduras)", + "fr": "Espagnol (Honduras)", + "hi": "स्पेनिश (होंडुरास)", "ja": "スペイン語(ホンジュラス)", + "ko": "스페인어 (온두라스)", "nl": "Spaans (Honduras)", "pt": "Espanhol (Honduras)", "ru": "Испанский (Гондурас)", + "zh-chs": "西班牙語(洪都拉斯)", "xloc": [ - "default.handlebars->25->883" + "default.handlebars->27->987" ] }, { @@ -16674,108 +22940,144 @@ "de": "Spanisch (Mexiko)", "en": "Spanish (Mexico)", "es": "Español (Mexico)", + "fr": "Espagnol (Mexique)", + "hi": "स्पेनिश (मेक्सिको)", "ja": "スペイン語(メキシコ)", + "ko": "스페인어 (멕시코)", "nl": "Spaans (Mexico)", "pt": "Espanhol (México)", "ru": "Испанский (Мексика)", + "zh-chs": "西班牙語(墨西哥)", "xloc": [ - "default.handlebars->25->884" + "default.handlebars->27->988" ] }, { "cs": "španělština (Nikaragua)", "de": "Spanisch (Nicaragua)", "en": "Spanish (Nicaragua)", + "fr": "Espagnol (Nicaragua)", + "hi": "स्पेनिश (निकारागुआ)", "ja": "スペイン語(ニカラグア)", + "ko": "스페인어 (니카라과)", "nl": "Spaans (Nicaragua)", "pt": "Espanhol (Nicarágua)", "ru": "Испанский (Никарагуа)", + "zh-chs": "西班牙語(尼加拉瓜)", "xloc": [ - "default.handlebars->25->885" + "default.handlebars->27->989" ] }, { "cs": "španělština (Panama)", "de": "Spanisch (Panama)", "en": "Spanish (Panama)", + "fr": "Espagnol (Panama)", + "hi": "स्पेनिश (पनामा)", "ja": "スペイン語(パナマ)", + "ko": "스페인어 (파나마)", "nl": "Spaans (Panama)", "pt": "Espanhol (Panamá)", "ru": "Испанский (Панама)", + "zh-chs": "西班牙語(巴拿馬)", "xloc": [ - "default.handlebars->25->886" + "default.handlebars->27->990" ] }, { "cs": "španělština (Paraguay)", "de": "Spanisch (Paraguay)", "en": "Spanish (Paraguay)", + "fr": "Espagnol (Paraguay)", + "hi": "स्पैनिश (पैराग्वे)", "ja": "スペイン語(パラグアイ)", + "ko": "스페인어 (파라과이)", "nl": "Spaans (Paraguay)", "pt": "Espanhol (Paraguai)", "ru": "Испанский (Парагвай)", + "zh-chs": "西班牙語(巴拉圭)", "xloc": [ - "default.handlebars->25->887" + "default.handlebars->27->991" ] }, { "cs": "španělština (Peru)", "de": "Spanisch (Peru)", "en": "Spanish (Peru)", + "fr": "Espagnol (Perou)", + "hi": "स्पेनिश (पेरू)", "ja": "スペイン語(ペルー)", + "ko": "스페인어 (페루)", "nl": "Spaans (Peru)", "pt": "Espanhol (Peru)", "ru": "Испанский (Перу)", + "zh-chs": "西班牙語(秘魯)", "xloc": [ - "default.handlebars->25->888" + "default.handlebars->27->992" ] }, { "cs": "španělština (Portoriko)", "de": "Spanisch (Puerto Rico)", "en": "Spanish (Puerto Rico)", + "fr": "Espagnol (Porto Rico)", + "hi": "स्पेनिश (प्यूर्टो रिको)", "ja": "スペイン語(プエルトリコ)", + "ko": "스페인어 (푸에르토 리코)", "nl": "Spaans (Puerto Rico)", "pt": "Espanhol (Porto Rico)", "ru": "Испанский (Пуэрто-Рико)", + "zh-chs": "西班牙語(波多黎各)", "xloc": [ - "default.handlebars->25->889" + "default.handlebars->27->993" ] }, { "cs": "španělština (Španělsko)", "de": "Spanisch (Spanien)", "en": "Spanish (Spain)", + "fr": "Espagnol (Espagne)", + "hi": "स्पेनिश (स्पेन)", "ja": "スペイン語(スペイン)", + "ko": "스페인어 (스페인)", "nl": "Spaans (Spanje)", "pt": "Espanhol (Espanha)", "ru": "Испанский (Испания)", + "zh-chs": "西班牙語(西班牙)", "xloc": [ - "default.handlebars->25->890" + "default.handlebars->27->994" ] }, { "cs": "španělština (Uruguay)", "de": "Spanisch (Uruguay)", "en": "Spanish (Uruguay)", + "fr": "Espagnol (Uruguay)", + "hi": "स्पेनिश (उरुग्वे)", "ja": "スペイン語(ウルグアイ)", + "ko": "스페인어 (우루과이)", "nl": "Spaans (Uruguay)", "pt": "Espanhol (Uruguai)", "ru": "Испанский (Уругвай)", + "zh-chs": "西班牙語(烏拉圭)", "xloc": [ - "default.handlebars->25->891" + "default.handlebars->27->995" ] }, { "cs": "španělština (Venezuela)", "de": "Spanisch (Venezuela)", "en": "Spanish (Venezuela)", + "fr": "Espagnol (Vénézuela)", + "hi": "स्पेनिश (वेनेजुएला)", "ja": "スペイン語(ベネズエラ)", + "ko": "스페인어 (베네수엘라)", "nl": "Spaans (Venezuela)", "pt": "Espanhol (Venezuela)", "ru": "Испанский (Венесуэла)", + "zh-chs": "西班牙語(委內瑞拉)", "xloc": [ - "default.handlebars->25->892" + "default.handlebars->27->996" ] }, { @@ -16783,12 +23085,16 @@ "de": "Spezielle Tasten", "en": "Special Keys", "es": "Teclas especiales", + "fr": "Touches spéciales", + "hi": "विशेष कुंजी", "ja": "特別なキー", + "ko": "특수 키", "nl": "Speciale toetsen", "pt": "Chaves especiais", "ru": "Специальные клавиши", + "zh-chs": "特殊鍵", "xloc": [ - "default-mobile.handlebars->9->230", + "default-mobile.handlebars->9->234", "default-mobile.handlebars->container->page_content->column_l->p10->p10desktop->deskarea4->1->3" ] }, @@ -16798,12 +23104,15 @@ "en": "Start", "es": "Inicio", "fr": "Lancé", + "hi": "शुरू", "ja": "開始", + "ko": "스타트", "nl": "Start", "pt": "Start", "ru": "Старт", + "zh-chs": "開始", "xloc": [ - "default.handlebars->25->629" + "default.handlebars->27->678" ] }, { @@ -16811,12 +23120,16 @@ "de": "Zustand", "en": "State", "es": "Estado", + "fr": "Etat", + "hi": "राज्य", "ja": "状態", + "ko": "상태", "nl": "Status", "pt": "Estado", "ru": "Состояние", + "zh-chs": "州", "xloc": [ - "default.handlebars->25->620", + "default.handlebars->27->669", "default.handlebars->container->column_l->p11->deskarea0->deskarea3x->DeskTools->deskToolsArea->DeskToolsServiceTab->deskToolsServiceHeader->1" ] }, @@ -16825,10 +23138,14 @@ "de": "Statistiken", "en": "Stats", "es": "Estadísticas", + "fr": "Statistiques", + "hi": "आँकड़े", "ja": "統計", + "ko": "통계", "nl": "Statistieken", "pt": "Estatísticas", "ru": "Статистика", + "zh-chs": "統計資料", "xloc": [ "default.handlebars->container->topbar->1->1->ServerSubMenuSpan->ServerSubMenu->1->0->ServerStats" ] @@ -16839,12 +23156,15 @@ "en": "Status", "es": "Estado", "fr": "Statut", + "hi": "स्थिति", "ja": "状態", + "ko": "상태", "nl": "Status", "pt": "Status", "ru": "Статус", + "zh-chs": "狀態", "xloc": [ - "default.handlebars->25->1357", + "default.handlebars->27->1493", "default.handlebars->container->column_l->p42->p42tbl->1->0->7" ] }, @@ -16854,12 +23174,28 @@ "en": "Stop", "es": "Detener", "fr": "Arrêtez", + "hi": "रुकें", "ja": "やめる", + "ko": "중지", "nl": "Stop", "pt": "Pare", "ru": "Стоп", + "zh-chs": "停止", "xloc": [ - "default.handlebars->25->630" + "default.handlebars->27->679" + ] + }, + { + "cs": "Zastavte proces", + "de": "Prozess stoppen", + "en": "Stop process", + "fr": "Arrêter le processus", + "ja": "プロセスを停止", + "nl": "Stop proces", + "ru": "Остановить процесс", + "zh-chs": "停止程序", + "xloc": [ + "default.handlebars->27->666" ] }, { @@ -16867,13 +23203,17 @@ "de": "Prozess #{0} \\\"{1}\\\" beenden?", "en": "Stop process #{0} \\\"{1}\\\"?", "es": "Detener proceso #{0} \\\"{1}\\\"?", + "fr": "Arrêter le processus #{0} \\\"{1}\\\"?", + "hi": "स्टॉप प्रोसेस # {0} \\\"{1} \\\"?", "ja": "プロセス#{0} \\\"{1}\\\"を停止しますか?", + "ko": "프로세스 # {0} \\\"{1} \\\"을 (를) 중지 하시겠습니까?", "nl": "Stop process #{0} \\\"{1}\\\"?", "pt": "Parar processo #{0} \\\"{1}\\\"?", "ru": "Прервать процесс #{0} \\\"{1}\\\"?", + "zh-chs": "停止進程#{0} \\“ {1} \\”?", "xloc": [ - "default-mobile.handlebars->9->235", - "default.handlebars->25->634" + "default-mobile.handlebars->9->239", + "default.handlebars->27->683" ] }, { @@ -16881,13 +23221,16 @@ "de": "Speicher überschritten", "en": "Storage exceed", "es": "El almacenamiento se excede", - "fr": "Stockage dépassent", + "fr": "Limite de stockage dépassée", + "hi": "भंडारण से अधिक है", "ja": "ストレージを超えています", + "ko": "저장 용량 초과", "nl": "Opslag overschrijden", "pt": "Armazenamento excedido", "ru": "Место для хранения превышено", + "zh-chs": "儲存空間超過", "xloc": [ - "default-mobile.handlebars->9->69" + "default-mobile.handlebars->9->72" ] }, { @@ -16895,12 +23238,16 @@ "de": "Speicher-Begrenzung überschritten", "en": "Storage limit exceed", "es": "El límite de almacenamiento se excede", + "fr": "Capacité de stockage dépassée", + "hi": "भंडारण सीमा से अधिक है", "ja": "ストレージ制限を超えています", + "ko": "저장 용량 한도 초과", "nl": "Opslaglimiet overschreden", "pt": "O limite de armazenamento excede", "ru": "Превышен лимит места для хранения", + "zh-chs": "儲存空間超過", "xloc": [ - "default.handlebars->25->1159" + "default.handlebars->27->1288" ] }, { @@ -16908,12 +23255,16 @@ "de": "Stark", "en": "Strong", "es": "Fuerte", + "fr": "Fort", + "hi": "मजबूत", "ja": "強い", + "ko": "강한", "nl": "Sterk", "pt": "Forte", "ru": "Надежный", + "zh-chs": "強大", "xloc": [ - "default.handlebars->25->963" + "default.handlebars->27->1068" ] }, { @@ -16922,15 +23273,34 @@ "en": "Strong Password", "es": "Contraseña segura", "fr": "Mot de passe fort", + "hi": "मजबूत पासवर्ड", "ja": "強力なパスワード", + "ko": "강력한 비밀번호", "nl": "Sterk wachtwoord", "pt": "Senha forte", "ru": "Надежный пароль", + "zh-chs": "強密碼", "xloc": [ - "login-mobile.handlebars->5->20", - "login-mobile.handlebars->5->24", - "login.handlebars->5->20", - "login.handlebars->5->24" + "login-mobile.handlebars->5->23", + "login-mobile.handlebars->5->27", + "login.handlebars->5->23", + "login.handlebars->5->27" + ] + }, + { + "cs": "Předložit", + "de": "einreichen", + "en": "Submit", + "fr": "Soumettre", + "hi": "प्रस्तुत", + "ja": "参加する", + "ko": "제출", + "nl": "Verzenden", + "pt": "Enviar", + "ru": "Отправить", + "zh-chs": "提交", + "xloc": [ + "invite.handlebars->container->column_l->5->1->0->3->3->3" ] }, { @@ -16939,12 +23309,15 @@ "en": "Success", "es": "Éxitoso", "fr": "Succès", + "hi": "सफलता", "ja": "成功", + "ko": "성공", "nl": "Geslaagd", "pt": "Sucesso", "ru": "Успешно", + "zh-chs": "成功", "xloc": [ - "default.handlebars->25->84" + "default.handlebars->27->66" ] }, { @@ -16952,8 +23325,14 @@ "de": "Zusammenfassung", "en": "Summary", "es": "Resumen", + "fr": "Résumé", + "hi": "सारांश", + "ja": "概要", + "ko": "요약", "nl": "Samenvatting", + "pt": "Sumário", "ru": "Резюме", + "zh-chs": "摘要", "xloc": [ "default.handlebars->container->topbar->1->1->MeshSubMenuSpan->MeshSubMenu->1->0->MeshSummary" ] @@ -16963,8 +23342,14 @@ "de": "Zusammenfassung -", "en": "Summary -", "es": "Resumen -", + "fr": "Résumé -", + "hi": "सारांश -", + "ja": "まとめ-", + "ko": "요약 -", "nl": "Samenvatting -", + "pt": "Resumo -", "ru": "Резюме -", + "zh-chs": "摘要-", "xloc": [ "default.handlebars->container->column_l->p21->p21title->3" ] @@ -16973,60 +23358,80 @@ "cs": "Sutu", "de": "Sutu", "en": "Sutu", + "fr": "Sutu", + "hi": "Su Tu", "ja": "ストゥ", + "ko": "수투", "nl": "Sutu", "pt": "Sutu", "ru": "Суту", + "zh-chs": "蘇圖", "xloc": [ - "default.handlebars->25->893" + "default.handlebars->27->997" ] }, { "cs": "svahilština", "de": "Suaheli", "en": "Swahili", + "fr": "Swahili", + "hi": "स्वाहिली", "ja": "スワヒリ語", + "ko": "스와힐리어", "nl": "Swahili", "pt": "Suaíli", "ru": "Суахили", + "zh-chs": "斯瓦希里語", "xloc": [ - "default.handlebars->25->894" + "default.handlebars->27->998" ] }, { "cs": "švédština", "de": "Schwedisch", "en": "Swedish", + "fr": "suédois", + "hi": "स्वीडिश", "ja": "スウェーデンの", + "ko": "스웨덴어", "nl": "Zweeds", "pt": "Sueco", "ru": "Шведский", + "zh-chs": "瑞典", "xloc": [ - "default.handlebars->25->895" + "default.handlebars->27->999" ] }, { "cs": "švédština (Finsko)", "de": "Schwedisch (Finnland)", "en": "Swedish (Finland)", + "fr": "Suédois (Finlande)", + "hi": "स्वीडिश (फिनलैंड)", "ja": "スウェーデン語(フィンランド)", + "ko": "스웨덴어 (핀란드)", "nl": "Zweeds (Finland)", "pt": "Sueco (Finlândia)", "ru": "Шведский (Финляндия)", + "zh-chs": "瑞典語(芬蘭)", "xloc": [ - "default.handlebars->25->896" + "default.handlebars->27->1000" ] }, { "cs": "švédština (Švédsko)", "de": "Schwedisch (Schweden)", "en": "Swedish (Sweden)", + "fr": "Suédois (Suède)", + "hi": "स्वीडिश (स्वीडन)", "ja": "スウェーデン語(スウェーデン)", + "ko": "스웨덴어 (스웨덴)", "nl": "Zweeds (Zweden)", "pt": "Sueco (Suécia)", "ru": "Шведский (Швеция)", + "zh-chs": "瑞典文(瑞典)", "xloc": [ - "default.handlebars->25->897" + "default.handlebars->27->1001" ] }, { @@ -17034,20 +23439,31 @@ "de": "Server-Gerätename zu Hostname synchronisieren", "en": "Sync server device name to hostname", "es": "Sincronizar el nombre del dispositivo del servidor con el nombre del host", + "fr": "Synchroniser le nom de l'appareil avec son nom d'hôte", + "hi": "होस्टनाम के लिए सर्वर डिवाइस नाम सिंक करें", + "ja": "サーバーのデバイス名をホスト名に同期する", + "ko": "서버 장치 이름을 호스트 이름과 동기화", "nl": "Synchroniseer serverapparaatnaam met hostnaam", + "pt": "Sincronizar o nome do dispositivo do servidor com o nome do host", "ru": "Синхронизировать имя устройства на сервере с именем хоста", + "zh-chs": "將服務器設備名稱同步到主機名", "xloc": [ - "default.handlebars->25->1081" + "default.handlebars->27->1185" ] }, { "cs": "SOFTWARE JE POSKYTOVÁN „TAK JAK JE“, BEZ ZÁRUKY, VYJÁDŘENÉ NEBO IMPLIKOVANÉ, VČETNĚ NEJEDNÁVANÝCH ZÁRUK OBCHODOVATELNOSTI, VHODNOSTI PRO URČITÝ ÚČEL A NEZÁVISLOST. V ŽÁDNÉM PŘÍPADĚ NEPOSKYTUJÍ AUTOŘI NEBO DRŽITELÉ AUTORSKÝCH PRÁV ŽÁDNÉ ZÁRUKY, ZA POŠKOZENÍ NEBO OSTATNÍ ODPOVĚDNOST, PŘI ČINNOSTI SMLOUVY, TORTU NEBO JINÉ, VYPLÝVAJÍCÍ ZE SOFTWARU NEBO POUŽITÍ NEBO OSTATNÍCH OBCHODŮ SOFTWARE.", + "de": "DIE SOFTWARE WIRD \"WIE BESEHEN\" OHNE JEGLICHE AUSDRÜCKLICHE ODER STILLSCHWEIGENDE GEWÄHRLEISTUNG ZUR VERFÜGUNG GESTELLT, EINSCHLIESSLICH DER GEWÄHRLEISTUNG FÜR MARKTGÄNGIGKEIT, EIGNUNG FÜR EINEN BESTIMMTEN ZWECK UND NICHTVERLETZUNG. IN KEINEM FALL HAFTEN DIE AUTOREN ODER COPYRIGHT-INHABER FÜR ANSPRÜCHE, SCHÄDEN ODER ANDERE HAFTUNGEN, OB VERTRAGS-, TORT- ODER ANDERWEITIGE MASSNAHMEN, DIE AUS, AUS ODER IM ZUSAMMENHANG MIT DER SOFTWARE ODER DER NUTZUNG ODER ANDEREN ANGEBOTE ENTSTEHEN SOFTWARE.", "en": "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.", "es": "EL SOFTWARE SE PROPORCIONA \"TAL CUAL\", SIN GARANTÍA DE NINGÚN TIPO, EXPRESA O IMPLÍCITA, INCLUYENDO PERO SIN LIMITARSE A LAS GARANTÍAS DE COMERCIABILIDAD, APTITUD PARA UN PROPÓSITO Y NO INFRACCIÓN PARTICULARES. EN NINGÚN CASO, LOS AUTORES O LOS TITULARES DE LOS DERECHOS DE AUTOR SERÁN RESPONSABLES DE NINGÚN RECLAMO, DAÑOS U OTRA RESPONSABILIDAD, YA SEA EN ACCIÓN DE CONTRATO, TORT O DE OTRA MANERA, DERIVADA DE, FUERA DE, O EN RELACIÓN CON EL SOFTWARE O EL USO O OTRO TRATO EN EL SOFTWARE.", + "fr": "LE LOGICIEL EST FOURNI «TEL QUEL», SANS GARANTIE D'AUCUNE SORTE, EXPRESSE OU IMPLICITE, Y COMPRIS MAIS SANS S'Y LIMITER LES GARANTIES DE QUALITÉ MARCHANDE, D'ADÉQUATION À UN USAGE PARTICULIER ET DE NON-CONTREFAÇON. EN AUCUN CAS, LES AUTEURS OU LES DÉTENTEURS DE DROITS D'AUTEUR NE SERONT RESPONSABLES DE TOUTE RÉCLAMATION, DOMMAGE OU AUTRE RESPONSABILITÉ, QUE CE SOIT DANS UNE ACTION CONTRACTUELLE, TORTURE OU AUTRE, DÉCOULANT DU LOGICIEL OU DE L'UTILISATION OU D'AUTRES OPÉRATIONS DANS LE LOGICIEL.", + "hi": "सॉफ़्टवेयर किसी भी प्रकार, किसी भी तरह की वारंटी के बिना \"IS\" के रूप में प्रदान किया जाता है, जो कि मर्चेंटैबिलिटी के वेरिएंट के लिए सीमित नहीं है, एक आंशिक गरीब और गैर सरकारी संगठन के लिए उपयुक्त है। किसी भी सूची में दिए गए ऑटो या कॉपीराइटर किसी भी क्लैम, डैमेज या अन्य लायबिलिटी के लिए उत्तरदायी नहीं होंगे, जो अनुबंध, टिकट या अन्य वॉइस, किसी भी तरह के एक्शन में हैं, जो सॉफ्टवेयर के उपयोग से संबंधित हैं या उपयोग नहीं कर रहे हैं। सॉफ्टवेयर।", "ja": "本ソフトウェアは、商品性、特定の目的への適合性、および非侵害の保証を含むが、これに限らず、明示または黙示を問わず、いかなる保証もなしに「現状のまま」提供されます。いかなる場合でも、作者または著作権者は、契約、不法行為、またはその他の行為、ソフトウェアまたは使用またはその他の取引に起因する、または関連するいかなる請求、損害またはその他の責任についても責任を負わないものとしますソフトウェア。", + "ko": "본 소프트웨어는 상품성, 특정 목적에의 적합성 및 비 침해에 대한 보증을 포함하되 명시 적이든 묵시적이든 어떠한 종류의 보증없이 \"있는 그대로\"제공됩니다. 어떠한 경우에도 저자 또는 저작권 소유자는 계약, 불법 행위 또는 기타 행위, 소프트웨어 또는 소프트웨어의 사용 또는 기타 거래와 관련하여 발생하는 모든 청구, 손해 또는 기타 책임에 대해 책임을지지 않습니다. 소프트웨어.", "nl": "DE SOFTWARE WORDT \"ALS ZODANIG\" GELEVERD, ZONDER ENIGE VORM VAN GARANTIE, UITDRUKKELIJK OF IMPLICIET, INCLUSIEF MAAR NIET BEPERKT TOT DE GARANTIES VAN VERKOOPBAARHEID, GESCHIKTHEID VOOR EEN BEPAALD DOEL EN NIET-INBREUK. IN GEEN GEVAL ZULLEN DE AUTEURS OF AUTEURSRECHTHOUDERS AANSPRAKELIJK ZIJN VOOR ENIGE CLAIM, SCHADE OF ANDERE AANSPRAKELIJKHEID, OOK IN EEN HANDELING VAN CONTRACT, SCHORT OF ANDERSZINS DIE VOORTVLOEIEN UIT, IN OF IN VERBAND MET DE SOFTWARE OF HET GEBRUIK OF ANDERE HANDELINGEN IN DE SOFTWARE.", "pt": "O SOFTWARE É FORNECIDO \"TAL COMO ESTÁ\", SEM GARANTIA DE QUALQUER TIPO, EXPRESSA OU IMPLÍCITA, INCLUINDO MAS NÃO SE LIMITANDO A GARANTIAS DE COMERCIALIZAÇÃO, ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA E NÃO INFRACÇÃO. EM NENHUM CASO OS AUTORES OU TITULARES DE DIREITOS AUTORAIS RESPONSABILIZARÃO POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE, SEJA EM AÇÃO DE CONTRATO, TORT OU OUTRA FORMA, DECORRENTE DE, FORA OU EM CONEXÃO COM O SOFTWARE OU O USO OU OUTROS NEGÓCIOS NO PROGRAMAS.", "ru": "ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ ПРЕДОСТАВЛЯЕТСЯ \"КАК ЕСТЬ\", БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ, ЯВНЫХ ИЛИ ПОДРАЗУМЕВАЕМЫХ, ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ ГАРАНТИЕЙ ТОВАРНОГО ОБЕСПЕЧЕНИЯ, ПРИГОДНОСТИ ДЛЯ ОСОБЫХ ЦЕЛЕЙ И НЕЗАКРЕПЛЕНИЙ. НИ ПРИ КАКИХ ОБСТОЯТЕЛЬСТВАХ АВТОРЫ ИЛИ СОБСТВЕННИКИ АВТОРСКИХ ПРАВ НЕ НЕСУТ ОТВЕТСТВЕННОСТИ ЗА ЛЮБЫЕ ПРЕТЕНЗИИ, УЩЕРБ ИЛИ ДРУГУЮ ОТВЕТСТВЕННОСТЬ, ВОЗНИКАЮЩЕЙ В РЕЗУЛЬТАТЕ ДЕЙСТВИЯ КОНТРАКТА, ДЕЛИКТНОГО ИЛИ ИНОГО ДЕЙСТВИЯ, ВОЗНИКАЮЩЕЕ В РЕЗУЛЬТАТЕ, В РЕЗУЛЬТАТЕ ИЛИ В СВЯЗИ С ПРОГРАММНЫМ ОБЕСПЕЧЕНИЕМ ИЛИ ИСПОЛЬЗОВАНИЕМ В ДРУГИХ ОТНОШЕНИЯХ ПРОГРАМНОГО ОБЕСПЕЧЕНИЯ.", + "zh-chs": "本軟件按“原樣”提供,不提供任何形式的明示或暗示的保證,包括但不限於對適銷性,特定目的的適用性和非侵權性的保證。無論是由於軟件,使用或其他方式產生的,與之有關或與之有關的合同,侵權或其他形式的任何索賠,損害或其他責任,作者或版權所有者概不負責。軟件。", "xloc": [ "terms-mobile.handlebars->container->page_content->column_l->49->1", "terms-mobile.handlebars->container->page_content->column_l->57->1", @@ -17059,12 +23475,17 @@ }, { "cs": "TENTO SOFTWARE POSKYTUJÍ DRŽITELÉ AUTORSKÝCH PRÁV A DODAVATELÉ \"TAK JAK JE\" A JAKÉKOLI VÝSLOVNÉ NEBO IMPLIKOVANÉ ZÁRUKY, VČETNĚ IMPLIKOVANÝCH ZÁRUK OBCHODOVATELNOSTI A VHODNOSTI PRO KONKRÉTNÍ ÚČEL, VČETNĚ, NEJMÉ OMEZENÉHO, NENÍ OMEZENO. V ŽÁDNÉM PŘÍPADĚ NESMÍ BÝT ZODPOVĚDNÝ MAJITEL AUTORSKÝCH PRÁV NEBO PŘIDĚLOVATELÉ ZA ŽÁDNÉ PŘÍMÉ, NEPŘÍMÉ, NÁHODNÉ, ZVLÁŠTNÍ, EXEMPLÁRNÍ NEBO NÁSLEDNÉ POŠKOZENÍ (VČETNĚ, ALE NEJEDNÁVĚJÍCÍCH, ZÍSKÁNÍ ZBOŽÍ NEBO SLUŽEB; ÚDAJE; NEBO PŘERUŠENÍ PODNIKŮ) JAK VYDĚLÁVALA A NA JAKÉKOLIV TEORII ODPOVĚDNOSTI, POKUD JDE O SMLOUVU, STRUČNOU ODPOVĚDNOST NEBO TORT (VČETNĚ NEGLIGENCE NEBO JINÉHO) VYPLÝVAJÍCÍ Z KAŽDÉHO ZPŮSOBU POUŽÍVÁNÍ TENTOHO SOFTWARU, AJ KDYKOLI PORUŠENÍ.", + "de": "DIESE SOFTWARE WIRD VON DEN COPYRIGHT-INHABERN UND BEITRÄGERN \"WIE BESEHEN\" UND AUSDRÜCKLICHEN ODER STILLSCHWEIGENDEN GEWÄHRLEISTUNGEN ZUR VERFÜGUNG GESTELLT, EINSCHLIESSLICH DER STILLSCHWEIGENDEN GEWÄHRLEISTUNGEN FÜR MARKTGÄNGIGKEIT UND EIGNUNG FÜR EINEN BESTIMMTEN ZWECK. IN KEINEM FALL HAFTET DER COPYRIGHT-EIGENTÜMER ODER DIE BEITRÄGE FÜR DIREKTE, INDIREKTE, NEBEN-, SPEZIELLE, BEISPIELHAFTE ODER FOLGESCHÄDEN (EINSCHLIESSLICH, ABER NICHT BESCHRÄNKT AUF, BESCHAFFUNG VON ERSATZ- ODER DIENSTLEISTUNGEN; ODER UNTERBRECHUNG DES GESCHÄFTS) JEDOCH VERURSACHT UND AUF JEGLICHE HAFTUNGSTHEORIE, OB VERTRAG, STRENGE HAFTUNG ODER HAFTUNG (EINSCHLIESSLICH NACHLÄSSIGKEIT ODER ANDERWEITIG), DIE AUS DER VERWENDUNG DIESER SOFTWARE ENTSTEHEN.", "en": "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.", "es": "ESTE SOFTWARE ES PROPORCIONADO POR LOS TITULARES DE LOS DERECHOS DE AUTOR Y LOS CONTRIBUYENTES \"TAL CUAL\" Y CUALQUIER GARANTÍA EXPRESA O IMPLÍCITA, INCLUYENDO, PERO SIN LIMITACIÓN, LAS GARANTÍAS IMPLÍCITAS DE COMERCIABILIDAD Y ADECUACIÓN PARA UNA VISUALIZACIÓN EN PARTICULAR. EN NINGÚN CASO EL PROPIETARIO DE DERECHOS DE AUTOR O LOS CONTRIBUIDORES SERÁN RESPONSABLES DE NINGÚN DAÑO DIRECTO, INDIRECTO, INCIDENTAL, ESPECIAL, EJEMPLAR O CONSECUENTE (INCLUYENDO, PERO SIN LIMITARSE A, LA ADQUISICIÓN DE BIENES O SERVICIOS SUSTITUTOS; PÉRDIDAS O USO; O INTERRUPCIÓN EMPRESARIAL) SIN EMBARGO CAUSADO Y EN CUALQUIER TEORÍA DE RESPONSABILIDAD, YA SEA POR CONTRATO, RESPONSABILIDAD ESTRICTA O TORT (INCLUYENDO NEGLIGENCIA O DE OTRA MANERA) QUE SURJA DE ALGUNA FORMA DEL USO DE ESTE SOFTWARE, INCLUSO SI SE RECONOCE LA POSIBILIDAD.", + "fr": "CE LOGICIEL EST FOURNI PAR LES DÉTENTEURS DE DROITS D'AUTEUR ET LES CONTRIBUTEURS \"EN L'ÉTAT\" ET TOUTE GARANTIE EXPRESSE OU IMPLICITE, Y COMPRIS, MAIS SANS S'Y LIMITER, LES GARANTIES IMPLICITES DE QUALITÉ MARCHANDE ET D'ADÉQUATION À UN USAGE PARTICULIER SONT EXCLUES. EN AUCUN CAS, LE PROPRIÉTAIRE OU LES CONTRIBUTEURS DE DROITS D'AUTEUR NE SERONT RESPONSABLES DES DOMMAGES DIRECTS, INDIRECTS, ACCESSOIRES, SPÉCIAUX, EXEMPLAIRES OU CONSÉCUTIFS (Y COMPRIS, MAIS SANS S'Y LIMITER, L'APPROVISIONNEMENT DE BIENS OU SERVICES DE SUBSTITUTION; PERTE D'UTILISATION, DE DONNÉES OU DE PROFITS; OU INTERRUPTION D'AFFAIRES) TOUTEFOIS CAUSÉE ET SUR TOUTE THÉORIE DE LA RESPONSABILITÉ, QUE CE SOIT DANS LE CONTRAT, LA RESPONSABILITÉ STRICTE OU LE TORT (Y COMPRIS LA NÉGLIGENCE OU AUTREMENT) DÉCOULANT DE TOUTE MANIÈRE D'UTILISER CE LOGICIEL, MÊME SI IL EST AVISÉ DE LA POSSIBILITÉ DE TELS DOMMAGES.", + "hi": "इस सॉफ़्टवेयर को COPYRIGHT के धारकों और ठेकेदारों द्वारा \"के रूप में\" और किसी भी अतिरिक्त वारंटी, जो कि शामिल नहीं हैं, के द्वारा प्रदान किया जाता है, जो कि किसी भी पार्टी के लिए इस पार्टी के चुनावों में शामिल होने के लिए नहीं आते हैं। किसी भी प्रत्यक्ष, संकेतक, विशेष, विशेष, विशेष, या आकस्मिक डैमेज (इनकॉलिंग, लेकिन सीमित नहीं हैं), के लिए किसी भी प्रत्यक्ष या माल या सेवाओं के संरक्षण के लिए किसी भी ईवेंट की दुकान पर कॉपियराइट ऑउटर या कॉन्ट्रिब्यूटर्स का उपयोग किया जा सकता है। या बिजनेस इंटेरप्शन) किसी भी तरह का हो गया है और किसी भी थ्योरी पर आधारित है, जो अनुबंध में है, स्ट्रैटजी लाइबिलिटी, या टाइप (किसी अन्य सॉफ्टवेयर के आधार पर) सॉफ्टवेयर के उपयोग से संबंधित सॉफ्टवेयर के उपयोग के लिए किसी भी प्रकार का उपयोग कर रहा है।", "ja": "このソフトウェアは、著作権者および寄稿者によって「現状のまま」提供され、商品性および特定の目的への適合性の黙示的な保証を含むがこれに限定されない明示的または黙示的な保証は放棄されます。いかなる場合においても、著作権所有者または貢献者は、直接的、間接的、偶発的、特別、例示的、または結果的な損害(代替品またはサービスの調達、代替品、データ、または利益の損失を含むが、これらに限定されない)について責任を負わないものとしますまたはビジネス中断)責任の理論、または契約、厳格な責任、または不法行為(過失またはその他を含む)にかかわらず、このソフトウェアの使用から生じたものであっても、POSSIの可能性がある場合でも。", + "ko": "이 소프트웨어는 저작권 소유자 및 배포자에 의해 \"있는 그대로\"제공되며, 명시 적 또는 묵시적 보증을 포함하되 이에 국한되지는 않지만 상품성 및 특정 목적에의 적합성에 대한 묵시적 보증은 이에 제한되지 않습니다. 어떠한 경우에도 저작권 소유자 나 제공자는 직접적, 간접적, 우발적, 특수 적, 간접적 또는 결과적 손해 (대체 상품 또는 서비스의 제조, 데이터 사용 손실, 손실, 이에 국한되지 않음)에 대해 책임을지지 않습니다. 또는 사업 중단) 계약, 엄격 책임 또는 불법 행위 (어떠한 과실 또는 기타 포함)에 관계없이 본 소프트웨어를 사용하지 않더라도 본 소프트웨어의 사용으로 인해 발생하는 경우에도 책임의 이론에 의해 발생합니다.", "nl": "DEZE SOFTWARE WORDT GELEVERD DOOR DE AUTEURSRECHTHOUDERS EN BIJDRAGERS \"ALS ZODANIG\" EN ENIGE EXPLICIETE OF IMPLICIETE GARANTIES, INCLUSIEF, MAAR NIET BEPERKT TOT, DE IMPLICIETE GARANTIES VAN VERKOOPBAARHEID EN GESCHIKTHEID VOOR EEN BEPAALD DOEL. IN GEEN GEVAL ZULLEN DE EIGENAAR VAN HET AUTEURSRECHT OF DE BIJDRAGERS AANSPRAKELIJK ZIJN VOOR ENIGE DIRECTE, INDIRECTE, INCIDENTELE, SPECIALE, UITZONDERLIJKE OF GEVOLGSCHADE (INCLUSIEF, MAAR NIET BEPERKT TOT, AANSCHAF VAN VERVANGENDE GOEDEREN OF DIENSTEN; VERLIES VAN GEBRUIK, GEGEVENS OF GEGEVENS; OF ONDERBREKING VAN HET BEDRIJF) EVENWEL VEROORZAAKT EN OP ENIGE AANSPRAAK VAN AANSPRAKELIJKHEID, OF IN CONTRACT, STRIKTE AANSPRAKELIJKHEID OF STORT (INCLUSIEF NALATIGHEID OF ANDERSZINS) DIE VOORTVLOEIT OP ENIGE MANIER UIT HET GEBRUIK VAN DEZE SOFTWARE, ZELFS ALS GEADVISEERD VAN DE MOGELIJKHEID.", "pt": "ESTE SOFTWARE É FORNECIDO PELOS TITULARES DE DIREITOS AUTORAIS E CONTRIBUIDORES \"TAL COMO ESTÁ\" E QUALQUER GARANTIA EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO A, AS GARANTIAS IMPLÍCITAS DE COMERCIALIZAÇÃO E ADEQUAÇÃO A UM PROPÓSITO ESPECÍFICO. EM NENHUM CASO O DIVISOR DE DIREITOS AUTORAIS OU OS CONTRIBUIDORES SERÃO RESPONSÁVEIS POR QUALQUER DANO DIRETO, INDIRETO, INCIDENTAL, ESPECIAL, EXEMPLAR OU CONSEQÜENCIAL (INCLUINDO, MAS NÃO SE LIMITANDO A, PROCURAÇÃO DE BENS OU SERVIÇOS SUBSTITUTOS; PERDA DE USO, DADOS, LUCROS DE USO); OU INTERRUPÇÃO DE NEGÓCIOS), CAUSADA E QUALQUER TEORIA DE RESPONSABILIDADE, CONTRATADA, RESPONSABILIDADE ESTIMATIVA OU ATRIBUIÇÃO (INCLUINDO NEGLIGÊNCIA OU DE OUTRA FORMA), surgindo de qualquer maneira fora do uso deste software, mesmo que seja aconselhável a possibilidade de tal conteúdo.", "ru": "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.", + "zh-chs": "版權持有者和貢獻者按“原樣”提供此軟件,不提供任何明示或暗示的擔保,包括但不限於針對特定目的的適銷性和適用性的暗示擔保。版權擁有者或貢獻者在任何情況下均不對任何直接,間接,偶發,特殊,專有或後果性的損害(包括但不限於,替代商品或服務的購買,使用,數據,或業務中斷),無論基於合同,嚴格責任或侵權行為(包括疏忽或其他方式),無論是否出於任何責任,都應通過使用本軟件的任何方式(即使已事先告知)進行了賠償。", "xloc": [ "terms-mobile.handlebars->container->page_content->column_l->21->1", "terms.handlebars->container->column_l->21->1" @@ -17072,12 +23493,17 @@ }, { "cs": "TENTO SOFTWARE JE POSKYTOVÁN PROJEKTEM OpenSSL „TAK JAK JE“, BEZ JAKÝCHKOLI ZÁRUK, VYJÁDŘENÝCH NEBO IMPLIKOVANÝCH, VČETNĚ (ALE NEJEN) ZÁRUK OBCHODOVATELNOSTI, VHODNOSTI PRO URČITÝ ÚČEL. OpenSSL NEBO PŘISPĚVATELÉ DO NĚJ V ŽÁDNÉM PŘÍPADĚ NEJSOU ODPOVĚDNÍ ZA ŽÁDNÉ PŘÍMÉ, NEPŘÍMÉ, NÁHODNÉ, KONKRÉTNÍ, EXEMPLÁRNÍ NEBO VYPLÝVAJÍCÍ ŠKODY (VČETNĚ, ALE ALE NIKOLI POUZE PROCUREMENT NÁHRADNÍHO ZBOŽÍ NEBO SLUŽEB; ZTRÁTY POUŽITÍ, DAT NEBO ZISKŮ; NEBO PŘERUŠENÍ PODNIKÁNI) NICMÉNĚ ZPŮSOBENÉ A ANI ZA JAKOUKOLI TEORII ODPOVĚDNOSTI AUTOŘI NEBO DRŽITELÉ AUTORSKÝCH PRÁV NEDRŽÍ ŽÁDNÉ ZÁRUKY, AŤ UŽ VE SMLOUVĚ, STRIKTNÍ ODPOVĚDNOSTI, NEBO PŘEČINU (VČETNĚ NEDBALOSTI ČI JINAK), MAJÍCÍ PŘÍČINU V POUŽITÍ TOHOTO SOFTWARE, A TO ANI I KDYBY NA MOŽNOST TAKOVÉ ŠKODY BYLI UPOZORNĚNI.", + "de": "DIESE SOFTWARE WIRD VOM OpenSSL-PROJEKT \"WIE BESEHEN\" ZUR VERFÜGUNG GESTELLT, UND JEGLICHE AUSDRÜCKLICHE ODER STILLSCHWEIGENDE GEWÄHRLEISTUNGEN, EINSCHLIESSLICH DER STILLSCHWEIGENDEN GEWÄHRLEISTUNGEN FÜR MARKTGÄNGIGKEIT UND EIGNUNG FÜR EINEN BESTIMMTEN ZWECK. IN KEINEM FALL HAFTET DAS OpenSSL-PROJEKT ODER SEINE BEITRÄGE FÜR DIREKTE, INDIREKTE, NEBEN-, SONDER-, BEISPIEL- ODER FOLGESCHÄDEN (EINSCHLIESSLICH, ABER SONDER-, BEISPIEL- ODER FOLGESCHÄDEN) ODER DIENSTLEISTUNGEN, VERLUST DER NUTZUNG, DATEN ODER GEWINNE ODER UNTERBRECHUNG DES GESCHÄFTS) JEDOCH UND JEGLICHE HAFTUNGSTHEORIE, OB VERTRAGS-, STRENGE HAFTUNG ODER TORT (EINSCHLIESSLICH DER NACHLÄSSIGKEIT ODER ANDERWEITIG) SOFTWARE, AUCH WENN AUF DIE MÖGLICHKEIT DIESER SCHÄDEN hingewiesen wird.", "en": "THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.", "es": "ESTE SOFTWARE ES PROPORCIONADO POR EL PROYECTO OpenSSL `` TAL CUAL '' Y CUALQUIER GARANTÍA EXPRESA O IMPLÍCITA, INCLUYENDO, PERO SIN LIMITACIÓN, LAS GARANTÍAS IMPLÍCITAS DE COMERCIABILIDAD Y APTITUD PARA UN PROPÓSITO EN PARTICULAR. EN NINGÚN CASO EL PROYECTO O SUS COLABORADORES SERÁN RESPONSABLES POR DAÑOS DIRECTOS, INDIRECTOS, INCIDENTALES, ESPECIALES, EJEMPLARES O CONSECUENTES (INCLUIDOS, PERO ESPECIALES, EJEMPLARES O DAÑOS CONSECUENTES (INCLUIDOS, PRO PERO NO LIMITADOS O SERVICIOS; PÉRDIDA DE USO, DATOS O BENEFICIOS; O INTERRUPCIÓN COMERCIAL) SIN EMBARGO Y EN CUALQUIER TEORÍA DE RESPONSABILIDAD, YA SEA EN CONTRATO, RESPONSABILIDAD ESTRICTA O TORT (INCLUYENDO NEGLIGENCIA O DE OTRA MANERA) QUE SURJA DE ALGUNA FORMA SOFTWARE, INCLUSO SI SE AVISA SOBRE LA POSIBILIDAD DE TALES DAÑOS.", + "fr": "CE LOGICIEL EST FOURNI PAR LE PROJET OpenSSL `` TEL QUEL '' ET TOUTE GARANTIE EXPRESSE OU IMPLICITE, Y COMPRIS, MAIS SANS S'Y LIMITER, LES GARANTIES IMPLICITES DE QUALITÉ MARCHANDE ET D'ADÉQUATION À UN USAGE PARTICULIER SONT DÉCLINÉES. LE PROJET OpenSSL OU SES CONTRIBUTEURS NE SERONT EN AUCUN CAS RESPONSABLES DE TOUT DOMMAGE DIRECT, INDIRECT, ACCIDENTEL, SPÉCIAL, EXEMPLAIRE OU CONSÉCUTIF (INCLUANT, MAIS SPÉCIAL, EXEMPLAIRE OU CONSÉCUTIF (INCLUANT, MAIS SANS S'Y LIMITER, L'APPROVISIONNEMENT DE BIENS DE SUBSTITUTION) OU SERVICES; PERTE D'UTILISATION, DE DONNÉES OU DE PROFITS; OU INTERRUPTION D'ENTREPRISE) TOUTEFOIS CAUSÉE ET SUR TOUTE THÉORIE DE RESPONSABILITÉ, QUE CE SOIT DANS LE CONTRAT, LA RESPONSABILITÉ STRICTE OU LE TORT (Y COMPRIS LA NÉGLIGENCE OU AUTREMENT) DÉCOULANT DE TOUTE MANIÈRE QUANT À L'UTILISATION DE CELLE-CI LOGICIEL, MÊME S'IL EST AVISÉ DE LA POSSIBILITÉ DE TELS DOMMAGES.", + "hi": "यह सॉफ़्टवेयर ओपनएसएसएल द्वारा प्रदान किया गया है `` जैसा है '' और किसी भी तरह से लागू या लागू किया गया, जिसमें कोई भी भाग नहीं है, मर्चेंटैबिलिटी के आवश्यक वारंटी और एक आंशिक पेंशन के लिए निर्धारित है। किसी भी प्रत्यक्ष, प्रत्यक्ष, विशेष, विशेष, या व्यावसायिक क्षेत्रों (अंतर्ग्रहण, बाउट विशेष, उत्कृष्ट, या शैक्षणिक मामलों) के लिए किसी भी सूची (इंसुलेट) में ओपनएसएसएल प्रोजक्ट या आई.टी. या सेवाएं, उपयोग, डेटा, या लाभ का नुकसान; या व्यापार का अंतर) किसी भी तरह से सीमित है और लेन-देन के सिद्धांत पर, अनुबंध में जो भी है, मजबूत देयता, या टिकट या दूसरे के आधार पर भुगतान कर सकते हैं, जो किसी अन्य व्यक्ति के पास हैं। सॉफ़्टवेयर, यदि एसयूसी डैमेज की स्थिति का पता लगाया गया हो।", "ja": "このソフトウェアは、OpenSSLプロジェクトによって「現状のまま」提供され、商品性および特定の目的への適合性の黙示的な保証を含むがこれに限定されない、明示的または黙示的な保証は放棄されます。いかなる場合も、OpenSSLプロジェクトまたはその貢献者は、直接的、間接的、偶発的、特別、例示的、または結果的損害(責任を含むが、特別損害、例示的損害、または結果的損害を含む)の責任を負いませんまたはサービス、使用、データ、または利益の損失、またはビジネス中断)、契約、厳格な責任、または不法行為(過失またはその他を含む)このような損害の可能性について通知された場合でも、ソフトウェア。", + "ko": "이 소프트웨어는``있는 그대로 ''OpenSSL 프로젝트에 의해 제공되며 상품성 및 특정 목적에의 적합성에 대한 묵시적 보증을 포함하되 이에 국한되지 않는 명시 적 또는 묵시적 보증을 제공합니다. 어떠한 경우에도 OpenSSL 프로젝트 또는 그 제공자는 직접적, 간접적, 우발적, 특별, 간접적 또는 결과적 손해에 대해 책임을지지 않습니다. 또는 서비스, 사용, 데이터 또는 이익의 상실 또는 비즈니스 중단) 계약, 엄격한 책임, 또는 이의 사용으로 인해 발생하는 모든 과실 또는 기타를 포함하여 책임의 이론에 의해 발생하는 모든 책임 이론 이러한 손상 가능성에 대해 조언 한 경우에도 소프트웨어.", "nl": "DEZE SOFTWARE WORDT GELEVERD DOOR HET OpenSSL-PROJECT `` ZOALS HET IS '' EN ELKE UITDRUKKELIJKE OF IMPLICIETE GARANTIES, INCLUSIEF MAAR NIET BEPERKT TOT DE IMPLICIETE GARANTIES VAN VERKOOPBAARHEID EN GESCHIKTHEID VOOR EEN BEPAALD DOEL WORDEN AFGEWEZEN. IN GEEN GEVAL ZAL HET PROJECT VAN DE OpenSSL OF HAAR BIJDRAGERS AANSPRAKELIJK ZIJN VOOR ENIGE DIRECTE, INDIRECTE, INCIDENTELE, SPECIALE, UITZONDERLIJKE OF GEVOLGSCHADE (INCLUSIEF, MAAR SPECIALE, UITZONDERLIJKE OF GEVOLGSCHADE (INCLUSIEF, MAAR NIET BEPERKT TOT SCHULDEN) OF DIENSTEN; VERLIES VAN GEBRUIK, GEGEVENS OF WINST; OF ONDERBREKING VAN HET BEDRIJF) EVENWEL OORZAAKT EN OP ENIGE AANSPRAAK VAN AANSPRAKELIJKHEID, OF IN CONTRACT, STRIKTE AANSPRAKELIJKHEID, OF TORT (INCLUSIEF NALATIGHEID OF ANDERSZINS) DIE OP ENIGE MANIER UIT DE GEBRUIKSVOORWAARDEN ONTSTAAN SOFTWARE, ZELFS INDIEN GEADVISEERD DOOR DE MOGELIJKHEID VAN DERGELIJKE SCHADE.", "pt": "ESTE SOFTWARE É FORNECIDO PELO PROJETO OpenSSL `` COMO ESTÁ '' E QUALQUER GARANTIA EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO A, AS GARANTIAS IMPLÍCITAS DE COMERCIALIZAÇÃO E ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA. EM NENHUM CASO O PROJETO OpenSSL OU SEUS CONTRIBUIDORES SERÃO RESPONSÁVEIS POR QUALQUER DANO DIRETO, INDIRETO, INCIDENTAL, ESPECIAL, EXEMPLAR OU CONSEQÜENCIAL (INCLUINDO DANOS ESPECIAIS, EXEMPLARES OU CONSEQÜENCIAIS (INCLUINDO, PROCESSOS, MAS NÃO LIMITADOS OU SERVIÇOS; PERDA DE USO, DADOS OU LUCROS; OU INTERRUPÇÃO DE NEGÓCIOS), CAUSADOS E QUALQUER TEORIA DE RESPONSABILIDADE, CONTRATOS, RESPONSABILIDADE ESTIMATIVA OU ATORT (INCLUINDO NEGLIGÊNCIA OU DE OUTRA FORMA) QUE POSSUEM DE QUALQUER FORMA DESTE USO SOFTWARE, MESMO SE AVISADO DA POSSIBILIDADE DE TAIS DANOS.", "ru": "THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.", + "zh-chs": "此軟件由OpenSSL項目“按原樣”提供,不提供任何明示或暗示的擔保,包括但不限於對適銷性和特定用途的適用性的暗示擔保。在任何情況下,OpenSSL項目或其貢獻者均不對任何直接,間接,偶發,特殊,特殊或繼發性損害(包括,但特殊,示例性或繼發性損害)承擔任何責任(包括但不限於以下情況)或服務;使用,數據或利潤的損失;或業務中斷),無論是基於合同,嚴格責任還是侵權(包括疏忽或其他方式),無論是由於何種使用造成的軟件,即使已告知可能發生此類損壞。", "xloc": [ "terms-mobile.handlebars->container->page_content->column_l->43->1", "terms.handlebars->container->column_l->43->1" @@ -17089,13 +23515,32 @@ "en": "TLS", "es": "TLS", "fr": "TLS", + "hi": "टीएलएस", "ja": "TLS", + "ko": "TLS", "nl": "TLS", "pt": "TLS", "ru": "TLS", + "zh-chs": "TLS", "xloc": [ - "default-mobile.handlebars->9->183", - "default.handlebars->25->464" + "default-mobile.handlebars->9->187", + "default.handlebars->27->471" + ] + }, + { + "cs": "TLS není nastaven", + "de": "TLS ist nicht eingerichtet", + "en": "TLS is not setup", + "fr": "TLS n'est pas configuré", + "hi": "टीएलएस सेटअप नहीं है", + "ja": "TLSがセットアップされていません", + "ko": "TLS가 설정되지 않았습니다", + "nl": "TLS is niet ingesteld", + "pt": "TLS não está configurado", + "ru": "TLS не настроен", + "zh-chs": "未設置TLS", + "xloc": [ + "default.handlebars->27->773" ] }, { @@ -17104,14 +23549,17 @@ "en": "TLS security required", "es": "Seguridad TLS requerida", "fr": "Sécurité TLS requise", + "hi": "TLS सुरक्षा की आवश्यकता है", "ja": "TLSセキュリティが必要", + "ko": "TLS 보안 필요", "nl": "TLS beveiliging vereist", "pt": "Segurança TLS necessária", "ru": "Требуется безопасность TLS", + "zh-chs": "需要TLS安全", "xloc": [ - "default-mobile.handlebars->9->216", - "default.handlebars->25->246", - "default.handlebars->25->551" + "default-mobile.handlebars->9->220", + "default.handlebars->27->230", + "default.handlebars->27->598" ] }, { @@ -17119,24 +23567,33 @@ "de": "Tab", "en": "Tab", "es": "Tab", + "fr": "Tab", + "hi": "टैब", "ja": "タブ", + "ko": "탭", "nl": "Tab", "pt": "Tab", "ru": "Tab", + "zh-chs": "標籤", "xloc": [ "default-mobile.handlebars->dialog->3->dialog3->deskkeys->3" ] }, { "cs": "Štítek1, Štítek2, Štítek3", + "de": "Tag1, Tag2, Tag3", "en": "Tag1, Tag2, Tag3", "es": "Etiqueta1, Etiqueta2, Etiqueta3", + "fr": "Tag1, Tag2, Tag3", + "hi": "टैग 1, टैग 2, टैग 3", "ja": "Tag1、Tag2、Tag3", + "ko": "Tag1, Tag2, Tag3", "nl": "Tag1, Tag2, Tag3", "pt": "Tag1, Tag2, Tag3", "ru": "Тег1, Тег2, Тег3", + "zh-chs": "標籤1,標籤2,標籤3", "xloc": [ - "default.handlebars->25->603" + "default.handlebars->27->651" ] }, { @@ -17144,15 +23601,19 @@ "de": "Tags", "en": "Tags", "es": "Etiquetas", + "fr": "Mots clés", + "hi": "टैग", "ja": "タグ", + "ko": "태그", "nl": "Tags", "pt": "Tags", "ru": "Теги", + "zh-chs": "標籤", "xloc": [ - "default-mobile.handlebars->9->197", - "default-mobile.handlebars->9->198", - "default-mobile.handlebars->9->225", - "default.handlebars->25->602", + "default-mobile.handlebars->9->201", + "default-mobile.handlebars->9->202", + "default-mobile.handlebars->9->229", + "default.handlebars->27->650", "default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->9->devListToolbarSort->sortselect->7" ] }, @@ -17160,36 +23621,48 @@ "cs": "tamilština", "de": "Tamil", "en": "Tamil", + "fr": "Tamil", + "hi": "तामिल", "ja": "タミル語", + "ko": "타밀 사람", "nl": "Tamil", "pt": "Tâmil", "ru": "Тамильский", + "zh-chs": "泰米爾語", "xloc": [ - "default.handlebars->25->898" + "default.handlebars->27->1002" ] }, { "cs": "tatarština", "de": "Tatar", "en": "Tatar", + "fr": "tatar", + "hi": "टाटर", "ja": "タタール", + "ko": "타타르어", "nl": "Tartaar", "pt": "Tatar", "ru": "Татарский", + "zh-chs": "塔塔爾族", "xloc": [ - "default.handlebars->25->899" + "default.handlebars->27->1003" ] }, { "cs": "telugština", "de": "Teluga", "en": "Teluga", + "fr": "Teluga", + "hi": "Teluga", "ja": "テルガ", + "ko": "텔 루가", "nl": "Teluga", "pt": "Teluga", "ru": "Телугу", + "zh-chs": "泰盧加", "xloc": [ - "default.handlebars->25->900" + "default.handlebars->27->1004" ] }, { @@ -17198,13 +23671,16 @@ "en": "Terminal", "es": "Terminal", "fr": "Terminal", + "hi": "टर्मिनल", "ja": "ターミナル", + "ko": "단말기", "nl": "Terminal", "pt": "Terminal", "ru": "Терминал", + "zh-chs": "終奌站", "xloc": [ - "default.handlebars->25->1073", - "default.handlebars->25->420", + "default.handlebars->27->1177", + "default.handlebars->27->424", "default.handlebars->container->topbar->1->1->MainSubMenuSpan->MainSubMenu->1->0->MainDevTerminal", "default.handlebars->contextMenu->cxterminal" ] @@ -17215,10 +23691,13 @@ "en": "Terminal -", "es": "Terminal -", "fr": "Terminal -", + "hi": "टर्मिनल -", "ja": "ターミナル -", + "ko": "터미널-", "nl": "Terminal -", "pt": "Terminal -", "ru": "Терминал - ", + "zh-chs": "終奌站 -", "xloc": [ "default.handlebars->container->column_l->p12->p12title->5" ] @@ -17228,12 +23707,16 @@ "de": "Terminal-Benachrichtigung", "en": "Terminal Notify", "es": "Notificación de terminal", + "fr": "Notifier l'utilisation du terminal", + "hi": "टर्मिनल सूचित करें", "ja": "ターミナル通知", + "ko": "터미널 알림", "nl": "Terminal melding", "pt": "Notificação - terminal", "ru": "Терминал уведомление", + "zh-chs": "終端通知", "xloc": [ - "default.handlebars->25->995" + "default.handlebars->27->1100" ] }, { @@ -17241,12 +23724,16 @@ "de": "Terminal-Einverständnis", "en": "Terminal Prompt", "es": "Mensaje en Terminal", + "fr": "Confirmer l'utilisation du terminal", + "hi": "टर्मिनल प्रॉम्प्ट", "ja": "端末プロンプト", + "ko": "터미널 프롬프트", "nl": "Terminal Prompt", "pt": "Prompt do terminal", "ru": "Запрос терминала", + "zh-chs": "終端提示", "xloc": [ - "default.handlebars->25->994" + "default.handlebars->27->1099" ] }, { @@ -17254,15 +23741,19 @@ "de": "Nutzungsbedingungen & Datenschutz", "en": "Terms & Privacy", "es": "Términos y privacidad", + "fr": "CGU & Vie privée", + "hi": "शर्तें और गोपनीयता", "ja": "利用規約とプライバシー", + "ko": "이용 약관", "nl": "Voorwaarden & Privacy", "pt": "Termos & Privacidade", "ru": "Условия и конфиденциальность", + "zh-chs": "條款和隱私", "xloc": [ - "default.handlebars->container->footer->3->3", + "default.handlebars->container->footer->3->termsLinkFooter", "download.handlebars->container->page_content->footer->1->1->0->3->1", "login-mobile.handlebars->container->footer->1->1->0->3->1", - "login.handlebars->container->footer->3->1", + "login.handlebars->container->footer->3->termsLinkFooter", "message.handlebars->container->page_content->footer->1->1->0->3->1" ] }, @@ -17272,10 +23763,13 @@ "en": "Terms of use", "es": "Términos de Uso", "fr": "Conditions d'utilisation", + "hi": "उपयोग की शर्तें", "ja": "利用規約", + "ko": "이용 약관", "nl": "Gebruiksvoorwaarden", "pt": "Termos de uso", "ru": "Условия пользования", + "zh-chs": "使用條款", "xloc": [ "terms-mobile.handlebars->container->page_content->column_l->1", "terms.handlebars->container->column_l->1" @@ -17285,22 +23779,31 @@ "cs": "thajština", "de": "Thai", "en": "Thai", + "fr": "thaïlandais", + "hi": "थाई", "ja": "タイ語", + "ko": "타이", "nl": "Thais", "pt": "Thai", "ru": "Тайский", + "zh-chs": "泰國", "xloc": [ - "default.handlebars->25->901" + "default.handlebars->27->1005" ] }, { "cs": "Níže jsou uvedena požadovaná zveřejnění součástí a softwaru s otevřeným zdrojovým kódem začleněných do tohoto softwaru.", + "de": "Im Folgenden sind die erforderlichen Angaben zu Open Source-Komponenten und -Software aufgeführt, die in dieser Software enthalten sind.", "en": "The following are the required disclosures of open source components and software incorporated into this software.", "es": "Las siguientes son las divulgaciones requeridas de componentes de código abierto y software incorporado en este software.", + "fr": "Les informations suivantes sont les divulgations requises des composants open source et des logiciels intégrés à ce logiciel.", + "hi": "इस सॉफ्टवेयर में शामिल मुक्त स्रोत घटकों और सॉफ़्टवेयर के आवश्यक प्रकटीकरण निम्नलिखित हैं।", "ja": "以下は、このソフトウェアに組み込まれているオープンソースコンポーネントとソフトウェアの必須の開示です。", + "ko": "다음은이 소프트웨어에 포함 된 오픈 소스 구성 요소 및 소프트웨어에 대한 필수 정보입니다.", "nl": "Hierna volgen de vereiste informatie over open source-componenten en software die in deze software is opgenomen.", "pt": "A seguir, são apresentadas as divulgações necessárias de componentes e software de código aberto incorporados neste software.", "ru": "Ниже приведены необходимые описания компонентов с открытым исходным кодом и программного обеспечения, включенного в это программное обеспечение.", + "zh-chs": "以下是此軟件中包含的開源組件和軟件的必需披露。", "xloc": [ "terms-mobile.handlebars->container->page_content->column_l->7", "terms.handlebars->container->column_l->7" @@ -17312,12 +23815,15 @@ "en": "The name of the device group this computer belong to", "es": "El nombre del grupo de dispositivos al que pertenece esta computadora", "fr": "Le nom du groupe de périphériques auquel cet ordinateur appartient", + "hi": "इस कंप्यूटर से संबंधित डिवाइस समूह का नाम है", "ja": "このコンピューターが属するデバイスグループの名前", + "ko": "이 컴퓨터가 속한 장치 그룹의 이름", "nl": "De naam van de apparaatgroep waartoe deze computer behoort", "pt": "O nome do grupo de dispositivos ao qual este computador pertence", "ru": "Имя группы устройств, к которой принадлежит этот компьютер", + "zh-chs": "該計算機所屬的設備組的名稱", "xloc": [ - "default.handlebars->25->444" + "default.handlebars->27->448" ] }, { @@ -17325,12 +23831,33 @@ "de": "Der Name der Gerätegruppe zu der dieser Rechner gehört.", "en": "The name of the device group this computer belong to.", "es": "El nombre del grupo de dispositivos al que pertenece esta computadora.", + "fr": "Nom du groupe de périphériques auquel appartient cet ordinateur.", + "hi": "इस कंप्यूटर से संबंधित डिवाइस समूह का नाम है।", "ja": "このコンピューターが属するデバイスグループの名前。", + "ko": "이 컴퓨터가 속한 장치 그룹의 이름입니다.", "nl": "De naam van de apparaatgroep waartoe deze computer behoort", "pt": "O nome do grupo de dispositivos ao qual este computador pertence.", "ru": "Имя группы устройств, к которой принадлежит этот компьютер.", + "zh-chs": "該計算機所屬的設備組的名稱。", "xloc": [ - "default.handlebars->25->442" + "default.handlebars->27->446" + ] + }, + { + "cs": "Název tohoto počítače nastavený v operačním systému", + "de": "Der im Betriebssystem festgelegte Name dieses Computers", + "en": "The name of this computer as set in the operating system", + "fr": "Le nom de cet ordinateur tel qu'il est défini dans le système d'exploitation", + "hi": "ऑपरेटिंग सिस्टम में सेट के रूप में इस कंप्यूटर का नाम", + "ja": "オペレーティングシステムに設定されているこのコンピューターの名前", + "ko": "운영 체제에 설정된이 컴퓨터의 이름", + "nl": "De naam van deze computer zoals ingesteld in het besturingssysteem", + "pt": "O nome deste computador, conforme definido no sistema operacional", + "ru": "Имя этого компьютера, указанное в операционной системе", + "zh-chs": "在操作系統中設置的此計算機的名稱", + "xloc": [ + "default.handlebars->27->449", + "default.handlebars->27->451" ] }, { @@ -17339,12 +23866,15 @@ "en": "There are currently no notifications", "es": "Actualmente no hay notificaciones", "fr": "Il n'y a actuellement aucune notification", + "hi": "वर्तमान में कोई सूचना नहीं है", "ja": "現在、通知はありません", + "ko": "현재 알림이 없습니다", "nl": "Er zijn momenteel geen meldingen", "pt": "Atualmente não há notificações", "ru": "На данный момент уведомлений нет", + "zh-chs": "目前沒有任何通知", "xloc": [ - "default.handlebars->25->1391" + "default.handlebars->27->1537" ] }, { @@ -17353,10 +23883,13 @@ "en": "These files are shared publicly, click \"link\" to get public url.", "es": "Estos archivos se comparten públicamente, haga clic en \"enlace\" para obtener la URL pública.", "fr": "Ces fichiers sont partagés publiquement, cliquez sur \"lien\" pour obtenir une URL publique.", + "hi": "ये फ़ाइलें सार्वजनिक रूप से साझा की जाती हैं, सार्वजनिक url प्राप्त करने के लिए \"लिंक\" पर क्लिक करें।", "ja": "これらのファイルは一般公開されています。「リンク」をクリックして公開URLを取得してください。", + "ko": "이 파일은 공개적으로 공유됩니다. 공개 링크를 받으려면 \"링크\"를 클릭하십시오.", "nl": "Deze bestanden worden openbaar gedeeld, klik op \"link\" om de openbare URL te krijgen.", "pt": "Esses arquivos são compartilhados publicamente, clique em \"link\" para obter o URL público.", "ru": "Эти файлы являются общедоступными, нажмите \"ссылку\", чтобы получить общедоступный URL.", + "zh-chs": "這些文件是公開共享的,請單擊“鏈接”以獲取公共URL。", "xloc": [ "default.handlebars->container->column_l->p5->p5filetable->p5PublicShare->0" ] @@ -17366,12 +23899,16 @@ "de": "Diese Einstellungen können verwendet werden, um MQTT für dieses Gerät zu verbinden.", "en": "These settings can be used to connect MQTT for this device.", "es": "Esta configuración se puede utilizar para conectar MQTT para este dispositivo.", + "fr": "Ces paramètres peuvent être utilisés pour connecter MQTT à cet appareil.", + "hi": "इस डिवाइस के लिए MQTT को जोड़ने के लिए इन सेटिंग्स का उपयोग किया जा सकता है।", "ja": "これらの設定を使用して、このデバイスのMQTTを接続できます。", + "ko": "이 설정은이 장치의 MQTT를 연결하는 데 사용할 수 있습니다.", "nl": "Deze instellingen kunnen worden gebruikt om MQTT voor dit apparaat te verbinden.", "pt": "Essas configurações podem ser usadas para conectar o MQTT a este dispositivo.", "ru": "Эти настройки можно использовать для подключения MQTT для этого устройства.", + "zh-chs": "這些設置可用於連接該設備的MQTT。", "xloc": [ - "default.handlebars->25->175" + "default.handlebars->27->158" ] }, { @@ -17379,13 +23916,33 @@ "de": "Dieses Konto besitzt keine Rechte um eine neue Gerätegruppe zu erzeugen.", "en": "This account does not have the rights to create a new device group.", "es": "Esta cuenta no tiene los derechos para crear un nuevo grupo de dispositivos.", + "fr": "Ce compte ne permet pas la création de groupe utilisateurs", + "hi": "इस खाते में नया उपकरण समूह बनाने के अधिकार नहीं हैं।", "ja": "このアカウントには、新しいデバイスグループを作成する権限がありません。", + "ko": "이 계정에는 새 장치 그룹을 만들 수있는 권한이 없습니다.", "nl": "Dit account heeft niet de rechten om een nieuwe apparaatgroep te maken.", "pt": "Esta conta não tem direitos para criar um novo grupo de dispositivos.", "ru": "Эта учетная запись не имеет прав для создания новой группы устройств.", + "zh-chs": "該帳戶無權創建新的設備組。", "xloc": [ - "default-mobile.handlebars->9->51", - "default.handlebars->25->949" + "default-mobile.handlebars->9->54", + "default.handlebars->27->1054" + ] + }, + { + "cs": "Toto je portál pro vzdálenou správu a podporu počítače.", + "de": "Dies ist ein Portal für die Remoteverwaltung und den Support von Computern.", + "en": "This is a portal for computer remote management and support.", + "fr": "Il s'agit d'un portail de gestion et d'assistance à distance des ordinateurs.", + "hi": "यह कंप्यूटर दूरस्थ प्रबंधन और समर्थन के लिए एक पोर्टल है।", + "ja": "これは、コンピューターのリモート管理とサポートのためのポータルです。", + "ko": "컴퓨터 원격 관리 및 지원을위한 포털입니다.", + "nl": "Dit is een portaal voor extern computerbeheer en ondersteuning.", + "pt": "Este é um portal para gerenciamento e suporte remotos de computadores.", + "ru": "Это портал для удаленного управления и поддержки компьютера.", + "zh-chs": "這是計算機遠程管理和支持的門戶。", + "xloc": [ + "invite.handlebars->container->column_l->3" ] }, { @@ -17393,12 +23950,16 @@ "de": "Dies ist keine sichere Richtlinie, da Agenten die Aktivierung durchführen.", "en": "This is not a secure policy as agents will be performing activation.", "es": "Esta no es una política segura ya que los agentes realizarán la activación.", + "fr": "Ce n'est pas une politique sécurisée car les agents effectueront l'activation.", + "hi": "यह एक सुरक्षित नीति नहीं है क्योंकि एजेंट सक्रियता का प्रदर्शन करेंगे।", "ja": "エージェントはアクティベーションを実行するため、これは安全なポリシーではありません。", + "ko": "에이전트가 활성화를 수행하므로 이는 보안 정책이 아닙니다.", "nl": "Dit is geen veilig beleid omdat agenten activering zullen uitvoeren.", "pt": "Esta não é uma política segura, pois os agentes estarão executando a ativação.", "ru": "Это не безопасная политика, так как агенты будут выполнять активацию.", + "zh-chs": "這不是安全的策略,因為代理將執行激活。", "xloc": [ - "default.handlebars->25->1061" + "default.handlebars->27->1165" ] }, { @@ -17406,10 +23967,14 @@ "de": "Diese Seite existiert nicht.", "en": "This page does not exist", "es": "Esta pagina no existe", + "fr": "Page introuvable", + "hi": "यह पृष्ठ मौजूद नहीं है", "ja": "このページは存在しません", + "ko": "이 페이지는 존재하지 않습니다", "nl": "Deze pagina bestaat niet", "pt": "Esta página não existe", "ru": "Страница не существует", + "zh-chs": "本頁面不存在", "xloc": [ "error404-mobile.handlebars->container->page_content->column_l->3", "error404.handlebars->container->column_l->3" @@ -17420,22 +23985,31 @@ "de": "Diese Richtlinie hat keine Wirkung auf Intel®-AMT-Geräte im ACM-Modus.", "en": "This policy will not impact devices with Intel® AMT in ACM mode.", "es": "Esta política no afectará a los dispositivos con Intel & reg; AMT en modo ACM.", + "fr": "Cette politique n'affectera pas les appareils avec Intel® AMT en mode ACM.", + "hi": "यह नीति AC® मोड में Intel® AMT वाले उपकरणों को प्रभावित नहीं करेगी।", "ja": "このポリシーは、Intel®を搭載したデバイスには影響しません。 ACMモードのAMT。", + "ko": "이 정책은 ACM 모드에서 인텔 ® AMT가 설치된 장치에는 영향을 미치지 않습니다.", "nl": "Dit beleid heeft geen invloed op apparaten met Intel® AMT ACM-modus", "pt": "Esta política não afetará os dispositivos com Intel® AMT no modo ACM.", "ru": "Эта политика не повлияет на устройства с Intel® AMT в режиме ACM.", + "zh-chs": "該策略不會影響採用ACM模式的英特爾®AMT的設備。", "xloc": [ - "default.handlebars->25->1060" + "default.handlebars->27->1164" ] }, { "cs": "Tento software se skládá z dobrovolných příspěvků mnoha jednotlivců (AUTHORS.txt, http://jqueryui.com/about ). Přesnou historii příspěvků naleznete v historii revizí a protokolech dostupných na adrese http://jquery-ui.googlecode.com/svn/", + "de": "Diese Software besteht aus freiwilligen Beiträgen vieler Einzelpersonen (AUTHORS.txt, http://jqueryui.com/about). Den genauen Beitragsverlauf finden Sie im Versionsverlauf und in den Protokollen unter http://jquery-ui.googlecode.com/svn/.", "en": "This software consists of voluntary contributions made by many individuals (AUTHORS.txt, http://jqueryui.com/about ). For exact contribution history,see the revision history and logs, available at http://jquery-ui.googlecode.com/svn/", "es": "Este software consta de contribuciones voluntarias realizadas por muchas personas (AUTHORS.txt, http://jqueryui.com/about). Para obtener una contribución precisa al historial, consulte el historial de revisiones y los registros, disponibles en http://jquery-ui.googlecode.com/svn/", + "fr": "Ce logiciel est constitué de contributions volontaires faites par de nombreuses personnes (AUTHORS.txt, http://jqueryui.com/about). Pour l'historique exact des contributions, consultez l'historique des révisions et les journaux, disponibles sur http://jquery-ui.googlecode.com/svn/", + "hi": "इस सॉफ्टवेयर में कई व्यक्तियों द्वारा स्वैच्छिक योगदान (AUTHORS.txt, http://jqueryui.com/about) शामिल हैं। सटीक योगदान इतिहास के लिए, संशोधन इतिहास और लॉग देखें, जो http://jquery-ui.googlecode.com/svn/ पर उपलब्ध है।", "ja": "このソフトウェアは、多くの個人による自発的な貢献で構成されています(AUTHORS.txt、http://jqueryui.com/about)。正確な貢献履歴については、http://jquery-ui.googlecode.com/svn/にある改訂履歴とログをご覧ください", + "ko": "이 소프트웨어는 많은 개인 (AUTHORS.txt, http://jqueryui.com/about)의 자발적인 기여로 구성됩니다. 정확한 기여 내역은 http://jquery-ui.googlecode.com/svn/에서 개정 내역 및 로그를 참조하십시오.", "nl": "Deze software bestaat uit vrijwillige bijdragen van veel personen (AUTHORS.txt, http://jqueryui.com/about ). Voor de exacte contributiegeschiedenis, zie de revisiegeschiedenis en logboeken, beschikbaar op http://jquery-ui.googlecode.com/svn/", "pt": "Este software consiste em contribuições voluntárias feitas por muitos indivíduos (AUTORES.txt, http://jqueryui.com/about ). Para obter o histórico exato de contribuições, consulte o histórico de revisões e os logs, disponíveis em http://jquery-ui.googlecode.com/svn/", "ru": "Это программное обеспечение состоит из добровольных взносов, сделанных многими людьми (AUTHORS.txt, http://jqueryui.com/about). Точную историю внесения см. в истории изменений и журналах, доступных по адресу http://jquery-ui.googlecode.com/svn/.", + "zh-chs": "該軟件由許多人的自願捐款組成(AUTHORS.txt,http://jqueryui.com/about)。有關確切的貢獻歷史記錄,請參閱修訂歷史記錄和日誌,網址為http://jquery-ui.googlecode.com/svn/", "xloc": [ "terms-mobile.handlebars->container->page_content->column_l->55->1", "terms.handlebars->container->column_l->55->1" @@ -17443,28 +24017,51 @@ }, { "cs": "Tento software využívá zdrojové kódy z", + "de": "Diese Software verwendet Code von", "en": "This software uses code from", "es": "Este software usa código de", + "fr": "Ce logiciel utilise le code de", + "hi": "इस सॉफ्टवेयर से कोड का उपयोग करता है", "ja": "このソフトウェアはからのコードを使用します", + "ko": "이 소프트웨어는", "nl": "Deze software maakt gebruik van code van", "pt": "Este software usa código de", "ru": "Это программное обеспечение использует код из", + "zh-chs": "該軟件使用以下代碼", "xloc": [ "terms-mobile.handlebars->container->page_content->column_l->75->1", "terms.handlebars->container->column_l->75->1" ] }, + { + "cs": "Tento token lze použít pouze jednou a je platný po dobu 5 minut.", + "de": "Dieser Token kann nur einmal verwendet werden und ist 5 Minuten gültig.", + "en": "This token can only be used once and is valid for 5 minutes.", + "fr": "Ce jeton ne peut être utilisé qu'une seule fois et est valide pendant 5 minutes.", + "nl": "Dit token kan maar één keer worden gebruikt en is 5 minuten geldig.", + "ja": "このトークンは1回だけ使用でき、5分間有効です。", + "ru": "Этот токен может быть использован только один раз и действителен в течение 5 минут.", + "zh-chs": "该令牌只能使用一次,有效期为5分钟。", + "xloc": [ + "account-login.html->2->5", + "account-login.txt" + ] + }, { "cs": "Tím se přidá položka do tohoto záznamu událostí na zařízení.", "de": "Dies wird einen Eintrag zum Ereignisprotokoll des Geräts hinzufügen.", "en": "This will add an entry to this device\\'s event log.", "es": "Esto agregará una entrada al registro de eventos de este dispositivo.", + "fr": "Cette action ajoutera une entrée dans le journal d'évènement de l'appareil.", + "hi": "यह इस उपकरण के ईवेंट लॉग में एक प्रविष्टि जोड़ देगा।", "ja": "これにより、このデバイスのイベントログにエントリが追加されます。", + "ko": "이 장치의 이벤트 로그에 항목이 추가됩니다.", "nl": "Hiermee wordt een vermelding toegevoegd aan het gebeurtenislogboek van dit apparaat.", "pt": "Isso adicionará uma entrada ao log de eventos deste dispositivo.", "ru": "Это добавит запись в журнал событий данного устройства.", + "zh-chs": "這會將條目添加到該設備的事件日誌中。", "xloc": [ - "default.handlebars->25->530" + "default.handlebars->27->577" ] }, { @@ -17472,11 +24069,16 @@ "de": "Dies wird die Geräte nicht vom Server entfernen, aber die Geräte werden nicht länger eine Verbindung zum Server aufbauen können. Aller entfernter Zugriff auf die Geräte geht verloren. Die Geräte müssen verbunden sein, damit dieser Befehl funktioniert.", "en": "This will not remove the devices from the server, but the devices will not longer be able to connect to the server. All remote access to the devices will be lost. The devices must be connected for this command to work.", "es": "Esto no eliminará los dispositivos del servidor, pero los dispositivos ya no podrán conectarse al servidor. Se perderá todo el acceso remoto a los dispositivos. Los dispositivos deben estar conectados para que este comando funcione.", + "fr": "Cela ne supprimera pas les périphériques du serveur, mais les périphériques ne pourront plus se connecter au serveur. Tout accès à distance aux appareils sera perdu. Les appareils doivent être connectés pour que cette commande fonctionne.", + "hi": "यह डिवाइस को सर्वर से नहीं हटाएगा, लेकिन डिवाइस सर्वर से कनेक्ट नहीं कर पाएंगे। उपकरणों की सभी दूरस्थ पहुँच खो जाएगी। इस कमांड को काम करने के लिए उपकरणों को जोड़ा जाना चाहिए।", "ja": "これによりサーバーからデバイスが削除されることはありませんが、デバイスはサーバーに接続できなくなります。デバイスへのすべてのリモートアクセスが失われます。このコマンドが機能するには、デバイスが接続されている必要があります。", + "ko": "이렇게하면 서버에서 장치가 제거되지 않지만 장치는 더 이상 서버에 연결할 수 없습니다. 장치에 대한 모든 원격 액세스가 손실됩니다. 이 명령이 작동하려면 장치가 연결되어 있어야합니다.", "nl": "Hiermee worden de apparaten niet van de server verwijderd, maar kunnen de apparaten geen verbinding meer maken met de server. Alle externe toegang tot de apparaten gaat verloren. De apparaten moeten zijn aangesloten om deze opdracht te laten werken.", + "pt": "Isso não removerá os dispositivos do servidor, mas os dispositivos não poderão mais se conectar ao servidor. Todo o acesso remoto aos dispositivos será perdido. Os dispositivos devem estar conectados para que este comando funcione.", "ru": "Это не приведет к удалению устройств с сервера, но они больше не смогут подключаться к серверу. Весь удаленный доступ к устройствам будет потерян. Устройства должны быть подключены, чтобы эта команда работала.", + "zh-chs": "這不會從服務器上刪除設備,但是設備將不再能夠連接到服務器。對設備的所有遠程訪問都將丟失。必須連接設備,此命令才能起作用。", "xloc": [ - "default.handlebars->25->558" + "default.handlebars->27->605" ] }, { @@ -17484,11 +24086,16 @@ "de": "Dies wird das Gerät nicht vom Server entfernen, aber das Gerät wird nicht länger eine Verbindung zum Server aufbauen können. Aller entfernter Zugriff auf das Gerät geht verloren. Das Gerät muss verbunden sein, damit dieser Befehl funktioniert.", "en": "This will not remove this device from the server, but the device will not longer be able to connect to the server. All remote access to the device will be lost. The device must be connect for this command to work.", "es": "Esto no eliminará este dispositivo del servidor, pero el dispositivo ya no podrá conectarse al servidor. Se perderá todo el acceso remoto al dispositivo. El dispositivo debe estar conectado para que este comando funcione.", + "fr": "Cela ne supprimera pas cet appareil du serveur, mais l'appareil ne pourra plus se connecter au serveur. Tout accès à distance à l'appareil sera perdu. Le périphérique doit être connecté pour que cette commande fonctionne.", + "hi": "यह सर्वर से इस डिवाइस को नहीं हटाएगा, लेकिन डिवाइस सर्वर से कनेक्ट करने में सक्षम नहीं होगा। डिवाइस के सभी रिमोट एक्सेस खो जाएंगे। इस कार्य के लिए डिवाइस को कनेक्ट होना चाहिए।", "ja": "このデバイスはサーバーから削除されませんが、デバイスはサーバーに接続できなくなります。デバイスへのすべてのリモートアクセスが失われます。このコマンドが機能するには、デバイスが接続されている必要があります。", + "ko": "이렇게하면 서버에서이 장치가 제거되지 않지만 장치는 더 이상 서버에 연결할 수 없습니다. 장치에 대한 모든 원격 액세스가 손실됩니다. 이 명령이 작동하려면 장치가 연결되어 있어야합니다.", "nl": "Hiermee wordt dit apparaat niet van de server verwijderd, maar kan het apparaat geen verbinding meer maken met de server. Alle externe toegang tot het apparaat gaat verloren. Het apparaat moet verbonden zijn om dit commando te laten werken.", + "pt": "Isso não removerá este dispositivo do servidor, mas o dispositivo não poderá mais se conectar ao servidor. Todo o acesso remoto ao dispositivo será perdido. O dispositivo deve estar conectado para que este comando funcione.", "ru": "Это не приведет к удалению этого устройства с сервера, но оно больше не сможет подключаться к серверу. Весь удаленный доступ к устройству будет потерян. Для работы этой команды устройство должно быть подключено.", + "zh-chs": "這不會將該設備從服務器上刪除,但是該設備將不再能夠連接到服務器。對設備的所有遠程訪問都將丟失。必須連接設備,此命令才能起作用。", "xloc": [ - "default.handlebars->25->559" + "default.handlebars->27->606" ] }, { @@ -17496,12 +24103,16 @@ "de": "Tigre", "en": "Tigre", "es": "Tigre", + "fr": "Tigre", + "hi": "टाइग्रे", "ja": "ティグレ", + "ko": "티 그레", "nl": "Tigre", "pt": "Tigre", "ru": "Тигровый", + "zh-chs": "蒂格雷", "xloc": [ - "default.handlebars->25->902" + "default.handlebars->27->1006" ] }, { @@ -17510,10 +24121,13 @@ "en": "Time", "es": "Tiempo", "fr": "Temps", + "hi": "समय", "ja": "時間", + "ko": "시각", "nl": "Tijd", "pt": "Tempo", "ru": "Время", + "zh-chs": "時間", "xloc": [ "player.handlebars->3->1" ] @@ -17523,12 +24137,16 @@ "de": "Um einen Rechner zu {0} hinzuzufügen, führe den folgenden Befehl aus. Root-Zugriff wird benötigt.", "en": "To add a computer to {0} run the following command. Root credentials will be needed.", "es": "Para agregar una computadora a {0} ejecute el siguiente comando. Se necesitarán credenciales de root.", + "fr": "Pour ajouter un appareil à {0} exécutez la commande suivante. Des accès administrateurs sont nécessaires.", + "hi": "कंप्यूटर को {0} में जोड़ने के लिए निम्नलिखित कमांड चलाएँ। रूट क्रेडेंशियल की जरूरत होगी।", "ja": "{0}にコンピューターを追加するには、次のコマンドを実行します。ルート資格情報が必要になります。", + "ko": "{0}에 컴퓨터를 추가하려면 다음 명령을 실행하십시오. 루트 자격 증명이 필요합니다.", "nl": "Voer de volgende opdracht uit om een computer toe te voegen aan {0}. Root gegevens zijn nodig.", "pt": "Para adicionar um computador a {0}, execute o seguinte comando.Serão necessárias credenciais raiz.", "ru": "Чтобы добавить компьютер в группу \\\"{0}\\\", выполните следующую команду. Потребуются права root.", + "zh-chs": "要將計算機添加到{0},請運行以下命令。需要根憑證。", "xloc": [ - "default.handlebars->25->333" + "default.handlebars->27->322" ] }, { @@ -17536,12 +24154,16 @@ "de": "Um ein neues Intel®-AMT-Gerät zur Gerätegruppe \\\"{0}\\\" mit CIRA hinzuzufügen, laden Sie die folgenden Script-Dateien herunter und verwenden Sie MeshCommander, um das Script auf den zu konfigurierenden Rechnern auszuführen.", "en": "To add a new Intel® AMT device to device group \\\"{0}\\\" with CIRA, download the following script files and use MeshCommander to run the script to configure computers.", "es": "Para agregar un nuevo Intel & reg; Dispositivo AMT al grupo de dispositivos \\\"{0}\\\" con CIRA, descargue los siguientes archivos de comandos y use MeshCommander para ejecutar el script para configurar computadoras.", + "fr": "Pour ajouter un appareil Intel® AMT au groupe \\\"{0}\\# en utilisant CIRA, téléchargez le script suivant et exécutez le à l'aide de MeshCommander.", + "hi": "CIRA के साथ डिवाइस समूह \\\"{0} \\\" में एक नया Intel® AMT डिवाइस जोड़ने के लिए, निम्नलिखित स्क्रिप्ट फ़ाइलों को डाउनलोड करें और MeshCommander ।", "ja": "新しいIntel®を追加するにはCIRAを使用してAMTデバイスからデバイスグループ\\\"{0}\\\"に移動し、次のスクリプトファイルをダウンロードして、 MeshCommander スクリプトを実行してコンピューターを構成します。", + "ko": "CIRA를 사용하여 장치 그룹 \\\"{0} \\\"에 새 인텔 ® AMT 장치를 추가하려면 다음 스크립트 파일을 다운로드하고 MeshCommander ", "nl": "Om een nieuw Intel® AMT-apparaat toe te voegen aan apparaatgroep \\\"{0}\\\" met CIRA, downloadt u de volgende scriptbestanden en gebruikt u MeshCommander om het script uit te voeren om computers te configureren.", "pt": "Para adicionar um novo Intel® Dispositivo AMT para grupo de dispositivos \\\"{0}\\\" com CIRA, baixe os seguintes arquivos de script e use MeshCommander para executar o script para configurar computadores.", "ru": "Чтобы добавить новое устройство Intel® AMT в группу устройств \\\"{0}\\\" с CIRA, загрузите следующие файлы со скриптами и используйте MeshCommander, чтобы запустить скрипт для настройки компьютеров.", + "zh-chs": "要將新的英特爾®AMT設備添加到具有CIRA的設備組“ {0} \\”中,請下載以下腳本文件,並使用 MeshCommander 來運行腳本來配置計算機。", "xloc": [ - "default.handlebars->25->262" + "default.handlebars->27->246" ] }, { @@ -17549,12 +24171,16 @@ "de": "Um ein neues Intel®-AMT-Gerät zur Gerätegruppe \\\"{0}\\\" mit CIRA hinzuzufügen, laden Sie das folgende Zertifikat als bekanntes Stammzertifikat in Intel AMT", "en": "To add a new Intel® AMT device to device group \\\"{0}\\\" with CIRA, load the following certificate as trusted root within Intel AMT", "es": "Para agregar un nuevo Dispositivo Intel & reg; AMT al grupo de dispositivos \\\"{0}\\\" con CIRA, cargue el siguiente certificado raíz como confiable dentro de Intel AMT", + "fr": "Pour ajouter un nouveau périphérique Intel® AMT au groupe de périphériques \\\"{0}\\\" avec CIRA, chargez le certificat suivant en tant que racine de confiance dans Intel AMT", + "hi": "CIRA के साथ डिवाइस समूह \\\"{0} \\\" में एक नया Intel® AMT उपकरण जोड़ने के लिए, निम्नलिखित प्रमाणपत्र को Intel AMT के रूप में विश्वसनीय रूट के रूप में लोड करें", "ja": "新しいIntel®を追加するにはAMTデバイスからCIRAを使用したデバイスグループ\\\"{0}\\\"に、Intel AMT内で信頼されたルートとして次の証明書をロード", + "ko": "CIRA를 사용하여 장치 그룹 \\\"{0} \\\"에 새 Intel® AMT 장치를 추가하려면 Intel AMT 내에서 신뢰할 수있는 루트로 다음 인증서를로드하십시오.", "nl": "Om een nieuw Intel® AMT-apparaat toe te voegen aan apparaatgroep \\\"{0}\\\" met CIRA, laadt u het volgende certificaat als vertrouwde root in Intel AMT", "pt": "Para adicionar um novo Intel® Dispositivo AMT para grupo de dispositivos \\\"{0}\\\" com CIRA, carregue o seguinte certificado como raiz confiável no Intel AMT", "ru": "Чтобы добавить новое устройство Intel® AMT в группу устройств \\\"{0}\\\" с CIRA, загрузите следующий сертификат в качестве доверенного в Intel AMT", + "zh-chs": "要將新的英特爾®AMT設備添加到具有CIRA的設備組“ {0} \\”,請在英特爾AMT中將以下證書作為受信任的根加載", "xloc": [ - "default.handlebars->25->265" + "default.handlebars->27->249" ] }, { @@ -17562,12 +24188,16 @@ "de": "Um ein neues Intel®-AMT-Gerät zur Gerätegruppe \\\"{0}\\\" mit CIRA hinzuzufügen, laden Sie das folgende Zertifikat als bekanntes Stammzertifikat in Intel AMT, authentifizieren Sie sich mittels eines Clientzertifikats mit dem folgenden Common Name und verbinden Sie sich zu folgendem Server.", "en": "To add a new Intel® AMT device to device group \\\"{0}\\\" with CIRA, load the following certificate as trusted root within Intel AMT, authenticate using a client certificate with the following common name and connect to the following server.", "es": "Para agregar un nuevo Dispositivo Intel & reg; AMT al grupo de dispositivos \\\"{0}\\\" con CIRA, cargue los siguientes certificados raíz como certificados de confianza dentro de Intel AMT, autentíquese utilizando un certificado de cliente con el siguiente nombre común y conéctese al siguiente servidor.", + "fr": "Pour ajouter un nouveau périphérique Intel® AMT au groupe de périphériques \\\"{0}\\\" avec CIRA, chargez le certificat suivant en tant que racine de confiance dans Intel AMT, authentifiez-vous à l'aide d'un certificat client avec le nom commun suivant et connectez-vous au serveur suivant.", + "hi": "CIRA के साथ डिवाइस ग्रुप \\\"{0} \\\" में एक नया इंटेल® एएमटी डिवाइस जोड़ने के लिए, इंटेल एएमटी के भीतर विश्वसनीय रूट के रूप में निम्नलिखित प्रमाण पत्र को लोड करें, निम्नलिखित सामान्य नाम के साथ एक क्लाइंट प्रमाण पत्र का उपयोग करके प्रमाणित करें और निम्न सर्वर से कनेक्ट करें।", "ja": "新しいIntel®を追加するにはCIRAを使用してデバイスグループ\\\"{0}\\\"へのAMTデバイス、Intel AMT内の信頼されたルートとして次の証明書を読み込み、次の共通名を持つクライアント証明書を使用して認証し、次のサーバーに接続します。", + "ko": "CIRA를 사용하여 장치 그룹 \\\"{0} \\\"에 새 Intel® AMT 장치를 추가하려면 Intel AMT 내에서 신뢰할 수있는 루트로 다음 인증서를로드하고 다음 일반 이름의 클라이언트 인증서를 사용하여 인증 한 후 다음 서버에 연결하십시오.", "nl": "Om een nieuw Intel® AMT-apparaat toe te voegen aan apparaatgroep \\\"{0}\\\" met CIRA, laadt u het volgende certificaat als vertrouwde root in Intel AMT, verifieert u met een clientcertificaat met de volgende gemeenschappelijke naam en maakt u verbinding met de volgende server.", "pt": "Para adicionar um novo Intel® Dispositivo AMT para grupo de dispositivos \\\"{0}\\\" com CIRA, carregue o seguinte certificado como raiz confiável no Intel AMT, autentique usando um certificado de cliente com o seguinte nome comum e conecte-se ao servidor a seguir.", "ru": "Чтобы добавить новое устройство Intel® AMT в группу устройств \\\"{0}\\\" с CIRA, загрузите следующий сертификат в качестве доверенного в Intel AMT, выполните аутентификацию с использованием сертификата клиента со следующим общим именем и подключитесь к серверу.", + "zh-chs": "要將新的英特爾®AMT設備添加到具有CIRA的設備組“ {0} \\”中,請將以下證書作為受信任的根加載到英特爾AMT中,使用具有以下通用名稱的客戶端證書進行身份驗證並連接到以下服務器。", "xloc": [ - "default.handlebars->25->274" + "default.handlebars->27->258" ] }, { @@ -17575,12 +24205,16 @@ "de": "Um einen neuen Rechner zur Gerätegruppe \\\"{0}\\\" hinzuzufügen, laden Sie den Mesh-Agenten herunter und installieren Sie ihn auf dem zu verwaltenden Rechner. In diesen Agenten sind Server- und Gerätegruppen-Informationen bereits eingebettet.", "en": "To add a new computer to device group \\\"{0}\\\", download the mesh agent and install it the computer to manage. This agent has server and device group information embedded within it.", "es": "Para agregar una nueva computadora al grupo de dispositivos \\\"{0}\\\", descargue el agente de malla e instálelo para administrar la computadora. Este agente tiene una información de servidor y grupo de dispositivos incrustada dentro de él.", + "fr": "Pour ajouter un nouvel appareil au groupe \\\"{0}\\\", télécharger et installer l'agent sur l'appareil à surveiller. L'agent contient le server et le groupe d'appartenance.", + "hi": "डिवाइस समूह में एक नया कंप्यूटर जोड़ने के लिए \\\"{0} \\\", मेष एजेंट डाउनलोड करें और इसे प्रबंधित करने के लिए कंप्यूटर स्थापित करें। इस एजेंट के पास सर्वर और डिवाइस समूह की जानकारी है।", "ja": "デバイスグループ\\\"{0}\\\"に新しいコンピューターを追加するには、メッシュエージェントをダウンロードし、管理するコンピューターにインストールします。このエージェントには、サーバーとデバイスグループの情報が埋め込まれています。", + "ko": "장치 그룹 \\\"{0} \\\"에 새 컴퓨터를 추가하려면 메쉬 에이전트를 다운로드하고 관리 할 컴퓨터를 설치하십시오. 이 에이전트에는 서버 및 장치 그룹 정보가 포함되어 있습니다.", "nl": "Als u een nieuwe computer aan apparaatgroep \\\"{0}\\\" wilt toevoegen, downloadt u de mesh-agent en installeert u deze op de te beheren computer. Deze agent heeft server- en apparaatgroepinformatie erin ingebed.", "pt": "Para adicionar um novo computador ao grupo de dispositivos \\\"{0}\\\", faça o download do agente de malha e instale-o no computador para gerenciar. Este agente possui informações de servidor e grupo de dispositivos incorporadas.", "ru": "Чтобы добавить новый компьютер в группу устройств \\\"{0}\\\", скачайте Mesh Agent и установите его для управления этим компьютером. В этот агент встроена информация о текущем сервере и группе устройств.", + "zh-chs": "要將新計算機添加到設備組\\“ {0} \\”,請下載網狀代理並安裝該計算機以進行管理。該代理中嵌入了服務器和設備組信息。", "xloc": [ - "default.handlebars->25->324" + "default.handlebars->27->311" ] }, { @@ -17588,12 +24222,16 @@ "de": "Um einen neuen Rechner zur Gerätegruppe \\\"{0}\\\" hinzuzufügen, laden Sie den Mesh-Agenten herunter und installieren Sie ihn auf dem zu verwaltenden Rechner. In dieses Agenten-Installationsprogramm sind Server- und Gerätegruppen-Informationen bereits eingebettet.", "en": "To add a new computer to device group \\\"{0}\\\", download the mesh agent and install it the computer to manage. This agent installer has server and device group information embedded within it.", "es": "Para agregar una nueva computadora al grupo de dispositivos \\\"{0}\\\", descargue el agente de malla e instálelo para administrar la computadora. Este agente instalador tiene una información de grupo de servidores y dispositivos integrada.", + "fr": "Pour ajouter un nouvel appareil au groupe \\\"{0}\\\", télécharger et installer l'agent sur l'appareil à surveiller. L'agent contient le server et le groupe d'appartenance.", + "hi": "डिवाइस समूह में एक नया कंप्यूटर जोड़ने के लिए \\\"{0} \\\", मेष एजेंट डाउनलोड करें और इसे प्रबंधित करने के लिए कंप्यूटर स्थापित करें। इस एजेंट इंस्टॉलर में सर्वर और डिवाइस समूह जानकारी है जो इसके भीतर एम्बेडेड है।", "ja": "デバイスグループ\\\"{0}\\\"に新しいコンピューターを追加するには、メッシュエージェントをダウンロードし、管理するコンピューターにインストールします。このエージェントインストーラーには、サーバーとデバイスグループの情報が埋め込まれています。", + "ko": "장치 그룹 \\\"{0} \\\"에 새 컴퓨터를 추가하려면 메쉬 에이전트를 다운로드하고 관리 할 컴퓨터를 설치하십시오. 이 에이전트 설치 관리자에는 서버 및 장치 그룹 정보가 포함되어 있습니다.", "nl": "Als u een nieuwe computer aan apparaatgroep \\\"{0}\\\" wilt toevoegen, downloadt u de mesh-agent en installeert u deze op de te beheren computer. In dit installatieprogramma van de agent zijn server- en apparaatgroepgegevens ingebed.", "pt": "Para adicionar um novo computador ao grupo de dispositivos \\\"{0}\\\", faça o download do agente de malha e instale-o no computador para gerenciar. Este instalador do agente possui informações de servidor e grupo de dispositivos incorporadas.", "ru": "Чтобы добавить новый компьютер в группу устройств \\\"{0}\\\", скачайте Mesh Agent и установите его для управления этим компьютером. В этот установщик агента встроена информация о текущем сервере и группе устройств.", + "zh-chs": "要將新計算機添加到設備組\\“ {0} \\”,請下載網狀代理並安裝該計算機以進行管理。該代理安裝程序中嵌入了服務器和設備組信息。", "xloc": [ - "default.handlebars->25->335" + "default.handlebars->27->324" ] }, { @@ -17601,12 +24239,16 @@ "de": "Um dieses Konto zu löschen, geben Sie das Konto-Passwort in beide untenstehenden Eingabefelder ein und wählen Sie OK.", "en": "To delete this account, type in the account password in both boxes below and hit ok.", "es": "Para eliminar esta cuenta, escriba la contraseña de la cuenta en los dos cuadros a continuación y presione Aceptar.", + "fr": "Pour supprimer votre compte, saisissez votre mot de passe ci-dessous puis cliquez sur \\\"Ok\\\"", + "hi": "इस खाते को हटाने के लिए, नीचे दिए गए दोनों बॉक्स में खाता पासवर्ड टाइप करें और ठीक दबाएं।", "ja": "このアカウントを削除するには、下の両方のボックスにアカウントのパスワードを入力して[OK]をクリックします。", + "ko": "이 계정을 삭제하려면 아래 두 상자에 계정 비밀번호를 입력하고 확인을 누르십시오.", "nl": "Om dit account te verwijderen, typt u het accountwachtwoord in beide onderstaande vakken en klikt u op OK.", "pt": "Para excluir esta conta, digite a senha da conta nas duas caixas abaixo e pressione ok.", "ru": "Чтобы удалить эту учетную запись, введите пароль учетной записи в оба поля и нажмите ОК.", + "zh-chs": "要刪除此帳戶,請在下面的兩個框中鍵入帳戶密碼,然後單擊確定。", "xloc": [ - "default.handlebars->25->936" + "default.handlebars->27->1041" ] }, { @@ -17614,23 +24256,57 @@ "de": "Um loszulegen,", "en": "To get started,", "es": "Para empezar", + "fr": "Pour commencer,", + "hi": "आरंभ करना,", "ja": "始めるには、", + "ko": "시작하려면", "nl": "om meteen aan de slag te gaan,", "pt": "Para começar,", "ru": "Для начала,", + "zh-chs": "開始,", "xloc": [ "default.handlebars->container->column_l->p1->NoMeshesPanel->1->1->0->3->getStarted1" ] }, + { + "cs": "Chcete-li nainstalovat software,", + "de": "Um die Software zu installieren,", + "en": "To install the software,", + "fr": "Pour installer le logiciel,", + "nl": "Om de software te installeren,", + "ja": "ソフトウェアをインストールするには、", + "ru": "Чтобы установить программное обеспечение,", + "zh-chs": "要安装软件,", + "xloc": [ + "mesh-invite.html->2->15->1" + ] + }, + { + "cs": "Chcete-li nainstalovat software, přejděte na [[[SERVERURL]]][[[LINKURL]]] a postupujte podle pokynů.", + "de": "Navigieren Sie zum Installieren der Software zu [[[SERVERURL]]][[[LINKURL]]] und befolgen Sie die Anweisungen.", + "en": "To install the software, navigate to [[[SERVERURL]]][[[LINKURL]]] and follow the instructions.", + "nl": "Om de software te installeren, navigeert u naar [[[SERVERURL]]] [[[LINKURL]]] en volgt u de instructies.", + "fr": "Pour installer le logiciel, accédez à [[[SERVERURL]]][[[LINKURL]]] et suivez les instructions.", + "ja": "ソフトウェアをインストールするには、[[[SERVERURL]]][[[LINKURL]]]に移動し、指示に従います。", + "ru": "Для установки программного обеспечения перейдите к [[[SERVERURL]]][[[LINKURL]]] и следуйте инструкциям.", + "zh-chs": "要安装软件,请导航至[[[SERVERURL]]][[[LINKURL]]],然后按照说明进行操作。", + "xloc": [ + "mesh-invite.txt" + ] + }, { "cs": "Pro instalaci spusťte následující příkaz s právy správce (root).", "de": "Zum Installieren, kopieren Sie den folgenden Befehl und führen Sie ihn in einem Root-Terminal aus.", "en": "To install, cut and paste the following command in a root terminal.", "es": "Para instalar, corte y pegue el siguiente comando en un terminal como root.", + "fr": "Pour installer, couper et coller la commande suivante dans un terminal ayant des droits administrateur", + "hi": "रूट टर्मिनल में निम्न कमांड को स्थापित, कट और पेस्ट करने के लिए।", "ja": "インストールするには、ルートターミナルで次のコマンドをカットアンドペーストします。", - "nl": "Om te installeren, knip en plak de volgende opdracht in de root-terminal.", + "ko": "설치하려면 다음 명령을 잘라서 루트 터미널에 붙여 넣으십시오.", + "nl": "Om te installeren, knip en plak de volgende opdracht in de terminal (root).", "pt": "Para instalar, recorte e cole o seguinte comando em um terminal raiz.", "ru": "Для установки, скопируйте и вставьте следующую команду в терминал. Потребуются права root.", + "zh-chs": "要在根終端中安裝,剪切和粘貼以下命令。", "xloc": [ "agentinvite.handlebars->container->column_l->5->linuxtab->3" ] @@ -17640,12 +24316,16 @@ "de": "Um den Mesh-Agenten zu entfernen, laden Sie die untenstehende Datei herunter, führen Sie sie aus und klicken Sie auf \\\"Deinstallieren\\\".", "en": "To remove a mesh agent, download the file below, run it and click \\\"uninstall\\\".", "es": "Para eliminar un agente de mesh, descargue el archivo a continuación, ejecútelo y haga clic en \\\"desinstalar\\\".", + "fr": "Pour supprimer l'agent, téléchargez le fichier ci-dessous, exécutez le et cliquez sur \\\"Désinstaller\\\".", + "hi": "एक मेष एजेंट को हटाने के लिए, नीचे दी गई फ़ाइल डाउनलोड करें, इसे चलाएं और \\\"अनइंस्टॉल \\\" पर क्लिक करें।", "ja": "メッシュエージェントを削除するには、以下のファイルをダウンロードして実行し、「アンインストール」をクリックします。", + "ko": "메쉬 에이전트를 제거하려면 아래 파일을 다운로드하여 실행 한 다음 \\\"제거 \\\"를 클릭하십시오.", "nl": "Om een mesh-agent te verwijderen, download het onderstaande bestand, voer het uit en klik op \\\"deinstalleer \\\".", "pt": "Para remover um agente de malha, faça o download do arquivo abaixo, execute-o e clique em \\\"uninstall\\\".", "ru": "Для удаления Mesh Agent скачайте файл ниже, запустите его и нажмите \\\"удалить\\\".", + "zh-chs": "要刪除網格代理,請下載以下文件,運行並單擊\\“卸載\\”。", "xloc": [ - "default.handlebars->25->338" + "default.handlebars->27->328" ] }, { @@ -17653,12 +24333,16 @@ "de": "Um einen Mesh-Agenten zu entfernen, führen Sie den folgenden Befehl aus. Root-Zugriff wird benötigt.", "en": "To remove a mesh agent, run the following command. Root credentials will be needed.", "es": "Para eliminar un agente de mesh, ejecute el siguiente comando. Se necesitarán credenciales de root.", + "fr": "Pour supprimer un agent, exécutez la commande suivante. Un accès administrateur est nécessaire.", + "hi": "मेष एजेंट को निकालने के लिए, निम्न कमांड चलाएँ। रूट क्रेडेंशियल की जरूरत होगी।", "ja": "メッシュエージェントを削除するには、次のコマンドを実行します。ルート資格情報が必要になります。", + "ko": "메시 에이전트를 제거하려면 다음 명령을 실행하십시오. 루트 자격 증명이 필요합니다.", "nl": "Voer de volgende opdracht uit om een mesh-agent te verwijderen. Root rechten zijn nodig.", "pt": "Para remover um agente de malha, execute o seguinte comando. Serão necessárias credenciais raiz.", "ru": "Для удаления Mesh Agent выполните следующую команду. Потребуются учетные данные root.", + "zh-chs": "要刪除網格代理,請運行以下命令。需要根憑證。", "xloc": [ - "default.handlebars->25->345" + "default.handlebars->27->335" ] }, { @@ -17666,10 +24350,14 @@ "de": "Zum Deinstallieren, kopieren Sie den folgenden Befehl und führen Sie ihn aus root aus.", "en": "To uninstall, cut and paste the following command as root.", "es": "Para desinstalar, corte y pegue el siguiente comando como root.", + "fr": "Pour déinstaller, couper/coller la commande suivante avec un compte administrateur.", + "hi": "अनइंस्टॉल करने के लिए, निम्न कमांड को रूट के रूप में काटें और पेस्ट करें।", "ja": "アンインストールするには、次のコマンドをルートとしてカットアンドペーストします。", + "ko": "설치 제거하려면 다음 명령을 잘라서 루트로 붙여 넣으십시오.", "nl": "Om de installatie ongedaan te maken, knip en plak je de volgende opdracht als root.", "pt": "Para desinstalar, recorte e cole o seguinte comando como raiz.", "ru": "Для удаления, скопируйте и вставьте следующую команду в терминал. Потребуются права root.", + "zh-chs": "要卸載,請以root用戶身份剪切並粘貼以下命令。", "xloc": [ "agentinvite.handlebars->container->column_l->5->linuxtab->9" ] @@ -17679,10 +24367,14 @@ "de": "Emulationstyp für F1 bis F10 umschalten", "en": "Toggle F1 to F10 keys emulation type", "es": "Cambiar el tipo de emulación de teclas F1 a F10", + "fr": "Basculer le type d'émulation des touches F1 à F10", + "hi": "F10 से F10 कीज इम्यूलेशन टाइप को टॉगल करें", "ja": "F1からF10キーのエミュレーションタイプを切り替えます", + "ko": "F1 ~ F10 키 에뮬레이션 유형 전환", "nl": "Schakel het emulatietype van F1 naar F10 toetsen", "pt": "Alterna o tipo de emulação de teclas F1 a F10", "ru": "Переключить тип эмуляции клавиш F1 - F10", + "zh-chs": "切換F1至F10鍵仿真類型", "xloc": [ "default.handlebars->container->column_l->p12->termTable->1->1->6->1->1->terminalSettingsButtons" ] @@ -17692,10 +24384,14 @@ "de": "Ansichtsmodus umschalten", "en": "Toggle View Mode", "es": "Cambiar modo de vista", + "fr": "Basculer le mode d'affichage", + "hi": "टॉगल देखें मोड", "ja": "表示モードの切り替え", + "ko": "보기 모드 전환", "nl": "Schakel weergavemodus", "pt": "Alternar modo de exibição", "ru": "Переключить вид", + "zh-chs": "切換查看模式", "xloc": [ "default.handlebars->container->column_l->p11->deskarea0->deskarea1->1", "player.handlebars->p11->deskarea0->deskarea1->1" @@ -17706,10 +24402,14 @@ "de": "Fokusmodus ein-/ausschalten; wenn aktiv, wird nur die Region um die Maus aktualisiert", "en": "Toggle focus mode, when active only the region around the mouse is updated", "es": "Alternar el modo de enfoque, cuando está activo solo se actualiza la región alrededor del mouse", + "fr": "Basculer le mode de mise au point, lorsqu'il est actif, seule la région autour de la souris est mise à jour", + "hi": "फोकस मोड को टॉगल करें, जब सक्रिय केवल माउस के आसपास के क्षेत्र को अपडेट किया जाता है", "ja": "フォーカスモードを切り替えます。アクティブな場合、マウス周辺の領域のみが更新されます。", + "ko": "마우스 주변 영역 만 활성화되면 포커스 모드 전환", "nl": "Schakel focusmodus in, indien actief wordt alleen het gebied rond de muis bijgewerkt", "pt": "Alternar modo de foco, quando ativo, apenas a região ao redor do mouse é atualizada", "ru": "Переключить режим фокусировки, когда активно обновление только области вокруг мыши", + "zh-chs": "切換焦點模式,激活後僅更新鼠標周圍的區域", "xloc": [ "default.handlebars->container->column_l->p11->deskarea0->deskarea1->1" ] @@ -17719,8 +24419,14 @@ "de": "Fußzeile ein-/ausschalten", "en": "Toggle footer bar", "es": "Alternar barra de pie de página", + "fr": "Changer le pied de page", + "hi": "टॉगल फुटर बार", + "ja": "フッターバーの切り替え", + "ko": "바닥 글 바 전환", "nl": "Schakel de voettekstbalk in", + "pt": "Alternar barra de rodapé", "ru": "Переключить нижнюю панель", + "zh-chs": "切換頁腳欄", "xloc": [ "default.handlebars->container->topbar->1->1->uiMenuButton->uiMenu" ] @@ -17731,10 +24437,13 @@ "en": "Toggle mouse and keyboard input", "es": "Alternar entrada de mouse y teclado", "fr": "Basculer la souris et le clavier", + "hi": "माउस और कीबोर्ड इनपुट टॉगल करें", "ja": "マウスとキーボードの入力を切り替える", + "ko": "마우스 및 키보드 입력 토글", "nl": "Schakelen tussen muis- en toetsenbordinvoer", "pt": "Alternar entrada de mouse e teclado", "ru": "Разрешить мышь и ввод с клавиатуры", + "zh-chs": "切換鼠標和鍵盤輸入", "xloc": [ "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->9" ] @@ -17745,14 +24454,18 @@ "en": "Toggle night mode", "es": "Alternar modo nocturno", "fr": "Basculer mode nuit", + "hi": "रात मोड टॉगल करें", "ja": "ナイトモードを切り替える", + "ko": "야간 모드 전환", "nl": "Wissel dag/nachtmodus", "pt": "Alternar modo noturno", "ru": "Переключить ночной режим", + "zh-chs": "切換夜間模式", "xloc": [ "agentinvite.handlebars->container->topbar->uiMenuButton->uiMenu", "default.handlebars->container->topbar->1->1->uiMenuButton->uiMenu", "error404.handlebars->container->topbar->uiMenuButton->uiMenu", + "invite.handlebars->container->topbar->uiMenuButton->uiMenu", "login.handlebars->container->topbar->uiMenuButton->uiMenu", "terms.handlebars->container->topbar->uiMenuButton->uiMenu" ] @@ -17762,9 +24475,14 @@ "de": "Hintergrundbild des entfernten Desktops ein-/ausschalten", "en": "Toggle remote desktop background", "es": "Alternar fondo de escritorio remoto", + "fr": "Changer l'arrière plan du bureau distant", + "hi": "दूरस्थ डेस्कटॉप पृष्ठभूमि टॉगल करें", "ja": "リモートデスクトップの背景を切り替える", + "ko": "원격 데스크톱 배경 전환", "nl": "Wissel bureaubladachtergrond op afstand in", + "pt": "Alternar plano de fundo da área de trabalho remota", "ru": "Переключить фон удаленного рабочего стола", + "zh-chs": "切換遠程桌面背景", "xloc": [ "default.handlebars->container->column_l->p11->deskarea0->deskarea4->1" ] @@ -17775,10 +24493,13 @@ "en": "Toggle terminal emulation type", "es": "Cambiar el tipo de emulación de terminal", "fr": "Basculer le type d'émulation de terminal", + "hi": "टर्मिनल एमुलेशन टाइप टॉगल करें", "ja": "ターミナルエミュレーションタイプの切り替え", + "ko": "터미널 에뮬레이션 유형 전환", "nl": "Schakel het type terminal emulatie in", "pt": "Alternar tipo de emulação de terminal", "ru": "Переключить тип эмуляции терминала", + "zh-chs": "切換終端仿真類型", "xloc": [ "default.handlebars->container->column_l->p12->termTable->1->1->6->1->1->terminalSettingsButtons" ] @@ -17788,10 +24509,14 @@ "de": "Werkzeug-Ansicht ein-/ausschalten", "en": "Toggle tools view", "es": "Alternar vista de herramientas", + "fr": "Basculer la vue des outils", + "hi": "टॉगल उपकरण देखें", "ja": "ツールビューの切り替え", + "ko": "도구보기 전환", "nl": "Schakel hulpmiddelenweergave in", "pt": "Alternar visualização de ferramentas", "ru": "Переключить вид инструментов", + "zh-chs": "切換工具視圖", "xloc": [ "default.handlebars->container->column_l->p11->deskarea0->deskarea4->1" ] @@ -17801,10 +24526,14 @@ "de": "Umschalten, was Return-Taste sendet", "en": "Toggle what the return key will send", "es": "Alternar lo que enviará la tecla de retorno", + "fr": "Inverser ce que la touche retour enverra", + "hi": "रिटर्न कुंजी को टॉगल करें", "ja": "リターンキーが送信するものを切り替える", + "ko": "리턴 키가 보낼 것을 토글", "nl": "Wissel wat de return toets zal verzenden", "pt": "Alterne o que a chave de retorno enviará", "ru": "Поменять функцию клавиши ввода", + "zh-chs": "切換返回鍵將發送的內容", "xloc": [ "default.handlebars->container->column_l->p12->termTable->1->1->6->1->1->terminalSettingsButtons" ] @@ -17815,10 +24544,13 @@ "en": "Tools", "es": "Herramientas", "fr": "Outils", + "hi": "उपकरण", "ja": "道具", + "ko": "도구", "nl": "Gereedschap", "pt": "Ferramentas", "ru": "Инструменты", + "zh-chs": "工具類", "xloc": [ "default.handlebars->container->column_l->p11->deskarea0->deskarea4->1" ] @@ -17828,14 +24560,19 @@ "de": "Oberfläche mit Leiste oben", "en": "Top bar interface", "es": "Interfaz de barra superior", + "fr": "Interface de la barre supérieure", + "hi": "शीर्ष बार इंटरफ़ेस", "ja": "トップバーインターフェース", + "ko": "상단 바 인터페이스", "nl": "Boven werkbalk interface", "pt": "Interface da barra superior", "ru": "Панель инструментов сверху", + "zh-chs": "頂欄界面", "xloc": [ "agentinvite.handlebars->container->topbar->uiMenuButton->uiMenu", "default.handlebars->container->topbar->1->1->uiMenuButton->uiMenu", "error404.handlebars->container->topbar->uiMenuButton->uiMenu", + "invite.handlebars->container->topbar->uiMenuButton->uiMenu", "login.handlebars->container->topbar->uiMenuButton->uiMenu", "terms.handlebars->container->topbar->uiMenuButton->uiMenu" ] @@ -17845,12 +24582,16 @@ "de": "Thema", "en": "Topic", "es": "Tema", + "fr": "Sujet", + "hi": "विषय", "ja": "トピック", + "ko": "이야기", "nl": "Onderwerp", "pt": "Tema", "ru": "Тема", + "zh-chs": "話題", "xloc": [ - "default.handlebars->25->553" + "default.handlebars->27->600" ] }, { @@ -17859,10 +24600,13 @@ "en": "Trace", "es": "Traza", "fr": "Trace", + "hi": "निशान", "ja": "トレース", + "ko": "자취", "nl": "Traceer", "pt": "Vestígio", "ru": "Трассировка", + "zh-chs": "跟踪", "xloc": [ "default.handlebars->container->topbar->1->1->ServerSubMenuSpan->ServerSubMenu->1->0->ServerTrace" ] @@ -17872,10 +24616,14 @@ "de": "Tracing", "en": "Tracing", "es": "Rastreo", + "fr": "Tracer", + "hi": "ट्रेसिंग", "ja": "トレース", + "ko": "트레이싱", "nl": "traceren", "pt": "Rastreamento", "ru": "Трассирование", + "zh-chs": "追踪", "xloc": [ "default.handlebars->container->column_l->p41->3->3" ] @@ -17885,12 +24633,16 @@ "de": "Trafficrouter verwendet, um zu einem Gerät über diesen Server zu verbinden", "en": "Traffic router used to connect to a device thru this server", "es": "Enrutador de tráfico utilizado para conectarse a un dispositivo a través de este servidor", + "fr": "Routeur de trafic utilisé pour se connecter à un appareil via ce serveur", + "hi": "ट्रैफ़िक राउटर इस सर्वर के माध्यम से एक डिवाइस से कनेक्ट करने के लिए उपयोग किया जाता है", "ja": "このサーバーを介してデバイスに接続するために使用されるトラフィックルーター", + "ko": "이 서버를 통해 장치에 연결하는 데 사용되는 트래픽 라우터", "nl": "Verkeersrouter gebruikt om verbinding te maken met een apparaat via deze server", "pt": "Roteador de tráfego usado para conectar-se a um dispositivo através deste servidor", "ru": "Router используется для подключения к различным портам устройства через этот сервер", + "zh-chs": "用於通過此服務器連接到設備的流量路由器", "xloc": [ - "default.handlebars->25->508" + "default.handlebars->27->515" ] }, { @@ -17898,60 +24650,80 @@ "de": "Versuchen Sie es erneut.", "en": "Try again.", "es": "Intenta nuevamente.", + "fr": "Essayer à nouveau.", + "hi": "पुनः प्रयास करें।", "ja": "再試行する。", + "ko": "다시 시도하십시오.", "nl": "Probeer opnieuw", "pt": "Tente novamente.", "ru": "Попытайтесь снова.", + "zh-chs": "再試一次。", "xloc": [ - "default.handlebars->25->131" + "default.handlebars->27->114" ] }, { "cs": "Tsonga", "de": "Tsonga", "en": "Tsonga", + "fr": "Tsonga", + "hi": "सोंगा", "ja": "ツォンガ", + "ko": "손가", "nl": "Tsonga", "pt": "Tsonga", "ru": "Тсонга", + "zh-chs": "特松加", "xloc": [ - "default.handlebars->25->903" + "default.handlebars->27->1007" ] }, { "cs": "setswanština", "de": "Tswana", "en": "Tswana", + "fr": "Tswana", + "hi": "सेत्स्वाना", "ja": "ツワナ", + "ko": "츠와 나", "nl": "Tswana", "pt": "Tswana", "ru": "Тсвана", + "zh-chs": "茨瓦納", "xloc": [ - "default.handlebars->25->904" + "default.handlebars->27->1008" ] }, { "cs": "turečtina", "de": "Türkisch", "en": "Turkish", + "fr": "turc", + "hi": "तुर्की", "ja": "トルコ語", + "ko": "터키어", "nl": "Turks", "pt": "turco", "ru": "Турецкий", + "zh-chs": "土耳其", "xloc": [ - "default.handlebars->25->905" + "default.handlebars->27->1009" ] }, { "cs": "turkmenština", "de": "Turkmenisch", "en": "Turkmen", + "fr": "Turkmène", + "hi": "तुक्रमेन", "ja": "トルクメン", + "ko": "투르크멘 말", "nl": "Turkmeens", "pt": "Turcomano", "ru": "Туркменский", + "zh-chs": "土庫曼人", "xloc": [ - "default.handlebars->25->906" + "default.handlebars->27->1010" ] }, { @@ -17959,12 +24731,16 @@ "de": "Zweifaktor-Authentifizierung", "en": "Two factor authentication", "es": "Autenticación de dos factores", + "fr": "Authentification à double facteur", + "hi": "दो तरीकों से प्रमाणीकरण", "ja": "二要素認証", + "ko": "이중 인증", "nl": "Twee-factor authenticatie", "pt": "Autenticação de dois fatores", "ru": "Двухфакторная аутентификация", + "zh-chs": "兩要素認證", "xloc": [ - "default.handlebars->25->50" + "default.handlebars->27->50" ] }, { @@ -17972,32 +24748,40 @@ "de": "Tippen", "en": "Type", "es": "Tipo", + "fr": "Type", + "hi": "प्रकार", "ja": "タイプ", + "ko": "유형", "nl": "Type", "pt": "Tipo", "ru": "Удаленный ввод", + "zh-chs": "類型", "xloc": [ - "default-mobile.handlebars->9->279", - "default-mobile.handlebars->9->57", - "default.handlebars->25->1037", - "default.handlebars->25->1040", - "default.handlebars->25->627", - "default.handlebars->25->956", - "default.handlebars->25->985", + "default-mobile.handlebars->9->283", + "default-mobile.handlebars->9->60", + "default.handlebars->27->1061", + "default.handlebars->27->1090", + "default.handlebars->27->1141", + "default.handlebars->27->1144", + "default.handlebars->27->676", "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3" ] }, { - "cs": "Zadejte název klíče, vyberte kolonku OTP a stiskněte tlačítko na YubiKey™.", + "cs": "Zadejte název klíče, vyberte kolonku OTP a stiskněte tlačítko na YubiKey™.", "de": "Geben Sie einen Schlüsselnamen ein, wählen Sie OTP und drücken Sie die Taste an Ihrem YubiKey™.", "en": "Type in a key name, select the OTP box and press the button on the YubiKey™.", - "es": "Escriba la clave, seleccione el cuadro OTP y presione el botón en YubiKey & trade;.", - "ja": "キー名を入力し、OTPボックスを選択して、YubiKey&trade;のボタンを押します。", - "nl": "Typ een sleutelnaam, selecteer het vak OTP en druk op de knop op de YubiKey™.", - "pt": "Digite um nome de chave, selecione a caixa OTP e pressione o botão no YubiKeytrade;.", + "es": "Escriba la clave, seleccione el cuadro OTP y presione el botón en YubiKey™.", + "fr": "Tapez un nom de clé, sélectionnez la case OTP et appuyez sur le bouton de la YubiKey™.", + "hi": "एक प्रमुख नाम टाइप करें, OTP बॉक्स चुनें और YubiKey™ पर बटन दबाएँ।", + "ja": "キー名を入力し、OTPボックスを選択して、YubiKey™ のボタンを押します。", + "ko": "키 이름을 입력하고 OTP 상자를 선택한 다음 YubiKey™ 의 단추를 누르십시오.", + "nl": "Typ een sleutelnaam, selecteer het vak OTP en druk op de knop op de YubiKey™.", + "pt": "Digite um nome de chave, selecione a caixa OTP e pressione o botão no YubiKey™.", "ru": "Введите имя ключа, выберите поле OTP и нажмите кнопку на YubiKey™.", + "zh-chs": "輸入密鑰名稱,選擇OTP框,然後按YubiKey™上的按鈕。", "xloc": [ - "default.handlebars->25->715" + "default.handlebars->27->819" ] }, { @@ -18005,12 +24789,16 @@ "de": "Geben Sie den Namen des hinzuzufügenden Schlüssels ein.", "en": "Type in the name of the key to add.", "es": "Escriba el nombre de la clave para agregar.", + "fr": "Saisissez un nom pour la clé puis cliquez sur Ok.", + "hi": "जोड़ने के लिए कुंजी के नाम में टाइप करें।", "ja": "追加するキーの名前を入力します。", + "ko": "추가 할 키 이름을 입력하십시오.", "nl": "Typ de naam van de sleutel die u wilt toevoegen.", "pt": "Digite o nome da chave a ser adicionada.", "ru": "Введите имя ключа для добавления.", + "zh-chs": "輸入要添加的密鑰的名稱。", "xloc": [ - "default.handlebars->25->712" + "default.handlebars->27->816" ] }, { @@ -18019,12 +24807,15 @@ "en": "UTF8 Terminal", "es": "Terminal UTF8", "fr": "Terminal UTF8", + "hi": "UTF8 टर्मिनल", "ja": "UTF8ターミナル", + "ko": "UTF8 터미널", "nl": "UTF8 Terminal", "pt": "Terminal UTF8", "ru": "Терминал UTF8", + "zh-chs": "UTF8終端", "xloc": [ - "default.handlebars->25->638" + "default.handlebars->27->687" ] }, { @@ -18032,12 +24823,16 @@ "de": "Ukrainisch", "en": "Ukrainian", "es": "Ucraniano", + "fr": "ukrainien", + "hi": "यूक्रेनी", "ja": "ウクライナ語", + "ko": "우크라이나 인", "nl": "Oekraïens", "pt": "ucraniano", "ru": "Украинский", + "zh-chs": "烏克蘭", "xloc": [ - "default.handlebars->25->907" + "default.handlebars->27->1011" ] }, { @@ -18045,13 +24840,17 @@ "de": "Auf Geräte kann nicht zugegriffen werden, bis die E-Mail-Adresse verifiziert wurde. Dies wird für eine Passwort-Wiederherstellung benötigt. Gehen Sie auf den \\\"Mein Konto\\\"-Tab, um Ihre E-Mail-Adresse zu ändern und zu verifizieren.", "en": "Unable to access a device until a email address is verified. This is required for password recovery. Go to the \\\"My Account\\\" tab to change and verify an email address.", "es": "No se puede acceder a un dispositivo hasta que se verifique una dirección de correo electrónico. Esto es necesario para la recuperación de contraseña. Vaya a la pestaña \\\"Mi cuenta\\\" para cambiar y verificar una dirección de correo electrónico.", + "fr": "Les appareils sont inaccessibles tant que l'email n'est pas vérifié. Cette action est nécessaire pour la récupération des mots de passe. Allez dans \\\"Mon compte\\\" pour vérifier l'adresse mail.", + "hi": "ईमेल पता सत्यापित होने तक डिवाइस तक पहुंचने में असमर्थ। पासवर्ड रिकवरी के लिए यह आवश्यक है। ईमेल पता बदलने और सत्यापित करने के लिए \\\"मेरा खाता \\\" टैब पर जाएं।", "ja": "メールアドレスが確認されるまでデバイスにアクセスできません。これはパスワードの回復に必要です。 [マイアカウント]タブに移動して、メールアドレスを変更および確認します。", + "ko": "이메일 주소가 확인 될 때까지 장치에 액세스 할 수 없습니다. 비밀번호 복구에 필요합니다. \\\"내 계정 \\\"탭으로 이동하여 이메일 주소를 변경하고 확인하십시오.", "nl": "Geen toegang tot een apparaat totdat een e-mailadres is geverifieerd. Dit is vereist voor wachtwoordherstel. Ga naar het tabblad \\\"Mijn account\\\" om een e-mailadres te wijzigen en te verifiëren.", "pt": "Não foi possível acessar um dispositivo até que um endereço de email seja verificado. Isso é necessário para a recuperação de senha. Vá para a guia \\\"Minha conta\\\" para alterar e verificar um endereço de email.", "ru": "Невозможно получить доступ к устройству, пока адрес email не подтвержден. Это необходимо для восстановления пароля. Перейдите на вкладку \\\"Моя учетная запись\\\", чтобы изменить и подтвердить адрес email.", + "zh-chs": "在驗證電子郵件地址之前,無法訪問設備。這是密碼恢復所必需的。轉到“我的帳戶”標籤以更改和驗證電子郵件地址。", "xloc": [ - "default.handlebars->25->436", - "default.handlebars->25->951" + "default.handlebars->27->1056", + "default.handlebars->27->440" ] }, { @@ -18059,13 +24858,17 @@ "de": "Auf Geräte kann nicht zugegriffen werden, bis die E-Mail-Adresse verifiziert wurde. Dies wird für eine Passwort-Wiederherstellung benötigt. Gehen Sie auf \\\"Mein Konto\\\", um Ihre E-Mail-Adresse zu ändern und zu verifizieren.", "en": "Unable to access a device until a email address is verified. This is required for password recovery. Go to the \\\"My Account\\\" to change and verify an email address.", "es": "No se puede acceder a un dispositivo hasta que se verifique una dirección de correo electrónico. Esto es necesario para la recuperación de contraseña. Vaya a \\\"Mi cuenta\\\" para cambiar y verificar una dirección de correo electrónico.", + "fr": "Les appareils sont inaccessibles tant que l'email n'est pas vérifié. Cette action est nécessaire pour la récupération des mots de passe. Allez dans \\\"Mon compte\\\" pour vérifier l'adresse mail.", + "hi": "ईमेल पता सत्यापित होने तक डिवाइस तक पहुंचने में असमर्थ। पासवर्ड रिकवरी के लिए यह आवश्यक है। ईमेल पता बदलने और सत्यापित करने के लिए \\\"मेरा खाता \\\" पर जाएं।", "ja": "メールアドレスが確認されるまでデバイスにアクセスできません。これはパスワードの回復に必要です。 「マイアカウント」に移動して、メールアドレスを変更および確認します。", + "ko": "이메일 주소가 확인 될 때까지 장치에 액세스 할 수 없습니다. 비밀번호 복구에 필요합니다. 이메일 주소를 변경하고 확인하려면 \\\"내 계정 \\\"으로 이동하십시오.", "nl": "Geen toegang tot een apparaat totdat een e-mailadres is geverifieerd. Dit is vereist voor wachtwoordherstel. Ga naar de \\\"Mijn account\\\" om een e-mailadres te wijzigen en te verifiëren.", "pt": "Não foi possível acessar um dispositivo até que um endereço de email seja verificado. Isso é necessário para a recuperação de senha. Vá para \\\"Minha conta\\\" para alterar e verificar um endereço de email.", "ru": "Невозможно получить доступ к устройству, пока адрес email не подтвержден. Это необходимо для восстановления пароля. Перейдите в раздел \\\"Моя учетная запись\\\", чтобы изменить и подтвердить адрес email.", + "zh-chs": "在驗證電子郵件地址之前,無法訪問設備。這是密碼恢復所必需的。轉到“我的帳戶”以更改並驗證電子郵件地址。", "xloc": [ - "default-mobile.handlebars->9->130", - "default-mobile.handlebars->9->53" + "default-mobile.handlebars->9->134", + "default-mobile.handlebars->9->56" ] }, { @@ -18073,13 +24876,17 @@ "de": "Auf Geräte kann nicht zugegriffen werden, bis Zweifaktor-Authentifizierung eingeschaltet wurde. Dies wird als Sicherheitsmaßnahme vorausgesetzt. Gehen Sie auf \\\"Mein Konto\\\" und sehen Sie sich die \\\"Kontosicherheit\\\"-Sektion an.", "en": "Unable to access a device until two-factor authentication is enabled. This is required for extra security. Go to the \\\"My Account\\\" and look at the \\\"Account Security\\\" section.", "es": "No se puede acceder a un dispositivo hasta que se habilita la autenticación de dos factores. Esto es necesario para mayor seguridad. Vaya a \\\"Mi cuenta\\\" y mire la sección \\\"Seguridad de la cuenta\\\".", + "fr": "Impossible d'accéder à un périphérique tant que l'authentification à deux facteurs n'est pas activée. Ceci est nécessaire pour plus de sécurité. Allez dans \\\"Mon compte\\\" et regardez la section \\\"Sécurité du compte\\\".", + "hi": "दो-कारक प्रमाणीकरण सक्षम होने तक डिवाइस तक पहुंचने में असमर्थ। अतिरिक्त सुरक्षा के लिए यह आवश्यक है। \\\"मेरा खाता \\\" पर जाएं और \\\"खाता सुरक्षा \\\" अनुभाग देखें।", "ja": "二要素認証が有効になるまでデバイスにアクセスできません。これは、追加のセキュリティのために必要です。 「マイアカウント」に移動して、「アカウントセキュリティ」セクションを確認します。", + "ko": "이중 인증이 활성화 될 때까지 장치에 액세스 할 수 없습니다. 추가 보안을 위해 필요합니다. \\\"내 계정 \\\"으로 이동하여 \\\"계정 보안 \\\"섹션을보십시오.", "nl": "Geen toegang tot een apparaat totdat tweefactorauthenticatie is ingeschakeld. Dit is vereist voor extra beveiliging. Ga naar de \\\"Mijn account\\\" en bekijk het gedeelte \\\"Accountbeveiliging\\\".", "pt": "Não foi possível acessar um dispositivo até que a autenticação de dois fatores esteja ativada. Isso é necessário para segurança extra. Vá para \\\"Minha conta\\\" e veja a seção \\\"Segurança da conta\\\".", "ru": "Невозможно получить доступ к устройству, пока не включена двухфакторная аутентификация. Это требуется для дополнительной безопасности. Перейдите в раздел \\\"Моя учетная запись\\\" и посмотрите \\\"Безопасность учетной записи\\\".", + "zh-chs": "在啟用兩因素身份驗證之前,無法訪問設備。這是額外的安全性所必需的。轉到“我的帳戶”,然後查看“帳戶安全性”部分。", "xloc": [ - "default-mobile.handlebars->9->132", - "default-mobile.handlebars->9->55" + "default-mobile.handlebars->9->136", + "default-mobile.handlebars->9->58" ] }, { @@ -18087,13 +24894,17 @@ "de": "Auf Geräte kann nicht zugegriffen werden, bis Zweifaktor-Authentifizierung eingeschaltet wurde. Dies wird als Sicherheitsmaßnahme vorausgesetzt. Gehen Sie auf den \\\"Mein Konto\\\"-Tab und sehen Sie sich die \\\"Kontosicherheit\\\"-Sektion an.", "en": "Unable to access a device until two-factor authentication is enabled. This is required for extra security. Go to the \\\"My Account\\\" tab and look at the \\\"Account Security\\\" section.", "es": "No se puede acceder a un dispositivo hasta que se habilita la autenticación de dos factores. Esto es necesario para mayor seguridad. Vaya a la pestaña \\\"Mi cuenta\\\" y mire la sección \\\"Seguridad de la cuenta\\\".", + "fr": "Impossible d'accéder à un périphérique tant que l'authentification à deux facteurs n'est pas activée. Ceci est nécessaire pour plus de sécurité. Accédez à l'onglet \\\"Mon compte\\\" et consultez la section \\\"Sécurité du compte\\\".", + "hi": "दो-कारक प्रमाणीकरण सक्षम होने तक डिवाइस तक पहुंचने में असमर्थ। अतिरिक्त सुरक्षा के लिए यह आवश्यक है। \\\"मेरा खाता \\\" टैब पर जाएं और \\\"खाता सुरक्षा \\\" अनुभाग देखें।", "ja": "二要素認証が有効になるまでデバイスにアクセスできません。これは、追加のセキュリティのために必要です。 [マイアカウント]タブに移動して、[アカウントセキュリティ]セクションを確認します。", + "ko": "이중 인증이 활성화 될 때까지 장치에 액세스 할 수 없습니다. 추가 보안을 위해 필요합니다. \\\"내 계정 \\\"탭으로 이동하여 \\\"계정 보안 \\\"섹션을 확인하십시오.", "nl": "Geen toegang tot een apparaat totdat tweefactorauthenticatie is ingeschakeld. Dit is vereist voor extra beveiliging. Ga naar het tabblad \\\"Mijn account\\\" en bekijk het gedeelte \\\"Accountbeveiliging\\\".", "pt": "Não foi possível acessar um dispositivo até que a autenticação de dois fatores esteja ativada. Isso é necessário para segurança extra. Vá para a guia \\\"Minha conta\\\" e consulte a seção \\\"Segurança da conta\\\".", "ru": "Невозможно получить доступ к устройству, пока не включена двухфакторная аутентификация. Это требуется для дополнительной безопасности. Перейдите на вкладку \\\"Моя учетная запись\\\" и посмотрите \\\"Безопасность учетной записи\\\".", + "zh-chs": "在啟用兩因素身份驗證之前,無法訪問設備。這是額外的安全性所必需的。轉到“我的帳戶”標籤,然後查看“帳戶安全性”部分。", "xloc": [ - "default.handlebars->25->438", - "default.handlebars->25->953" + "default.handlebars->27->1058", + "default.handlebars->27->442" ] }, { @@ -18101,13 +24912,17 @@ "de": "Web-Socket kann nicht verbunden werden", "en": "Unable to connect web socket", "es": "No se puede conectar al web socket.", + "fr": "Impossible de se connecter à la web socket", + "hi": "वेब सॉकेट कनेक्ट करने में असमर्थ", "ja": "Webソケットに接続できません", + "ko": "웹 소켓을 연결할 수 없습니다", "nl": "Kan geen websocket aansluiten", "pt": "Não foi possível conectar o soquete da web", "ru": "Невозможно подключить веб-сокет", + "zh-chs": "無法連接網絡套接字", "xloc": [ "default-mobile.handlebars->9->8", - "default.handlebars->25->48" + "default.handlebars->27->48" ] }, { @@ -18115,12 +24930,17 @@ "de": "Konto kann nicht anlegen werden", "en": "Unable to create account.", "es": "No se puede crear una cuenta.", + "fr": "Impossible de créer le compte", + "hi": "खाता बनाने में असमर्थ।", "ja": "アカウントを作成できません。", + "ko": "계정을 만들 수 없습니다.", "nl": "Kan geen account maken.", + "pt": "Não foi possível criar a conta.", "ru": "Невозможно создать учетную запись.", + "zh-chs": "無法創建帳戶。", "xloc": [ - "login-mobile.handlebars->5->2", - "login.handlebars->5->2" + "login-mobile.handlebars->5->3", + "login.handlebars->5->3" ] }, { @@ -18128,13 +24948,17 @@ "de": "Authentifizierung kann nicht durchgeführt werden", "en": "Unable to perform authentication", "es": "No se puede realizar la autenticación", + "fr": "Impossible d'effectuer l'authentification", + "hi": "प्रमाणीकरण करने में असमर्थ", "ja": "認証を実行できません", + "ko": "인증을 수행 할 수 없습니다", "nl": "Kan authenticatie niet uitvoeren", "pt": "Não foi possível executar a autenticação", "ru": "Невозможно выполнить аутентификацию", + "zh-chs": "無法執行身份驗證", "xloc": [ "default-mobile.handlebars->9->7", - "default.handlebars->25->47" + "default.handlebars->27->47" ] }, { @@ -18142,12 +24966,16 @@ "de": "Dieser Adressbereich kann nicht gescannt werden.", "en": "Unable to scan this address range.", "es": "No se puede escanear este rango de direcciones.", + "fr": "Impossible de scanner la plage d'adresse IP.", + "hi": "इस पता श्रेणी को स्कैन करने में असमर्थ।", "ja": "このアドレス範囲をスキャンできません。", + "ko": "이 주소 범위를 스캔 할 수 없습니다.", "nl": "Kan dit adresbereik niet scannen.", "pt": "Não foi possível verificar este intervalo de endereços.", "ru": "Невозможно отсканировать этот диапазон адресов.", + "zh-chs": "無法掃描該地址範圍。", "xloc": [ - "default.handlebars->25->162" + "default.handlebars->27->145" ] }, { @@ -18155,12 +24983,17 @@ "de": "E-Mail kann nicht gesendet werden.", "en": "Unable to sent email.", "es": "No se puede enviar el correo electrónico.", + "fr": "Impossible d'envoyer le mail.", + "hi": "ईमेल भेजने में असमर्थ।", "ja": "メールを送信できません。", + "ko": "이메일을 보낼 수 없습니다.", "nl": "Kan geen e-mail verzenden.", + "pt": "Não foi possível enviar o email.", "ru": "Не удалось отправить email.", + "zh-chs": "無法發送電子郵件。", "xloc": [ - "login-mobile.handlebars->5->11", - "login.handlebars->5->11" + "login-mobile.handlebars->5->12", + "login.handlebars->5->12" ] }, { @@ -18168,12 +25001,19 @@ "de": "Deinstallation", "en": "Uninstall", "es": "Desinstalar", + "fr": "Désinstaller", + "hi": "स्थापना रद्द करें", "ja": "アンインストール", + "ko": "제거", "nl": "deinstallatie", + "pt": "Desinstalar", "ru": "Удаление", + "zh-chs": "卸載", "xloc": [ - "default-mobile.handlebars->9->326", - "default.handlebars->25->1130" + "default-mobile.handlebars->9->330", + "default.handlebars->27->1243", + "default.handlebars->27->555", + "default.handlebars->27->574" ] }, { @@ -18181,14 +25021,19 @@ "de": "Agenten deinstallieren", "en": "Uninstall Agent", "es": "Desinstalar Agente", + "fr": "Désinstaller l'agent", + "hi": "एजेंट को अनइंस्टॉल करें", "ja": "エージェントのアンインストール", + "ko": "에이전트 제거", "nl": "deinstallatie agent", + "pt": "Desinstalar agente", "ru": "Удаление агента", + "zh-chs": "卸載代理", "xloc": [ - "default-mobile.handlebars->9->308", - "default.handlebars->25->1107", - "default.handlebars->25->384", - "default.handlebars->25->541" + "default-mobile.handlebars->9->312", + "default.handlebars->27->1215", + "default.handlebars->27->374", + "default.handlebars->27->588" ] }, { @@ -18196,11 +25041,16 @@ "de": "Agenten deinstallieren", "en": "Uninstall agent", "es": "Desinstalar agente", + "fr": "Désinstaller l'agent", + "hi": "एजेंट को अनइंस्टॉल करें", "ja": "エージェントをアンインストールする", + "ko": "에이전트 제거", "nl": "deinstallatie agent", + "pt": "Desinstalar agente", "ru": "Удалить агент", + "zh-chs": "卸載代理", "xloc": [ - "default.handlebars->25->561" + "default.handlebars->27->608" ] }, { @@ -18209,22 +25059,27 @@ "en": "Unknown", "es": "Desconocido", "fr": "Inconnue", + "hi": "अनजान", "ja": "未知の", + "ko": "알 수 없는", "nl": "Onbekend", "pt": "Desconhecido", "ru": "Неизвестно", + "zh-chs": "未知", "xloc": [ - "default-mobile.handlebars->9->126", - "default-mobile.handlebars->9->143", - "default-mobile.handlebars->9->171", - "default-mobile.handlebars->9->172", - "default.handlebars->25->108", - "default.handlebars->25->109", - "default.handlebars->25->13", - "default.handlebars->25->1382", - "default.handlebars->25->380", - "default.handlebars->25->41", - "default.handlebars->25->42" + "default-mobile.handlebars->9->130", + "default-mobile.handlebars->9->147", + "default-mobile.handlebars->9->175", + "default-mobile.handlebars->9->176", + "default.handlebars->27->13", + "default.handlebars->27->1528", + "default.handlebars->27->370", + "default.handlebars->27->41", + "default.handlebars->27->42", + "default.handlebars->27->763", + "default.handlebars->27->770", + "default.handlebars->27->91", + "default.handlebars->27->92" ] }, { @@ -18233,13 +25088,16 @@ "en": "Unknown #{0}", "es": "Desconocido # {0}", "fr": " #{0} Inconnue", + "hi": "अज्ञात # {0}", "ja": "不明な#{0}", + "ko": "알 수없는 # {0}", "nl": "Onbekend #{0}", "pt": "Desconhecido # {0}", "ru": "Неизвестно #{0}", + "zh-chs": "未知#{0}", "xloc": [ - "default-mobile.handlebars->9->273", - "default.handlebars->25->979" + "default-mobile.handlebars->9->277", + "default.handlebars->27->1084" ] }, { @@ -18247,10 +25105,32 @@ "de": "Unbekannte Aktion", "en": "Unknown Action", "es": "Acción desconocida", + "fr": "Action inconnue", + "hi": "अज्ञात क्रिया", + "ja": "不明なアクション", + "ko": "알 수없는 동작", "nl": "Onbekende actie", + "pt": "Ação desconhecida", "ru": "Неизвестное действие", + "zh-chs": "未知動作", "xloc": [ - "default.handlebars->25->1403" + "default.handlebars->27->1550" + ] + }, + { + "cs": "Neznámé zařízení", + "de": "Unbekanntes Gerät", + "en": "Unknown Device", + "fr": "Périphérique inconnu", + "hi": "अज्ञात यन्त्र", + "ja": "未知のディバイス", + "ko": "알려지지 않은 장치", + "nl": "Onbekend apparaat", + "pt": "Dispositivo desconhecido", + "ru": "Неизвестное устройство", + "zh-chs": "未知設備", + "xloc": [ + "default.handlebars->27->1508" ] }, { @@ -18258,12 +25138,18 @@ "de": "Unbekannte Gerätegruppe", "en": "Unknown Device Group", "es": "Grupo de dispositivos desconocido", + "fr": "Groupe d'appareil inconnu", + "hi": "अज्ञात उपकरण समूह", + "ja": "不明なデバイスグループ", + "ko": "알 수없는 장치 그룹", "nl": "Onbekende apparaatgroep", + "pt": "Grupo de dispositivos desconhecidos", "ru": "Неизвестная группа устройств", + "zh-chs": "未知設備組", "xloc": [ - "default.handlebars->25->1296", - "default.handlebars->25->1370", - "default.handlebars->25->1407" + "default.handlebars->27->1431", + "default.handlebars->27->1514", + "default.handlebars->27->1554" ] }, { @@ -18271,10 +25157,16 @@ "de": "Unbekannte Gruppe", "en": "Unknown Group", "es": "Grupo desconocido", + "fr": "Groupe inconnu", + "hi": "अज्ञात समूह", + "ja": "不明なグループ", + "ko": "알 수없는 그룹", "nl": "Onbekende groep", + "pt": "Grupo desconhecido", "ru": "Неизвестная группа", + "zh-chs": "未知群組", "xloc": [ - "default.handlebars->25->1399" + "default.handlebars->27->1546" ] }, { @@ -18283,13 +25175,16 @@ "en": "Unknown State", "es": "Estado desconocido", "fr": "Etat inconnu", + "hi": "अज्ञात राज्य", "ja": "不明な状態", + "ko": "알 수없는 상태", "nl": "Onbekende staat", "pt": "Estado desconhecido", "ru": "Состояние неизвестно", + "zh-chs": "未知狀態", "xloc": [ - "default-mobile.handlebars->9->178", - "default.handlebars->25->456" + "default-mobile.handlebars->9->182", + "default.handlebars->27->463" ] }, { @@ -18297,10 +25192,16 @@ "de": "Unbekannte Benutzergruppe", "en": "Unknown User Group", "es": "Grupo de usuarios desconocidos", + "fr": "Groupe utilisateurs inconnu", + "hi": "अज्ञात उपयोगकर्ता समूह", + "ja": "不明なユーザーグループ", + "ko": "알 수없는 사용자 그룹", "nl": "Onbekende gebruikersgroep", + "pt": "Grupo de usuários desconhecidos", "ru": "Неизвестная группа пользователей", + "zh-chs": "未知用戶組", "xloc": [ - "default.handlebars->25->1378" + "default.handlebars->27->1520" ] }, { @@ -18309,13 +25210,16 @@ "en": "Unknown Version & State", "es": "Versión y estado desconocido.", "fr": "Version et état inconnus", + "hi": "अज्ञात संस्करण और राज्य", "ja": "不明なバージョンと状態", + "ko": "알 수없는 버전 및 상태", "nl": "Onbekende versie en staat", "pt": "Estado da versão desconhecida", "ru": "Версия и состояние неизвестны", + "zh-chs": "未知版本和狀態", "xloc": [ - "default-mobile.handlebars->9->180", - "default.handlebars->25->458" + "default-mobile.handlebars->9->184", + "default.handlebars->27->465" ] }, { @@ -18324,14 +25228,17 @@ "en": "Unlimited", "es": "Ilimitado", "fr": "Illimité", + "hi": "असीमित", "ja": "無制限", + "ko": "제한 없는", "nl": "Ongelimiteerd", "pt": "Ilimitado", "ru": "Неограниченно", + "zh-chs": "無限", "xloc": [ - "default.handlebars->25->173", - "default.handlebars->25->297", - "default.handlebars->25->311" + "default.handlebars->27->156", + "default.handlebars->27->284", + "default.handlebars->27->298" ] }, { @@ -18340,10 +25247,13 @@ "en": "Up", "es": "Arriba", "fr": "Up", + "hi": "यूपी", "ja": "アップ", + "ko": "쪽으로", "nl": "Omhoog", "pt": "Acima", "ru": "Вверх", + "zh-chs": "上", "xloc": [ "default-mobile.handlebars->container->page_content->column_l->p10->p10files->p13toolbar->1->2->1->1", "default-mobile.handlebars->container->page_content->column_l->p5->p5myfiles->p5toolbar->1->0->1->1", @@ -18357,11 +25267,16 @@ "de": "Aktuell", "en": "Up to date", "es": "Actualizado", + "fr": "A jour", + "hi": "आधुनिक", "ja": "最新の", + "ko": "최신 정보", "nl": "Bijgewerkt", + "pt": "Atualizado", "ru": "Актуально", + "zh-chs": "最新", "xloc": [ - "default.handlebars->25->1460" + "default.handlebars->27->1611" ] }, { @@ -18370,10 +25285,13 @@ "en": "Upload", "es": "Subir", "fr": "Télécharger", + "hi": "डालना", "ja": "アップロードする", + "ko": "업로드", "nl": "Uploaden", "pt": "Envio", "ru": "Загрузить", + "zh-chs": "上載", "xloc": [ "default-mobile.handlebars->container->page_content->column_l->p10->p10files->p13toolbar->1->2->1->3", "default-mobile.handlebars->container->page_content->column_l->p5->p5myfiles->p5toolbar->1->0->1->3", @@ -18386,19 +25304,23 @@ "de": "Datei hochladen", "en": "Upload File", "es": "Subir Archivo", + "fr": "Envoyer un fichier", + "hi": "दस्तावेज अपलोड करें", "ja": "ファイルをアップロードする", + "ko": "파일 업로드", "nl": "Upload bestand", "pt": "Subir arquivo", "ru": "Загрузить файл", + "zh-chs": "上傳文件", "xloc": [ - "default-mobile.handlebars->9->253", - "default-mobile.handlebars->9->271", - "default-mobile.handlebars->9->85", - "default.handlebars->25->1182", - "default.handlebars->25->1190", - "default.handlebars->25->661", - "default.handlebars->25->684", - "default.handlebars->25->687", + "default-mobile.handlebars->9->257", + "default-mobile.handlebars->9->275", + "default-mobile.handlebars->9->88", + "default.handlebars->27->1312", + "default.handlebars->27->1320", + "default.handlebars->27->710", + "default.handlebars->27->733", + "default.handlebars->27->736", "default.handlebars->container->dialog->dialogBody->dialog3->d3localmode->1" ] }, @@ -18407,12 +25329,16 @@ "de": "Mesh-Agent-Kern hochladen", "en": "Upload Mesh Agent Core", "es": "Subir Mesh Agent Core", + "fr": "Importer le noyau de l'agent de maillage", + "hi": "मेष एजेंट कोर अपलोड करें", "ja": "メッシュエージェントコアのアップロード", + "ko": "메시 에이전트 코어 업로드", "nl": "Upload Mesh Agent Core", "pt": "Carregar núcleo do agente de malha", "ru": "Загрузить ядро Mesh Agent", + "zh-chs": "上傳網格代理核心", "xloc": [ - "default.handlebars->25->707" + "default.handlebars->27->808" ] }, { @@ -18420,12 +25346,16 @@ "de": "Kern-Datei hochladen", "en": "Upload a core file", "es": "Subir un archivo central", + "fr": "Téléchargez un fichier principal", + "hi": "एक कोर फ़ाइल अपलोड करें", "ja": "コアファイルをアップロードする", + "ko": "핵심 파일 업로드", "nl": "Upload een kernbestand", "pt": "Carregar um arquivo principal", "ru": "Загрузить файл ядра", + "zh-chs": "上載核心文件", "xloc": [ - "default.handlebars->25->704" + "default.handlebars->27->805" ] }, { @@ -18433,12 +25363,16 @@ "de": "Vorgabe-Serverkern hochladen", "en": "Upload default server core", "es": "Subir núcleo del servidor predeterminado", + "fr": "Télécharger le noyau du serveur par défaut", + "hi": "डिफ़ॉल्ट सर्वर कोर अपलोड करें", "ja": "デフォルトのサーバーコアをアップロードする", + "ko": "기본 서버 코어 업로드", "nl": "Upload standaard serverkern", "pt": "Carregar núcleo do servidor padrão", "ru": "Загрузить ядро по умолчанию с сервера ", + "zh-chs": "上載默認服務器核心", "xloc": [ - "default.handlebars->25->701" + "default.handlebars->27->802" ] }, { @@ -18446,12 +25380,16 @@ "de": "Wiederherstellungkern hochladen", "en": "Upload recovery core", "es": "Subir núcleo de recuperación", + "fr": "Télécharger le noyau de récupération", + "hi": "रिकवरी कोर अपलोड करें", "ja": "復旧コアをアップロードする", + "ko": "복구 코어 업로드", "nl": "Upload herstelkern", "pt": "Carregar núcleo de recuperação", "ru": "Загрузить ядро восстановления", + "zh-chs": "上傳恢復核心", "xloc": [ - "default.handlebars->25->703" + "default.handlebars->27->804" ] }, { @@ -18459,11 +25397,17 @@ "de": "Das Hochladen wird 1 Datei überschreiben. Fortfahren?", "en": "Upload will overwrite 1 file. Continue?", "es": "La carga sobrescribirá un archivo. ¿Continuar?", + "fr": "L'envoi écrasera 1 fichier. Continuer ?", + "hi": "अपलोड 1 फ़ाइल को अधिलेखित कर देगा। जारी रखें?", + "ja": "アップロードにより1つのファイルが上書きされます。継続する?", + "ko": "업로드하면 파일 1 개를 덮어 씁니다. 계속하다?", "nl": "Upload overschrijft {0} bestand. Doorgaan?", + "pt": "O upload substituirá 1 arquivo. Continuar?", "ru": "Загрузка перезапишет 1 файл. Продолжить?", + "zh-chs": "上傳將覆蓋1個文件。繼續?", "xloc": [ - "default.handlebars->25->1191", - "default.handlebars->25->685" + "default.handlebars->27->1321", + "default.handlebars->27->734" ] }, { @@ -18471,11 +25415,17 @@ "de": "Das Hochladen wird {0} Dateien überschreiben. Fortfahren?", "en": "Upload will overwrite {0} files. Continue?", "es": "La carga sobrescribirá el archivo {0}. ¿Continuar?", + "fr": "L'envoi écrasera {0} fichiers. Continuer ?", + "hi": "अपलोड {0} फ़ाइलों को अधिलेखित कर देगा। जारी रखें?", + "ja": "アップロードは{0}ファイルを上書きします。継続する?", + "ko": "업로드하면 {0} 파일을 덮어 씁니다. 계속하다?", "nl": "Upload overschrijft {0} bestanden. Doorgaan?", + "pt": "O upload substituirá {0} arquivos. Continuar?", "ru": "Загрузка перезапишет {0} файлов. Продолжить?", + "zh-chs": "上傳將覆蓋{0}個文件。繼續?", "xloc": [ - "default.handlebars->25->1192", - "default.handlebars->25->686" + "default.handlebars->27->1322", + "default.handlebars->27->735" ] }, { @@ -18483,33 +25433,45 @@ "de": "Das Hochladen wird {0} Datei{1} überschreiben. Fortfahren?", "en": "Upload will overwrite {0} file{1}. Continue?", "es": "La carga sobrescribirá el archivo {0} {1}. ¿Continuar?", + "fr": "L'envoi écrasera {0} fichier{1}. Continuer ?", + "hi": "अपलोड {0} फ़ाइल {1} को अधिलेखित कर देगा। जारी रखें?", "ja": "アップロードすると、{0}ファイル{1}が上書きされます。持続する?", + "ko": "업로드하면 {0} 파일 {1}을 (를) 덮어 씁니다. 계속하다?", "nl": "Uploaden overschrijft {0} bestand {1}. Doorgaan met?", "pt": "O upload substituirá o {0} arquivo {1}.Continuar?", - "ru": "Загрузка перезапишет {0} файлов. Продолжить?" + "ru": "Загрузка перезапишет {0} файлов. Продолжить?", + "zh-chs": "上傳將覆蓋{0}文件{1}。繼續?" }, { "cs": "hornolužická srbština", "de": "Obersorbisch", "en": "Upper Sorbian", + "fr": "Haut-sorabe", + "hi": "अपर सोरबियन", "ja": "上ソルビア語", + "ko": "어퍼 소르 비아 어", "nl": "Sorbisch", "pt": "Sorábio superior", "ru": "Верхний Сорбский", + "zh-chs": "上索布族", "xloc": [ - "default.handlebars->25->908" + "default.handlebars->27->1012" ] }, { "cs": "urdština", "de": "Urdu", "en": "Urdu", + "fr": "Ourdou", + "hi": "उर्दू", "ja": "ウルドゥー語", + "ko": "우르두어", "nl": "Urdu", "pt": "urdu", "ru": "Урду", + "zh-chs": "烏爾都語", "xloc": [ - "default.handlebars->25->909" + "default.handlebars->27->1013" ] }, { @@ -18518,9 +25480,13 @@ "en": "Use Security Key", "es": "Usar clave de seguridad", "fr": "Utiliser clé de sécurité", + "hi": "सुरक्षा कुंजी का उपयोग करें", "ja": "セキュリティキーを使用", + "ko": "보안 키 사용", "nl": "Gebruik beveiligingssleutel", + "pt": "Usar chave de segurança", "ru": "Используйте ключ безопасности", + "zh-chs": "使用安全密鑰", "xloc": [ "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->tokenpanel->1->7->1->4->1->3", "login.handlebars->container->column_l->centralTable->1->0->logincell->tokenpanel->1->7->1->4->1->3" @@ -18532,12 +25498,15 @@ "en": "Use the desktop version of this website to add devices.", "es": "Use la versión de escritorio de este sitio web para agregar dispositivos.", "fr": "Utilisez la version complète de ce site pour ajouter des appareils.", + "hi": "उपकरणों को जोड़ने के लिए इस वेबसाइट के डेस्कटॉप संस्करण का उपयोग करें।", "ja": "このWebサイトのデスクトップバージョンを使用して、デバイスを追加します。", + "ko": "이 웹 사이트의 데스크탑 버전을 사용하여 장치를 추가하십시오.", "nl": "Gebruik de desktopversie van deze website om apparaten toe te voegen.", "pt": "Use a versão desktop deste site para adicionar dispositivos.", "ru": "Чтобы добавить устройства, используйте настольную версию этого сайта.", + "zh-chs": "使用此網站的桌面版本添加設備。", "xloc": [ - "default-mobile.handlebars->9->99" + "default-mobile.handlebars->9->103" ] }, { @@ -18545,13 +25514,17 @@ "de": "Verwendet", "en": "Used", "es": "Usado", + "fr": "Utilisé", + "hi": "उपयोग किया गया", "ja": "中古", + "ko": "익숙한", "nl": "Gebruikt", "pt": "Usava", "ru": "Использовано", + "zh-chs": "用過的", "xloc": [ - "default.handlebars->25->1393", - "default.handlebars->25->1395" + "default.handlebars->27->1540", + "default.handlebars->27->1542" ] }, { @@ -18560,16 +25533,20 @@ "en": "User", "es": "Usuario", "fr": "Utilisateur", + "hi": "उपयोगकर्ता", "ja": "ユーザー", + "ko": "사용자", "nl": "Gebruiker", "pt": "Do utilizador", "ru": "Пользователь", + "zh-chs": "用戶", "xloc": [ - "default-mobile.handlebars->9->328", - "default.handlebars->25->1034", - "default.handlebars->25->1218", - "default.handlebars->25->1291", - "default.handlebars->25->200" + "default-mobile.handlebars->9->332", + "default.handlebars->27->1138", + "default.handlebars->27->1348", + "default.handlebars->27->1427", + "default.handlebars->27->184", + "default.handlebars->27->539" ] }, { @@ -18577,12 +25554,16 @@ "de": "Benutzer + Dateien", "en": "User + Files", "es": "Usuario + Archivos", + "fr": "Utilisateur + Fichiers", + "hi": "उपयोगकर्ता + फ़ाइलें", "ja": "ユーザー+ファイル", + "ko": "사용자 + 파일", "nl": "Gebruiker + bestanden", "pt": "Usuário + Arquivos", "ru": "Пользователь + Файлы", + "zh-chs": "用戶+文件", "xloc": [ - "default.handlebars->25->1219" + "default.handlebars->27->1349" ] }, { @@ -18590,15 +25571,19 @@ "de": "Benutzerkonten-Import", "en": "User Account Import", "es": "Importar cuenta de usuario", + "fr": "Importation de compte utilisateur", + "hi": "उपयोगकर्ता खाता आयात", "ja": "ユーザーアカウントのインポート", + "ko": "사용자 계정 가져 오기", "nl": "Gebruikersaccount importeren", "pt": "Importação de conta de usuário", "ru": "Импорт учетной записи пользователя", + "zh-chs": "用戶帳戶導入", "xloc": [ - "default.handlebars->25->1226", - "default.handlebars->25->1227", - "default.handlebars->25->1229", - "default.handlebars->25->1231" + "default.handlebars->27->1361", + "default.handlebars->27->1362", + "default.handlebars->27->1364", + "default.handlebars->27->1366" ] }, { @@ -18606,10 +25591,16 @@ "de": "Benutzerkonten", "en": "User Accounts", "es": "Cuentas de usuario", + "fr": "Comptes utilisateurs", + "hi": "उपयोगकर्ता का खाता", + "ja": "ユーザーアカウント", + "ko": "사용자 계정", "nl": "Gebruikersaccounts", + "pt": "Contas de usuário", "ru": "Учетные записи пользователей", + "zh-chs": "用戶帳號", "xloc": [ - "default.handlebars->25->1412" + "default.handlebars->27->1559" ] }, { @@ -18617,13 +25608,18 @@ "de": "Benutzerberechtigungen", "en": "User Authorizations", "es": "Autorizaciones de usuario", + "fr": "Autorisations des utilisateurs sur le groupe", + "hi": "उपयोगकर्ता प्राधिकरण", "ja": "ユーザー認証", + "ko": "사용자 인증", "nl": "Gebruikersautorisaties", "pt": "Autorizações de usuário", "ru": "Полномочия пользователя", + "zh-chs": "用戶授權", "xloc": [ - "default-mobile.handlebars->9->281", - "default.handlebars->25->1029" + "default-mobile.handlebars->9->285", + "default.handlebars->27->1136", + "default.handlebars->27->537" ] }, { @@ -18632,12 +25628,15 @@ "en": "User Consent", "es": "Consentimiento del usuario", "fr": "Consentement de l'utilisateur", + "hi": "उपयोगकर्ता सहमति", "ja": "ユーザーの同意", + "ko": "사용자 동의", "nl": "Toestemming van gebruiker", "pt": "Consentimento do Usuário", "ru": "Согласие пользователя", + "zh-chs": "用戶同意", "xloc": [ - "default.handlebars->25->1001" + "default.handlebars->27->1106" ] }, { @@ -18645,12 +25644,19 @@ "de": "Benutzergruppe", "en": "User Group", "es": "Grupo de usuario", + "fr": "Groupe d'utilisateurs", + "hi": "यूजर ग्रुप", + "ja": "ユーザー・グループ", + "ko": "사용자 그룹", "nl": "Gebruikers Groep", + "pt": "Grupo de usuários", "ru": "Группа пользователей", + "zh-chs": "用戶組", "xloc": [ - "default.handlebars->25->1087", - "default.handlebars->25->1274", - "default.handlebars->25->1385" + "default.handlebars->27->1192", + "default.handlebars->27->1410", + "default.handlebars->27->1522", + "default.handlebars->27->1531" ] }, { @@ -18658,8 +25664,14 @@ "de": "Benutzergruppe -", "en": "User Group -", "es": "Grupo de usuario -", + "fr": "Groupe utilisateurs", + "hi": "यूजर ग्रुप -", + "ja": "ユーザー・グループ -", + "ko": "사용자 그룹-", "nl": "Gebruikersgroep.", + "pt": "Grupo de usuários -", "ru": "Группа пользователей -", + "zh-chs": "用戶組-", "xloc": [ "default.handlebars->container->column_l->p51->1->1->0->1->p30title->3" ] @@ -18669,10 +25681,16 @@ "de": "Benutzergruppenmitgliedschaft", "en": "User Group Memberships", "es": "Membresías de grupos de usuarios", + "fr": "Appartenances aux groupes d'utilisateurs", + "hi": "उपयोगकर्ता समूह सदस्यताएँ", + "ja": "ユーザーグループのメンバーシップ", + "ko": "사용자 그룹 멤버십", "nl": "Gebruikersgroeps lidmaatschap", + "pt": "Membros do grupo de usuários", "ru": "Членство в группах пользователей", + "zh-chs": "用戶組成員資格", "xloc": [ - "default.handlebars->25->1377" + "default.handlebars->27->1519" ] }, { @@ -18680,13 +25698,17 @@ "de": "Benutzeridentifikation", "en": "User Identifier", "es": "Identificador de usuario", + "fr": "Identifiant de l'utilisateur", + "hi": "उपयोगकर्ता पहचानकर्ता", "ja": "ユーザー識別子", + "ko": "사용자 식별자", "nl": "gebruikersID", "pt": "Identificador do usuário", "ru": "Идентификатор пользователя", + "zh-chs": "用戶標識", "xloc": [ - "default.handlebars->25->1133", - "default.handlebars->25->1326" + "default.handlebars->27->1246", + "default.handlebars->27->1460" ] }, { @@ -18694,12 +25716,16 @@ "de": "Benutzerlistenexport", "en": "User List Export", "es": "Exportar lista de usuarios", + "fr": "Export des utilisateurs", + "hi": "उपयोगकर्ता सूची निर्यात", "ja": "ユーザーリストのエクスポート", + "ko": "사용자 목록 내보내기", "nl": "Gebruikerslijst exporteren", "pt": "Exportação da lista de usuários", "ru": "Экспортировать список пользователей", + "zh-chs": "用戶列表導出", "xloc": [ - "default.handlebars->25->1238" + "default.handlebars->27->1373" ] }, { @@ -18708,12 +25734,15 @@ "en": "User Name", "es": "Nombre de Usuario", "fr": "Nom", + "hi": "उपयोगकर्ता नाम", "ja": "ユーザー名", + "ko": "사용자 이름", "nl": "Gebruikersnaam", "pt": "Nome de Usuário", "ru": "Имя пользователя", + "zh-chs": "用戶名", "xloc": [ - "default.handlebars->25->1132" + "default.handlebars->27->1245" ] }, { @@ -18722,23 +25751,41 @@ "en": "User Names", "es": "Nombres de usuario", "fr": "Noms", + "hi": "उपयोगकर्ता नाम", "ja": "ユーザー名", + "ko": "사용자 이름", "nl": "Gebruikersnamen", "pt": "Nomes de usuário", "ru": "Имена пользователей", + "zh-chs": "用戶名", "xloc": [ - "default.handlebars->25->1085", - "default.handlebars->25->1315" + "default.handlebars->27->1190", + "default.handlebars->27->1448" ] }, + { + "cs": "Uživatelská oprávnění", + "de": "Benutzerberechtigungen", + "en": "User Permissions", + "fr": "Autorisations utilisateur", + "ja": "ユーザー権限", + "nl": "Gebruikersrechten", + "ru": "Пользовательские разрешения", + "zh-chs": "用户权限" + }, { "cs": "PowerShell uživatele", "de": "Benutzer-PowerShell", "en": "User PowerShell", "es": "Usuario PowerShell", + "fr": "PowerShell utilisateur", + "hi": "उपयोगकर्ता पॉवरशेल", "ja": "ユーザーPowerShell", + "ko": "사용자 PowerShell", "nl": "Gebruiker PowerShell", + "pt": "Usuário PowerShell", "ru": "User PowerShell", + "zh-chs": "用戶PowerShell", "xloc": [ "default.handlebars->termShellContextMenu->cxtermups", "xterm.handlebars->termShellContextMenu->cxtermups" @@ -18749,12 +25796,16 @@ "de": "Benutzersitzungen", "en": "User Sessions", "es": "Sesiones de usuario", + "fr": "Nombre de sessions actives", + "hi": "उपयोगकर्ता सत्र", "ja": "ユーザーセッション", + "ko": "사용자 세션", "nl": "Gebruikerssessie", "pt": "Sessões de Usuário", "ru": "Сессии пользователя", + "zh-chs": "用戶會話", "xloc": [ - "default.handlebars->25->1429" + "default.handlebars->27->1576" ] }, { @@ -18763,9 +25814,13 @@ "en": "User Shell", "es": "Shell de Usuario", "fr": "Shell utilisateur", + "hi": "उपयोगकर्ता शेल", "ja": "ユーザーシェル", + "ko": "사용자 셸", "nl": "Gebruiker Shell", + "pt": "Shell do Usuário", "ru": "User Shell", + "zh-chs": "用戶外殼", "xloc": [ "default.handlebars->termShellContextMenu->cxtermunorm", "default.handlebars->termShellContextMenuLinux->cxtermps", @@ -18773,18 +25828,48 @@ "xterm.handlebars->termShellContextMenuLinux->cxtermps" ] }, + { + "cs": "Uživatel [[[USERNAME]]] na serveru", + "de": "Benutzer [[[USERNAME]]] auf dem Server", + "en": "User [[[USERNAME]]] on server", + "fr": "Utilisateur [[[USERNAME]]] sur le serveur", + "nl": "Gebruiker [[[USERNAME]]] op server", + "ja": "サーバー上のユーザー[[[USERNAME]]]", + "ru": "Пользователь [[[USERNAME]]] на сервере", + "zh-chs": "伺服器上的使用者[[[USERNAME]]]", + "xloc": [ + "mesh-invite.html->2->5" + ] + }, + { + "cs": "Uživatel [[[USERNAME]]] na serveru [[[SERVERNAME]]] ([[[SERVERURL]]]/) požaduje instalaci softwaru k zahájení relace vzdáleného řízení.", + "de": "Benutzer [[[USERNAME]]] auf dem Server [[[SERVERNAME]]] ([[[SERVERURL]]]/) fordert Sie auf, Software zu installieren, um die Fernsteuerungssitzung zu starten.", + "en": "User [[[USERNAME]]] on server [[[SERVERNAME]]] ([[[SERVERURL]]]/) is requesting you install software to start the remote control session.", + "nl": "Gebruiker [[[USERNAME]]] op server [[[SERVERNAME]]] ([[[SERVERURL]]] /) vraagt u de software te installeren om de sessie voor afstandsbediening te starten.", + "fr": "L'utilisateur [[[USERNAME]]] sur le serveur [[[SERVERNAME]]] ([[[SERVERURL]]]/) vous demande d'installer un logiciel pour démarrer la session de contrôle à distance.", + "ja": "サーバー[[[SERVERNAME]]]([[[SERVERURL]]]/)のユーザー[[[USERNAME]]]が、リモートコントロールセッションを開始するためのソフトウェアのインストールを要求しています。", + "ru": "Пользователь [[[USERNAME]]] на сервере [[[SERVERNAME]]] ([[[SERVERURL]]]/) запрашивает установку программного обеспечения для запуска сеанса удаленного управления.", + "zh-chs": "服务器[[[SERVERNAME]]]([[[SERVERURL]]]/)上的用户[[[USERNAME]]]请求您安装软件以启动远程控制会话。", + "xloc": [ + "mesh-invite.txt" + ] + }, { "cs": "Převzít z webového prohlížeče", "de": "Browsereinstellung des Benutzers", "en": "User browser value", "es": "Valor del navegador del usuario", + "fr": "Configuration du navigateur", + "hi": "उपयोगकर्ता ब्राउज़र मान", "ja": "ユーザーブラウザーの値", + "ko": "사용자 브라우저 값", "nl": "Browserwaarde gebruiker", "pt": "Valor do navegador do usuário", "ru": "Использовать настройки браузера", + "zh-chs": "用戶瀏覽器價值", "xloc": [ - "default.handlebars->25->918", - "default.handlebars->25->920" + "default.handlebars->27->1023", + "default.handlebars->27->1025" ] }, { @@ -18792,14 +25877,19 @@ "de": "Benutzerinterface-Auswahl", "en": "User interface selection", "es": "Selección de interfaz de usuario", + "fr": "Sélection de l'interface utilisateur", + "hi": "उपयोगकर्ता इंटरफ़ेस चयन", "ja": "ユーザーインターフェイスの選択", + "ko": "사용자 인터페이스 선택", "nl": "Wissel gebruikersinterface", "pt": "Seleção da interface do usuário", "ru": "Выбор пользовательского интерфейса", + "zh-chs": "用戶界面選擇", "xloc": [ "agentinvite.handlebars->container->topbar", "default.handlebars->container->topbar->1->1", "error404.handlebars->container->topbar", + "invite.handlebars->container->topbar", "login.handlebars->container->topbar", "terms.handlebars->container->topbar" ] @@ -18810,10 +25900,13 @@ "en": "UserID", "es": "UserID", "fr": "Identifiant d'utilisateur", + "hi": "यूज़र आईडी", "ja": "ユーザーID", + "ko": "아이디", "nl": "GebruikersID", "pt": "ID do usuário", "ru": "UserID", + "zh-chs": "用戶身份", "xloc": [ "player.handlebars->3->5" ] @@ -18824,16 +25917,19 @@ "en": "Username", "es": "Usuario", "fr": "Nom d'utilisateur", + "hi": "उपयोगकर्ता नाम", "ja": "ユーザー名", + "ko": "사용자 이름", "nl": "Gebruikersnaam", "pt": "Nome de usuário", "ru": "Имя пользователя", + "zh-chs": "用戶名", "xloc": [ - "default-mobile.handlebars->9->212", - "default.handlebars->25->1244", - "default.handlebars->25->241", - "default.handlebars->25->271", - "default.handlebars->25->547", + "default-mobile.handlebars->9->216", + "default.handlebars->27->1379", + "default.handlebars->27->225", + "default.handlebars->27->255", + "default.handlebars->27->594", "player.handlebars->3->4" ] }, @@ -18843,12 +25939,16 @@ "en": "Username already exists.", "es": "El Usuario ya existe.", "fr": "Ce nom d'utilisateur existe déjà.", + "hi": "उपयोगकर्ता का नाम पहले से मौजूद है।", "ja": "ユーザー名は既に存在します。", + "ko": "사용자 이름이 이미 존재합니다.", "nl": "Gebruikersnaam bestaat al.", + "pt": "O nome de usuário já existe.", "ru": "Имя пользователя уже существует.", + "zh-chs": "此用戶名已存在。", "xloc": [ - "login-mobile.handlebars->5->6", - "login.handlebars->5->6" + "login-mobile.handlebars->5->7", + "login.handlebars->5->7" ] }, { @@ -18857,11 +25957,15 @@ "en": "Username:", "es": "Usuario:", "fr": "Nom d'utilisateur:", + "hi": "उपयोगकर्ता नाम:", "ja": "ユーザー名:", + "ko": "사용자 이름:", "nl": "Gebruikersnaam:", "pt": "Nome de usuário:", "ru": "Имя пользователя:", + "zh-chs": "用戶名:", "xloc": [ + "account-invite.html->2->5", "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->createpanel->1->1->9->1->nuUserRow->1", "login-mobile.handlebars->container->page_content->column_l->1->1->0->1->loginpanel->1->7->1->0->loginusername", "login.handlebars->container->column_l->centralTable->1->0->logincell->createpanel->1->9->1->nuUserRow->nuUser", @@ -18874,14 +25978,17 @@ "en": "Users", "es": "Usuarios", "fr": "Utilisateurs", + "hi": "उपयोगकर्ता", "ja": "ユーザー", + "ko": "사용자", "nl": "Gebruikers", "pt": "Usuários", "ru": "Пользователи", + "zh-chs": "用戶數", "xloc": [ - "default.handlebars->25->1273", - "default.handlebars->25->1284", - "default.handlebars->25->1428", + "default.handlebars->27->1409", + "default.handlebars->27->1420", + "default.handlebars->27->1575", "default.handlebars->container->topbar->1->1->UsersSubMenuSpan->UsersSubMenu->1->0->UsersGeneral" ] }, @@ -18890,10 +25997,16 @@ "de": "Benutzersitzungen", "en": "Users Sessions", "es": "Sesiones de Usuario", + "fr": "Sessions utilisateurs", + "hi": "उपयोगकर्ता सत्र", + "ja": "ユーザーセッション", + "ko": "사용자 세션", "nl": "gebruikers Sessies", + "pt": "Sessões de Usuários", "ru": "Сессии пользователей", + "zh-chs": "用戶會話", "xloc": [ - "default.handlebars->25->1416" + "default.handlebars->27->1563" ] }, { @@ -18901,24 +26014,32 @@ "de": "VT100+ (F10 = ESC+[OY)", "en": "VT100+ (F10 = ESC+[OY)", "es": "VT100+ (F10 = ESC+[OY)", + "fr": "VT100 + (F10 = ESC + [OY)", + "hi": "VT100 + (F10 = ESC + [ओए)", "ja": "VT100 +(F10 = ESC + [OY)", + "ko": "VT100 + (F10 = ESC + [OY)", "nl": "VT100+ (F10 = ESC+[OY)", "pt": "VT100+ (F10 = ESC+[OY)", "ru": "VT100+ (F10 = ESC+[OY)", + "zh-chs": "VT100 +(F10 = ESC + [OY)", "xloc": [ - "default.handlebars->25->643" + "default.handlebars->27->692" ] }, { "cs": "Venda", "de": "Venda", "en": "Venda", + "fr": "Venda", + "hi": "वेन्दा", "ja": "ベンダー", + "ko": "벤다", "nl": "Venda", "pt": "Venda", "ru": "Венда", + "zh-chs": "文達", "xloc": [ - "default.handlebars->25->910" + "default.handlebars->27->1014" ] }, { @@ -18927,13 +26048,32 @@ "en": "Vendor", "es": "Vendedor", "fr": "Vendeur", + "hi": "विक्रेता", "ja": "ベンダー", + "ko": "공급 업체", "nl": "Fabrikant", "pt": "Fornecedor", "ru": "Вендор", + "zh-chs": "供應商", "xloc": [ - "default.handlebars->25->67", - "default.handlebars->25->70" + "default.handlebars->27->778", + "default.handlebars->27->781" + ] + }, + { + "cs": "Ověřeno", + "de": "Verifiziert", + "en": "Verified", + "fr": "Vérifié", + "hi": "सत्यापित", + "ja": "検証済み", + "ko": "확인 됨", + "nl": "Geverifieerd", + "pt": "Verificado", + "ru": "Проверенный", + "zh-chs": "已驗證", + "xloc": [ + "default.handlebars->27->1495" ] }, { @@ -18942,10 +26082,13 @@ "en": "Verify Email", "es": "Verificar correo electronico", "fr": "Vérifier le Courriel", + "hi": "ईमेल सत्यापित करें", "ja": "Eメールを確認します", + "ko": "이메일 확인", "nl": "Verifieer Email", "pt": "Verificar Email", "ru": "Подтвердить email", + "zh-chs": "驗證郵件", "xloc": [ "default.handlebars->container->footer->3->verifyEmailId2" ] @@ -18956,10 +26099,13 @@ "en": "Verify email", "es": "Verificar correo electronico", "fr": "Vérifier le courriel", + "hi": "ईमेल सत्यापित करें", "ja": "Eメールを確認します", + "ko": "이메일 확인", "nl": "Verifieer Email", "pt": "Verificar email", "ru": "Подтвердить email", + "zh-chs": "驗證郵件", "xloc": [ "default-mobile.handlebars->container->page_content->column_l->p3->p3info->1->p3AccountActions->7->1->verifyEmailId->0", "default.handlebars->container->column_l->p2->p2AccountActions->3->verifyEmailId->0" @@ -18971,27 +26117,47 @@ "en": "Version", "es": "Version", "fr": "Version", + "hi": "संस्करण", "ja": "バージョン", + "ko": "버전", "nl": "Versie", "pt": "Versão", "ru": "Версия", + "zh-chs": "版", "xloc": [ - "default.handlebars->25->68", - "default.handlebars->25->73", - "default.handlebars->25->81", + "default.handlebars->27->741", + "default.handlebars->27->762", + "default.handlebars->27->779", + "default.handlebars->27->784", "default.handlebars->container->column_l->p42->p42tbl->1->0->5" ] }, + { + "cs": "Verze nekompatibilní, nejprve prosím upgradujte instalaci MeshCentral", + "de": "Version nicht kompatibel, bitte aktualisieren Sie zuerst Ihre MeshCentral-Installation", + "en": "Version incompatible, please upgrade your MeshCentral installation first", + "fr": "Version incompatible, veuillez d'abord mettre à niveau votre installation MeshCentral", + "ja": "バージョンに互換性がありません。最初にMeshCentralインストールをアップグレードしてください", + "nl": "Versie is niet compatibel, upgrade eerst uw MeshCentral installatie", + "ru": "Версия несовместима, пожалуйста, сначала обновите установку MeshCentral", + "zh-chs": "版本不兼容,请先升级您的MeshCentral安装", + "xloc": [ + "default.handlebars->27->1607" + ] + }, { "cs": "Velmi pomalu", "de": "Sehr langsam", "en": "Very slow", "es": "Muy Lento", "fr": "Très lent", + "hi": "बहुत धीमी गति से", "ja": "非常に遅い", + "ko": "아주 느린", "nl": "erg traag", "pt": "Muito devagar", "ru": "Очень медленно", + "zh-chs": "非常慢", "xloc": [ "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->7->d7framelimiter->7", "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->7->d7framelimiter->7" @@ -19003,12 +26169,15 @@ "en": "Vietnamese", "es": "Vietnamita", "fr": "Vietnamien", + "hi": "वियतनामी", "ja": "ベトナム人", + "ko": "베트남어", "nl": "Vietnamees", "pt": "vietnamita", "ru": "Вьетнамский", + "zh-chs": "越南文", "xloc": [ - "default.handlebars->25->911" + "default.handlebars->27->1015" ] }, { @@ -19017,25 +26186,46 @@ "en": "View", "es": "Ver", "fr": "Vue", + "hi": "राय", "ja": "表示する", + "ko": "전망", "nl": "Kijken", "pt": "Visualizar", "ru": "Вид", + "zh-chs": "視圖", "xloc": [ "default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->9->devListToolbarView" ] }, + { + "cs": "Zobrazit Changelog", + "de": "Changelog anzeigen", + "en": "View Changelog", + "fr": "Voir la log des modifications", + "ja": "変更ログを表示", + "nl": "Bekijk aanpassingen log", + "ru": "Просмотр журнала изменений", + "zh-chs": "查看变更日志", + "xloc": [ + "default.handlebars->27->1610", + "default.handlebars->27->1612" + ] + }, { "cs": "Zobrazit poznámky k tomuto zařízení", "de": "Zeige Notizen zu diesem Gerät", "en": "View notes about this device", "es": "Ver notas sobre este dispositivo", + "fr": "Voir les notes sur l'appareil", + "hi": "इस उपकरण के बारे में नोट्स देखें", "ja": "このデバイスに関するメモを表示", + "ko": "이 장치에 대한 메모보기", "nl": "Bekijk opmerkingen over dit apparaat", "pt": "Ver notas sobre este dispositivo", "ru": "Посмотреть примечания этого устройства", + "zh-chs": "查看有關此設備的註釋", "xloc": [ - "default.handlebars->25->497" + "default.handlebars->27->504" ] }, { @@ -19043,12 +26233,16 @@ "de": "Zeige Notizen zu dieser Gerätegruppe", "en": "View notes about this device group", "es": "Ver notas sobre este grupo de dispositivos", + "fr": "Voir les notes sur le groupe d'appareils", + "hi": "इस उपकरण समूह के बारे में नोट्स देखें", "ja": "このデバイスグループに関するメモを表示する", + "ko": "이 장치 그룹에 대한 메모보기", "nl": "Bekijk opmerkingen over deze apparaatgroep", "pt": "Ver notas sobre este grupo de dispositivos", "ru": "Посмотреть примечания этой группы устройств", + "zh-chs": "查看有關此設備組的註釋", "xloc": [ - "default.handlebars->25->1014" + "default.handlebars->27->1121" ] }, { @@ -19056,24 +26250,32 @@ "de": "Zeige Notizen zu diesem Benutzer", "en": "View notes about this user", "es": "Ver notas sobre este usuario", + "fr": "Voir les notes sur l'utilisateur", + "hi": "इस उपयोगकर्ता के बारे में नोट्स देखें", "ja": "このユーザーに関するメモを表示", + "ko": "이 사용자에 대한 메모보기", "nl": "Bekijk opmerkingen over deze gebruiker", "pt": "Ver notas sobre este usuário", "ru": "Посмотреть примечания об этом пользователе", + "zh-chs": "查看有關此用戶的註釋", "xloc": [ - "default.handlebars->25->1349" + "default.handlebars->27->1483" ] }, { "cs": "volapük", "de": "Volapuk", "en": "Volapuk", + "fr": "Volapuk", + "hi": "वोलापुक", "ja": "ヴォラプク", + "ko": "볼라 푸크", "nl": "Volapuk", "pt": "Volapuk", "ru": "Волапукский", + "zh-chs": "沃拉普克", "xloc": [ - "default.handlebars->25->912" + "default.handlebars->27->1016" ] }, { @@ -19082,11 +26284,15 @@ "en": "WARNING: ", "es": "ADVERTENCIA:", "fr": "ATTENTION:", + "hi": "चेतावनी:", "ja": "警告:", + "ko": "경고:", "nl": "Waarschuwing", + "pt": "ATENÇÃO:", "ru": "ВНИМАНИЕ: ", + "zh-chs": "警告:", "xloc": [ - "default.handlebars->25->64" + "default.handlebars->27->64" ] }, { @@ -19094,28 +26300,50 @@ "de": "Warte auf anderen Benutzer...", "en": "Waiting for other user...", "es": "Esperando a otro usuario ...", + "fr": "En attente de l'utilisateur...", + "hi": "अन्य उपयोगकर्ता की प्रतीक्षा कर रहा है ...", "ja": "他のユーザーを待っています...", + "ko": "다른 사용자를 기다리는 중 ...", "nl": "Wachten op de gebruiker ...", "pt": "Aguardando outro usuário ...", "ru": "В ожидании другой стороны...", + "zh-chs": "正在等待其他用戶...", "xloc": [ "messenger.handlebars->13->6" ] }, + { + "cs": "Probudit", + "de": "Aufwachen", + "en": "Wake", + "fr": "Réveiller", + "ja": "ウェイク", + "nl": "wekken", + "ru": "Услуга", + "zh-chs": "唤醒", + "xloc": [ + "default.handlebars->27->551", + "default.handlebars->27->570" + ] + }, { "cs": "Probudit zařízení", "de": "Geräte wecken", "en": "Wake Devices", "es": "Despertar Dispositivos", + "fr": "Réveil d'appareils", + "hi": "जागो यंत्र", "ja": "ウェイクデバイス", + "ko": "웨이크 장치", "nl": "apparaat wekken", "pt": "Reativar dispositivo", "ru": "Разбудить устройства", + "zh-chs": "喚醒設備", "xloc": [ - "default-mobile.handlebars->9->304", - "default-mobile.handlebars->9->317", - "default.handlebars->25->1103", - "default.handlebars->25->1121" + "default-mobile.handlebars->9->308", + "default-mobile.handlebars->9->321", + "default.handlebars->27->1211", + "default.handlebars->27->1233" ] }, { @@ -19123,13 +26351,17 @@ "de": "Aufwecken", "en": "Wake-up", "es": "Despertar", + "fr": "Réveil", + "hi": "उठो", "ja": "目を覚ます", + "ko": "모닝콜", "nl": "Wakker worden", "pt": "Ligar", "ru": "Разбудить", + "zh-chs": "醒來", "xloc": [ - "default-mobile.handlebars->9->206", - "default.handlebars->25->536" + "default-mobile.handlebars->9->210", + "default.handlebars->27->583" ] }, { @@ -19137,24 +26369,32 @@ "de": "Geräte aufwecken", "en": "Wake-up devices", "es": "Despertar Dispositivos", + "fr": "Réveil des appareils sélectionnés", + "hi": "वेक-अप डिवाइस", "ja": "ウェイクアップデバイス", + "ko": "웨이크 업 장치", "nl": "apparaat wekken", "pt": "Acordar dispositivo", "ru": "Разбудить устройства", + "zh-chs": "喚醒設備", "xloc": [ - "default.handlebars->25->387" + "default.handlebars->27->377" ] }, { "cs": "valonština", "de": "Wallonisch", "en": "Walloon", + "fr": "Wallon", + "hi": "वलून", "ja": "ワロン", + "ko": "왈론 사람", "nl": "Waals", "pt": "valão", "ru": "Валлонский", + "zh-chs": "瓦隆", "xloc": [ - "default.handlebars->25->913" + "default.handlebars->27->1017" ] }, { @@ -19163,12 +26403,15 @@ "en": "Weak", "es": "Debil", "fr": "Faible", + "hi": "कमज़ोर", "ja": "弱い", + "ko": "약한", "nl": "Zwak", "pt": "Fraco", "ru": "Слабый", + "zh-chs": "弱", "xloc": [ - "default.handlebars->25->965" + "default.handlebars->27->1070" ] }, { @@ -19177,15 +26420,18 @@ "en": "Weak Password", "es": "Contraseña debil", "fr": "Mot de passe faible", + "hi": "कमजोर पासवर्ड", "ja": "弱いパスワード", + "ko": "약한 암호", "nl": "Zwak wachtwoord", "pt": "Senha fraca", "ru": "Слабый пароль", + "zh-chs": "密碼強度低", "xloc": [ - "login-mobile.handlebars->5->22", - "login-mobile.handlebars->5->26", - "login.handlebars->5->22", - "login.handlebars->5->26" + "login-mobile.handlebars->5->25", + "login-mobile.handlebars->5->29", + "login.handlebars->5->25", + "login.handlebars->5->29" ] }, { @@ -19194,13 +26440,16 @@ "en": "Web Server", "es": "Servidor Web", "fr": "Serveur Web", + "hi": "वेब सर्वर", "ja": "Webサーバー", + "ko": "웹 서버", "nl": "webserver", "pt": "Servidor web", "ru": "Веб-сервер", + "zh-chs": "網絡服務器", "xloc": [ - "default.handlebars->25->1447", - "default.handlebars->25->1448" + "default.handlebars->27->1596", + "default.handlebars->27->1597" ] }, { @@ -19209,12 +26458,15 @@ "en": "Web Server Requests", "es": "Solicitudes al servidor web", "fr": "Demandes de serveur Web", + "hi": "वेब सर्वर अनुरोध", "ja": "Webサーバーリクエスト", + "ko": "웹 서버 요청", "nl": "Webserver Verzoeken", "pt": "Solicitações de servidor Web", "ru": "Запросы веб-сервера", + "zh-chs": "Web服務器請求", "xloc": [ - "default.handlebars->25->1449" + "default.handlebars->27->1598" ] }, { @@ -19223,12 +26475,15 @@ "en": "Web Socket Relay", "es": "Web Socket Relay", "fr": "Relais Web Socket", + "hi": "वेब सॉकेट रिले", "ja": "Webソケットリレー", + "ko": "웹 소켓 릴레이", "nl": "Web Socket Relay", "pt": "Encaminhador de soquete da Web", "ru": "Ретранслятор Web Socket", + "zh-chs": "Web套接字中繼", "xloc": [ - "default.handlebars->25->1450" + "default.handlebars->27->1599" ] }, { @@ -19237,11 +26492,15 @@ "en": "Welcome", "es": "Bienvenido {0}.", "fr": "Bienvenue", + "hi": "स्वागत हे", "ja": "ようこそ", + "ko": "어서 오십시오", "nl": "Welkom", "pt": "Bem vindo", "ru": "Добро пожаловать", + "zh-chs": "歡迎", "xloc": [ + "invite.handlebars->container->column_l->1", "login.handlebars->container->column_l->1" ] }, @@ -19251,11 +26510,15 @@ "en": "Welcome {0}.", "es": "Bienvenido {0}.", "fr": "Bienvenue {0}.", + "hi": "आपका स्वागत है {0}।", "ja": "{0}へようこそ。", + "ko": "{0}을 (를) 환영합니다.", "nl": "Welkom {0}.", + "pt": "Bem-vindo {0}.", "ru": "Добро пожаловать {0}.", + "zh-chs": "歡迎{0}。", "xloc": [ - "default.handlebars->25->44", + "default.handlebars->27->44", "terms.handlebars->3->1" ] }, @@ -19264,12 +26527,48 @@ "de": "Walisisch", "en": "Welsh", "fr": "Gallois", + "hi": "वेल्श", "ja": "ウェールズ", + "ko": "웨일스 말", "nl": "Wels", "pt": "galês", "ru": "Уэльский", + "zh-chs": "威爾士語", "xloc": [ - "default.handlebars->25->914" + "default.handlebars->27->1018" + ] + }, + { + "cs": "Pokud je tato možnost povolena, může kdokoli použít k připojení zařízení k této skupině zařízení pomocí následujícího veřejného odkazu:", + "de": "Wenn diese Option aktiviert ist, können Einladungscodes von jedem Benutzer verwendet werden, um Geräte über den folgenden öffentlichen Link mit dieser Gerätegruppe zu verbinden:", + "en": "When enabled, invitation codes can be used by anyone to join devices to this device group using the following public link:", + "fr": "Une fois activé, les codes d'invitation peuvent être utilisés par n'importe qui pour joindre des appareils à ce groupe d'appareils en utilisant le lien public suivant:", + "hi": "जब सक्षम किया जाता है, तो निमंत्रण कोड का उपयोग किसी भी व्यक्ति द्वारा इस उपकरण समूह में निम्नलिखित सार्वजनिक लिंक का उपयोग करके उपकरणों में शामिल होने के लिए किया जा सकता है:", + "ja": "有効にすると、誰でも次の公開リンクを使用してこのデバイスグループにデバイスを参加させるために招待コードを使用できます。", + "ko": "사용 설정되면 초대 코드를 사용하여 다음 공개 링크를 사용하여이 장치 그룹에 장치를 결합 할 수 있습니다.", + "nl": "Indien ingeschakeld, kunnen uitnodigingscodes door iedereen worden gebruikt om apparaten toe te voegen aan deze apparaatgroep via de volgende openbare link:", + "pt": "Quando ativado, os códigos de convite podem ser usados ​​por qualquer pessoa para associar dispositivos a este grupo de dispositivos usando o seguinte link público:", + "ru": "Когда этот параметр включен, коды приглашений могут использоваться любым пользователем для присоединения устройств к этой группе устройств по следующей общедоступной ссылке:", + "zh-chs": "啟用後,任何人都可以使用邀請代碼通過以下公共鏈接將設備加入該設備組:", + "xloc": [ + "default.handlebars->27->1252" + ] + }, + { + "cs": "Pokud je tato možnost povolena, při každém přihlášení budete mít možnost dostávat přihlašovací token na váš e-mailový účet pro zvýšení bezpečnosti.", + "de": "Wenn diese Option aktiviert ist, erhalten Sie bei jeder Anmeldung die Option, ein Anmeldetoken für zusätzliche Sicherheit an Ihr E-Mail-Konto zu senden.", + "en": "When enabled, on each login, you will be given the option to receive a login token to you email account for added security.", + "fr": "Lorsqu'il est activé, à chaque connexion, vous aurez la possibilité de recevoir un jeton de connexion à votre compte de messagerie pour plus de sécurité.", + "hi": "सक्षम होने पर, प्रत्येक लॉगिन पर, आपको अतिरिक्त सुरक्षा के लिए ईमेल अकाउंट में लॉगिन टोकन प्राप्त करने का विकल्प दिया जाएगा।", + "ja": "有効にすると、ログインごとに、セキュリティを強化するためにメールアカウントにログイントークンを受け取るオプションが表示されます。", + "ko": "활성화되면 각 로그인마다 보안 강화를 위해 이메일 계정으로 로그인 토큰을받을 수있는 옵션이 제공됩니다.", + "nl": "Indien ingeschakeld, krijgt u bij elke login de optie om een login-token voor uw e-mailaccount te ontvangen voor extra veiligheid.", + "pt": "Quando ativado, em cada login, você terá a opção de receber um token de login na sua conta de email para aumentar a segurança.", + "ru": "При включении при каждом входе в систему вам будет предоставлена возможность получать токен для входа в свою учетную запись электронной почты для обеспечения дополнительной безопасности.", + "zh-chs": "啟用後,每次登錄時,您都可以選擇向電子郵件帳戶接收登錄令牌,以提高安全性。", + "xloc": [ + "default-mobile.handlebars->9->31", + "default.handlebars->27->810" ] }, { @@ -19278,12 +26577,15 @@ "en": "Will be changed on next login.", "es": "Se cambiará en el próximo inicio de sesión.", "fr": "Sera changé lors de la prochaine connexion.", + "hi": "अगले लॉगिन पर बदला जाएगा।", "ja": "次回ログイン時に変更されます。", + "ko": "다음에 로그인하면 변경됩니다.", "nl": "Wordt bij de volgende aanmelding gewijzigd.", "pt": "Será alterado no próximo login.", "ru": "Будет изменено при следующем входе в систему.", + "zh-chs": "下次登錄時將更改。", "xloc": [ - "default.handlebars->25->1334" + "default.handlebars->27->1468" ] }, { @@ -19291,10 +26593,14 @@ "de": "Win", "en": "Win", "es": "Windows", + "fr": "Gagner", + "hi": "जीत", "ja": "勝つ", + "ko": "승리", "nl": "Win", "pt": "Win", "ru": "Win", + "zh-chs": "贏得", "xloc": [ "default-mobile.handlebars->dialog->3->dialog3->deskkeys->5", "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->deskkeys->3" @@ -19305,10 +26611,14 @@ "de": "Win+Runter", "en": "Win+Down", "es": "Win+Down", - "ja": "Win + Down", + "fr": "Win + Down", + "hi": "जीत + नीचे", + "ja": "Win+Down", + "ko": "승 + 다운", "nl": "Win+pijl naar omlaag", "pt": "Win+Down", "ru": "Win+Вниз", + "zh-chs": "勝負", "xloc": [ "default-mobile.handlebars->dialog->3->dialog3->deskkeys->7", "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->deskkeys->5" @@ -19319,10 +26629,14 @@ "de": "Win+L", "en": "Win+L", "es": "Win+L", - "ja": "Win + L", + "fr": "Win + L", + "hi": "जीत + L", + "ja": "Win+L", + "ko": "승 + L", "nl": "Win+L", "pt": "Win+L", "ru": "Win+L", + "zh-chs": "贏+ L", "xloc": [ "default-mobile.handlebars->dialog->3->dialog3->deskkeys->11", "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->deskkeys->9" @@ -19333,10 +26647,14 @@ "de": "Win+Links", "en": "Win+Left", "es": "Win+Left", - "ja": "Win +左", + "fr": "Gagner + Gauche", + "hi": "जीत + वाम", + "ja": "Win+左", + "ko": "승 + 왼쪽", "nl": "Win+pijl Links", "pt": "Win+Left", "ru": "Win+Влево", + "zh-chs": "贏+左", "xloc": [ "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->deskkeys->23" ] @@ -19346,10 +26664,14 @@ "de": "Win+M", "en": "Win+M", "es": "Win+M", - "ja": "Win + M", + "fr": "Win + M", + "hi": "जीत + M", + "ja": "Win+M", + "ko": "승 + M", "nl": "Win+M", "pt": "Win+M", "ru": "Win+M", + "zh-chs": "Win + M", "xloc": [ "default-mobile.handlebars->dialog->3->dialog3->deskkeys->13", "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->deskkeys->11" @@ -19360,10 +26682,14 @@ "de": "Win+R", "en": "Win+R", "es": "Win+R", - "ja": "Win + R", + "fr": "Win + R", + "hi": "जीत + आर", + "ja": "Win+R", + "ko": "승 + R", "nl": "Win+R", "pt": "Win+R", "ru": "Win+R", + "zh-chs": "Win + R", "xloc": [ "default-mobile.handlebars->dialog->3->dialog3->deskkeys->17", "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->deskkeys->15" @@ -19374,10 +26700,14 @@ "de": "Win+Rechts", "en": "Win+Right", "es": "Win+Right", + "fr": "Win + Right", + "hi": "जीत + दायां", "ja": "勝ち+右", + "ko": "승리 + 오른쪽", "nl": "Win+pijl rechts", "pt": "Win+Right", "ru": "Win+Вправо", + "zh-chs": "贏+右", "xloc": [ "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->deskkeys->25" ] @@ -19387,26 +26717,50 @@ "de": "Win+Hoch", "en": "Win+Up", "es": "Win+Up", + "fr": "Gagnez +", + "hi": "जीत + ऊपर", "ja": "Win + Up", + "ko": "승 +", "nl": "Win+ pijl omhoog", "pt": "Win+Up", "ru": "Win+Вверх", + "zh-chs": "勝+勝", "xloc": [ "default-mobile.handlebars->dialog->3->dialog3->deskkeys->9", "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->deskkeys->7" ] }, + { + "cs": "Spustitelný soubor Win32", + "de": "Win32 ausführbar", + "en": "Win32 Executable", + "fr": "Exécutable Win32", + "hi": "Win32 निष्पादन योग्य", + "ja": "Win32実行可能ファイル", + "ko": "실행 가능한 Win32", + "nl": "Win32 uitvoerbaar", + "pt": "Executável Win32", + "ru": "Исполняемый файл Win32", + "zh-chs": "Win32可執行文件", + "xloc": [ + "default.handlebars->27->622" + ] + }, { "cs": "WinSCP", "de": "WinSCP", "en": "WinSCP", "es": "WinSCP", + "fr": "WinSCP", + "hi": "WinSCP", "ja": "WinSCP", + "ko": "WinSCP", "nl": "WinSCP", "pt": "WinSCP", "ru": "WinSCP", + "zh-chs": "WinSCP", "xloc": [ - "default.handlebars->25->517" + "default.handlebars->27->524" ] }, { @@ -19414,12 +26768,16 @@ "de": "Windows", "en": "Windows", "es": "Windows", + "fr": "Windows", + "hi": "खिड़कियाँ", "ja": "窓", + "ko": "윈도우", "nl": "Windows", "pt": "Windows", "ru": "Windows", + "zh-chs": "視窗", "xloc": [ - "default.handlebars->25->315" + "default.handlebars->27->302" ] }, { @@ -19427,13 +26785,17 @@ "de": "Windows (.exe)", "en": "Windows (.exe)", "es": "Windows (.exe)", + "fr": "Windows (.exe)", + "hi": "विंडोज (.exe)", "ja": "Windows(.exe)", + "ko": "Windows (.exe)", "nl": "Windows (.exe)", "pt": "Windows (.exe)", "ru": "Windows (.exe)", + "zh-chs": "Windows(.exe)", "xloc": [ - "default.handlebars->25->327", - "default.handlebars->25->341" + "default.handlebars->27->314", + "default.handlebars->27->331" ] }, { @@ -19441,12 +26803,16 @@ "de": "Windows (32bit)", "en": "Windows (32bit)", "es": "Windows (32bit)", + "fr": "Windows (32bit)", + "hi": "विंडोज (32 बिट)", "ja": "Windows(32ビット)", + "ko": "윈도우 (32 비트)", "nl": "Windows (32bit)", "pt": "Windows (32 Bits)", "ru": "Windows (32bit)", + "zh-chs": "Windows(32位)", "xloc": [ - "default.handlebars->25->576" + "default.handlebars->27->624" ] }, { @@ -19454,12 +26820,16 @@ "de": "Windows (64bit)", "en": "Windows (64bit)", "es": "Windows (64bit)", + "fr": "Windows (64bit)", + "hi": "विंडोज (64 बिट)", "ja": "Windows(64ビット)", + "ko": "윈도우 (64 비트)", "nl": "Windows (64bit)", "pt": "Windows (64 Bits)", "ru": "Windows (64bit)", + "zh-chs": "Windows(64位)", "xloc": [ - "default.handlebars->25->577" + "default.handlebars->27->625" ] }, { @@ -19467,12 +26837,16 @@ "de": "Windows (Deinstallation)", "en": "Windows (UnInstall)", "es": "Windows (Desinstalar)", + "fr": "Windows (Désinstallation)", + "hi": "विंडोज (UnInstall)", "ja": "Windows(アンインストール)", + "ko": "Windows (제거)", "nl": "Windows (deinstallatie)", "pt": "Windows (Desinstalador)", "ru": "Windows (Удаление)", + "zh-chs": "Windows(卸載)", "xloc": [ - "default.handlebars->25->318" + "default.handlebars->27->305" ] }, { @@ -19480,10 +26854,14 @@ "de": "Windows 32bit", "en": "Windows 32bit", "es": "Windows 32bit", + "fr": "Windows 32bit", + "hi": "विंडोज 32 बिट", "ja": "Windows 32ビット", + "ko": "윈도우 32 비트", "nl": "Windows 32bit", "pt": "Windows 32 Bits", "ru": "Windows 32bit", + "zh-chs": "Windows 32位", "xloc": [ "agentinvite.handlebars->container->column_l->5->1->twintab32" ] @@ -19493,13 +26871,17 @@ "de": "Windows 32bit Konsole", "en": "Windows 32bit console", "es": "Consola Windows 32bits", + "fr": "Console Windows 32 bits", + "hi": "विंडोज 32 बिट कंसोल", "ja": "Windows 32ビットコンソール", + "ko": "Windows 32 비트 콘솔", "nl": "Windows 32bit console", "pt": "Windows 32 Bits console", "ru": "Консоль Windows 32bit", + "zh-chs": "Windows 32位控制台", "xloc": [ - "default-mobile.handlebars->9->144", - "default.handlebars->25->14" + "default-mobile.handlebars->9->148", + "default.handlebars->27->14" ] }, { @@ -19507,13 +26889,17 @@ "de": "Windows 32bit Dienst", "en": "Windows 32bit service", "es": "Servicio Windows 32bits", + "fr": "Service Windows 32 bits", + "hi": "विंडोज 32 बिट सेवा", "ja": "Windows 32ビットサービス", + "ko": "Windows 32 비트 서비스", "nl": "Windows 32bit service", "pt": "Serviço Windows 32 Bits", "ru": "Служба Windows 32bit", + "zh-chs": "Windows 32位服務", "xloc": [ - "default-mobile.handlebars->9->146", - "default.handlebars->25->16" + "default-mobile.handlebars->9->150", + "default.handlebars->27->16" ] }, { @@ -19521,10 +26907,14 @@ "de": "Windows 64bit", "en": "Windows 64bit", "es": "Windows 64bit", + "fr": "Windows 64bit", + "hi": "विंडोज 64 बिट", "ja": "Windows 64ビット", + "ko": "윈도우 64 비트", "nl": "Windows 64bit", "pt": "Windows 64 Bits", "ru": "Windows 64bit", + "zh-chs": "Windows 64位", "xloc": [ "agentinvite.handlebars->container->column_l->5->1->twintab64" ] @@ -19534,13 +26924,17 @@ "de": "Windows 64bit Konsole", "en": "Windows 64bit console", "es": "Consola Windows 64bits", + "fr": "Console Windows 64 bits", + "hi": "विंडोज 64 बिट कंसोल", "ja": "Windows 64ビットコンソール", + "ko": "Windows 64 비트 콘솔", "nl": "Windows 64bit console", "pt": "Windows 64 Bits console", "ru": "Консоль Windows 64bit", + "zh-chs": "Windows 64位控制台", "xloc": [ - "default-mobile.handlebars->9->145", - "default.handlebars->25->15" + "default-mobile.handlebars->9->149", + "default.handlebars->27->15" ] }, { @@ -19548,13 +26942,17 @@ "de": "Windows 64bit Dienst", "en": "Windows 64bit service", "es": "Servicio Windows 64bits", + "fr": "Service Windows 64 bits", + "hi": "विंडोज 64 बिट सेवा", "ja": "Windows 64ビットサービス", + "ko": "Windows 64 비트 서비스", "nl": "Windows 64bit service", "pt": "Serviço Windows 64 Bits", "ru": "Служба Windows 64bit", + "zh-chs": "Windows 64位服務", "xloc": [ - "default-mobile.handlebars->9->147", - "default.handlebars->25->17" + "default-mobile.handlebars->9->151", + "default.handlebars->27->17" ] }, { @@ -19562,13 +26960,17 @@ "de": "Windows MinCore Konsole", "en": "Windows MinCore console", "es": "Consola MinCore de Windows", + "fr": "Console Windows MinCore", + "hi": "Windows MinCore कंसोल", "ja": "Windows MinCoreコンソール", + "ko": "Windows MinCore 콘솔", "nl": "Windows MinCore console", "pt": "Windows MinCore console", "ru": "Консоль Windows MinCore", + "zh-chs": "Windows MinCore控制台", "xloc": [ - "default-mobile.handlebars->9->164", - "default.handlebars->25->34" + "default-mobile.handlebars->9->168", + "default.handlebars->27->34" ] }, { @@ -19576,13 +26978,17 @@ "de": "Windows MinCore Dienst", "en": "Windows MinCore service", "es": "Servicio MinCore de Windows", + "fr": "Service Windows MinCore", + "hi": "विंडोज MinCore सेवा", "ja": "Windows MinCoreサービス", + "ko": "Windows MinCore 서비스", "nl": "Windows MinCore service", "pt": "Windows MinCore service", "ru": "Служба Windows MinCore", + "zh-chs": "Windows MinCore服務", "xloc": [ - "default-mobile.handlebars->9->165", - "default.handlebars->25->35" + "default-mobile.handlebars->9->169", + "default.handlebars->27->35" ] }, { @@ -19590,12 +26996,16 @@ "de": "nur Windows", "en": "Windows only", "es": "Solo Windows", + "fr": "Windows seulement", + "hi": "केवल विंडोज", "ja": "Windowsのみ", + "ko": "Windows 만", "nl": "alleen Windows", "pt": "Apenas Windows", "ru": "Только Windows", + "zh-chs": "僅Windows", "xloc": [ - "default.handlebars->25->288" + "default.handlebars->27->275" ] }, { @@ -19603,13 +27013,17 @@ "de": "Windows x64 (.exe)", "en": "Windows x64 (.exe)", "es": "Windows x64 (.exe)", + "fr": "Windows x64 (.exe)", + "hi": "Windows x64 (.exe)", "ja": "Windows x64(.exe)", + "ko": "Windows x64 (.exe)", "nl": "Windows x64 (.exe)", "pt": "Windows x64 (.exe)", "ru": "Windows x64 (.exe)", + "zh-chs": "Windows x64(.exe)", "xloc": [ - "default.handlebars->25->330", - "default.handlebars->25->344" + "default.handlebars->27->318", + "default.handlebars->27->334" ] }, { @@ -19617,7 +27031,14 @@ "de": "Umbruch an", "en": "Wrap On", "es": "Envoltura: On", + "fr": "Envelopper", + "hi": "लपेटें पर", + "ja": "ラップオン", + "ko": "포장", "nl": "Wrap Aan", + "pt": "Wrap On", + "ru": "Wrap On", + "zh-chs": "總結", "xloc": [ "default.handlebars->container->dialog->dialogBody->dialog4" ] @@ -19627,10 +27048,16 @@ "de": "Umbruch: aus", "en": "Wrap: OFF", "es": "Envoltura: OFF", + "fr": "Envelopper: OFF", + "hi": "लपेटें: बंद", + "ja": "ラップ:オフ", + "ko": "랩 : OFF", "nl": "Wrap: UIT", + "pt": "Wrap: OFF", "ru": "Перенос строк: ВЫКЛ", + "zh-chs": "包裝:關閉", "xloc": [ - "default.handlebars->25->679" + "default.handlebars->27->728" ] }, { @@ -19638,10 +27065,16 @@ "de": "Umbruch: an", "en": "Wrap: ON", "es": "Envoltura: ON", + "fr": "Enveloppement: ON", + "hi": "लपेटें: पर", + "ja": "ラップ:オン", + "ko": "랩 : ON", "nl": "Wrap: AAN", + "pt": "Wrap: ON", "ru": "Перенос строк: ВКЛ", + "zh-chs": "包裝:開", "xloc": [ - "default.handlebars->25->678" + "default.handlebars->27->727" ] }, { @@ -19650,12 +27083,15 @@ "en": "Write an event for this device", "es": "Escribe un evento para este dispositivo.", "fr": "Écrire un événement pour ce périphérique", + "hi": "इस उपकरण के लिए एक घटना लिखें", "ja": "このデバイスのイベントを書く", + "ko": "이 기기에 대한 이벤트 작성", "nl": "Schrijf een gebeurtenis voor dit apparaat", "pt": "Escreva um evento para este dispositivo", "ru": "Записать событие к этому устройству", + "zh-chs": "為此設備寫一個事件", "xloc": [ - "default.handlebars->25->499" + "default.handlebars->27->506" ] }, { @@ -19663,6 +27099,7 @@ "de": "X", "en": "X", "es": "X", + "fr": "X", "ja": "バツ", "nl": "X", "pt": "X", @@ -19679,21 +27116,34 @@ "de": "XENx86", "en": "XENx86", "es": "XENx86", + "fr": "XENx86", + "hi": "XENx86", "ja": "XENx86", + "ko": "XENx86", "nl": "XENx86", "pt": "XENx86", "ru": "XENx86", + "zh-chs": "XENx86", "xloc": [ - "default-mobile.handlebars->9->151", - "default.handlebars->25->21" + "default-mobile.handlebars->9->155", + "default.handlebars->27->21" ] }, { + "cs": "XTerm", + "de": "XTerm", "en": "XTerm", + "es": "XTerm", + "fr": "XTerm", + "hi": "XTerm", + "ja": "XTerm", + "ko": "XTerm", "nl": "XTerm", + "pt": "XTerm", "ru": "XTerm", + "zh-chs": "XTerm", "xloc": [ - "default.handlebars->25->511" + "default.handlebars->27->518" ] }, { @@ -19701,12 +27151,16 @@ "de": "Xhosa", "en": "Xhosa", "es": "Xhosa", + "fr": "Xhosa", + "hi": "षोसा", "ja": "コーサ", + "ko": "코사", "nl": "Xhosa", "pt": "Xhosa", "ru": "Кос", + "zh-chs": "科薩", "xloc": [ - "default.handlebars->25->915" + "default.handlebars->27->1019" ] }, { @@ -19714,12 +27168,16 @@ "de": "Jiddisch", "en": "Yiddish", "es": "Yiddish", + "fr": "yiddish", + "hi": "यहूदी", "ja": "イディッシュ語", + "ko": "이디시어", "nl": "Jiddisch", "pt": "Iídiche", "ru": "Идиш", + "zh-chs": "意第緒語", "xloc": [ - "default.handlebars->25->916" + "default.handlebars->27->1020" ] }, { @@ -19728,22 +27186,26 @@ "en": "You can reactivate this feature at any time.", "es": "Puedes reactivar esta función en cualquier momento.", "fr": "Vous pouvez réactiver cette fonctionnalité à tout moment.", + "hi": "आप किसी भी समय इस सुविधा को पुनः सक्रिय कर सकते हैं।", "ja": "この機能はいつでも再アクティブ化できます。", + "ko": "언제든지이 기능을 다시 활성화 할 수 있습니다.", "nl": "U kunt deze functie op elk moment opnieuw activeren.", "pt": "Você pode reativar esse recurso a qualquer momento.", "ru": "Вы можете возобновить эту функцию в любое время.", + "zh-chs": "您可以隨時重新激活此功能。", "xloc": [ - "default.handlebars->25->129" + "default.handlebars->27->112" ] }, { - "cs": "Byla vám doručena pozvánka k instalaci softwaru, který umožňuje vzdálenou správu zařízení.\n Postupujte podle níže uvedených pokynů, pokud jste si vědom toho, že tato pozvánka je legitimní a chcete tento přístup umožnit.\n Vyberte si operační systém a postupujte dle pokynů níže.", - "de": "Sie wurden eingeladen, eine Software zu installieren, die es einem Remote-Operator erlaubt, entfernt auf Ihren Rechner zuzugreifen, einschließlich Bildschirm und Dateien.\n Befolgen Sie die untenstehenden Anweisungen ausschließlich dann, wenn Sie diese Einladung erwartet haben und Sie wissen, wer auf Ihren Rechner zugreifen wird.\n Wählen Sie Ihr Betriebssystem und folgen Sie den untenstehenden Anweisungen.", - "en": "You have been invited to install a software that will allow a remote operator to fully access your computer remotely including the desktop and files.\n Only follow the instructions below if this invitation was expected and you know who will be accessing your computer.\n Selecting your operation system and follow the instructions below.", - "es": "Se le invitó a instalar un software que permitirá que un operador remoto acceda completamente a su computadora de forma remota, incluido el escritorio y los archivos.\n Solo siga las instrucciones a continuación si se esperaba esta invitación y sabe quién accederá a su computadora.\n Seleccione su sistema operativo y siga las instrucciones a continuación.", - "nl": "U bent uitgenodigd om software te installeren waarmee een externe operator op afstand volledige toegang heeft tot uw computer, inclusief het bureaublad en de bestanden. Volg de onderstaande instructies alleen als deze uitnodiging werd verwacht en u weet wie toegang krijgt tot uw computer. Selecteer uw besturingssysteem en volg de onderstaande instructies.", - "pt": "Você foi convidado a instalar um software que permitirá que um operador remoto acesse totalmente seu computador remotamente, incluindo a área de trabalho e os arquivos.\n Siga apenas as instruções abaixo se esse convite for esperado e você sabe quem acessará seu computador.\n Selecionando seu sistema operacional e siga as instruções abaixo.", - "ru": "Вам предлагается установить программное обеспечение, которое позволит удаленному оператору получить полный доступ к Вашему компьютеру, включая рабочий стол и файлы. Следуйте приведенным ниже инструкциям только в том случае, если это приглашение ожидалось и Вы знаете кто будет обращаться к Вашему компьютеру. Выберите Вашу операционную систему и следуйте инструкциям ниже.", + "cs": "Byli jste vyzváni k instalaci softwaru, který vzdálenému operátorovi umožní vzdálený přístup k vašemu počítači na dálku, včetně plochy a souborů. Postupujte podle níže uvedených pokynů, pokud byla tato pozvánka očekávána a víte, kdo bude mít přístup k vašemu počítači. Výběr operačního systému a postupujte podle pokynů níže.", + "de": "Sie wurden aufgefordert, eine Software zu installieren, mit der ein Fernbediener remote auf Ihren Computer zugreifen kann, einschließlich Desktop und Dateien. Befolgen Sie die nachstehenden Anweisungen nur, wenn diese Einladung erwartet wurde und Sie wissen, wer auf Ihren Computer zugreifen wird. Wählen Sie Ihr Betriebssystem aus und befolgen Sie die nachstehenden Anweisungen.", + "en": "You have been invited to install a software that will allow a remote operator to fully access your computer remotely including the desktop and files. Only follow the instructions below if this invitation was expected and you know who will be accessing your computer. Selecting your operation system and follow the instructions below.", + "nl": "U bent uitgenodigd om software te installeren waarmee een externe operator op afstand volledige toegang heeft tot uw computer, inclusief het bureaublad en de bestanden. Volg de onderstaande instructies alleen als deze uitnodiging werd verwacht en u weet wie er toegang krijgt tot uw computer. Selecteer uw besturingssysteem en volg de onderstaande instructies.", + "fr": "Vous avez été invité à installer un logiciel qui permettra à un opérateur distant d'accéder pleinement à votre ordinateur à distance, y compris le bureau et les fichiers. Suivez les instructions ci-dessous uniquement si cette invitation était attendue et que vous savez qui aura accès à votre ordinateur. Sélectionnez votre système d'exploitation et suivez les instructions ci-dessous.", + "ja": "リモートオペレーターがデスクトップやファイルを含め、リモートでコンピューターに完全にアクセスできるようにするソフトウェアをインストールするよう招待されました。この招待が予期されていて、誰がコンピュータにアクセスするかがわかっている場合にのみ、以下の手順に従ってください。オペレーティングシステムを選択し、以下の手順に従います。", + "ru": "Вам было предложено установить программное обеспечение, которое позволит удаленному оператору получить полный доступ к вашему компьютеру, включая рабочий стол и файлы. Следуйте приведенным ниже инструкциям только в том случае, если это приглашение ожидалось и вы знаете, кто будет обращаться к вашему компьютеру. Выбор вашей операционной системы и следуйте инструкциям ниже.", + "zh-chs": "已邀请您安装软件,该软件将允许远程操作员远程完全访问您的计算机,包括桌面和文件。如果预期会收到此邀请,请仅遵循以下说明,并且您知道谁将访问您的计算机。选择操作系统,然后按照以下说明进行操作。", "xloc": [ "agentinvite.handlebars->container->column_l->3" ] @@ -19754,25 +27216,46 @@ "en": "You will now need a valid token to login again.", "es": "Ahora necesitará un token válido para iniciar sesión nuevamente.", "fr": "Vous aurez maintenant besoin d'un jeton valide pour vous connecter à nouveau.", + "hi": "अब आपको फिर से लॉगिन करने के लिए वैध टोकन की आवश्यकता होगी।", "ja": "再度ログインするには、有効なトークンが必要になります。", + "ko": "이제 다시 로그인하려면 유효한 토큰이 필요합니다.", "nl": "U hebt nu een geldig token nodig om opnieuw in te loggen.", "pt": "Agora você precisará de um token válido para fazer login novamente.", "ru": "Теперь вам понадобится действительный токен, чтобы снова войти в систему.", + "zh-chs": "您現在需要一個有效的令牌才能再次登錄。", "xloc": [ - "default.handlebars->25->124" + "default.handlebars->27->107" ] }, { - "cs": "YubiKey™ OTP", + "cs": "Váš přihlašovací token je: [[[TOKEN]]]", + "de": "Ihr Login-Token lautet: [[[TOKEN]]]", + "en": "Your login token is: [[[TOKEN]]]", + "fr": "Votre jeton de connexion est: [[[TOKEN]]]", + "nl": "Uw login token is: [[[TOKEN]]]", + "ja": "ログイントークンは次のとおりです:[[[TOKEN]]]", + "ru": "Ваш токен для входа: [[[TOKEN]]]", + "zh-chs": "您的登录令牌为:[[[TOKEN]]]", + "xloc": [ + "account-login.html->2->3", + "account-login.txt" + ] + }, + { + "cs": "YubiKey™ OTP", "de": "YubiKey™ OTP", "en": "YubiKey™ OTP", "es": "YubiKey™ OTP", - "ja": "YubiKey&trade; OTP", + "fr": "YubiKey™ OTP", + "hi": "YubiKey™ OTP", + "ja": "YubiKey™ OTP", + "ko": "YubiKey™ OTP", "nl": "YubiKey™ OTP", "pt": "YubiKey™ OTP", "ru": "YubiKey™ OTP", + "zh-chs": "YubiKey™ OTP", "xloc": [ - "default.handlebars->25->718" + "default.handlebars->27->822" ] }, { @@ -19780,12 +27263,16 @@ "de": "Zoomen um Fläche zu entsprechen", "en": "Zoom to fit extent", "es": "Zoom para adaptarse a la extensión", + "fr": "Adapter la vue", + "hi": "फिट करने के लिए ज़ूम", "ja": "範囲に合わせてズーム", + "ko": "범위에 맞게 확대", "nl": "Zoom in op maat", "pt": "Zoom para ajustar a extensão", "ru": "Масштабирование по размеру", + "zh-chs": "縮放至適合範圍", "xloc": [ - "default.handlebars->25->425" + "default.handlebars->27->429" ] }, { @@ -19793,13 +27280,17 @@ "de": "Bis auf Fläche hineinzoomen", "en": "Zoom-in to extent", "es": "Acercar a medida", + "fr": "Zoomer pour agrandir", + "hi": "ज़ूम-इन हद तक", "ja": "拡大する", + "ko": "확대", "nl": "Inzoomen tot maat", "pt": "Aumentar o zoom até o limite", "ru": "Масштабирование +", + "zh-chs": "放大到一定程度", "xloc": [ - "default.handlebars->25->422", - "default.handlebars->25->428" + "default.handlebars->27->426", + "default.handlebars->27->432" ] }, { @@ -19807,13 +27298,17 @@ "de": "Bis auf Fläche herauszoomen", "en": "Zoom-out to extent", "es": "Alejar a medida", + "fr": "Dézoomer pour réduire", + "hi": "ज़ूम-आउट करने के लिए", "ja": "ズームアウト", + "ko": "범위 축소", "nl": "Uitzoomen naar maat", "pt": "Diminuir o zoom até o limite", "ru": "Масштабирование -", + "zh-chs": "縮小到一定程度", "xloc": [ - "default.handlebars->25->423", - "default.handlebars->25->429" + "default.handlebars->27->427", + "default.handlebars->27->433" ] }, { @@ -19821,12 +27316,174 @@ "de": "Zulu", "en": "Zulu", "es": "Zulu", + "fr": "zoulou", + "hi": "ज़ुलु", "ja": "ズールー", - "nl": "Zoeloe", + "ko": "줄루 족", + "nl": "Zulu", "pt": "Zulu", "ru": "Зулусский", + "zh-chs": "祖魯族", "xloc": [ - "default.handlebars->25->917" + "default.handlebars->27->1021" + ] + }, + { + "cs": "[[[ACCOUNTNAME]]]", + "de": "[[[ACCOUNTNAME]]]", + "en": "[[[ACCOUNTNAME]]]", + "fr": "[[[ACCOUNTNAME]]]", + "nl": "[[[ACCOUNTNAME]]]", + "ja": "[[[ACCOUNTNAME]]]", + "ru": "[[[ACCOUNTNAME]]]", + "zh-chs": "[[[ACCOUNTNAME]]]" + }, + { + "cs": "[[[MSG]]]", + "de": "[[[MSG]]]", + "en": "[[[MSG]]]", + "fr": "[[[MSG]]]", + "nl": "[[[MSG]]]", + "ja": "[[[MSG]]]", + "ru": "[[[MSG]]]", + "zh-chs": "[[[MSG]]]" + }, + { + "cs": "[[[PASSWORD]]]", + "de": "[[[PASSWORD]]]", + "en": "[[[PASSWORD]]]", + "fr": "[[[PASSWORD]]]", + "nl": "[[[PASSWORD]]]", + "ja": "[[[PASSWORD]]]", + "ru": "[[[PASSWORD]]]", + "zh-chs": "[[[PASSWORD]]]" + }, + { + "cs": "[[[SERVERNAME]]]", + "de": "[[[SERVERNAME]]]", + "en": "[[[SERVERNAME]]]", + "fr": "[[[SERVERNAME]]]", + "nl": "[[[SERVERNAME]]]", + "ja": "[[[SERVERNAME]]]", + "ru": "[[[SERVERNAME]]]", + "zh-chs": "[[[SERVERNAME]]]", + "xloc": [ + "account-check.html->2->3->1", + "account-reset.html->2->3->1", + "mesh-invite.html->2->5->1" + ] + }, + { + "cs": "[[[SERVERNAME]]] - Pozvánka na účet", + "de": "[[[SERVERNAME]]] - Kontoeinladung", + "en": "[[[SERVERNAME]]] - Account Invitation", + "fr": "[[[SERVERNAME]]] - Invitation au compte", + "nl": "[[[SERVERNAME]]] - Account uitnodiging", + "ja": "[[[SERVERNAME]]]-アカウントの招待", + "ru": "[[[SERVERNAME]]] - приглашение в аккаунт", + "zh-chs": "[[[SERVERNAME]]]-帐户邀请", + "xloc": [ + "account-invite.html->0", + "account-invite.html->2->1->1->0->1->1", + "account-invite.txt" + ] + }, + { + "cs": "[[[SERVERNAME]]] - Přihlášení k účtu", + "de": "[[[SERVERNAME]]] - Konto-Login", + "en": "[[[SERVERNAME]]] - Account Login", + "nl": "[[[SERVERNAME]]] - Inloggen account", + "fr": "[[[SERVERNAME]]] - Connexion au compte", + "ja": "[[[SERVERNAME]]]-アカウントログイン", + "ru": "[[[SERVERNAME]]] - Вход в аккаунт", + "zh-chs": "[[[SERVERNAME]]]-帐户登录", + "xloc": [ + "account-login.html->0", + "account-login.html->2->1->1->0->1->1", + "account-login.txt" + ] + }, + { + "cs": "[[[SERVERNAME]]] - Reset účtu", + "de": "[[[SERVERNAME]]] - Zurücksetzen des Kontos", + "en": "[[[SERVERNAME]]] - Account Reset", + "nl": "[[[SERVERNAME]]] - Account Reset", + "fr": "[[[SERVERNAME]]] - Réinitialisation du compte", + "ja": "[[[SERVERNAME]]]-アカウントのリセット", + "ru": "[[[SERVERNAME]]] - Сброс учетной записи", + "zh-chs": "[[[SERVERNAME]]]-帐户重置", + "xloc": [ + "account-reset.html->0", + "account-reset.txt" + ] + }, + { + "cs": "[[[SERVERNAME]]] - Instalace agenta", + "de": "[[[SERVERNAME]]] - Agenteninstallation", + "en": "[[[SERVERNAME]]] - Agent Installation", + "nl": "[[[SERVERNAME]]] - Agent installatie", + "fr": "[[[SERVERNAME]]] - Installation de l'agent", + "ja": "[[[SERVERNAME]]]-エージェントのインストール", + "ru": "[[[SERVERNAME]]] - Установка агента", + "zh-chs": "[[[SERVERNAME]]]-代理程序安装", + "xloc": [ + "mesh-invite.html->2->1->1->0->1->1" + ] + }, + { + "cs": "[[[SERVERNAME]]] - Ověření e-mailem", + "de": "[[[SERVERNAME]]] - E-Mail-Überprüfung", + "en": "[[[SERVERNAME]]] - Email Verification", + "nl": "[[[SERVERNAME]]] - E-mail Verificatie", + "fr": "[[[SERVERNAME]]] - Vérification E-mail", + "ja": "[[[SERVERNAME]]]-メールの確認", + "ru": "[[[SERVERNAME]]] - подтверждение по электронной почте", + "zh-chs": "[[[SERVERNAME]]]-电子邮件验证", + "xloc": [ + "account-check.html->0", + "account-check.txt" + ] + }, + { + "cs": "[[[SERVERNAME]]] - Pozvánka", + "de": "[[[SERVERNAME]]] - Einladung", + "en": "[[[SERVERNAME]]] - Invitation", + "nl": "[[[SERVERNAME]]] - Uitnodiging", + "fr": "[[[SERVERNAME]]] - Invitation", + "ja": "[[[SERVERNAME]]]-招待", + "ru": "[[[SERVERNAME]]] - Приглашение", + "zh-chs": "[[[SERVERNAME]]]-邀请", + "xloc": [ + "mesh-invite.html->0", + "mesh-invite.txt" + ] + }, + { + "cs": "[[[SERVERNAME]]] - Ověření", + "de": "[[[SERVERNAME]]] - Überprüfung", + "en": "[[[SERVERNAME]]] - Verification", + "nl": "[[[SERVERNAME]]] - Verificatie", + "fr": "[[[SERVERNAME]]] - Vérification", + "ja": "[[[SERVERNAME]]]-確認", + "ru": "[[[SERVERNAME]]] - Подтверждение", + "zh-chs": "[[[SERVERNAME]]]-验证", + "xloc": [ + "account-check.html->2->1->1->0->1->1", + "account-reset.html->2->1->1->0->1->1" + ] + }, + { + "cs": "[[[USERNAME]]]", + "de": "[[[USERNAME]]]", + "en": "[[[USERNAME]]]", + "fr": "[[[USERNAME]]]", + "nl": "[[[USERNAME]]]", + "ja": "[[[USERNAME]]]", + "ru": "[[[USERNAME]]]", + "zh-chs": "[[[USERNAME]]]", + "xloc": [ + "account-invite.html->2", + "mesh-invite.html->2" ] }, { @@ -19834,13 +27491,18 @@ "de": "\\\\", "en": "\\\\", "es": "\\\\", + "fr": "\\\\", + "hi": "\\\\", "ja": "\\\\", + "ko": "\\\\", "nl": "\\\\", + "pt": "\\\\", "ru": "\\\\", + "zh-chs": "\\\\", "xloc": [ - "default-mobile.handlebars->9->239", - "default-mobile.handlebars->9->240", - "default-mobile.handlebars->9->241" + "default-mobile.handlebars->9->243", + "default-mobile.handlebars->9->244", + "default-mobile.handlebars->9->245" ] }, { @@ -19848,11 +27510,16 @@ "de": "\\\\'", "en": "\\\\'", "es": "\\\\'", + "fr": "\\\\'", + "hi": "\\\\'", "ja": "\\\\'", + "ko": "\\\\'", "nl": "\\\\'", + "pt": "\\\\'", "ru": "\\\\'", + "zh-chs": "\\\\'", "xloc": [ - "default.handlebars->25->1458" + "default.handlebars->27->1608" ] }, { @@ -19860,14 +27527,17 @@ "de": "eines hinzufügen", "en": "add one", "es": "Agregar Uno", - "fr": "ajoute un", + "fr": "en ajouter un", + "hi": "एक जोड़ें", "ja": "ひとつ追加", + "ko": "하나 추가", "nl": "Voeg toe", "pt": "Adicione um", "ru": "добавить", + "zh-chs": "加一", "xloc": [ - "default.handlebars->25->197", - "default.handlebars->25->199" + "default.handlebars->27->181", + "default.handlebars->27->183" ] }, { @@ -19875,36 +27545,75 @@ "de": "Admin", "en": "admin", "es": "admin", + "fr": "administrateur", + "hi": "व्यवस्थापक", "ja": "管理者", + "ko": "관리자", "nl": "Beheerder", "pt": "správce", "ru": "админ", + "zh-chs": "管理員", "xloc": [ - "default.handlebars->25->242" + "default.handlebars->27->226" + ] + }, + { + "cs": "a postupujte podle pokynů.", + "de": "und folgen Sie den Anweisungen.", + "en": "and follow the instructions.", + "fr": "et suivez les instructions.", + "nl": "en volg de instructies.", + "ja": "指示に従ってください。", + "ru": "и следуйте инструкциям.", + "zh-chs": "并按照说明进行操作。", + "xloc": [ + "mesh-invite.html->2->15->1" ] }, { "cs": "a jeho zdroj může být stažen z", + "de": "und seine Quelle kann von heruntergeladen werden", "en": "and its source can be downloaded from", "es": "y su codigo fuente se puede descargar desde", + "fr": "et les sources sont téléchargeables depuis", + "hi": "और इसके स्रोत से डाउनलोड किया जा सकता है", "ja": "そのソースはからダウンロードできます", + "ko": "소스는", "nl": "en de bron kan worden gedownload van", "pt": "e sua fonte pode ser baixada de", "ru": "и исходный код можно скачать с", + "zh-chs": "它的來源可以從", "xloc": [ "terms-mobile.handlebars->container->page_content->column_l->75->1", "terms.handlebars->container->column_l->75->1" ] }, + { + "cs": "klikněte zde", + "de": "hier klicken", + "en": "click here", + "nl": "Klik hier", + "fr": "cliquez ici", + "ja": "ここをクリック", + "ru": "кликните сюда", + "zh-chs": "点击这里", + "xloc": [ + "mesh-invite.html->2->15->1->1" + ] + }, { "cs": "vytvořením skupiny zařízení a to kliknutím sem", "de": "hier klicken, um eine Gerätegruppe zu erstellen", "en": "click here to create a device group", "es": "Haga clic aquí para crear un grupo de dispositivos", + "fr": "Créer un nouveau groupe d'appareils", + "hi": "डिवाइस समूह बनाने के लिए यहां क्लिक करें", "ja": "ここをクリックしてデバイスグループを作成します", + "ko": "장치 그룹을 만들려면 여기를 클릭하십시오", "nl": "klik hier om een apparaatgroep te maken", "pt": "clique aqui para criar um grupo de dispositivos", "ru": "для создания группы устройств нажмите сюда", + "zh-chs": "單擊此處創建設備組", "xloc": [ "default.handlebars->container->column_l->p1->NoMeshesPanel->1->1->0->3->getStarted1->1->0" ] @@ -19914,10 +27623,14 @@ "de": "zum Wiederverbinden klicken", "en": "click to reconnect", "es": "Haga clic para volver a conectar", + "fr": "Se reconnecter", + "hi": "पुन: कनेक्ट करने के लिए क्लिक करें", "ja": "クリックして再接続", + "ko": "다시 연결하려면 클릭", "nl": "klik om opnieuw verbinding te maken", "pt": "clique para reconectar", "ru": "нажмите для переподключения", + "zh-chs": "點擊重新連接", "xloc": [ "default-mobile.handlebars->container->page_content->column_l->p0->1->p0message->2->0", "default.handlebars->container->column_l->p0->p0message->2->0" @@ -19925,14 +27638,19 @@ }, { "cs": "console.txt", + "de": "console.txt", "en": "console.txt", "es": "Consola.txt", + "fr": "console.txt", + "hi": "console.txt", "ja": "console.txt", + "ko": "console.txt", "nl": "console.txt", "pt": "console.txt", "ru": "console.txt", + "zh-chs": "console.txt", "xloc": [ - "default.handlebars->25->698" + "default.handlebars->27->799" ] }, { @@ -19940,51 +27658,119 @@ "de": "kopieren", "en": "copy", "es": "Copiar", + "fr": "Copier", + "hi": "प्रतिलिपि", "ja": "コピー", + "ko": "부", "nl": "kopiëren", "pt": "Copiar", "ru": "копировать", + "zh-chs": "複製", "xloc": [ - "default-mobile.handlebars->9->89", - "default.handlebars->25->1187" + "default-mobile.handlebars->9->92", + "default.handlebars->27->1317" ] }, + { + "cs": "devicelist.csv", + "de": "devicelist.csv", + "en": "devicelist.csv", + "es": "devicelist.csv", + "fr": "devicelist.csv", + "hi": "devicelist.csv", + "ja": "devicelist.csv", + "ko": "devicelist.csv", + "nl": "devicelist.csv", + "pt": "devicelist.csv", + "ru": "devicelist.csv", + "zh-chs": "devicelist.csv", + "xloc": [ + "default.handlebars->27->391", + "default.handlebars->27->396" + ] + }, + { + "cs": "devicelist.json", + "de": "devicelist.json", + "en": "devicelist.json", + "es": "devicelist.json", + "fr": "devicelist.json", + "hi": "devicelist.json", + "ja": "devicelist.json", + "ko": "devicelist.json", + "nl": "devicelist.json", + "pt": "devicelist.json", + "ru": "devicelist.json", + "zh-chs": "devicelist.json", + "xloc": [ + "default.handlebars->27->393", + "default.handlebars->27->397" + ] + }, + { + "cs": "kódování", + "de": "Codierung", + "en": "encoding", + "fr": "encodage", + "hi": "एन्कोडिंग", + "ja": "エンコーディング", + "ko": "부호화", + "nl": "codering", + "pt": "codificação", + "ru": "кодирование", + "zh-chs": "編碼方式" + }, { "cs": "eventslist.csv", + "de": "eventslist.csv", "en": "eventslist.csv", "es": "eventslist.csv", + "fr": "eventslist.csv", + "hi": "eventslist.csv", "ja": "eventslist.csv", + "ko": "eventslist.csv", "nl": "eventslist.csv", "pt": "eventslist.csv", "ru": "eventslist.csv", + "zh-chs": "eventslist.csv", "xloc": [ - "default.handlebars->25->1196", - "default.handlebars->25->1201" + "default.handlebars->27->1326", + "default.handlebars->27->1331" ] }, { "cs": "eventslist.json", + "de": "eventslist.json", "en": "eventslist.json", "es": "eventslist.json", + "fr": "eventslist.json", + "hi": "eventslist.json", "ja": "eventslist.json", + "ko": "eventslist.json", "nl": "eventslist.json", "pt": "eventslist.json", - "ru": "eventslist.csv", + "ru": "eventslist.json", + "zh-chs": "eventslist.json", "xloc": [ - "default.handlebars->25->1198", - "default.handlebars->25->1202" + "default.handlebars->27->1328", + "default.handlebars->27->1332" ] }, { "cs": "e-mail@example.com", + "de": "example@email.com", "en": "example@email.com", "es": "ejemplo@email.com", + "fr": "example@email.com", + "hi": "example@email.com", "ja": "example@email.com", + "ko": "example@email.com", "nl": "voorbeeld@email.nl", "pt": "example@email.com", "ru": "example@email.com", + "zh-chs": "example@email.com", "xloc": [ - "default.handlebars->25->284" + "default.handlebars->27->271" ] }, { @@ -19993,23 +27779,33 @@ "en": "free", "es": "Gratis", "fr": "libre", + "hi": "नि: शुल्क", "ja": "無料", + "ko": "비어 있는", "nl": "vrij", "pt": "livre", "ru": "свободно", + "zh-chs": "自由", "xloc": [ - "default.handlebars->25->1424" + "default.handlebars->27->1571" ] }, { "cs": "s:", + "de": "g:", "en": "g:", "es": "g:", + "fr": "g:", + "hi": "छ:", + "ja": "g:", + "ko": "지:", "nl": "g:", + "pt": "g:", "ru": "г:", + "zh-chs": "G:", "xloc": [ - "default.handlebars->25->406", - "default.handlebars->25->407" + "default.handlebars->27->406", + "default.handlebars->27->407" ] }, { @@ -20017,21 +27813,32 @@ "de": "gruppe:", "en": "group:", "es": "grupo:", + "fr": "groupe :", + "hi": "समूह:", + "ja": "グループ:", + "ko": "그룹:", "nl": "groep:", + "pt": "grupo:", "ru": "группа:", + "zh-chs": "組:", "xloc": [ - "default.handlebars->25->404", - "default.handlebars->25->405" + "default.handlebars->27->404", + "default.handlebars->27->405" ] }, { "cs": "http://creativecommons.org/licenses/by/2.0/uk/legalcode", + "de": "http://creativecommons.org/licenses/by/2.0/uk/legalcode", "en": "http://creativecommons.org/licenses/by/2.0/uk/legalcode", "es": "http://creativecommons.org/licenses/by/2.0/uk/legalcode", + "fr": "http://creativecommons.org/licenses/by/2.0/uk/legalcode", + "hi": "http://creativecommons.org/licenses/by/2.0/uk/legalcode", "ja": "http://creativecommons.org/licenses/by/2.0/uk/legalcode", + "ko": "http://creativecommons.org/licenses/by/2.0/uk/legalcode", "nl": "http://creativecommons.org/licenses/by/2.0/uk/legalcode", "pt": "http://creativecommons.org/licenses/by/2.0/uk/legalcode", "ru": "http://creativecommons.org/licenses/by/2.0/uk/legalcode", + "zh-chs": "http://creativecommons.org/licenses/by/2.0/uk/legalcode", "xloc": [ "terms-mobile.handlebars->container->page_content->column_l->75->1->3", "terms.handlebars->container->column_l->75->1->3" @@ -20039,12 +27846,17 @@ }, { "cs": "http://jquery.com/", + "de": "http://jquery.com/", "en": "http://jquery.com/", "es": "http://jquery.com/", + "fr": "http://jquery.com/", + "hi": "http://jquery.com/", "ja": "http://jquery.com/", + "ko": "http://jquery.com/", "nl": "http://jquery.com/", "pt": "http://jquery.com/", "ru": "http://jquery.com/", + "zh-chs": "http://jquery.com/", "xloc": [ "terms-mobile.handlebars->container->page_content->column_l->47->1->1", "terms.handlebars->container->column_l->47->1->1" @@ -20052,12 +27864,17 @@ }, { "cs": "http://jqueryui.com/", + "de": "http://jqueryui.com/", "en": "http://jqueryui.com/", "es": "http://jqueryui.com/", + "fr": "http://jqueryui.com/", + "hi": "http://jqueryui.com/", "ja": "http://jqueryui.com/", + "ko": "http://jqueryui.com/", "nl": "http://jqueryui.com/", "pt": "http://jqueryui.com/", "ru": "http://jqueryui.com/", + "zh-chs": "http://jqueryui.com/", "xloc": [ "terms-mobile.handlebars->container->page_content->column_l->53->1->1", "terms.handlebars->container->column_l->53->1->1" @@ -20065,12 +27882,17 @@ }, { "cs": "http://www.openssl.org/source/license.html", + "de": "http://www.openssl.org/source/license.html", "en": "http://www.openssl.org/source/license.html", "es": "http://www.openssl.org/source/license.html", + "fr": "http://www.openssl.org/source/license.html", + "hi": "http://www.openssl.org/source/license.html", "ja": "http://www.openssl.org/source/license.html", + "ko": "http://www.openssl.org/source/license.html", "nl": "http://www.openssl.org/source/license.html", "pt": "http://www.openssl.org/source/license.html", "ru": "http://www.openssl.org/source/license.html", + "zh-chs": "http://www.openssl.org/source/license.html", "xloc": [ "terms-mobile.handlebars->container->page_content->column_l->25->1->0", "terms.handlebars->container->column_l->25->1->0" @@ -20078,12 +27900,17 @@ }, { "cs": "http://www.webtoolkit.info/javascript-base64.html", + "de": "http://www.webtoolkit.info/javascript-base64.html", "en": "http://www.webtoolkit.info/javascript-base64.html", "es": "http://www.webtoolkit.info/javascript-base64.html", + "fr": "http://www.webtoolkit.info/javascript-base64.html", + "hi": "http://www.webtoolkit.info/javascript-base64.html", "ja": "http://www.webtoolkit.info/javascript-base64.html", + "ko": "http://www.webtoolkit.info/javascript-base64.html", "nl": "http://www.webtoolkit.info/javascript-base64.html", "pt": "http://www.webtoolkit.info/javascript-base64.html", "ru": "http://www.webtoolkit.info/javascript-base64.html", + "zh-chs": "http://www.webtoolkit.info/javascript-base64.html", "xloc": [ "terms-mobile.handlebars->container->page_content->column_l->75->1->1", "terms-mobile.handlebars->container->page_content->column_l->75->1->5", @@ -20093,12 +27920,17 @@ }, { "cs": "https://github.com/kanaka/noVNC/blob/master/LICENSE.txt", + "de": "https://github.com/kanaka/noVNC/blob/master/LICENSE.txt", "en": "https://github.com/kanaka/noVNC/blob/master/LICENSE.txt", "es": "https://github.com/kanaka/noVNC/blob/master/LICENSE.txt", + "fr": "https://github.com/kanaka/noVNC/blob/master/LICENSE.txt", + "hi": "https://github.com/kanaka/noVNC/blob/master/LICENSE.txt", "ja": "https://github.com/kanaka/noVNC/blob/master/LICENSE.txt", + "ko": "https://github.com/kanaka/noVNC/blob/master/LICENSE.txt", "nl": "https://github.com/kanaka/noVNC/blob/master/LICENSE.txt", "pt": "https://github.com/kanaka/noVNC/blob/master/LICENSE.txt", "ru": "https://github.com/kanaka/noVNC/blob/master/LICENSE.txt", + "zh-chs": "https://github.com/kanaka/noVNC/blob/master/LICENSE.txt", "xloc": [ "terms-mobile.handlebars->container->page_content->column_l->61->1->0", "terms.handlebars->container->column_l->61->1->0" @@ -20106,12 +27938,17 @@ }, { "cs": "https://github.com/ryrych/rcarousel/blob/master/widget/license", + "de": "https://github.com/ryrych/rcarousel/blob/master/widget/license", "en": "https://github.com/ryrych/rcarousel/blob/master/widget/license", "es": "https://github.com/ryrych/rcarousel/blob/master/widget/license", + "fr": "https://github.com/ryrych/rcarousel/blob/master/widget/license", + "hi": "https://github.com/ryrych/rcarousel/blob/master/widget/license", "ja": "https://github.com/ryrych/rcarousel/blob/master/widget/license", + "ko": "https://github.com/ryrych/rcarousel/blob/master/widget/license", "nl": "https://github.com/ryrych/rcarousel/blob/master/widget/license", "pt": "https://github.com/ryrych/rcarousel/blob/master/widget/license", "ru": "https://github.com/ryrych/rcarousel/blob/master/widget/license", + "zh-chs": "https://github.com/ryrych/rcarousel/blob/master/widget/license", "xloc": [ "terms-mobile.handlebars->container->page_content->column_l->67->1->0", "terms.handlebars->container->column_l->67->1->0" @@ -20119,35 +27956,120 @@ }, { "cs": "identif., jméno, e-mail, vytvoření, poslední přihlášení, skupiny, faktory ověrování", + "de": "ID, Name, E-Mail, Erstellung, Lastlogin, Gruppen, Authfaktoren", "en": "id, name, email, creation, lastlogin, groups, authfactors", "es": "id, nombre, correo electronico, creacion, ultimo logeo, grupos, factor de autenticacion", + "fr": "id, nom, email, création, lastlogin, groupes, authfactors", + "hi": "आईडी, नाम, ईमेल, निर्माण, lastlogin, समूह, ऑक्टाफ़ेक्टर्स", "ja": "id、名前、電子メール、作成、lastlogin、グループ、authfactors", + "ko": "아이디, 이름, 이메일, 생성, 마지막 로그인, 그룹, 인증 자", "nl": "id, naam, e-mail, aanmaken, laatste inlog, groepen, authenticatiefactors", "pt": "id, nome, email, criação, último login, grupos, fatores de autenticação", "ru": "id, name, email, creation, lastlogin, groups, authfactors", + "zh-chs": "id,名稱,電子郵件,創建,lastlogin,組,authfactors", "xloc": [ - "default.handlebars->25->1239" + "default.handlebars->27->1374" + ] + }, + { + "cs": "id, jméno, jméno, hostitel, ikona, ip, osdesc, stát, jméno skupiny, conn, pwr", + "de": "id, name, rname, host, icon, ip, osdesc, state, gruppenname, conn, pwr", + "en": "id, name, rname, host, icon, ip, osdesc, state, groupname, conn, pwr", + "fr": "id, nom, rname, hôte, icône, ip, osdesc, état, nom de groupe, conn, pwr", + "hi": "आईडी, नाम, rname, होस्ट, आइकन, आईपी, osdesc, राज्य, groupname, कॉन, पेजर", + "ja": "id、name、rname、host、icon、ip、osdesc、state、groupname、conn、pwr", + "ko": "아이디, 이름, rname, 호스트, 아이콘, ip, osdesc, 상태, 그룹 이름, conn, pwr", + "nl": "id, naam, rname, host, icoon, ip, osdesc, status, groepsnaam, conn, pwr", + "pt": "id, nome, rname, host, ícone, ip, osdesc, estado, nome do grupo, conn, pwr", + "ru": "идентификатор, имя, имя, хост, значок, ip, osdesc, состояние, имя группы, conn, pwr", + "zh-chs": "id,名稱,rname,主機,圖標,ip,osdesc,狀態,組名,conn,pwr", + "xloc": [ + "default.handlebars->27->395" ] }, { "cs": "ip:", + "de": "ip:", "en": "ip:", "es": "IP:", + "fr": "ip:", + "hi": "आईपी:", + "ja": "ip:", + "ko": "ip :", "nl": "ip:", + "pt": "ip:", "ru": "ip:", + "zh-chs": "ip:", "xloc": [ - "default.handlebars->25->402", - "default.handlebars->25->403" + "default.handlebars->27->402", + "default.handlebars->27->403" + ] + }, + { + "cs": "požaduje obnovení hesla k účtu, dokončete proces kliknutím na následující odkaz.", + "de": "Wenn Sie ein Zurücksetzen des Kontokennworts anfordern, klicken Sie auf den folgenden Link, um den Vorgang abzuschließen.", + "en": "is requesting an account password reset, click on the following link to complete the process.", + "fr": "demande une réinitialisation du mot de passe du compte, cliquez sur le lien suivant pour terminer le processus.", + "nl": "vraagt om het opnieuw instellen van het wachtwoord van een account, klik op de volgende link om het proces te voltooien.", + "ja": "がアカウントパスワードのリセットを要求している場合は、次のリンクをクリックしてプロセスを完了します。", + "ru": "запрашивает сброс пароля учетной записи, нажмите на следующую ссылку, чтобы завершить процесс.", + "zh-chs": "正在要求重置帐户密码,请单击以下链接以完成该过程。", + "xloc": [ + "account-reset.html->2->3" + ] + }, + { + "cs": "požaduje ověření e-mailem a dokončete proces kliknutím na následující odkaz.", + "de": "Wenn Sie eine E-Mail-Bestätigung anfordern, klicken Sie auf den folgenden Link, um den Vorgang abzuschließen.", + "en": "is requesting email verification, click on the following link to complete the process.", + "fr": "demande une vérification par e-mail, cliquez sur le lien suivant pour terminer le processus.", + "nl": "vraagt om e-mailverificatie, klik op de volgende link om het proces te voltooien.", + "ja": "がメールの確認をリクエストしている場合は、次のリンクをクリックしてプロセスを完了してください。", + "ru": "запрашивает подтверждение по электронной почте, нажмите на следующую ссылку, чтобы завершить процесс.", + "zh-chs": "正在请求电子邮件验证,请单击以下链接以完成该过程。", + "xloc": [ + "account-check.html->2->3" + ] + }, + { + "cs": "vás žádá o instalaci softwaru pro spuštění relace dálkového ovládání.", + "de": "fordert Sie auf, Software zu installieren, um eine Fernsteuerungssitzung zu starten.", + "en": "is requesting you to install software to start a remote control session.", + "fr": "vous demande d'installer un logiciel pour démarrer une session de contrôle à distance.", + "nl": "vraagt u om de software te installeren om een ondersteunings sessie te starten.", + "ja": "リモートコントロールセッションを開始するソフトウェアをインストールするように要求しています。", + "ru": "просит вас установить программное обеспечение, чтобы начать сеанс удаленного управления.", + "zh-chs": "正在要求您安装软件以启动远程控制会话。", + "xloc": [ + "mesh-invite.html->2->5" + ] + }, + { + "cs": "k max, standardně prázdné", + "de": "k max, leer für Standard", + "en": "k max, blank for default", + "fr": "k max, vide par défaut", + "ja": "k max、デフォルトでは空白", + "nl": "k max, blank voor standaard", + "ru": "k max, пусто по умолчанию", + "zh-chs": "k max,默认为空白", + "xloc": [ + "default.handlebars->27->1395" ] }, { "cs": "licencováno pod", + "de": "lizenziert unter der", "en": "licensed under the", "es": "licenciado bajo el", + "fr": "sous licence", + "hi": "के तहत लाइसेंस प्राप्त है", "ja": "の下でライセンス", + "ko": "에 따라 라이센스", "nl": "onder licentie van de", "pt": "licenciado sob o", "ru": "под лицензией", + "zh-chs": "根據", "xloc": [ "terms-mobile.handlebars->container->page_content->column_l->75->1", "terms.handlebars->container->column_l->75->1" @@ -20158,13 +28080,17 @@ "de": "verschieben", "en": "move", "es": "Mover", + "fr": "Déplacer", + "hi": "चाल", "ja": "動く", + "ko": "움직임", "nl": "verplaatsen", "pt": "Mover", "ru": "переместить", + "zh-chs": "移動", "xloc": [ - "default-mobile.handlebars->9->90", - "default.handlebars->25->1188" + "default-mobile.handlebars->9->93", + "default.handlebars->27->1318" ] }, { @@ -20172,88 +28098,131 @@ "de": "öffnen", "en": "open", "es": "Abrir", + "fr": "ouvert", + "hi": "खुला हुआ", "ja": "開いた", + "ko": "열다", "nl": "Open", "pt": "abrir", - "ru": "открыть" + "ru": "открыть", + "zh-chs": "打開" }, { "cs": "servererrors.txt", + "de": "servererrors.txt", "en": "servererrors.txt", "es": "servererrors.txt", + "fr": "servererrors.txt", + "hi": "servererrors.txt", "ja": "servererrors.txt", + "ko": "servererrors.txt", "nl": "servererrors.txt", "pt": "servererrors.txt", "ru": "servererrors.txt", + "zh-chs": "servererrors.txt", "xloc": [ - "default.handlebars->25->978" + "default.handlebars->27->1083" ] }, { "cs": "servertrace.csv", + "de": "servertrace.csv", "en": "servertrace.csv", "es": "servertrace.csv", + "fr": "servertrace.csv", + "hi": "servertrace.csv", "ja": "servertrace.csv", + "ko": "servertrace.csv", "nl": "servertrace.csv", "pt": "servertrace.csv", "ru": "servertrace.csv", + "zh-chs": "servertrace.csv", "xloc": [ - "default.handlebars->25->1457" + "default.handlebars->27->1606" ] }, { "cs": "š:", + "de": "t:", "en": "t:", "es": "t:", + "fr": "t:", + "hi": "टी:", + "ja": "т:", + "ko": "티:", "nl": "t:", + "pt": "t:", "ru": "т:", + "zh-chs": "t:", "xloc": [ - "default.handlebars->25->410", - "default.handlebars->25->411" + "default.handlebars->27->410", + "default.handlebars->27->411" ] }, { "cs": "štítek:", + "de": "Etikett:", "en": "tag:", "es": "etiqueta:", + "fr": "étiquette:", + "hi": "टैग:", + "ja": "鬼ごっこ:", + "ko": "꼬리표:", "nl": "tag:", + "pt": "tag:", "ru": "тег:", + "zh-chs": "標籤:", "xloc": [ - "default.handlebars->25->408", - "default.handlebars->25->409" + "default.handlebars->27->408", + "default.handlebars->27->409" ] }, { "cs": "time, conn.agent, conn.users, conn.usersessions, conn.relaysession, conn.intelamt, mem.external, mem.heapused, mem.heaptotal, mem.rss", + "de": "Zeit, conn.agent, conn.users, conn.usersessions, conn.relaysession, conn.intelamt, mem.external, mem.heapused, mem.heaptotal, mem.rss", "en": "time, conn.agent, conn.users, conn.usersessions, conn.relaysession, conn.intelamt, mem.external, mem.heapused, mem.heaptotal, mem.rss", + "fr": "temps, conn.agent, conn.users, conn.usersessions, conn.relaysession, conn.intelamt, mem.external, mem.heapused, mem.heaptotal, mem.rss", + "hi": "समय, con.agent, con.users, conn.usersession, con.relaysession, conn.intelamt, mem.external, mem.heapused, mem.heaptotal, mem.rss", "ja": "time、conn.agent、conn.users、conn.usersessions、conn.relaysession、conn.intelamt、mem.external、mem.heapused、mem.heaptotal、mem.rss", + "ko": "시간, 연결 에이전트, 연결 사용자, 연결 사용자 세션, 연결 릴레이 세션, 연결 정보, mem.external, mem.heapused, mem.heaptotal, mem.rss", "nl": "tijd, conn.agent, conn.gebruikers, conn.gebruikerssessies, conn.relaysessie, conn.intelamt, mem.extern, mem.heapused, mem.heaptotaal, mem.rss", "pt": "tempo, conn.agente, conn.usuários.usersessions, conn.relaysession, conn.intelamt, mem.externo mem.amontoado, mem.heaptotal, mem.rss", "ru": "time, conn.agent, conn.users, conn.usersessions, conn.relaysession, conn.intelamt, mem.external, mem.heapused, mem.heaptotal, mem.rss", + "zh-chs": "時間,conn.agent,conn.users,conn.usersessions,conn.relaysession,conn.intelamt,mem.external,mem.heapused,mem.heaptotal,mem.rss", "xloc": [ - "default.handlebars->25->1437" + "default.handlebars->27->1584" ] }, { "cs": "time, source, message", + "de": "Zeit, Quelle, Nachricht", "en": "time, source, message", "es": "Tiempo, fuente, mensaje", + "fr": "heure, source, message", + "hi": "समय, स्रोत, संदेश", "ja": "時間、ソース、メッセージ", + "ko": "시간, 출처, 메시지", "nl": "tijd, bron, bericht", "pt": "hora, fonte, mensagem", "ru": "time, source, message", + "zh-chs": "時間,來源,訊息", "xloc": [ - "default.handlebars->25->1456" + "default.handlebars->27->1605" ] }, { "cs": "time, type, action, user, message", + "de": "Zeit, Typ, Aktion, Benutzer, Nachricht", "en": "time, type, action, user, message", "es": "hora, tipo, acción, usuario, mensaje", + "fr": "heure, type, action, utilisateur, message", + "hi": "समय, प्रकार, क्रिया, उपयोगकर्ता, संदेश", "ja": "時間、タイプ、アクション、ユーザー、メッセージ", + "ko": "시간, 유형, 행동, 사용자, 메시지", "nl": "tijd, type, actie, gebruiker, bericht", "pt": "hora, tipo, ação, usuário, mensagem", - "ru": "time, type, action, user, message" + "ru": "time, type, action, user, message", + "zh-chs": "時間,類型,動作,用戶,消息" }, { "cs": "celkem", @@ -20261,71 +28230,130 @@ "en": "total", "es": "Total", "fr": "total", + "hi": "कुल", "ja": "合計", + "ko": "합계", "nl": "totaal", "pt": "total", "ru": "всего", + "zh-chs": "總", "xloc": [ - "default.handlebars->25->1425" + "default.handlebars->27->1572" ] }, { "cs": "u:", + "de": "u:", "en": "u:", "es": "u:", + "fr": "u:", + "hi": "यू:", + "ja": "u:", + "ko": "유:", "nl": "u:", + "pt": "u:", "ru": "п:", + "zh-chs": "你:", "xloc": [ - "default.handlebars->25->400", - "default.handlebars->25->401" + "default.handlebars->27->400", + "default.handlebars->27->401" ] }, + { + "cs": "nedefinováno", + "de": "nicht definiert", + "en": "undefined", + "fr": "indéfini", + "hi": "अपरिभाषित", + "ja": "未定義", + "ko": "찾으시는 주소가 없습니다", + "nl": "onbepaald", + "pt": "Indefinido", + "ru": "не определено", + "zh-chs": "未定義" + }, { "cs": "uživatel:", + "de": "Benutzer:", "en": "user:", "es": "usuario:", + "fr": "utilisateur:", + "hi": "उपयोगकर्ता:", + "ja": "ユーザー:", + "ko": "사용자:", "nl": "gebruiker:", + "pt": "do utilizador:", "ru": "пользователь:", + "zh-chs": "用戶:", "xloc": [ - "default.handlebars->25->398", - "default.handlebars->25->399" + "default.handlebars->27->398", + "default.handlebars->27->399" ] }, { "cs": "userlist.csv", + "de": "userlist.csv", "en": "userlist.csv", "es": "userlist.csv", + "fr": "userlist.csv", + "hi": "userlist.csv", "ja": "userlist.csv", + "ko": "userlist.csv", "nl": "userlist.csv", "pt": "Lista de usuários.csv", "ru": "userlist.csv", + "zh-chs": "userlist.csv", "xloc": [ - "default.handlebars->25->1235", - "default.handlebars->25->1240" + "default.handlebars->27->1370", + "default.handlebars->27->1375" ] }, { "cs": "userlist.json", + "de": "userlist.json", "en": "userlist.json", "es": "userlist.json", + "fr": "userlist.json", + "hi": "userlist.json", "ja": "userlist.json", + "ko": "userlist.json", "nl": "userlist.json", "pt": "Lista de usuários.json", "ru": "userlist.json", + "zh-chs": "userlist.json", "xloc": [ - "default.handlebars->25->1237", - "default.handlebars->25->1241" + "default.handlebars->27->1372", + "default.handlebars->27->1376" ] }, { + "cs": "utc, čas, typ, akce, uživatel, zařízení, zpráva", + "de": "utc, Zeit, Typ, Aktion, Benutzer, Gerät, Nachricht", "en": "utc, time, type, action, user, device, message", + "fr": "utc, temps, type, action, utilisateur, appareil, message", + "hi": "utc, time, type, action, user, device, message", + "ja": "utc、時間、タイプ、アクション、ユーザー、デバイス、メッセージ", + "ko": "utc, 시간, 유형, 행동, 사용자, 장치, 메시지", + "nl": "utc, tiid, type, actie, bebruiker, apparaat, bericht", + "pt": "utc, hora, tipo, ação, usuário, dispositivo, mensagem", + "ru": "utc, время, тип, действие, пользователь, устройство, сообщение", + "zh-chs": "utc,時間,類型,操作,用戶,設備,消息", "xloc": [ - "default.handlebars->25->1200" + "default.handlebars->27->1330" ] }, { + "cs": "{0} - Instalace agenta", + "de": "{0} - Agenteninstallation", "en": "{0} - Agent Installation", + "fr": "{0} {0} - Installation de l'agent", + "hi": "{0} - एजेंट स्थापना", + "ja": "{0}-エージェントのインストール", + "ko": "{0}-에이전트 설치", + "nl": "{0} - Agent Installatie", + "pt": "{0} - Instalação do agente", "ru": "{0} - установка агента", + "zh-chs": "{0}-代理安裝", "xloc": [ "agentinvite.handlebars->3->2" ] @@ -20335,12 +28363,16 @@ "de": "{0} GB", "en": "{0} Gb", "es": "{0} Gb", + "fr": "{0} Gb", + "hi": "{0} जी.बी.", "ja": "{0} Gb", + "ko": "{0} Gb", "nl": "{0} Gb", "pt": "{0} Gb", "ru": "{0} Гб", + "zh-chs": "{0} Gb", "xloc": [ - "default.handlebars->25->1168" + "default.handlebars->27->1297" ] }, { @@ -20348,12 +28380,16 @@ "de": "{0} kB", "en": "{0} Kb", "es": "{0} Kb", + "fr": "{0} Kb", + "hi": "{0} Kb", "ja": "{0} Kb", + "ko": "{0} 파운드", "nl": "{0} Kb", "pt": "{0} Kb", "ru": "{0} Kб", + "zh-chs": "{0} Kb", "xloc": [ - "default.handlebars->25->1166" + "default.handlebars->27->1295" ] }, { @@ -20361,12 +28397,16 @@ "de": "{0} MB", "en": "{0} Mb", "es": "{0} Mb", + "fr": "{0} Mб", + "hi": "{0} एमबी", "ja": "{0} Mb", + "ko": "{0} Mb", "nl": "{0} Mb", "pt": "{0} Mb", "ru": "{0} Mб", + "zh-chs": "{0} Mb", "xloc": [ - "default.handlebars->25->1167" + "default.handlebars->27->1296" ] }, { @@ -20374,12 +28414,16 @@ "de": "{0} MB, {1} MHz", "en": "{0} Mb, {1} Mhz", "es": "{0} Mb, {1} Mhz", + "fr": "{0} Mb, {1} Mhz", + "hi": "{0} एमबी, {1} Mhz", "ja": "{0} Mb、{1} Mhz", + "ko": "{0} Mb, {1} Mhz", "nl": "{0} Mb, {1} Mhz", "pt": "{0} Mb, {1} Mhz", "ru": "{0} Мб, {1} Мгц", + "zh-chs": "{0} Mb,{1} Mhz", "xloc": [ - "default.handlebars->25->77" + "default.handlebars->27->788" ] }, { @@ -20388,12 +28432,15 @@ "en": "{0} active sessions", "es": "{0} sesiones activas.", "fr": "{0} sessions actives", + "hi": "{0} सक्रिय सत्र", "ja": "{0}アクティブセッション", + "ko": "{0} 활성 세션", "nl": "{0} actieve sessies", "pt": "{0} sessões ativas", "ru": "{0} активных сессий", + "zh-chs": "{0}個活動會話", "xloc": [ - "default.handlebars->25->1355" + "default.handlebars->27->1491" ] }, { @@ -20401,12 +28448,16 @@ "de": "{0} B", "en": "{0} b", "es": "{0} b", + "fr": "{0} b", + "hi": "{0} b", "ja": "{0} b", + "ko": "{0} b", "nl": "{0} b", "pt": "{0} b", "ru": "{0} байт", + "zh-chs": "{0} b", "xloc": [ - "default.handlebars->25->1165" + "default.handlebars->27->1294" ] }, { @@ -20415,13 +28466,16 @@ "en": "{0} bytes", "es": "{0} bytes", "fr": "{0} octets", + "hi": "{0} बाइट्स", "ja": "{0}バイト", + "ko": "{0} 바이트", "nl": "{0} bytes", "pt": "{0} bytes", "ru": "{0} байт", + "zh-chs": "{0}個字節", "xloc": [ - "default-mobile.handlebars->9->78", - "default.handlebars->25->1175" + "default-mobile.handlebars->9->81", + "default.handlebars->27->1305" ] }, { @@ -20430,12 +28484,15 @@ "en": "{0} bytes remaining", "es": "Quedan {0} bytes.", "fr": "{0} octets restants", + "hi": "{0} बाइट्स शेष", "ja": "残り{0}バイト", + "ko": "남은 {0} 바이트", "nl": "{0} resterende bytes", "pt": "{0} bytes restantes", "ru": "{0} байт осталось", + "zh-chs": "剩餘{0}個字節", "xloc": [ - "default.handlebars->25->1160" + "default.handlebars->27->1289" ] }, { @@ -20443,12 +28500,16 @@ "de": "{0} Gigabytes verbleibend", "en": "{0} gigabytes remaining", "es": "Queda {0} gigabytes.", + "fr": "{0} Go restant", + "hi": "{0} गीगाबाइट शेष", "ja": "残り{0}ギガバイト", + "ko": "남은 {0} 기가 바이트", "nl": "{0} rsterende gigabytes", "pt": "{0} gigabytes restantes", "ru": "{0} гигабайт осталось", + "zh-chs": "剩餘{0} GB", "xloc": [ - "default.handlebars->25->1163" + "default.handlebars->27->1292" ] }, { @@ -20456,12 +28517,16 @@ "de": "{0} Gruppen", "en": "{0} groups", "es": "{0} grupos", + "fr": "{0} groupes", + "hi": "{0} समूह", "ja": "{0}グループ", + "ko": "{0} 그룹", "nl": "{0} groepen", "pt": "{0} grupos", "ru": "{0} групп", + "zh-chs": "{0}個群組", "xloc": [ - "default.handlebars->25->1339" + "default.handlebars->27->1473" ] }, { @@ -20469,10 +28534,16 @@ "de": "{0} Stunden", "en": "{0} hours", "es": "{0} horas", + "fr": "{0} heure(s)", + "hi": "{0} घंटे", + "ja": "{0}時間", + "ko": "{0} 시간", "nl": "{0} uur", + "pt": "{0} horas", "ru": "{0} часов", + "zh-chs": "{0}小時", "xloc": [ - "default.handlebars->25->169" + "default.handlebars->27->152" ] }, { @@ -20480,22 +28551,30 @@ "de": "{0} Stunde{1}", "en": "{0} hour{1}", "es": "{0} hora {1}", + "fr": "{0} heure{1}", + "hi": "{0} घंटा {1}", "ja": "{0}時間{1}", + "ko": "{0} 시간 {1}", "nl": "{0} uur{1}", "pt": "{0} horas{1}", - "ru": "{0} часов" + "ru": "{0} часов", + "zh-chs": "{0}小時{1}" }, { "cs": "{0} kilobajtů zbývá", "de": "{0} Kilobytes verbleibend", "en": "{0} kilobytes remaining", "es": "Quedan {0} kilobytes", + "fr": "{0} Ko restant", + "hi": "{0} किलोबाइट शेष", "ja": "残り{0}キロバイト", + "ko": "남은 {0} 킬로바이트", "nl": "{0} resterende kilobytes", "pt": "{0} kilobytes restantes", "ru": "{0} килобайт осталось", + "zh-chs": "剩餘{0}千字節", "xloc": [ - "default.handlebars->25->1161" + "default.handlebars->27->1290" ] }, { @@ -20503,13 +28582,17 @@ "de": "{0} Kleinbuchstaben", "en": "{0} lower case", "es": "{0} minúscula", + "fr": "{0} minuscule", + "hi": "{0} लोअर केस", "ja": "{0}小文字", + "ko": "{0} 소문자", "nl": "{0} kleine letters", "pt": "{0} letras minúsculas", "ru": "{0} букв в нижнем регистре", + "zh-chs": "{0}小寫", "xloc": [ - "login-mobile.handlebars->5->31", - "login.handlebars->5->31" + "login-mobile.handlebars->5->34", + "login.handlebars->5->34" ] }, { @@ -20517,12 +28600,16 @@ "de": "{0} Megabytes verbleibend", "en": "{0} megabytes remaining", "es": "Quedan {0} megabytes", + "fr": "{0} Mo restant", + "hi": "{0} मेगाबाइट शेष", "ja": "残り{0}メガバイト", + "ko": "남은 {0} MB", "nl": "{0} resterende megabytes", "pt": "{0} megabytes restantes", "ru": "{0} мегабайт осталось", + "zh-chs": "剩餘{0}兆字節", "xloc": [ - "default.handlebars->25->1162" + "default.handlebars->27->1291" ] }, { @@ -20530,10 +28617,16 @@ "de": "{0} Minuten bis zur Trennung", "en": "{0} minutes until disconnect", "es": "{0} minutos hasta desconectar", + "fr": "{0} minute(s) avant déconnexion", + "hi": "{0} मिनट डिस्कनेक्ट होने तक", + "ja": "切断するまで{0}分", + "ko": "연결을 끊을 때까지 {0} 분", "nl": "{0} minuten totdat de verbinding wordt verbroken", + "pt": "{0} minutos até desconectar", "ru": "{0} минут до разъединения", + "zh-chs": "{0}分鐘直到斷開連接", "xloc": [ - "default.handlebars->25->62" + "default.handlebars->27->62" ] }, { @@ -20541,22 +28634,30 @@ "de": "{0} Minute{1} bis zur Trennung", "en": "{0} minute{1} until disconnect", "es": "{0} minutes {1} hasta desconectar", + "fr": "{0} minute{1} avant déconnexion", + "hi": "डिस्कनेक्ट होने तक {0} मिनट {1}", "ja": "切断するまで{0}分{1}", + "ko": "연결을 끊을 때까지 {0} 분 {1}", "nl": "{0} minuut {1} tot verbreken", "pt": "{0} minutos{1} até desconectar", - "ru": "{0} минут до разъединения" + "ru": "{0} минут до разъединения", + "zh-chs": "{0}分鐘{1},直到斷開連接" }, { "cs": "{0} dalších uživatelů není zobrazeno, vyhledejte je pomocí kolonky pro vyhledávání…", "de": "{0} weitere Benutzer nicht angezeigt, Suchfeld verwenden um weitere Benutzer zu suchen...", "en": "{0} more users not shown, use search box to look for users...", "es": "{0} no se muestran más usuarios, use la opcion de busqueda para encontrar los usuarios...", + "fr": "{0} autres utilisateurs non affichés, utilisez le champ de recherche pour rechercher des utilisateurs...", + "hi": "{0} अधिक उपयोगकर्ता नहीं दिखाए गए, उपयोगकर्ताओं को देखने के लिए खोज बॉक्स का उपयोग करें ...", "ja": "{0}個のユーザーが表示されていません。検索ボックスを使用してユーザーを検索してください...", + "ko": "{0} 명의 사용자가 더 이상 표시되지 않습니다. 검색 창을 사용하여 사용자를 찾으십시오 ...", "nl": "{0} meer gebruikers niet getoond, gebruik zoekvak om gebruikers te zoeken ...", "pt": "{0} mais usuários não exibidos, use a caixa de pesquisa para procurar usuários ...", "ru": "Еще {0} пользователей не показаны, используйте поиск для нахождения пользователей...", + "zh-chs": "{0}未顯示更多用戶,請使用搜索框查找用戶...", "xloc": [ - "default.handlebars->25->1210" + "default.handlebars->27->1340" ] }, { @@ -20565,12 +28666,15 @@ "en": "{0} nodes", "es": "{0} nodos", "fr": "{0} appareil", + "hi": "{0} नोड्स", "ja": "{0}ノード", + "ko": "{0} 노드", "nl": "{0} knooppunten", "pt": "{0} nós", "ru": "{0} устройств", + "zh-chs": "{0}個節點", "xloc": [ - "default.handlebars->25->348" + "default.handlebars->27->338" ] }, { @@ -20578,13 +28682,17 @@ "de": "{0} nicht-alphanumerisch", "en": "{0} non-alphanumeric", "es": "{0} no alfanumérico", + "fr": "{0} non alphanumérique", + "hi": "{0} गैर-अल्फ़ान्यूमेरिक", "ja": "{0}英数字以外", + "ko": "영숫자가 아닌 {0}", "nl": "{0} niet-alfanumeriek", "pt": "{0} não alfanumérico", "ru": "{0} спец. символы", + "zh-chs": "{0}非字母數字", "xloc": [ - "login-mobile.handlebars->5->33", - "login.handlebars->5->33" + "login-mobile.handlebars->5->36", + "login.handlebars->5->36" ] }, { @@ -20592,35 +28700,63 @@ "de": "{0} numerisch", "en": "{0} numeric", "es": "{0} numerico", + "fr": "{0} numérique", + "hi": "{0} संख्यात्मक", "ja": "{0}数値", + "ko": "{0} 숫자", "nl": "{0} numeriek", "pt": "{0} numérico", "ru": "{0} цифры", + "zh-chs": "{0}數字", "xloc": [ - "login-mobile.handlebars->5->32", - "login.handlebars->5->32" + "login-mobile.handlebars->5->35", + "login.handlebars->5->35" ] }, + { + "cs": "{0} sekund {1}", + "de": "{0} Sekunde {1}", + "en": "{0} second {1}", + "es": "{0} segundo {1}", + "fr": "{0} seconde {1}", + "hi": "{0} दूसरा {1}", + "ja": "{0}秒 {1}", + "ko": "{0} 초 {1}", + "nl": "{0} seconde {1}", + "pt": "{0} segundo {1}", + "ru": "{0} секунд {1}", + "zh-chs": "{0}秒{1}" + }, { "cs": "{0} sekund do odpojení", "de": "{0} Sekunden bis zur Trennung", "en": "{0} seconds until disconnect", "es": "{0} segundos hasta desconectar", + "fr": "{0} seconde(s) avant déconnexion", + "hi": "डिस्कनेक्ट होने तक {0} सेकंड", + "ja": "切断するまで{0}秒", + "ko": "연결을 끊을 때까지 {0} 초", "nl": "{0} seconden totdat de verbinding wordt verbroken", + "pt": "{0} segundos até desconectar", "ru": "{0} секунд до разъединения", + "zh-chs": "{0}秒,直到斷開連接", "xloc": [ - "default.handlebars->25->60" + "default.handlebars->27->60" ] }, { "cs": "{0} sekund{1}", "de": "{0} Sekunde{1}", "en": "{0} second{1}", - "es": "{0} segundo {1}", - "ja": "{0}秒{1}", - "nl": "{0} seconde {1}", + "es": "{0} second{1}", + "fr": "{0} seconde{1}", + "hi": "{0} दूसरा {1}", + "ja": "{0} 秒{1}", + "ko": "{0} 초 {1}", + "nl": "{0} seconde{1}", "pt": "{0} segundo{1}", - "ru": "{0} секунд", + "ru": "{0} секунд{1}", + "zh-chs": "{0}秒{1}", "xloc": [ "player.handlebars->3->3" ] @@ -20630,22 +28766,30 @@ "de": "{0} Sekunde{1} bis zur Trennung", "en": "{0} second{1} until disconnect", "es": "{0} segundos {1} hasta desconectar", + "fr": "{0} seconde{1} avant deconnexion", + "hi": "डिस्कनेक्ट होने तक {0} दूसरा {1}", "ja": "切断するまで{0}秒{1}", + "ko": "연결을 끊을 때까지 {0} 초 {1}", "nl": "{0} seconde {1} tot verbreken", "pt": "{0} segundo{1} até desconectar", - "ru": "{0} секунд до разъединения" + "ru": "{0} секунд до разъединения", + "zh-chs": "{0}秒{1},直到斷開連接" }, { "cs": "{0} relací", "de": "{0} Sitzungen", "en": "{0} sessions", "es": "{0} sesiones", + "fr": "{0} sessions", + "hi": "{0} सत्र", "ja": "{0}セッション", + "ko": "{0} 세션", "nl": "{0} sessies", "pt": "{0} sessões", "ru": "{0} сессий", + "zh-chs": "{0}個會話", "xloc": [ - "default.handlebars->25->1214" + "default.handlebars->27->1344" ] }, { @@ -20653,12 +28797,16 @@ "de": "{0} Einstellungen (.msh)", "en": "{0} settings (.msh)", "es": "Configuración {0} (.msh)", + "fr": "{0} paramètres (.msh)", + "hi": "{0} सेटिंग्स (.msh)", "ja": "{0}設定(.msh)", + "ko": "{0} 설정 (.msh)", "nl": "{0} instellingen (.msh)", "pt": "{0} configurações (.msh)", "ru": "{0} настройки (.msh)", + "zh-chs": "{0}設置(.msh)", "xloc": [ - "default.handlebars->25->332" + "default.handlebars->27->321" ] }, { @@ -20666,10 +28814,14 @@ "de": "{0} bis {1}", "en": "{0} to {1}", "es": "{0} a {1}", + "fr": "{0} à {1}", + "hi": "{0} से {1}", "ja": "{0}から{1}", + "ko": "{0}에서 {1}", "nl": "{0} tot {1}", "pt": "{0} para {1}", "ru": "{0} до {1}", + "zh-chs": "{0}至{1}", "xloc": [ "player.handlebars->3->8" ] @@ -20679,13 +28831,17 @@ "de": "{0} Großbuchstaben", "en": "{0} upper case", "es": "{0} mayuscula", + "fr": "{0} majuscule(s)", + "hi": "{0} ऊपरी मामला", "ja": "{0}大文字", + "ko": "{0} 대문자", "nl": "{0} hoofdletters", "pt": "{0} maiúsculas", "ru": "{0} заглавных букв", + "zh-chs": "{0}大寫", "xloc": [ - "login-mobile.handlebars->5->30", - "login.handlebars->5->30" + "login-mobile.handlebars->5->33", + "login.handlebars->5->33" ] }, { @@ -20693,12 +28849,16 @@ "de": "{0} Benutzer", "en": "{0} users", "es": "{0} usuarios", + "fr": "{0} utilisateurs", + "hi": "{0} उपयोगकर्ता", "ja": "{0}ユーザー", + "ko": "{0} 사용자", "nl": "{0} gebruikers", "pt": "{0} usuários", "ru": "{0} пользователей", + "zh-chs": "{0}個用戶", "xloc": [ - "default.handlebars->25->216" + "default.handlebars->27->200" ] }, { @@ -20706,12 +28866,16 @@ "de": "{0}B verbleibend", "en": "{0}b left", "es": "Quedan {0}b ", + "fr": "{0}b restant", + "hi": "{0} b बचा", "ja": "{0} b残り", + "ko": "{0} b 남음", "nl": "{0}b over", "pt": "{0}b restante", "ru": "{0} байт осталось", + "zh-chs": "還剩{0} b", "xloc": [ - "default-mobile.handlebars->9->70" + "default-mobile.handlebars->9->73" ] }, { @@ -20719,12 +28883,16 @@ "de": "{0}G verbleibend", "en": "{0}g left", "es": "Quedan {0}g", + "fr": "{0}g restant", + "hi": "{0} जी बचा", "ja": "{0} g残り", + "ko": "{0} g 남음", "nl": "{0}g over", "pt": "{0}g restante", "ru": "{0} гигабайт осталось", + "zh-chs": "還剩{0} g", "xloc": [ - "default-mobile.handlebars->9->73" + "default-mobile.handlebars->9->76" ] }, { @@ -20732,12 +28900,16 @@ "de": "{0}k in 1 Datei. {1}k maximal", "en": "{0}k in 1 file. {1}k maximum", "es": "{0}k en 1 archivo. {1}k maximo", + "fr": "{0} k dans 1 fichier.{1} k maximum", + "hi": "{0} k 1 फाइल में। {१} k अधिकतम", "ja": "{0} k in 1ファイル。 {1} k最大", + "ko": "1 개의 파일에서 {0} k. {1} k 최대", "nl": "{0}k in 1 bestand. {1}k maximum", "pt": "{0} k em 1 arquivo. {1} k no máximo", "ru": "{0}k в 1 файле. {1}k максимум", + "zh-chs": "{0} k合1檔案。最多{1} k", "xloc": [ - "default.handlebars->25->1170" + "default.handlebars->27->1299" ] }, { @@ -20745,12 +28917,15 @@ "de": "{0}k in {1} Dateien. {2}k maximal", "en": "{0}k in {1} files. {2}k maximum", "es": "{0}k en {1} archivos. {2}k maximo", + "fr": "{0} k dans {1} fichiers.{2} k maximum", "ja": "{0} k個の{1}ファイル。 {2} k最大", + "ko": "{1} 파일에서 {0} k. {2} k 최대", "nl": "{0}k in 1 file. {2}k maximum", "pt": "{0} k em {1} arquivos. {2} k no máximo", "ru": "{0}k в {1} файлах. {2}k максимум", + "zh-chs": "{1}個文件中有{0}個。最多{2} k", "xloc": [ - "default.handlebars->25->1169" + "default.handlebars->27->1298" ] }, { @@ -20758,12 +28933,16 @@ "de": "{0}k verbleibend", "en": "{0}k left", "es": "Quedan {0}k", + "fr": "{0}k restant", + "hi": "{0} k बचा", "ja": "{0} k残り", + "ko": "{0} k 남음", "nl": "{0}k over", "pt": "{0}k restante", "ru": "{0} килобайт осталось", + "zh-chs": "還剩{0} k", "xloc": [ - "default-mobile.handlebars->9->71" + "default-mobile.handlebars->9->74" ] }, { @@ -20771,12 +28950,16 @@ "de": "{0}M verbleibend", "en": "{0}m left", "es": "Quedan {0}m", + "fr": "{0}m restant", + "hi": "{0} m बचा हुआ", "ja": "残り{0} m", + "ko": "{0} 남음", "nl": "{0}m over", "pt": "{0}m restante", "ru": "{0} мегабайт осталось", + "zh-chs": "還有{0} m", "xloc": [ - "default-mobile.handlebars->9->72" + "default-mobile.handlebars->9->75" ] }, { @@ -20784,6 +28967,7 @@ "de": "↺", "en": "↺", "es": "↺", + "fr": "↺", "ja": "↺", "nl": "↺", "pt": "↺", @@ -20797,6 +28981,7 @@ "de": "↻", "en": "↻", "es": "↻", + "fr": "↻", "ja": "↻", "nl": "↻", "pt": "↻", @@ -20810,6 +28995,7 @@ "de": "⇲", "en": "⇲", "es": "⇲", + "fr": "⇲", "ja": "⇲", "nl": "⇲", "pt": "⇲", @@ -20824,6 +29010,7 @@ "de": "◀", "en": "◀", "es": "◀", + "fr": "◀", "ja": "◀", "nl": "◀", "pt": "◀", @@ -20840,6 +29027,7 @@ "de": "♦", "en": "♦", "es": "♦", + "fr": "♦", "ja": "♦", "nl": "♦", "pt": "♦", @@ -20848,6 +29036,7 @@ "agentinvite.handlebars->container->topbar->uiMenuButton", "default.handlebars->container->topbar->1->1->uiMenuButton", "error404.handlebars->container->topbar->uiMenuButton", + "invite.handlebars->container->topbar->uiMenuButton", "login.handlebars->container->topbar->uiMenuButton", "terms.handlebars->container->topbar->uiMenuButton" ] @@ -20857,6 +29046,7 @@ "de": "✓", "en": "✓", "es": "✓", + "fr": "✓", "ja": "✓", "nl": "✓", "pt": "✓", @@ -20864,6 +29054,7 @@ "xloc": [ "default.handlebars->container->column_l->p13->p13filetable->p13bigok->0", "default.handlebars->container->column_l->p2->p2AccountSecurity->3->manageAuthApp->0->authAppSetupCheck->0", + "default.handlebars->container->column_l->p2->p2AccountSecurity->3->manageEmail2FA->0->authEmailSetupCheck->0", "default.handlebars->container->column_l->p2->p2AccountSecurity->3->manageHardwareOtp->0->authKeySetupCheck->0", "default.handlebars->container->column_l->p2->p2AccountSecurity->3->manageOtp->0->authCodesSetupCheck->0", "default.handlebars->container->column_l->p5->p5filetable->bigok->0", @@ -20876,6 +29067,7 @@ "de": "✖", "en": "✖", "es": "✖", + "fr": "✖", "ja": "✖", "nl": "✖", "pt": "✖", @@ -20893,6 +29085,7 @@ "de": "✗", "en": "✗", "es": "✗", + "fr": "✗", "ja": "✗", "nl": "✗", "pt": "✗", diff --git a/views/agentinvite.handlebars b/views/agentinvite.handlebars index 7694e4e8..5d8f9dea 100644 --- a/views/agentinvite.handlebars +++ b/views/agentinvite.handlebars @@ -73,9 +73,7 @@

Remote Agent Installation

- You have been invited to install a software that will allow a remote operator to fully access your computer remotely including the desktop and files. - Only follow the instructions below if this invitation was expected and you know who will be accessing your computer. - Selecting your operation system and follow the instructions below. + You have been invited to install a software that will allow a remote operator to fully access your computer remotely including the desktop and files. Only follow the instructions below if this invitation was expected and you know who will be accessing your computer. Selecting your operation system and follow the instructions below.

diff --git a/views/default-mobile.handlebars b/views/default-mobile.handlebars index 76cd2274..607bb250 100644 --- a/views/default-mobile.handlebars +++ b/views/default-mobile.handlebars @@ -252,6 +252,7 @@

Account Security

@@ -666,6 +667,9 @@ var t = localStorage.getItem('desktopsettings'); if (t != null) { desktopsettings = JSON.parse(t); } applyDesktopSettings(); + + // Arrange the user interface + QV('manageEmail2FA', features & 0x00800000); } function onStateChanged(server, state, prevState, errorCode) { @@ -750,6 +754,7 @@ case 'users': { users = {}; for (var m in message.users) { users[message.users[m]._id] = message.users[m]; } + if (currentUser != null) { currentUser = users[currentUser._id]; } updateUsers(); break; } @@ -761,6 +766,7 @@ case 'meshes': { meshes = {}; for (var m in message.meshes) { meshes[message.meshes[m]._id] = message.meshes[m]; } + if (currentMesh != null) { currentMesh = meshes[currentMesh._id]; } updateMeshes(); updateDevices(); break; @@ -789,10 +795,9 @@ nodes = []; for (var m in message.nodes) { for (var n in message.nodes[m]) { - if (!meshes[m]) { console.log('Invalid mesh (1): ' + m); continue; } message.nodes[m][n].namel = message.nodes[m][n].name.toLowerCase(); if (message.nodes[m][n].rname) { message.nodes[m][n].rnamel = message.nodes[m][n].rname.toLowerCase(); } else { message.nodes[m][n].rnamel = message.nodes[m][n].namel; } - message.nodes[m][n].meshnamel = meshes[m].name.toLowerCase(); + message.nodes[m][n].meshnamel = meshes[m]?meshes[m].name.toLowerCase():'*'; message.nodes[m][n].meshid = m; message.nodes[m][n].state = (message.nodes[m][n].state) ? (message.nodes[m][n].state) : 0; message.nodes[m][n].desc = message.nodes[m][n].desc; @@ -801,6 +806,13 @@ nodes.push(message.nodes[m][n]); } } + + // If we are currently looking at a node this is now gone, change the view. + //if ((currentNode != null) && (getNodeFromId(currentNode._id) == null)) { currentNode = null; go(1); } + + // Change the reference to the current node + if (currentNode != null) { currentNode = getNodeFromId(currentNode._id); } + //onSortSelectChange(); //onSearchInputChanged(); updateDevices(); @@ -897,6 +909,9 @@ userinfo = message.event.account; if (oldsiteadmin != newsiteadmin) updateSiteAdmin(); updateSelf(); + + // If our list of nodes may have changes, request the new list now. + if (message.event.nodeListChange == userinfo._id) { meshserver.send({ action: 'nodes' }); } } break; } @@ -934,7 +949,7 @@ } case 'createmesh': { // A new mesh was created - if (message.event.links[userinfo._id] != null) { // Check if this is a mesh create for a mesh we own. If site administrator, we get all messages so need to ignore some. + if ((meshes[message.event.meshid] == null) && ((userinfo.manageAllDeviceGroups) || (message.event.links[userinfo._id] != null))) { // Check if this is a mesh create for a mesh we own. If site administrator, we get all messages so need to ignore some. meshes[message.event.meshid] = { _id: message.event.meshid, name: message.event.name, mtype: message.event.mtype, desc: message.event.desc, links: message.event.links }; updateMeshes(); updateDevices(); @@ -970,9 +985,9 @@ if ((xxcurrentView == 20) && (currentMesh == meshes[message.event.meshid])) go(2); delete meshes[message.event.meshid]; - // Delete all nodes in that mesh + // Delete all nodes in that mesh, except ones with direct links var newnodes = []; - for (var i in nodes) { if (nodes[i].meshid != message.event.meshid) { newnodes.push(nodes[i]); } } + for (var i in nodes) { if ((nodes[i].meshid != message.event.meshid) || ((userinfo.links != null) && (userinfo.links[nodes[i]._id] != null))) { newnodes.push(nodes[i]); } } nodes = newnodes; // If we are looking at a node in the deleted mesh, move back to "My Devices" @@ -1014,7 +1029,7 @@ if (getNodeFromId(node._id) != null) break; // This node is already known. node.namel = node.name.toLowerCase(); if (node.rname) { node.rnamel = node.rname.toLowerCase(); } else { node.rnamel = node.namel; } - node.meshnamel = meshes[node.meshid].name.toLowerCase(); + node.meshnamel = meshes[node.meshid]?meshes[node.meshid].name.toLowerCase():'*'; node.state = 0; if (!node.icon) node.icon = 1; node.ident = ++nodeShortIdent; @@ -1058,6 +1073,7 @@ node.gpsloc = message.event.node.gpsloc; node.tags = message.event.node.tags; node.userloc = message.event.node.userloc; + node.rdpport = message.event.node.rdpport; if (message.event.node.agent != null) { if (node.agent == null) node.agent = {}; if (message.event.node.agent.ver != null) { node.agent.ver = message.event.node.agent.ver; } @@ -1096,7 +1112,7 @@ for (var i in nodes) { if (nodes[i]._id == message.event.nodeid) { index = i; break; } } if (index != -1) { var node = nodes[index]; - if (meshes[message.event.newMeshId] == null) { + if ((meshes[message.event.newMeshId] == null) && ((userinfo.links == null) || (userinfo.links[node._id] == null))) { // We don't see the new mesh, remove this device // TODO: Correctly disconnect from this node (Desktop/Terminal/Files...) @@ -1105,7 +1121,7 @@ } else { // We see the new mesh, move this device node.meshid = message.event.newMeshId; - node.meshnamel = meshes[message.event.newMeshId].name.toLowerCase(); + node.meshnamel = meshes[message.event.newMeshId]?meshes[message.event.newMeshId].name.toLowerCase():'*'; } updateDevices(); refreshDevice(message.event.nodeid); @@ -1115,7 +1131,7 @@ if (!meshes[node.meshid]) break; // This is a node for a mesh we don't know. Happens when we are site administrator, we get all messages. node.namel = node.name.toLowerCase(); if (node.rname) { node.rnamel = node.rname.toLowerCase(); } else { node.rnamel = node.namel; } - node.meshnamel = meshes[node.meshid].name.toLowerCase(); + node.meshnamel = meshes[node.meshid]?meshes[node.meshid].name.toLowerCase():'*'; node.state = 0; if (!node.icon) node.icon = 1; node.ident = ++nodeShortIdent; @@ -1212,6 +1228,14 @@ // MY ACCOUNT // + function account_manageAuthEmail() { + if (xxdialogMode || ((features & 0x00800000) == 0)) return; + var emailU2Fenabled = ((userinfo.otpekey == 1) && (userinfo.email != null) && (userinfo.emailVerified == true)); + setDialogMode(2, "Email Authentication", 1, function () { + if (emailU2Fenabled != Q('email2facheck').checked) { meshserver.send({ action: 'otpemail', enabled: Q('email2facheck').checked }); } + }, "When enabled, on each login, you will be given the option to receive a login token to you email account for added security." + '

'); + } + function account_manageAuthApp() { if (xxdialogMode || ((features & 4096) == 0)) return; if (userinfo.otpsecret == 1) { account_removeOtp(); } else { account_addOtp(); } @@ -1321,7 +1345,7 @@ if ((userinfo.emailVerified !== true) && (serverinfo.emailcheck == true) && (userinfo.siteadmin != 0xFFFFFFFF)) { setDialogMode(2, "Account Security", 1, null, "Unable to access a device until a email address is verified. This is required for password recovery. Go to the \"My Account\" to change and verify an email address."); return; } // Remind the user to add two factor authentication - if ((features & 0x00040000) && !((userinfo.otpsecret == 1) || (userinfo.otphkeys > 0) || (userinfo.otpkeys > 0))) { setDialogMode(2, "Account Security", 1, null, "Unable to access a device until two-factor authentication is enabled. This is required for extra security. Go to the \"My Account\" and look at the \"Account Security\" section."); return; } + if ((features & 0x00040000) && !((userinfo.otpsecret == 1) || (userinfo.otphkeys > 0) || (userinfo.otpkeys > 0) || ((features & 0x00800000) && (userinfo.otpekey == 1)))) { setDialogMode(2, "Account Security", 1, null, "Unable to access a device until two-factor authentication is enabled. This is required for extra security. Go to the \"My Account\" and look at the \"Account Security\" section."); return; } // We are allowed, let's prompt to information var x = addHtmlValue("Name", ''); @@ -1727,15 +1751,23 @@ if (sort == 0) { // Mesh header nodes.sort(meshSort); - if (nodes[i].meshid != current) { + //if (nodes[i].meshid != current) { + if (((meshes[nodes[i].meshid]?nodes[i].meshid:'*') != current)) { deviceHeaderSet(); var extra = ''; - if (meshes[nodes[i].meshid].mtype == 1) { extra = '' + ", Intel® AMT only" + ''; } + if ((meshes[nodes[i].meshid] != null) && (meshes[nodes[i].meshid].mtype == 1)) { extra = '' + ", Intel® AMT only" + ''; } if (current != null) { if (c == 2) { r += '
'; } if (r != '') { r += ''; } } r += '
'; //r += getMeshActions(meshes[nodes[i].meshid], meshrights); - r += '' + EscapeHtml(meshes[nodes[i].meshid].name) + '' + extra + '
'; - current = nodes[i].meshid; + + if (meshes[nodes[i].meshid]) { + r += '' + EscapeHtml(meshes[nodes[i].meshid].name) + '' + extra + '
'; + current = nodes[i].meshid; + } else { + r += '' + "Individual Devices" + '
'; + current = '*'; + } + displayedMeshes[current] = 1; c = 0; } @@ -1888,13 +1920,12 @@ if ((userinfo.emailVerified !== true) && (serverinfo.emailcheck == true) && (userinfo.siteadmin != 0xFFFFFFFF)) { setDialogMode(2, "Account Security", 1, null, "Unable to access a device until a email address is verified. This is required for password recovery. Go to the \"My Account\" to change and verify an email address."); return; } // Remind the user to add two factor authentication - if ((features & 0x00040000) && !((userinfo.otpsecret == 1) || (userinfo.otphkeys > 0) || (userinfo.otpkeys > 0))) { setDialogMode(2, "Account Security", 1, null, "Unable to access a device until two-factor authentication is enabled. This is required for extra security. Go to the \"My Account\" and look at the \"Account Security\" section."); return; } + if ((features & 0x00040000) && !((userinfo.otpsecret == 1) || (userinfo.otphkeys > 0) || (userinfo.otpkeys > 0) || ((features & 0x00800000) && (userinfo.otpekey == 1)))) { setDialogMode(2, "Account Security", 1, null, "Unable to access a device until two-factor authentication is enabled. This is required for extra security. Go to the \"My Account\" and look at the \"Account Security\" section."); return; } var node = getNodeFromId(nodeid); if (node == null) { goBack(); return; } var mesh = meshes[node.meshid]; - if (mesh == null) { goBack(); return; } - var meshrights = GetMeshRights(mesh); + var meshrights = GetNodeRights(node); if (!currentNode || currentNode._id != node._id || refresh == true) { currentNode = node; @@ -1908,13 +1939,13 @@ var x = ''; // Attribute: Mesh - x += addDeviceAttribute('' + "Group" + '', '' + EscapeHtml(meshes[node.meshid].name) + ''); + if (mesh) { x += addDeviceAttribute('' + "Group" + '', '' + EscapeHtml(meshes[node.meshid].name) + ''); } // Attribute: Name if (node.rname != null) { x += addDeviceAttribute('' + "Name" + '', '' + EscapeHtml(node.rname) + ''); } // Attribute: Host - if ((mesh.mtype == 1) || (node.name != node.host)) { + if ((features & 1) == 0) { // If not WAN-only, local hostname is in use if ((meshrights & 4) != 0) { if (node.host) { x += addDeviceAttribute("Hostname", '' + EscapeHtml(node.host) + ''); @@ -2075,7 +2106,7 @@ if ((currentDevicePanel != 1) && (currentNode != null) && ((meshrights & 8) || (meshrights & 256)) && - (((meshes[currentNode.meshid].mtype == 1) && ((typeof currentNode.intelamt.sku !== 'number') || ((currentNode.intelamt.sku & 8) != 0))) || (currentNode.agent && (currentNode.agent.caps & 1))) + (((currentNode.agent == null) && ((typeof currentNode.intelamt.sku !== 'number') || ((currentNode.intelamt.sku & 8) != 0))) || (currentNode.agent && (currentNode.agent.caps & 1))) ) { menus.push({ n: 'Desktop', f: 'setupDeviceMenu(1)' }); } if ((currentDevicePanel != 2) && (currentNode != null) && (meshrights & 8) && ((meshrights == 0xFFFFFFFF) || ((meshrights & 1024) == 0)) && ((currentNode.mtype == 2) && (currentNode.agent.caps & 4))) { menus.push({ n: 'Files', f: 'setupDeviceMenu(2)' }); } updateFooterMenu(menus); @@ -2199,9 +2230,9 @@ if (amtuser == '') amtuser = 'admin'; var amtpass = Q('dp10password').value; if (amtpass == '') amtuser = ''; - meshserver.send({ action: 'changedevice', nodeid: tag.node._id, intelamt: { user: amtuser, pass: amtpass, tls: Q('dp10tls').value } }); + meshserver.send({ action: 'changedevice', nodeid: tag.node._id, intelamt: { user: amtuser, pass: amtpass, tls: parseInt(Q('dp10tls').value) } }); tag.node.intelamt.user = amtuser; - tag.node.intelamt.tls = Q('dp10tls').value; + tag.node.intelamt.tls = parseInt(Q('dp10tls').value); if (tag.func) { setTimeout(tag.func, 300); } } } @@ -2305,22 +2336,23 @@ // Show the right buttons QV('disconnectbutton1', (deskState != 0)); - QV('connectbutton1', (deskState == 0) && (mesh.mtype == 2) && ((meshrights & 8) || (meshrights & 256))); + QV('connectbutton1', (deskState == 0) && ((meshrights & 8) || (meshrights & 256)) && (currentNode.agent != null) && (currentNode.agent.caps & 1)); QV('connectbutton1h', (deskState == 0) && (meshrights & 8) && - ((mesh.mtype == 1) || - (currentNode.intelamt != null) && - ((currentNode.intelamt.state == 2) && + ( + ((currentNode.intelamt != null) && + (currentNode.intelamt.state == 2) && (currentNode.intelamt.ver != null) && - (typeof currentNode.intelamt.sku == 'number') && - ((currentNode.intelamt.sku & 8) != 0)) + ((currentNode.intelamt.sku == null) || + ((typeof currentNode.intelamt.sku == 'number') && + ((currentNode.intelamt.sku & 8) != 0)))) ) ); // Show the right settings - QV('d7amtkvm', (currentNode.intelamt != null && ((currentNode.intelamt.ver != null) || (mesh.mtype == 1))) && ((deskState == 0) || (desktop.contype == 2))); - QV('d7meshkvm', (mesh.mtype == 2) && ((deskState == false) || (desktop.contype == 1))); + QV('d7amtkvm', (currentNode.intelamt != null && ((currentNode.intelamt.ver != null) || (currentNode.agent == null))) && ((deskState == 0) || (desktop.contype == 2))); + QV('d7meshkvm', ((currentNode.agent != null) && (currentNode.agent.caps & 1) && ((deskState == false) || (desktop.contype == 1)))); // Enable buttons var online = ((currentNode.conn & 1) != 0); // If Agent (1) connected, enable remote desktop @@ -3166,7 +3198,7 @@ x += '

'; var currentMeshLinks = currentMesh.links[userinfo._id]; - if (currentMeshLinks && ((currentMeshLinks.rights & 2) != 0)) { x += ''; } + if (currentMeshLinks && ((currentMeshLinks.rights & 2) != 0)) { x += ''; } /* if ((meshrights & 4) != 0) { @@ -3443,11 +3475,14 @@ if (typeof mesh == 'string') { mesh = meshes[mesh] } if ((mesh == null) || (mesh.links == null)) { return 0; } - // Check direct link permission + // Check if super user + if (userinfo.manageAllDeviceGroups) return 0xFFFFFFFF; + + // Check device group link permission var rights = 0, r = mesh.links[userid]; if (r != null) { + if (rights == 0xFFFFFFFF) { return 0xFFFFFFFF; } // User has full rights thru a device group link, stop here. rights = r.rights; - if (rights == 0xFFFFFFFF) { return rights; } // User has full rights thru a direct link, stop here. } // Check permissions thru user groups @@ -3458,7 +3493,7 @@ if (i.startsWith('ugrp/')) { r = mesh.links[i]; if (r != null) { - if (r.rights == 0xFFFFFFFF) { return r.rights; } // User has full rights thru a user group, stop here. + if (r.rights == 0xFFFFFFFF) { return 0xFFFFFFFF; } // User has full rights thru a user group, stop here. rights |= r.rights; // TODO: Deal with reverse permissions } } @@ -3476,6 +3511,9 @@ if ((mesh == null) || (mesh.links == null)) { return false; } if (mesh.links[userid] != null) { return true; } // User has visilibity thru a direct link + // Check if user user + if (userinfo.manageAllDeviceGroups) return true; + // Check permissions thru user groups var user = null; if (userid == userinfo._id) { user = userinfo; } else { if (users != null) { user = users[userid]; } } @@ -3493,7 +3531,25 @@ if (node == null) { return 0; } if (userid == null) { userid = userinfo._id; } if (typeof node == 'string') { node = getNodeFromId(node); if (node == null) { return 0; } } - return GetMeshRights(node.meshid, userid); + var r = GetMeshRights(node.meshid, userid); + if (r == 0xFFFFFFFF) return r; + var user = null; + + // Check direct device rights using device data + if ((node.links != null) && (node.links[userid] != null)) { r |= node.links[userid].rights; } // TODO: Deal with reverse permissions + + // Check direct device rights using user data + /* + if (userid == userinfo._id) { user = userinfo; } else { if (users != null) { user = users[userid]; } } + if ((user != null) && (user.links != null)) { + var r2 = user.links[node._id]; + if (r2 != null) { + if (r2.rights == 0xFFFFFFFF) { return 0xFFFFFFFF; } // User has full rights thru a device link, stop here. + r |= r2.rights; // TODO: Deal with reverse permissions + } + } + */ + return r; } // @@ -3520,7 +3576,7 @@ function joinPaths() { var x = []; for (var i in arguments) { var w = arguments[i]; if ((w != null) && (w != '')) { while (w.endsWith('/') || w.endsWith('\\')) { w = w.substring(0, w.length - 1); } while (w.startsWith('/') || w.startsWith('\\')) { w = w.substring(1); } x.push(w); } } return x.join('/'); } function focusTextBox(x) { setTimeout(function () { Q(x).selectionStart = Q(x).selectionEnd = 65535; Q(x).focus(); }, 0); } var isFilenameValid = (function () { var x1 = /^[^\\/:\*\?"<>\|]+$/, x2 = /^\./, x3 = /^(nul|prn|con|lpt[0-9]|com[0-9])(\.|$)/i; return function isFilenameValid(fname) { return x1.test(fname) && !x2.test(fname) && !x3.test(fname) && (fname[0] != '.'); } })(); - function parseUriArgs() { var name, r = {}, parsedUri = window.document.location.href.split(/[\?&|\=]/); parsedUri.splice(0, 1); for (x in parsedUri) { switch (x % 2) { case 0: { name = decodeURIComponent(parsedUri[x]); break; } case 1: { r[name] = decodeURIComponent(parsedUri[x]); var x = parseInt(r[name]); if (x == r[name]) { r[name] = x; } break; } default: { break; } } } return r; } + function parseUriArgs() { var href = window.document.location.href; if (href.endsWith('#')) { href = href.substring(0, href.length - 1); } var name, r = {}, parsedUri = href.split(/[\?&|\=]/); parsedUri.splice(0, 1); for (x in parsedUri) { switch (x % 2) { case 0: { name = decodeURIComponent(parsedUri[x]); break; } case 1: { r[name] = decodeURIComponent(parsedUri[x]); var x = parseInt(r[name]); if (x == r[name]) { r[name] = x; } break; } default: { break; } } } return r; } function printDate(d) { return d.toLocaleDateString(args.locale); } function printTime(d) { return d.toLocaleTimeString(args.locale); } function printDateTime(d) { return d.toLocaleString(args.locale); } diff --git a/views/default.handlebars b/views/default.handlebars index dd816fe9..37d055d2 100644 --- a/views/default.handlebars +++ b/views/default.handlebars @@ -72,6 +72,11 @@ + +
+
{{{titlehtml}}}
+
+ {{{title1}}} +
+
+ {{{title2}}} +
+

{{{logoutControl}}}

+
+
+
+
+
+
+ ♦ + +
+
+
+

Welcome

+

+ This is a portal for computer remote management and support. +

+
+ + + + + +
+
Invitation Code
+
+
+
+
+ +
+
+ +
+ + + diff --git a/views/login-mobile.handlebars b/views/login-mobile.handlebars index 3ae96860..fa900c5a 100644 --- a/views/login-mobile.handlebars +++ b/views/login-mobile.handlebars @@ -164,7 +164,10 @@
-
+
+ + +
@@ -238,7 +241,7 @@ - -
-
-
-
+
@@ -43,6 +40,9 @@
+
+
+
00:00:00
@@ -60,6 +60,8 @@ + +
@@ -91,6 +93,7 @@ var recFileEndTime = 0; var recFileMetadata = null; var recFileProtocol = 0; + var recFileIndexBasePtr = null; var agentDesktop = null; var amtDesktop = null; var playing = false; @@ -138,6 +141,22 @@ } } + function readBlockAt(ptr, func) { + var fr = new FileReader(); + fr.onload = function () { + var type = ReadShort(this.result, 0); + var flags = ReadShort(this.result, 2); + var size = ReadInt(this.result, 4); + var time = (ReadInt(this.result, 8) << 32) + ReadInt(this.result, 12); + if ((ptr + 16 + size) > recFile.size) { func(-1); } else { + var fr2 = new FileReader(); + fr2.onload = function () { func(type, flags, time, this.result); }; + fr2.readAsBinaryString(recFile.slice(ptr + 16, ptr + 16 + size)); + } + }; + fr.readAsBinaryString(recFile.slice(ptr, ptr + 16)); + } + function readLastBlock(func) { if (recFile.size < 32) { func(-1); } else { var fr = new FileReader(); @@ -146,7 +165,24 @@ var flags = ReadShort(this.result, 2); var size = ReadInt(this.result, 4); var time = (ReadInt(this.result, 8) << 32) + ReadInt(this.result, 12); - if ((type == 3) && (size == 16) && (this.result.substring(16, 32) == 'MeshCentralMCREC')) { func(type, flags, time); } else { func(-1); } + var magic = this.result.substring(16, 32); + if ((type == 3) && (size == 16) && (magic == 'MeshCentralMCNDX')) { + // Extra metadata present, lets read it. + var fr2 = new FileReader(); + fr2.onload = function () { + var xtype = ReadShort(this.result, 0); + var xflags = ReadShort(this.result, 2); + var xsize = ReadInt(this.result, 4); + var xtime = (ReadInt(this.result, 8) << 32) + ReadInt(this.result, 12); + var extras = JSON.parse(this.result.substring(16)); + func(type, flags, xtime, extras); // Include extra metadata + } + fr2.readAsBinaryString(recFile.slice(time, recFile.size - 32)); + } else if ((type == 3) && (size == 16) && (magic == 'MeshCentralMCREC')) { + func(type, flags, time); // No extra metadata + } else { + func(-1); // Fail + } }; fr.readAsBinaryString(recFile.slice(recFile.size - 32, recFile.size)); } @@ -161,9 +197,10 @@ function processFirstBlock(type, flags, time, data) { recFileProtocol = 0; - if ((type != 1) || (flags != 0)) { cleanup(); return; } + if ((type != 1) || (flags > 2)) { cleanup(); return; } try { recFileMetadata = JSON.parse(data) } catch (ex) { cleanup(); return; } if ((recFileMetadata == null) || (recFileMetadata.magic != 'MeshCentralRelaySession') || (recFileMetadata.ver != 1)) { cleanup(); return; } + if (recFileExtras) { for (var i in recFileExtras) { recFileMetadata[i] = recFileExtras[i]; } } var x = ''; x += addInfo("Time", recFileMetadata.time); if (recFileEndTime != 0) { var secs = Math.floor((recFileEndTime - time) / 1000); x += addInfo("Duration", format("{0} second{1}", secs, (secs > 1) ? 's' : '')); } @@ -181,6 +218,17 @@ else if (p == 101) { p = "Intel® AMT Redirection"; } x += addInfoNoEsc("Protocol", p); } + if (recFileMetadata.indexInterval) { + recFileIndexBasePtr = recFilePtr; + x += addInfoNoEsc("Seeking", format("Indexed every {0} seconds", recFileMetadata.indexInterval)); + QV('SeekBackwardButton', true); + QV('SeekForwardButton', true); + QE('SeekBackwardButton', true); + QE('SeekForwardButton', true); + } else { + QV('SeekBackwardButton', false); + QV('SeekForwardButton', false); + } QV('DeskParent', true); QV('TermParent', false); if (recFileMetadata.protocol == 1) { @@ -222,6 +270,7 @@ QV('metadatadiv', true); QH('metadatadiv', x); QH('deskstatus', recFile.name); + QS('progressbar').width = '0px'; } function processBlock(type, flags, time, data) { @@ -231,24 +280,26 @@ processBlockEx(type, flags, time, data); } else { waitTimerArgs = [type, flags, time, data] - waitTimer = setTimeout(function () { waitTimer = null; processBlockEx(waitTimerArgs[0], waitTimerArgs[1], waitTimerArgs[2], waitTimerArgs[3]); }, waitTime); + waitTimer = setTimeout(function () { waitTimer = null; if (waitTimerArgs) { processBlockEx(waitTimerArgs[0], waitTimerArgs[1], waitTimerArgs[2], waitTimerArgs[3]); } }, waitTime); } } - function processBlockEx(type, flags, time, data) { - if (playing == false) return; + function processBlockEx(type, flags, time, data, forced) { + if ((playing == false) && (forced !== true)) return; var flagBinary = (flags & 1) != 0, flagUser = (flags & 2) != 0; - // Update the clock - var deltaTimeTotalSec = Math.floor((time - recFileStartTime) / 1000); - if (currentDeltaTimeTotalSec != deltaTimeTotalSec) { - currentDeltaTimeTotalSec = deltaTimeTotalSec; - var deltaTimeHours = Math.floor(deltaTimeTotalSec / 3600); - deltaTimeTotalSec -= (deltaTimeHours * 3600) - var deltaTimeMinutes = Math.floor(deltaTimeTotalSec / 60); - deltaTimeTotalSec -= (deltaTimeHours * 60) - var deltaTimeSeconds = Math.floor(deltaTimeTotalSec); - QH('timespan', pad2(deltaTimeHours) + ':' + pad2(deltaTimeMinutes) + ':' + pad2(deltaTimeSeconds)) + if (type == 2) { + // Update the clock + recFileLastTime = time; + var deltaTimeTotalSec = Math.floor((time - recFileStartTime) / 1000); + if (currentDeltaTimeTotalSec != deltaTimeTotalSec) { + // Hours, minutes and seconds + currentDeltaTimeTotalSec = deltaTimeTotalSec; + var hrs = Math.floor(deltaTimeTotalSec / 3600); + var mins = Math.floor((deltaTimeTotalSec % 3600) / 60); + var secs = Math.floor(deltaTimeTotalSec % 60); + QH('timespan', pad2(hrs) + ':' + pad2(mins) + ':' + pad2(secs)) + } } if ((type == 2) && flagBinary && !flagUser) { @@ -277,7 +328,6 @@ } } - recFileLastTime = time; if (playing) { readNextBlock(processBlock); } } @@ -298,6 +348,8 @@ QE('PlayButton', false); QE('PauseButton', false); QE('RestartButton', false); + QE('SeekBackwardButton', false); + QE('SeekForwardButton', false); QS('progressbar').width = '0px'; QH('timespan', '00:00:00'); QV('metadatadiv', true); @@ -323,8 +375,17 @@ cleanup(); recFile = files[0]; recFilePtr = 0; - readNextBlock(processFirstBlock); - readLastBlock(function (type, flags, time) { if (type == 3) { recFileEndTime = time; } else { recFileEndTime = 0; } }); + readLastBlock(function (type, flags, time, extras) { + if (type == 3) { + // File is ok + recFileEndTime = time; + recFileExtras = extras; + readNextBlock(processFirstBlock); + } else { + // This is not a good file + recFileEndTime = 0; + } + }); } var dragtimer = null; @@ -367,7 +428,17 @@ recFile = files[0]; recFilePtr = 0; readNextBlock(processFirstBlock); - readLastBlock(function (type, flags, time) { if (type == 3) { recFileEndTime = time; } else { recFileEndTime = 0; } }); + readLastBlock(function (type, flags, time, extras) { + if (type == 3) { + // File is ok + recFileEndTime = time; + recFileExtras = extras; + readNextBlock(processFirstBlock); + } else { + // This is not a good file + recFileEndTime = 0; + } + }); Q('OpenFileButton').blur(); } @@ -491,6 +562,70 @@ } } + function seekBackward() { + var ndxNumber = Math.round(currentDeltaTimeTotalSec / recFileMetadata.indexInterval); + if (ndxNumber < 2) { + pause(); restart(); + } else { + if (recFileMetadata.indexes[ndxNumber - 2] != null) { seek(ndxNumber - 2); } + } + } + + function seekForward() { + var ndxNumber = Math.round(currentDeltaTimeTotalSec / recFileMetadata.indexInterval); + if (recFileMetadata.indexes[ndxNumber] != null) { seek(ndxNumber); } + } + + function progressBarSeek(event) { + var ndxNumber = Math.round((event.clientX / document.body.offsetWidth) * (recFileMetadata.indexes.length + 1)) - 1; + if (ndxNumber == -1) { pause(); restart(); } else { seek(ndxNumber); } + } + + var SeekIndex; + var SeekIndexPtr; + var SeekIndexTime; + var SeekPlayState; + function seek(indexNumber) { + //console.log('seek', indexNumber); + if ((recFileMetadata.indexes == null) || (recFileMetadata.indexes[indexNumber] == null)) return null; + SeekPlayState = playing; + pause(); + restart(); + SeekIndex = recFileMetadata.indexes[indexNumber]; + SeekIndexPtr = 3; + recFileLastTime = SeekIndexTime = recFileStartTime + ((1 + indexNumber) * recFileMetadata.indexInterval * 1000); + recFilePtr = recFileIndexBasePtr + SeekIndex[0]; + var width = SeekIndex[1]; + var height = SeekIndex[2]; + + if (recFileEndTime == 0) { + // File pointer progress bar + QS('progressbar').width = Math.floor(100 * (recFilePtr / recFile.size)) + '%'; + } else { + // Time progress bar + QS('progressbar').width = Math.floor(((recFileLastTime - recFileStartTime) / (recFileEndTime - recFileStartTime)) * 100) + '%'; + } + + if (agentDesktop) { + agentDesktop.Canvas.clearRect(0, 0, agentDesktop.CanvasId.width, agentDesktop.CanvasId.height); + agentDesktop.ProcessScreenMsg(width, height); + } + + QV('metadatadiv', false); + QV('Desk', false); + + seekFetchNext(function () { QV('Desk', true); if (SeekPlayState) { play(); } }); + } + + function seekFetchNext(func) { + if (SeekIndex[SeekIndexPtr] == null) { func(); return; } + readBlockAt(recFileIndexBasePtr + SeekIndex[SeekIndexPtr], function (type, flags, time, data) { + SeekIndexPtr++; + processBlockEx(type, flags, SeekIndexTime, data, true); + seekFetchNext(func); + }); + } + // // POPUP DIALOG // diff --git a/views/terms.handlebars b/views/terms.handlebars index 0e57f943..86c917ea 100644 --- a/views/terms.handlebars +++ b/views/terms.handlebars @@ -152,7 +152,7 @@ - +
BackBack
@@ -170,6 +170,13 @@ QV('column_l', true); userInterfaceSelectMenu(); + // Fix links if a loginKey if used + var urlargs = parseUriArgs(); + if (urlargs.key) { + console.log('aa', urlargs.key); + Q('backLink').href += '?key=' + urlargs.key; + } + // Setup logout control var logoutControl = ''; if (logoutControls.name != null) { logoutControl = format("Welcome {0}.", logoutControls.name); } @@ -242,6 +249,7 @@ function putstore(name, val) { try { if (typeof (localStorage) === 'undefined') return; localStorage.setItem(name, val); } catch (e) { } } function getstore(name, val) { try { if (typeof (localStorage) === 'undefined') return val; var v = localStorage.getItem(name); if ((v == null) || (v == null)) return val; return v; } catch (e) { return val; } } function format(format) { var args = Array.prototype.slice.call(arguments, 1); return format.replace(/{(\d+)}/g, function (match, number) { return typeof args[number] != 'undefined' ? args[number] : match; }); }; + function parseUriArgs() { var href = window.document.location.href; if (href.endsWith('#')) { href = href.substring(0, href.length - 1); } var name, r = {}, parsedUri = href.split(/[\?&|\=]/); parsedUri.splice(0, 1); for (x in parsedUri) { switch (x % 2) { case 0: { name = decodeURIComponent(parsedUri[x]); break; } case 1: { r[name] = decodeURIComponent(parsedUri[x]); var x = parseInt(r[name]); if (x == r[name]) { r[name] = x; } break; } default: { break; } } } return r; } diff --git a/webauthn.js b/webauthn.js index 28a7202a..d1f25da3 100644 --- a/webauthn.js +++ b/webauthn.js @@ -251,7 +251,7 @@ module.exports.CreateWebAuthnModule = function () { function ASN1toPEM(pkBuffer) { if (!Buffer.isBuffer(pkBuffer)) { throw new Error("ASN1toPEM: pkBuffer must be Buffer."); } let type; - if (pkBuffer.length == 65 && pkBuffer[0] == 0x04) { pkBuffer = Buffer.concat([new Buffer.from("3059301306072a8648ce3d020106082a8648ce3d030107034200", "hex"), pkBuffer]); type = 'PUBLIC KEY'; } else { type = 'CERTIFICATE'; } + if (pkBuffer.length == 65 && pkBuffer[0] == 0x04) { pkBuffer = Buffer.concat([Buffer.from("3059301306072a8648ce3d020106082a8648ce3d030107034200", "hex"), pkBuffer]); type = 'PUBLIC KEY'; } else { type = 'CERTIFICATE'; } const b64cert = pkBuffer.toString('base64'); let PEMKey = ''; for (let i = 0; i < Math.ceil(b64cert.length / 64); i++) { const start = 64 * i; PEMKey += b64cert.substr(start, 64) + '\n'; } diff --git a/webserver.js b/webserver.js index afc62cd2..89ebd0a6 100644 --- a/webserver.js +++ b/webserver.js @@ -180,8 +180,9 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { obj.crypto.randomBytes(16, function (err, buf) { obj.httpAuthRealm = buf.toString('hex'); }); obj.crypto.randomBytes(48, function (err, buf) { obj.relayRandom = buf; }); - // Get non-english pages + // Get non-english web pages and emails getRenderList(); + getEmailLanguageList(); // Setup DNS domain TLS SNI credentials { @@ -203,6 +204,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { //function EscapeHtmlBreaks(x) { if (typeof x == "string") return x.replace(/&/g, '&').replace(/>/g, '>').replace(/').replace(/\n/g, '').replace(/\t/g, '  '); if (typeof x == "boolean") return x; if (typeof x == "number") return x; } // Fetch all users from the database, keep this in memory obj.db.GetAllType('user', function (err, docs) { + obj.common.unEscapeAllLinksFieldName(docs); var domainUserCount = {}, i = 0; for (i in parent.config.domains) { domainUserCount[i] = 0; } for (i in docs) { var u = obj.users[docs[i]._id] = docs[i]; domainUserCount[u.domain]++; } @@ -215,6 +217,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { } // Fetch all device groups (meshes) from the database, keep this in memory + // As we load things in memory, we will also be doing some cleaning up. + // We will not save any clean up in the database right now, instead it will be saved next time there is a change. obj.db.GetAllType('mesh', function (err, docs) { obj.common.unEscapeAllLinksFieldName(docs); for (var i in docs) { obj.meshes[docs[i]._id] = docs[i]; } // Get all meshes, including deleted ones. @@ -222,14 +226,63 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Fetch all user groups from the database, keep this in memory obj.db.GetAllType('ugrp', function (err, docs) { obj.common.unEscapeAllLinksFieldName(docs); - for (var i in docs) { obj.userGroups[docs[i]._id] = docs[i]; } // Get all user groups - // We loaded the users, device groups and suer group state, start the server + // Perform user group link cleanup + for (var i in docs) { + const ugrp = docs[i]; + if (ugrp.links != null) { + for (var j in ugrp.links) { + if (j.startsWith('user/') && (obj.users[j] == null)) { delete ugrp.links[j]; } // User group has a link to a user that does not exist + else if (j.startsWith('mesh/') && ((obj.meshes[j] == null) || (obj.meshes[j].deleted != null))) { delete ugrp.links[j]; } // User has a link to a device group that does not exist + } + } + obj.userGroups[docs[i]._id] = docs[i]; // Get all user groups + } + + // Perform device group link cleanup + for (var i in obj.meshes) { + const mesh = obj.meshes[i]; + if (mesh.links != null) { + for (var j in mesh.links) { + if (j.startsWith('ugrp/') && (obj.userGroups[j] == null)) { delete mesh.links[j]; } // Device group has a link to a user group that does not exist + else if (j.startsWith('user/') && (obj.users[j] == null)) { delete mesh.links[j]; } // Device group has a link to a user that does not exist + } + } + } + + // Perform user link cleanup + for (var i in obj.users) { + const user = obj.users[i]; + if (user.links != null) { + for (var j in user.links) { + if (j.startsWith('ugrp/') && (obj.userGroups[j] == null)) { delete user.links[j]; } // User has a link to a user group that does not exist + else if (j.startsWith('mesh/') && ((obj.meshes[j] == null) || (obj.meshes[j].deleted != null))) { delete user.links[j]; } // User has a link to a device group that does not exist + //else if (j.startsWith('node/') && (obj.nodes[j] == null)) { delete user.links[j]; } // TODO + } + //if (Object.keys(user.links).length == 0) { delete user.links; } + } + } + + // We loaded the users, device groups and user group state, start the server serverStart(); }); }); }); + // Clean up a device, used before saving it in the database + obj.cleanDevice = function (device) { + // Check device links, if a link points to an unknown user, remove it. + if (device.links != null) { + for (var j in device.links) { + if (obj.users[j] == null) { + delete device.links[j]; + if (Object.keys(device.links).length == 0) { delete device.links; } + } + } + } + return device; + } + // Return statistics about this web server obj.getStats = function () { return { @@ -476,19 +529,22 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { } // Check if the source IP address is allowed, return domain if allowed + // If there is a fail and null is returned, the request or connection is closed already. function checkUserIpAddress(req, res) { if ((parent.config.settings.userblockedip != null) && (checkIpAddressEx(req, res, parent.config.settings.userblockedip, true) == true)) { obj.blockedUsers++; return null; } if ((parent.config.settings.userallowedip != null) && (checkIpAddressEx(req, res, parent.config.settings.userallowedip, false) == false)) { obj.blockedUsers++; return null; } const domain = (req.url ? getDomain(req) : getDomain(res)); + if (domain == null) { parent.debug('web', 'handleRootRequest: invalid domain.'); try { res.sendStatus(404); } catch (ex) { } return; } if ((domain.userblockedip != null) && (checkIpAddressEx(req, res, domain.userblockedip, true) == true)) { obj.blockedUsers++; return null; } if ((domain.userallowedip != null) && (checkIpAddressEx(req, res, domain.userallowedip, false) == false)) { obj.blockedUsers++; return null; } return domain; } // Check if the source IP address is allowed, return domain if allowed + // If there is a fail and null is returned, the request or connection is closed already. function checkAgentIpAddress(req, res) { - if ((parent.config.settings.agentblockedip != null) && (checkIpAddressEx(req, res, parent.config.settings.agentblockedip, true) == true)) { obj.blockedAgents++; return null; } - if ((parent.config.settings.agentallowedip != null) && (checkIpAddressEx(req, res, parent.config.settings.agentallowedip, false) == false)) { obj.blockedAgents++; return null; } + if ((parent.config.settings.agentblockedip != null) && (checkIpAddressEx(req, res, parent.config.settings.agentblockedip, null) == true)) { obj.blockedAgents++; return null; } + if ((parent.config.settings.agentallowedip != null) && (checkIpAddressEx(req, res, parent.config.settings.agentallowedip, null) == false)) { obj.blockedAgents++; return null; } const domain = (req.url ? getDomain(req) : getDomain(res)); if ((domain.agentblockedip != null) && (checkIpAddressEx(req, res, domain.agentblockedip, null) == true)) { obj.blockedAgents++; return null; } if ((domain.agentallowedip != null) && (checkIpAddressEx(req, res, domain.agentallowedip, null) == false)) { obj.blockedAgents++; return null; } @@ -496,9 +552,10 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { } // Return the current domain of the request + // Request or connection says open regardless of the response function getDomain(req) { if (req.xdomain != null) { return req.xdomain; } // Domain already set for this request, return it. - if (req.headers.host != null) { var d = obj.dnsDomains[req.headers.host.toLowerCase()]; if (d != null) return d; } // If this is a DNS name domain, return it here. + if (req.headers.host != null) { var d = obj.dnsDomains[req.headers.host.split(':')[0].toLowerCase()]; if (d != null) return d; } // If this is a DNS name domain, return it here. var x = req.url.split('/'); if (x.length < 2) return parent.config.domains['']; var y = parent.config.domains[x[1].toLowerCase()]; @@ -508,7 +565,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { function handleLogoutRequest(req, res) { const domain = checkUserIpAddress(req, res); - if ((domain == null) || (domain.auth == 'sspi')) { parent.debug('web', 'handleLogoutRequest: failed checks.'); res.sendStatus(404); return; } + if (domain == null) { return; } + if (domain.auth == 'sspi') { parent.debug('web', 'handleLogoutRequest: failed checks.'); res.sendStatus(404); return; } if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0' }); @@ -541,7 +599,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { } // Check if a 2nd factor is present - return ((parent.config.settings.no2factorauth !== true) && ((user.otpsecret != null) || ((user.otphkeys != null) && (user.otphkeys.length > 0)))); + return ((parent.config.settings.no2factorauth !== true) && ((user.otpsecret != null) || ((user.email != null) && (user.emailVerified == true) && (parent.mailserver != null) && (user.otpekey != null)) || ((user.otphkeys != null) && (user.otphkeys.length > 0)))); } // Check the 2-step auth token @@ -550,6 +608,22 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { const twoStepLoginSupported = ((domain.auth != 'sspi') && (obj.parent.certificates.CommonName.indexOf('.') != -1) && (obj.args.nousers !== true) && (parent.config.settings.no2factorauth !== true)); if (twoStepLoginSupported == false) { parent.debug('web', 'checkUserOneTimePassword: not supported.'); func(true); return; }; + // Check if we can use OTP tokens with email + var otpemail = (parent.mailserver != null); + if ((typeof domain.passwordrequirements == 'object') && (domain.passwordrequirements.email2factor == false)) { otpemail = false; } + + // Check email key + if ((otpemail) && (user.otpekey != null) && (user.otpekey.d != null) && (user.otpekey.k === token)) { + var deltaTime = (Date.now() - user.otpekey.d); + if ((deltaTime > 0) && (deltaTime < 300000)) { // Allow 5 minutes to use the email token (10000 * 60 * 5). + user.otpekey = {}; + obj.db.SetUser(user); + parent.debug('web', 'checkUserOneTimePassword: success (email).'); + func(true); + return; + } + } + // Check hardware key if (user.otphkeys && (user.otphkeys.length > 0) && (typeof (hwtoken) == 'string') && (hwtoken.length > 0)) { var authResponse = null; @@ -595,10 +669,10 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Update the hardware key counter and accept the 2nd factor webAuthnKey.counter = webauthnResponse.counter; obj.db.SetUser(user); - parent.debug('web', 'checkUserOneTimePassword: success.'); + parent.debug('web', 'checkUserOneTimePassword: success (hardware).'); func(true); } else { - parent.debug('web', 'checkUserOneTimePassword: fail.'); + parent.debug('web', 'checkUserOneTimePassword: fail (hardware).'); func(false); } return; @@ -610,12 +684,21 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Check Google Authenticator const otplib = require('otplib') otplib.authenticator.options = { window: 2 }; // Set +/- 1 minute window - if (user.otpsecret && (typeof (token) == 'string') && (token.length == 6) && (otplib.authenticator.check(token, user.otpsecret) == true)) { func(true); return; }; + if (user.otpsecret && (typeof (token) == 'string') && (token.length == 6) && (otplib.authenticator.check(token, user.otpsecret) == true)) { + parent.debug('web', 'checkUserOneTimePassword: success (authenticator).'); + func(true); + return; + }; // Check written down keys if ((user.otpkeys != null) && (user.otpkeys.keys != null) && (typeof (token) == 'string') && (token.length == 8)) { var tokenNumber = parseInt(token); - for (var i = 0; i < user.otpkeys.keys.length; i++) { if ((tokenNumber === user.otpkeys.keys[i].p) && (user.otpkeys.keys[i].u === true)) { user.otpkeys.keys[i].u = false; func(true); return; } } + for (var i = 0; i < user.otpkeys.keys.length; i++) { + if ((tokenNumber === user.otpkeys.keys[i].p) && (user.otpkeys.keys[i].u === true)) { + parent.debug('web', 'checkUserOneTimePassword: success (one-time).'); + user.otpkeys.keys[i].u = false; func(true); return; + } + } } // Check OTP hardware key @@ -631,7 +714,15 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { var yubikeyotp = require('yubikeyotp'); var request = { otp: token, id: domain.yubikey.id, key: domain.yubikey.secret, timestamp: true } if (domain.yubikey.proxy) { request.requestParams = { proxy: domain.yubikey.proxy }; } - yubikeyotp.verifyOTP(request, function (err, results) { func((results != null) && (results.status == 'OK')); }); + yubikeyotp.verifyOTP(request, function (err, results) { + if ((results != null) && (results.status == 'OK')) { + parent.debug('web', 'checkUserOneTimePassword: success (Yubikey).'); + func(true); + } else { + parent.debug('web', 'checkUserOneTimePassword: fail (Yubikey).'); + func(false); + } + }); return; } } @@ -663,7 +754,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { function handleLoginRequest(req, res, direct) { const domain = checkUserIpAddress(req, res); - if (domain == null) { parent.debug('web', 'handleLoginRequest: invalid domain'); res.sendStatus(404); return; } + if (domain == null) { return; } if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key // Check if this is a banned ip address @@ -687,6 +778,17 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Check if this user has 2-step login active if ((req.session.loginmode != '6') && checkUserOneTimePasswordRequired(domain, user, req)) { + if ((req.body.hwtoken == '**email**') && (user.email != null) && (user.emailVerified == true) && (parent.mailserver != null) && (user.otpekey != null)) { + user.otpekey = { k: obj.common.zeroPad(getRandomEightDigitInteger(), 8), d: Date.now() }; + obj.db.SetUser(user); + parent.debug('web', 'Sending 2FA email to: ' + user.email); + parent.mailserver.sendAccountLoginMail(domain, user.email, user.otpekey.k, obj.getLanguageCodes(req)); + req.session.messageid = 2; // "Email sent" message + req.session.loginmode = '4'; + if (direct === true) { handleRootRequestEx(req, res, domain); } else { res.redirect(domain.url + getQueryPortion(req)); } + return; + } + checkUserOneTimePassword(req, domain, user, req.body.token, req.body.hwtoken, function (result) { if (result == false) { var randomWaitTime = 0; @@ -695,6 +797,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if ((req.body.token != null) || (req.body.hwtoken != null)) { randomWaitTime = 2000 + (obj.crypto.randomBytes(2).readUInt16BE(0) % 4095); // This is a fail, wait a random time. 2 to 6 seconds. req.session.messageid = 108; // Invalid token, try again. + if (obj.parent.authlog) { obj.parent.authLog('https', 'Failed 2FA for ' + xusername + ' from ' + cleanRemoteAddr(req.ip) + ' port ' + req.port); } parent.debug('web', 'handleLoginRequest: invalid 2FA token'); obj.parent.DispatchEvent(['*', 'server-users', 'user/' + domain.id + '/' + user.name], obj, { action: 'authfail', username: user.name, userid: 'user/' + domain.id + '/' + user.name, domain: domain.id, msg: 'User login attempt with incorrect 2nd factor from ' + cleanRemoteAddr(req.ip) }); obj.setbadLogin(req); @@ -705,6 +808,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Wait and redirect the user setTimeout(function () { req.session.loginmode = '4'; + req.session.tokenemail = ((user.email != null) && (user.emailVerified == true) && (parent.mailserver != null) && (user.otpekey != null)); req.session.tokenusername = xusername; req.session.tokenpassword = xpassword; if (direct === true) { handleRootRequestEx(req, res, domain); } else { res.redirect(domain.url + getQueryPortion(req)); } @@ -717,6 +821,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { } // Login successful + if (obj.parent.authlog) { obj.parent.authLog('https', 'Accepted password for ' + xusername + ' from ' + cleanRemoteAddr(req.ip) + ' port ' + req.connection.remotePort); } parent.debug('web', 'handleLoginRequest: successful 2FA login'); completeLoginRequest(req, res, domain, user, userid, xusername, xpassword, direct); } @@ -725,10 +830,14 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { } // Login successful + if (obj.parent.authlog) { obj.parent.authLog('https', 'Accepted password for ' + xusername + ' from ' + cleanRemoteAddr(req.ip) + ' port ' + req.connection.remotePort); } parent.debug('web', 'handleLoginRequest: successful login'); completeLoginRequest(req, res, domain, user, userid, xusername, xpassword, direct); } else { - // Login failed, wait a random delay + // Login failed, log the error + if (obj.parent.authlog) { obj.parent.authLog('https', 'Failed password for ' + xusername + ' from ' + cleanRemoteAddr(req.ip) + ' port ' + req.connection.remotePort); } + + // Wait a random delay setTimeout(function () { // If the account is locked, display that. if (typeof xusername == 'string') { @@ -787,6 +896,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { //req.session.regenerate(function () { // Store the user's primary key in the session store to be retrieved, or in this case the entire user object delete req.session.loginmode; + delete req.session.tokenemail; delete req.session.tokenusername; delete req.session.tokenpassword; delete req.session.tokenemail; @@ -823,7 +933,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { function handleCreateAccountRequest(req, res, direct) { const domain = checkUserIpAddress(req, res); - if ((domain == null) || (domain.auth == 'sspi') || (domain.auth == 'ldap')) { parent.debug('web', 'handleCreateAccountRequest: failed checks.'); res.sendStatus(404); return; } + if (domain == null) { return; } + if ((domain.auth == 'sspi') || (domain.auth == 'ldap')) { parent.debug('web', 'handleCreateAccountRequest: failed checks.'); res.sendStatus(404); return; } if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key // Always lowercase the email address @@ -918,7 +1029,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { obj.db.SetUser(user); // Send the verification email - if ((obj.parent.mailserver != null) && (domain.auth != 'sspi') && (domain.auth != 'ldap') && (obj.common.validateEmail(user.email, 1, 256) == true)) { obj.parent.mailserver.sendAccountCheckMail(domain, user.name, user.email); } + if ((obj.parent.mailserver != null) && (domain.auth != 'sspi') && (domain.auth != 'ldap') && (obj.common.validateEmail(user.email, 1, 256) == true)) { obj.parent.mailserver.sendAccountCheckMail(domain, user.name, user.email, obj.getLanguageCodes(req)); } }, 0); var event = { etype: 'user', userid: user._id, username: user.name, account: obj.CloneSafeUser(user), action: 'accountcreate', msg: 'Account created, email is ' + req.body.email, domain: domain.id }; if (obj.db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to create the user. Another event will come. @@ -935,6 +1046,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Called to process an account password reset function handleResetPasswordRequest(req, res, direct) { const domain = checkUserIpAddress(req, res); + if (domain == null) { return; } if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key // Check everything is ok @@ -1002,6 +1114,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Failed, error out. parent.debug('web', 'handleResetPasswordRequest: failed authenticate()'); delete req.session.loginmode; + delete req.session.tokenemail; delete req.session.tokenusername; delete req.session.tokenpassword; delete req.session.resettokenusername; @@ -1018,7 +1131,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Called to process an account reset request function handleResetAccountRequest(req, res, direct) { const domain = checkUserIpAddress(req, res); - if ((domain == null) || (domain.auth == 'sspi') || (domain.auth == 'ldap') || (obj.args.lanonly == true) || (obj.parent.certificates.CommonName == null) || (obj.parent.certificates.CommonName.indexOf('.') == -1)) { parent.debug('web', 'handleResetAccountRequest: check failed'); res.sendStatus(404); return; } + if (domain == null) { return; } + if ((domain.auth == 'sspi') || (domain.auth == 'ldap') || (obj.args.lanonly == true) || (obj.parent.certificates.CommonName == null) || (obj.parent.certificates.CommonName.indexOf('.') == -1)) { parent.debug('web', 'handleResetAccountRequest: check failed'); res.sendStatus(404); return; } if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key // Always lowercase the email address @@ -1066,7 +1180,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Send email to perform recovery. delete req.session.tokenemail; if (obj.parent.mailserver != null) { - obj.parent.mailserver.sendAccountResetMail(domain, user.name, user.email); + obj.parent.mailserver.sendAccountResetMail(domain, user.name, user.email, obj.getLanguageCodes(req)); if (i == 0) { parent.debug('web', 'handleResetAccountRequest: Hold on, reset mail sent.'); req.session.loginmode = '1'; @@ -1086,7 +1200,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { } else { // No second factor, send email to perform recovery. if (obj.parent.mailserver != null) { - obj.parent.mailserver.sendAccountResetMail(domain, user.name, user.email); + obj.parent.mailserver.sendAccountResetMail(domain, user.name, user.email, obj.getLanguageCodes(req)); if (i == 0) { parent.debug('web', 'handleResetAccountRequest: Hold on, reset mail sent.'); req.session.loginmode = '1'; @@ -1111,7 +1225,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Called to process a web based email verification request function handleCheckMailRequest(req, res) { const domain = checkUserIpAddress(req, res); - if ((domain == null) || (domain.auth == 'sspi') || (domain.auth == 'ldap')) { parent.debug('web', 'handleCheckMailRequest: failed checks.'); res.sendStatus(404); return; } + if (domain == null) { return; } + if ((domain.auth == 'sspi') || (domain.auth == 'ldap')) { parent.debug('web', 'handleCheckMailRequest: failed checks.'); res.sendStatus(404); return; } if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key if (req.query.c != null) { @@ -1120,28 +1235,28 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { var idsplit = cookie.u.split('/'); if ((idsplit.length != 2) || (idsplit[0] != domain.id)) { parent.debug('web', 'handleCheckMailRequest: Invalid domain.'); - render(req, res, getRenderPage('message', req), getRenderArgs({ title3: 'Account Verification', message: 'ERROR: Invalid domain. Go to login page.' }, domain)); + render(req, res, getRenderPage('message', req, domain), getRenderArgs({ title3: 'Account Verification', message: 'ERROR: Invalid domain. Go to login page.' }, domain)); } else { obj.db.Get('user/' + cookie.u.toLowerCase(), function (err, docs) { if (docs.length == 0) { parent.debug('web', 'handleCheckMailRequest: Invalid username.'); - render(req, res, getRenderPage('message', req), getRenderArgs({ title3: 'Account Verification', message: 'ERROR: Invalid username \"' + EscapeHtml(idsplit[1]) + '\". Go to login page.' }, domain)); + render(req, res, getRenderPage('message', req, domain), getRenderArgs({ title3: 'Account Verification', message: 'ERROR: Invalid username \"' + EscapeHtml(idsplit[1]) + '\". Go to login page.' }, domain)); } else { var user = docs[0]; if (user.email != cookie.e) { parent.debug('web', 'handleCheckMailRequest: Invalid e-mail.'); - render(req, res, getRenderPage('message', req), getRenderArgs({ title3: 'Account Verification', message: 'ERROR: Invalid e-mail \"' + EscapeHtml(user.email) + '\" for user \"' + EscapeHtml(user.name) + '\". Go to login page.' }, domain)); + render(req, res, getRenderPage('message', req, domain), getRenderArgs({ title3: 'Account Verification', message: 'ERROR: Invalid e-mail \"' + EscapeHtml(user.email) + '\" for user \"' + EscapeHtml(user.name) + '\". Go to login page.' }, domain)); } else { if (cookie.a == 1) { // Account email verification if (user.emailVerified == true) { parent.debug('web', 'handleCheckMailRequest: email already verified.'); - render(req, res, getRenderPage('message', req), getRenderArgs({ title3: 'Account Verification', message: 'E-mail \"' + EscapeHtml(user.email) + '\" for user \"' + EscapeHtml(user.name) + '\" already verified. Go to login page.' }, domain)); + render(req, res, getRenderPage('message', req, domain), getRenderArgs({ title3: 'Account Verification', message: 'E-mail \"' + EscapeHtml(user.email) + '\" for user \"' + EscapeHtml(user.name) + '\" already verified. Go to login page.' }, domain)); } else { obj.db.GetUserWithVerifiedEmail(domain.id, user.email, function (err, docs) { if (docs.length > 0) { parent.debug('web', 'handleCheckMailRequest: email already in use.'); - render(req, res, getRenderPage('message', req), getRenderArgs({ title3: 'Account Verification', message: 'E-mail \"' + EscapeHtml(user.email) + '\" already in use on a different account. Change the email address and try again. Go to login page.' }, domain)); + render(req, res, getRenderPage('message', req, domain), getRenderArgs({ title3: 'Account Verification', message: 'E-mail \"' + EscapeHtml(user.email) + '\" already in use on a different account. Change the email address and try again. Go to login page.' }, domain)); } else { parent.debug('web', 'handleCheckMailRequest: email verification success.'); @@ -1156,7 +1271,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { obj.parent.DispatchEvent(['*', 'server-users', user._id], obj, event); // Send the confirmation page - render(req, res, getRenderPage('message', req), getRenderArgs({ title3: 'Account Verification', message: 'Verified email ' + EscapeHtml(user.email) + ' for user account ' + EscapeHtml(user.name) + '. Go to login page.' }, domain)); + render(req, res, getRenderPage('message', req, domain), getRenderArgs({ title3: 'Account Verification', message: 'Verified email ' + EscapeHtml(user.email) + ' for user account ' + EscapeHtml(user.name) + '. Go to login page.' }, domain)); // Send a notification obj.parent.DispatchEvent([user._id], obj, { action: 'notify', value: 'Email verified:
' + EscapeHtml(user.email) + '.', nolog: 1, id: Math.random() }); @@ -1167,7 +1282,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Account reset if (user.emailVerified != true) { parent.debug('web', 'handleCheckMailRequest: email not verified.'); - render(req, res, getRenderPage('message', req), getRenderArgs({ title3: 'Account Verification', message: 'E-mail \"' + EscapeHtml(user.email) + '\" for user \"' + EscapeHtml(user.name) + '\" not verified. Go to login page.' }, domain)); + render(req, res, getRenderPage('message', req, domain), getRenderArgs({ title3: 'Account Verification', message: 'E-mail \"' + EscapeHtml(user.email) + '\" for user \"' + EscapeHtml(user.name) + '\" not verified. Go to login page.' }, domain)); } else { // Set a temporary password obj.crypto.randomBytes(16, function (err, buf) { @@ -1192,24 +1307,43 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { obj.parent.DispatchEvent(['*', 'server-users', user._id], obj, event); // Send the new password - render(req, res, getRenderPage('message', req), getRenderArgs({ title3: 'Account Verification', message: '
Password for account ' + EscapeHtml(user.name) + ' has been reset to:
' + EscapeHtml(newpass) + '
Login and go to the \"My Account\" tab to update your password. Go to login page.' }, domain)); + render(req, res, getRenderPage('message', req, domain), getRenderArgs({ title3: 'Account Verification', message: '
Password for account ' + EscapeHtml(user.name) + ' has been reset to:
' + EscapeHtml(newpass) + '
Login and go to the \"My Account\" tab to update your password. Go to login page.' }, domain)); parent.debug('web', 'handleCheckMailRequest: send temporary password.'); }, 0); }); } } else { - render(req, res, getRenderPage('message', req), getRenderArgs({ title3: 'Account Verification', message: 'ERROR: Invalid account check. Go to login page.' }, domain)); + render(req, res, getRenderPage('message', req, domain), getRenderArgs({ title3: 'Account Verification', message: 'ERROR: Invalid account check. Go to login page.' }, domain)); } } } }); } } else { - render(req, res, getRenderPage('message', req), getRenderArgs({ title3: 'Account Verification', message: 'ERROR: Invalid account check, verification url is only valid for 30 minutes. Go to login page.' }, domain)); + render(req, res, getRenderPage('message', req, domain), getRenderArgs({ title3: 'Account Verification', message: 'ERROR: Invalid account check, verification url is only valid for 30 minutes. Go to login page.' }, domain)); } } } + // Called to process an agent invite GET/POST request + function handleInviteRequest(req, res) { + const domain = getDomain(req); + if (domain == null) { parent.debug('web', 'handleInviteRequest: failed checks.'); res.sendStatus(404); return; } + if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key + if ((req.body.inviteCode == null) || (req.body.inviteCode == '')) { render(req, res, getRenderPage('invite', req, domain), getRenderArgs({ messageid: 0 }, domain)); return; } // No invitation code + + // Each for a device group that has this invite code. + for (var i in obj.meshes) { + if ((obj.meshes[i].invite != null) && (obj.meshes[i].invite.codes.indexOf(req.body.inviteCode) >= 0)) { + // Send invitation link, valid for 1 minute. + res.redirect(domain.url + 'agentinvite?c=' + parent.encodeCookie({ a: 4, mid: i, f: obj.meshes[i].invite.flags, expire: 1 }, parent.invitationLinkEncryptionKey) + (req.query.key ? ('&key=' + req.query.key) : '')); + return; + } + } + + render(req, res, getRenderPage('invite', req, domain), getRenderArgs({ messageid: 100 }, domain)); // Bad invitation code + } + // Called to process an agent invite request function handleAgentInviteRequest(req, res) { const domain = getDomain(req); @@ -1225,7 +1359,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { var installflags = cookie.f; if (typeof installflags != 'number') { installflags = 0; } parent.debug('web', 'handleAgentInviteRequest using cookie.'); - render(req, res, getRenderPage('agentinvite', req), getRenderArgs({ meshid: mesh._id.split('/')[2], serverport: ((args.aliasport != null) ? args.aliasport : args.port), serverhttps: ((args.notls == true) ? '0' : '1'), servernoproxy: ((domain.agentnoproxy === true) ? '1' : '0'), meshname: encodeURIComponent(mesh.name), installflags: installflags }, domain)); + render(req, res, getRenderPage('agentinvite', req, domain), getRenderArgs({ meshid: mesh._id.split('/')[2], serverport: ((args.aliasport != null) ? args.aliasport : args.port), serverhttps: ((args.notls == true) ? '0' : '1'), servernoproxy: ((domain.agentnoproxy === true) ? '1' : '0'), meshname: encodeURIComponent(mesh.name), installflags: installflags }, domain)); } else if (req.query.m != null) { // The MeshId is specified in the query string, use that var mesh = obj.meshes['mesh/' + domain.id + '/' + req.query.m.toLowerCase()]; @@ -1234,14 +1368,15 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if (req.query.f) { installflags = parseInt(req.query.f); } if (typeof installflags != 'number') { installflags = 0; } parent.debug('web', 'handleAgentInviteRequest using meshid.'); - render(req, res, getRenderPage('agentinvite', req), getRenderArgs({ meshid: mesh._id.split('/')[2], serverport: ((args.aliasport != null) ? args.aliasport : args.port), serverhttps: ((args.notls == true) ? '0' : '1'), servernoproxy: ((domain.agentnoproxy === true) ? '1' : '0'), meshname: encodeURIComponent(mesh.name), installflags: installflags }, domain)); + render(req, res, getRenderPage('agentinvite', req, domain), getRenderArgs({ meshid: mesh._id.split('/')[2], serverport: ((args.aliasport != null) ? args.aliasport : args.port), serverhttps: ((args.notls == true) ? '0' : '1'), servernoproxy: ((domain.agentnoproxy === true) ? '1' : '0'), meshname: encodeURIComponent(mesh.name), installflags: installflags }, domain)); } } function handleDeleteAccountRequest(req, res, direct) { parent.debug('web', 'handleDeleteAccountRequest()'); const domain = checkUserIpAddress(req, res); - if ((domain == null) || (domain.auth == 'sspi') || (domain.auth == 'ldap')) { parent.debug('web', 'handleDeleteAccountRequest: failed checks.'); res.sendStatus(404); return; } + if (domain == null) { return; } + if ((domain.auth == 'sspi') || (domain.auth == 'ldap')) { parent.debug('web', 'handleDeleteAccountRequest: failed checks.'); res.sendStatus(404); return; } if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key var user = null; @@ -1263,32 +1398,52 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Check if the password is correct obj.authenticate(user.name, req.body.apassword1, domain, function (err, userid) { - var user = obj.users[userid]; - if (user) { - // Remove all the mesh links to this user - if (user.links != null) { - for (var meshid in user.links) { - // Get the mesh - var mesh = obj.meshes[meshid]; - if (mesh) { - // Remove user from the mesh - if (mesh.links[userid] != null) { delete mesh.links[userid]; obj.db.Set(obj.common.escapeLinksFieldName(mesh)); } - // Notify mesh change - var change = 'Removed user ' + user.name + ' from group ' + mesh.name; - obj.parent.DispatchEvent(['*', mesh._id, user._id, userid], obj, { etype: 'mesh', userid: user._id, username: user.name, meshid: mesh._id, name: mesh.name, mtype: mesh.mtype, desc: mesh.desc, action: 'meshchange', links: mesh.links, msg: change, domain: domain.id }); + var deluser = obj.users[userid]; + if ((deluser != null) || (userid == null)) { + // Remove all links to this user + if (deluser.links != null) { + for (var i in deluser.links) { + if (i.startsWith('mesh/')) { + // Get the device group + mesh = parent.meshes[i]; + if (mesh) { + // Remove user from the mesh + if (mesh.links[deluser._id] != null) { delete mesh.links[deluser._id]; parent.db.Set(mesh); } + + // Notify mesh change + change = 'Removed user ' + deluser.name + ' from group ' + mesh.name; + var event = { etype: 'mesh', userid: user._id, username: user.name, meshid: mesh._id, name: mesh.name, mtype: mesh.mtype, desc: mesh.desc, action: 'meshchange', links: mesh.links, msg: change, domain: domain.id, invite: mesh.invite }; + if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the mesh. Another event will come. + parent.parent.DispatchEvent(['*', mesh._id, deluser._id, user._id], obj, event); + } + } else if (i.startsWith('node/')) { + // Get the node and the rights for this node + parent.GetNodeWithRights(domain, deluser, i, function (node, rights, visible) { + if ((node == null) || (node.links == null) || (node.links[deluser._id] == null)) return; + + // Remove the link and save the node to the database + delete node.links[deluser._id]; + if (Object.keys(node.links).length == 0) { delete node.links; } + db.Set(obj.cleanDevice(node)); + + // Event the node change + var event = { etype: 'node', userid: user._id, username: user.name, action: 'changenode', nodeid: node._id, domain: domain.id, msg: (command.rights == 0) ? ('Removed user device rights for ' + node.name) : ('Changed user device rights for ' + node.name), node: parent.CloneSafeNode(node) } + if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the mesh. Another event will come. + parent.parent.DispatchEvent(['*', node.meshid, node._id], obj, event); + }); } } } // Remove notes for this user - obj.db.Remove('nt' + user._id); + obj.db.Remove('nt' + deluser._id); // Remove the user - obj.db.Remove(user._id); - delete obj.users[user._id]; + obj.db.Remove(deluser._id); + delete obj.users[deluser._id]; req.session = null; if (direct === true) { handleRootRequestEx(req, res, domain); } else { res.redirect(domain.url + getQueryPortion(req)); } - obj.parent.DispatchEvent(['*', 'server-users'], obj, { etype: 'user', userid: user._id, username: user.name, action: 'accountremove', msg: 'Account removed', domain: domain.id }); + obj.parent.DispatchEvent(['*', 'server-users'], obj, { etype: 'user', userid: deluser._id, username: deluser.name, action: 'accountremove', msg: 'Account removed', domain: domain.id }); parent.debug('web', 'handleDeleteAccountRequest: removed user.'); } else { parent.debug('web', 'handleDeleteAccountRequest: auth failed.'); @@ -1328,7 +1483,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Handle password changes function handlePasswordChangeRequest(req, res, direct) { const domain = checkUserIpAddress(req, res); - if ((domain == null) || (domain.auth == 'sspi') || (domain.auth == 'ldap')) { parent.debug('web', 'handlePasswordChangeRequest: failed checks (1).'); res.sendStatus(404); return; } + if (domain == null) { return; } + if ((domain.auth == 'sspi') || (domain.auth == 'ldap')) { parent.debug('web', 'handlePasswordChangeRequest: failed checks (1).'); res.sendStatus(404); return; } if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key // Check if the user is logged and we have all required parameters @@ -1369,7 +1525,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Indicates that any request to "/" should render "default" or "login" depending on login state function handleRootRequest(req, res, direct) { const domain = checkUserIpAddress(req, res); - if (domain == null) { parent.debug('web', 'handleRootRequest: invalid domain.'); try { res.sendStatus(404); } catch (ex) { } return; } + if (domain == null) { return; } if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key if (!obj.args) { parent.debug('web', 'handleRootRequest: no obj.args.'); res.sendStatus(500); return; } @@ -1377,16 +1533,19 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Login using SSPI domain.sspi.authenticate(req, res, function (err) { if ((err != null) || (req.connection.user == null)) { + if (obj.parent.authlog) { obj.parent.authLog('https', 'Failed SSPI-auth for ' + req.connection.user + ' from ' + cleanRemoteAddr(req.ip) + ' port ' + req.connection.remotePort); } parent.debug('web', 'handleRootRequest: SSPI auth required.'); res.end('Authentication Required...'); } else { + if (obj.parent.authlog) { obj.parent.authLog('https', 'Accepted SSPI-auth for ' + req.connection.user + ' from ' + cleanRemoteAddr(req.ip) + ' port ' + req.connection.remotePort); } parent.debug('web', 'handleRootRequest: SSPI auth ok.'); handleRootRequestEx(req, res, domain, direct); } }); } else if (req.query.user && req.query.pass) { - // User credentials are being passed in the URL. WARNING: Putting credentials in a URL is not good security... but people are requesting this option. + // User credentials are being passed in the URL. WARNING: Putting credentials in a URL is bad security... but people are requesting this option. obj.authenticate(req.query.user, req.query.pass, domain, function (err, userid) { + if (obj.parent.authlog) { obj.parent.authLog('https', 'Accepted password for ' + req.connection.user + ' from ' + cleanRemoteAddr(req.ip) + ' port ' + req.connection.remotePort); } parent.debug('web', 'handleRootRequest: user/pass in URL auth ok.'); req.session.userid = userid; req.session.domainid = domain.id; @@ -1498,7 +1657,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // If a user exists and is logged in, serve the default app, otherwise server the login app. if (req.session && req.session.userid && obj.users[req.session.userid]) { var user = obj.users[req.session.userid]; - if (req.session.domainid != domain.id) { // Check is the session is for the correct domain + if (req.session.domainid != domain.id) { // Check if the session is for the correct domain parent.debug('web', 'handleRootRequestEx: incorrect domain.'); req.session = null; res.redirect(domain.url + getQueryPortion(req)); // BAD*** @@ -1555,11 +1714,22 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if (domain.geolocation == true) { features += 0x00008000; } // Enable geo-location features if ((domain.passwordrequirements != null) && (domain.passwordrequirements.hint === true)) { features += 0x00010000; } // Enable password hints if (parent.config.settings.no2factorauth !== true) { features += 0x00020000; } // Enable WebAuthn/FIDO2 support - if ((obj.args.nousers != true) && (domain.passwordrequirements != null) && (domain.passwordrequirements.force2factor === true)) { features += 0x00040000; } // Force 2-factor auth + if ((obj.args.nousers != true) && (domain.passwordrequirements != null) && (domain.passwordrequirements.force2factor === true)) { + // Check if we can skip 2nd factor auth because of the source IP address + var skip2factor = false; + if ((req != null) && (req.ip != null) && (domain.passwordrequirements != null) && (domain.passwordrequirements.skip2factor != null)) { + for (var i in domain.passwordrequirements.skip2factor) { + if (require('ipcheck').match(req.ip, domain.passwordrequirements.skip2factor[i]) === true) { skip2factor = true; } + } + } + if (skip2factor == false) { features += 0x00040000; } // Force 2-factor auth + } if ((domain.auth == 'sspi') || (domain.auth == 'ldap')) { features += 0x00080000; } // LDAP or SSPI in use, warn that users must login first before adding a user to a group. if (domain.amtacmactivation) { features += 0x00100000; } // Intel AMT ACM activation/upgrade is possible if (domain.usernameisemail) { features += 0x00200000; } // Username is email address if (parent.mqttbroker != null) { features += 0x00400000; } // This server supports MQTT channels + if (((typeof domain.passwordrequirements != 'object') || (domain.passwordrequirements.email2factor != false)) && (parent.mailserver != null)) { features += 0x00800000; } // using email for 2FA is allowed + if (domain.agentinvitecodes == true) { features += 0x01000000; } // Support for agent invite codes // Create a authentication cookie const authCookie = obj.parent.encodeCookie({ userid: user._id, domainid: domain.id, ip: cleanRemoteAddr(req.ip) }, obj.parent.loginCookieEncryptionKey); @@ -1581,7 +1751,14 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { parent.debug('web', 'handleRootRequestEx: success.'); obj.db.Get('ws' + user._id, function (err, states) { var webstate = (states.length == 1) ? obj.filterUserWebState(states[0].state) : ''; - render(req, res, getRenderPage('default', req), getRenderArgs({ authCookie: authCookie, authRelayCookie: authRelayCookie, viewmode: viewmode, currentNode: currentNode, logoutControls: JSON.stringify(logoutcontrols), domain: domain.id, debuglevel: parent.debugLevel, serverDnsName: obj.getWebServerName(domain), serverRedirPort: args.redirport, serverPublicPort: httpsPort, noServerBackup: (args.noserverbackup == 1 ? 1 : 0), features: features, sessiontime: args.sessiontime, mpspass: args.mpspass, passRequirements: passRequirements, webcerthash: Buffer.from(obj.webCertificateFullHashs[domain.id], 'binary').toString('base64').replace(/\+/g, '@').replace(/\//g, '$'), footer: (domain.footer == null) ? '' : domain.footer, webstate: encodeURIComponent(webstate), pluginHandler: (parent.pluginHandler == null) ? 'null' : parent.pluginHandler.prepExports(), StartGeoLocation: StartGeoLocation, EndGeoLocation: EndGeoLocation, StartGeoLocationJS: StartGeoLocationJS, EndGeoLocationJS: EndGeoLocationJS }, domain)); + if ((webstate == '') && (typeof domain.defaultuserwebstate == 'object')) { webstate = JSON.stringify(domain.defaultuserwebstate); } // User has no web state, use defaults. + if (typeof domain.forceduserwebstate == 'object') { // Forces initial user web state is present, use it. + var webstate2 = {}; + try { if (webstate != '') { webstate2 = JSON.parse(webstate); } } catch (ex) { } + for (var i in domain.forceduserwebstate) { webstate2[i] = domain.forceduserwebstate[i]; } + webstate = JSON.stringify(webstate2); + } + render(req, res, getRenderPage('default', req, domain), getRenderArgs({ authCookie: authCookie, authRelayCookie: authRelayCookie, viewmode: viewmode, currentNode: currentNode, logoutControls: JSON.stringify(logoutcontrols), domain: domain.id, debuglevel: parent.debugLevel, serverDnsName: obj.getWebServerName(domain), serverRedirPort: args.redirport, serverPublicPort: httpsPort, noServerBackup: (args.noserverbackup == 1 ? 1 : 0), features: features, sessiontime: args.sessiontime, mpspass: args.mpspass, passRequirements: passRequirements, webcerthash: Buffer.from(obj.webCertificateFullHashs[domain.id], 'binary').toString('base64').replace(/\+/g, '@').replace(/\//g, '$'), footer: (domain.footer == null) ? '' : domain.footer, webstate: encodeURIComponent(webstate), pluginHandler: (parent.pluginHandler == null) ? 'null' : parent.pluginHandler.prepExports(), StartGeoLocation: StartGeoLocation, EndGeoLocation: EndGeoLocation, StartGeoLocationJS: StartGeoLocationJS, EndGeoLocationJS: EndGeoLocationJS }, domain)); }); } else { // Send back the login application @@ -1647,14 +1824,18 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { var hwstate = null; if (hardwareKeyChallenge) { hwstate = obj.parent.encodeCookie({ u: req.session.tokenusername, p: req.session.tokenpassword, c: req.session.u2fchallenge }, obj.parent.loginCookieEncryptionKey) } + // Check if we can use OTP tokens with email + var otpemail = (parent.mailserver != null) && (req.session.tokenemail); + if ((typeof domain.passwordrequirements == 'object') && (domain.passwordrequirements.email2factor == false)) { otpemail = false; } + // Render the login page - render(req, res, getRenderPage('login', req), getRenderArgs({ loginmode: loginmode, rootCertLink: getRootCertLink(), newAccount: newAccountsAllowed, newAccountPass: (((domain.newaccountspass == null) || (domain.newaccountspass == '')) ? 0 : 1), serverDnsName: obj.getWebServerName(domain), serverPublicPort: httpsPort, emailcheck: emailcheck, features: features, sessiontime: args.sessiontime, passRequirements: passRequirements, footer: (domain.footer == null) ? '' : domain.footer, hkey: encodeURIComponent(hardwareKeyChallenge), messageid: msgid, passhint: passhint, welcometext: domain.welcometext ? encodeURIComponent(domain.welcometext).split('\'').join('\\\'') : null, hwstate: hwstate }, domain)); + render(req, res, getRenderPage('login', req, domain), getRenderArgs({ loginmode: loginmode, rootCertLink: getRootCertLink(), newAccount: newAccountsAllowed, newAccountPass: (((domain.newaccountspass == null) || (domain.newaccountspass == '')) ? 0 : 1), serverDnsName: obj.getWebServerName(domain), serverPublicPort: httpsPort, emailcheck: emailcheck, features: features, sessiontime: args.sessiontime, passRequirements: passRequirements, footer: (domain.footer == null) ? '' : domain.footer, hkey: encodeURIComponent(hardwareKeyChallenge), messageid: msgid, passhint: passhint, welcometext: domain.welcometext ? encodeURIComponent(domain.welcometext).split('\'').join('\\\'') : null, hwstate: hwstate, otpemail: otpemail }, domain)); } // Handle a post request on the root function handleRootPostRequest(req, res) { const domain = checkUserIpAddress(req, res); - if (domain == null) { parent.debug('web', 'handleTermsRequest: Bad domain'); res.end("Not Found"); return; } + if (domain == null) { return; } if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.end("Not Found"); return; } // Check 3FA URL key parent.debug('web', 'handleRootPostRequest, action: ' + req.body.action); @@ -1698,7 +1879,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Serve the xterm page function handleXTermRequest(req, res) { const domain = checkUserIpAddress(req, res); - if (domain == null) { parent.debug('web', 'handleXTermRequest: Bad domain'); res.sendStatus(404); return; } + if (domain == null) { return; } if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key parent.debug('web', 'handleXTermRequest: sending xterm'); @@ -1720,7 +1901,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { const authCookie = obj.parent.encodeCookie({ userid: user._id, domainid: domain.id, ip: cleanRemoteAddr(req.ip) }, obj.parent.loginCookieEncryptionKey); const authRelayCookie = obj.parent.encodeCookie({ ruserid: user._id, domainid: domain.id }, obj.parent.loginCookieEncryptionKey); var httpsPort = ((obj.args.aliasport == null) ? obj.args.port : obj.args.aliasport); // Use HTTPS alias port is specified - render(req, res, getRenderPage('xterm', req), getRenderArgs({ serverDnsName: obj.getWebServerName(domain), serverRedirPort: args.redirport, serverPublicPort: httpsPort, authCookie: authCookie, authRelayCookie: authRelayCookie, logoutControls: JSON.stringify(logoutcontrols), name: EscapeHtml(node.name) }, domain)); + render(req, res, getRenderPage('xterm', req, domain), getRenderArgs({ serverDnsName: obj.getWebServerName(domain), serverRedirPort: args.redirport, serverPublicPort: httpsPort, authCookie: authCookie, authRelayCookie: authRelayCookie, logoutControls: JSON.stringify(logoutcontrols), name: EscapeHtml(node.name) }, domain)); }); } else { res.redirect(domain.url + getQueryPortion(req)); @@ -1731,7 +1912,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Render the terms of service. function handleTermsRequest(req, res) { const domain = checkUserIpAddress(req, res); - if (domain == null) { parent.debug('web', 'handleTermsRequest: Bad domain'); res.sendStatus(404); return; } + if (domain == null) { return; } if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key // See if term.txt was loaded from the database @@ -1739,14 +1920,14 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Send the terms from the database res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0' }); if (req.session && req.session.userid) { - if (req.session.domainid != domain.id) { req.session = null; res.redirect(domain.url + getQueryPortion(req)); return; } // Check is the session is for the correct domain + if (req.session.domainid != domain.id) { req.session = null; res.redirect(domain.url + getQueryPortion(req)); return; } // Check if the session is for the correct domain var user = obj.users[req.session.userid]; var logoutcontrols = { name: user.name }; var extras = (req.query.key != null) ? ('&key=' + req.query.key) : ''; if ((domain.ldap == null) && (domain.sspi == null) && (obj.args.user == null) && (obj.args.nousers != true)) { logoutcontrols.logoutUrl = (domain.url + 'logout?' + Math.random() + extras); } // If a default user is in use or no user mode, don't display the logout button - render(req, res, getRenderPage('terms', req), getRenderArgs({ terms: encodeURIComponent(parent.configurationFiles['terms.txt'].toString()).split('\'').join('\\\''), logoutControls: JSON.stringify(logoutcontrols) }, domain)); + render(req, res, getRenderPage('terms', req, domain), getRenderArgs({ terms: encodeURIComponent(parent.configurationFiles['terms.txt'].toString()).split('\'').join('\\\''), logoutControls: JSON.stringify(logoutcontrols) }, domain)); } else { - render(req, res, getRenderPage('terms', req), getRenderArgs({ terms: encodeURIComponent(parent.configurationFiles['terms.txt'].toString()).split('\'').join('\\\''), logoutControls: '{}' }, domain)); + render(req, res, getRenderPage('terms', req, domain), getRenderArgs({ terms: encodeURIComponent(parent.configurationFiles['terms.txt'].toString()).split('\'').join('\\\''), logoutControls: '{}' }, domain)); } } else { // See if there is a terms.txt file in meshcentral-data @@ -1758,14 +1939,14 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Send the terms from terms.txt res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0' }); if (req.session && req.session.userid) { - if (req.session.domainid != domain.id) { req.session = null; res.redirect(domain.url + getQueryPortion(req)); return; } // Check is the session is for the correct domain + if (req.session.domainid != domain.id) { req.session = null; res.redirect(domain.url + getQueryPortion(req)); return; } // Check if the session is for the correct domain var user = obj.users[req.session.userid]; var logoutcontrols = { name: user.name }; var extras = (req.query.key != null) ? ('&key=' + req.query.key) : ''; if ((domain.ldap == null) && (domain.sspi == null) && (obj.args.user == null) && (obj.args.nousers != true)) { logoutcontrols.logoutUrl = (domain.url + 'logout?' + Math.random() + extras); } // If a default user is in use or no user mode, don't display the logout button - render(req, res, getRenderPage('terms', req), getRenderArgs({ terms: encodeURIComponent(data).split('\'').join('\\\''), logoutControls: JSON.stringify(logoutcontrols) }, domain)); + render(req, res, getRenderPage('terms', req, domain), getRenderArgs({ terms: encodeURIComponent(data).split('\'').join('\\\''), logoutControls: JSON.stringify(logoutcontrols) }, domain)); } else { - render(req, res, getRenderPage('terms', req), getRenderArgs({ terms: encodeURIComponent(data).split('\'').join('\\\''), logoutControls: '{}' }, domain)); + render(req, res, getRenderPage('terms', req, domain), getRenderArgs({ terms: encodeURIComponent(data).split('\'').join('\\\''), logoutControls: '{}' }, domain)); } }); } else { @@ -1773,14 +1954,14 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { parent.debug('web', 'handleTermsRequest: sending default terms'); res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0' }); if (req.session && req.session.userid) { - if (req.session.domainid != domain.id) { req.session = null; res.redirect(domain.url + getQueryPortion(req)); return; } // Check is the session is for the correct domain + if (req.session.domainid != domain.id) { req.session = null; res.redirect(domain.url + getQueryPortion(req)); return; } // Check if the session is for the correct domain var user = obj.users[req.session.userid]; var logoutcontrols = { name: user.name }; var extras = (req.query.key != null) ? ('&key=' + req.query.key) : ''; if ((domain.ldap == null) && (domain.sspi == null) && (obj.args.user == null) && (obj.args.nousers != true)) { logoutcontrols.logoutUrl = (domain.url + 'logout?' + Math.random() + extras); } // If a default user is in use or no user mode, don't display the logout button - render(req, res, getRenderPage('terms', req), getRenderArgs({ logoutControls: JSON.stringify(logoutcontrols) }, domain)); + render(req, res, getRenderPage('terms', req, domain), getRenderArgs({ logoutControls: JSON.stringify(logoutcontrols) }, domain)); } else { - render(req, res, getRenderPage('terms', req), getRenderArgs({ logoutControls: '{}' }, domain)); + render(req, res, getRenderPage('terms', req, domain), getRenderArgs({ logoutControls: '{}' }, domain)); } } } @@ -1795,7 +1976,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { var webRtcConfig = null; if (obj.parent.config.settings && obj.parent.config.settings.webrtconfig && (typeof obj.parent.config.settings.webrtconfig == 'object')) { webRtcConfig = encodeURIComponent(JSON.stringify(obj.parent.config.settings.webrtconfig)); } res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0' }); - render(req, res, getRenderPage('messenger', req), getRenderArgs({ webrtconfig: webRtcConfig }, domain)); + render(req, res, getRenderPage('messenger', req, domain), getRenderArgs({ webrtconfig: webRtcConfig }, domain)); } // Returns the server root certificate encoded in base64 @@ -1843,6 +2024,11 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Server name is an IPv4 address obj.fs.readFile(obj.parent.path.join(obj.parent.webPublicPath, 'scripts/cira_setup_script_ip.mescript'), 'utf8', function (err, data) { if (err != null) { func(null); return; } + + // Randomize the environement detection + var randomDnsName; + do { randomDnsName = getRandomLowerCase(14); } while (randomDnsName == 'aabbccddeeffgg'); + while (data.indexOf('aabbccddeeffgg') >= 0) { data = data.replace('aabbccddeeffgg', randomDnsName); } var scriptFile = JSON.parse(data); // Change a few things in the script @@ -1862,19 +2048,18 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { scriptFile.mescript = Buffer.from(scriptEngine.script_compile(runscript), 'binary').toString('base64'); scriptFile.scriptText = runscript; - // Randomize the environement detection - var randomDnsName; - do { randomDnsName = getRandomLowerCase(14); } while (randomDnsName == 'aabbccddeeffgg'); - var text = JSON.stringify(scriptFile, null, ' '); - for (var i = 0; i < 5; i++) { text = text.replace('aabbccddeeffgg', randomDnsName); } - // Send the script - func(Buffer.from(text)); + func(Buffer.from(JSON.stringify(scriptFile, null, ' '))); }); } else { // Server name is a hostname obj.fs.readFile(obj.parent.path.join(obj.parent.webPublicPath, 'scripts/cira_setup_script_dns.mescript'), 'utf8', function (err, data) { if (err != null) { res.sendStatus(404); return; } + + // Randomize the environement detection + var randomDnsName; + do { randomDnsName = getRandomLowerCase(14); } while (randomDnsName == 'aabbccddeeffgg'); + while (data.indexOf('aabbccddeeffgg') >= 0) { data = data.replace('aabbccddeeffgg', randomDnsName); } var scriptFile = JSON.parse(data); // Change a few things in the script @@ -1893,14 +2078,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { scriptFile.mescript = Buffer.from(scriptEngine.script_compile(runscript), 'binary').toString('base64'); scriptFile.scriptText = runscript; - // Randomize the environement detection - var randomDnsName; - do { randomDnsName = getRandomLowerCase(14); } while (randomDnsName == 'aabbccddeeffgg'); - var text = JSON.stringify(scriptFile, null, ' '); - for (var i = 0; i < 5; i++) { text = text.replace('aabbccddeeffgg', randomDnsName); } - // Send the script - func(Buffer.from(text)); + func(Buffer.from(JSON.stringify(scriptFile, null, ' '))); }); } } @@ -1937,7 +2116,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Handle user public file downloads function handleDownloadUserFiles(req, res) { const domain = checkUserIpAddress(req, res); - if (domain == null) { res.sendStatus(404); return; } + if (domain == null) { return; } if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key if (obj.common.validateString(req.path, 1, 4096) == false) { res.sendStatus(404); return; } @@ -1958,19 +2137,20 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { } try { res.sendFile(obj.path.resolve(__dirname, path)); } catch (e) { res.sendStatus(404); } } else { - render(req, res, getRenderPage('download', req), getRenderArgs({ rootCertLink: getRootCertLink(), message: "" + filename + ", " + stat.size + " byte" + ((stat.size < 2) ? '' : 's') + "." }, domain)); + render(req, res, getRenderPage('download', req, domain), getRenderArgs({ rootCertLink: getRootCertLink(), message: "" + filename + ", " + stat.size + " byte" + ((stat.size < 2) ? '' : 's') + "." }, domain)); } } else { - render(req, res, getRenderPage('download', req), getRenderArgs({ rootCertLink: getRootCertLink(), message: "Invalid file link, please check the URL again." }, domain)); + render(req, res, getRenderPage('download', req, domain), getRenderArgs({ rootCertLink: getRootCertLink(), message: "Invalid file link, please check the URL again." }, domain)); } } // Handle logo request function handleLogoRequest(req, res) { const domain = checkUserIpAddress(req, res); + if (domain == null) { return; } //res.set({ 'Cache-Control': 'max-age=86400' }); // 1 day - if ((domain != null) && domain.titlepicture) { + if (domain.titlepicture) { if ((parent.configurationFiles != null) && (parent.configurationFiles[domain.titlepicture] != null)) { // Use the logo in the database res.set({ 'Content-Type': 'image/jpeg' }); @@ -1982,7 +2162,10 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { } } - if (parent.webPublicOverridePath && obj.fs.existsSync(obj.path.join(obj.parent.webPublicOverridePath, 'images/logoback.png'))) { + if ((domain.webpublicpath != null) && (obj.fs.existsSync(obj.path.join(domain.webpublicpath, 'images/logoback.png')))) { + // Use the domain logo picture + try { res.sendFile(obj.path.join(domain.webpublicpath, 'images/logoback.png')); } catch (ex) { res.sendStatus(404); } + } else if (parent.webPublicOverridePath && obj.fs.existsSync(obj.path.join(obj.parent.webPublicOverridePath, 'images/logoback.png'))) { // Use the override logo picture try { res.sendFile(obj.path.join(obj.parent.webPublicOverridePath, 'images/logoback.png')); } catch (ex) { res.sendStatus(404); } } else { @@ -1994,6 +2177,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Handle translation request function handleTranslationsRequest(req, res) { const domain = checkUserIpAddress(req, res); + if (domain == null) { return; } //if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key if ((obj.userAllowedIp != null) && (checkIpAddressEx(req, res, obj.userAllowedIp, false) === false)) { return; } // Check server-wide IP filter only. @@ -2057,9 +2241,10 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Handle welcome image request function handleWelcomeImageRequest(req, res) { const domain = checkUserIpAddress(req, res); + if (domain == null) { return; } //res.set({ 'Cache-Control': 'max-age=86400' }); // 1 day - if ((domain != null) && domain.welcomepicture) { + if (domain.welcomepicture) { if ((parent.configurationFiles != null) && (parent.configurationFiles[domain.welcomepicture] != null)) { // Use the welcome image in the database res.set({ 'Content-Type': 'image/jpeg' }); @@ -2071,7 +2256,17 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { try { res.sendFile(obj.path.join(obj.parent.datapath, domain.welcomepicture)); return; } catch (ex) { } } - if (parent.webPublicOverridePath) { + if (domain.webpublicpath != null) { + obj.fs.exists(obj.path.join(domain.webpublicpath, 'images/mainwelcome.jpg'), function (exists) { + if (exists) { + // Use the domain logo picture + try { res.sendFile(obj.path.join(domain.webpublicpath, 'images/mainwelcome.jpg')); } catch (ex) { res.sendStatus(404); } + } else { + // Use the default logo picture + try { res.sendFile(obj.path.join(obj.parent.webPublicPath, 'images/mainwelcome.jpg')); } catch (ex) { res.sendStatus(404); } + } + }); + } else if (parent.webPublicOverridePath) { obj.fs.exists(obj.path.join(obj.parent.webPublicOverridePath, 'images/mainwelcome.jpg'), function (exists) { if (exists) { // Use the override logo picture @@ -2090,17 +2285,18 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Server the player page function handlePlayerRequest(req, res) { const domain = checkUserIpAddress(req, res); - if ((domain == null) || (domain.redirects == null)) { res.sendStatus(404); return; } + if (domain == null) { return; } parent.debug('web', 'handlePlayerRequest: sending player'); res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0' }); - render(req, res, getRenderPage('player', req), getRenderArgs({}, domain)); + render(req, res, getRenderPage('player', req, domain), getRenderArgs({}, domain)); } // Handle domain redirection obj.handleDomainRedirect = function (req, res) { const domain = checkUserIpAddress(req, res); - if ((domain == null) || (domain.redirects == null)) { res.sendStatus(404); return; } + if (domain == null) { return; } + if (domain.redirects == null) { res.sendStatus(404); return; } var urlArgs = '', urlName = null, splitUrl = req.originalUrl.split('?'); if (splitUrl.length > 1) { urlArgs = '?' + splitUrl[1]; } if ((splitUrl.length > 0) && (splitUrl[0].length > 1)) { urlName = splitUrl[0].substring(1).toLowerCase(); } @@ -2150,7 +2346,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Download a file from the server function handleDownloadFile(req, res) { const domain = checkUserIpAddress(req, res); - if (domain == null) { res.sendStatus(404); return; } + if (domain == null) { return; } if ((req.query.link == null) || (req.session == null) || (req.session.userid == null) || (domain == null) || (domain.userQuota == -1)) { res.sendStatus(404); return; } const user = obj.users[req.session.userid]; if (user == null) { res.sendStatus(404); return; } @@ -2167,7 +2363,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Upload a MeshCore.js file to the server function handleUploadMeshCoreFile(req, res) { const domain = checkUserIpAddress(req, res); - if (domain == null) { res.sendStatus(404); return; } + if (domain == null) { return; } if (domain.id !== '') { res.sendStatus(401); return; } var authUserid = null; @@ -2205,7 +2401,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Upload a file to the server function handleUploadFile(req, res) { const domain = checkUserIpAddress(req, res); - if (domain == null) { res.sendStatus(404); return; } + if (domain == null) { return; } if (domain.userQuota == -1) { res.sendStatus(401); return; } var authUserid = null; if ((req.session != null) && (typeof req.session.userid == 'string')) { authUserid = req.session.userid; } @@ -2330,7 +2526,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if (!node.intelamt) { console.log('ERR: Not AMT node'); try { ws.close(); } catch (e) { } return; } // Disconnect websocket // Check if this user has permission to manage this computer - if ((obj.GetMeshRights(user, node.meshid) & MESHRIGHT_REMOTECONTROL) == 0) { console.log('ERR: Access denied (2)'); try { ws.close(); } catch (e) { } return; } + if ((obj.GetNodeRights(user, node.meshid, node._id) & MESHRIGHT_REMOTECONTROL) == 0) { console.log('ERR: Access denied (3)'); try { ws.close(); } catch (e) { } return; } // Check what connectivity is available for this node var state = parent.GetConnectivityState(req.query.host); @@ -2420,7 +2616,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // TLSSocket to encapsulate TLS communication, which then tunneled via SerialTunnel an then wrapped through CIRA APF const TLSSocket = require('tls').TLSSocket; - const tlsoptions = { secureProtocol: ((req.query.tls1only == 1) ? 'TLSv1_method' : 'SSLv23_method'), ciphers: 'RSA+AES:!aNULL:!MD5:!DSS', secureOptions: constants.SSL_OP_NO_SSLv2 | constants.SSL_OP_NO_SSLv3 | constants.SSL_OP_NO_COMPRESSION | constants.SSL_OP_CIPHER_SERVER_PREFERENCE, rejectUnauthorized: false }; + const tlsoptions = { ciphers: 'RSA+AES:!aNULL:!MD5:!DSS', secureOptions: constants.SSL_OP_NO_SSLv2 | constants.SSL_OP_NO_SSLv3 | constants.SSL_OP_NO_COMPRESSION | constants.SSL_OP_CIPHER_SERVER_PREFERENCE, rejectUnauthorized: false }; + if (req.query.tls1only == 1) { tlsoptions.secureProtocol = 'TLSv1_method'; } const tlsock = new TLSSocket(ser, tlsoptions); tlsock.on('error', function (err) { parent.debug('webrelay', "CIRA TLS Connection Error ", err); }); tlsock.on('secureConnect', function () { parent.debug('webrelay', "CIRA Secure TLS Connection"); ws._socket.resume(); }); @@ -2601,7 +2798,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { ws._socket.resume(); } else { // If TLS is going to be used, setup a TLS socket - var tlsoptions = { secureProtocol: ((req.query.tls1only == 1) ? 'TLSv1_method' : 'SSLv23_method'), ciphers: 'RSA+AES:!aNULL:!MD5:!DSS', secureOptions: constants.SSL_OP_NO_SSLv2 | constants.SSL_OP_NO_SSLv3 | constants.SSL_OP_NO_COMPRESSION | constants.SSL_OP_CIPHER_SERVER_PREFERENCE, rejectUnauthorized: false }; + var tlsoptions = { ciphers: 'RSA+AES:!aNULL:!MD5:!DSS', secureOptions: constants.SSL_OP_NO_SSLv2 | constants.SSL_OP_NO_SSLv3 | constants.SSL_OP_NO_COMPRESSION | constants.SSL_OP_CIPHER_SERVER_PREFERENCE, rejectUnauthorized: false }; + if (req.query.tls1only == 1) { tlsoptions.secureProtocol = 'TLSv1_method'; } ws.forwardclient = obj.tls.connect(port, node.host, tlsoptions, function () { // The TLS connection method is the same as TCP, but located a bit differently. parent.debug('webrelay', 'TLS connected to ' + node.host + ':' + port + '.'); @@ -2632,13 +2830,13 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // If the TCP connection closes, disconnect the associated web socket. ws.forwardclient.on('close', function () { - parent.debug('webrelay', 'TCP relay disconnected from ' + node.host + '.'); + parent.debug('webrelay', 'TCP relay disconnected from ' + node.host + ':' + port + '.'); try { ws.close(); } catch (e) { } }); // If the TCP connection causes an error, disconnect the associated web socket. ws.forwardclient.on('error', function (err) { - parent.debug('webrelay', 'TCP relay error from ' + node.host + ': ' + err.errno); + parent.debug('webrelay', 'TCP relay error from ' + node.host + ':' + port + ': ' + err); try { ws.close(); } catch (e) { } }); @@ -2663,14 +2861,14 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Handle a Intel AMT activation request function handleAmtActivateWebSocket(ws, req) { const domain = checkUserIpAddress(ws, req); - if (domain == null) { ws.send(JSON.stringify({ errorText: 'Invalid domain' })); ws.close(); return; } + if (domain == null) { return; } if (req.query.id == null) { ws.send(JSON.stringify({ errorText: 'Missing group identifier' })); ws.close(); return; } // Fetch the mesh object ws.meshid = 'mesh/' + domain.id + '/' + req.query.id; const mesh = obj.meshes[ws.meshid]; - if (mesh == null) { delete ws.meshid; ws.send(JSON.stringify({ errorText: 'Invalid device group' })); ws.close(); return; } - if (mesh.mtype != 1) { ws.send(JSON.stringify({ errorText: 'Invalid device group type' })); ws.close(); return; } + if (mesh == null) { ws.send(JSON.stringify({ errorText: 'Invalid device group: ' + ws.meshid })); delete ws.meshid; ws.close(); return; } + if (mesh.mtype != 1) { ws.send(JSON.stringify({ errorText: 'Invalid device group type:' + ws.meshid })); delete ws.meshid; ws.close(); return; } // Fetch the remote IP:Port for logging ws.remoteaddr = cleanRemoteAddr(req.ip); @@ -2852,7 +3050,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Handle the web socket echo request, just echo back the data sent function handleEchoWebSocket(ws, req) { const domain = checkUserIpAddress(ws, req); - if (domain == null) { res.sendStatus(404); return; } + if (domain == null) { return; } ws._socket.setKeepAlive(true, 240000); // Set TCP keep alive // When data is received from the web socket, echo it back @@ -2937,7 +3135,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Update the database var oldname = node.host; node.host = amthost; - obj.db.Set(node); + obj.db.Set(obj.cleanDevice(node)); // Event the node change var event = { etype: 'node', action: 'changenode', nodeid: node._id, domain: domain.id, msg: 'Intel(R) AMT host change ' + node.name + ' from group ' + mesh.name + ': ' + oldname + ' to ' + amthost }; @@ -2981,7 +3179,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Handle a server backup request function handleBackupRequest(req, res) { const domain = checkUserIpAddress(req, res); - if (domain == null) { res.sendStatus(404); return; } + if (domain == null) { return; } if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key if ((!req.session) || (req.session == null) || (!req.session.userid) || (obj.parent.args.noserverbackup == 1)) { res.sendStatus(401); return; } var user = obj.users[req.session.userid]; @@ -3014,7 +3212,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Handle a server restore request function handleRestoreRequest(req, res) { const domain = checkUserIpAddress(req, res); - if (domain == null) { res.sendStatus(404); return; } + if (domain == null) { return; } if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key if (obj.parent.args.noserverbackup == 1) { res.sendStatus(401); return; } var authUserid = null; @@ -3041,8 +3239,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Handle a request to download a mesh agent obj.handleMeshAgentRequest = function (req, res) { - const domain = checkUserIpAddress(req, res); - if (domain == null) { res.sendStatus(404); return; } + var domain = getDomain(req, res); + if (domain == null) { parent.debug('web', 'handleRootRequest: invalid domain.'); try { res.sendStatus(404); } catch (ex) { } return; } // If required, check if this user has rights to do this if ((obj.parent.config.settings != null) && ((obj.parent.config.settings.lockagentdownload == true) || (domain.lockagentdownload == true)) && (req.session.userid == null)) { res.sendStatus(401); return; } @@ -3093,6 +3291,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { obj.parent.exeHandler.streamExeWithMeshPolicy({ platform: 'win32', sourceFileName: obj.parent.meshAgentBinaries[req.query.id].path, destinationStream: res, msh: meshsettings, peinfo: obj.parent.meshAgentBinaries[req.query.id].pe }); } } else if (req.query.script != null) { + if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key + // Send a specific mesh install script back var scriptInfo = obj.parent.meshAgentInstallScripts[req.query.script]; if (scriptInfo == null) { res.sendStatus(404); return; } @@ -3112,6 +3312,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { for (var i in cmdoptions) { data = data.split('{{{' + i + '}}}').join(cmdoptions[i]); } res.send(data); } else if (req.query.meshcmd != null) { + if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key + // Send meshcmd for a specific platform back var agentid = parseInt(req.query.meshcmd); // If the agentid is 3 or 4, check if we have a signed MeshCmd.exe @@ -3138,8 +3340,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { obj.parent.exeHandler.streamExeWithJavaScript({ platform: argentInfo.platform, sourceFileName: argentInfo.path, destinationStream: res, js: Buffer.from(obj.parent.defaultMeshCmd, 'utf8'), peinfo: argentInfo.pe }); } } else if (req.query.meshaction != null) { - const domain = checkUserIpAddress(req, res); - if (domain == null) { res.sendStatus(404); return; } + if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key var user = obj.users[req.session.userid]; if ((req.query.meshaction == 'route') && (req.query.nodeid != null)) { obj.db.Get(req.query.nodeid, function (err, nodes) { @@ -3152,7 +3353,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { localPort: 1234, remoteName: node.name, remoteNodeId: node._id, - remoteTarget: '', + remoteTarget: null, remotePort: 3389, username: '', password: '', @@ -3166,10 +3367,9 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'text/plain', 'Content-Disposition': 'attachment; filename="meshaction.txt"' }); res.send(JSON.stringify(meshaction, null, ' ')); }); - } - else if (req.query.meshaction == 'generic') { + } else if (req.query.meshaction == 'generic') { var meshaction = { - username: '', + username: user.name, password: '', serverId: obj.agentCertificateHashHex.toUpperCase(), // SHA384 of server HTTPS public key serverHttpsHash: Buffer.from(obj.webCertificateHashs[domain.id], 'binary').toString('hex').toUpperCase(), // SHA384 of server HTTPS certificate @@ -3190,15 +3390,19 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { res.sendStatus(401); } } else { + domain = checkUserIpAddress(req, res); // Recheck the domain to apply user IP filtering. + if (domain == null) return; + if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key // Send a list of available mesh agents var response = 'Mesh Agents'; response += ''; for (var agentid in obj.parent.meshAgentBinaries) { var agentinfo = obj.parent.meshAgentBinaries[agentid]; + var originalUrl = req.originalUrl.split('?')[0]; response += ''; - response += ''; + response += ''; response += ''; - response += ''; + response += ''; } response += '
IDDescriptionLinkSizeSHA384MeshCmd
' + agentinfo.id + '' + agentinfo.desc + '' + agentinfo.rname + '' + agentinfo.rname + '' + agentinfo.size + '' + agentinfo.hashhex + '' + agentinfo.rname.replace('agent', 'cmd') + '
' + agentinfo.rname.replace('agent', 'cmd') + '
'; res.send(response); @@ -3213,8 +3417,9 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Create a OSX mesh agent installer obj.handleMeshOsxAgentRequest = function (req, res) { - const domain = checkUserIpAddress(req, res); - if ((domain == null) || (req.query.id == null)) { res.sendStatus(404); return; } + const domain = getDomain(req, res); + if (domain == null) { parent.debug('web', 'handleRootRequest: invalid domain.'); try { res.sendStatus(404); } catch (ex) { } return; } + if (req.query.id == null) { res.sendStatus(404); return; } // If required, check if this user has rights to do this if ((obj.parent.config.settings != null) && ((obj.parent.config.settings.lockagentdownload == true) || (domain.lockagentdownload == true)) && (req.session.userid == null)) { res.sendStatus(401); return; } @@ -3304,8 +3509,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Handle a request to download a mesh settings obj.handleMeshSettingsRequest = function (req, res) { - const domain = checkUserIpAddress(req, res); - if (domain == null) { res.sendStatus(404); return; } + const domain = getDomain(req); + if (domain == null) { return; } //if ((domain.id !== '') || (!req.session) || (req.session == null) || (!req.session.userid)) { res.sendStatus(401); return; } // If required, check if this user has rights to do this @@ -3342,7 +3547,8 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Handle a request for power events obj.handleDevicePowerEvents = function (req, res) { const domain = checkUserIpAddress(req, res); - if (domain == null) { res.sendStatus(404); return; } + if (domain == null) { return; } + if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key if ((domain.id !== '') || (!req.session) || (req.session == null) || (!req.session.userid) || (req.query.id == null) || (typeof req.query.id != 'string')) { res.sendStatus(401); return; } var x = req.query.id.split('/'); var user = obj.users[req.session.userid]; @@ -3355,7 +3561,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { var node = docs[0]; // Check if we have right to this node - if (obj.GetMeshRights(user, node.meshid) == 0) { res.sendStatus(401); return; } + if (obj.GetNodeRights(user, node.meshid, node._id) == 0) { res.sendStatus(401); return; } // Get the list of power events and send them res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'text/csv', 'Content-Disposition': 'attachment; filename="powerevents.csv"' }); @@ -3381,7 +3587,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Handle a plugin admin request obj.handlePluginAdminReq = function (req, res) { const domain = checkUserIpAddress(req, res); - if (domain == null) { res.sendStatus(404); return; } + if (domain == null) { return; } if ((!req.session) || (req.session == null) || (!req.session.userid)) { res.sendStatus(401); return; } var user = obj.users[req.session.userid]; if (user == null) { res.sendStatus(401); return; } @@ -3391,7 +3597,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { obj.handlePluginAdminPostReq = function (req, res) { const domain = checkUserIpAddress(req, res); - if (domain == null) { res.sendStatus(404); return; } + if (domain == null) { return; } if ((!req.session) || (req.session == null) || (!req.session.userid)) { res.sendStatus(401); return; } var user = obj.users[req.session.userid]; if (user == null) { res.sendStatus(401); return; } @@ -3401,7 +3607,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { obj.handlePluginJS = function (req, res) { const domain = checkUserIpAddress(req, res); - if (domain == null) { res.sendStatus(404); return; } + if (domain == null) { return; } if ((!req.session) || (req.session == null) || (!req.session.userid)) { res.sendStatus(401); return; } var user = obj.users[req.session.userid]; if (user == null) { res.sendStatus(401); return; } @@ -3538,6 +3744,10 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { obj.app.get(url + 'player.htm', handlePlayerRequest); obj.app.get(url + 'player', handlePlayerRequest); obj.app.ws(url + 'amtactivate', handleAmtActivateWebSocket); + if (parent.config.domains[i].agentinvitecodes == true) { + obj.app.get(url + 'invite', handleInviteRequest); + obj.app.post(url + 'invite', handleInviteRequest); + } if (parent.pluginHandler != null) { obj.app.get(url + 'pluginadmin.ashx', obj.handlePluginAdminReq); obj.app.post(url + 'pluginadmin.ashx', obj.handlePluginAdminPostReq); @@ -3560,7 +3770,11 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Use the data folder server picture try { res.sendFile(p); } catch (ex) { res.sendStatus(404); } } else { - if (parent.webPublicOverridePath && obj.fs.existsSync(obj.path.join(obj.parent.webPublicOverridePath, 'images/server-256.png'))) { + var domain = getDomain(req); + if ((domain != null) && (domain.webpublicpath != null) && (obj.fs.existsSync(obj.path.join(domain.webpublicpath, 'images/server-256.png')))) { + // Use the domain server picture + try { res.sendFile(obj.path.join(domain.webpublicpath, 'images/server-256.png')); } catch (ex) { res.sendStatus(404); } + } else if (parent.webPublicOverridePath && obj.fs.existsSync(obj.path.join(obj.parent.webPublicOverridePath, 'images/server-256.png'))) { // Use the override server picture try { res.sendFile(obj.path.join(obj.parent.webPublicOverridePath, 'images/server-256.png')); } catch (ex) { res.sendStatus(404); } } else { @@ -3574,7 +3788,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Receive mesh agent connections obj.app.ws(url + 'agent.ashx', function (ws, req) { var domain = checkAgentIpAddress(ws, req); - if (domain == null) { parent.debug('web', 'Got agent connection from blocked IP address ' + cleanRemoteAddr(req.ip) + ', holding.'); return; } + if (domain == null) { parent.debug('web', 'Got agent connection with bad domain or blocked IP address ' + cleanRemoteAddr(req.ip) + ', holding.'); return; } //console.log('Agent connect: ' + cleanRemoteAddr(req.ip)); try { obj.meshAgentHandler.CreateMeshAgent(obj, obj.db, ws, req, obj.args, domain); } catch (e) { console.log(e); } }); @@ -3583,7 +3797,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if (obj.parent.mqttbroker != null) { obj.app.ws(url + 'mqtt.ashx', function (ws, req) { var domain = checkAgentIpAddress(ws, req); - if (domain == null) { parent.debug('web', 'Got agent connection from blocked IP address ' + cleanRemoteAddr(req.ip) + ', holding.'); return; } + if (domain == null) { parent.debug('web', 'Got agent connection with bad domain or blocked IP address ' + cleanRemoteAddr(req.ip) + ', holding.'); return; } var serialtunnel = SerialTunnel(); serialtunnel.xtransport = 'ws'; serialtunnel.xdomain = domain; @@ -3629,7 +3843,13 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { //obj.app.get(url + 'stop', function (req, res) { res.send('Stopping Server, click here to login.'); setTimeout(function () { parent.Stop(); }, 500); }); // Indicates to ExpressJS that the override public folder should be used to serve static files. - if (obj.parent.webPublicOverridePath != null) { obj.app.use(url, obj.express.static(obj.parent.webPublicOverridePath)); } + if (parent.config.domains[i].webpublicpath != null) { + // Use domain public path + obj.app.use(url, obj.express.static(parent.config.domains[i].webpublicpath)); + } else if (obj.parent.webPublicOverridePath != null) { + // Use override path + obj.app.use(url, obj.express.static(obj.parent.webPublicOverridePath)); + } // Indicates to ExpressJS that the default public folder should be used to serve static files. obj.app.use(url, obj.express.static(obj.parent.webPublicPath)); @@ -3643,7 +3863,9 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { obj.app.use(function (req, res, next) { parent.debug('web', '404 Error ' + req.url); var domain = getDomain(req); - res.status(404).render(getRenderPage('error404', req), getRenderArgs({}, domain)); + if ((domain == null) || (domain.auth == 'sspi')) { res.sendStatus(404); return; } + if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key + res.status(404).render(getRenderPage('error404', req, domain), getRenderArgs({}, domain)); }); } @@ -3661,8 +3883,14 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Check IP filtering and domain var domain = null; - if (noAuthOk == true) { domain = getDomain(req); } else { domain = checkUserIpAddress(ws, req); } // If auth is required, enforce IP address filtering. - if (domain == null) { try { ws.send(JSON.stringify({ action: 'close', cause: 'noauth', msg: 'noauth-1' })); ws.close(); return; } catch (e) { return; } } + if (noAuthOk == true) { + domain = getDomain(req); + if (domain == null) { try { ws.send(JSON.stringify({ action: 'close', cause: 'noauth', msg: 'noauth-1' })); ws.close(); return; } catch (e) { } return; } + } else { + // If authentication is required, enforce IP address filtering. + domain = checkUserIpAddress(ws, req); + if (domain == null) { return; } + } // A web socket session can be authenticated in many ways (Default user, session, user/pass and cookie). Check authentication here. if ((req.query.user != null) && (req.query.pass != null)) { @@ -3672,12 +3900,26 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if ((err == null) && (user)) { // Check if a 2nd factor is needed if (checkUserOneTimePasswordRequired(domain, user, req) == true) { - if (typeof req.query.token != 'string') { - try { ws.send(JSON.stringify({ action: 'close', cause: 'noauth', msg: 'tokenrequired' })); ws.close(); } catch (e) { } + // Figure out if email 2FA is allowed + var email2fa = (((typeof domain.passwordrequirements != 'object') || (domain.passwordrequirements.email2factor != false)) && (parent.mailserver != null) && (user.otpekey != null)); + if ((typeof req.query.token != 'string') || (req.query.token == '**email**')) { + if ((req.query.token == '**email**') && (email2fa == true)) { + // Cause a token to be sent to the user's registered email + user.otpekey = { k: obj.common.zeroPad(getRandomEightDigitInteger(), 8), d: Date.now() }; + obj.db.SetUser(user); + parent.debug('web', 'Sending 2FA email to: ' + user.email); + parent.mailserver.sendAccountLoginMail(domain, user.email, user.otpekey.k, obj.getLanguageCodes(req)); + // Ask for a login token & confirm email was sent + try { ws.send(JSON.stringify({ action: 'close', cause: 'noauth', msg: 'tokenrequired', email2fa: email2fa, email2fasent: true })); ws.close(); } catch (e) { } + } else { + // Ask for a login token + try { ws.send(JSON.stringify({ action: 'close', cause: 'noauth', msg: 'tokenrequired', email2fa: email2fa })); ws.close(); } catch (e) { } + } } else { checkUserOneTimePassword(req, domain, user, req.query.token, null, function (result) { if (result == false) { - try { ws.send(JSON.stringify({ action: 'close', cause: 'noauth', msg: 'tokenrequired' })); ws.close(); } catch (e) { } + // Failed, ask for a login token again + try { ws.send(JSON.stringify({ action: 'close', cause: 'noauth', msg: 'tokenrequired', email2fa: email2fa })); ws.close(); } catch (e) { } } else { // We are authenticated with 2nd factor. func(ws, req, domain, user); @@ -3731,12 +3973,25 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if ((err == null) && (user)) { // Check if a 2nd factor is needed if (checkUserOneTimePasswordRequired(domain, user, req) == true) { + // Figure out if email 2FA is allowed + var email2fa = (((typeof domain.passwordrequirements != 'object') || (domain.passwordrequirements.email2factor != false)) && (parent.mailserver != null) && (user.otpekey != null)); if (s.length != 3) { - try { ws.send(JSON.stringify({ action: 'close', cause: 'noauth', msg: 'tokenrequired' })); ws.close(); } catch (e) { } + try { ws.send(JSON.stringify({ action: 'close', cause: 'noauth', msg: 'tokenrequired', email2fa: email2fa })); ws.close(); } catch (e) { } } else { checkUserOneTimePassword(req, domain, user, s[2], null, function (result) { if (result == false) { - try { ws.send(JSON.stringify({ action: 'close', cause: 'noauth', msg: 'tokenrequired' })); ws.close(); } catch (e) { } + if ((s[2] == '**email**') && (email2fa == true)) { + // Cause a token to be sent to the user's registered email + user.otpekey = { k: obj.common.zeroPad(getRandomEightDigitInteger(), 8), d: Date.now() }; + obj.db.SetUser(user); + parent.debug('web', 'Sending 2FA email to: ' + user.email); + parent.mailserver.sendAccountLoginMail(domain, user.email, user.otpekey.k, obj.getLanguageCodes(req)); + // Ask for a login token & confirm email was sent + try { ws.send(JSON.stringify({ action: 'close', cause: 'noauth', msg: 'tokenrequired', email2fa: email2fa, email2fasent: true })); ws.close(); } catch (e) { } + } else { + // Ask for a login token + try { ws.send(JSON.stringify({ action: 'close', cause: 'noauth', msg: 'tokenrequired', email2fa: email2fa })); ws.close(); } catch (e) { } + } } else { // We are authenticated with 2nd factor. func(ws, req, domain, user); @@ -3806,6 +4061,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { obj.tcpServer = obj.tlsServer.listen(port, function () { console.log('MeshCentral HTTPS server running on ' + certificates.CommonName + ':' + port + ((args.aliasport != null) ? (', alias port ' + args.aliasport) : '') + '.'); }); obj.parent.updateServerState('servername', certificates.CommonName); } + if (obj.parent.authlog) { obj.parent.authLog('https', 'Server listening on 0.0.0.0 port ' + port + '.'); } obj.parent.updateServerState('https-port', port); if (args.aliasport != null) { obj.parent.updateServerState('https-aliasport', args.aliasport); } } else { @@ -3991,12 +4247,20 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { db.Get(nodeid, function (err, nodes) { if ((nodes == null) || (nodes.length != 1)) { func(null, 0, false); return; } // No such nodeid - // Check direct link - var rights = 0, visible = false, r = user.links[nodes[0].meshid]; + // Check device link + var rights = 0, visible = false, r = user.links[nodeid]; if (r != null) { - rights = r.rights; + if (r.rights == 0xFFFFFFFF) { func(nodes[0], 0xFFFFFFFF, true); return; } // User has full rights thru a device link, stop here. + rights |= r.rights; + visible = true; + } + + // Check device group link + r = user.links[nodes[0].meshid]; + if (r != null) { + if (r.rights == 0xFFFFFFFF) { func(nodes[0], 0xFFFFFFFF, true); return; } // User has full rights thru a device group link, stop here. + rights |= r.rights; visible = true; - if (rights == 0xFFFFFFFF) { func(nodes[0], rights, true); return; } // User has full rights thru a direct link, stop here. } // Check user group links @@ -4006,7 +4270,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if (g && (g.links != null)) { r = g.links[nodes[0].meshid]; if (r != null) { - if (r.rights == 0xFFFFFFFF) { func(nodes[0], r.rights, true); return; } // User has full rights thru a user group link, stop here. + if (r.rights == 0xFFFFFFFF) { func(nodes[0], 0xFFFFFFFF, true); return; } // User has full rights thru a user group link, stop here. rights |= r.rights; // TODO: Deal with reverse rights visible = true; } @@ -4023,7 +4287,14 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { obj.GetAllMeshWithRights = function (user, rights) { if (typeof user == 'string') { user = obj.users[user]; } if ((user == null) || (user.links == null)) { return []; } + var r = []; + if ((user.siteadmin == 0xFFFFFFFF) && (parent.config.settings.managealldevicegroups.indexOf(user._id) >= 0)) { + // This is a super user that can see all device groups for a given domain + var meshStartStr = 'mesh/' + user.domain + '/'; + for (var i in obj.meshes) { if ((obj.meshes[i]._id.startsWith(meshStartStr)) && (obj.meshes[i].deleted == null)) { r.push(obj.meshes[i]); } } + return r; + } for (var i in user.links) { if (i.startsWith('mesh/')) { // Grant access to a device group thru a direct link @@ -4054,6 +4325,12 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if (typeof user == 'string') { user = obj.users[user]; } if ((user == null) || (user.links == null)) { return []; } var r = []; + if ((user.siteadmin == 0xFFFFFFFF) && (parent.config.settings.managealldevicegroups.indexOf(user._id) >= 0)) { + // This is a super user that can see all device groups for a given domain + var meshStartStr = 'mesh/' + user.domain + '/'; + for (var i in obj.meshes) { if ((obj.meshes[i]._id.startsWith(meshStartStr)) && (obj.meshes[i].deleted == null)) { r.push(obj.meshes[i]._id); } } + return r; + } for (var i in user.links) { if (i.startsWith('mesh/')) { // Grant access to a device group thru a direct link @@ -4079,7 +4356,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { return r; } - // Get the right of a user on a given device group + // Get the rights of a user on a given device group obj.GetMeshRights = function (user, mesh) { if ((user == null) || (mesh == null)) { return 0; } if (typeof user == 'string') { user = obj.users[user]; } @@ -4091,6 +4368,9 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { meshid = mesh._id; } else return 0; + // Check if this is a super user that can see all device groups for a given domain + if ((user.siteadmin == 0xFFFFFFFF) && (parent.config.settings.managealldevicegroups.indexOf(user._id) >= 0) && (meshid.startsWith('mesh/' + user.domain + '/'))) { return 0xFFFFFFFF; } + // Check direct user to device group permissions var rights = 0; r = user.links[meshid]; @@ -4132,6 +4412,9 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { meshid = mesh._id; } else return false; + // Check if this is a super user that can see all device groups for a given domain + if ((user.siteadmin == 0xFFFFFFFF) && (parent.config.settings.managealldevicegroups.indexOf(user._id) >= 0) && (meshid.startsWith('mesh/' + user.domain + '/'))) { return true; } + // Check direct user to device group permissions if (user.links[meshid] != null) { return true; } // If the user has a direct link, stop here. @@ -4146,6 +4429,18 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { return false; } + // Return the user rights for a given node + obj.GetNodeRights = function (user, mesh, nodeid) { + if ((user == null) || (mesh == null) || (nodeid == null)) { return 0; } + if (typeof user == 'string') { user = obj.users[user]; } + var r = obj.GetMeshRights(user, mesh); + if (r == 0xFFFFFFFF) return r; + + // Check direct device rights using device data + if ((user.links != null) && (user.links[nodeid] != null)) { r |= user.links[nodeid].rights; } // TODO: Deal with reverse permissions + return r; + } + // Returns a list of displatch targets for a given mesh // We have to target the meshid and all user groups for this mesh, plus any added targets obj.CreateMeshDispatchTargets = function (mesh, addedTargets) { @@ -4170,6 +4465,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { delete user2.domain; delete user2.subscriptions; delete user2.passtype; + if ((typeof user2.otpekey == 'object') && (user2.otpekey != null)) { user2.otpekey = 1; } // Indicates that email 2FA is enabled. if ((typeof user2.otpsecret == 'string') && (user2.otpsecret != null)) { user2.otpsecret = 1; } // Indicates a time secret is present. if ((typeof user2.otpkeys == 'object') && (user2.otpkeys != null)) { user2.otpkeys = 0; if (user.otpkeys != null) { for (var i = 0; i < user.otpkeys.keys.length; i++) { if (user.otpkeys.keys[i].u == true) { user2.otpkeys = 1; } } } } // Indicates the number of one time backup codes that are active. if ((typeof user2.otphkeys == 'object') && (user2.otphkeys != null)) { user2.otphkeys = user2.otphkeys.length; } // Indicates the number of hardware keys setup @@ -4201,7 +4497,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { } // Filter the user web site and only output state that we need to keep - const acceptableUserWebStateStrings = ['webPageStackMenu', 'notifications', 'deviceView', 'nightMode', 'webPageFullScreen', 'search', 'showRealNames', 'sort', 'deskAspectRatio', 'viewsize', 'DeskControl', 'uiMode']; + const acceptableUserWebStateStrings = ['webPageStackMenu', 'notifications', 'deviceView', 'nightMode', 'webPageFullScreen', 'search', 'showRealNames', 'sort', 'deskAspectRatio', 'viewsize', 'DeskControl', 'uiMode', 'footerBar']; const acceptableUserWebStateDesktopStrings = ['encoding', 'showfocus', 'showmouse', 'showcad', 'limitFrameRate', 'noMouseRotate', 'quality', 'scaling'] obj.filterUserWebState = function (state) { if (typeof state == 'string') { try { state = JSON.parse(state); } catch (ex) { return null; } } @@ -4223,9 +4519,17 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { } // Return the correct render page given mobile, minify and override path. - function getRenderPage(pagename, req) { + function getRenderPage(pagename, req, domain) { var mobile = isMobileBrowser(req), minify = obj.args.minify && !req.query.nominify, p; if (mobile) { + if ((domain != null) && (domain.webviewspath != null)) { // If the domain has a web views path, use that first + if (minify) { + p = obj.path.join(domain.webviewspath, pagename + '-mobile-min'); + if (obj.fs.existsSync(p + '.handlebars')) { return p; } // Mobile + Minify + Override document + } + p = obj.path.join(domain.webviewspath, pagename + '-mobile'); + if (obj.fs.existsSync(p + '.handlebars')) { return p; } // Mobile + Override document + } if (obj.parent.webViewsOverridePath != null) { if (minify) { p = obj.path.join(obj.parent.webViewsOverridePath, pagename + '-mobile-min'); @@ -4241,6 +4545,14 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { p = obj.path.join(obj.parent.webViewsPath, pagename + '-mobile'); if (obj.fs.existsSync(p + '.handlebars')) { return p; } // Mobile document } + if ((domain != null) && (domain.webviewspath != null)) { // If the domain has a web views path, use that first + if (minify) { + p = obj.path.join(domain.webviewspath, pagename + '-min'); + if (obj.fs.existsSync(p + '.handlebars')) { return p; } // Minify + Override document + } + p = obj.path.join(domain.webviewspath, pagename); + if (obj.fs.existsSync(p + '.handlebars')) { return p; } // Override document + } if (obj.parent.webViewsOverridePath != null) { if (minify) { p = obj.path.join(obj.parent.webViewsOverridePath, pagename + '-min'); @@ -4265,7 +4577,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if ((domain.titlepicture == null) && (domain.titlehtml == null)) { if (domain.title == null) { xargs.title1 = 'MeshCentral'; - xargs.title2 = '2.0'; + xargs.title2 = ''; } else { xargs.title1 = domain.title; xargs.title2 = domain.title2 ? domain.title2 : ''; @@ -4290,13 +4602,13 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Check that we are in the same domain and the user has rights over this node. if ((splitsessionid.length == 4) && (splitsessionid[0] == 'user') && (splitsessionid[1] == domainid)) { // Check if this user has rights to get this message - if (obj.GetMeshRights(splitsessionid[0] + '/' + splitsessionid[1] + '/' + splitsessionid[2], meshid) == 0) return; // TODO: Check if this is ok + if (obj.GetNodeRights(splitsessionid[0] + '/' + splitsessionid[1] + '/' + splitsessionid[2], meshid, nodeid) == 0) return; // TODO: Check if this is ok // See if the session is connected. If so, go ahead and send this message to the target node var ws = obj.wssessions2[command.sessionid]; if (ws != null) { - command.nodeid = nodeid; // Set the nodeid, required for responses. - delete command.sessionid; // Remove the sessionid, since we are sending to that sessionid, so it's implyed. + command.nodeid = nodeid; // Set the nodeid, required for responses. + delete command.sessionid; // Remove the sessionid, since we are sending to that sessionid, so it's implyed. try { ws.send(JSON.stringify(command)); } catch (ex) { } } else if (parent.multiServer != null) { // See if we can send this to a peer server @@ -4313,7 +4625,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Check that we are in the same domain and the user has rights over this node. if ((splituserid[0] == 'user') && (splituserid[1] == domainid)) { // Check if this user has rights to get this message - if (obj.GetMeshRights(command.userid, meshid) == 0) return; // TODO: Check if this is ok + if (obj.GetNodeRights(command.userid, meshid, nodeid) == 0) return; // TODO: Check if this is ok // See if the session is connected var sessions = obj.wssessions[command.userid]; @@ -4321,7 +4633,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Go ahead and send this message to the target node if (sessions != null) { command.nodeid = nodeid; // Set the nodeid, required for responses. - delete command.userid; // Remove the userid, since we are sending to that userid, so it's implyed. + delete command.userid; // Remove the userid, since we are sending to that userid, so it's implyed. for (i in sessions) { sessions[i].send(JSON.stringify(command)); } } @@ -4336,7 +4648,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Find all connected user sessions with access to this device for (var userid in obj.wssessions) { var xsessions = obj.wssessions[userid]; - if (obj.GetMeshRights(userid, meshid) != 0) { + if (obj.GetNodeRights(userid, meshid, nodeid) != 0) { // Send the message to all sessions for this user on this server for (i in xsessions) { try { xsessions[i].send(cmdstr); } catch (e) { } } } @@ -4352,28 +4664,36 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { } } + // Returns a list of acceptable languages in order + obj.getLanguageCodes = function(req) { + // If a user set a localization, use that + if ((req.query.lang == null) && (req.session != null) && (req.session.userid)) { + var user = obj.users[req.session.userid]; + if ((user != null) && (user.lang != null)) { req.query.lang = user.lang; } + }; + + // Get a list of acceptable languages in order + var acceptLanguages = []; + if (req.query.lang != null) { + acceptLanguages.push(req.query.lang.toLowerCase()); + } else { + if (req.headers['accept-language'] != null) { + var acceptLanguageSplit = req.headers['accept-language'].split(';'); + for (var i in acceptLanguageSplit) { + var acceptLanguageSplitEx = acceptLanguageSplit[i].split(','); + for (var j in acceptLanguageSplitEx) { if (acceptLanguageSplitEx[j].startsWith('q=') == false) { acceptLanguages.push(acceptLanguageSplitEx[j].toLowerCase()); } } + } + } + } + + return acceptLanguages; + } + // Render a page using the proper language function render(req, res, filename, args) { if (obj.renderPages != null) { - // If a user set a localization, use that - if ((req.query.lang == null) && (req.session != null) && (req.session.userid)) { - var user = obj.users[req.session.userid]; - if ((user != null) && (user.lang != null)) { req.query.lang = user.lang; } - }; - - // Get a list of acceptable languages in order - var acceptLanguages = []; - if (req.query.lang != null) { - acceptLanguages.push(req.query.lang.toLowerCase()); - } else { - if (req.headers['accept-language'] != null) { - var acceptLanguageSplit = req.headers['accept-language'].split(';'); - for (var i in acceptLanguageSplit) { - var acceptLanguageSplitEx = acceptLanguageSplit[i].split(','); - for (var j in acceptLanguageSplitEx) { if (acceptLanguageSplitEx[j].startsWith('q=') == false) { acceptLanguages.push(acceptLanguageSplitEx[j].toLowerCase()); } } - } - } - } + // Get the list of acceptable languages in order + var acceptLanguages = obj.getLanguageCodes(req); // Take a look at the options we have for this file var fileOptions = obj.renderPages[obj.path.basename(filename)]; @@ -4439,6 +4759,45 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { } } + // Get the list of pages with different languages that can be rendered + function getEmailLanguageList() { + // Fetch default rendeing pages + var translateFolder = null; + if (obj.fs.existsSync('emails/translations')) { translateFolder = 'emails/translations'; } + if (obj.fs.existsSync(obj.path.join(__dirname, 'emails', 'translations'))) { translateFolder = obj.path.join(__dirname, 'emails', 'translations'); } + + if (translateFolder != null) { + obj.emailLanguages = ['en']; + var files = obj.fs.readdirSync(translateFolder); + for (var i in files) { + var name = files[i]; + if (name.endsWith('.html')) { + name = name.substring(0, name.length - 5); + var xname = name.split('_'); + if (xname.length == 2) { + if (obj.emailLanguages.indexOf(xname[1]) == -1) { obj.emailLanguages.push(xname[1]); } + } + } + } + + // See if there are any custom rending pages that will override the default ones + if ((obj.parent.webEmailsOverridePath != null) && (obj.fs.existsSync(obj.path.join(obj.parent.webEmailsOverridePath, 'translations')))) { + translateFolder = obj.path.join(obj.parent.webEmailsOverridePath, 'translations'); + var files = obj.fs.readdirSync(translateFolder); + for (var i in files) { + var name = files[i]; + if (name.endsWith('.html')) { + name = name.substring(0, name.length - 5); + var xname = name.split('_'); + if (xname.length == 2) { + if (obj.emailLanguages.indexOf(xname[1]) == -1) { obj.emailLanguages.push(xname[1]); } + } + } + } + } + } + } + // Return true if a mobile browser is detected. // This code comes from "http://detectmobilebrowsers.com/" and was modified, This is free and unencumbered software released into the public domain. For more information, please refer to the http://unlicense.org/ function isMobileBrowser(req) { @@ -4457,6 +4816,9 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { function getRandomPassword() { return Buffer.from(obj.crypto.randomBytes(9), 'binary').toString('base64').split('/').join('@'); } function getRandomLowerCase(len) { var r = '', random = obj.crypto.randomBytes(len); for (var i = 0; i < len; i++) { r += String.fromCharCode(97 + (random[i] % 26)); } return r; } + // Generate a 8 digit integer with even random probability for each value. + function getRandomEightDigitInteger() { var bigInt; do { bigInt = parent.crypto.randomBytes(4).readUInt32BE(0); } while (bigInt >= 4200000000); return bigInt % 100000000; } + // Clean a IPv6 address that encodes a IPv4 address function cleanRemoteAddr(addr) { if (typeof addr != 'string') { return null; } if (addr.indexOf('::ffff:') == 0) { return addr.substring(7); } else { return addr; } } @@ -4489,11 +4851,14 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { obj.badLoginTable = {}; obj.badLoginTableLastClean = 0; if (parent.config.settings == null) { parent.config.settings = {}; } - if (parent.config.settings.maxinvalidlogin == null) { parent.config.settings.maxinvalidlogin = { time: 10, count: 10 }; } - if (typeof parent.config.settings.maxinvalidlogin.time != 'number') { parent.config.settings.maxinvalidlogin.time = 10; } - if (typeof parent.config.settings.maxinvalidlogin.count != 'number') { parent.config.settings.maxinvalidlogin.count = 10; } - if ((typeof parent.config.settings.maxinvalidlogin.coolofftime != 'number') || (parent.config.settings.maxinvalidlogin.coolofftime < 1)) { parent.config.settings.maxinvalidlogin.coolofftime = null; } + if (parent.config.settings.maxinvalidlogin !== false) { + if (typeof parent.config.settings.maxinvalidlogin != 'object') { parent.config.settings.maxinvalidlogin = { time: 10, count: 10 }; } + if (typeof parent.config.settings.maxinvalidlogin.time != 'number') { parent.config.settings.maxinvalidlogin.time = 10; } + if (typeof parent.config.settings.maxinvalidlogin.count != 'number') { parent.config.settings.maxinvalidlogin.count = 10; } + if ((typeof parent.config.settings.maxinvalidlogin.coolofftime != 'number') || (parent.config.settings.maxinvalidlogin.coolofftime < 1)) { parent.config.settings.maxinvalidlogin.coolofftime = null; } + } obj.setbadLogin = function (ip) { // Set an IP address that just did a bad login request + if (parent.config.settings.maxinvalidlogin === false) return; if (typeof ip == 'object') { ip = cleanRemoteAddr(ip.ip); } var splitip = ip.split('.'); if (splitip.length == 4) { ip = (splitip[0] + '.' + splitip[1] + '.' + splitip[2] + '.*'); } @@ -4505,6 +4870,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { } } obj.checkAllowLogin = function (ip) { // Check if an IP address is allowed to login + if (parent.config.settings.maxinvalidlogin === false) return true; if (typeof ip == 'object') { ip = cleanRemoteAddr(ip.ip); } var splitip = ip.split('.'); if (splitip.length == 4) { ip = (splitip[0] + '.' + splitip[1] + '.' + splitip[2] + '.*'); } // If this is IPv4, keep only the 3 first @@ -4517,6 +4883,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { return (ipTable.length < parent.config.settings.maxinvalidlogin.count); // No more than x bad logins in x minutes } obj.cleanBadLoginTable = function () { // Clean up the IP address login blockage table, we do this occasionaly. + if (parent.config.settings.maxinvalidlogin === false) return; var cutoffTime = Date.now() - (parent.config.settings.maxinvalidlogin.time * 60000); // Time in minutes for (var ip in obj.badLoginTable) { var ipTable = obj.badLoginTable[ip];