PageRenderTime 65ms CodeModel.GetById 32ms RepoModel.GetById 1ms app.codeStats 0ms

/public/library/xinha/plugins/MootoolsFileManager/mootools-filemanager/Backend/FileManager.php

https://bitbucket.org/mayorbrain/precurio-v2
PHP | 429 lines | 315 code | 70 blank | 44 comment | 67 complexity | da16a54f434931a83284417f451b9f57 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, LGPL-2.1, BSD-3-Clause, LGPL-2.0, CC-BY-SA-3.0, MIT
  1. <?php
  2. /*
  3. Script: FileManager.php
  4. MooTools FileManager - Backend for the FileManager Script
  5. License:
  6. MIT-style license.
  7. Copyright:
  8. Copyright (c) 2009 [Christoph Pojer](http://cpojer.net).
  9. Dependencies:
  10. - Upload.php
  11. - Image.php
  12. - getId3 Library
  13. Options:
  14. - directory: (string) The base directory to be used for the FileManger
  15. - baseURL: (string) Absolute URL to the FileManager files
  16. - assetBasePath: (string) The path to all images and swf files
  17. - id3Path: (string, optional) The path to the getid3.php file
  18. - mimeTypesPath: (string, optional) The path to the MimTypes.ini file.
  19. - dateFormat: (string, defaults to *j M Y - H:i*) The format in which dates should be displayed
  20. - upload: (boolean, defaults to *false*) Whether to allow uploads or not
  21. - destroy: (boolean, defaults to *false*) Whether to allow deletion of files or not
  22. - maxUploadSize: (integeter, defaults to *3145728* bytes) The maximum file size for upload in bytes
  23. - safe: (string, defaults to *true*) If true, disallows
  24. - filter: (string) If specified, the mimetypes to be allowed (for display and upload).
  25. Example: image/ allows all Image Mimetypes
  26. */
  27. require_once(FileManagerUtility::getPath() . '/Upload.php');
  28. require_once(FileManagerUtility::getPath() . '/Image.php');
  29. class FileManager {
  30. protected $path = null;
  31. protected $length = null;
  32. protected $basedir = null;
  33. protected $basename = null;
  34. protected $options;
  35. protected $post;
  36. protected $get;
  37. public function __construct($options){
  38. $path = FileManagerUtility::getPath();
  39. $this->options = array_merge(array(
  40. 'directory' => '../Demos/Files',
  41. 'baseURL' => '',
  42. 'assetBasePath' => '../Assets',
  43. 'id3Path' => $path . '/Assets/getid3/getid3.php',
  44. 'mimeTypesPath' => $path . '/MimeTypes.ini',
  45. 'dateFormat' => 'j M Y - H:i',
  46. 'maxUploadSize' => 1024 * 1024 * 3,
  47. 'upload' => false,
  48. 'destroy' => false,
  49. 'safe' => true,
  50. 'filter' => null,
  51. // Xinha: Allow to specify the "Resize Large Images" tolerance level.
  52. 'suggestedMaxImageDimension' => array('width' => 800, 'height' => 600),
  53. ), $options);
  54. $this->basedir = realpath($this->options['directory']);
  55. $this->basename = pathinfo($this->basedir, PATHINFO_BASENAME) . '/';
  56. $this->path = realpath($this->options['directory'] . '/../');
  57. $this->length = strlen($this->path);
  58. header('Expires: Fri, 01 Jan 1990 00:00:00 GMT');
  59. header('Cache-Control: no-cache, no-store, max-age=0, must-revalidate');
  60. $this->get = $_GET;
  61. $this->post = $_POST;
  62. }
  63. public function fireEvent($event){
  64. $event = $event ? 'on' . ucfirst($event) : null;
  65. if (!$event || !method_exists($this, $event)) $event = 'onView';
  66. $this->{$event}();
  67. }
  68. protected function onView(){
  69. $dir = $this->getDir(!empty($this->post['directory']) ? $this->post['directory'] : null);
  70. $files = ($files = glob($dir . '/*')) ? $files : array();
  71. if ($dir != $this->basedir) array_unshift($files, $dir . '/..');
  72. natcasesort($files);
  73. foreach ($files as $file){
  74. $mime = $this->getMimeType($file);
  75. if ($this->options['filter'] && $mime != 'text/directory' && !FileManagerUtility::startsWith($mime, $this->options['filter']))
  76. continue;
  77. $out[is_dir($file) ? 0 : 1][] = array(
  78. 'name' => pathinfo($file, PATHINFO_BASENAME),
  79. 'date' => date($this->options['dateFormat'], filemtime($file)),
  80. 'mime' => $this->getMimeType($file),
  81. 'icon' => $this->getIcon($this->normalize($file)),
  82. 'size' => filesize($file)
  83. );
  84. }
  85. echo json_encode(array(
  86. 'path' => $this->getPath($dir),
  87. 'dir' => array(
  88. 'name' => pathinfo($dir, PATHINFO_BASENAME),
  89. 'date' => date($this->options['dateFormat'], filemtime($dir)),
  90. 'mime' => 'text/directory',
  91. 'icon' => 'dir'
  92. ),
  93. 'files' => array_merge(!empty($out[0]) ? $out[0] : array(), !empty($out[1]) ? $out[1] : array())
  94. ));
  95. }
  96. protected function onDetail(){
  97. if (empty($this->post['directory']) || empty($this->post['file'])) return;
  98. $file = realpath($this->path . '/' . $this->post['directory'] . '/' . $this->post['file']);
  99. if (!$this->checkFile($file)) return;
  100. require_once($this->options['id3Path']);
  101. // Xinha: The URL is weird in the standard distribution of filemanager, it seems to expect
  102. // that the files directory (where you are selecting/uploading) is always within the filemanager
  103. // directory itself somewhere.
  104. //
  105. // Also the 'baseURL' seems to be wanted as the parent of the 'basedir' ("directory" option)
  106. // Xinha is supplying both the same (eg url = /foo/test and dir = /home/bar/public_html/foo/test )
  107. // so we will rip off the first part of directory, below.
  108. $url = $this->options['baseURL'] . '/' . preg_replace('/^[^\/]*\//', '', $this->post['directory'] . '/' . $this->post['file']);
  109. $mime = $this->getMimeType($file);
  110. $content = null;
  111. // Xinha: We want to get some more information about what has been selected in a way
  112. // we can use it. Effectively what gets put in here will be passed into the
  113. // 'onDetails' event handler of your FileManager object (if any).
  114. $extra_return_detail = array
  115. (
  116. 'url' => $url,
  117. 'mime' => $mime
  118. );
  119. if (FileManagerUtility::startsWith($mime, 'image/')){
  120. $size = getimagesize($file);
  121. $content = '<img src="' . $url . '" class="preview" alt="" />
  122. <h2>${more}</h2>
  123. <dl>
  124. <dt>${width}</dt><dd>' . $size[0] . 'px</dd>
  125. <dt>${height}</dt><dd>' . $size[1] . 'px</dd>
  126. </dl>';
  127. // Xinha: Return some information about the image which can be access
  128. // from the onDetails event handler in FileManager
  129. $extra_return_detail['width'] = $size[0];
  130. $extra_return_detail['height'] = $size[1];
  131. }elseif (FileManagerUtility::startsWith($mime, 'text/') || $mime == 'application/x-javascript'){
  132. $filecontent = file_get_contents($file, null, null, 0, 300);
  133. if (!FileManagerUtility::isBinary($filecontent)) $content = '<div class="textpreview">' . nl2br(str_replace(array('$', "\t"), array('&#36;', '&nbsp;&nbsp;'), htmlentities($filecontent))) . '</div>';
  134. }elseif ($mime == 'application/zip'){
  135. $out = array(array(), array());
  136. $getid3 = new getID3();
  137. $getid3->Analyze($file);
  138. foreach ($getid3->info['zip']['files'] as $name => $size){
  139. $icon = is_array($size) ? 'dir' : $this->getIcon($name);
  140. $out[($icon == 'dir') ? 0 : 1][$name] = '<li><a><img src="' . $this->options['assetBasePath'] . '/Icons/' . $icon . '.png" alt="" /> ' . $name . '</a></li>';
  141. }
  142. natcasesort($out[0]);
  143. natcasesort($out[1]);
  144. $content = '<ul>' . implode(array_merge($out[0], $out[1])) . '</ul>';
  145. }elseif (FileManagerUtility::startsWith($mime, 'audio/')){
  146. $getid3 = new getID3();
  147. $getid3->Analyze($file);
  148. $content = '<div class="object">
  149. <object type="application/x-shockwave-flash" data="' . $this->options['assetBasePath'] . '/dewplayer.swf?mp3=' . rawurlencode($url) . '&volume=30" width="200" height="20">
  150. <param name="movie" value="' . $this->options['assetBasePath'] . '/dewplayer.swf?mp3=' . rawurlencode($url) . '&volume=30" />
  151. </object>
  152. </div>
  153. <h2>${more}</h2>
  154. <dl>
  155. <dt>${title}</dt><dd>' . $getid3->info['comments']['title'][0] . '</dd>
  156. <dt>${artist}</dt><dd>' . $getid3->info['comments']['artist'][0] . '</dd>
  157. <dt>${album}</dt><dd>' . $getid3->info['comments']['album'][0] . '</dd>
  158. <dt>${length}</dt><dd>' . $getid3->info['playtime_string'] . '</dd>
  159. <dt>${bitrate}</dt><dd>' . round($getid3->info['bitrate']/1000) . 'kbps</dd>
  160. </dl>';
  161. }
  162. echo json_encode(array_merge(array(
  163. 'content' => $content ? $content : '<div class="margin">
  164. ${nopreview}<br/><button value="' . $url . '">${download}</button>
  165. </div>'
  166. ), $extra_return_detail));
  167. }
  168. protected function onDestroy(){
  169. if (!$this->options['destroy'] || empty($this->post['directory']) || empty($this->post['file'])) return;
  170. $file = realpath($this->path . '/' . $this->post['directory'] . '/' . $this->post['file']);
  171. if (!$this->checkFile($file)) return;
  172. $this->unlink($file);
  173. echo json_encode(array(
  174. 'content' => 'destroyed'
  175. ));
  176. }
  177. protected function onCreate(){
  178. if ($this->options['upload'])
  179. {
  180. if (empty($this->post['directory']) || empty($this->post['file'])) return;
  181. $file = $this->getName($this->post['file'], $this->getDir($this->post['directory']));
  182. if (!$file) return;
  183. mkdir($file);
  184. }
  185. $this->onView();
  186. }
  187. protected function onUpload(){
  188. try{
  189. if (!$this->options['upload'])
  190. throw new FileManagerException('disabled');
  191. if (empty($this->get['directory']) || (function_exists('UploadIsAuthenticated') && !UploadIsAuthenticated($this->get)))
  192. throw new FileManagerException('authenticated');
  193. $dir = $this->getDir($this->get['directory']);
  194. $name = pathinfo((Upload::exists('Filedata')) ? $this->getName($_FILES['Filedata']['name'], $dir) : null, PATHINFO_FILENAME);
  195. $file = Upload::move('Filedata', $dir . '/', array(
  196. 'name' => $name,
  197. 'extension' => $this->options['safe'] && $name && in_array(strtolower(pathinfo($_FILES['Filedata']['name'], PATHINFO_EXTENSION)), array('exe', 'dll', 'php', 'php3', 'php4', 'php5', 'phps')) ? 'txt' : null,
  198. 'size' => $this->options['maxUploadSize'],
  199. 'mimes' => $this->getAllowedMimeTypes()
  200. ));
  201. if (FileManagerUtility::startsWith(Upload::mime($file), 'image/') && !empty($this->get['resize'])){
  202. $img = new Image($file);
  203. $size = $img->getSize();
  204. if ($size['width'] > $this->options['suggestedMaxImageDimension']['width']) $img->resize( $this->options['suggestedMaxImageDimension']['width'])->save();
  205. elseif ($size['height'] > $this->options['suggestedMaxImageDimension']['height']) $img->resize(null, $this->options['suggestedMaxImageDimension']['height'])->save();
  206. }
  207. echo json_encode(array(
  208. 'status' => 1,
  209. 'name' => pathinfo($file, PATHINFO_BASENAME)
  210. ));
  211. }catch(UploadException $e){
  212. echo json_encode(array(
  213. 'status' => 0,
  214. 'error' => class_exists('ValidatorException') ? strip_tags($e->getMessage()) : '${upload.' . $e->getMessage() . '}' // This is for Styx :)
  215. ));
  216. }catch(FileManagerException $e){
  217. echo json_encode(array(
  218. 'status' => 0,
  219. 'error' => '${upload.' . $e->getMessage() . '}'
  220. ));
  221. }
  222. }
  223. /* This method is used by both move and rename */
  224. protected function onMove(){
  225. if (empty($this->post['directory']) || empty($this->post['file'])) return;
  226. $rename = empty($this->post['newDirectory']) && !empty($this->post['name']);
  227. $dir = $this->getDir($this->post['directory']);
  228. $file = realpath($dir . '/' . $this->post['file']);
  229. $is_dir = is_dir($file);
  230. if (!$this->checkFile($file) || (!$rename && $is_dir))
  231. return;
  232. if ($rename || $is_dir){
  233. if (empty($this->post['name'])) return;
  234. $newname = $this->getName($this->post['name'], $dir);
  235. $fn = 'rename';
  236. }else{
  237. $newname = $this->getName(pathinfo($file, PATHINFO_FILENAME), $this->getDir($this->post['newDirectory']));
  238. $fn = !empty($this->post['copy']) ? 'copy' : 'rename';
  239. }
  240. if (!$newname) return;
  241. $ext = pathinfo($file, PATHINFO_EXTENSION);
  242. if ($ext) $newname .= '.' . $ext;
  243. $fn($file, $newname);
  244. echo json_encode(array(
  245. 'name' => pathinfo($this->normalize($newname), PATHINFO_BASENAME),
  246. ));
  247. }
  248. protected function unlink($file){
  249. $file = realpath($file);
  250. if ($this->basedir==$file || strlen($this->basedir)>=strlen($file))
  251. return;
  252. if (is_dir($file)){
  253. $files = glob($file . '/*');
  254. if (is_array($files))
  255. foreach ($files as $f)
  256. $this->unlink($f);
  257. rmdir($file);
  258. }else{
  259. try{ if ($this->checkFile($file)) unlink($file); }catch(Exception $e){}
  260. }
  261. }
  262. protected function getName($file, $dir){
  263. $files = array();
  264. foreach ((array)glob($dir . '/*') as $f)
  265. $files[] = pathinfo($f, PATHINFO_FILENAME);
  266. $pathinfo = pathinfo($file);
  267. $file = $dir . '/' . FileManagerUtility::pagetitle($pathinfo['filename'], $files).(!empty($pathinfo['extension']) ? '.' . $pathinfo['extension'] : null);
  268. return !$file || !FileManagerUtility::startsWith($file, $this->basedir) || file_exists($file) ? null : $file;
  269. }
  270. protected function getIcon($file){
  271. if (FileManagerUtility::endsWith($file, '/..')) return 'dir_up';
  272. else if (is_dir($file)) return 'dir';
  273. $ext = pathinfo($file, PATHINFO_EXTENSION);
  274. return ($ext && file_exists(realpath($this->options['assetBasePath'] . '/Icons/' . $ext . '.png'))) ? $ext : 'default';
  275. }
  276. protected function getMimeType($file){
  277. return is_dir($file) ? 'text/directory' : Upload::mime($file);
  278. }
  279. protected function getDir($dir){
  280. $dir = realpath($this->path . '/' . (FileManagerUtility::startsWith($dir, $this->basename) ? $dir : $this->basename));
  281. return $this->checkFile($dir) ? $dir : $this->basedir;
  282. }
  283. protected function getPath($file){
  284. $file = $this->normalize(substr($file, $this->length));
  285. return substr($file, FileManagerUtility::startsWith($file, '/') ? 1 : 0);
  286. }
  287. protected function checkFile($file){
  288. $mimes = $this->getAllowedMimeTypes();
  289. $hasFilter = $this->options['filter'] && count($mimes);
  290. if ($hasFilter) array_push($mimes, 'text/directory');
  291. return !(!$file || !FileManagerUtility::startsWith($file, $this->basedir) || !file_exists($file) || ($hasFilter && !in_array($this->getMimeType($file), $mimes)));
  292. }
  293. protected function normalize($file){
  294. return preg_replace('/\\\|\/{2,}/', '/', $file);
  295. }
  296. protected function getAllowedMimeTypes(){
  297. $filter = $this->options['filter'];
  298. if (!$filter) return null;
  299. if (!FileManagerUtility::endsWith($filter, '/')) return array($filter);
  300. static $mimes;
  301. if (!$mimes) $mimes = parse_ini_file($this->options['mimeTypesPath']);
  302. foreach ($mimes as $mime)
  303. if (FileManagerUtility::startsWith($mime, $filter))
  304. $mimeTypes[] = strtolower($mime);
  305. return $mimeTypes;
  306. }
  307. }
  308. class FileManagerException extends Exception {}
  309. /* Stripped-down version of some Styx PHP Framework-Functionality bundled with this FileBrowser. Styx is located at: http://styx.og5.net */
  310. class FileManagerUtility {
  311. public static function endsWith($string, $look){
  312. return strrpos($string, $look)===strlen($string)-strlen($look);
  313. }
  314. public static function startsWith($string, $look){
  315. return strpos($string, $look)===0;
  316. }
  317. public static function pagetitle($data, $options = array()){
  318. static $regex;
  319. if (!$regex){
  320. $regex = array(
  321. explode(' ', 'Æ æ Œ œ ß Ü ü Ö ö Ä ä À Á Â Ã Ä Å &#260; &#258; Ç &#262; &#268; &#270; &#272; Ð È É Ê Ë &#280; &#282; &#286; Ì Í Î Ï &#304; &#321; &#317; &#313; Ñ &#323; &#327; Ò Ó Ô Õ Ö Ø &#336; &#340; &#344; Š &#346; &#350; &#356; &#354; Ù Ú Û Ü &#366; &#368; Ý Ž &#377; &#379; à á â ã ä å &#261; &#259; ç &#263; &#269; &#271; &#273; è é ê ë &#281; &#283; &#287; ì í î ï &#305; &#322; &#318; &#314; ñ &#324; &#328; ð ò ó ô õ ö ø &#337; &#341; &#345; &#347; š &#351; &#357; &#355; ù ú û ü &#367; &#369; ý ÿ ž &#378; &#380;'),
  322. explode(' ', 'Ae ae Oe oe ss Ue ue Oe oe Ae ae A A A A A A A A C C C D D D E E E E E E G I I I I I L L L N N N O O O O O O O R R S S S T T U U U U U U Y Z Z Z a a a a a a a a c c c d d e e e e e e g i i i i i l l l n n n o o o o o o o o r r s s s t t u u u u u u y y z z z'),
  323. );
  324. $regex[0][] = '"';
  325. $regex[0][] = "'";
  326. }
  327. $data = trim(substr(preg_replace('/(?:[^A-z0-9]|_|\^)+/i', '_', str_replace($regex[0], $regex[1], $data)), 0, 64), '_');
  328. return !empty($options) ? self::checkTitle($data, $options) : $data;
  329. }
  330. protected static function checkTitle($data, $options = array(), $i = 0){
  331. if (!is_array($options)) return $data;
  332. foreach ($options as $content)
  333. if ($content && strtolower($content) == strtolower($data.($i ? '_' . $i : '')))
  334. return self::checkTitle($data, $options, ++$i);
  335. return $data.($i ? '_' . $i : '');
  336. }
  337. public static function isBinary($str){
  338. $array = array(0, 255);
  339. for($i = 0; $i < strlen($str); $i++)
  340. if (in_array(ord($str[$i]), $array)) return true;
  341. return false;
  342. }
  343. public static function getPath(){
  344. static $path;
  345. return $path ? $path : $path = pathinfo(__FILE__, PATHINFO_DIRNAME);
  346. }
  347. }