root / trunk / plugins / ImageManager / Classes / ImageManager.php @ 48

Revision 48, 15.7 kB (checked in by yermol, 8 years ago)

now uses PHP_SELF to figure out installation directory URL.
changed plugin to plugin and f to function everywhere.
updated README.

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