PageRenderTime 40ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/server/fs.ajax.php

https://gitlab.com/x33n/ampache
PHP | 267 lines | 207 code | 11 blank | 49 comment | 51 complexity | a362e2157ef16b486dba169217b77c79 MD5 | raw file
  1. <?php
  2. /* vim:set softtabstop=4 shiftwidth=4 expandtab: */
  3. /**
  4. *
  5. * LICENSE: GNU General Public License, version 2 (GPLv2)
  6. * Copyright 2001 - 2015 Ampache.org
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License v2
  10. * as published by the Free Software Foundation.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  20. *
  21. */
  22. // jsTree file system browser
  23. define('AJAX_INCLUDE','1');
  24. require_once '../lib/init.php';
  25. $rootdir = Upload::get_root();
  26. if (empty($rootdir)) {
  27. exit;
  28. }
  29. $rootdir .= DIRECTORY_SEPARATOR;
  30. ini_set('open_basedir', $rootdir);
  31. class fs
  32. {
  33. protected $base = null;
  34. protected function real($path)
  35. {
  36. $temp = realpath($path);
  37. if (!$temp) { throw new Exception('Path does not exist: ' . $path); }
  38. if ($this->base && strlen($this->base)) {
  39. if (strpos($temp, $this->base) !== 0) { throw new Exception('Path is not inside base ('.$this->base.'): ' . $temp); }
  40. }
  41. return $temp;
  42. }
  43. protected function path($id)
  44. {
  45. $id = str_replace('/', DIRECTORY_SEPARATOR, $id);
  46. $id = trim($id, DIRECTORY_SEPARATOR);
  47. $id = $this->real($this->base . DIRECTORY_SEPARATOR . $id);
  48. return $id;
  49. }
  50. protected function id($path)
  51. {
  52. $path = $this->real($path);
  53. $path = substr($path, strlen($this->base));
  54. $path = str_replace(DIRECTORY_SEPARATOR, '/', $path);
  55. $path = trim($path, '/');
  56. return strlen($path) ? $path : '/';
  57. }
  58. public function __construct($base)
  59. {
  60. $this->base = $this->real($base);
  61. if (!$this->base) { throw new Exception('Base directory does not exist'); }
  62. }
  63. public function lst($id, $with_root = false)
  64. {
  65. $dir = $this->path($id);
  66. $lst = @scandir($dir);
  67. if (!$lst) { throw new Exception('Could not list path: ' . $dir); }
  68. $res = array();
  69. foreach ($lst as $item) {
  70. if ($item == '.' || $item == '..' || $item === null) { continue; }
  71. $tmp = preg_match('([^ a-zа-я-_0-9.]+)ui', $item);
  72. if ($tmp === false || $tmp === 1) { continue; }
  73. if (is_dir($dir . DIRECTORY_SEPARATOR . $item)) {
  74. $res[] = array('text' => $item, 'children' => true, 'id' => $this->id($dir . DIRECTORY_SEPARATOR . $item), 'icon' => 'folder');
  75. } else {
  76. //$res[] = array('text' => $item, 'children' => false, 'id' => $this->id($dir . DIRECTORY_SEPARATOR . $item), 'type' => 'file', 'icon' => 'file file-'.substr($item, strrpos($item,'.') + 1));
  77. }
  78. }
  79. if ($with_root && $this->id($dir) === '/') {
  80. $res = array(array('text' => basename($this->base), 'children' => $res, 'id' => '/', 'icon'=>'folder', 'state' => array('opened' => true, 'disabled' => true)));
  81. }
  82. return $res;
  83. }
  84. public function data($id)
  85. {
  86. if (strpos($id, ":")) {
  87. $id = array_map(array($this, 'id'), explode(':', $id));
  88. return array('type'=>'multiple', 'content'=> 'Multiple selected: ' . implode(' ', $id));
  89. }
  90. $dir = $this->path($id);
  91. if (is_dir($dir)) {
  92. return array('type'=>'folder', 'content'=> $id);
  93. }
  94. if (is_file($dir)) {
  95. $ext = strpos($dir, '.') !== FALSE ? substr($dir, strrpos($dir, '.') + 1) : '';
  96. $dat = array('type' => $ext, 'content' => '');
  97. switch ($ext) {
  98. /*case 'txt':
  99. case 'text':
  100. case 'md':
  101. case 'js':
  102. case 'json':
  103. case 'css':
  104. case 'html':
  105. case 'htm':
  106. case 'xml':
  107. case 'c':
  108. case 'cpp':
  109. case 'h':
  110. case 'sql':
  111. case 'log':
  112. case 'py':
  113. case 'rb':
  114. case 'htaccess':
  115. case 'php':
  116. $dat['content'] = file_get_contents($dir);
  117. break;
  118. case 'jpg':
  119. case 'jpeg':
  120. case 'gif':
  121. case 'png':
  122. case 'bmp':
  123. $dat['content'] = 'data:'.finfo_file(finfo_open(FILEINFO_MIME_TYPE), $dir).';base64,'.base64_encode(file_get_contents($dir));
  124. break;*/
  125. default:
  126. $dat['content'] = 'File not recognized: '.$this->id($dir);
  127. break;
  128. }
  129. return $dat;
  130. }
  131. throw new Exception('Not a valid selection: ' . $dir);
  132. }
  133. public function create($id, $name, $mkdir = false)
  134. {
  135. $dir = $this->path($id);
  136. if (preg_match('([^ a-zа-я-_0-9.]+)ui', $name) || !strlen($name)) {
  137. throw new Exception('Invalid name: ' . $name);
  138. }
  139. if ($mkdir) {
  140. mkdir($dir . DIRECTORY_SEPARATOR . $name);
  141. } else {
  142. file_put_contents($dir . DIRECTORY_SEPARATOR . $name, '');
  143. }
  144. return array('id' => $this->id($dir . DIRECTORY_SEPARATOR . $name));
  145. }
  146. public function rename($id, $name)
  147. {
  148. $dir = $this->path($id);
  149. if ($dir === $this->base) {
  150. throw new Exception('Cannot rename root');
  151. }
  152. if (preg_match('([^ a-zа-я-_0-9.]+)ui', $name) || !strlen($name)) {
  153. throw new Exception('Invalid name: ' . $name);
  154. }
  155. $new = explode(DIRECTORY_SEPARATOR, $dir);
  156. array_pop($new);
  157. array_push($new, $name);
  158. $new = implode(DIRECTORY_SEPARATOR, $new);
  159. if (is_file($new) || is_dir($new)) { throw new Exception('Path already exists: ' . $new); }
  160. rename($dir, $new);
  161. return array('id' => $this->id($new));
  162. }
  163. public function remove($id)
  164. {
  165. $dir = $this->path($id);
  166. if ($dir === $this->base) {
  167. throw new Exception('Cannot remove root');
  168. }
  169. if (is_dir($dir)) {
  170. foreach (array_diff(scandir($dir), array(".", "..")) as $f) {
  171. $this->remove($this->id($dir . DIRECTORY_SEPARATOR . $f));
  172. }
  173. rmdir($dir);
  174. }
  175. if (is_file($dir)) {
  176. unlink($dir);
  177. }
  178. return array('status' => 'OK');
  179. }
  180. public function move($id, $par)
  181. {
  182. $dir = $this->path($id);
  183. $par = $this->path($par);
  184. $new = explode(DIRECTORY_SEPARATOR, $dir);
  185. $new = array_pop($new);
  186. $new = $par . DIRECTORY_SEPARATOR . $new;
  187. rename($dir, $new);
  188. return array('id' => $this->id($new));
  189. }
  190. public function copy($id, $par)
  191. {
  192. $dir = $this->path($id);
  193. $par = $this->path($par);
  194. $new = explode(DIRECTORY_SEPARATOR, $dir);
  195. $new = array_pop($new);
  196. $new = $par . DIRECTORY_SEPARATOR . $new;
  197. if (is_file($new) || is_dir($new)) { throw new Exception('Path already exists: ' . $new); }
  198. if (is_dir($dir)) {
  199. mkdir($new);
  200. foreach (array_diff(scandir($dir), array(".", "..")) as $f) {
  201. $this->copy($this->id($dir . DIRECTORY_SEPARATOR . $f), $this->id($new));
  202. }
  203. }
  204. if (is_file($dir)) {
  205. copy($dir, $new);
  206. }
  207. return array('id' => $this->id($new));
  208. }
  209. }
  210. if (isset($_GET['operation'])) {
  211. $fs = new fs($rootdir);
  212. try {
  213. $rslt = null;
  214. switch ($_GET['operation']) {
  215. case 'get_node':
  216. $node = isset($_GET['id']) && $_GET['id'] !== '#' ? $_GET['id'] : '/';
  217. $rslt = $fs->lst($node, (isset($_GET['id']) && $_GET['id'] === '#'));
  218. break;
  219. case "get_content":
  220. $node = isset($_GET['id']) && $_GET['id'] !== '#' ? $_GET['id'] : '/';
  221. $rslt = $fs->data($node);
  222. break;
  223. case 'create_node':
  224. $node = isset($_GET['id']) && $_GET['id'] !== '#' ? $_GET['id'] : '/';
  225. $rslt = $fs->create($node, isset($_GET['text']) ? $_GET['text'] : '', (!isset($_GET['type']) || $_GET['type'] !== 'file'));
  226. break;
  227. case 'rename_node':
  228. $node = isset($_GET['id']) && $_GET['id'] !== '#' ? $_GET['id'] : '/';
  229. $rslt = $fs->rename($node, isset($_GET['text']) ? $_GET['text'] : '');
  230. break;
  231. case 'delete_node':
  232. $node = isset($_GET['id']) && $_GET['id'] !== '#' ? $_GET['id'] : '/';
  233. $rslt = $fs->remove($node);
  234. break;
  235. case 'move_node':
  236. $node = isset($_GET['id']) && $_GET['id'] !== '#' ? $_GET['id'] : '/';
  237. $parn = isset($_GET['parent']) && $_GET['parent'] !== '#' ? $_GET['parent'] : '/';
  238. $rslt = $fs->move($node, $parn);
  239. break;
  240. case 'copy_node':
  241. $node = isset($_GET['id']) && $_GET['id'] !== '#' ? $_GET['id'] : '/';
  242. $parn = isset($_GET['parent']) && $_GET['parent'] !== '#' ? $_GET['parent'] : '/';
  243. $rslt = $fs->copy($node, $parn);
  244. break;
  245. default:
  246. throw new Exception('Unsupported operation: ' . $_GET['operation']);
  247. }
  248. header('Content-Type: application/json; charset=utf8');
  249. echo json_encode($rslt);
  250. } catch (Exception $e) {
  251. header($_SERVER["SERVER_PROTOCOL"] . ' 500 Server Error');
  252. header('Status: 500 Server Error');
  253. echo $e->getMessage();
  254. }
  255. die();
  256. }