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 "
$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 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 "\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 VNC viewer.");
ob_flush();
flush();
}
function output_kill_form()
{
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);
$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 " . $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("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 "";
}
}
out("You can use an external audio play at " .
"$url or $icy, or use one of the playlists: " .
"[M3U] " .
"[PLS]");
}
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 "";
echo "
";
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 "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 . " \n";
//echo "do_kill: " . $do_kill . " \n";
?>
";
else
echo "";
out("