source: trunk/plugins/ExtendedFileManager/Classes/ExtendedFileManager.php @ 521

Last change on this file since 521 was 521, checked in by koto, 13 years ago

Ticket #811: Added ExtendedFileManager? plugin ver 1.1.1 (with Polish translation)
Currently the plugin depends on ImageManager? class files.
Added dirSize() method used by ExtendedFileManager? to ImageManager/Classes/Files?.php

File size: 20.1 KB
Line 
1<?php
2/**
3 * ExtendedFileManager, list images, directories, and thumbnails.
4 * Authors: Wei Zhuo, Afru, Krzysztof Kotowicz
5 * Version: Updated on 08-01-2005 by Afru
6 * Version: Updated on 20-06-2006 by Krzysztof Kotowicz
7 * Package: ExtendedFileManager (EFM 1.1.1)
8 * http://www.afrusoft.com/htmlarea
9 */
10
11/**
12 * We use classes from ImageManager to avoid code duplication
13 */
14require_once '../ImageManager/Classes/Files.php';
15
16/**
17 * ExtendedFileManager Class.
18 * @author $Author: Wei Zhuo $
19 * @author $Author: Krzysztof Kotowicz $
20 * @version $Id: ExtendedFileManager.php 27 2004-04-01 08:31:57Z Wei Zhuo $
21 */
22class ExtendedFileManager
23{
24        /**
25         * Configuration array.
26         */
27        var $config;
28
29        /**
30         * Array of directory information.
31         */
32        var $dirs;
33       
34    /**
35     * Manager mode - image | link
36     */
37        var $mode;
38
39        /**
40         * Constructor. Create a new Image Manager instance.
41         * @param array $config configuration array, see config.inc.php
42         */
43        function ExtendedFileManager($config, $mode = null)
44        {
45                $this->config = $config;
46               
47                $this->mode = empty($mode) ? (empty($config['insert_mode']) ? 'image' : $config['insert_mode']): $mode;
48        }
49
50        /**
51         * Get the base directory.
52         * @return string base dir, see config.inc.php
53         */
54        function getImagesDir()
55        {
56                Return $this->config['images_dir'];
57        }
58
59        /**
60         * Get the base URL.
61         * @return string base url, see config.inc.php
62         */
63        function getImagesURL()
64        {
65                Return $this->config['images_url'];
66        }
67
68        function isValidBase()
69        {
70                return is_dir($this->getImagesDir());
71        }
72
73        /**
74         * Get the tmp file prefix.
75     * @return string tmp file prefix.
76         */
77        function getTmpPrefix()
78        {
79                Return $this->config['tmp_prefix'];
80        }
81
82        /**
83         * Get the sub directories in the base dir.
84         * Each array element contain
85         * the relative path (relative to the base dir) as key and the
86         * full path as value.
87         * @return array of sub directries
88         * <code>array('path name' => 'full directory path', ...)</code>
89         */
90        function getDirs()
91        {
92                if(is_null($this->dirs))
93                {
94                        $dirs = $this->_dirs($this->getImagesDir(),'/');
95                        ksort($dirs);
96                        $this->dirs = $dirs;
97                }
98                return $this->dirs;
99        }
100
101        /**
102         * Recursively travese the directories to get a list
103         * of accessable directories.
104         * @param string $base the full path to the current directory
105         * @param string $path the relative path name
106         * @return array of accessiable sub-directories
107         * <code>array('path name' => 'full directory path', ...)</code>
108         */
109        function _dirs($base, $path)
110        {
111                $base = Files::fixPath($base);
112                $dirs = array();
113
114                if($this->isValidBase() == false)
115                        return $dirs;
116
117                $d = @dir($base);
118               
119                while (false !== ($entry = $d->read()))
120                {
121                        //If it is a directory, and it doesn't start with
122                        // a dot, and if is it not the thumbnail directory
123                        if(is_dir($base.$entry)
124                                && substr($entry,0,1) != '.'
125                                && $this->isThumbDir($entry) == false)
126                        {
127                                $relative = Files::fixPath($path.$entry);
128                                $fullpath = Files::fixPath($base.$entry);
129                                $dirs[$relative] = $fullpath;
130                                $dirs = array_merge($dirs, $this->_dirs($fullpath, $relative));
131                        }
132                }
133                $d->close();
134
135                Return $dirs;
136        }
137
138        /**
139         * Get all the files and directories of a relative path.
140         * @param string $path relative path to be base path.
141         * @return array of file and path information.
142         * <code>array(0=>array('relative'=>'fullpath',...), 1=>array('filename'=>fileinfo array(),...)</code>
143         * fileinfo array: <code>array('url'=>'full url',
144         *                       'relative'=>'relative to base',
145         *                        'fullpath'=>'full file path',
146         *                        'image'=>imageInfo array() false if not image,
147         *                        'stat' => filestat)</code>
148         */
149        function getFiles($path)
150        {
151                $files = array();
152                $dirs = array();
153
154        $valid_extensions = $this->mode == 'image' ? $this->config['allowed_image_extensions'] : $this->config['allowed_link_extensions'];
155
156                if($this->isValidBase() == false)
157                        return array($files,$dirs);
158
159                $path = Files::fixPath($path);
160                $base = Files::fixPath($this->getImagesDir());
161                $fullpath = Files::makePath($base,$path);
162
163
164                $d = @dir($fullpath);
165               
166                while (false !== ($entry = $d->read()))
167                {
168                        //not a dot file or directory
169                        if(substr($entry,0,1) != '.')
170                        {
171                                if(is_dir($fullpath.$entry)
172                                        && $this->isThumbDir($entry) == false)
173                                {
174                                        $relative = Files::fixPath($path.$entry);
175                                        $full = Files::fixPath($fullpath.$entry);
176                                        $count = $this->countFiles($full);
177                                        $dirs[$relative] = array('fullpath'=>$full,'entry'=>$entry,'count'=>$count, 'stat'=>stat($fullpath.$entry));
178                                }
179
180                                else if(is_file($fullpath.$entry) && $this->isThumb($entry)==false && $this->isTmpFile($entry) == false)
181                                {
182                                        $afruext = strtolower(substr(strrchr($entry, "."), 1));
183
184                    if(in_array($afruext,$valid_extensions))
185                                        {
186
187                                                $file['url'] = Files::makePath($this->config['base_url'],$path).$entry;
188                                                $file['relative'] = $path.$entry;
189                                                $file['fullpath'] = $fullpath.$entry;
190                                                $img = $this->getImageInfo($fullpath.$entry);
191                                                if(!is_array($img)) $img[0]=$img[1]=0;
192                                                $file['image'] = $img;
193                                                $file['stat'] = stat($fullpath.$entry);
194                                                $file['ext'] = $afruext;
195                                                $files[$entry] = $file;
196                                        }
197
198                                }
199                        }
200                }
201                $d->close();
202                ksort($dirs);
203                ksort($files);
204               
205                Return array($dirs, $files);
206        }       
207
208        /**
209         * Count the number of files and directories in a given folder
210         * minus the thumbnail folders and thumbnails.
211         */
212        function countFiles($path)
213        {
214                $total = 0;
215
216                if(is_dir($path))
217                {
218                        $d = @dir($path);
219
220                        while (false !== ($entry = $d->read()))
221                        {
222                                //echo $entry."<br>";
223                                if(substr($entry,0,1) != '.'
224                                        && $this->isThumbDir($entry) == false
225                                        && $this->isTmpFile($entry) == false
226                                        && $this->isThumb($entry) == false)
227                                {
228                                        $total++;
229                                }
230                        }
231                        $d->close();
232                }
233                return $total;
234        }
235
236        /**
237         * Get image size information.
238         * @param string $file the image file
239         * @return array of getImageSize information,
240         *  false if the file is not an image.
241         */
242        function getImageInfo($file)
243        {
244                Return @getImageSize($file);
245        }
246
247        /**
248         * Check if the file contains the thumbnail prefix.
249         * @param string $file filename to be checked
250         * @return true if the file contains the thumbnail prefix, false otherwise.
251         */
252        function isThumb($file)
253        {
254                $len = strlen($this->config['thumbnail_prefix']);
255                if(substr($file,0,$len)==$this->config['thumbnail_prefix'])
256                        Return true;
257                else
258                        Return false;
259        }
260
261        /**
262         * Check if the given directory is a thumbnail directory.
263         * @param string $entry directory name
264         * @return true if it is a thumbnail directory, false otherwise
265         */
266        function isThumbDir($entry)
267        {
268                if($this->config['thumbnail_dir'] == false
269                        || strlen(trim($this->config['thumbnail_dir'])) == 0)
270                        Return false;           
271                else
272                        Return ($entry == $this->config['thumbnail_dir']);
273        }
274
275        /**
276         * Check if the given file is a tmp file.
277         * @param string $file file name
278         * @return boolean true if it is a tmp file, false otherwise
279         */
280        function isTmpFile($file)
281        {
282                $len = strlen($this->config['tmp_prefix']);
283                if(substr($file,0,$len)==$this->config['tmp_prefix'])
284                        Return true;
285                else
286                        Return false;           
287        }
288
289        /**
290         * For a given image file, get the respective thumbnail filename
291         * no file existence check is done.
292         * @param string $fullpathfile the full path to the image file
293         * @return string of the thumbnail file
294         */
295        function getThumbName($fullpathfile)
296        {
297                $path_parts = pathinfo($fullpathfile);
298               
299                $thumbnail = $this->config['thumbnail_prefix'].$path_parts['basename'];
300
301                if($this->config['safe_mode'] == true
302                        || strlen(trim($this->config['thumbnail_dir'])) == 0)
303                {
304                        Return Files::makeFile($path_parts['dirname'],$thumbnail);
305                }
306                else
307                {
308                        if(strlen(trim($this->config['thumbnail_dir'])) > 0)
309                        {
310                                $path = Files::makePath($path_parts['dirname'],$this->config['thumbnail_dir']);
311                                if(!is_dir($path))
312                                        Files::createFolder($path);
313                                Return Files::makeFile($path,$thumbnail);
314                        }
315                        else //should this ever happen?
316                        {
317                                //error_log('ExtendedFileManager: Error in creating thumbnail name');
318                        }
319                }
320        }
321       
322        /**
323         * Similar to getThumbName, but returns the URL, base on the
324         * given base_url in config.inc.php
325         * @param string $relative the relative image file name,
326         * relative to the base_dir path
327         * @return string the url of the thumbnail
328         */
329        function getThumbURL($relative)
330        {
331                $path_parts = pathinfo($relative);
332                $thumbnail = $this->config['thumbnail_prefix'].$path_parts['basename'];
333                if($path_parts['dirname']=='\\') $path_parts['dirname']='/';
334
335                if($this->config['safe_mode'] == true
336                        || strlen(trim($this->config['thumbnail_dir'])) == 0)
337                {
338                        Return Files::makeFile($this->getImagesURL(),$thumbnail);
339                }
340                else
341                {
342                        if(strlen(trim($this->config['thumbnail_dir'])) > 0)
343                        {
344                                $path = Files::makePath($path_parts['dirname'],$this->config['thumbnail_dir']);
345                                $url_path = Files::makePath($this->getImagesURL(), $path);
346                                Return Files::makeFile($url_path,$thumbnail);
347                        }
348                        else //should this ever happen?
349                        {
350                                //error_log('ExtendedFileManager: Error in creating thumbnail url');
351                        }
352
353                }
354        }
355
356   /**
357    * For a given image file, get the respective resized filename
358    * no file existence check is done.
359    * @param string $fullpathfile the full path to the image file
360    * @param integer $width the intended width
361    * @param integer $height the intended height
362    * @param boolean $mkDir whether to attempt to make the resized_dir if it doesn't exist
363    * @return string of the resized filename
364    */
365        function getResizedName($fullpathfile, $width, $height, $mkDir = TRUE)
366        {
367                $path_parts = pathinfo($fullpathfile);
368
369                $thumbnail = $this->config['resized_prefix']."_{$width}x{$height}_{$path_parts['basename']}";
370
371                if( strlen(trim($this->config['resized_dir'])) == 0 || $this->config['safe_mode'] == true )
372                {
373                        Return Files::makeFile($path_parts['dirname'],$thumbnail);
374                }
375                else
376                {
377      $path = Files::makePath($path_parts['dirname'],$this->config['resized_dir']);
378      if($mkDir && !is_dir($path))
379        Files::createFolder($path);
380      Return Files::makeFile($path,$thumbnail);
381                }
382        }
383
384        /**
385         * Check if the given path is part of the subdirectories
386         * under the base_dir.
387         * @param string $path the relative path to be checked
388         * @return boolean true if the path exists, false otherwise
389         */
390        function validRelativePath($path)
391        {
392                $dirs = $this->getDirs();
393                if($path == '/')
394                        Return true;
395                //check the path given in the url against the
396                //list of paths in the system.
397                for($i = 0; $i < count($dirs); $i++)
398                {
399                        $key = key($dirs);
400                        //we found the path
401                        if($key == $path)
402                                Return true;
403               
404                        next($dirs);
405                }               
406                Return false;
407        }
408
409        /**
410         * Process uploaded files, assumes the file is in
411         * $_FILES['upload'] and $_POST['dir'] is set.
412         * The dir must be relative to the base_dir and exists.
413         * @return null
414         */
415        function processUploads()
416        {
417                if($this->isValidBase() == false)
418                        return;
419
420                $relative = null;
421
422                if(isset($_POST['dir']))
423                        $relative = rawurldecode($_POST['dir']);
424                else
425                        return;
426
427                //check for the file, and must have valid relative path
428                if(isset($_FILES['upload']) && $this->validRelativePath($relative))
429                {
430                        Return $this->_processFiles($relative, $_FILES['upload']);
431                }
432        }
433
434        /**
435         * Process upload files. The file must be an
436         * uploaded file. Any duplicate
437         * file will be renamed. See Files::copyFile for details
438         * on renaming.
439         * @param string $relative the relative path where the file
440         * should be copied to.
441         * @param array $file the uploaded file from $_FILES
442         * @return boolean true if the file was processed successfully,
443         * false otherwise
444         */
445        function _processFiles($relative, $file)
446        {
447               
448                if($file['error']!=0)
449                {
450                        Return false;
451                }
452
453                if(!is_file($file['tmp_name']))
454                {
455                        Return false;
456                }
457
458                if(!is_uploaded_file($file['tmp_name']))
459                {
460                        Files::delFile($file['tmp_name']);
461                        Return false;
462                }
463
464        $valid_extensions = $this->mode == 'image' ? $this->config['allowed_image_extensions'] : $this->config['allowed_link_extensions'];
465        $max_size = $this->mode == 'image' ? $this->config['max_filesize_kb_image'] : $this->config['max_filesize_kb_link'];
466                $afruext = strtolower(substr(strrchr($file['name'], "."), 1));
467
468                if(!in_array($afruext, $valid_extensions))
469                {
470                        Files::delFile($file['tmp_name']);
471                        Return "Cannot upload .".$afruext." Files. Permission denied.";
472                }
473
474                if($file['size']>($max_size*1024))
475                {
476                        Files::delFile($file['tmp_name']);
477                        Return "Unble to upload file. Maximum file size [".$max_size."Kb] exceeded.";
478                }
479
480                if(!empty($this->config['max_foldersize_mb']) &&  (Files::dirSize($this->getImagesDir()))+$file['size']> ($this->config['max_foldersize_mb']*1048576))
481                {
482                        Files::delFile($file['tmp_name']);
483                        Return ("Cannot upload. Maximum folder size reached. Delete unwanted files and try again.");
484                }
485
486                //now copy the file
487                $path = Files::makePath($this->getImagesDir(),$relative);
488                $result = Files::copyFile($file['tmp_name'], $path, $file['name']);
489
490                //no copy error
491                if(!is_int($result))
492                {
493                        Files::delFile($file['tmp_name']);
494                        Return $file['name']." successfully uploaded.";
495                }
496
497                //delete tmp files.
498                Files::delFile($file['tmp_name']);
499                Return false;
500
501        }
502
503
504        function getDiskInfo()
505        {
506        if (empty($this->config['max_foldersize_mb']))
507            return '';
508           
509                $tmpFreeSize=($this->config['max_foldersize_mb']*1048576)-Files::dirSize($this->getImagesDir());
510
511                if(!is_numeric($tmpFreeSize) || $tmpFreeSize<0) $tmpFreeSize=0;
512       
513                Return 'Total Size : '.$this->config['max_foldersize_mb'].' Mb , Free Space: '.Files::formatSize($tmpFreeSize);
514        }
515
516
517
518        /**
519         * Get the URL of the relative file.
520         * basically appends the relative file to the
521         * base_url given in config.inc.php
522         * @param string $relative a file the relative to the base_dir
523         * @return string the URL of the relative file.
524         */
525        function getFileURL($relative)
526        {
527                Return Files::makeFile($this->getImagesURL(),$relative);
528        }
529
530        /**
531         * Get the fullpath to a relative file.
532         * @param string $relative the relative file.
533         * @return string the full path, .ie. the base_dir + relative.
534         */
535        function getFullPath($relative)
536        {
537                Return Files::makeFile($this->getImagesDir(),$relative);;
538        }
539
540        /**
541         * Get the default thumbnail.
542         * @return string default thumbnail, empty string if
543         * the thumbnail doesn't exist.
544         */
545        function getDefaultThumb()
546        {
547                if(is_file($this->config['default_thumbnail']))
548                        Return $this->config['default_thumbnail'];
549                else
550                        Return '';
551        }
552
553
554        /**
555         * Checks image size. If the image size is less than default size
556         * returns the original size else returns default size to display thumbnail
557        */
558        function checkImageSize($relative)
559        {
560                $fullpath = Files::makeFile($this->getImagesDir(),$relative);
561
562                $afruext = strtolower(substr(strrchr($relative, "."), 1));
563               
564                if(!in_array($afruext,$this->config['thumbnail_extensions']))
565                {
566                        $imgInfo=array(0,0);
567                        Return $imgInfo;
568                }
569                else
570                {
571                        $imgInfo = @getImageSize($fullpath);
572                        //not an image
573                        if(!is_array($imgInfo))
574                        {
575                                $imgInfo=array(0,0);
576                                Return $imgInfo;
577                        }
578                        else
579                        {
580                                if($imgInfo[0] > $this->config['thumbnail_width'])
581                                $imgInfo[0] = $this->config['thumbnail_width'];
582
583                                if($imgInfo[1] > $this->config['thumbnail_height'])
584                                $imgInfo[1] = $this->config['thumbnail_height'];
585
586                                Return $imgInfo;
587                        }
588                }
589
590        }
591
592
593        /**
594         * Get the thumbnail url to be displayed.
595         * If the thumbnail exists, and it is up-to-date
596         * the thumbnail url will be returns. If the
597         * file is not an image, a default image will be returned.
598         * If it is an image file, and no thumbnail exists or
599         * the thumbnail is out-of-date (i.e. the thumbnail
600         * modified time is less than the original file)
601         * then a thumbs.php?img=filename.jpg is returned.
602         * The thumbs.php url will generate a new thumbnail
603         * on the fly. If the image is less than the dimensions
604         * of the thumbnails, the image will be display instead.
605         * @param string $relative the relative image file.
606         * @return string the url of the thumbnail, be it
607         * actually thumbnail or a script to generate the
608         * thumbnail on the fly.
609         */
610        function getThumbnail($relative)
611        {
612                global $IMConfig;
613               
614                $fullpath = Files::makeFile($this->getImagesDir(),$relative);
615
616                //not a file???
617                if(!is_file($fullpath))
618                        Return $this->getDefaultThumb();
619
620                $afruext = strtolower(substr(strrchr($relative, "."), 1));
621               
622                if(!in_array($afruext,$this->config['thumbnail_extensions']))
623                {
624                        if(is_file('icons/'.$afruext.'.gif'))
625                                Return('icons/'.$afruext.'.gif');
626                        else
627                                Return $this->getDefaultThumb();
628                }
629
630                $imgInfo = @getImageSize($fullpath);
631
632                //not an image
633                if(!is_array($imgInfo))
634                        Return $this->getDefaultThumb();
635
636
637                //Returning original image as thumbnail without Image Library by Afru
638                if(!$this->config['img_library']) Return $this->getFileURL($relative);
639
640
641                //the original image is smaller than thumbnails,
642                //so just return the url to the original image.
643                if ($imgInfo[0] <= $this->config['thumbnail_width']
644                 && $imgInfo[1] <= $this->config['thumbnail_height'])
645                        Return $this->getFileURL($relative);
646
647                $thumbnail = $this->getThumbName($fullpath);
648               
649                //check for thumbnails, if exists and
650                // it is up-to-date, return the thumbnail url
651                if(is_file($thumbnail))
652                {
653                        if(filemtime($thumbnail) >= filemtime($fullpath))
654                                Return $this->getThumbURL($relative);
655                }
656
657                //well, no thumbnail was found, so ask the thumbs.php
658                //to generate the thumbnail on the fly.
659                Return $IMConfig['backend_url'] . '__function=thumbs&img='.rawurlencode($relative);
660        }
661
662        /**
663         * Delete and specified files.
664         * @return boolean true if delete, false otherwise
665         */
666        function deleteFiles()
667        {
668                if(isset($_GET['delf']))
669                        return $this->_delFile(rawurldecode($_GET['delf']));
670        return false;
671        }
672
673        /**
674         * Delete and specified directories.
675         * @return boolean true if delete, false otherwise
676         */
677        function deleteDirs()
678        {
679                 if(isset($_GET['deld']))
680                        return $this->_delDir(rawurldecode($_GET['deld']));             
681                 else
682                         Return false;
683        }
684
685        /**
686         * Delete the relative file, and any thumbnails.
687         * @param string $relative the relative file.
688         * @return boolean true if deleted, false otherwise.
689         */
690        function _delFile($relative)
691        {
692                $fullpath = Files::makeFile($this->getImagesDir(),$relative);
693       
694                $afruext = strtolower(substr(strrchr($relative, "."), 1));
695
696        $valid_extensions = $this->mode == 'image' ? $this->config['allowed_image_extensions'] : $this->config['allowed_link_extensions'];
697
698                if(!in_array($afruext,$valid_extensions))
699                {
700                        return false;
701                }
702
703                //check that the file is an image
704                if(is_array($this->getImageInfo($fullpath)))
705                {
706                        $thumbnail = $this->getThumbName($fullpath);
707                        Files::delFile($thumbnail);
708                }
709
710                Return Files::delFile($fullpath);
711        }
712
713        /**
714         * Delete directories recursively.
715         * @param string $relative the relative path to be deleted.
716         * @return boolean true if deleted, false otherwise.
717         */
718        function _delDir($relative)
719        {
720                $fullpath = Files::makePath($this->getImagesDir(),$relative);
721                if($this->countFiles($fullpath) <= 0)
722                        return Files::delFolder($fullpath,true); //delete recursively.
723                else
724                        Return false;
725        }
726
727        /**
728         * Create new directories.
729         * If in safe_mode, nothing happens.
730         * @return boolean true if created, false otherwise.
731         */
732        function processNewDir()
733        {
734                if($this->config['safe_mode'] == true)
735                        Return false;
736
737                if(isset($_GET['newDir']) && isset($_GET['dir']))
738                {
739                        $newDir = rawurldecode($_GET['newDir']);
740                        $dir = rawurldecode($_GET['dir']);
741                        $path = Files::makePath($this->getImagesDir(),$dir);
742                        $fullpath = Files::makePath($path, Files::escape($newDir));
743                        if(is_dir($fullpath))
744                                Return false;
745
746                        Return Files::createFolder($fullpath);
747                }
748        }
749}
750
751?>
Note: See TracBrowser for help on using the repository browser.