You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

screen.php 6.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. <?php
  2. /**
  3. * Virtual machine PNG screenshot generation
  4. *
  5. * @author Ian Moore (imoore76 at yahoo dot com)
  6. * @copyright Copyright (C) 2010-2015 Ian Moore (imoore76 at yahoo dot com)
  7. * @version $Id: screen.php 591 2015-04-11 22:40:47Z imoore76 $
  8. * @package phpVirtualBox
  9. *
  10. */
  11. # Turn off PHP notices
  12. error_reporting(E_ALL & ~E_NOTICE & ~E_STRICT & ~E_WARNING);
  13. require_once(dirname(__FILE__).'/lib/config.php');
  14. require_once(dirname(__FILE__).'/lib/utils.php');
  15. require_once(dirname(__FILE__).'/lib/vboxconnector.php');
  16. // Allow caching of some screenshot data
  17. @Header('ETag: "' . $_REQUEST['vm'].'_'.$_REQUEST['randid'].'"');
  18. session_cache_limiter('private_no_expire');
  19. // Check for valid session
  20. global $_SESSION;
  21. session_init();
  22. if(!@$_SESSION['valid']) {
  23. return;
  24. }
  25. // Clean request
  26. $_REQUEST = array_merge(@$_GET,@$_POST);
  27. $settings = new phpVBoxConfigClass();
  28. $vbox = new vboxconnector();
  29. $vbox->connect();
  30. // Set width. Else assume we want real time updates if VM is running below
  31. if($_REQUEST['width']) {
  32. $force_width = $_REQUEST['width'];
  33. }
  34. try {
  35. // Is VM Specified
  36. if(!$_REQUEST['vm']) {
  37. echo("Please specify a VM to take a screen shot of. E.g. http://webserver/phpvirtualbox/screen.php?vm=VMName");
  38. exit;
  39. }
  40. $machine = $vbox->vbox->findMachine($_REQUEST['vm']);
  41. // Is snapshot specified?
  42. if($_REQUEST['snapshot']) {
  43. $snapshot = $machine->findSnapshot($_REQUEST['snapshot']);
  44. $machine->releaseRemote();
  45. $machine = &$snapshot->machine;
  46. } else {
  47. // Get machine state
  48. switch($machine->state->__toString()) {
  49. case 'Running':
  50. case 'Saved':
  51. case 'Restoring':
  52. break;
  53. default:
  54. $machine->releaseRemote();
  55. throw new Exception('The specified virtual machine is not in a Running state.');
  56. }
  57. }
  58. // Date last modified
  59. $dlm = floor($machine->lastStateChange/1000);
  60. // Set last modified header
  61. header("Last-Modified: " . gmdate("D, d M Y H:i:s", $dlm) . " GMT");
  62. $_REQUEST['vm'] = $machine->id;
  63. // Take active screenshot if machine is running
  64. if(!$_REQUEST['snapshot'] && $machine->state->__toString() == 'Running') {
  65. // Let the browser cache images for 3 seconds
  66. $ctime = 0;
  67. if(strpos($_SERVER['HTTP_IF_NONE_MATCH'],'_')) {
  68. $ctime = preg_replace("/.*_/",str_replace('"','',$_SERVER['HTTP_IF_NONE_MATCH']));
  69. } else if(strpos($_ENV['HTTP_IF_NONE_MATCH'],'_')) {
  70. $ctime = preg_replace("/.*_/",str_replace('"','',$_ENV['HTTP_IF_NONE_MATCH']));
  71. } else if(strpos($_SERVER['HTTP_IF_MODIFIED_SINCE'],'GMT')) {
  72. $ctime = strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']);
  73. } else if(strpos($_ENV['HTTP_IF_MODIFIED_SINCE'],'GMT')) {
  74. $ctime = strtotime($_ENV['HTTP_IF_MODIFIED_SINCE']);
  75. }
  76. if($ctime >= (time()-3)) {
  77. if (strpos(strtolower(php_sapi_name()),'cgi') !== false) {
  78. Header("Status: 304 Not Modified");
  79. } else {
  80. Header("HTTP/1.0 304 Not Modified");
  81. }
  82. exit;
  83. }
  84. header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
  85. $vbox->session = $vbox->websessionManager->getSessionObject($vbox->vbox->handle);
  86. $machine->lockMachine($vbox->session->handle,'Shared');
  87. $machine->releaseRemote();
  88. $res = $vbox->session->console->display->getScreenResolution(0);
  89. $screenWidth = array_shift($res);
  90. $screenHeight = array_shift($res);
  91. // Force screenshot width while maintaining aspect ratio
  92. if($force_width) {
  93. $factor = (float)$force_width / (float)$screenWidth;
  94. $screenWidth = $force_width;
  95. if($factor > 0) {
  96. $screenHeight = $factor * $screenHeight;
  97. } else {
  98. $screenHeight = ($screenWidth * 9.0/16.0);
  99. }
  100. // If no width is set, we were reached from Open in New Window
  101. } else if(!$_REQUEST['width']) {
  102. //Set no caching
  103. header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
  104. header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
  105. header("Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0");
  106. }
  107. // If we were unable to get screen dimensions, set it to something
  108. if(!$screenWidth || !$screenHeight) {
  109. $screenWidth = 640;
  110. $screenHeight = 480;
  111. }
  112. // array() for compatibility with readSavedScreenshotPNGToArray return value
  113. try {
  114. $imageraw = array($vbox->session->console->display->takeScreenShotToArray(0, $screenWidth, $screenHeight, 'PNG'));
  115. } catch (Exception $e) {
  116. // For some reason this is required or you get "Could not take a screenshot (VERR_TRY_AGAIN)" in some cases.
  117. // I think it's a bug in the Linux guest additions, but cannot prove it.
  118. $vbox->session->console->display->invalidateAndUpdate();
  119. $imageraw = array($vbox->session->console->display->takeScreenShotToArray(0, $screenWidth, $screenHeight, 'PNG'));
  120. }
  121. $vbox->session->unlockMachine();
  122. $vbox->session->releaseRemote();
  123. } else {
  124. // Let the browser cache saved state images
  125. $ctime = 0;
  126. if(strpos($_SERVER['HTTP_IF_NONE_MATCH'],'_')) {
  127. $ctime = preg_replace("/.*_/",str_replace('"','',$_SERVER['HTTP_IF_NONE_MATCH']));
  128. } else if(strpos($_ENV['HTTP_IF_NONE_MATCH'],'_')) {
  129. $ctime = preg_replace("/.*_/",str_replace('"','',$_ENV['HTTP_IF_NONE_MATCH']));
  130. } else if(strpos($_SERVER['HTTP_IF_MODIFIED_SINCE'],'GMT')) {
  131. $ctime = strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']);
  132. } else if(strpos($_ENV['HTTP_IF_MODIFIED_SINCE'],'GMT')) {
  133. $ctime = strtotime($_ENV['HTTP_IF_MODIFIED_SINCE']);
  134. }
  135. if($dlm <= $ctime) {
  136. if (strpos(strtolower(php_sapi_name()),'cgi') !== false) {
  137. Header("Status: 304 Not Modified");
  138. } else {
  139. Header("HTTP/1.0 304 Not Modified");
  140. }
  141. exit;
  142. }
  143. if($_REQUEST['full']) $imageraw = $machine->readSavedScreenshotPNGToArray(0);
  144. else $imageraw = $machine->readSavedThumbnailToArray(0, 'PNG');
  145. $machine->releaseRemote();
  146. }
  147. $vbox->session = null;
  148. header("Content-type: image/png",true);
  149. foreach($imageraw as $i) {
  150. if(is_array($i)) echo(base64_decode($i[0]));
  151. }
  152. } catch (Exception $ex) {
  153. // Ensure we close the VM Session if we hit a error, ensure we don't have a aborted VM
  154. if($vbox && $vbox->session && $vbox->session->handle) {
  155. try {
  156. $vbox->session->unlockMachine();
  157. unset($vbox->session);
  158. } catch (Exception $e) {
  159. }
  160. }
  161. if($_REQUEST['full'] && strpos($ex->faultstring,'VERR_NOT_SUPPORTED') > 0) {
  162. @header("Content-type: text/html");
  163. echo("Screen shots are not supported by your VirtualBox installation. To enable screen shots, please install a VirtualBox exteionsion pack that supports VRDE ");
  164. 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>.");
  165. } else if($_REQUEST['full'] || $_REQUEST['debug']) {
  166. header("Content-type: text/html", true);
  167. echo("<pre>");
  168. print_r($ex);
  169. echo("</pre>");
  170. }
  171. }