1<?php
2
3/*
4 * haiku.php - an online Haiku demo using qemu and vnc.
5 *
6 * Copyright 2007-2011, Francois Revol, revol@free.fr.
7 * Distributed under the terms of the MIT License.
8 */
9
10// parts inspired by the Free Live OS Zoo
11// http://www.oszoo.org/wiki/index.php/Free_Live_OS_Zoo
12
13
14// include local configuration that possibly overrides defines below.
15if (file_exists('haiku.conf.php'))
16	include('haiku.conf.php');
17
18
19// name of the page
20define("PAGE_TITLE", "Haiku Online Demo");
21
22
23// relative path to the vnc java applet jar
24// you must *copy* (apache doesn't seem to like symlinks) it there.
25
26// on debian, apt-get install vnc-java will put them in
27// /usr/share/vnc-java
28//define("VNCJAVA_PATH", "vnc-java");
29//define("VNCJAR", "vncviewer.jar");
30//define("VNCCLASS", "vncviewer.class");
31
32// to use the tightvnc applet instead (supports > 8bpp):
33// on debian, apt-get install tightvnc-java will put them in
34// /usr/share/tightvnc-java
35// else you can get it from http://www.tightvnc.com/download-old.php :
36// wget http://www.tightvnc.com/download/1.3.10/tightvnc-1.3.10_javabin.zip
37// (you will have to move the VncViewer.jar file around)
38define("VNCJAVA_PATH", "tightvnc-java");
39define("VNCJAR", "VncViewer.jar");
40define("VNCCLASS", "VncViewer.class");
41
42// do not show applet controls
43define("VNC_HIDE_CONTROLS", true);
44
45// generate and use (plain text) passwords
46// NOT IMPLEMENTED
47//define("VNC_USE_PASS", true);
48
49// maximum count of qemu instances.
50define("MAX_QEMUS", 2);
51
52// size of the java applet, must match the default resolution of the image.
53//define("APPLET_WIDTH", "800");
54//define("APPLET_HEIGHT", "600");
55define("APPLET_WIDTH", "1024");
56define("APPLET_HEIGHT", "768");
57// vnc protocol base port.
58define("VNCPORTBASE", 5900);
59
60// base port for audio streams
61//define("AUDIOPORTBASE", 8080);
62define("AUDIOPORTBASE", (VNCPORTBASE + MAX_QEMUS));
63
64// if audio is enabled
65define("AUDIOENABLED", false);
66
67// base port for serial output
68//define("SERIALPORTBASE", 9000);
69define("SERIALPORTBASE", (VNCPORTBASE + MAX_QEMUS * 2));
70
71// timeout before the demo session is killed, as argument to /bin/sleep
72define("SESSION_TIMEOUT", "20m");
73
74// path to qemu binary
75define("QEMU_BASE", "/usr/local");
76define("QEMU_BIN", QEMU_BASE . "/bin/qemu");
77define("QEMU_KEYMAPS", QEMU_BASE . "/share/qemu/keymaps");
78// default arguments: no network, emulate tablet, readonly image file.
79define("QEMU_ARGS", ""
80	."-daemonize " /* detach from stdin */
81	."-localtime " /* not UTC */
82	."-name '" . addslashes(PAGE_TITLE) . "' "
83	."-monitor null " /* disable the monitor */
84	."-serial none "
85	."-parallel none "
86	."-net none "
87	."-usbdevice wacom-tablet "
88	//."-vga vmware "
89	."-snapshot ");
90
91// absolute path to the image.
92define("QEMU_IMAGE_PATH", "/home/revol/haiku.image");
93// BAD: let's one download the image
94//define("QEMU_IMAGE_PATH", dirname($_SERVER['SCRIPT_FILENAME']) . "/haiku.image");
95
96// max number of cpus for the VM, no more than 8
97define("QEMU_MAX_CPUS", 1);
98
99// qemu 0.8.2 needs "", qemu 0.9.1 needs ":"
100define("QEMU_VNC_PREFIX", ":");
101
102// name of session and pid files in /tmp
103define("QEMU_SESSFILE_TMPL", "qemu-haiku-session-");
104define("QEMU_PIDFILE_TMPL", "qemu-haiku-pid-");
105define("QEMU_LOGFILE_TMPL", "qemu-haiku-log-");
106// name of session variable holding the qemu slot; not yet used correctly
107define("QEMU_IDX_VAR", "QEMU_HAIKU_SESSION_VAR");
108
109
110// uncomment if you want to pass your Sonix webcam device through
111// migth need to update VID:PID
112// doesnt really work yet
113//define("QEMU_USB_PASSTHROUGH", "-usbdevice host:0c45:6005");
114
115
116define("BGCOLOR", "#336698");
117
118
119
120
121$vnckeymap = "en-us";
122
123$cpucount = 1;
124
125// statics
126//$count = $_SESSION['compteur'];
127//$count = $GLOBALS['compteur'];
128$closing = 0;
129$do_kill = 0;
130$do_run = 0;
131
132function out($str)
133{
134	echo "<div class=\"haiku_online_out\">$str</div>\n";
135	ob_flush();
136	flush();
137}
138
139function dbg($str)
140{
141	echo "<div class=\"haiku_online_debug\">$str</div>\n";
142	ob_flush();
143	flush();
144}
145
146function err($str)
147{
148	echo "<div class=\"haiku_online_error\">$str</div>\n";
149	ob_flush();
150	flush();
151}
152
153function make_qemu_sessionfile_name($idx)
154{
155	return "/tmp/" . QEMU_SESSFILE_TMPL . $idx;
156}
157
158function make_qemu_pidfile_name($idx)
159{
160	return "/tmp/" . QEMU_PIDFILE_TMPL . $idx;
161}
162
163function make_qemu_logfile_name($idx)
164{
165	return "/tmp/" . QEMU_LOGFILE_TMPL . $idx;
166}
167
168function find_qemu_slot()
169{
170	for ($idx = 0; $idx < MAX_QEMUS; $idx++) {
171		$pidfile = make_qemu_pidfile_name($idx);
172		$sessfile = make_qemu_sessionfile_name($idx);
173		dbg("checking \"$pidfile\", \"$sessfile\"...");
174		if (!file_exists($pidfile) && !file_exists($sessfile)) {
175			file_put_contents($sessfile, session_id());
176			$sid = file_get_contents($sessfile);
177			if ($sid != session_id())
178				continue;
179			$_SESSION[QEMU_IDX_VAR] = $idx;
180			return $idx;
181		}
182	}
183	return -1;
184}
185
186function total_qemu_slots()
187{
188	return MAX_QEMUS;
189}
190
191
192function available_qemu_slots()
193{
194	$count = 0;
195	for ($idx = 0; $idx < MAX_QEMUS; $idx++) {
196		$pidfile = make_qemu_pidfile_name($idx);
197		$sessfile = make_qemu_sessionfile_name($idx);
198		//dbg("checking \"$pidfile\", \"$sessfile\"...");
199		if (!file_exists($pidfile) && !file_exists($sessfile))
200			$count++;
201	}
202	return $count;
203}
204
205function qemu_slot()
206{
207	return $_SESSION[QEMU_IDX_VAR];
208}
209
210function audio_port()
211{
212	return AUDIOPORTBASE + qemu_slot();
213}
214
215function vnc_display()
216{
217	return qemu_slot();
218}
219
220function vnc_addr()
221{
222	return $_SERVER['HTTP_HOST'];
223}
224
225function vnc_port()
226{
227	return VNCPORTBASE + vnc_display();
228}
229
230function vnc_addr_display()
231{
232	return vnc_addr() . ":" . vnc_display();
233}
234
235function vnc_url()
236{
237	return "vnc://" . vnc_addr_display();
238}
239
240function is_my_session_valid()
241{
242	if (!isset($_SESSION[QEMU_IDX_VAR]))
243		return 0;
244	$idx = $_SESSION[QEMU_IDX_VAR];
245	$sessfile = make_qemu_sessionfile_name($idx);
246	if (!file_exists($sessfile))
247		return 0;
248	$qemusession=file_get_contents($sessfile);
249	// has expired
250	if ($qemusession != session_id()) {
251		return 0;
252	}
253	return 1;
254}
255
256
257function list_keymaps()
258{
259	$bads = array('.', '..', 'common', 'modifiers');
260	$keymaps = scandir(QEMU_KEYMAPS);
261	foreach ($keymaps as $key => $map) {
262		if (in_array($map, $bads))
263			unset($keymaps[$key]);
264	}
265	return $keymaps;
266}
267
268
269function in_keymaps($keymap)
270{
271	$keymaps = list_keymaps();
272
273	if ($keymap == "")
274		return false;
275	if (in_array($keymap, $keymaps))
276		return true;
277
278	return false;
279}
280
281
282function probe_keymap()
283{
284	global $vnckeymap;
285	if (is_string($_GET['keymap']) && in_keymaps($_GET['keymap']))
286	{
287		$vnckeymap = $_GET['keymap'];
288		dbg("Overriden keymap '" . $vnckeymap . "' in arguments.");
289		return;
290	}
291	// if the browser advertised a prefered lang...
292	if (!isset($_SERVER["HTTP_ACCEPT_LANGUAGE"]))
293		return;
294	$langs = $_SERVER["HTTP_ACCEPT_LANGUAGE"];
295	$langs = ereg_replace(";q=[^,]*", "", $langs);
296	$langs = str_replace(" ", "", $langs);
297	$langs = split(",", $langs);
298	//print_r($langs);
299	//print_r($keymaps);
300	foreach($langs as $lang)
301	{
302		if (!in_keymaps($lang))
303			$lang = ereg_replace("-.*", "", $lang);
304		if (in_keymaps($lang))
305		{
306			$vnckeymap = $lang;
307			dbg("Detected keymap '" . $vnckeymap .
308			    "' from browser headers.");
309			return;
310		}
311	}
312}
313
314
315function probe_options_form()
316{
317	global $cpucount;
318	$cpucount = 1;
319	if (isset($_GET['cpucount']))
320		$cpucount = (int)$_GET['cpucount'];
321	$cpucount = max(min($cpucount, QEMU_MAX_CPUS), 1);
322	//dbg("cpucount $cpucount");
323}
324
325
326function output_options_form()
327{
328	global $vnckeymap;
329	$idx = qemu_slot();
330	echo "<form method=\"get\" action=\"" . $_SERVER['PHP_SELF'] . "\">";
331	echo "<table border=\"0\" class=\"haiku_online_form\">\n";
332
333	$keymaps = list_keymaps();
334	echo "<tr>\n<td align=\"right\">\n";
335	echo "Select your keymap:";
336	echo "</td>\n<td>\n";
337	echo "<select name=\"keymap\">";
338	foreach ($keymaps as $keymap) {
339		echo "<option value=\"$keymap\" ";
340		if ($keymap == $vnckeymap)
341			echo "selected=\"selected\" ";
342		echo ">$keymap</option>";
343		//echo "<option name=\"keymap\" ";
344		//echo "value=\"$keymap\">" . locale_get_display_name($keymap);
345		//echo "</option>";
346	}
347	echo "</select>";
348	echo "</td>\n</tr>\n";
349
350
351	$modes = array("1024x768"/*, "800x600"*/);
352	echo "<tr ";
353	if (count($modes) < 2)
354		echo "class=\"haiku_online_disabled\"";
355	echo ">\n";
356	echo "<td align=\"right\">\n";
357	echo "Select display size:";
358	echo "</td>\n<td>\n";
359	echo "<select name=\"videomode\" ";
360	if (count($modes) < 2)
361		echo "disabled=\"disabled\"";
362	echo ">";
363	foreach ($modes as $mode) {
364		echo "<option value=\"$mode\" ";
365		if ($mode == $videomode)
366			echo "selected=\"selected\" ";
367		echo ">$mode</option>";
368	}
369	echo "</select>";
370	echo "</td>\n</tr>\n";
371
372
373	echo "<tr ";
374	if (QEMU_MAX_CPUS < 2)
375		echo "class=\"haiku_online_disabled\"";
376	echo ">\n";
377	echo "<td align=\"right\">\n";
378	echo "Select cpu count:";
379	echo "</td>\n<td>\n";
380	echo "<select name=\"cpucount\" ";
381	if (QEMU_MAX_CPUS < 2)
382		echo "disabled=\"disabled\"";
383	echo ">";
384	for ($ncpu = 1; $ncpu <= QEMU_MAX_CPUS; $ncpu++) {
385		echo "<option value=\"$ncpu\" ";
386		if ($ncpu == 1)
387			echo "selected=\"selected\" ";
388		echo ">$ncpu</option>";
389	}
390	echo "</select>";
391	echo "</td>\n</tr>\n";
392
393
394	echo "<tr ";
395	if (!AUDIOENABLED)
396		echo "class=\"haiku_online_disabled\"";
397	echo ">\n";
398	echo "<td align=\"right\">\n";
399	echo "Check to enable sound:";
400	echo "</td>\n<td>\n";
401	echo "<input type=\"checkbox\" name=\"sound\" id=\"sound_cb\" ";
402	echo "value=\"1\" ";
403	if (AUDIOENABLED) {
404		//echo "checked=\"checked\" /";
405	} else
406		echo "disabled=\"disabled\" /";
407	echo "><label for=\"sound_cb\">Sound</label>";
408	echo "</td>\n</tr>\n";
409
410	$enable_serial = 1;
411	echo "<tr ";
412	if (!$enable_serial)
413		echo "class=\"haiku_online_disabled\"";
414	echo ">\n";
415	echo "<td align=\"right\">\n";
416	echo "Check to enable serial output:";
417	echo "</td>\n<td>\n";
418	echo "<input type=\"checkbox\" name=\"serial\" id=\"serial_cb\" ";
419	echo "value=\"1\" "/*"disabled "*/;
420	if ($enable_serial) {
421		//echo "checked ";
422	}
423	echo "/><label for=\"serial_cb\">Serial</label>";
424	echo "</td>\n</tr>\n";
425
426	if (defined("QEMU_USB_PASSTHROUGH")) {
427
428		$enable_webcam = 1;
429		echo "<tr ";
430		if (!$enable_webcam)
431			echo "class=\"haiku_online_disabled\"";
432		echo ">\n";
433		echo "<td align=\"right\">\n";
434		echo "Check to enable webcam:";
435		echo "</td>\n<td>\n";
436		echo "<input type=\"checkbox\" name=\"webcam\" id=\"webcam_cb\" ";
437		echo "value=\"1\" "/*"disabled "*/;
438		if ($enable_webcam) {
439			//echo "checked ";
440		}
441		echo "/><label for=\"webcam_cb\">Webcam</label>";
442		echo "</td>\n</tr>\n";
443	}
444	/*
445	echo "<tr>\n<td align=\"right\">\n";
446	//out("Click here to enable sound:");
447	echo "</td>\n<td>\n";
448	echo "</td>\n</tr>\n";
449
450	echo "<tr>\n<td align=\"right\">\n";
451	//out("Click here to enable sound:");
452	echo "</td>\n<td>\n";
453	echo "</td>\n</tr>\n";
454	*/
455
456	echo "<tr>\n<td align=\"right\">\n";
457	echo "Click here to start the session:";
458	echo "</td>\n<td>\n";
459	echo "<input type=\"submit\" name=\"run\" ";
460	echo "value=\"Start!\" />";
461	echo "</td>\n</tr>\n";
462
463	echo "</table>\n";
464	echo "</form>\n";
465	out("NOTE: You will need a Java-enabled browser to display the VNC " .
466	    "Applet used by this demo. " .
467	    "You can however use instead an external <a " .
468	    "href=\"http://fr.wikipedia.org/wiki/Virtual_Network_Computing\"" .
469	    ">VNC viewer</a>.");
470	ob_flush();
471	flush();
472}
473
474function output_kill_form()
475{
476	echo "<form method=\"get\" action=\"" . $_SERVER['PHP_SELF'] . "\">";
477	echo "<table border=\"0\" class=\"haiku_online_form\">\n";
478	echo "<tr>\n";
479	echo "<td>\n";
480	echo "Click here to kill the session:";
481	echo "</td>\n";
482	echo "<td>\n";
483	echo "<input type=\"submit\" name=\"kill\" ";
484	echo "value=\"Terminate\"/>";
485	echo "</td>\n";
486	echo "</tr>\n";
487	echo "</table>\n";
488	echo "</form>\n";
489	ob_flush();
490	flush();
491}
492
493
494function start_qemu()
495{
496	global $vnckeymap;
497	global $cpucount;
498	$idx = find_qemu_slot();
499	if ($idx < 0) {
500		err("No available qemu slot, please try later.");
501		return $idx;
502	}
503	$pidfile = make_qemu_pidfile_name($idx);
504	$logfile = make_qemu_logfile_name($idx);
505	$cmd = '';
506	if (isset($_GET['sound'])) {
507		$cmd .= "QEMU_AUDIO_DRV=twolame ";
508		//$cmd .= "QEMU_TWOLAME_SAMPLES=" . 4096 . " ";
509		$cmd .= "QEMU_TWOLAME_PORT=" . audio_port() . " ";
510	}
511	$cmd .= QEMU_BIN . " " . QEMU_ARGS;
512	if ($cpucount > 1)
513		$cmd .= " -smp " . $cpucount;
514	if (isset($_GET['sound'])) {
515		$cmd .= " -soundhw hda";
516	}
517	if (isset($_GET['serial'])) {
518		$cmd .= " -serial telnet::";
519		$cmd .= (SERIALPORTBASE + qemu_slot());
520		$cmd .= ",server,nowait,nodelay";
521	}
522	if (isset($_GET['webcam']) && defined("QEMU_USB_PASSTHROUGH")) {
523		$cmd .= " " . QEMU_USB_PASSTHROUGH;
524	}
525	$cmd .= " -k " . $vnckeymap .
526		" -vnc " . QEMU_VNC_PREFIX . vnc_display() .
527		" -pidfile " . $pidfile .
528		" " . QEMU_IMAGE_PATH;
529	//$cmd .= " || echo $? && echo done )";
530	// redirect output to log file
531	//$cmd .= " >$logfile 2>&1";
532
533	if (file_exists($pidfile))
534		unlink($pidfile);
535	dbg("Starting <tt>" . $cmd . "</tt>...");
536
537	$descriptorspec = array(
538	//       0 => array("pipe", "r"),   // stdin
539	//       1 => array("pipe", "w"),  // stdout
540	//       2 => array("pipe", "w")   // stderr
541	);
542	//$cmd="/bin/ls";
543	//passthru($cmd, $ret);
544	//dbg("ret=$ret");
545	$cmd .= " &";
546	$process = proc_open($cmd, $descriptorspec, $pipes);
547	sleep(1);
548	proc_close($process);
549
550	dbg("Started QEMU.");
551	$sessfile = make_qemu_sessionfile_name($idx);
552	$cmd = "(PID=`cat " . $pidfile . "`; " .
553	  "sleep " . SESSION_TIMEOUT . "; " .
554	  "kill -9 \$PID && " .
555	  "rm " . $pidfile . " " . $sessfile . ") &";
556
557	$process = proc_open($cmd, $descriptorspec, $wkpipes);
558	sleep(1);
559	proc_close($process);
560
561	dbg("Started timed kill.");
562	dbg("Ready for a " . SESSION_TIMEOUT . " session.");
563}
564
565function stop_qemu()
566{
567	$qemuidx = qemu_slot();
568	$pidfile = make_qemu_pidfile_name($qemuidx);
569	if (file_exists($pidfile)) {
570		$pid = file_get_contents($pidfile);
571		//out("PID:" . $pid);
572		system("/bin/kill -TERM " . $pid);
573		unlink($pidfile);
574	}
575	$sessionfile = make_qemu_sessionfile_name($qemuidx);
576	if (file_exists($sessionfile)) {
577		unlink($sessionfile);
578	}
579	unset($_SESSION[QEMU_IDX_VAR]);
580
581	out("reloading...");
582	sleep(1);
583	echo "<script>\n";
584	echo "<!--\n";
585	echo "window.location = \"" . $_SERVER['PHP_SELF'] . "\";\n";
586	echo "//--></script>\n";
587	out("Click <a href=\"" . $_SERVER['PHP_SELF'] .
588	    "\">here</a> to reload the page.");
589}
590
591function output_vnc_info()
592{
593	out("You can use an external VNC client at " .
594	    "<a href=\"vnc://" . vnc_addr_display() . "\">" .
595	    "vnc://" . vnc_addr_display() . "</a> " .
596	    "or open <a href=\"" . $_SERVER['PHP_SELF'] . "?getfile=vncinfo&slot=" . vnc_display() . "\">this file</a>, " .
597	    "or enter <tt>" . vnc_addr_display() . "</tt> in your " .
598	    "<a href=\"http://fr.wikipedia.org/wiki/Virtual_Network_" .
599	    "Computing\"" .
600	    ">VNC viewer</a>.");
601	//echo "<br />\n";
602}
603
604function output_vnc_info_file()
605{
606	if (!is_my_session_valid())
607		die("Bad request");
608
609	header("Pragma: public");
610	header("Expires: 0");
611	header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
612	header("Content-type: application/x-vnc");
613	header('Content-Disposition: attachment; filename="onlinedemo.vnc"');
614
615	echo "[connection]\n";
616	echo "host=" . vnc_addr() . "\n";
617	echo "port=" . vnc_display() . "\n";
618	if (defined('VNC_USE_PASS') && VNC_USE_PASS)
619		echo "password=" . $_SESSION['VNC_PASS'] . "\n";
620	//echo "[options]\n";
621	// cf. http://www.realvnc.com/pipermail/vnc-list/1999-December/011086.html
622	// cf. http://www.tek-tips.com/viewthread.cfm?qid=1173303&page=1
623	//echo "\n";
624}
625
626function output_audio_player_code($external_only=false)
627{
628	if (!isset($_GET['sound']))
629		return;
630
631	$port = audio_port();
632	$url = "http://" . $_SERVER['HTTP_HOST'] . ":$port/";
633	$icy = "icy://" . $_SERVER['HTTP_HOST'] . ":$port/";
634	$use_html5 = true;
635
636	if (!$external_only) {
637		if ($use_html5) {
638			echo "<audio autoplay=\"autoplay\" autobuffer=\"autobuffer\" controls=\"controls\">";
639			echo "<source src=\"" . $url . "\" type=\"audio/mpeg\" />";
640		}
641		if (!$use_html5) {
642			echo "<object type=\"audio/mpeg\" width=\"300\" height=\"50\">";
643			echo "<param name=\"src\" value=\"" . $url . "\" />";
644			echo "<param name=\"controller\" value=\"true\" />";
645			echo "<param name=\"controls\" value=\"controlPanel\" />";
646			echo "<param name=\"autoplay\" value=\"true\" />";
647			echo "<param name=\"autostart\" value=\"1\" />";
648
649			echo "<embed src=\"$url\" type=\"audio/mpeg\" ";
650			echo "autoplay=\"true\" width=\"300\" height=\"50\" ";
651			echo "controller=\"true\" align=\"right\" hidden=\"false\"></embed>";
652
653			echo "</object>";
654		}
655		if ($use_html5) {
656			echo "</audio>";
657		}
658	}
659	out("You can use an external audio play at " .
660	    "<a href=\"$url\">$url</a> or <a href=\"$icy\">$icy</a>, or use one of the playlists: " .
661	    "<a href=\"" . $_SERVER['PHP_SELF'] . "?getfile=audiom3u\">[M3U]</a> " .
662	    "<a href=\"" . $_SERVER['PHP_SELF'] . "?getfile=audiopls\">[PLS]</a>");
663}
664
665function output_audio_player_file_m3u()
666{
667	if (!is_my_session_valid())
668		die("Bad request");
669
670	header("Pragma: public");
671	header("Expires: 0");
672	header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
673	header("Content-type: audio/x-mpegurl");
674	//header("Content-type: text/plain");
675	header('Content-Disposition: attachment; filename="onlinedemo.m3u"');
676
677	$port = audio_port();
678	$url = "http://" . $_SERVER['HTTP_HOST'] . ":$port/";
679
680	// cf. http://hanna.pyxidis.org/tech/m3u.html
681	echo "#EXTM3U\n";
682	echo "#EXTINF:0," . PAGE_TITLE . "\n";
683	echo "$url\n";
684	//echo "\n";
685}
686
687function output_audio_player_file_pls()
688{
689	if (!is_my_session_valid())
690		die("Bad request");
691
692	header("Pragma: public");
693	header("Expires: 0");
694	header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
695	header("Content-type: audio/x-scpls");
696	//header("Content-type: text/plain");
697	header('Content-Disposition: attachment; filename="onlinedemo.pls"');
698
699	$port = audio_port();
700	$url = "http://" . $_SERVER['HTTP_HOST'] . ":$port/";
701
702	echo "[playlist]\n";
703	echo "numberofentries=1\n";
704	echo "File1=$url\n";
705	echo "Title1=" . PAGE_TITLE . "\n";
706	echo "Length1=-1\n";
707	echo "version=2\n";
708	//echo "\n";
709}
710
711function output_applet_code($external_only=false)
712{
713	$w = APPLET_WIDTH;
714	$h = APPLET_HEIGHT;
715	$port = vnc_port();
716	$vncjpath = VNCJAVA_PATH;
717	$jar = VNCJAR;
718	$class = VNCCLASS;
719	if ($external_only)
720		return;
721	if (!VNC_HIDE_CONTROLS)
722		$h += 32;
723	echo "<a name=\"haiku_online_applet\"></a>";
724	echo "<center>";
725	echo "<applet code=$class codebase=\"$vncjpath/\" ";
726	echo "archive=\"$vncjpath/$jar\" width=$w height=$h ";
727	echo "bgcolor=\"#336698\">\n";
728	//not needed
729	//echo "<param name=\"HOST\" value=\"$HTTP_HOST\">\n";
730	echo "<param name=\"PORT\" value=\"$port\">\n";
731	$pass = '';
732	if (defined('VNC_USE_PASS') && VNC_USE_PASS)
733		$pass = $_SESSION['VNC_PASS'];
734	echo "<param name=\"PASSWORD\" value=\"" . $pass . "\">\n";
735	if (VNC_HIDE_CONTROLS)
736		echo "<param name=\"Show controls\" value=\"No\">\n";
737	//echo "<param name=\"share desktop\" value=\"no\" />";
738	echo "<param name=\"background-color\" value=\"#336698\">\n";
739	echo "<param name=\"foreground-color\" value=\"#ffffff\">\n";
740	//echo "<param name=\"background\" value=\"#336698\">\n";
741	//echo "<param name=\"foreground\" value=\"#ffffff\">\n";
742	echo "There should be a java applet here... ";
743	echo "make sure you have a JVM and it's enabled!<br />\n";
744	echo "If you do not have Java you can use an external VNC ";
745	echo "client as described above.\n";
746
747	echo "</applet>\n";
748	echo "</center>";
749	ob_flush();
750	flush();
751	// scroll to the top of the applet
752	echo "<script>\n";
753	echo "<!--\n";
754	echo "scrollToAnchor(\"haiku_online_applet\");";
755	echo "//--></script>\n";
756	ob_flush();
757	flush();
758}
759
760function output_serial_output_code($external_only=false)
761{
762	if (!isset($_GET['serial']))
763		return;
764
765	$url = "telnet://" . $_SERVER['HTTP_HOST'] . ":";
766	$url .= (SERIALPORTBASE + qemu_slot()) . "/";
767	out("You can get serial output at <a href=\"$url\">$url</a>");
768	return;
769
770	// not really http...
771	$url = "http://" . $_SERVER['HTTP_HOST'] . ":";
772	$url .= (SERIALPORTBASE + qemu_slot()) . "/";
773	echo "<center>";
774	echo "<iframe src=\"$url/\" type=\"text/plain\" width=\"100%\" ";
775	echo "height=\"200\"></iframe>";
776	echo "</center>";
777
778}
779
780
781session_start();
782
783// parse args
784
785// output redirections...
786if (isset($_GET['getfile'])) {
787	switch ($_GET['getfile']) {
788	case "vncinfo":
789		output_vnc_info_file();
790		break;
791	case "audiom3u":
792		output_audio_player_file_m3u();
793		break;
794	case "audiopls":
795		output_audio_player_file_pls();
796		break;
797	default:
798		die("Bad request");
799	}
800	die();
801}
802
803if (isset($_GET['close']))
804	$closing = 1;
805
806if (isset($_GET['kill']))
807	$do_kill = 1;
808
809if (isset($_GET['run']))
810	$do_run = 1;
811
812if (isset($_GET['frame'])) {}
813
814
815//echo "do_run: " . $do_run . "<br>\n";
816//echo "do_kill: " . $do_kill . "<br>\n";
817
818?>
819<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
820<head>
821<meta name="robots" content="noindex, nofollow, noarchive" />
822<title><?php echo PAGE_TITLE; ?></title>
823<link rel="shortcut icon" href="http://www.haiku-os.org/sites/haiku-os.org/themes/shijin/favicon.ico" type="image/x-icon" />
824<style type="text/css">
825<!--
826 /* basic style */
827body { background-color: <?php echo BGCOLOR; ?>; }
828a:link { color:orange; }
829a:visited { color:darkorange; }
830a:hover { color:pink; }
831.haiku_online_form { color: white; }
832.haiku_online_disabled { color: grey; }
833.haiku_online_out { color: white; }
834.haiku_online_debug { color: orange; }
835.haiku_online_error { color: red; font-weight: bold; }
836.haiku_online_applet { background-color: <?php echo BGCOLOR; ?>; }
837-->
838</style>
839<script type="text/javascript">
840function onPageUnload() {
841	//window.open("<?php echo $_SERVER["SCRIPT_NAME"] . "?close"; ?>", "closing", "width=100,height=30,location=no,menubar=no,toolbar=no,scrollbars=no");
842}
843
844function scrollToAnchor(anchor) {
845  var a = document.anchors[anchor];
846  if (a) {
847    if (a.scrollIntoView)
848      a.scrollIntoView(true);
849    else if (a.focus)
850      a.focus();
851  } else
852    window.location.hash = anchor;
853}
854</script>
855</head>
856<?php
857
858
859if ($closing == 1)
860	echo "<body>";
861else
862	echo "<body onunload=\"onPageUnload();\">";
863
864
865out("<div style=\"text-align:right;\">Available displays: " .
866    available_qemu_slots() . "/" . total_qemu_slots() .
867    "</div>");
868
869
870probe_keymap();
871probe_options_form();
872
873dbg("Checking if session is running...");
874
875$qemuidx = -1;
876
877if (is_my_session_valid()) {
878	dbg("Session running.");
879	$qemuidx = qemu_slot();
880	if ($do_kill) {
881		dbg("closing...");
882		stop_qemu();
883	}
884} else if (!$do_kill && $do_run) {
885	dbg("Need to start qemu.");
886
887	$qemuidx = start_qemu();
888	//out("Waiting for vnc server...");
889	//sleep(5);
890}
891
892
893if ($qemuidx >= 0 && !$do_kill) {
894	output_kill_form();
895	output_serial_output_code();
896	output_audio_player_code();
897	output_vnc_info();
898	out("Waiting for vnc server...");
899	sleep(1);
900	output_applet_code();
901} else {
902	output_options_form();
903}
904
905//phpinfo();
906
907?>
908
909</body>
910</html>
911