{% extends "console-base.html" %} {% load i18n %} {% load static %} {% block head %} <!-- noVNC example: lightweight example using minimal UI and features This is a self-contained file which doesn't import WebUtil or external CSS. Copyright (C) 2019 The noVNC Authors noVNC is licensed under the MPL 2.0 (see LICENSE.txt) This file is licensed under the 2-Clause BSD license (see LICENSE.txt). Connect parameters are provided in query string: http://example.com/?host=HOST&port=PORT&scale=true --> <title>WebVirtCloud - noVNC - Lite</title> <meta charset="utf-8"> <!-- Always force latest IE rendering engine (even in intranet) & Chrome Frame. Remove this if you use the .htaccess --> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <!-- Stylesheets --> <link rel="stylesheet" href='{% static "js/novnc/app/styles/lite.css" %}'> <!-- Promise polyfill for IE11 --> <script src="{% static 'js/novnc/vendor/promise.js' %}"></script> <!-- ES2015/ES6 modules polyfill --> <script nomodule src="{% static 'js/novnc/vendor/browser-es-module-loader/dist/browser-es-module-loader.js' %}"></script> <!-- actual script modules --> <script type="module" crossorigin="anonymous"> // RFB holds the API to connect and communicate with a VNC server import RFB from '{% static "js/novnc/core/rfb.js" %}'; let rfb; let desktopName; // When this function is called we have // successfully connected to a server function connectedToServer(e) { status("Connected to " + desktopName); } // This function is called when we are disconnected function disconnectedFromServer(e) { if (e.detail.clean) { status("Disconnected"); } else { status("Something went wrong, connection is closed"); } } // When this function is called, the server requires // credentials to authenticate function credentialsAreRequired(e) { const password = prompt("Password Required:"); rfb.sendCredentials({ password: password }); } // When this function is called we have received // a desktop name from the server function updateDesktopName(e) { desktopName = e.detail.name; } // Since most operating systems will catch Ctrl+Alt+Del // before they get a chance to be intercepted by the browser, // we provide a way to emulate this key sequence. function sendCtrlAltDel() { rfb.sendCtrlAltDel(); return false; } function fullscreen() { if (document.fullscreenElement || // alternative standard method document.mozFullScreenElement || // currently working methods document.webkitFullscreenElement || document.msFullscreenElement) { if (document.exitFullscreen) { document.exitFullscreen(); } else if (document.mozCancelFullScreen) { document.mozCancelFullScreen(); } else if (document.webkitExitFullscreen) { document.webkitExitFullscreen(); } else if (document.msExitFullscreen) { document.msExitFullscreen(); } } else { if (document.documentElement.requestFullscreen) { document.documentElement.requestFullscreen(); } else if (document.documentElement.mozRequestFullScreen) { document.documentElement.mozRequestFullScreen(); } else if (document.documentElement.webkitRequestFullscreen) { document.documentElement.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT); } else if (document.body.msRequestFullscreen) { document.body.msRequestFullscreen(); } } return false; } function sendCtrlAltFN(f) { rfb.sendCtrlAltFN(f); return false; } function machineShutdown() { rfb.machineShutdown(); return false; } function machineReboot() { rfb.machineReboot(); return false; } function machineReset() { rfb.machineReset(); return false; } // Show a status text in the top bar function status(text) { document.getElementById('noVNC_status').textContent = text; } // This function extracts the value of one variable from the // query string. If the variable isn't defined in the URL // it returns the default value instead. function readQueryVariable(name, defaultValue) { // A URL with a query parameter can look like this: // https://www.example.com?myqueryparam=myvalue // // Note that we use location.href instead of location.search // because Firefox < 53 has a bug w.r.t location.search const re = new RegExp('.*[?&]' + name + '=([^&#]*)'), match = document.location.href.match(re); if (match) { // We have to decode the URL since want the cleartext value return decodeURIComponent(match[1]); } return defaultValue; } document.getElementById('sendCtrlAltDelButton').onclick = sendCtrlAltDel; document.getElementById('machineShutdownButton').onclick = machineShutdown; document.getElementById('machineRebootButton').onclick = machineReboot; document.getElementById('machineResetButton').onclick = machineReset; document.getElementById('fullscreen_button').onclick = fullscreen; document.getElementById('ctrlaltdel').addEventListener('click', sendCtrlAltDel); document.getElementById('ctrlaltf1').addEventListener('click', function () { sendCtrlAltFN(0); }); document.getElementById('ctrlaltf2').addEventListener('click', function () { sendCtrlAltFN(1); }); document.getElementById('ctrlaltf3').addEventListener('click', function () { sendCtrlAltFN(2); }); document.getElementById('ctrlaltf4').addEventListener('click', function () { sendCtrlAltFN(3); }); document.getElementById('ctrlaltf5').addEventListener('click', function () { sendCtrlAltFN(4); }); document.getElementById('ctrlaltf6').addEventListener('click', function () { sendCtrlAltFN(5); }); document.getElementById('ctrlaltf7').addEventListener('click', function () { sendCtrlAltFN(6); }); document.getElementById('ctrlaltf8').addEventListener('click', function () { sendCtrlAltFN(7); }); document.getElementById('ctrlaltf9').addEventListener('click', function () { sendCtrlAltFN(8); }); document.getElementById('ctrlaltf10').addEventListener('click', function () { sendCtrlAltFN(9); }); document.getElementById('ctrlaltf11').addEventListener('click', function () { sendCtrlAltFN(10); }); document.getElementById('ctrlaltf12').addEventListener('click', function () { sendCtrlAltFN(11); }); // Read parameters specified in the URL query string // By default, use the host and port of server that served this file const host = readQueryVariable('host', '{{ ws_host }}'); let port = readQueryVariable('port', '{{ ws_port }}'); {% if perms.instances.passwordless_console %} const password = '{{ console_passwd }}'; {% else %} const password = readQueryVariable('password'); {% endif %} //const path = readQueryVariable('path', 'websockify'); const path = readQueryVariable('path', '{{ ws_path }}'); // | | | | | | // | | | Connect | | | // v v v v v v status("Connecting"); // Build the websocket URL used to connect let url; if (window.location.protocol === "https:") { url = 'wss'; } else { url = 'ws'; } url += '://' + host; if (port) { url += ':' + port; } url += '/' + path; // Creating a new RFB object will start a new connection rfb = new RFB(document.getElementById('noVNC_container'), url, { credentials: { password: password } }); // Add listeners to important events from the RFB module rfb.addEventListener("connect", connectedToServer); rfb.addEventListener("disconnect", disconnectedFromServer); rfb.addEventListener("credentialsrequired", credentialsAreRequired); rfb.addEventListener("desktopname", updateDesktopName); // Set parameters that can be changed on an active connection rfb.scaleViewport = {{ scale }}; rfb.viewOnly = {{ view_only }}; rfb.resizeSession = {{ resize_session }}; rfb.clipViewport = {{ clip_viewport }}; </script> {% endblock %} {% block content %} <div id="noVNC_status_bar"> <div id="noVNC_left_dummy_elem"></div> <div id="noVNC_status">{% trans 'Loading' %}</div> <div id="noVNC_buttons"> <input type="button" value="Send CtrlAltDel" id="sendCtrlAltDelButton" class="noVNC_shown"> <span id="noVNC_power_buttons" class="noVNC_hidden"> <input type="button" value="Shutdown" id="machineShutdownButton"> <input type="button" value="Reboot" id="machineRebootButton"> <input type="button" value="Reset" id="machineResetButton"> </span> </div> </div> <div id="noVNC_container"> <!-- This is where the remote screen will appear --> </div> {% endblock %}