8bpp): // on debian, apt-get install tightvnc-java will put them in // /usr/share/tightvnc-java 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)); // 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 /dev/null " ."-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, not 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-"); // 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 "
$str
\n"; ob_flush(); flush(); } function dbg($str) { echo "
$str
\n"; ob_flush(); flush(); } function err($str) { echo "
$str
\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 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)) { $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 "
"; echo "\n"; $keymaps = list_keymaps(); echo "\n\n\n\n"; $modes = array("1024x768"/*, "800x600"*/); echo "\n"; echo "\n\n\n"; echo "\n"; echo "\n\n\n"; $enable_sound = 0; echo "\n"; echo "\n\n\n"; $enable_serial = 1; echo "\n"; echo "\n\n\n"; if (defined("QEMU_USB_PASSTHROUGH")) { $enable_webcam = 1; echo "\n"; echo "\n\n\n"; } /* echo "\n\n\n\n"; echo "\n\n\n\n"; */ echo "\n\n\n\n"; echo "
\n"; echo "Select your keymap:"; echo "\n"; echo ""; echo "
\n"; echo "Select display size:"; echo "\n"; echo ""; echo "
\n"; echo "Select cpu count:"; echo "\n"; echo ""; echo "
\n"; echo "Check to enable sound:"; echo "\n"; echo ""; echo "
\n"; echo "Check to enable serial output:"; echo "\n"; echo ""; echo "
\n"; echo "Check to enable webcam:"; echo "\n"; echo ""; echo "
\n"; //out("Click here to enable sound:"); echo "\n"; echo "
\n"; //out("Click here to enable sound:"); echo "\n"; echo "
\n"; echo "Click here to start the session:"; echo "\n"; echo ""; echo "
\n"; echo "
\n"; out("NOTE: You will need a Java-enabled browser to display the VNC " . "Applet needed by this demo."); out("You can however use instead an external VNC viewer."); ob_flush(); flush(); } function output_kill_form() { echo "
"; echo "\n"; echo "\n"; echo "\n"; echo "\n"; echo "\n"; echo "
\n"; echo "Click here to kill the session:"; echo "\n"; echo ""; echo "
\n"; echo "
\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); $cmd = QEMU_BIN . " " . QEMU_ARGS; if ($cpucount > 1) $cmd .= " -smp " . $cpucount; 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; if (file_exists($pidfile)) unlink($pidfile); dbg("Starting " . $cmd . "..."); $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 "\n"; out("Click here to reload the page."); } function output_vnc_info() { out("You can use an external VNC client at " . "" . "vnc://" . vnc_addr_display() . " " . "or open this file, " . "or enter " . vnc_addr_display() . " in your " . "VNC viewer."); //echo "
\n"; } function output_vnc_info_file() { if (!is_my_session_valid()) die("Bad request"); 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 (true) return; $port = audio_port(); $url = "http://" . $_SERVER['HTTP_HOST'] . ":$port/"; $icy = "icy://" . $_SERVER['HTTP_HOST'] . ":$port/"; if (!$external_only) { echo ""; } out("You can use an external audio play at " . "$url or $icy, or use " . "this playlist."); } function output_audio_player_file() { if (!is_my_session_valid()) die("Bad request"); 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/"; //echo "#EXTM3U\n"; //echo "#EXTINF:0," . PAGE_TITLE . "\n"; echo "$url\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; echo ""; echo "
"; echo "\n"; //not needed //echo "\n"; echo "\n"; $pass = ''; if (defined('VNC_USE_PASS') && VNC_USE_PASS) $pass = $_SESSION['VNC_PASS']; echo "\n"; if (defined("VNC_HIDE_CONTROLS") && VNC_HIDE_CONTROLS) echo "\n"; //echo ""; echo "\n"; echo "\n"; //echo "\n"; //echo "\n"; echo "There should be a java applet here... "; echo "make sure you have a JVM and it's enabled!
\n"; echo "If you do not have Java you can use an external VNC "; echo "client as described above.\n"; echo "
\n"; echo "
"; ob_flush(); flush(); // scroll to the top of the applet echo "\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 $url"); return; // not really http... $url = "http://" . $_SERVER['HTTP_HOST'] . ":"; $url .= (SERIALPORTBASE + qemu_slot()) . "/"; echo "
"; echo ""; echo "
"; } session_start(); // parse args // output redirections... if (isset($_GET['getfile'])) { switch ($_GET['getfile']) { case "vncinfo": output_vnc_info_file(); break; case "audiopls": output_audio_player_file(); 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 . "
\n"; //echo "do_kill: " . $do_kill . "
\n"; ?> <?php echo PAGE_TITLE; ?> "; else echo ""; out("
Available displays: " . available_qemu_slots() . "/" . total_qemu_slots() . "
"); 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(); ?>