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.

api.php 9.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. <?php
  2. /**
  3. * Main API interface between JavaScript ajax calls and PHP functions.
  4. * Accepts JSON, POST data or simple GET requests, and returns JSON data.
  5. *
  6. * @author Ian Moore (imoore76 at yahoo dot com)
  7. * @copyright Copyright (C) 2010-2015 Ian Moore (imoore76 at yahoo dot com)
  8. * @version $Id: api.php 596 2015-04-19 11:50:53Z imoore76 $
  9. * @package phpVirtualBox
  10. * @see vboxconnector
  11. * @see vboxAjaxRequest
  12. *
  13. * @global array $GLOBALS['response'] resopnse data sent back via json
  14. * @name $response
  15. */
  16. # Turn off PHP errors
  17. error_reporting(E_ALL & ~E_NOTICE & ~E_STRICT & ~E_WARNING);
  18. //Set no caching
  19. header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
  20. header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
  21. header("Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0");
  22. header("Pragma: no-cache");
  23. require_once(dirname(__FILE__).'/lib/config.php');
  24. require_once(dirname(__FILE__).'/lib/utils.php');
  25. require_once(dirname(__FILE__).'/lib/vboxconnector.php');
  26. // Init session
  27. global $_SESSION;
  28. /*
  29. * Clean request
  30. */
  31. $request = clean_request();
  32. global $response;
  33. $response = array('data'=>array('responseData'=>array()),'errors'=>array(),'persist'=>array(),'messages'=>array());
  34. /*
  35. * Built-in requests
  36. */
  37. $vbox = null; // May be set during request handling
  38. /**
  39. * Main try / catch. Logic dictated by incoming 'fn' request
  40. * parameter.
  41. */
  42. try {
  43. /* Check for password recovery file */
  44. if(file_exists(dirname(dirname(__FILE__)).'/recovery.php')) {
  45. throw new Exception('recovery.php exists in phpVirtualBox\'s folder. This is a security hazard. phpVirtualBox will not run until recovery.php has been renamed to a file name that does not end in .php such as <b>recovery.php-disabled</b>.',vboxconnector::PHPVB_ERRNO_FATAL);
  46. }
  47. /* Check for PHP version */
  48. if (!version_compare(PHP_VERSION, '5.2.0', '>=')) {
  49. throw new Exception('phpVirtualBox requires PHP >= 5.2.0, but this server is running version '. PHP_VERSION .'. Please upgrade PHP.');
  50. }
  51. # Only valid function chars
  52. $request['fn'] = preg_replace('[^a-zA-Z0-9_-]', '', $request['fn']);
  53. /* Check for function called */
  54. switch($request['fn']) {
  55. /*
  56. * No method called
  57. */
  58. case '':
  59. throw new Exception('No method called.');
  60. break;
  61. /*
  62. * Return phpVirtualBox's configuration data
  63. */
  64. case 'getConfig':
  65. $settings = new phpVBoxConfigClass();
  66. $response['data']['responseData'] = get_object_vars($settings);
  67. $response['data']['responseData']['host'] = parse_url($response['data']['responseData']['location']);
  68. $response['data']['responseData']['host'] = $response['data']['responseData']['host']['host'];
  69. $response['data']['responseData']['phpvboxver'] = @constant('PHPVBOX_VER');
  70. // Session
  71. session_init();
  72. // Hide credentials
  73. unset($response['data']['responseData']['username']);
  74. unset($response['data']['responseData']['password']);
  75. foreach($response['data']['responseData']['servers'] as $k => $v)
  76. $response['data']['responseData']['servers'][$k] = array('name'=>$v['name']);
  77. // Vbox version
  78. $vbox = new vboxconnector();
  79. $response['data']['responseData']['version'] = $vbox->getVersion();
  80. $response['data']['responseData']['hostOS'] = $vbox->vbox->host->operatingSystem;
  81. $response['data']['responseData']['DSEP'] = $vbox->getDsep();
  82. $response['data']['responseData']['groupDefinitionKey'] = ($settings->phpVboxGroups ? vboxconnector::phpVboxGroupKey : 'GUI/GroupDefinitions');
  83. $response['data']['success'] = true;
  84. break;
  85. /*
  86. *
  87. * USER FUNCTIONS FOLLOW
  88. *
  89. */
  90. /*
  91. * Pass login to authentication module.
  92. */
  93. case 'login':
  94. // NOTE: Do not break. Fall through to 'getSession
  95. if(!$request['params']['u'] || !$request['params']['p']) {
  96. break;
  97. }
  98. // Session
  99. session_init(true);
  100. $settings = new phpVBoxConfigClass();
  101. // Try / catch here to hide login credentials
  102. try {
  103. $settings->auth->login($request['params']['u'], $request['params']['p']);
  104. } catch(Exception $e) {
  105. throw new Exception($e->getMessage(), $e->getCode());
  106. }
  107. // We're done writing to session
  108. if(function_exists('session_write_close'))
  109. @session_write_close();
  110. /*
  111. * Return $_SESSION data
  112. */
  113. case 'getSession':
  114. $settings = new phpVBoxConfigClass();
  115. if(method_exists($settings->auth,'autoLoginHook'))
  116. {
  117. // Session
  118. session_init(true);
  119. $settings->auth->autoLoginHook();
  120. // We're done writing to session
  121. if(function_exists('session_write_close'))
  122. @session_write_close();
  123. } else {
  124. session_init();
  125. }
  126. $response['data']['responseData'] = $_SESSION;
  127. $response['data']['success'] = true;
  128. break;
  129. /*
  130. * Change phpVirtualBox password. Passed to auth module's
  131. * changePassword method.
  132. */
  133. case 'changePassword':
  134. // Session
  135. session_init(true);
  136. $settings = new phpVBoxConfigClass();
  137. $response['data']['success'] = $settings->auth->changePassword($request['params']['old'],
  138. $request['params']['new']);
  139. // We're done writing to session
  140. if(function_exists('session_write_close'))
  141. @session_write_close();
  142. break;
  143. /*
  144. * Get a list of phpVirtualBox users. Passed to auth module's
  145. * getUsers method.
  146. */
  147. case 'getUsers':
  148. // Session
  149. session_init();
  150. // Must be an admin
  151. if(!$_SESSION['admin']) break;
  152. $settings = new phpVBoxConfigClass();
  153. $response['data']['responseData'] = $settings->auth->listUsers();
  154. $response['date']['success'] = true;
  155. break;
  156. /*
  157. * Remove a phpVirtualBox user. Passed to auth module's
  158. * deleteUser method.
  159. */
  160. case 'delUser':
  161. // Session
  162. session_init();
  163. // Must be an admin
  164. if(!$_SESSION['admin']) break;
  165. $settings = new phpVBoxConfigClass();
  166. $settings->auth->deleteUser($request['params']['u']);
  167. $response['data']['success'] = true;
  168. break;
  169. /*
  170. * Edit a phpVirtualBox user. Passed to auth module's
  171. * updateUser method.
  172. */
  173. case 'editUser':
  174. $skipExistCheck = true;
  175. // Fall to addUser
  176. /*
  177. * Add a user to phpVirtualBox. Passed to auth module's
  178. * updateUser method.
  179. */
  180. case 'addUser':
  181. // Session
  182. session_init();
  183. // Must be an admin
  184. if(!$_SESSION['admin']) break;
  185. $settings = new phpVBoxConfigClass();
  186. $settings->auth->updateUser($request['params'], @$skipExistCheck);
  187. $response['data']['success'] = true;
  188. break;
  189. /*
  190. * Log out of phpVirtualBox. Passed to auth module's
  191. * logout method.
  192. */
  193. case 'logout':
  194. // Session
  195. session_init(true);
  196. $vbox = new vboxconnector();
  197. $vbox->skipSessionCheck = true;
  198. $settings = new phpVBoxConfigClass();
  199. $settings->auth->logout($response);
  200. session_destroy();
  201. $response['data']['success'] = true;
  202. break;
  203. /*
  204. * If the above cases did not match, assume it is a request
  205. * that should be passed to vboxconnector.
  206. */
  207. default:
  208. $vbox = new vboxconnector();
  209. /*
  210. * Every 1 minute we'll check that the account has not
  211. * been deleted since login, and update admin credentials.
  212. */
  213. if($_SESSION['user'] && ((intval($_SESSION['authCheckHeartbeat'])+60) < time())) {
  214. // init session and keep it open
  215. session_init(true);
  216. $vbox->settings->auth->heartbeat($vbox);
  217. // We're done writing to session
  218. if(function_exists('session_write_close'))
  219. @session_write_close();
  220. } else {
  221. // init session but close it
  222. session_init();
  223. }
  224. /*
  225. * Persistent request data
  226. */
  227. if(is_array($request['persist'])) {
  228. $vbox->persistentRequest = $request['persist'];
  229. }
  230. /*
  231. * Call to vboxconnector
  232. */
  233. $vbox->{$request['fn']}($request['params'],array(&$response));
  234. /*
  235. * Send back persistent request in response
  236. */
  237. if(is_array($vbox->persistentRequest) && count($vbox->persistentRequest)) {
  238. $response['data']['persist'] = $vbox->persistentRequest;
  239. }
  240. break;
  241. } // </switch()>
  242. /*
  243. * Catch all exceptions and populate errors in the
  244. * JSON response data.
  245. */
  246. } catch (Exception $e) {
  247. // Just append to $vbox->errors and let it get
  248. // taken care of below
  249. if(!$vbox || !$vbox->errors) {
  250. $vbox->errors = array();
  251. }
  252. $vbox->errors[] = $e;
  253. }
  254. // Add any messages
  255. if($vbox && count($vbox->messages)) {
  256. foreach($vbox->messages as $m)
  257. $response['messages'][] = 'vboxconnector('.$request['fn'] .'): ' . $m;
  258. }
  259. // Add other error info
  260. if($vbox && $vbox->errors) {
  261. foreach($vbox->errors as $e) { /* @var $e Exception */
  262. ob_start();
  263. print_r($e);
  264. $d = ob_get_contents();
  265. ob_end_clean();
  266. # Add connection details to connection errors
  267. if($e->getCode() == vboxconnector::PHPVB_ERRNO_CONNECT && isset($vbox->settings))
  268. $d .= "\n\nLocation:" . $vbox->settings->location;
  269. $response['messages'][] = htmlentities($e->getMessage()).' ' . htmlentities($details);
  270. $response['errors'][] = array(
  271. 'error'=> ($e->getCode() & vboxconnector::PHPVB_ERRNO_HTML ? $e->getMessage() : htmlentities($e->getMessage())),
  272. 'details'=>htmlentities($d),
  273. 'errno'=>$e->getCode(),
  274. // Fatal errors halt all processing
  275. 'fatal'=>($e->getCode() & vboxconnector::PHPVB_ERRNO_FATAL),
  276. // Connection errors display alternate servers options
  277. 'connection'=>($e->getCode() & vboxconnector::PHPVB_ERRNO_CONNECT)
  278. );
  279. }
  280. }
  281. /*
  282. * Return response as JSON encoded data or use PHP's
  283. * print_r to dump data to browser.
  284. */
  285. if(isset($request['printr'])) {
  286. print_r($response);
  287. } else {
  288. header('Content-type: application/json');
  289. echo(json_encode($response));
  290. }