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.

jqueryFileTree.php 8.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  1. <?php
  2. //
  3. // jQuery File Tree PHP Connector
  4. //
  5. // Version 1.01
  6. //
  7. // Cory S.N. LaViska
  8. // A Beautiful Site (http://abeautifulsite.net/)
  9. // 24 March 2008
  10. //
  11. // History:
  12. //
  13. // 1.01 - updated to work with foreign characters in directory/file names (12 April 2008)
  14. // 1.00 - released (24 March 2008)
  15. //
  16. // Output a list of files for jQuery File Tree
  17. //
  18. // ]--- Modified by Ian Moore for phpVirtualBox.
  19. //
  20. // $Id: jqueryFileTree.php 592 2015-04-12 19:53:44Z imoore76 $
  21. //
  22. //
  23. # Turn off PHP notices
  24. error_reporting(E_ALL & ~E_NOTICE & ~E_STRICT & ~E_WARNING);
  25. global $vbox, $localbrowser, $allowed;
  26. require_once(dirname(__FILE__).'/lib/config.php');
  27. require_once(dirname(__FILE__).'/lib/utils.php');
  28. require_once(dirname(__FILE__).'/lib/vboxconnector.php');
  29. error_reporting(E_ALL & ~E_NOTICE & ~E_STRICT & ~E_WARNING);
  30. session_init();
  31. if(!$_SESSION['valid']) return;
  32. /*
  33. * Get Settings
  34. */
  35. $settings = new phpVBoxConfigClass();
  36. $vbox = new vboxconnector();
  37. $vbox->connect();
  38. /*
  39. * Clean request
  40. */
  41. global $request;
  42. $request = clean_request();
  43. /*
  44. * Determine directory separator
  45. */
  46. $localbrowser = @$settings->browserLocal;
  47. if($localbrowser) {
  48. define('DSEP', DIRECTORY_SEPARATOR);
  49. } else {
  50. define('DSEP',$vbox->getDsep());
  51. }
  52. /*
  53. * Compose allowed file types list
  54. */
  55. $allowed_exts = $settings->browserRestrictFiles;
  56. if(is_array($allowed_exts) && count($allowed_exts) > 0) $allowed_exts = array_combine($allowed_exts,$allowed_exts);
  57. else $allowed_exts = array();
  58. /* Allowed folders list */
  59. $allowed_folders = @$settings->browserRestrictFolders;
  60. if(!is_array($allowed_folders))
  61. $allowed_folders = array();
  62. /*
  63. * Get a list of windows drives
  64. */
  65. function get_windows_drives() {
  66. $checklist = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
  67. $drives = array();
  68. for($i = 0; $i < strlen($d); $i++) {
  69. if(is_dir($checklist[$i].':\\')) {
  70. $drives[] = $checklist[$i].':\\';
  71. }
  72. }
  73. return $drives;
  74. }
  75. /*
  76. * Allowed folders in windows if none are set
  77. */
  78. if(stripos($vbox->vbox->host->operatingSystem,'win') === 0 && !count($allowed_folders)) {
  79. /*
  80. * Assumes web server and vbox host are the same physical machine
  81. */
  82. if($request['fullpath'] && !$settings->forceWindowsAllDriveList && !$settings->noWindowsDriveList && stripos(PHP_OS,'win') === 0) {
  83. $allowed_folders = get_windows_drives();
  84. /*
  85. * Just show all C-Z drive letters if vboxhost is windows and our web server is not...
  86. */
  87. } else if($request['fullpath'] && ($settings->forceWindowsAllDriveList || (!$settings->noWindowsDriveList && stripos(PHP_OS,'win') === false))) {
  88. $allowed_folders = array();
  89. for($i = 67; $i < 91; $i++) {
  90. $allowed_folders[] = chr($i) .':\\';
  91. }
  92. }
  93. $allowed_folders = array_combine($allowed_folders,$allowed_folders);
  94. }
  95. /* Deterine target DIR requested.
  96. * In some cases, "dir" passed is just a file name
  97. */
  98. if(strpos($request['dir'],DSEP)===false) {
  99. $request['dir'] = DSEP;
  100. }
  101. // Eliminate duplicate DSEPs
  102. $request['dir'] = str_replace(DSEP.DSEP,DSEP,$request['dir']);
  103. /*
  104. * Check that folder restriction validates if it exists
  105. */
  106. if($request['dir'] != DSEP && count($allowed_folders)) {
  107. $valid = false;
  108. foreach($allowed_folders as $f) {
  109. if(strpos(strtoupper($request['dir']),strtoupper($f)) === 0) {
  110. $valid = true;
  111. break;
  112. }
  113. }
  114. if(!$valid) {
  115. $request['dir'] = DSEP;
  116. }
  117. }
  118. /*
  119. * Populate $returnData with directory listing
  120. */
  121. $returnData = array();
  122. /* Folder Restriction with root '/' requested */
  123. if($request['dir'] == DSEP && count($allowed_folders)) {
  124. /* Just return restricted folders */
  125. foreach($allowed_folders as $f) {
  126. array_push($returnData, folder_entry($f, true));
  127. }
  128. } else {
  129. /* Full, expanded path to $dir */
  130. if($request['fullpath']) {
  131. /* Go through allowed folders if it is set */
  132. if(count($allowed_folders)) {
  133. foreach($allowed_folders as $f) {
  134. /* If this was not exactly the requested folder, but a parent,
  135. * list everything below it.
  136. */
  137. if((strtoupper($request['dir']) != strtoupper($f)) && strpos(strtoupper($request['dir']),strtoupper($f)) === 0) {
  138. // List entries in this folder
  139. $path = explode(DSEP, substr($request['dir'],strlen($f)));
  140. if($path[0] == '') {
  141. array_shift($path);
  142. }
  143. $folder_entry = folder_entry($f, true);
  144. $folder_entry['children'] = getdir($f, $request['dirsOnly'], $path);
  145. $folder_entry['expanded'] = true;
  146. array_push($returnData, $folder_entry);
  147. } else {
  148. array_push($returnData, folder_entry($f,true));
  149. }
  150. }
  151. /* Just get full path */
  152. } else {
  153. // List entries in this folder
  154. $path = explode(DSEP,$request['dir']);
  155. $root = array_shift($path).DSEP;
  156. // Folder entry
  157. $returnData = getdir($root, $request['dirsOnly'], $path);
  158. }
  159. } else {
  160. /* Default action. Return dir requested */
  161. $returnData = getdir($request['dir'], $request['dirsOnly']);
  162. }
  163. }
  164. header('Content-type: application/json');
  165. echo(json_encode($returnData));
  166. /*
  167. * Get directory entries
  168. */
  169. function getdir($dir, $dirsOnly=false, $recurse=array()) {
  170. if(!$dir) $dir = DSEP;
  171. $entries = getDirEntries($dir, $dirsOnly);
  172. if(!count($entries))
  173. return array();
  174. $dirents = array();
  175. foreach($entries as $path => $type) {
  176. if($type == 'folder' && count($recurse) && (strcasecmp($recurse[0],vbox_basename($path)) == 0)) {
  177. $entry = folder_entry($path, false, true);
  178. $entry['children'] = getdir($dir.DSEP.array_shift($recurse), $dirsOnly, $recurse);
  179. array_push($dirents, $entry);
  180. } else {
  181. // Push folder on to stack
  182. if($type == 'folder') {
  183. array_push($dirents, folder_entry($path));
  184. // Push file on to stack
  185. } else {
  186. $ext = strtolower(preg_replace('/^.*\./', '', $file));
  187. if(count($allowed) && !$allowed['.'.$ext]) continue;
  188. array_push($dirents, file_entry($path));
  189. }
  190. }
  191. }
  192. return $dirents;
  193. }
  194. function vbox_basename($b) { return substr($b,strrpos($b,DSEP)+1); }
  195. function file_entry($f) {
  196. $f = str_replace(DSEP.DSEP,DSEP,$f);
  197. $ext = strtolower(preg_replace('/^.*\./', '', $f));
  198. return array(
  199. 'ext' => $ext,
  200. 'name' => htmlentities(vbox_basename($f), ENT_QUOTES),
  201. 'path' => htmlentities($f, ENT_QUOTES),
  202. 'type' => 'file'
  203. );
  204. }
  205. function folder_entry($f,$full=false,$expanded=false) {
  206. $f = str_replace(DSEP.DSEP,DSEP,$f);
  207. $selected = (strnatcasecmp(rtrim($f,DSEP),rtrim($GLOBALS['request']['dir'],DSEP)) == 0) && $expanded;
  208. return array(
  209. 'expanded' => (bool)$expanded,
  210. 'selected' => (bool)$selected,
  211. 'path' => htmlentities($f,ENT_QUOTES),
  212. 'name' => htmlentities(($full ? $f : vbox_basename($f)),ENT_QUOTES),
  213. 'type' => 'folder',
  214. 'children' => array()
  215. );
  216. }
  217. /**
  218. * Rreturn a list of directory entries
  219. *
  220. * @param String $dir
  221. * @return Array of entries
  222. */
  223. function getDirEntries($dir, $foldersOnly=false) {
  224. global $localbrowser, $allowed_exts, $vbox;
  225. // Append trailing slash if it isn't here
  226. if(substr($dir,-1) != DSEP)
  227. $dir .= DSEP;
  228. /*
  229. * Use local file / folder browser (PHP)
  230. */
  231. if($localbrowser) {
  232. // If the dir doesn't exist or we can't scan it, just return
  233. if(!(file_exists($dir) && ($ents = @scandir($dir))))
  234. return array();
  235. $newtypes = array();
  236. $newents = array();
  237. for($i = 0; $i < count($ents); $i++) {
  238. // Skip . and ..
  239. if($ents[$i] == '.' || $ents[$i] == '..')
  240. continue;
  241. $fullpath = $dir.$ents[$i];
  242. $isdir = @is_dir($fullpath);
  243. if(!$isdir && $foldersOnly)
  244. continue;
  245. array_push($newtypes, $isdir ? 'folder' : 'file');
  246. array_push($newents, $fullpath);
  247. }
  248. return array_combine($newents, $newtypes);
  249. /*
  250. * Use remote file / folder browser (vbox)
  251. */
  252. } else {
  253. try {
  254. $appl = $vbox->vbox->createAppliance();
  255. $vfs = $appl->createVFSExplorer('file://'.str_replace(DSEP.DSEP,DSEP,$dir));
  256. $progress = $vfs->update();
  257. $progress->waitForCompletion(-1);
  258. $progress->releaseRemote();
  259. list($ents,$types) = $vfs->entryList();
  260. $vfs->releaseRemote();
  261. $appl->releaseRemote();
  262. } catch (Exception $e) {
  263. echo($e->getMessage());
  264. return array();
  265. }
  266. // Convert types to file / folder
  267. $newtypes = array();
  268. $newents = array();
  269. for($i = 0; $i < count($types); $i++) {
  270. // Skip . and ..
  271. if($ents[$i] == '.' || $ents[$i] == '..')
  272. continue;
  273. $isdir = $types[$i] == 4;
  274. if(!$isdir && $foldersOnly)
  275. continue;
  276. array_push($newtypes, $isdir ? 'folder' : 'file');
  277. array_push($newents, $dir.$ents[$i]);
  278. }
  279. return array_combine($newents,$newtypes);
  280. }
  281. }