225 lines
6.7 KiB
PHP
225 lines
6.7 KiB
PHP
<?php
|
|
/**
|
|
* Virtual machine PNG screenshot generation
|
|
*
|
|
* @author Ian Moore (imoore76 at yahoo dot com)
|
|
* @copyright Copyright (C) 2010-2015 Ian Moore (imoore76 at yahoo dot com)
|
|
* @version $Id: screen.php 591 2015-04-11 22:40:47Z imoore76 $
|
|
* @package phpVirtualBox
|
|
*
|
|
*/
|
|
|
|
# Turn off PHP notices
|
|
error_reporting(E_ALL & ~E_NOTICE & ~E_STRICT & ~E_WARNING);
|
|
|
|
require_once(dirname(__FILE__).'/lib/config.php');
|
|
require_once(dirname(__FILE__).'/lib/utils.php');
|
|
require_once(dirname(__FILE__).'/lib/vboxconnector.php');
|
|
|
|
|
|
// Allow caching of some screenshot data
|
|
@Header('ETag: "' . $_REQUEST['vm'].'_'.$_REQUEST['randid'].'"');
|
|
session_cache_limiter('private_no_expire');
|
|
|
|
// Check for valid session
|
|
global $_SESSION;
|
|
session_init();
|
|
if(!@$_SESSION['valid']) {
|
|
return;
|
|
}
|
|
|
|
// Clean request
|
|
$_REQUEST = array_merge(@$_GET,@$_POST);
|
|
|
|
$settings = new phpVBoxConfigClass();
|
|
$vbox = new vboxconnector();
|
|
$vbox->connect();
|
|
|
|
// Set width. Else assume we want real time updates if VM is running below
|
|
if($_REQUEST['width']) {
|
|
$force_width = $_REQUEST['width'];
|
|
}
|
|
|
|
try {
|
|
|
|
// Is VM Specified
|
|
if(!$_REQUEST['vm']) {
|
|
echo("Please specify a VM to take a screen shot of. E.g. http://webserver/phpvirtualbox/screen.php?vm=VMName");
|
|
exit;
|
|
}
|
|
|
|
$machine = $vbox->vbox->findMachine($_REQUEST['vm']);
|
|
|
|
// Is snapshot specified?
|
|
if($_REQUEST['snapshot']) {
|
|
|
|
$snapshot = $machine->findSnapshot($_REQUEST['snapshot']);
|
|
$machine->releaseRemote();
|
|
$machine = &$snapshot->machine;
|
|
|
|
} else {
|
|
|
|
// Get machine state
|
|
switch($machine->state->__toString()) {
|
|
case 'Running':
|
|
case 'Saved':
|
|
case 'Restoring':
|
|
break;
|
|
default:
|
|
$machine->releaseRemote();
|
|
throw new Exception('The specified virtual machine is not in a Running state.');
|
|
}
|
|
|
|
}
|
|
|
|
// Date last modified
|
|
$dlm = floor($machine->lastStateChange/1000);
|
|
|
|
// Set last modified header
|
|
header("Last-Modified: " . gmdate("D, d M Y H:i:s", $dlm) . " GMT");
|
|
|
|
$_REQUEST['vm'] = $machine->id;
|
|
|
|
|
|
|
|
// Take active screenshot if machine is running
|
|
if(!$_REQUEST['snapshot'] && $machine->state->__toString() == 'Running') {
|
|
|
|
// Let the browser cache images for 3 seconds
|
|
$ctime = 0;
|
|
if(strpos($_SERVER['HTTP_IF_NONE_MATCH'],'_')) {
|
|
$ctime = preg_replace("/.*_/",str_replace('"','',$_SERVER['HTTP_IF_NONE_MATCH']));
|
|
} else if(strpos($_ENV['HTTP_IF_NONE_MATCH'],'_')) {
|
|
$ctime = preg_replace("/.*_/",str_replace('"','',$_ENV['HTTP_IF_NONE_MATCH']));
|
|
} else if(strpos($_SERVER['HTTP_IF_MODIFIED_SINCE'],'GMT')) {
|
|
$ctime = strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']);
|
|
} else if(strpos($_ENV['HTTP_IF_MODIFIED_SINCE'],'GMT')) {
|
|
$ctime = strtotime($_ENV['HTTP_IF_MODIFIED_SINCE']);
|
|
}
|
|
|
|
if($ctime >= (time()-3)) {
|
|
if (strpos(strtolower(php_sapi_name()),'cgi') !== false) {
|
|
Header("Status: 304 Not Modified");
|
|
} else {
|
|
Header("HTTP/1.0 304 Not Modified");
|
|
}
|
|
exit;
|
|
}
|
|
|
|
|
|
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
|
|
|
|
$vbox->session = $vbox->websessionManager->getSessionObject($vbox->vbox->handle);
|
|
$machine->lockMachine($vbox->session->handle,'Shared');
|
|
$machine->releaseRemote();
|
|
|
|
|
|
$res = $vbox->session->console->display->getScreenResolution(0);
|
|
|
|
$screenWidth = array_shift($res);
|
|
$screenHeight = array_shift($res);
|
|
|
|
|
|
// Force screenshot width while maintaining aspect ratio
|
|
if($force_width) {
|
|
|
|
$factor = (float)$force_width / (float)$screenWidth;
|
|
|
|
$screenWidth = $force_width;
|
|
if($factor > 0) {
|
|
$screenHeight = $factor * $screenHeight;
|
|
} else {
|
|
$screenHeight = ($screenWidth * 9.0/16.0);
|
|
}
|
|
|
|
// If no width is set, we were reached from Open in New Window
|
|
} else if(!$_REQUEST['width']) {
|
|
|
|
//Set no caching
|
|
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
|
|
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
|
|
header("Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0");
|
|
|
|
}
|
|
|
|
// If we were unable to get screen dimensions, set it to something
|
|
if(!$screenWidth || !$screenHeight) {
|
|
$screenWidth = 640;
|
|
$screenHeight = 480;
|
|
}
|
|
// array() for compatibility with readSavedScreenshotPNGToArray return value
|
|
try {
|
|
$imageraw = array($vbox->session->console->display->takeScreenShotToArray(0, $screenWidth, $screenHeight, 'PNG'));
|
|
} catch (Exception $e) {
|
|
// For some reason this is required or you get "Could not take a screenshot (VERR_TRY_AGAIN)" in some cases.
|
|
// I think it's a bug in the Linux guest additions, but cannot prove it.
|
|
$vbox->session->console->display->invalidateAndUpdate();
|
|
$imageraw = array($vbox->session->console->display->takeScreenShotToArray(0, $screenWidth, $screenHeight, 'PNG'));
|
|
}
|
|
|
|
$vbox->session->unlockMachine();
|
|
$vbox->session->releaseRemote();
|
|
|
|
} else {
|
|
|
|
// Let the browser cache saved state images
|
|
$ctime = 0;
|
|
if(strpos($_SERVER['HTTP_IF_NONE_MATCH'],'_')) {
|
|
$ctime = preg_replace("/.*_/",str_replace('"','',$_SERVER['HTTP_IF_NONE_MATCH']));
|
|
} else if(strpos($_ENV['HTTP_IF_NONE_MATCH'],'_')) {
|
|
$ctime = preg_replace("/.*_/",str_replace('"','',$_ENV['HTTP_IF_NONE_MATCH']));
|
|
} else if(strpos($_SERVER['HTTP_IF_MODIFIED_SINCE'],'GMT')) {
|
|
$ctime = strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']);
|
|
} else if(strpos($_ENV['HTTP_IF_MODIFIED_SINCE'],'GMT')) {
|
|
$ctime = strtotime($_ENV['HTTP_IF_MODIFIED_SINCE']);
|
|
}
|
|
|
|
if($dlm <= $ctime) {
|
|
if (strpos(strtolower(php_sapi_name()),'cgi') !== false) {
|
|
Header("Status: 304 Not Modified");
|
|
} else {
|
|
Header("HTTP/1.0 304 Not Modified");
|
|
}
|
|
exit;
|
|
}
|
|
|
|
|
|
if($_REQUEST['full']) $imageraw = $machine->readSavedScreenshotPNGToArray(0);
|
|
else $imageraw = $machine->readSavedThumbnailToArray(0, 'PNG');
|
|
|
|
$machine->releaseRemote();
|
|
|
|
}
|
|
$vbox->session = null;
|
|
|
|
header("Content-type: image/png",true);
|
|
|
|
foreach($imageraw as $i) {
|
|
if(is_array($i)) echo(base64_decode($i[0]));
|
|
}
|
|
|
|
|
|
} catch (Exception $ex) {
|
|
|
|
// Ensure we close the VM Session if we hit a error, ensure we don't have a aborted VM
|
|
if($vbox && $vbox->session && $vbox->session->handle) {
|
|
try {
|
|
$vbox->session->unlockMachine();
|
|
unset($vbox->session);
|
|
} catch (Exception $e) {
|
|
}
|
|
}
|
|
|
|
if($_REQUEST['full'] && strpos($ex->faultstring,'VERR_NOT_SUPPORTED') > 0) {
|
|
@header("Content-type: text/html");
|
|
echo("Screen shots are not supported by your VirtualBox installation. To enable screen shots, please install a VirtualBox exteionsion pack that supports VRDE ");
|
|
echo("such as the Oracle VM VirtualBox Extension Pack found in the Downloads section of <a href='http://www.virtualbox.org'>http://www.virtualbox.org</a>.");
|
|
} else if($_REQUEST['full'] || $_REQUEST['debug']) {
|
|
header("Content-type: text/html", true);
|
|
echo("<pre>");
|
|
print_r($ex);
|
|
echo("</pre>");
|
|
}
|
|
}
|
|
|