<?php /* * haiku.php - an online Haiku demo using qemu and vnc. * * Copyright 2007-2011, Francois Revol, revol@free.fr. * Distributed under the terms of the MIT License. */ // parts inspired by the Free Live OS Zoo // http://www.oszoo.org/wiki/index.php/Free_Live_OS_Zoo // include local configuration that possibly overrides defines below. if (file_exists('haiku.conf.php')) include('haiku.conf.php'); // name of the page define("PAGE_TITLE", "Haiku Online Demo"); // relative path to the vnc java applet jar // you must *copy* (apache doesn't seem to like symlinks) it there. // on debian, apt-get install vnc-java will put them in // /usr/share/vnc-java //define("VNCJAVA_PATH", "vnc-java"); //define("VNCJAR", "vncviewer.jar"); //define("VNCCLASS", "vncviewer.class"); // to use the tightvnc applet instead (supports > 8bpp): // on debian, apt-get install tightvnc-java will put them in // /usr/share/tightvnc-java // else you can get it from http://www.tightvnc.com/download-old.php : // wget http://www.tightvnc.com/download/1.3.10/tightvnc-1.3.10_javabin.zip // (you will have to move the VncViewer.jar file around) define("VNCJAVA_PATH", "tightvnc-java"); define("VNCJAR", "VncViewer.jar"); define("VNCCLASS", "VncViewer.class"); // do not show applet controls define("VNC_HIDE_CONTROLS", true); // generate and use (plain text) passwords // NOT IMPLEMENTED //define("VNC_USE_PASS", true); // maximum count of qemu instances. define("MAX_QEMUS", 2); // size of the java applet, must match the default resolution of the image. //define("APPLET_WIDTH", "800"); //define("APPLET_HEIGHT", "600"); define("APPLET_WIDTH", "1024"); define("APPLET_HEIGHT", "768"); // vnc protocol base port. define("VNCPORTBASE", 5900); // base port for audio streams //define("AUDIOPORTBASE", 8080); define("AUDIOPORTBASE", (VNCPORTBASE + MAX_QEMUS)); // if audio is enabled define("AUDIOENABLED", false); // base port for serial output //define("SERIALPORTBASE", 9000); define("SERIALPORTBASE", (VNCPORTBASE + MAX_QEMUS * 2)); // timeout before the demo session is killed, as argument to /bin/sleep define("SESSION_TIMEOUT", "20m"); // path to qemu binary define("QEMU_BASE", "/usr/local"); define("QEMU_BIN", QEMU_BASE . "/bin/qemu"); define("QEMU_KEYMAPS", QEMU_BASE . "/share/qemu/keymaps"); // default arguments: no network, emulate tablet, readonly image file. define("QEMU_ARGS", "" ."-daemonize " /* detach from stdin */ ."-localtime " /* not UTC */ ."-name '" . addslashes(PAGE_TITLE) . "' " ."-monitor null " /* disable the monitor */ ."-serial none " ."-parallel none " ."-net none " ."-usbdevice wacom-tablet " //."-vga vmware " ."-snapshot "); // absolute path to the image. define("QEMU_IMAGE_PATH", "/home/revol/haiku.image"); // BAD: let's one download the image //define("QEMU_IMAGE_PATH", dirname($_SERVER['SCRIPT_FILENAME']) . "/haiku.image"); // max number of cpus for the VM, no more than 8 define("QEMU_MAX_CPUS", 1); // qemu 0.8.2 needs "", qemu 0.9.1 needs ":" define("QEMU_VNC_PREFIX", ":"); // name of session and pid files in /tmp define("QEMU_SESSFILE_TMPL", "qemu-haiku-session-"); define("QEMU_PIDFILE_TMPL", "qemu-haiku-pid-"); define("QEMU_LOGFILE_TMPL", "qemu-haiku-log-"); // name of session variable holding the qemu slot; not yet used correctly define("QEMU_IDX_VAR", "QEMU_HAIKU_SESSION_VAR"); // uncomment if you want to pass your Sonix webcam device through // migth need to update VID:PID // doesnt really work yet //define("QEMU_USB_PASSTHROUGH", "-usbdevice host:0c45:6005"); define("BGCOLOR", "#336698"); $vnckeymap = "en-us"; $cpucount = 1; // statics //$count = $_SESSION['compteur']; //$count = $GLOBALS['compteur']; $closing = 0; $do_kill = 0; $do_run = 0; function out($str) { echo "<div class=\"haiku_online_out\">$str</div>\n"; ob_flush(); flush(); } function dbg($str) { echo "<div class=\"haiku_online_debug\">$str</div>\n"; ob_flush(); flush(); } function err($str) { echo "<div class=\"haiku_online_error\">$str</div>\n"; ob_flush(); flush(); } function make_qemu_sessionfile_name($idx) { return "/tmp/" . QEMU_SESSFILE_TMPL . $idx; } function make_qemu_pidfile_name($idx) { return "/tmp/" . QEMU_PIDFILE_TMPL . $idx; } function make_qemu_logfile_name($idx) { return "/tmp/" . QEMU_LOGFILE_TMPL . $idx; } function find_qemu_slot() { for ($idx = 0; $idx < MAX_QEMUS; $idx++) { $pidfile = make_qemu_pidfile_name($idx); $sessfile = make_qemu_sessionfile_name($idx); dbg("checking \"$pidfile\", \"$sessfile\"..."); if (!file_exists($pidfile) && !file_exists($sessfile)) { file_put_contents($sessfile, session_id()); $sid = file_get_contents($sessfile); if ($sid != session_id()) continue; $_SESSION[QEMU_IDX_VAR] = $idx; return $idx; } } return -1; } function total_qemu_slots() { return MAX_QEMUS; } function available_qemu_slots() { $count = 0; for ($idx = 0; $idx < MAX_QEMUS; $idx++) { $pidfile = make_qemu_pidfile_name($idx); $sessfile = make_qemu_sessionfile_name($idx); //dbg("checking \"$pidfile\", \"$sessfile\"..."); if (!file_exists($pidfile) && !file_exists($sessfile)) $count++; } return $count; } function qemu_slot() { return $_SESSION[QEMU_IDX_VAR]; } function audio_port() { return AUDIOPORTBASE + qemu_slot(); } function vnc_display() { return qemu_slot(); } function vnc_addr() { return $_SERVER['HTTP_HOST']; } function vnc_port() { return VNCPORTBASE + vnc_display(); } function vnc_addr_display() { return vnc_addr() . ":" . vnc_display(); } function vnc_url() { return "vnc://" . vnc_addr_display(); } function is_my_session_valid() { if (!isset($_SESSION[QEMU_IDX_VAR])) return 0; $idx = $_SESSION[QEMU_IDX_VAR]; $sessfile = make_qemu_sessionfile_name($idx); if (!file_exists($sessfile)) return 0; $qemusession=file_get_contents($sessfile); // has expired if ($qemusession != session_id()) { return 0; } return 1; } function list_keymaps() { $bads = array('.', '..', 'common', 'modifiers'); $keymaps = scandir(QEMU_KEYMAPS); foreach ($keymaps as $key => $map) { if (in_array($map, $bads)) unset($keymaps[$key]); } return $keymaps; } function in_keymaps($keymap) { $keymaps = list_keymaps(); if ($keymap == "") return false; if (in_array($keymap, $keymaps)) return true; return false; } function probe_keymap() { global $vnckeymap; if (is_string($_GET['keymap']) && in_keymaps($_GET['keymap'])) { $vnckeymap = $_GET['keymap']; dbg("Overriden keymap '" . $vnckeymap . "' in arguments."); return; } // if the browser advertised a prefered lang... if (!isset($_SERVER["HTTP_ACCEPT_LANGUAGE"])) return; $langs = $_SERVER["HTTP_ACCEPT_LANGUAGE"]; $langs = ereg_replace(";q=[^,]*", "", $langs); $langs = str_replace(" ", "", $langs); $langs = split(",", $langs); //print_r($langs); //print_r($keymaps); foreach($langs as $lang) { if (!in_keymaps($lang)) $lang = ereg_replace("-.*", "", $lang); if (in_keymaps($lang)) { $vnckeymap = $lang; dbg("Detected keymap '" . $vnckeymap . "' from browser headers."); return; } } } function probe_options_form() { global $cpucount; $cpucount = 1; if (isset($_GET['cpucount'])) $cpucount = (int)$_GET['cpucount']; $cpucount = max(min($cpucount, QEMU_MAX_CPUS), 1); //dbg("cpucount $cpucount"); } function output_options_form() { global $vnckeymap; $idx = qemu_slot(); echo "<form method=\"get\" action=\"" . $_SERVER['PHP_SELF'] . "\">"; echo "<table border=\"0\" class=\"haiku_online_form\">\n"; $keymaps = list_keymaps(); echo "<tr>\n<td align=\"right\">\n"; echo "Select your keymap:"; echo "</td>\n<td>\n"; echo "<select name=\"keymap\">"; foreach ($keymaps as $keymap) { echo "<option value=\"$keymap\" "; if ($keymap == $vnckeymap) echo "selected=\"selected\" "; echo ">$keymap</option>"; //echo "<option name=\"keymap\" "; //echo "value=\"$keymap\">" . locale_get_display_name($keymap); //echo "</option>"; } echo "</select>"; echo "</td>\n</tr>\n"; $modes = array("1024x768"/*, "800x600"*/); echo "<tr "; if (count($modes) < 2) echo "class=\"haiku_online_disabled\""; echo ">\n"; echo "<td align=\"right\">\n"; echo "Select display size:"; echo "</td>\n<td>\n"; echo "<select name=\"videomode\" "; if (count($modes) < 2) echo "disabled=\"disabled\""; echo ">"; foreach ($modes as $mode) { echo "<option value=\"$mode\" "; if ($mode == $videomode) echo "selected=\"selected\" "; echo ">$mode</option>"; } echo "</select>"; echo "</td>\n</tr>\n"; echo "<tr "; if (QEMU_MAX_CPUS < 2) echo "class=\"haiku_online_disabled\""; echo ">\n"; echo "<td align=\"right\">\n"; echo "Select cpu count:"; echo "</td>\n<td>\n"; echo "<select name=\"cpucount\" "; if (QEMU_MAX_CPUS < 2) echo "disabled=\"disabled\""; echo ">"; for ($ncpu = 1; $ncpu <= QEMU_MAX_CPUS; $ncpu++) { echo "<option value=\"$ncpu\" "; if ($ncpu == 1) echo "selected=\"selected\" "; echo ">$ncpu</option>"; } echo "</select>"; echo "</td>\n</tr>\n"; echo "<tr "; if (!AUDIOENABLED) echo "class=\"haiku_online_disabled\""; echo ">\n"; echo "<td align=\"right\">\n"; echo "Check to enable sound:"; echo "</td>\n<td>\n"; echo "<input type=\"checkbox\" name=\"sound\" id=\"sound_cb\" "; echo "value=\"1\" "; if (AUDIOENABLED) { //echo "checked=\"checked\" /"; } else echo "disabled=\"disabled\" /"; echo "><label for=\"sound_cb\">Sound</label>"; echo "</td>\n</tr>\n"; $enable_serial = 1; echo "<tr "; if (!$enable_serial) echo "class=\"haiku_online_disabled\""; echo ">\n"; echo "<td align=\"right\">\n"; echo "Check to enable serial output:"; echo "</td>\n<td>\n"; echo "<input type=\"checkbox\" name=\"serial\" id=\"serial_cb\" "; echo "value=\"1\" "/*"disabled "*/; if ($enable_serial) { //echo "checked "; } echo "/><label for=\"serial_cb\">Serial</label>"; echo "</td>\n</tr>\n"; if (defined("QEMU_USB_PASSTHROUGH")) { $enable_webcam = 1; echo "<tr "; if (!$enable_webcam) echo "class=\"haiku_online_disabled\""; echo ">\n"; echo "<td align=\"right\">\n"; echo "Check to enable webcam:"; echo "</td>\n<td>\n"; echo "<input type=\"checkbox\" name=\"webcam\" id=\"webcam_cb\" "; echo "value=\"1\" "/*"disabled "*/; if ($enable_webcam) { //echo "checked "; } echo "/><label for=\"webcam_cb\">Webcam</label>"; echo "</td>\n</tr>\n"; } /* echo "<tr>\n<td align=\"right\">\n"; //out("Click here to enable sound:"); echo "</td>\n<td>\n"; echo "</td>\n</tr>\n"; echo "<tr>\n<td align=\"right\">\n"; //out("Click here to enable sound:"); echo "</td>\n<td>\n"; echo "</td>\n</tr>\n"; */ echo "<tr>\n<td align=\"right\">\n"; echo "Click here to start the session:"; echo "</td>\n<td>\n"; echo "<input type=\"submit\" name=\"run\" "; echo "value=\"Start!\" />"; echo "</td>\n</tr>\n"; echo "</table>\n"; echo "</form>\n"; out("NOTE: You will need a Java-enabled browser to display the VNC " . "Applet used by this demo. " . "You can however use instead an external <a " . "href=\"http://fr.wikipedia.org/wiki/Virtual_Network_Computing\"" . ">VNC viewer</a>."); ob_flush(); flush(); } function output_kill_form() { echo "<form method=\"get\" action=\"" . $_SERVER['PHP_SELF'] . "\">"; echo "<table border=\"0\" class=\"haiku_online_form\">\n"; echo "<tr>\n"; echo "<td>\n"; echo "Click here to kill the session:"; echo "</td>\n"; echo "<td>\n"; echo "<input type=\"submit\" name=\"kill\" "; echo "value=\"Terminate\"/>"; echo "</td>\n"; echo "</tr>\n"; echo "</table>\n"; echo "</form>\n"; ob_flush(); flush(); } function start_qemu() { global $vnckeymap; global $cpucount; $idx = find_qemu_slot(); if ($idx < 0) { err("No available qemu slot, please try later."); return $idx; } $pidfile = make_qemu_pidfile_name($idx); $logfile = make_qemu_logfile_name($idx); $cmd = ''; if (isset($_GET['sound'])) { $cmd .= "QEMU_AUDIO_DRV=twolame "; //$cmd .= "QEMU_TWOLAME_SAMPLES=" . 4096 . " "; $cmd .= "QEMU_TWOLAME_PORT=" . audio_port() . " "; } $cmd .= QEMU_BIN . " " . QEMU_ARGS; if ($cpucount > 1) $cmd .= " -smp " . $cpucount; if (isset($_GET['sound'])) { $cmd .= " -soundhw hda"; } if (isset($_GET['serial'])) { $cmd .= " -serial telnet::"; $cmd .= (SERIALPORTBASE + qemu_slot()); $cmd .= ",server,nowait,nodelay"; } if (isset($_GET['webcam']) && defined("QEMU_USB_PASSTHROUGH")) { $cmd .= " " . QEMU_USB_PASSTHROUGH; } $cmd .= " -k " . $vnckeymap . " -vnc " . QEMU_VNC_PREFIX . vnc_display() . " -pidfile " . $pidfile . " " . QEMU_IMAGE_PATH; //$cmd .= " || echo $? && echo done )"; // redirect output to log file //$cmd .= " >$logfile 2>&1"; if (file_exists($pidfile)) unlink($pidfile); dbg("Starting <tt>" . $cmd . "</tt>..."); $descriptorspec = array( // 0 => array("pipe", "r"), // stdin // 1 => array("pipe", "w"), // stdout // 2 => array("pipe", "w") // stderr ); //$cmd="/bin/ls"; //passthru($cmd, $ret); //dbg("ret=$ret"); $cmd .= " &"; $process = proc_open($cmd, $descriptorspec, $pipes); sleep(1); proc_close($process); dbg("Started QEMU."); $sessfile = make_qemu_sessionfile_name($idx); $cmd = "(PID=`cat " . $pidfile . "`; " . "sleep " . SESSION_TIMEOUT . "; " . "kill -9 \$PID && " . "rm " . $pidfile . " " . $sessfile . ") &"; $process = proc_open($cmd, $descriptorspec, $wkpipes); sleep(1); proc_close($process); dbg("Started timed kill."); dbg("Ready for a " . SESSION_TIMEOUT . " session."); } function stop_qemu() { $qemuidx = qemu_slot(); $pidfile = make_qemu_pidfile_name($qemuidx); if (file_exists($pidfile)) { $pid = file_get_contents($pidfile); //out("PID:" . $pid); system("/bin/kill -TERM " . $pid); unlink($pidfile); } $sessionfile = make_qemu_sessionfile_name($qemuidx); if (file_exists($sessionfile)) { unlink($sessionfile); } unset($_SESSION[QEMU_IDX_VAR]); out("reloading..."); sleep(1); echo "<script>\n"; echo "<!--\n"; echo "window.location = \"" . $_SERVER['PHP_SELF'] . "\";\n"; echo "//--></script>\n"; out("Click <a href=\"" . $_SERVER['PHP_SELF'] . "\">here</a> to reload the page."); } function output_vnc_info() { out("You can use an external VNC client at " . "<a href=\"vnc://" . vnc_addr_display() . "\">" . "vnc://" . vnc_addr_display() . "</a> " . "or open <a href=\"" . $_SERVER['PHP_SELF'] . "?getfile=vncinfo&slot=" . vnc_display() . "\">this file</a>, " . "or enter <tt>" . vnc_addr_display() . "</tt> in your " . "<a href=\"http://fr.wikipedia.org/wiki/Virtual_Network_" . "Computing\"" . ">VNC viewer</a>."); //echo "<br />\n"; } function output_vnc_info_file() { if (!is_my_session_valid()) die("Bad request"); header("Pragma: public"); header("Expires: 0"); header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); header("Content-type: application/x-vnc"); header('Content-Disposition: attachment; filename="onlinedemo.vnc"'); echo "[connection]\n"; echo "host=" . vnc_addr() . "\n"; echo "port=" . vnc_display() . "\n"; if (defined('VNC_USE_PASS') && VNC_USE_PASS) echo "password=" . $_SESSION['VNC_PASS'] . "\n"; //echo "[options]\n"; // cf. http://www.realvnc.com/pipermail/vnc-list/1999-December/011086.html // cf. http://www.tek-tips.com/viewthread.cfm?qid=1173303&page=1 //echo "\n"; } function output_audio_player_code($external_only=false) { if (!isset($_GET['sound'])) return; $port = audio_port(); $url = "http://" . $_SERVER['HTTP_HOST'] . ":$port/"; $icy = "icy://" . $_SERVER['HTTP_HOST'] . ":$port/"; $use_html5 = true; if (!$external_only) { if ($use_html5) { echo "<audio autoplay=\"autoplay\" autobuffer=\"autobuffer\" controls=\"controls\">"; echo "<source src=\"" . $url . "\" type=\"audio/mpeg\" />"; } if (!$use_html5) { echo "<object type=\"audio/mpeg\" width=\"300\" height=\"50\">"; echo "<param name=\"src\" value=\"" . $url . "\" />"; echo "<param name=\"controller\" value=\"true\" />"; echo "<param name=\"controls\" value=\"controlPanel\" />"; echo "<param name=\"autoplay\" value=\"true\" />"; echo "<param name=\"autostart\" value=\"1\" />"; echo "<embed src=\"$url\" type=\"audio/mpeg\" "; echo "autoplay=\"true\" width=\"300\" height=\"50\" "; echo "controller=\"true\" align=\"right\" hidden=\"false\"></embed>"; echo "</object>"; } if ($use_html5) { echo "</audio>"; } } out("You can use an external audio play at " . "<a href=\"$url\">$url</a> or <a href=\"$icy\">$icy</a>, or use one of the playlists: " . "<a href=\"" . $_SERVER['PHP_SELF'] . "?getfile=audiom3u\">[M3U]</a> " . "<a href=\"" . $_SERVER['PHP_SELF'] . "?getfile=audiopls\">[PLS]</a>"); } function output_audio_player_file_m3u() { if (!is_my_session_valid()) die("Bad request"); header("Pragma: public"); header("Expires: 0"); header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); header("Content-type: audio/x-mpegurl"); //header("Content-type: text/plain"); header('Content-Disposition: attachment; filename="onlinedemo.m3u"'); $port = audio_port(); $url = "http://" . $_SERVER['HTTP_HOST'] . ":$port/"; // cf. http://hanna.pyxidis.org/tech/m3u.html echo "#EXTM3U\n"; echo "#EXTINF:0," . PAGE_TITLE . "\n"; echo "$url\n"; //echo "\n"; } function output_audio_player_file_pls() { if (!is_my_session_valid()) die("Bad request"); header("Pragma: public"); header("Expires: 0"); header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); header("Content-type: audio/x-scpls"); //header("Content-type: text/plain"); header('Content-Disposition: attachment; filename="onlinedemo.pls"'); $port = audio_port(); $url = "http://" . $_SERVER['HTTP_HOST'] . ":$port/"; echo "[playlist]\n"; echo "numberofentries=1\n"; echo "File1=$url\n"; echo "Title1=" . PAGE_TITLE . "\n"; echo "Length1=-1\n"; echo "version=2\n"; //echo "\n"; } function output_applet_code($external_only=false) { $w = APPLET_WIDTH; $h = APPLET_HEIGHT; $port = vnc_port(); $vncjpath = VNCJAVA_PATH; $jar = VNCJAR; $class = VNCCLASS; if ($external_only) return; if (!VNC_HIDE_CONTROLS) $h += 32; echo "<a name=\"haiku_online_applet\"></a>"; echo "<center>"; echo "<applet code=$class codebase=\"$vncjpath/\" "; echo "archive=\"$vncjpath/$jar\" width=$w height=$h "; echo "bgcolor=\"#336698\">\n"; //not needed //echo "<param name=\"HOST\" value=\"$HTTP_HOST\">\n"; echo "<param name=\"PORT\" value=\"$port\">\n"; $pass = ''; if (defined('VNC_USE_PASS') && VNC_USE_PASS) $pass = $_SESSION['VNC_PASS']; echo "<param name=\"PASSWORD\" value=\"" . $pass . "\">\n"; if (VNC_HIDE_CONTROLS) echo "<param name=\"Show controls\" value=\"No\">\n"; //echo "<param name=\"share desktop\" value=\"no\" />"; echo "<param name=\"background-color\" value=\"#336698\">\n"; echo "<param name=\"foreground-color\" value=\"#ffffff\">\n"; //echo "<param name=\"background\" value=\"#336698\">\n"; //echo "<param name=\"foreground\" value=\"#ffffff\">\n"; echo "There should be a java applet here... "; echo "make sure you have a JVM and it's enabled!<br />\n"; echo "If you do not have Java you can use an external VNC "; echo "client as described above.\n"; echo "</applet>\n"; echo "</center>"; ob_flush(); flush(); // scroll to the top of the applet echo "<script>\n"; echo "<!--\n"; echo "scrollToAnchor(\"haiku_online_applet\");"; echo "//--></script>\n"; ob_flush(); flush(); } function output_serial_output_code($external_only=false) { if (!isset($_GET['serial'])) return; $url = "telnet://" . $_SERVER['HTTP_HOST'] . ":"; $url .= (SERIALPORTBASE + qemu_slot()) . "/"; out("You can get serial output at <a href=\"$url\">$url</a>"); return; // not really http... $url = "http://" . $_SERVER['HTTP_HOST'] . ":"; $url .= (SERIALPORTBASE + qemu_slot()) . "/"; echo "<center>"; echo "<iframe src=\"$url/\" type=\"text/plain\" width=\"100%\" "; echo "height=\"200\"></iframe>"; echo "</center>"; } session_start(); // parse args // output redirections... if (isset($_GET['getfile'])) { switch ($_GET['getfile']) { case "vncinfo": output_vnc_info_file(); break; case "audiom3u": output_audio_player_file_m3u(); break; case "audiopls": output_audio_player_file_pls(); break; default: die("Bad request"); } die(); } if (isset($_GET['close'])) $closing = 1; if (isset($_GET['kill'])) $do_kill = 1; if (isset($_GET['run'])) $do_run = 1; if (isset($_GET['frame'])) {} //echo "do_run: " . $do_run . "<br>\n"; //echo "do_kill: " . $do_kill . "<br>\n"; ?> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <meta name="robots" content="noindex, nofollow, noarchive" /> <title><?php echo PAGE_TITLE; ?></title> <link rel="shortcut icon" href="http://www.haiku-os.org/sites/haiku-os.org/themes/shijin/favicon.ico" type="image/x-icon" /> <style type="text/css"> <!-- /* basic style */ body { background-color: <?php echo BGCOLOR; ?>; } a:link { color:orange; } a:visited { color:darkorange; } a:hover { color:pink; } .haiku_online_form { color: white; } .haiku_online_disabled { color: grey; } .haiku_online_out { color: white; } .haiku_online_debug { color: orange; } .haiku_online_error { color: red; font-weight: bold; } .haiku_online_applet { background-color: <?php echo BGCOLOR; ?>; } --> </style> <script type="text/javascript"> function onPageUnload() { //window.open("<?php echo $_SERVER["SCRIPT_NAME"] . "?close"; ?>", "closing", "width=100,height=30,location=no,menubar=no,toolbar=no,scrollbars=no"); } function scrollToAnchor(anchor) { var a = document.anchors[anchor]; if (a) { if (a.scrollIntoView) a.scrollIntoView(true); else if (a.focus) a.focus(); } else window.location.hash = anchor; } </script> </head> <?php if ($closing == 1) echo "<body>"; else echo "<body onunload=\"onPageUnload();\">"; out("<div style=\"text-align:right;\">Available displays: " . available_qemu_slots() . "/" . total_qemu_slots() . "</div>"); probe_keymap(); probe_options_form(); dbg("Checking if session is running..."); $qemuidx = -1; if (is_my_session_valid()) { dbg("Session running."); $qemuidx = qemu_slot(); if ($do_kill) { dbg("closing..."); stop_qemu(); } } else if (!$do_kill && $do_run) { dbg("Need to start qemu."); $qemuidx = start_qemu(); //out("Waiting for vnc server..."); //sleep(5); } if ($qemuidx >= 0 && !$do_kill) { output_kill_form(); output_serial_output_code(); output_audio_player_code(); output_vnc_info(); out("Waiting for vnc server..."); sleep(1); output_applet_code(); } else { output_options_form(); } //phpinfo(); ?> </body> </html>