PageRenderTime 201ms CodeModel.GetById 33ms RepoModel.GetById 0ms app.codeStats 0ms

/admin/includes/fancyupload/Backend/FileManager.php

http://compactcms.googlecode.com/
PHP | 399 lines | 304 code | 64 blank | 31 comment | 66 complexity | 7f2e2f595be263787b0bf76444795d64 MD5 | raw file
Possible License(s): GPL-3.0, CC0-1.0
  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' => '',
  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' => true,
  48. 'destroy' => true,
  49. 'safe' => false,
  50. 'filter' => null
  51. ), $options);
  52. $this->basedir = realpath($this->options['directory']);
  53. $this->basename = pathinfo($this->basedir, PATHINFO_BASENAME) . '/';
  54. $this->path = realpath($this->options['directory'] . '/../');
  55. $this->length = strlen($this->path);
  56. header('Expires: Fri, 01 Jan 1990 00:00:00 GMT');
  57. header('Cache-Control: no-cache, no-store, max-age=0, must-revalidate');
  58. $this->get = $_GET;
  59. $this->post = $_POST;
  60. }
  61. public function fireEvent($event){
  62. $event = $event ? 'on' . ucfirst($event) : null;
  63. if (!$event || !method_exists($this, $event)) $event = 'onView';
  64. $this->{$event}();
  65. }
  66. protected function onView(){
  67. $dir = $this->getDir(!empty($this->post['directory']) ? $this->post['directory'] : null);
  68. $files = ($files = glob($dir . '/*')) ? $files : array();
  69. if ($dir != $this->basedir) array_unshift($files, $dir . '/..');
  70. natcasesort($files);
  71. foreach ($files as $file){
  72. $mime = $this->getMimeType($file);
  73. if ($this->options['filter'] && $mime != 'text/directory' && !FileManagerUtility::startsWith($mime, $this->options['filter']))
  74. continue;
  75. $out[is_dir($file) ? 0 : 1][] = array(
  76. 'name' => pathinfo($file, PATHINFO_BASENAME),
  77. 'date' => date($this->options['dateFormat'], filemtime($file)),
  78. 'mime' => $this->getMimeType($file),
  79. 'icon' => $this->getIcon($this->normalize($file)),
  80. 'size' => filesize($file)
  81. );
  82. }
  83. echo json_encode(array(
  84. 'path' => $this->getPath($dir),
  85. 'dir' => array(
  86. 'name' => pathinfo($dir, PATHINFO_BASENAME),
  87. 'date' => date($this->options['dateFormat'], filemtime($dir)),
  88. 'mime' => 'text/directory',
  89. 'icon' => 'dir'
  90. ),
  91. 'files' => array_merge(!empty($out[0]) ? $out[0] : array(), !empty($out[1]) ? $out[1] : array())
  92. ));
  93. }
  94. protected function onDetail(){
  95. if (empty($this->post['directory']) || empty($this->post['file'])) return;
  96. $file = realpath($this->path . '/' . $this->post['directory'] . '/' . $this->post['file']);
  97. if (!$this->checkFile($file)) return;
  98. require_once($this->options['id3Path']);
  99. $url = $this->options['baseURL'] . $this->normalize(substr($file, strlen($this->path)+1));
  100. $mime = $this->getMimeType($file);
  101. $content = null;
  102. if (FileManagerUtility::startsWith($mime, 'image/')){
  103. $size = getimagesize($file);
  104. $content = '<img src="' . $url . '" class="preview" alt="" />
  105. <h2>${more}</h2>
  106. <dl>
  107. <dt>${width}</dt><dd>' . $size[0] . 'px</dd>
  108. <dt>${height}</dt><dd>' . $size[1] . 'px</dd>
  109. </dl>';
  110. }elseif (FileManagerUtility::startsWith($mime, 'text/') || $mime == 'application/x-javascript'){
  111. $filecontent = file_get_contents($file, null, null, 0, 300);
  112. if (!FileManagerUtility::isBinary($filecontent)) $content = '<div class="textpreview">' . nl2br(str_replace(array('$', "\t"), array('&#36;', '&nbsp;&nbsp;'), htmlentities($filecontent))) . '</div>';
  113. }elseif ($mime == 'application/zip'){
  114. $out = array(array(), array());
  115. $getid3 = new getID3();
  116. $getid3->Analyze($file);
  117. foreach ($getid3->info['zip']['files'] as $name => $size){
  118. $icon = is_array($size) ? 'dir' : $this->getIcon($name);
  119. $out[($icon == 'dir') ? 0 : 1][$name] = '<li><a><img src="' . $this->options['assetBasePath'] . '/Icons/' . $icon . '.png" alt="" /> ' . $name . '</a></li>';
  120. }
  121. natcasesort($out[0]);
  122. natcasesort($out[1]);
  123. $content = '<ul>' . implode(array_merge($out[0], $out[1])) . '</ul>';
  124. }elseif (FileManagerUtility::startsWith($mime, 'audio/')){
  125. $getid3 = new getID3();
  126. $getid3->Analyze($file);
  127. $content = '<div class="object">
  128. <object type="application/x-shockwave-flash" data="' . $this->options['assetBasePath'] . '/dewplayer.swf?mp3=' . rawurlencode($url) . '&volume=30" width="200" height="20">
  129. <param name="movie" value="' . $this->options['assetBasePath'] . '/dewplayer.swf?mp3=' . rawurlencode($url) . '&volume=30" />
  130. </object>
  131. </div>
  132. <h2>${more}</h2>
  133. <dl>
  134. <dt>${title}</dt><dd>' . @$getid3->info['comments']['title'][0] . '</dd>
  135. <dt>${artist}</dt><dd>' . @$getid3->info['comments']['artist'][0] . '</dd>
  136. <dt>${album}</dt><dd>' . @$getid3->info['comments']['album'][0] . '</dd>
  137. <dt>${length}</dt><dd>' . @$getid3->info['playtime_string'] . '</dd>
  138. <dt>${bitrate}</dt><dd>' . @round($getid3->info['bitrate']/1000) . 'kbps</dd>
  139. </dl>';
  140. }
  141. echo json_encode(array(
  142. 'content' => $content ? $content : '<div class="margin">
  143. ${nopreview}<br/><button value="' . $url . '">${download}</button>
  144. </div>'
  145. ));
  146. }
  147. protected function onDestroy(){
  148. if (!$this->options['destroy'] || empty($this->post['directory']) || empty($this->post['file'])) return;
  149. $file = realpath($this->path . '/' . $this->post['directory'] . '/' . $this->post['file']);
  150. if (!$this->checkFile($file)) return;
  151. $this->unlink($file);
  152. echo json_encode(array(
  153. 'content' => 'destroyed'
  154. ));
  155. }
  156. protected function onCreate(){
  157. if (empty($this->post['directory']) || empty($this->post['file'])) return;
  158. $file = $this->getName($this->post['file'], $this->getDir($this->post['directory']));
  159. if (!$file) return;
  160. mkdir($file);
  161. $this->onView();
  162. }
  163. protected function onUpload(){
  164. try{
  165. if (!$this->options['upload'])
  166. throw new FileManagerException('disabled');
  167. if (empty($this->get['directory']) || (function_exists('UploadIsAuthenticated') && !UploadIsAuthenticated($this->get)))
  168. throw new FileManagerException('authenticated');
  169. $dir = $this->getDir($this->get['directory']);
  170. $name = pathinfo((Upload::exists('Filedata')) ? $this->getName($_FILES['Filedata']['name'], $dir) : null, PATHINFO_FILENAME);
  171. $file = Upload::move('Filedata', $dir . '/', array(
  172. 'name' => $name,
  173. 'extension' => $this->options['safe'] && $name && in_array(strtolower(pathinfo($_FILES['Filedata']['name'], PATHINFO_EXTENSION)), array('exe', 'dll', 'php', 'php3', 'php4', 'php5', 'phps')) ? 'txt' : null,
  174. 'size' => $this->options['maxUploadSize'],
  175. 'mimes' => $this->getAllowedMimeTypes()
  176. ));
  177. if (FileManagerUtility::startsWith(Upload::mime($file), 'image/') && !empty($this->get['resize'])){
  178. $img = new Image($file);
  179. $size = $img->getSize();
  180. if ($size['width'] > 800) $img->resize(800)->save();
  181. elseif ($size['height'] > 600) $img->resize(null, 600)->save();
  182. }
  183. echo json_encode(array(
  184. 'status' => 1,
  185. 'name' => pathinfo($file, PATHINFO_BASENAME)
  186. ));
  187. }catch(UploadException $e){
  188. echo json_encode(array(
  189. 'status' => 0,
  190. 'error' => class_exists('ValidatorException') ? strip_tags($e->getMessage()) : '${upload.' . $e->getMessage() . '}' // This is for Styx :)
  191. ));
  192. }catch(FileManagerException $e){
  193. echo json_encode(array(
  194. 'status' => 0,
  195. 'error' => '${upload.' . $e->getMessage() . '}'
  196. ));
  197. }
  198. }
  199. /* This method is used by both move and rename */
  200. protected function onMove(){
  201. if (empty($this->post['directory']) || empty($this->post['file'])) return;
  202. $rename = empty($this->post['newDirectory']) && !empty($this->post['name']);
  203. $dir = $this->getDir($this->post['directory']);
  204. $file = realpath($dir . '/' . $this->post['file']);
  205. $is_dir = is_dir($file);
  206. if (!$this->checkFile($file) || (!$rename && $is_dir))
  207. return;
  208. if ($rename || $is_dir){
  209. if (empty($this->post['name'])) return;
  210. $newname = $this->getName($this->post['name'], $dir);
  211. $fn = 'rename';
  212. }else{
  213. $newname = $this->getName(pathinfo($file, PATHINFO_FILENAME), $this->getDir($this->post['newDirectory']));
  214. $fn = !empty($this->post['copy']) ? 'copy' : 'rename';
  215. }
  216. if (!$newname) return;
  217. $ext = pathinfo($file, PATHINFO_EXTENSION);
  218. if ($ext) $newname .= '.' . $ext;
  219. $fn($file, $newname);
  220. echo json_encode(array(
  221. 'name' => pathinfo($this->normalize($newname), PATHINFO_BASENAME),
  222. ));
  223. }
  224. protected function unlink($file){
  225. $file = realpath($file);
  226. if ($this->basedir==$file || strlen($this->basedir)>=strlen($file))
  227. return;
  228. if (is_dir($file)){
  229. $files = glob($file . '/*');
  230. if (is_array($files))
  231. foreach ($files as $f)
  232. $this->unlink($f);
  233. rmdir($file);
  234. }else{
  235. try{ if ($this->checkFile($file)) unlink($file); }catch(Exception $e){}
  236. }
  237. }
  238. protected function getName($file, $dir){
  239. $files = array();
  240. foreach ((array)glob($dir . '/*') as $f)
  241. $files[] = pathinfo($f, PATHINFO_FILENAME);
  242. $pathinfo = pathinfo($file);
  243. $file = $dir . '/' . FileManagerUtility::pagetitle($pathinfo['filename'], $files).(!empty($pathinfo['extension']) ? '.' . $pathinfo['extension'] : null);
  244. return !$file || !FileManagerUtility::startsWith($file, $this->basedir) || file_exists($file) ? null : $file;
  245. }
  246. protected function getIcon($file){
  247. if (FileManagerUtility::endsWith($file, '/..')) return 'dir_up';
  248. else if (is_dir($file)) return 'dir';
  249. $ext = pathinfo($file, PATHINFO_EXTENSION);
  250. return ($ext && file_exists(realpath($this->options['assetBasePath'] . '/Icons/' . $ext . '.png'))) ? $ext : 'default';
  251. }
  252. protected function getMimeType($file){
  253. return is_dir($file) ? 'text/directory' : Upload::mime($file);
  254. }
  255. protected function getDir($dir){
  256. $dir = realpath($this->path . '/' . (FileManagerUtility::startsWith($dir, $this->basename) ? $dir : $this->basename));
  257. return $this->checkFile($dir) ? $dir : $this->basedir;
  258. }
  259. protected function getPath($file){
  260. $file = $this->normalize(substr($file, $this->length));
  261. return substr($file, FileManagerUtility::startsWith($file, '/') ? 1 : 0);
  262. }
  263. protected function checkFile($file){
  264. $mimes = $this->getAllowedMimeTypes();
  265. $hasFilter = $this->options['filter'] && count($mimes);
  266. if ($hasFilter) array_push($mimes, 'text/directory');
  267. return !(!$file || !FileManagerUtility::startsWith($file, $this->basedir) || !file_exists($file) || ($hasFilter && !in_array($this->getMimeType($file), $mimes)));
  268. }
  269. protected function normalize($file){
  270. return preg_replace('/\\\|\/{2,}/', '/', $file);
  271. }
  272. protected function getAllowedMimeTypes(){
  273. $filter = $this->options['filter'];
  274. if (!$filter) return null;
  275. if (!FileManagerUtility::endsWith($filter, '/')) return array($filter);
  276. static $mimes;
  277. if (!$mimes) $mimes = parse_ini_file($this->options['mimeTypesPath']);
  278. foreach ($mimes as $mime)
  279. if (FileManagerUtility::startsWith($mime, $filter))
  280. $mimeTypes[] = strtolower($mime);
  281. return $mimeTypes;
  282. }
  283. }
  284. class FileManagerException extends Exception {}
  285. /* Stripped-down version of some Styx PHP Framework-Functionality bundled with this FileBrowser. Styx is located at: http://styx.og5.net */
  286. class FileManagerUtility {
  287. public static function endsWith($string, $look){
  288. return strrpos($string, $look)===strlen($string)-strlen($look);
  289. }
  290. public static function startsWith($string, $look){
  291. return strpos($string, $look)===0;
  292. }
  293. public static function pagetitle($data, $options = array()){
  294. static $regex;
  295. if (!$regex){
  296. $regex = array(
  297. 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;'),
  298. 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'),
  299. );
  300. $regex[0][] = '"';
  301. $regex[0][] = "'";
  302. }
  303. $data = trim(substr(preg_replace('/(?:[^A-z0-9]|_|\^)+/i', '_', str_replace($regex[0], $regex[1], $data)), 0, 64), '_');
  304. return !empty($options) ? self::checkTitle($data, $options) : $data;
  305. }
  306. protected static function checkTitle($data, $options = array(), $i = 0){
  307. if (!is_array($options)) return $data;
  308. foreach ($options as $content)
  309. if ($content && strtolower($content) == strtolower($data.($i ? '_' . $i : '')))
  310. return self::checkTitle($data, $options, ++$i);
  311. return $data.($i ? '_' . $i : '');
  312. }
  313. public static function isBinary($str){
  314. $array = array(0, 255);
  315. for($i = 0; $i < strlen($str); $i++)
  316. if (in_array(ord($str[$i]), $array)) return true;
  317. return false;
  318. }
  319. public static function getPath(){
  320. static $path;
  321. return $path ? $path : $path = pathinfo(__FILE__, PATHINFO_DIRNAME);
  322. }
  323. }