source: trunk/plugins/MootoolsFileManager/mootools-filemanager/Backend/FileManager.php @ 1239

Last change on this file since 1239 was 1239, checked in by gogo, 10 years ago

Add new plugin MootoolsFileManager?
ticket:1502

File size: 16.0 KB
Line 
1<?php
2/*
3Script: FileManager.php
4        MooTools FileManager - Backend for the FileManager Script
5
6License:
7        MIT-style license.
8
9Copyright:
10        Copyright (c) 2009 [Christoph Pojer](http://cpojer.net).
11
12Dependencies:
13        - Upload.php
14        - Image.php
15        - getId3 Library
16
17Options:
18        - directory: (string) The base directory to be used for the FileManger
19        - baseURL: (string) Absolute URL to the FileManager files
20        - assetBasePath: (string) The path to all images and swf files
21        - id3Path: (string, optional) The path to the getid3.php file
22        - mimeTypesPath: (string, optional) The path to the MimTypes.ini file.
23        - dateFormat: (string, defaults to *j M Y - H:i*) The format in which dates should be displayed
24        - upload: (boolean, defaults to *false*) Whether to allow uploads or not
25        - destroy: (boolean, defaults to *false*) Whether to allow deletion of files or not
26        - maxUploadSize: (integeter, defaults to *3145728* bytes) The maximum file size for upload in bytes
27        - safe: (string, defaults to *true*) If true, disallows
28        - filter: (string) If specified, the mimetypes to be allowed (for display and upload).
29                Example: image/ allows all Image Mimetypes
30*/
31
32require_once(FileManagerUtility::getPath() . '/Upload.php');
33require_once(FileManagerUtility::getPath() . '/Image.php');
34
35class FileManager {
36       
37        protected $path = null;
38        protected $length = null;
39        protected $basedir = null;
40        protected $basename = null;
41        protected $options;
42        protected $post;
43        protected $get;
44       
45        public function __construct($options){
46                $path = FileManagerUtility::getPath();
47               
48                $this->options = array_merge(array(
49                        'directory' => '../Demos/Files',
50                        'baseURL' => '',
51                        'assetBasePath' => '../Assets',
52                        'id3Path' => $path . '/Assets/getid3/getid3.php',
53                        'mimeTypesPath' => $path . '/MimeTypes.ini',
54                        'dateFormat' => 'j M Y - H:i',
55                        'maxUploadSize' => 1024 * 1024 * 3,
56                        'suggestedMaxImageDimension' => array('width' => 800, 'height' => 600),
57                        'upload' => false,
58                        'destroy' => false,
59                        'safe' => true,
60                        'filter' => null
61                ), $options);
62               
63                $this->basedir = realpath($this->options['directory']);
64                $this->basename = pathinfo($this->basedir, PATHINFO_BASENAME) . '/';
65                $this->path = realpath($this->options['directory'] . '/../');
66                $this->length = strlen($this->path);
67               
68                header('Expires: Fri, 01 Jan 1990 00:00:00 GMT');
69                header('Cache-Control: no-cache, no-store, max-age=0, must-revalidate');
70               
71                $this->get = $_GET;
72                $this->post = $_POST;
73        }
74       
75        public function fireEvent($event){
76                $event = $event ? 'on' . ucfirst($event) : null;
77                if (!$event || !method_exists($this, $event)) $event = 'onView';
78               
79                $this->{$event}();
80        }
81       
82        protected function onView(){
83                $dir = $this->getDir(!empty($this->post['directory']) ? $this->post['directory'] : null);
84                $files = ($files = glob($dir . '/*')) ? $files : array();
85               
86                if ($dir != $this->basedir) array_unshift($files, $dir . '/..');
87                natcasesort($files);
88                foreach ($files as $file){
89                        $mime = $this->getMimeType($file);
90                        if ($this->options['filter'] && $mime != 'text/directory' && !FileManagerUtility::startsWith($mime, $this->options['filter']))
91                                continue;
92                       
93                        $out[is_dir($file) ? 0 : 1][] = array(
94                                'name' => pathinfo($file, PATHINFO_BASENAME),
95                                'date' => date($this->options['dateFormat'], filemtime($file)),
96                                'mime' => $this->getMimeType($file),
97                                'icon' => $this->getIcon($this->normalize($file)),
98                                'size' => filesize($file)
99                        );
100                }
101               
102                echo json_encode(array(
103                        'path' => $this->getPath($dir),
104                        'dir' => array(
105                                'name' => pathinfo($dir, PATHINFO_BASENAME),
106                                'date' => date($this->options['dateFormat'], filemtime($dir)),
107                                'mime' => 'text/directory',
108                                'icon' => 'dir'
109                        ),
110                        'files' => array_merge(!empty($out[0]) ? $out[0] : array(), !empty($out[1]) ? $out[1] : array())
111                ));
112        }
113       
114        protected function onDetail(){
115                if (empty($this->post['directory']) || empty($this->post['file'])) return;
116               
117                $file = realpath($this->path . '/' . $this->post['directory'] . '/' . $this->post['file']);
118                if (!$this->checkFile($file)) return;
119               
120                require_once($this->options['id3Path']);
121               
122                // Xinha: The URL is weird in the standard distribution of filemanager, it seems to expect
123                // that the files directory (where you are selecting/uploading) is always within the filemanager
124                // directory itself somewhere.
125                //
126                // Also the 'baseURL' seems to be wanted as the parent of the 'basedir' ("directory" option)
127                // Xinha is supplying both the same (eg url = /foo/test and dir = /home/bar/public_html/foo/test )
128                // so we will rip off the first part of directory, below.
129                $url = $this->options['baseURL'] . '/' . preg_replace('/^[^\/]*\//', '', $this->post['directory'] . '/' . $this->post['file']);//$this->normalize(substr($file, strlen($this->path)+1));
130                $mime = $this->getMimeType($file);
131                $content = null;
132                $extra_return_detail = array();
133               
134                if (FileManagerUtility::startsWith($mime, 'image/')){
135                        $size = getimagesize($file);
136                        $content = '<img src="' . $url . '" class="preview" alt="" />
137                                <h2>${more}</h2>
138                                <dl>
139                                        <dt>${width}</dt><dd>' . $size[0] . 'px</dd>
140                                        <dt>${height}</dt><dd>' . $size[1] . 'px</dd>
141                                </dl>';
142                                $extra_return_detail['width']  = $size[0];
143                                $extra_return_detail['height'] = $size[1];
144                }elseif (FileManagerUtility::startsWith($mime, 'text/') || $mime == 'application/x-javascript'){
145                        $filecontent = file_get_contents($file, null, null, 0, 300);
146                        if (!FileManagerUtility::isBinary($filecontent)) $content = '<div class="textpreview">' . nl2br(str_replace(array('$', "\t"), array('&#36;', '&nbsp;&nbsp;'), htmlentities($filecontent))) . '</div>';
147                }elseif ($mime == 'application/zip'){
148                        $out = array(array(), array());
149                        $getid3 = new getID3();
150                        $getid3->Analyze($file);
151                        foreach ($getid3->info['zip']['files'] as $name => $size){
152                                $icon = is_array($size) ? 'dir' : $this->getIcon($name);
153                                $out[($icon == 'dir') ? 0 : 1][$name] = '<li><a><img src="' . $this->options['assetBasePath'] . '/Icons/' . $icon . '.png" alt="" /> ' . $name . '</a></li>';
154                        }
155                        natcasesort($out[0]);
156                        natcasesort($out[1]);
157                        $content = '<ul>' . implode(array_merge($out[0], $out[1])) . '</ul>';
158                }elseif (FileManagerUtility::startsWith($mime, 'audio/')){
159                        $getid3 = new getID3();
160                        $getid3->Analyze($file);
161                       
162                        $content = '<div class="object">
163                                        <object type="application/x-shockwave-flash" data="' . $this->options['assetBasePath'] . '/dewplayer.swf?mp3=' . rawurlencode($url) . '&volume=30" width="200" height="20">
164                                                <param name="movie" value="' . $this->options['assetBasePath'] . '/dewplayer.swf?mp3=' . rawurlencode($url) . '&volume=30" />
165                                        </object>
166                                </div>
167                                <h2>${more}</h2>
168                                <dl>
169                                        <dt>${title}</dt><dd>' . $getid3->info['comments']['title'][0] . '</dd>
170                                        <dt>${artist}</dt><dd>' . $getid3->info['comments']['artist'][0] . '</dd>
171                                        <dt>${album}</dt><dd>' . $getid3->info['comments']['album'][0] . '</dd>
172                                        <dt>${length}</dt><dd>' . $getid3->info['playtime_string'] . '</dd>
173                                        <dt>${bitrate}</dt><dd>' . round($getid3->info['bitrate']/1000) . 'kbps</dd>
174                                </dl>';
175                }
176               
177                echo json_encode(array_merge(array(
178                        'content' => $content ? $content : '<div class="margin">
179                                ${nopreview}<br/><button value="' . $url . '">${download}</button>
180                        </div>',
181                        'url'     => $url,
182                        'mime'    => $mime,
183                ), $extra_return_detail));
184        }
185       
186        protected function onDestroy(){
187                if (!$this->options['destroy'] || empty($this->post['directory']) || empty($this->post['file'])) return;
188               
189                $file = realpath($this->path . '/' . $this->post['directory'] . '/' . $this->post['file']);
190                if (!$this->checkFile($file)) return;
191               
192                $this->unlink($file);
193               
194                echo json_encode(array(
195                        'content' => 'destroyed'
196                ));
197        }
198       
199        protected function onCreate(){
200    try
201    {
202      if (!$this->options['upload'])
203        throw new FileManagerException('disabled');
204       
205                if (empty($this->post['directory']) || empty($this->post['file'])) return;
206               
207                $file = $this->getName($this->post['file'], $this->getDir($this->post['directory']));
208                if (!$file) return;
209               
210                mkdir($file);
211                }
212                catch(FileManagerException $e){
213                /*
214      echo json_encode(array(
215        'status' => 0,
216        'error' => '${upload.' . $e->getMessage() . '}'
217      ));
218     */
219    }
220   
221                $this->onView();
222        }
223       
224        protected function onUpload(){
225                try{
226                        if (!$this->options['upload'])
227                                throw new FileManagerException('disabled');
228                        if (empty($this->get['directory']) || (function_exists('UploadIsAuthenticated') && !UploadIsAuthenticated($this->get)))
229                                throw new FileManagerException('authenticated');
230                       
231                        $dir = $this->getDir($this->get['directory']);
232                        $name = pathinfo((Upload::exists('Filedata')) ? $this->getName($_FILES['Filedata']['name'], $dir) : null, PATHINFO_FILENAME);
233                        $file = Upload::move('Filedata', $dir . '/', array(
234                                'name' => $name,
235                                'extension' => $this->options['safe'] && $name && in_array(strtolower(pathinfo($_FILES['Filedata']['name'], PATHINFO_EXTENSION)), array('exe', 'dll', 'php', 'php3', 'php4', 'php5', 'phps')) ? 'txt' : null,
236                                'size' => $this->options['maxUploadSize'],
237                                'mimes' => $this->getAllowedMimeTypes()
238                        ));
239                       
240                        if (FileManagerUtility::startsWith(Upload::mime($file), 'image/') && !empty($this->get['resize'])){
241                                $img = new Image($file);
242                                $size = $img->getSize();
243                                if ($size['width'] > $this->options['suggestedMaxImageDimension']['width']) $img->resize( $this->options['suggestedMaxImageDimension']['width'])->save();
244                                elseif ($size['height'] > $this->options['suggestedMaxImageDimension']['height']) $img->resize(null, $this->options['suggestedMaxImageDimension']['height'])->save();
245                        }
246                       
247                        echo json_encode(array(
248                                'status' => 1,
249                                'name' => pathinfo($file, PATHINFO_BASENAME)
250                        ));
251                }catch(UploadException $e){
252                        echo json_encode(array(
253                                'status' => 0,
254                                'error' => class_exists('ValidatorException') ? strip_tags($e->getMessage()) : '${upload.' . $e->getMessage() . '}' // This is for Styx :)
255                        ));
256                }catch(FileManagerException $e){
257                        echo json_encode(array(
258                                'status' => 0,
259                                'error' => '${upload.' . $e->getMessage() . '}'
260                        ));
261                }
262        }
263       
264        /* This method is used by both move and rename */
265        protected function onMove(){
266                if (empty($this->post['directory']) || empty($this->post['file'])) return;
267               
268                $rename = empty($this->post['newDirectory']) && !empty($this->post['name']);
269                $dir = $this->getDir($this->post['directory']);
270                $file = realpath($dir . '/' . $this->post['file']);
271               
272                $is_dir = is_dir($file);
273                if (!$this->checkFile($file) || (!$rename && $is_dir))
274                        return;
275               
276                if ($rename || $is_dir){
277                        if (empty($this->post['name'])) return;
278                        $newname = $this->getName($this->post['name'], $dir);
279                        $fn = 'rename';
280                }else{
281                        $newname = $this->getName(pathinfo($file, PATHINFO_FILENAME), $this->getDir($this->post['newDirectory']));
282                        $fn = !empty($this->post['copy']) ? 'copy' : 'rename';
283                }
284               
285                if (!$newname) return;
286               
287                $ext = pathinfo($file, PATHINFO_EXTENSION);
288                if ($ext) $newname .= '.' . $ext;
289                $fn($file, $newname);
290               
291                echo json_encode(array(
292                        'name' => pathinfo($this->normalize($newname), PATHINFO_BASENAME),
293                ));
294        }
295       
296        protected function unlink($file){
297                $file = realpath($file);
298                if ($this->basedir==$file || strlen($this->basedir)>=strlen($file))
299                        return;
300               
301                if (is_dir($file)){
302                        $files = glob($file . '/*');
303                        if (is_array($files))
304                                foreach ($files as $f)
305                                        $this->unlink($f);
306                               
307                        rmdir($file);
308                }else{
309                        try{ if ($this->checkFile($file)) unlink($file); }catch(Exception $e){}
310                }
311        }
312       
313        protected function getName($file, $dir){
314                $files = array();
315                foreach ((array)glob($dir . '/*') as $f)
316                        $files[] = pathinfo($f, PATHINFO_FILENAME);
317               
318                $pathinfo = pathinfo($file);
319                $file = $dir . '/' . FileManagerUtility::pagetitle($pathinfo['filename'], $files).(!empty($pathinfo['extension']) ? '.' . $pathinfo['extension'] : null);
320               
321                return !$file || !FileManagerUtility::startsWith($file, $this->basedir) || file_exists($file) ? null : $file;
322        }
323       
324        protected function getIcon($file){
325                if (FileManagerUtility::endsWith($file, '/..')) return 'dir_up';
326                else if (is_dir($file)) return 'dir';
327               
328                $ext = pathinfo($file, PATHINFO_EXTENSION);
329                return ($ext && file_exists(realpath($this->options['assetBasePath'] . '/Icons/' . $ext . '.png'))) ? $ext : 'default';
330        }
331
332        protected function getMimeType($file){
333                return is_dir($file) ? 'text/directory' : Upload::mime($file);
334        }
335       
336        protected function getDir($dir){
337                $dir = realpath($this->path . '/' . (FileManagerUtility::startsWith($dir, $this->basename) ? $dir : $this->basename));
338                return $this->checkFile($dir) ? $dir : $this->basedir;
339        }
340       
341        protected function getPath($file){
342                $file = $this->normalize(substr($file, $this->length));
343                return substr($file, FileManagerUtility::startsWith($file, '/') ? 1 : 0);
344        }
345       
346        protected function checkFile($file){
347                $mimes = $this->getAllowedMimeTypes();
348                $hasFilter = $this->options['filter'] && count($mimes);
349                if ($hasFilter) array_push($mimes, 'text/directory');
350                return !(!$file || !FileManagerUtility::startsWith($file, $this->basedir) || !file_exists($file) || ($hasFilter && !in_array($this->getMimeType($file), $mimes)));
351        }
352       
353        protected function normalize($file){
354                return preg_replace('/\\\|\/{2,}/', '/', $file);
355        }
356       
357        protected function getAllowedMimeTypes(){
358                $filter = $this->options['filter'];
359               
360                if (!$filter) return null;
361                if (!FileManagerUtility::endsWith($filter, '/')) return array($filter);
362               
363                static $mimes;
364                if (!$mimes) $mimes = parse_ini_file($this->options['mimeTypesPath']);
365               
366                foreach ($mimes as $mime)
367                        if (FileManagerUtility::startsWith($mime, $filter))
368                                $mimeTypes[] = strtolower($mime);
369               
370                return $mimeTypes;
371        }
372
373}
374
375class FileManagerException extends Exception {}
376
377/* Stripped-down version of some Styx PHP Framework-Functionality bundled with this FileBrowser. Styx is located at: http://styx.og5.net */
378class FileManagerUtility {
379       
380        public static function endsWith($string, $look){
381                return strrpos($string, $look)===strlen($string)-strlen($look);
382        }
383       
384        public static function startsWith($string, $look){
385                return strpos($string, $look)===0;
386        }
387       
388        public static function pagetitle($data, $options = array()){
389                static $regex;
390                if (!$regex){
391                        $regex = array(
392                                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;'),
393                                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'),
394                        );
395                       
396                        $regex[0][] = '"';
397                        $regex[0][] = "'";
398                }
399               
400                $data = trim(substr(preg_replace('/(?:[^A-z0-9]|_|\^)+/i', '_', str_replace($regex[0], $regex[1], $data)), 0, 64), '_');
401                return !empty($options) ? self::checkTitle($data, $options) : $data;
402        }
403       
404        protected static function checkTitle($data, $options = array(), $i = 0){
405                if (!is_array($options)) return $data;
406               
407                foreach ($options as $content)
408                        if ($content && strtolower($content) == strtolower($data.($i ? '_' . $i : '')))
409                                return self::checkTitle($data, $options, ++$i);
410               
411                return $data.($i ? '_' . $i : '');
412        }
413       
414        public static function isBinary($str){
415                $array = array(0, 255);
416                for($i = 0; $i < strlen($str); $i++)
417                        if (in_array(ord($str[$i]), $array)) return true;
418               
419                return false;
420        }
421       
422        public static function getPath(){
423                static $path;
424                return $path ? $path : $path = pathinfo(__FILE__, PATHINFO_DIRNAME);
425        }
426       
427}
Note: See TracBrowser for help on using the repository browser.